From fc40200ebf82fae3e40c4e88246496644edafe66 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 21 Feb 2020 10:32:19 +0800 Subject: soc: imx: increase build coverage for imx8m soc driver The soc-imx8.c driver is actually for i.MX8M family, so rename it to soc-imx8m.c. Use CONFIG_SOC_IMX8M as build gate, not CONFIG_ARCH_MXC, to control whether build this driver, also make it possible for compile test. Default set it to y for ARCH_MXC && ARM64 Signed-off-by: Peng Fan Reviewed-by: Leonard Crestez Signed-off-by: Shawn Guo --- drivers/soc/imx/Kconfig | 9 ++ drivers/soc/imx/Makefile | 2 +- drivers/soc/imx/soc-imx8.c | 230 -------------------------------------------- drivers/soc/imx/soc-imx8m.c | 230 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 240 insertions(+), 231 deletions(-) delete mode 100644 drivers/soc/imx/soc-imx8.c create mode 100644 drivers/soc/imx/soc-imx8m.c (limited to 'drivers/soc/imx') diff --git a/drivers/soc/imx/Kconfig b/drivers/soc/imx/Kconfig index 0281ef9a1800..70019cefa617 100644 --- a/drivers/soc/imx/Kconfig +++ b/drivers/soc/imx/Kconfig @@ -17,4 +17,13 @@ config IMX_SCU_SOC Controller Unit SoC info module, it will provide the SoC info like SoC family, ID and revision etc. +config SOC_IMX8M + bool "i.MX8M SoC family support" + depends on ARCH_MXC || COMPILE_TEST + default ARCH_MXC && ARM64 + help + If you say yes here you get support for the NXP i.MX8M family + support, it will provide the SoC info like SoC family, + ID and revision etc. + endmenu diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile index cf9ca42ff739..103e2c93c342 100644 --- a/drivers/soc/imx/Makefile +++ b/drivers/soc/imx/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o -obj-$(CONFIG_ARCH_MXC) += soc-imx8.o +obj-$(CONFIG_SOC_IMX8M) += soc-imx8m.o obj-$(CONFIG_IMX_SCU_SOC) += soc-imx-scu.o diff --git a/drivers/soc/imx/soc-imx8.c b/drivers/soc/imx/soc-imx8.c deleted file mode 100644 index 719e1f189ebf..000000000000 --- a/drivers/soc/imx/soc-imx8.c +++ /dev/null @@ -1,230 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright 2019 NXP. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define REV_B1 0x21 - -#define IMX8MQ_SW_INFO_B1 0x40 -#define IMX8MQ_SW_MAGIC_B1 0xff0055aa - -#define IMX_SIP_GET_SOC_INFO 0xc2000006 - -#define OCOTP_UID_LOW 0x410 -#define OCOTP_UID_HIGH 0x420 - -/* Same as ANADIG_DIGPROG_IMX7D */ -#define ANADIG_DIGPROG_IMX8MM 0x800 - -struct imx8_soc_data { - char *name; - u32 (*soc_revision)(void); -}; - -static u64 soc_uid; - -#ifdef CONFIG_HAVE_ARM_SMCCC -static u32 imx8mq_soc_revision_from_atf(void) -{ - struct arm_smccc_res res; - - arm_smccc_smc(IMX_SIP_GET_SOC_INFO, 0, 0, 0, 0, 0, 0, 0, &res); - - if (res.a0 == SMCCC_RET_NOT_SUPPORTED) - return 0; - else - return res.a0 & 0xff; -} -#else -static inline u32 imx8mq_soc_revision_from_atf(void) { return 0; }; -#endif - -static u32 __init imx8mq_soc_revision(void) -{ - struct device_node *np; - void __iomem *ocotp_base; - u32 magic; - u32 rev = 0; - - np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp"); - if (!np) - goto out; - - ocotp_base = of_iomap(np, 0); - WARN_ON(!ocotp_base); - - /* - * SOC revision on older imx8mq is not available in fuses so query - * the value from ATF instead. - */ - rev = imx8mq_soc_revision_from_atf(); - if (!rev) { - magic = readl_relaxed(ocotp_base + IMX8MQ_SW_INFO_B1); - if (magic == IMX8MQ_SW_MAGIC_B1) - rev = REV_B1; - } - - soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH); - soc_uid <<= 32; - soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW); - - iounmap(ocotp_base); - -out: - of_node_put(np); - return rev; -} - -static void __init imx8mm_soc_uid(void) -{ - void __iomem *ocotp_base; - struct device_node *np; - - np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-ocotp"); - if (!np) - return; - - ocotp_base = of_iomap(np, 0); - WARN_ON(!ocotp_base); - - soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH); - soc_uid <<= 32; - soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW); - - iounmap(ocotp_base); - of_node_put(np); -} - -static u32 __init imx8mm_soc_revision(void) -{ - struct device_node *np; - void __iomem *anatop_base; - u32 rev; - - np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop"); - if (!np) - return 0; - - anatop_base = of_iomap(np, 0); - WARN_ON(!anatop_base); - - rev = readl_relaxed(anatop_base + ANADIG_DIGPROG_IMX8MM); - - iounmap(anatop_base); - of_node_put(np); - - imx8mm_soc_uid(); - - return rev; -} - -static const struct imx8_soc_data imx8mq_soc_data = { - .name = "i.MX8MQ", - .soc_revision = imx8mq_soc_revision, -}; - -static const struct imx8_soc_data imx8mm_soc_data = { - .name = "i.MX8MM", - .soc_revision = imx8mm_soc_revision, -}; - -static const struct imx8_soc_data imx8mn_soc_data = { - .name = "i.MX8MN", - .soc_revision = imx8mm_soc_revision, -}; - -static const struct imx8_soc_data imx8mp_soc_data = { - .name = "i.MX8MP", - .soc_revision = imx8mm_soc_revision, -}; - -static const struct of_device_id imx8_soc_match[] = { - { .compatible = "fsl,imx8mq", .data = &imx8mq_soc_data, }, - { .compatible = "fsl,imx8mm", .data = &imx8mm_soc_data, }, - { .compatible = "fsl,imx8mn", .data = &imx8mn_soc_data, }, - { .compatible = "fsl,imx8mp", .data = &imx8mp_soc_data, }, - { } -}; - -#define imx8_revision(soc_rev) \ - soc_rev ? \ - kasprintf(GFP_KERNEL, "%d.%d", (soc_rev >> 4) & 0xf, soc_rev & 0xf) : \ - "unknown" - -static int __init imx8_soc_init(void) -{ - struct soc_device_attribute *soc_dev_attr; - struct soc_device *soc_dev; - const struct of_device_id *id; - u32 soc_rev = 0; - const struct imx8_soc_data *data; - int ret; - - soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); - if (!soc_dev_attr) - return -ENOMEM; - - soc_dev_attr->family = "Freescale i.MX"; - - ret = of_property_read_string(of_root, "model", &soc_dev_attr->machine); - if (ret) - goto free_soc; - - id = of_match_node(imx8_soc_match, of_root); - if (!id) { - ret = -ENODEV; - goto free_soc; - } - - data = id->data; - if (data) { - soc_dev_attr->soc_id = data->name; - if (data->soc_revision) - soc_rev = data->soc_revision(); - } - - soc_dev_attr->revision = imx8_revision(soc_rev); - if (!soc_dev_attr->revision) { - ret = -ENOMEM; - goto free_soc; - } - - soc_dev_attr->serial_number = kasprintf(GFP_KERNEL, "%016llX", soc_uid); - if (!soc_dev_attr->serial_number) { - ret = -ENOMEM; - goto free_rev; - } - - soc_dev = soc_device_register(soc_dev_attr); - if (IS_ERR(soc_dev)) { - ret = PTR_ERR(soc_dev); - goto free_serial_number; - } - - pr_info("SoC: %s revision %s\n", soc_dev_attr->soc_id, - soc_dev_attr->revision); - - if (IS_ENABLED(CONFIG_ARM_IMX_CPUFREQ_DT)) - platform_device_register_simple("imx-cpufreq-dt", -1, NULL, 0); - - return 0; - -free_serial_number: - kfree(soc_dev_attr->serial_number); -free_rev: - if (strcmp(soc_dev_attr->revision, "unknown")) - kfree(soc_dev_attr->revision); -free_soc: - kfree(soc_dev_attr); - return ret; -} -device_initcall(imx8_soc_init); diff --git a/drivers/soc/imx/soc-imx8m.c b/drivers/soc/imx/soc-imx8m.c new file mode 100644 index 000000000000..719e1f189ebf --- /dev/null +++ b/drivers/soc/imx/soc-imx8m.c @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 NXP. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define REV_B1 0x21 + +#define IMX8MQ_SW_INFO_B1 0x40 +#define IMX8MQ_SW_MAGIC_B1 0xff0055aa + +#define IMX_SIP_GET_SOC_INFO 0xc2000006 + +#define OCOTP_UID_LOW 0x410 +#define OCOTP_UID_HIGH 0x420 + +/* Same as ANADIG_DIGPROG_IMX7D */ +#define ANADIG_DIGPROG_IMX8MM 0x800 + +struct imx8_soc_data { + char *name; + u32 (*soc_revision)(void); +}; + +static u64 soc_uid; + +#ifdef CONFIG_HAVE_ARM_SMCCC +static u32 imx8mq_soc_revision_from_atf(void) +{ + struct arm_smccc_res res; + + arm_smccc_smc(IMX_SIP_GET_SOC_INFO, 0, 0, 0, 0, 0, 0, 0, &res); + + if (res.a0 == SMCCC_RET_NOT_SUPPORTED) + return 0; + else + return res.a0 & 0xff; +} +#else +static inline u32 imx8mq_soc_revision_from_atf(void) { return 0; }; +#endif + +static u32 __init imx8mq_soc_revision(void) +{ + struct device_node *np; + void __iomem *ocotp_base; + u32 magic; + u32 rev = 0; + + np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp"); + if (!np) + goto out; + + ocotp_base = of_iomap(np, 0); + WARN_ON(!ocotp_base); + + /* + * SOC revision on older imx8mq is not available in fuses so query + * the value from ATF instead. + */ + rev = imx8mq_soc_revision_from_atf(); + if (!rev) { + magic = readl_relaxed(ocotp_base + IMX8MQ_SW_INFO_B1); + if (magic == IMX8MQ_SW_MAGIC_B1) + rev = REV_B1; + } + + soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH); + soc_uid <<= 32; + soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW); + + iounmap(ocotp_base); + +out: + of_node_put(np); + return rev; +} + +static void __init imx8mm_soc_uid(void) +{ + void __iomem *ocotp_base; + struct device_node *np; + + np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-ocotp"); + if (!np) + return; + + ocotp_base = of_iomap(np, 0); + WARN_ON(!ocotp_base); + + soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH); + soc_uid <<= 32; + soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW); + + iounmap(ocotp_base); + of_node_put(np); +} + +static u32 __init imx8mm_soc_revision(void) +{ + struct device_node *np; + void __iomem *anatop_base; + u32 rev; + + np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop"); + if (!np) + return 0; + + anatop_base = of_iomap(np, 0); + WARN_ON(!anatop_base); + + rev = readl_relaxed(anatop_base + ANADIG_DIGPROG_IMX8MM); + + iounmap(anatop_base); + of_node_put(np); + + imx8mm_soc_uid(); + + return rev; +} + +static const struct imx8_soc_data imx8mq_soc_data = { + .name = "i.MX8MQ", + .soc_revision = imx8mq_soc_revision, +}; + +static const struct imx8_soc_data imx8mm_soc_data = { + .name = "i.MX8MM", + .soc_revision = imx8mm_soc_revision, +}; + +static const struct imx8_soc_data imx8mn_soc_data = { + .name = "i.MX8MN", + .soc_revision = imx8mm_soc_revision, +}; + +static const struct imx8_soc_data imx8mp_soc_data = { + .name = "i.MX8MP", + .soc_revision = imx8mm_soc_revision, +}; + +static const struct of_device_id imx8_soc_match[] = { + { .compatible = "fsl,imx8mq", .data = &imx8mq_soc_data, }, + { .compatible = "fsl,imx8mm", .data = &imx8mm_soc_data, }, + { .compatible = "fsl,imx8mn", .data = &imx8mn_soc_data, }, + { .compatible = "fsl,imx8mp", .data = &imx8mp_soc_data, }, + { } +}; + +#define imx8_revision(soc_rev) \ + soc_rev ? \ + kasprintf(GFP_KERNEL, "%d.%d", (soc_rev >> 4) & 0xf, soc_rev & 0xf) : \ + "unknown" + +static int __init imx8_soc_init(void) +{ + struct soc_device_attribute *soc_dev_attr; + struct soc_device *soc_dev; + const struct of_device_id *id; + u32 soc_rev = 0; + const struct imx8_soc_data *data; + int ret; + + soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); + if (!soc_dev_attr) + return -ENOMEM; + + soc_dev_attr->family = "Freescale i.MX"; + + ret = of_property_read_string(of_root, "model", &soc_dev_attr->machine); + if (ret) + goto free_soc; + + id = of_match_node(imx8_soc_match, of_root); + if (!id) { + ret = -ENODEV; + goto free_soc; + } + + data = id->data; + if (data) { + soc_dev_attr->soc_id = data->name; + if (data->soc_revision) + soc_rev = data->soc_revision(); + } + + soc_dev_attr->revision = imx8_revision(soc_rev); + if (!soc_dev_attr->revision) { + ret = -ENOMEM; + goto free_soc; + } + + soc_dev_attr->serial_number = kasprintf(GFP_KERNEL, "%016llX", soc_uid); + if (!soc_dev_attr->serial_number) { + ret = -ENOMEM; + goto free_rev; + } + + soc_dev = soc_device_register(soc_dev_attr); + if (IS_ERR(soc_dev)) { + ret = PTR_ERR(soc_dev); + goto free_serial_number; + } + + pr_info("SoC: %s revision %s\n", soc_dev_attr->soc_id, + soc_dev_attr->revision); + + if (IS_ENABLED(CONFIG_ARM_IMX_CPUFREQ_DT)) + platform_device_register_simple("imx-cpufreq-dt", -1, NULL, 0); + + return 0; + +free_serial_number: + kfree(soc_dev_attr->serial_number); +free_rev: + if (strcmp(soc_dev_attr->revision, "unknown")) + kfree(soc_dev_attr->revision); +free_soc: + kfree(soc_dev_attr); + return ret; +} +device_initcall(imx8_soc_init); -- cgit v1.2.3