diff options
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); |