Samsung SoC drivers changes for v5.11

1. Limit the big.LITTLE cpuidle driver to Peach-Pit/Pi Chromebooks only
    because these are the only platforms were the driver works properly.
 2. Convert the Exynos CLKOUT driver to a full module which solves
    boot-probe ordering issues (e.g. if device nodes in DTS are moved).
    This also brings modularization and compile testing.
 3. Few minor cleanups in documentation and code.
 -----BEGIN PGP SIGNATURE-----
 
 iQJEBAABCgAuFiEE3dJiKD0RGyM7briowTdm5oaLg9cFAl+ur8AQHGtyemtAa2Vy
 bmVsLm9yZwAKCRDBN2bmhouD1/oQD/9HmtgBS4xbdnr/LtrZOEtm4YGEJ6UqUiUA
 FApt7xTcvv9NdCPk6RJW+XrDpaSBXrLjYnYELLSr1EtPk6OlkaGIAEUPTv8PhHKf
 e0z//0wrofnqIrdZOo34iretNK9srGYQ04MWXudZtfN6ibwPxz6RvxklRIxZg/7L
 J0fgnf+4ngwCQxw5CjHwPiapEisBZcIq5R7o+bl3z9jvLc6FFZzXqabnvorjg5E3
 vTpAVjryelQDVdiPzfHjF26PxT8o9nDqo7CWmwoUT25gigB+vw+fJu/mAripL1Jy
 wta1FZP/WuqgeyCWksPP8PxRKhvFRPpL9mIyAttHlaRLwIonR9bJbPXBr07Av//W
 +KV7RqbDdXQNeZpIlmkue1yL/bpCVO/V8LyomSvJ2VKqfY/8LSx+fRfLTBVhf6TF
 Ta0iHjM1+YG6gwFZLg7Zdob0pnP+YKb4tW0qwHPN2gLWvK2kTgEV7zcZD9La1K/U
 pe12dK02gmKn8wRP5kxdGliXQfsEbKZCCQX2pxtPNuuP2AUaNcPD0ZPKakqDmTKs
 t0K9XXSiKxpj2/2Fx2SX4V/ugcbTN2hs17JUY9cY0x4+MGHDLzsuRv3FLK9HoAkE
 QHnfQh6a2MkE05pC5VzCa0fvmn4UTZHrBGFGPTdkv3GjqIIGvy+jjwzXw4fiw4ZG
 JiVGI3zReg==
 =XD94
 -----END PGP SIGNATURE-----

Merge tag 'samsung-drivers-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux into arm/drivers

Samsung SoC drivers changes for v5.11

1. Limit the big.LITTLE cpuidle driver to Peach-Pit/Pi Chromebooks only
   because these are the only platforms were the driver works properly.
2. Convert the Exynos CLKOUT driver to a full module which solves
   boot-probe ordering issues (e.g. if device nodes in DTS are moved).
   This also brings modularization and compile testing.
3. Few minor cleanups in documentation and code.

* tag 'samsung-drivers-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux:
  clk: samsung: allow building the clkout driver as module
  soc: samsung: s3c-pm-check: Fix incorrectly named variable 'val'
  soc: samsung: exynos5422-asv: remove unneeded semicolon
  serial: s3c: Update path of Samsung S3C machine file
  Documentation: Update paths of Samsung S3C machine files
  clk: samsung: exynos-clkout: convert to module driver
  soc: samsung: exynos-pmu: instantiate clkout driver as MFD
  cpuidle: big.LITTLE: enable driver only on Peach-Pit/Pi Chromebooks

Link: https://lore.kernel.org/r/20201113162211.10020-1-krzk@kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2020-11-23 21:44:35 +01:00
commit 4ce4be5d28
14 changed files with 185 additions and 89 deletions

View file

@ -2951,7 +2951,7 @@
mtdset= [ARM]
ARM/S3C2412 JIVE boot control
See arch/arm/mach-s3c2412/mach-jive.c
See arch/arm/mach-s3c/mach-jive.c
mtouchusb.raw_coordinates=
[HW] Make the MicroTouch USB driver use raw coordinates

View file

