mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-18 17:54:13 +08:00
soc: samsung: Add exynos chipid driver support
Exynos SoCs have Chipid, for identification of product IDs and SoC revisions. This patch intends to provide initialization code for all these functionalities, at the same time it provides some sysfs entries for accessing these information to user-space. This driver uses existing binding for exynos-chipid. Changes by Bartlomiej: - fixed return values on errors - removed bogus kfree_const() - added missing Exynos4210 EVT0 id - converted code to use EXYNOS_MASK define - fixed np use after of_node_put() - fixed too early use of dev_info() - made driver fail for unknown SoC-s - added SPDX tag - updated Copyrights Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com> [m.szyprowski: for suggestion and code snippet of product_id_to_soc_id] Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> [s.nawrocki: updated copyright date, removed uneeded headers inclusion] Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
This commit is contained in:
parent
5f9e832c13
commit
3253b7b7cd
@ -7,6 +7,11 @@ menuconfig SOC_SAMSUNG
|
||||
|
||||
if SOC_SAMSUNG
|
||||
|
||||
config EXYNOS_CHIPID
|
||||
bool "Exynos Chipid controller driver" if COMPILE_TEST
|
||||
depends on ARCH_EXYNOS || COMPILE_TEST
|
||||
select SOC_BUS
|
||||
|
||||
config EXYNOS_PMU
|
||||
bool "Exynos PMU controller driver" if COMPILE_TEST
|
||||
depends on ARCH_EXYNOS || ((ARM || ARM64) && COMPILE_TEST)
|
||||
|
@ -1,4 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
obj-$(CONFIG_EXYNOS_CHIPID) += exynos-chipid.o
|
||||
obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o
|
||||
|
||||
obj-$(CONFIG_EXYNOS_PMU_ARM_DRIVERS) += exynos3250-pmu.o exynos4-pmu.o \
|
||||
|
109
drivers/soc/samsung/exynos-chipid.c
Normal file
109
drivers/soc/samsung/exynos-chipid.c
Normal file
@ -0,0 +1,109 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2019 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com/
|
||||
*
|
||||
* EXYNOS - CHIP ID support
|
||||
* Author: Pankaj Dubey <pankaj.dubey@samsung.com>
|
||||
* Author: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
|
||||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sys_soc.h>
|
||||
|
||||
#define EXYNOS_SUBREV_MASK (0xF << 4)
|
||||
#define EXYNOS_MAINREV_MASK (0xF << 0)
|
||||
#define EXYNOS_REV_MASK (EXYNOS_SUBREV_MASK | EXYNOS_MAINREV_MASK)
|
||||
#define EXYNOS_MASK 0xFFFFF000
|
||||
|
||||
static const struct exynos_soc_id {
|
||||
const char *name;
|
||||
unsigned int id;
|
||||
} soc_ids[] = {
|
||||
{ "EXYNOS3250", 0xE3472000 },
|
||||
{ "EXYNOS4210", 0x43200000 }, /* EVT0 revision */
|
||||
{ "EXYNOS4210", 0x43210000 },
|
||||
{ "EXYNOS4212", 0x43220000 },
|
||||
{ "EXYNOS4412", 0xE4412000 },
|
||||
{ "EXYNOS5250", 0x43520000 },
|
||||
{ "EXYNOS5260", 0xE5260000 },
|
||||
{ "EXYNOS5410", 0xE5410000 },
|
||||
{ "EXYNOS5420", 0xE5420000 },
|
||||
{ "EXYNOS5440", 0xE5440000 },
|
||||
{ "EXYNOS5800", 0xE5422000 },
|
||||
{ "EXYNOS7420", 0xE7420000 },
|
||||
{ "EXYNOS5433", 0xE5433000 },
|
||||
};
|
||||
|
||||
static const char * __init 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)
|
||||
return soc_ids[i].name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int __init exynos_chipid_early_init(void)
|
||||
{
|
||||
struct soc_device_attribute *soc_dev_attr;
|
||||
void __iomem *exynos_chipid_base;
|
||||
struct soc_device *soc_dev;
|
||||
struct device_node *root;
|
||||
struct device_node *np;
|
||||
u32 product_id;
|
||||
u32 revision;
|
||||
|
||||
/* look up for chipid node */
|
||||
np = of_find_compatible_node(NULL, NULL, "samsung,exynos4210-chipid");
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
exynos_chipid_base = of_iomap(np, 0);
|
||||
of_node_put(np);
|
||||
|
||||
if (!exynos_chipid_base) {
|
||||
pr_err("Failed to map SoC chipid\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
product_id = readl_relaxed(exynos_chipid_base);
|
||||
revision = product_id & EXYNOS_REV_MASK;
|
||||
iounmap(exynos_chipid_base);
|
||||
|
||||
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
|
||||
if (!soc_dev_attr)
|
||||
return -ENOMEM;
|
||||
|
||||
soc_dev_attr->family = "Samsung Exynos";
|
||||
|
||||
root = of_find_node_by_path("/");
|
||||
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->soc_id = product_id_to_soc_id(product_id);
|
||||
if (!soc_dev_attr->soc_id) {
|
||||
pr_err("Unknown SoC\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* please note that the actual registration will be deferred */
|
||||
soc_dev = soc_device_register(soc_dev_attr);
|
||||
if (IS_ERR(soc_dev)) {
|
||||
kfree(soc_dev_attr->revision);
|
||||
kfree(soc_dev_attr);
|
||||
return PTR_ERR(soc_dev);
|
||||
}
|
||||
|
||||
/* it is too early to use dev_info() here (soc_dev is NULL) */
|
||||
pr_info("soc soc0: Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n",
|
||||
soc_dev_attr->soc_id, product_id, revision);
|
||||
|
||||
return 0;
|
||||
}
|
||||
early_initcall(exynos_chipid_early_init);
|
Loading…
Reference in New Issue
Block a user