summaryrefslogtreecommitdiffstats
path: root/drivers/soc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/soc')
-rw-r--r--drivers/soc/samsung/Kconfig5
-rw-r--r--drivers/soc/samsung/Makefile3
-rw-r--r--drivers/soc/samsung/exynos-chipid.c94
-rw-r--r--drivers/soc/samsung/exynos5422-asv.c1
-rw-r--r--drivers/soc/samsung/pm_domains.c1
5 files changed, 87 insertions, 17 deletions
diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig
index 5745d7e5908e..e2cedef1e8d1 100644
--- a/drivers/soc/samsung/Kconfig
+++ b/drivers/soc/samsung/Kconfig
@@ -13,18 +13,21 @@ config EXYNOS_ASV_ARM
depends on EXYNOS_CHIPID
config EXYNOS_CHIPID
- bool "Exynos ChipID controller and ASV driver" if COMPILE_TEST
+ tristate "Exynos ChipID controller and ASV driver"
depends on ARCH_EXYNOS || COMPILE_TEST
+ default ARCH_EXYNOS
select EXYNOS_ASV_ARM if ARM && ARCH_EXYNOS
select MFD_SYSCON
select SOC_BUS
help
Support for Samsung Exynos SoC ChipID and Adaptive Supply Voltage.
+ This driver can also be built as module (exynos_chipid).
config EXYNOS_PMU
bool "Exynos PMU controller driver" if COMPILE_TEST
depends on ARCH_EXYNOS || ((ARM || ARM64) && COMPILE_TEST)
select EXYNOS_PMU_ARM_DRIVERS if ARM && ARCH_EXYNOS
+ select MFD_CORE
# There is no need to enable these drivers for ARMv8
config EXYNOS_PMU_ARM_DRIVERS
diff --git a/drivers/soc/samsung/Makefile b/drivers/soc/samsung/Makefile
index 0c523a8de4eb..2ae4bea804cf 100644
--- a/drivers/soc/samsung/Makefile
+++ b/drivers/soc/samsung/Makefile
@@ -1,8 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_EXYNOS_ASV_ARM) += exynos5422-asv.o
+obj-$(CONFIG_EXYNOS_CHIPID) += exynos_chipid.o
+exynos_chipid-y += exynos-chipid.o exynos-asv.o
-obj-$(CONFIG_EXYNOS_CHIPID) += exynos-chipid.o exynos-asv.o
obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o
obj-$(CONFIG_EXYNOS_PMU_ARM_DRIVERS) += exynos3250-pmu.o exynos4-pmu.o \
diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c
index 5c1d0f97f766..a28053ec7e6a 100644
--- a/drivers/soc/samsung/exynos-chipid.c
+++ b/drivers/soc/samsung/exynos-chipid.c
@@ -15,7 +15,9 @@
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/mfd/syscon.h>
+#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
@@ -24,6 +26,17 @@
#include "exynos-asv.h"
+struct exynos_chipid_variant {
+ unsigned int rev_reg; /* revision register offset */
+ unsigned int main_rev_shift; /* main revision offset in rev_reg */
+ unsigned int sub_rev_shift; /* sub revision offset in rev_reg */
+};
+
+struct exynos_chipid_info {
+ u32 product_id;
+ u32 revision;
+};
+
static const struct exynos_soc_id {
const char *name;
unsigned int id;
@@ -42,6 +55,8 @@ static const struct exynos_soc_id {
{ "EXYNOS5440", 0xE5440000 },
{ "EXYNOS5800", 0xE5422000 },
{ "EXYNOS7420", 0xE7420000 },
+ { "EXYNOS850", 0xE3830000 },
+ { "EXYNOSAUTOV9", 0xAAA80000 },
};
static const char *product_id_to_soc_id(unsigned int product_id)
@@ -49,31 +64,57 @@ static const char *product_id_to_soc_id(unsigned int product_id)
int i;
for (i = 0; i < ARRAY_SIZE(soc_ids); i++)
- if ((product_id & EXYNOS_MASK) == soc_ids[i].id)
+ if (product_id == soc_ids[i].id)
return soc_ids[i].name;
return NULL;
}
+static int exynos_chipid_get_chipid_info(struct regmap *regmap,
+ const struct exynos_chipid_variant *data,
+ struct exynos_chipid_info *soc_info)
+{
+ int ret;
+ unsigned int val, main_rev, sub_rev;
+
+ ret = regmap_read(regmap, EXYNOS_CHIPID_REG_PRO_ID, &val);
+ if (ret < 0)
+ return ret;
+ soc_info->product_id = val & EXYNOS_MASK;
+
+ if (data->rev_reg != EXYNOS_CHIPID_REG_PRO_ID) {
+ ret = regmap_read(regmap, data->rev_reg, &val);
+ if (ret < 0)
+ return ret;
+ }
+ main_rev = (val >> data->main_rev_shift) & EXYNOS_REV_PART_MASK;
+ sub_rev = (val >> data->sub_rev_shift) & EXYNOS_REV_PART_MASK;
+ soc_info->revision = (main_rev << EXYNOS_REV_PART_SHIFT) | sub_rev;
+
+ return 0;
+}
+
static int exynos_chipid_probe(struct platform_device *pdev)
{
+ const struct exynos_chipid_variant *drv_data;
+ struct exynos_chipid_info soc_info;
struct soc_device_attribute *soc_dev_attr;
struct soc_device *soc_dev;
struct device_node *root;
struct regmap *regmap;
- u32 product_id;
- u32 revision;
int ret;
+ drv_data = of_device_get_match_data(&pdev->dev);
+ if (!drv_data)
+ return -EINVAL;
+
regmap = device_node_to_regmap(pdev->dev.of_node);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
- ret = regmap_read(regmap, EXYNOS_CHIPID_REG_PRO_ID, &product_id);
+ ret = exynos_chipid_get_chipid_info(regmap, drv_data, &soc_info);
if (ret < 0)
return ret;
- revision = product_id & EXYNOS_REV_MASK;
-
soc_dev_attr = devm_kzalloc(&pdev->dev, sizeof(*soc_dev_attr),
GFP_KERNEL);
if (!soc_dev_attr)
@@ -86,8 +127,8 @@ static int exynos_chipid_probe(struct platform_device *pdev)
of_node_put(root);
soc_dev_attr->revision = devm_kasprintf(&pdev->dev, GFP_KERNEL,
- "%x", revision);
- soc_dev_attr->soc_id = product_id_to_soc_id(product_id);
+ "%x", soc_info.revision);
+ soc_dev_attr->soc_id = product_id_to_soc_id(soc_info.product_id);
if (!soc_dev_attr->soc_id) {
pr_err("Unknown SoC\n");
return -ENODEV;
@@ -104,9 +145,8 @@ static int exynos_chipid_probe(struct platform_device *pdev)
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",
- soc_dev_attr->soc_id, product_id, revision);
+ dev_info(&pdev->dev, "Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n",
+ soc_dev_attr->soc_id, soc_info.product_id, soc_info.revision);
return 0;
@@ -125,10 +165,29 @@ static int exynos_chipid_remove(struct platform_device *pdev)
return 0;
}
+static const struct exynos_chipid_variant exynos4210_chipid_drv_data = {
+ .rev_reg = 0x0,
+ .main_rev_shift = 4,
+ .sub_rev_shift = 0,
+};
+
+static const struct exynos_chipid_variant exynos850_chipid_drv_data = {
+ .rev_reg = 0x10,
+ .main_rev_shift = 20,
+ .sub_rev_shift = 16,
+};
+
static const struct of_device_id exynos_chipid_of_device_ids[] = {
- { .compatible = "samsung,exynos4210-chipid" },
- {}
+ {
+ .compatible = "samsung,exynos4210-chipid",
+ .data = &exynos4210_chipid_drv_data,
+ }, {
+ .compatible = "samsung,exynos850-chipid",
+ .data = &exynos850_chipid_drv_data,
+ },
+ { }
};
+MODULE_DEVICE_TABLE(of, exynos_chipid_of_device_ids);
static struct platform_driver exynos_chipid_driver = {
.driver = {
@@ -138,4 +197,11 @@ static struct platform_driver exynos_chipid_driver = {
.probe = exynos_chipid_probe,
.remove = exynos_chipid_remove,
};
-builtin_platform_driver(exynos_chipid_driver);
+module_platform_driver(exynos_chipid_driver);
+
+MODULE_DESCRIPTION("Samsung Exynos ChipID controller and ASV driver");
+MODULE_AUTHOR("Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>");
+MODULE_AUTHOR("Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>");
+MODULE_AUTHOR("Pankaj Dubey <pankaj.dubey@samsung.com>");
+MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/soc/samsung/exynos5422-asv.c b/drivers/soc/samsung/exynos5422-asv.c
index ca409a976e34..475ae5276529 100644
--- a/drivers/soc/samsung/exynos5422-asv.c
+++ b/drivers/soc/samsung/exynos5422-asv.c
@@ -503,3 +503,4 @@ int exynos5422_asv_init(struct exynos_asv *asv)
return 0;
}
+EXPORT_SYMBOL_GPL(exynos5422_asv_init);
diff --git a/drivers/soc/samsung/pm_domains.c b/drivers/soc/samsung/pm_domains.c
index 5ec0c13f0aaf..d07f3c9d6903 100644
--- a/drivers/soc/samsung/pm_domains.c
+++ b/drivers/soc/samsung/pm_domains.c
@@ -28,7 +28,6 @@ struct exynos_pm_domain_config {
*/
struct exynos_pm_domain {
void __iomem *base;
- bool is_off;
struct generic_pm_domain pd;
u32 local_pwr_cfg;
};