@ -29,7 +29,7 @@ GPIOLIB
The following functions now either have a `s3c_` specific variant
or are merged into gpiolib. See the definitions in
arch/arm/plat-samsung/include/plat/gpio-cfg.h:
arch/arm/mach-s3c/gpio-cfg.h:
- s3c2410_gpio_setpin() gpio_set_value() or gpio_direction_output()
- s3c2410_gpio_getpin() gpio_get_value() or gpio_direction_input()
@ -86,7 +86,7 @@ between the calls.
Headers
-------
See arch/arm/mach-s3c24xx/include/mach/regs-gpio.h for the list
See arch/arm/mach-s3c/regs-gpio-s3c24xx.h for the list
of GPIO pins, and the configuration values for them. This
is included by using #include <mach/regs-gpio.h>

View file

@ -18,7 +18,7 @@ Introduction
versions.
The S3C2416 and S3C2450 devices are very similar and S3C2450 support is
included under the arch/arm/mach-s3c2416 directory. Note, while core
included under the arch/arm/mach-s3c directory. Note, while core
support for these SoCs is in, work on some of the extra peripherals
and extra interrupts is still ongoing.
@ -37,19 +37,11 @@ Configuration
Layout
------
The core support files are located in the platform code contained in
arch/arm/plat-s3c24xx with headers in include/asm-arm/plat-s3c24xx.
This directory should be kept to items shared between the platform
code (arch/arm/plat-s3c24xx) and the arch/arm/mach-s3c24* code.
The core support files, register, kernel and paltform data are located in the
platform code contained in arch/arm/mach-s3c with headers in
arch/arm/mach-s3c/include
Each cpu has a directory with the support files for it, and the
machines that carry the device. For example S3C2410 is contained
in arch/arm/mach-s3c2410 and S3C2440 in arch/arm/mach-s3c2440
Register, kernel and platform data definitions are held in the
arch/arm/mach-s3c2410 directory./include/mach
arch/arm/plat-s3c24xx:
arch/arm/mach-s3c:
Files in here are either common to all the s3c24xx family,
or are common to only some of them with names to indicate this
@ -134,7 +126,7 @@ Adding New Machines
should keep this in mind before altering items outside of their own
machine files.
Machine definitions should be kept in linux/arch/arm/mach-s3c2410,
Machine definitions should be kept in arch/arm/mach-s3c,
and there are a number of examples that can be looked at.
Read the kernel patch submission policies as well as the
@ -293,7 +285,7 @@ Platform Data
}
Note, since the code is marked as __init, it should not be
exported outside arch/arm/mach-s3c2410/, or exported to
exported outside arch/arm/mach-s3c/, or exported to
modules via EXPORT_SYMBOL() and related functions.

View file

@ -36,7 +36,7 @@ Board Support
-------------
The driver attaches to a platform device, which will need to be
added by the board specific support file in linux/arch/arm/mach-s3c2410,
added by the board specific support file in arch/arm/mach-s3c,
such as mach-bast.c or mach-smdk2410.c
The platform device's platform_data field is only needed if the
@ -51,9 +51,9 @@ Board Support
Platform Data
-------------
See arch/arm/mach-s3c2410/include/mach/usb-control.h for the
See include/linux/platform_data/usb-ohci-s3c2410.h for the
descriptions of the platform device data. An implementation
can be found in linux/arch/arm/mach-s3c2410/usb-simtec.c .
can be found in arch/arm/mach-s3c/simtec-usb.c .
The `struct s3c2410_hcd_info` contains a pair of functions
that get called to enable over-current detection, and to

View file

@ -37,5 +37,4 @@ implementation to configure pins as necessary.
The s3c_gpio_cfgpin() and s3c_gpio_setpull() provide the means for a
driver or machine to change gpio configuration.
See arch/arm/plat-samsung/include/plat/gpio-cfg.h for more information
on these functions.
See arch/arm/mach-s3c/gpio-cfg.h for more information on these functions.

View file

