diff options
author | Krzysztof Kozlowski <krzk@kernel.org> | 2020-12-07 19:54:57 +0100 |
---|---|---|
committer | Krzysztof Kozlowski <krzk@kernel.org> | 2021-01-03 17:08:45 +0100 |
commit | 352bfbb3e0230c96b2bce00d2ac3f0de303cc7b6 (patch) | |
tree | 4dceab7b8a6908399c857195f85ffcdeb6e867f9 /drivers/soc/samsung/exynos-chipid.c | |
parent | 4561560dfb4f847a0b327d48bdd1f45bf1b6261f (diff) |
soc: samsung: exynos-chipid: convert to driver and merge exynos-asv
The Exynos Chip ID driver on Exynos SoCs has so far only informational
purpose - to expose the SoC device in sysfs. No other drivers depend on
it so there is really no benefit of initializing it early.
The code would be the most flexible if converted to a regular driver.
However there is already another driver - Exynos ASV (Adaptive Supply
Voltage) - which binds to the device node of Chip ID.
The solution is to convert the Exynos Chip ID to a built in driver and
merge the Exynos ASV into it.
This has several benefits:
1. Although the Exynos ASV driver binds to a device node present in all
Exynos DTS (generic compatible), it fails to probe except on the
supported ones (only Exynos5422). This means that the regular boot
process has a planned/normal device probe failure.
Merging the ASV into Chip ID will remove this probe failure because
the final driver will always bind, just with disabled ASV features.
2. Allows to use dev_info() as the SoC bus is present (since
core_initcall).
3. Could speed things up because of execution of Chip ID code in a SMP
environment (after bringing up secondary CPUs, unlike early_initcall),
This reduces the amount of work to be done early, when the kernel has
to bring up critical devices.
5. Makes the Chip ID code defer-probe friendly,
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
Link: https://lore.kernel.org/r/20201207190517.262051-5-krzk@kernel.org
Reviewed-by: Pankaj Dubey <pankaj.dubey@samsung.com>
Diffstat (limited to 'drivers/soc/samsung/exynos-chipid.c')
-rw-r--r-- | drivers/soc/samsung/exynos-chipid.c | 69 |
1 files changed, 48 insertions, 21 deletions
diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c index 1a76eade2ed6..fa6a9b9f6d70 100644 --- a/drivers/soc/samsung/exynos-chipid.c +++ b/drivers/soc/samsung/exynos-chipid.c @@ -2,20 +2,28 @@ /* * Copyright (c) 2019 Samsung Electronics Co., Ltd. * http://www.samsung.com/ + * Copyright (c) 2020 Krzysztof Kozlowski <krzk@kernel.org> * * Exynos - CHIP ID support * Author: Pankaj Dubey <pankaj.dubey@samsung.com> * Author: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> + * Author: Krzysztof Kozlowski <krzk@kernel.org> + * + * Samsung Exynos SoC Adaptive Supply Voltage and Chip ID support */ -#include <linux/io.h> +#include <linux/device.h> +#include <linux/errno.h> #include <linux/mfd/syscon.h> #include <linux/of.h> +#include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/slab.h> #include <linux/soc/samsung/exynos-chipid.h> #include <linux/sys_soc.h> +#include "exynos-asv.h" + static const struct exynos_soc_id { const char *name; unsigned int id; @@ -46,25 +54,17 @@ static const char * __init product_id_to_soc_id(unsigned int product_id) return NULL; } -static int __init exynos_chipid_early_init(void) +static int exynos_chipid_probe(struct platform_device *pdev) { struct soc_device_attribute *soc_dev_attr; struct soc_device *soc_dev; struct device_node *root; - struct device_node *syscon; struct regmap *regmap; u32 product_id; u32 revision; int ret; - syscon = of_find_compatible_node(NULL, NULL, - "samsung,exynos4210-chipid"); - if (!syscon) - return -ENODEV; - - regmap = device_node_to_regmap(syscon); - of_node_put(syscon); - + regmap = device_node_to_regmap(pdev->dev.of_node); if (IS_ERR(regmap)) return PTR_ERR(regmap); @@ -74,7 +74,8 @@ static int __init exynos_chipid_early_init(void) revision = product_id & EXYNOS_REV_MASK; - soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); + soc_dev_attr = devm_kzalloc(&pdev->dev, sizeof(*soc_dev_attr), + GFP_KERNEL); if (!soc_dev_attr) return -ENOMEM; @@ -84,20 +85,24 @@ static int __init exynos_chipid_early_init(void) of_property_read_string(root, "model", &soc_dev_attr->machine); of_node_put(root); - soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%x", revision); + soc_dev_attr->revision = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "%x", revision); soc_dev_attr->soc_id = product_id_to_soc_id(product_id); if (!soc_dev_attr->soc_id) { pr_err("Unknown SoC\n"); - ret = -ENODEV; - goto err; + return -ENODEV; } /* please note that the actual registration will be deferred */ soc_dev = soc_device_register(soc_dev_attr); - if (IS_ERR(soc_dev)) { - ret = PTR_ERR(soc_dev); + if (IS_ERR(soc_dev)) + return PTR_ERR(soc_dev); + + ret = exynos_asv_init(&pdev->dev, regmap); + if (ret) goto err; - } + + platform_set_drvdata(pdev, soc_dev); dev_info(soc_device_to_device(soc_dev), "Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n", @@ -106,9 +111,31 @@ static int __init exynos_chipid_early_init(void) return 0; err: - kfree(soc_dev_attr->revision); - kfree(soc_dev_attr); + soc_device_unregister(soc_dev); + return ret; } -arch_initcall(exynos_chipid_early_init); +static int exynos_chipid_remove(struct platform_device *pdev) +{ + struct soc_device *soc_dev = platform_get_drvdata(pdev); + + soc_device_unregister(soc_dev); + + return 0; +} + +static const struct of_device_id exynos_chipid_of_device_ids[] = { + { .compatible = "samsung,exynos4210-chipid" }, + {} +}; + +static struct platform_driver exynos_chipid_driver = { + .driver = { + .name = "exynos-chipid", + .of_match_table = exynos_chipid_of_device_ids, + }, + .probe = exynos_chipid_probe, + .remove = exynos_chipid_remove, +}; +builtin_platform_driver(exynos_chipid_driver); |