From b5cc96d3bfcbc495a350f78aa2e1295b238d26da Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Mon, 20 Jan 2020 14:51:28 +0200 Subject: soc: imx: gpcv2: include linux/sizes.h This header is included indirectly on arm/arm64 but not on x86 so CONFIG_COMPILE_TEST breaks. Fix by including directly. Signed-off-by: Leonard Crestez Signed-off-by: Shawn Guo --- drivers/soc/imx/gpcv2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c index b0dffb06c05d..6cf8a7a412bd 100644 --- a/drivers/soc/imx/gpcv2.c +++ b/drivers/soc/imx/gpcv2.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3-59-g8ed1b From 0a7696b319511b0eccb0c92d030d84653b90a975 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Mon, 27 Jan 2020 14:27:31 +0000 Subject: firmware: imx: scu-pd: Add missing audio PD ranges imx8qxp_scu_pd_ranges keeps PD ranges for both i.MX8QM and i.MX8QXP. The following PD are missing: audio-clk1/ spdif1 / sai3..7. Add them now. Signed-off-by: Daniel Baluta Signed-off-by: Shawn Guo --- drivers/firmware/imx/scu-pd.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c index b556612207e5..c10f63901c1c 100644 --- a/drivers/firmware/imx/scu-pd.c +++ b/drivers/firmware/imx/scu-pd.c @@ -109,6 +109,7 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { { "audio-pll0", IMX_SC_R_AUDIO_PLL_0, 1, false, 0 }, { "audio-pll1", IMX_SC_R_AUDIO_PLL_1, 1, false, 0 }, { "audio-clk-0", IMX_SC_R_AUDIO_CLK_0, 1, false, 0 }, + { "audio-clk-1", IMX_SC_R_AUDIO_CLK_1, 1, false, 0 }, { "dma0-ch", IMX_SC_R_DMA_0_CH0, 16, true, 0 }, { "dma1-ch", IMX_SC_R_DMA_1_CH0, 16, true, 0 }, { "dma2-ch", IMX_SC_R_DMA_2_CH0, 5, true, 0 }, @@ -116,7 +117,13 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { { "asrc1", IMX_SC_R_ASRC_1, 1, false, 0 }, { "esai0", IMX_SC_R_ESAI_0, 1, false, 0 }, { "spdif0", IMX_SC_R_SPDIF_0, 1, false, 0 }, + { "spdif1", IMX_SC_R_SPDIF_1, 1, false, 0 }, { "sai", IMX_SC_R_SAI_0, 3, true, 0 }, + { "sai3", IMX_SC_R_SAI_3, 1, false, 0 }, + { "sai4", IMX_SC_R_SAI_4, 1, false, 0 }, + { "sai5", IMX_SC_R_SAI_5, 1, false, 0 }, + { "sai6", IMX_SC_R_SAI_6, 1, false, 0 }, + { "sai7", IMX_SC_R_SAI_7, 1, false, 0 }, { "amix", IMX_SC_R_AMIX, 1, false, 0 }, { "mqs0", IMX_SC_R_MQS_0, 1, false, 0 }, { "dsp", IMX_SC_R_DSP, 1, false, 0 }, -- cgit v1.2.3-59-g8ed1b From e391b24d94915ff870cdca9a1cee01324326bb95 Mon Sep 17 00:00:00 2001 From: Sebastien Fagard Date: Mon, 27 Jan 2020 14:27:32 +0000 Subject: firmware: imx: scu-pd: enlarge PD range for mu_b The range of resources for Messaging Units side B needs to contain all the possible MUB resource available: starting from MU_5B up to MU_13B. This patch is needed to enable MU_8B for the 'imx-shmem-net' driver which allows two OS partitions communicating via MUs without Hypervisor. Signed-off-by: Sebastien Fagard Signed-off-by: Daniel Baluta Signed-off-by: Shawn Guo --- drivers/firmware/imx/scu-pd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c index c10f63901c1c..09cfa268c6bd 100644 --- a/drivers/firmware/imx/scu-pd.c +++ b/drivers/firmware/imx/scu-pd.c @@ -93,7 +93,7 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { { "kpp", IMX_SC_R_KPP, 1, false, 0 }, { "fspi", IMX_SC_R_FSPI_0, 2, true, 0 }, { "mu_a", IMX_SC_R_MU_0A, 14, true, 0 }, - { "mu_b", IMX_SC_R_MU_13B, 1, true, 13 }, + { "mu_b", IMX_SC_R_MU_5B, 9, true, 5 }, /* CONN SS */ { "usb", IMX_SC_R_USB_0, 2, true, 0 }, -- cgit v1.2.3-59-g8ed1b From 4f929d0877543df8a834afa5b8732d469c05cd84 Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Thu, 20 Feb 2020 17:56:49 +0200 Subject: firmware: imx: Remove IMX_SC_RPC_SVC_ABORT This is not used by linux and not supported as part of imx SCU api, it was added by mistake. The constant value "9" has since been reassigned in firmware to a different service. Signed-off-by: Leonard Crestez Signed-off-by: Shawn Guo --- include/linux/firmware/imx/ipc.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/firmware/imx/ipc.h b/include/linux/firmware/imx/ipc.h index 6312c8cb084a..891057434858 100644 --- a/include/linux/firmware/imx/ipc.h +++ b/include/linux/firmware/imx/ipc.h @@ -25,7 +25,6 @@ enum imx_sc_rpc_svc { IMX_SC_RPC_SVC_PAD = 6, IMX_SC_RPC_SVC_MISC = 7, IMX_SC_RPC_SVC_IRQ = 8, - IMX_SC_RPC_SVC_ABORT = 9 }; struct imx_sc_rpc_msg { -- cgit v1.2.3-59-g8ed1b From 705dcca91d0a75f5657f3d5465f7dbd31c3efa8b Mon Sep 17 00:00:00 2001 From: Joakim Zhang Date: Mon, 17 Feb 2020 11:19:15 +0800 Subject: firmware: imx: scu-pd: add power domain for I2C and INTMUX in CM40 SS Add power domain for I2C and INTMUX in CM40 SS. Signed-off-by: Joakim Zhang Signed-off-by: Shawn Guo --- drivers/firmware/imx/scu-pd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c index 09cfa268c6bd..f3b4246ff200 100644 --- a/drivers/firmware/imx/scu-pd.c +++ b/drivers/firmware/imx/scu-pd.c @@ -165,6 +165,10 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { /* DC SS */ { "dc0", IMX_SC_R_DC_0, 1, false, 0 }, { "dc0-pll", IMX_SC_R_DC_0_PLL_0, 2, true, 0 }, + + /* CM40 SS */ + { "cm40_i2c", IMX_SC_R_M4_0_I2C, 1, 0 }, + { "cm40_intmux", IMX_SC_R_M4_0_INTMUX, 1, 0 }, }; static const struct imx_sc_pd_soc imx8qxp_scu_pd = { -- cgit v1.2.3-59-g8ed1b 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/Makefile | 2 +- drivers/soc/imx/Kconfig | 9 ++ drivers/soc/imx/Makefile | 2 +- drivers/soc/imx/soc-imx8.c | 230 -------------------------------------------- drivers/soc/imx/soc-imx8m.c | 230 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 241 insertions(+), 232 deletions(-) delete mode 100644 drivers/soc/imx/soc-imx8.c create mode 100644 drivers/soc/imx/soc-imx8m.c diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index 8b49d782a1ab..a39f17cea376 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -11,7 +11,7 @@ obj-$(CONFIG_ARCH_DOVE) += dove/ obj-$(CONFIG_MACH_DOVE) += dove/ obj-y += fsl/ obj-$(CONFIG_ARCH_GEMINI) += gemini/ -obj-$(CONFIG_ARCH_MXC) += imx/ +obj-y += imx/ obj-$(CONFIG_ARCH_IXP4XX) += ixp4xx/ obj-$(CONFIG_SOC_XWAY) += lantiq/ obj-y += mediatek/ 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-59-g8ed1b From e0ea2d11f8a08ba7066ff897e16c5217215d1e68 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Fri, 13 Mar 2020 11:09:12 +0100 Subject: soc: imx: gpc: fix power up sequencing Currently we wait only until the PGC inverts the isolation setting before disabling the peripheral clocks. This doesn't ensure that the reset is properly propagated through the peripheral devices in the power domain. Wait until the PGC signals that the power up request is done and wait a bit for resets to propagate before disabling the clocks. Signed-off-by: Lucas Stach Signed-off-by: Shawn Guo --- drivers/soc/imx/gpc.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c index 98b9d9a902ae..90a8b2c0676f 100644 --- a/drivers/soc/imx/gpc.c +++ b/drivers/soc/imx/gpc.c @@ -87,8 +87,8 @@ static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd) static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd) { struct imx_pm_domain *pd = to_imx_pm_domain(genpd); - int i, ret, sw, sw2iso; - u32 val; + int i, ret; + u32 val, req; if (pd->supply) { ret = regulator_enable(pd->supply); @@ -107,17 +107,18 @@ static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd) regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS, 0x1, 0x1); - /* Read ISO and ISO2SW power up delays */ - regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS, &val); - sw = val & 0x3f; - sw2iso = (val >> 8) & 0x3f; - /* Request GPC to power up domain */ - val = BIT(pd->cntr_pdn_bit + 1); - regmap_update_bits(pd->regmap, GPC_CNTR, val, val); + req = BIT(pd->cntr_pdn_bit + 1); + regmap_update_bits(pd->regmap, GPC_CNTR, req, req); - /* Wait ISO + ISO2SW IPG clock cycles */ - udelay(DIV_ROUND_UP(sw + sw2iso, pd->ipg_rate_mhz)); + /* Wait for the PGC to handle the request */ + ret = regmap_read_poll_timeout(pd->regmap, GPC_CNTR, val, !(val & req), + 1, 50); + if (ret) + pr_err("powerup request on domain %s timed out\n", genpd->name); + + /* Wait for reset to propagate through peripherals */ + usleep_range(5, 10); /* Disable reset clocks for all devices in the domain */ for (i = 0; i < pd->num_clks; i++) @@ -343,6 +344,7 @@ static const struct regmap_config imx_gpc_regmap_config = { .rd_table = &access_table, .wr_table = &access_table, .max_register = 0x2ac, + .fast_io = true, }; static struct generic_pm_domain *imx_gpc_onecell_domains[] = { -- cgit v1.2.3-59-g8ed1b From 5b00b83754167ce060495aca3945a725b9190a15 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Sat, 7 Mar 2020 09:25:54 +0800 Subject: firmware: imx: add COMPILE_TEST for IMX_SCU driver Add COMPILE_TEST support to IMX_SCU driver for better compile testing coverage. Any driver depending on IMX_SCU shouldn't have COMPILE_TEST though. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- drivers/firmware/imx/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/imx/Kconfig b/drivers/firmware/imx/Kconfig index 1d2e5b85d7ca..58e8c6c115a0 100644 --- a/drivers/firmware/imx/Kconfig +++ b/drivers/firmware/imx/Kconfig @@ -12,7 +12,7 @@ config IMX_DSP config IMX_SCU bool "IMX SCU Protocol driver" - depends on IMX_MBOX + depends on IMX_MBOX || COMPILE_TEST help The System Controller Firmware (SCFW) is a low-level system function which runs on a dedicated Cortex-M core to provide power, clock, and -- cgit v1.2.3-59-g8ed1b From 2a52651292ad9e642d205ce2ece2686d3b3395a7 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 16 Mar 2020 11:09:02 +0800 Subject: soc: imx: drop COMPILE_TEST for IMX_SCU_SOC With COMPILE_TEST, there will be build error, because IMX_SCU might be set to n, so drop COMPILE_TEST. Suggested-by: Shawn Guo Signed-off-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/soc/imx/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/imx/Kconfig b/drivers/soc/imx/Kconfig index 70019cefa617..67aa94b2481b 100644 --- a/drivers/soc/imx/Kconfig +++ b/drivers/soc/imx/Kconfig @@ -10,7 +10,7 @@ config IMX_GPCV2_PM_DOMAINS config IMX_SCU_SOC bool "i.MX System Controller Unit SoC info support" - depends on IMX_SCU || COMPILE_TEST + depends on IMX_SCU select SOC_BUS help If you say yes here you get support for the NXP i.MX System -- cgit v1.2.3-59-g8ed1b