@ -34,7 +34,7 @@ These resources should be specified in that order, as the ordering of the
two address regions is important (the driver expects these to be address
and then data).
An example from arch/arm/mach-s3c2410/mach-bast.c is::
An example from arch/arm/mach-s3c/mach-bast.c is::
static struct resource bast_dm9k_resource[] = {
[0] = {

View file

@ -19,6 +19,16 @@ config EXYNOS_AUDSS_CLK_CON
on some Exynos SoC variants. Choose M or Y here if you want to
use audio devices such as I2S, PCM, etc.
config EXYNOS_CLKOUT
tristate "Samsung Exynos clock output driver"
depends on COMMON_CLK_SAMSUNG
default y if ARCH_EXYNOS
help
Support for the clock output (XCLKOUT) present on some of Exynos SoC
variants. Usually the XCLKOUT is used to monitor the status of the
certains clocks from SoC, but it could also be tied to other devices
as an input clock.
# For S3C24XX platforms, select following symbols:
config S3C2410_COMMON_CLK
bool "Samsung S3C2410 clock controller support" if COMPILE_TEST

View file

@ -15,7 +15,7 @@ obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o
obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5-subcmu.o
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos5433.o
obj-$(CONFIG_EXYNOS_AUDSS_CLK_CON) += clk-exynos-audss.o
obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-clkout.o
obj-$(CONFIG_EXYNOS_CLKOUT) += clk-exynos-clkout.o
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos7.o
obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o
obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o

View file

@ -9,10 +9,13 @@
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/syscore_ops.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#define EXYNOS_CLKOUT_NR_CLKS 1
#define EXYNOS_CLKOUT_PARENTS 32
@ -28,41 +31,103 @@ struct exynos_clkout {
struct clk_mux mux;
spinlock_t slock;
void __iomem *reg;
struct device_node *np;
u32 pmu_debug_save;
struct clk_hw_onecell_data data;
};
static struct exynos_clkout *clkout;
struct exynos_clkout_variant {
u32 mux_mask;
};
static int exynos_clkout_suspend(void)
static const struct exynos_clkout_variant exynos_clkout_exynos4 = {
.mux_mask = EXYNOS4_CLKOUT_MUX_MASK,
};
static const struct exynos_clkout_variant exynos_clkout_exynos5 = {
.mux_mask = EXYNOS5_CLKOUT_MUX_MASK,
};
static const struct of_device_id exynos_clkout_ids[] = {
{
.compatible = "samsung,exynos3250-pmu",
.data = &exynos_clkout_exynos4,
}, {
.compatible = "samsung,exynos4210-pmu",
.data = &exynos_clkout_exynos4,
}, {
.compatible = "samsung,exynos4412-pmu",
.data = &exynos_clkout_exynos4,
}, {
.compatible = "samsung,exynos5250-pmu",
.data = &exynos_clkout_exynos5,
}, {
.compatible = "samsung,exynos5410-pmu",
.data = &exynos_clkout_exynos5,
}, {
.compatible = "samsung,exynos5420-pmu",
.data = &exynos_clkout_exynos5,
}, {
.compatible = "samsung,exynos5433-pmu",
.data = &exynos_clkout_exynos5,
}, { }
};
MODULE_DEVICE_TABLE(of, exynos_clkout_ids);
/*
* Device will be instantiated as child of PMU device without its own
* device node. Therefore match compatibles against parent.
*/
static int exynos_clkout_match_parent_dev(struct device *dev, u32 *mux_mask)
{
clkout->pmu_debug_save = readl(clkout->reg + EXYNOS_PMU_DEBUG_REG);
const struct exynos_clkout_variant *variant;
const struct of_device_id *match;
if (!dev->parent) {
dev_err(dev, "not instantiated from MFD\n");
return -EINVAL;
}
match = of_match_device(exynos_clkout_ids, dev->parent);
if (!match) {
dev_err(dev, "cannot match parent device\n");
return -EINVAL;
}
variant = match->data;
*mux_mask = variant->mux_mask;
return 0;
}
static void exynos_clkout_resume(void)
{
writel(clkout->pmu_debug_save, clkout->reg + EXYNOS_PMU_DEBUG_REG);
}
static struct syscore_ops exynos_clkout_syscore_ops = {
.suspend = exynos_clkout_suspend,
.resume = exynos_clkout_resume,
};
static void __init exynos_clkout_init(struct device_node *node, u32 mux_mask)
static int exynos_clkout_probe(struct platform_device *pdev)
{
const char *parent_names[EXYNOS_CLKOUT_PARENTS];
struct clk *parents[EXYNOS_CLKOUT_PARENTS];
int parent_count;
int ret;
int i;
struct exynos_clkout *clkout;
int parent_count, ret, i;
u32 mux_mask;
clkout = kzalloc(struct_size(clkout, data.hws, EXYNOS_CLKOUT_NR_CLKS),
GFP_KERNEL);
clkout = devm_kzalloc(&pdev->dev,
struct_size(clkout, data.hws, EXYNOS_CLKOUT_NR_CLKS),
GFP_KERNEL);
if (!clkout)
return;
return -ENOMEM;
ret = exynos_clkout_match_parent_dev(&pdev->dev, &mux_mask);
if (ret)
return ret;
clkout->np = pdev->dev.of_node;
if (!clkout->np) {
/*
* pdev->dev.parent was checked by exynos_clkout_match_parent_dev()
* so it is not NULL.
*/
clkout->np = pdev->dev.parent->of_node;
}
platform_set_drvdata(pdev, clkout);
spin_lock_init(&clkout->slock);
@ -71,7 +136,7 @@ static void __init exynos_clkout_init(struct device_node *node, u32 mux_mask)
char name[] = "clkoutXX";
snprintf(name, sizeof(name), "clkout%d", i);
parents[i] = of_clk_get_by_name(node, name);
parents[i] = of_clk_get_by_name(clkout->np, name);
if (IS_ERR(parents[i])) {
parent_names[i] = "none";
continue;
@ -82,11 +147,13 @@ static void __init exynos_clkout_init(struct device_node *node, u32 mux_mask)
}
if (!parent_count)
goto free_clkout;
return -EINVAL;
clkout->reg = of_iomap(node, 0);
if (!clkout->reg)
clkout->reg = of_iomap(clkout->np, 0);
if (!clkout->reg) {
ret = -ENODEV;
goto clks_put;
}
clkout->gate.reg = clkout->reg + EXYNOS_PMU_DEBUG_REG;
clkout->gate.bit_idx = EXYNOS_CLKOUT_DISABLE_SHIFT;
@ -103,17 +170,17 @@ static void __init exynos_clkout_init(struct device_node *node, u32 mux_mask)
&clk_mux_ops, NULL, NULL, &clkout->gate.hw,
&clk_gate_ops, CLK_SET_RATE_PARENT
| CLK_SET_RATE_NO_REPARENT);
if (IS_ERR(clkout->data.hws[0]))
if (IS_ERR(clkout->data.hws[0])) {
ret = PTR_ERR(clkout->data.hws[0]);
goto err_unmap;
}
clkout->data.num = EXYNOS_CLKOUT_NR_CLKS;
ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, &clkout->data);
ret = of_clk_add_hw_provider(clkout->np, of_clk_hw_onecell_get, &clkout->data);
if (ret)
goto err_clk_unreg;
register_syscore_ops(&exynos_clkout_syscore_ops);
return;
return 0;
err_clk_unreg:
clk_hw_unregister(clkout->data.hws[0]);
@ -123,38 +190,56 @@ static void __init exynos_clkout_init(struct device_node *node, u32 mux_mask)
for (i = 0; i < EXYNOS_CLKOUT_PARENTS; ++i)
if (!IS_ERR(parents[i]))
clk_put(parents[i]);
free_clkout:
kfree(clkout);
pr_err("%s: failed to register clkout clock\n", __func__);
dev_err(&pdev->dev, "failed to register clkout clock\n");
return ret;
}
/*
* We use CLK_OF_DECLARE_DRIVER initialization method to avoid setting
* the OF_POPULATED flag on the pmu device tree node, so later the
* Exynos PMU platform device can be properly probed with PMU driver.
*/
static void __init exynos4_clkout_init(struct device_node *node)
static int exynos_clkout_remove(struct platform_device *pdev)
{
exynos_clkout_init(node, EXYNOS4_CLKOUT_MUX_MASK);
}
CLK_OF_DECLARE_DRIVER(exynos4210_clkout, "samsung,exynos4210-pmu",
exynos4_clkout_init);
CLK_OF_DECLARE_DRIVER(exynos4412_clkout, "samsung,exynos4412-pmu",
exynos4_clkout_init);
CLK_OF_DECLARE_DRIVER(exynos3250_clkout, "samsung,exynos3250-pmu",
exynos4_clkout_init);
struct exynos_clkout *clkout = platform_get_drvdata(pdev);
static void __init exynos5_clkout_init(struct device_node *node)
{
exynos_clkout_init(node, EXYNOS5_CLKOUT_MUX_MASK);
of_clk_del_provider(clkout->np);
clk_hw_unregister(clkout->data.hws[0]);
iounmap(clkout->reg);
return 0;
}
CLK_OF_DECLARE_DRIVER(exynos5250_clkout, "samsung,exynos5250-pmu",
exynos5_clkout_init);
CLK_OF_DECLARE_DRIVER(exynos5410_clkout, "samsung,exynos5410-pmu",
exynos5_clkout_init);
CLK_OF_DECLARE_DRIVER(exynos5420_clkout, "samsung,exynos5420-pmu",
exynos5_clkout_init);
CLK_OF_DECLARE_DRIVER(exynos5433_clkout, "samsung,exynos5433-pmu",
exynos5_clkout_init);
static int exynos_clkout_suspend(struct device *dev)
{
struct exynos_clkout *clkout = dev_get_drvdata(dev);
clkout->pmu_debug_save = readl(clkout->reg + EXYNOS_PMU_DEBUG_REG);
return 0;
}
static int exynos_clkout_resume(struct device *dev)
{
struct exynos_clkout *clkout = dev_get_drvdata(dev);
writel(clkout->pmu_debug_save, clkout->reg + EXYNOS_PMU_DEBUG_REG);
return 0;
}
static SIMPLE_DEV_PM_OPS(exynos_clkout_pm_ops, exynos_clkout_suspend,
exynos_clkout_resume);
static struct platform_driver exynos_clkout_driver = {
.driver = {
.name = "exynos-clkout",
.of_match_table = exynos_clkout_ids,
.pm = &exynos_clkout_pm_ops,
},
.probe = exynos_clkout_probe,
.remove = exynos_clkout_remove,
};
module_platform_driver(exynos_clkout_driver);
MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>");
MODULE_AUTHOR("Tomasz Figa <tomasz.figa@gmail.com>");
MODULE_DESCRIPTION("Samsung Exynos clock output driver");
MODULE_LICENSE("GPL");

View file

@ -155,8 +155,7 @@ static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int part_id)
static const struct of_device_id compatible_machine_match[] = {
{ .compatible = "arm,vexpress,v2p-ca15_a7" },
{ .compatible = "samsung,exynos5420" },
{ .compatible = "samsung,exynos5800" },
{ .compatible = "google,peach" },
{},
};

View file

@ -8,6 +8,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/mfd/core.h>
#include <linux/mfd/syscon.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
@ -97,6 +98,10 @@ static const struct of_device_id exynos_pmu_of_device_ids[] = {
{ /*sentinel*/ },
};
static const struct mfd_cell exynos_pmu_devs[] = {
{ .name = "exynos-clkout", },
};
struct regmap *exynos_get_pmu_regmap(void)
{
struct device_node *np = of_find_matching_node(NULL,
@ -110,6 +115,7 @@ EXPORT_SYMBOL_GPL(exynos_get_pmu_regmap);
static int exynos_pmu_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int ret;
pmu_base_addr = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pmu_base_addr))
@ -128,6 +134,11 @@ static int exynos_pmu_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, pmu_context);
ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, exynos_pmu_devs,
ARRAY_SIZE(exynos_pmu_devs), NULL, 0, NULL);
if (ret)
return ret;
if (devm_of_platform_populate(dev))
dev_err(dev, "Error populating children, reboot and poweroff might not work properly\n");

View file

@ -383,7 +383,7 @@ static int __asv_offset_voltage(unsigned int index)
return 25000;
default:
return 0;
};
}
}
static void exynos5422_asv_offset_voltage_setup(struct exynos_asv *asv)

View file

@ -151,7 +151,7 @@ static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
/**
* s3c_pm_runcheck() - helper to check a resource on restore.
* @res: The resource to check
* @vak: Pointer to list of CRC32 values to check.
* @val: Pointer to list of CRC32 values to check.
*
* Called from the s3c_pm_check_restore() via s3c_pm_run_sysram(), this
* function runs the given memory resource checking it against the stored

View file

@ -254,7 +254,7 @@
* serial port
*
* the pointer is setup by the machine specific initialisation from the
* arch/arm/mach-s3c2410/ directory.
* arch/arm/mach-s3c/ directory.
*/
struct s3c2410_uartcfg {