* [PATCH V2] ARM: imx: add smp support for imx7d
@ 2021-01-07 12:31 Marek Vasut
2021-01-17 11:46 ` Shawn Guo
0 siblings, 1 reply; 3+ messages in thread
From: Marek Vasut @ 2021-01-07 12:31 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Marek Vasut, Shawn Guo, Arulpandiyan Vadivel, Anson Huang,
Leonard Crestez, Fabio Estevam, NXP Linux Team
From: Anson Huang <b20788@freescale.com>
Add SMP support for i.MX7D, including CPU hotplug support, for
systems where TFA is not present.
The arm,cpu-registers-not-fw-configured is required, otherwise the
timer does not work correctly.
Signed-off-by: Anson Huang <b20788@freescale.com>
Signed-off-by: Arulpandiyan Vadivel <arulpandiyan_vadivel@mentor.com> # Fix merge conflicts
Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
Signed-off-by: Marek Vasut <marex@denx.de> # heavy cleanup
Cc: Fabio Estevam <festevam@gmail.com>
Cc: NXP Linux Team <linux-imx@nxp.com>
Cc: Shawn Guo <shawnguo@kernel.org>
To: linux-arm-kernel@lists.infradead.org
---
V2: - Fix trivial typo in SRC_GPR1() macro
- Add timeout in imx_gpcv2_set_core1_pdn_pup_by_software()
---
arch/arm/mach-imx/Makefile | 2 +-
arch/arm/mach-imx/common.h | 3 ++
arch/arm/mach-imx/headsmp.S | 9 ++++
arch/arm/mach-imx/hotplug.c | 3 ++
arch/arm/mach-imx/mach-imx7d.c | 3 +-
arch/arm/mach-imx/platsmp.c | 26 ++++++++++
arch/arm/mach-imx/src.c | 86 ++++++++++++++++++++++++++++++----
7 files changed, 121 insertions(+), 11 deletions(-)
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 9cebd360d58e..d1506ef7a537 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -35,7 +35,7 @@ obj-$(CONFIG_HAVE_IMX_ANATOP) += anatop.o
obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
obj-$(CONFIG_HAVE_IMX_SRC) += src.o
-ifneq ($(CONFIG_SOC_IMX6)$(CONFIG_SOC_LS1021A),)
+ifneq ($(CONFIG_SOC_IMX6)$(CONFIG_SOC_IMX7D_CA7)$(CONFIG_SOC_LS1021A),)
AFLAGS_headsmp.o :=-Wa,-march=armv7-a
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 2d76e2c6c99e..e99c65698086 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -69,11 +69,13 @@ void imx_set_cpu_arg(int cpu, u32 arg);
void v7_secondary_startup(void);
void imx_scu_map_io(void);
void imx_smp_prepare(void);
+void imx_gpcv2_set_core1_pdn_pup_by_software(bool pdn);
#else
static inline void imx_scu_map_io(void) {}
static inline void imx_smp_prepare(void) {}
#endif
void imx_src_init(void);
+void imx7_src_init(void);
void imx_gpc_pre_suspend(bool arm_power_off);
void imx_gpc_post_resume(void);
void imx_gpc_mask_all(void);
@@ -133,6 +135,7 @@ static inline void imx_init_l2cache(void) {}
#endif
extern const struct smp_operations imx_smp_ops;
+extern const struct smp_operations imx7_smp_ops;
extern const struct smp_operations ls1021a_smp_ops;
#endif
diff --git a/arch/arm/mach-imx/headsmp.S b/arch/arm/mach-imx/headsmp.S
index 766dbdb2ae27..fcba58be8e79 100644
--- a/arch/arm/mach-imx/headsmp.S
+++ b/arch/arm/mach-imx/headsmp.S
@@ -21,6 +21,15 @@ diag_reg_offset:
ENTRY(v7_secondary_startup)
ARM_BE8(setend be) @ go BE8 if entered LE
+ mrc p15, 0, r0, c0, c0, 0
+ lsl r0, r0, #16
+ lsr r0, r0, #20
+ /* 0xc07 is cortex A7's ID */
+ mov r1, #0xc00
+ orr r1, #0x7
+ cmp r0, r1
+ beq secondary_startup
+
set_diag_reg
b secondary_startup
ENDPROC(v7_secondary_startup)
diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c
index 82e22398d43d..e24a46dc5703 100644
--- a/arch/arm/mach-imx/hotplug.c
+++ b/arch/arm/mach-imx/hotplug.c
@@ -11,6 +11,7 @@
#include <asm/proc-fns.h>
#include "common.h"
+#include "hardware.h"
/*
* platform-specific code to shutdown a CPU
@@ -40,5 +41,7 @@ int imx_cpu_kill(unsigned int cpu)
return 0;
imx_enable_cpu(cpu, false);
imx_set_cpu_arg(cpu, 0);
+ if (cpu_is_imx7d())
+ imx_gpcv2_set_core1_pdn_pup_by_software(true);
return 1;
}
diff --git a/arch/arm/mach-imx/mach-imx7d.c b/arch/arm/mach-imx/mach-imx7d.c
index 879c35929a13..1eeb194fab65 100644
--- a/arch/arm/mach-imx/mach-imx7d.c
+++ b/arch/arm/mach-imx/mach-imx7d.c
@@ -91,7 +91,7 @@ static void __init imx7d_init_late(void)
static void __init imx7d_init_irq(void)
{
imx_init_revision_from_anatop();
- imx_src_init();
+ imx7_src_init();
irqchip_init();
}
@@ -102,6 +102,7 @@ static const char *const imx7d_dt_compat[] __initconst = {
};
DT_MACHINE_START(IMX7D, "Freescale i.MX7 Dual (Device Tree)")
+ .smp = smp_ops(imx7_smp_ops),
.init_irq = imx7d_init_irq,
.init_machine = imx7d_init_machine,
.init_late = imx7d_init_late,
diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
index cf4e9335831c..972639038be5 100644
--- a/arch/arm/mach-imx/platsmp.c
+++ b/arch/arm/mach-imx/platsmp.c
@@ -92,6 +92,32 @@ const struct smp_operations imx_smp_ops __initconst = {
#endif
};
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+static void __init imx7_smp_init_cpus(void)
+{
+ struct device_node *np;
+ int i, ncores = 0;
+
+ /* The iMX7D SCU does not report core count, get it from DT */
+ for_each_of_cpu_node(np)
+ ncores++;
+
+ for (i = ncores; i < NR_CPUS; i++)
+ set_cpu_possible(i, false);
+}
+
+const struct smp_operations imx7_smp_ops __initconst = {
+ .smp_init_cpus = imx7_smp_init_cpus,
+ .smp_boot_secondary = imx_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_die = imx_cpu_die,
+ .cpu_kill = imx_cpu_kill,
+#endif
+};
+
#define DCFG_CCSR_SCRATCHRW1 0x200
static int ls1021a_boot_secondary(unsigned int cpu, struct task_struct *idle)
diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c
index f52f371292ac..37cc2d12e196 100644
--- a/arch/arm/mach-imx/src.c
+++ b/arch/arm/mach-imx/src.c
@@ -6,15 +6,19 @@
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/iopoll.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/reset-controller.h>
#include <linux/smp.h>
#include <asm/smp_plat.h>
#include "common.h"
+#include "hardware.h"
#define SRC_SCR 0x000
-#define SRC_GPR1 0x020
+#define SRC_GPR1_V1 0x020
+#define SRC_GPR1_V2 0x074
+#define SRC_GPR1(gpr_v2) ((gpr_v2) ? SRC_GPR1_V2 : SRC_GPR1_V1)
#define BP_SRC_SCR_WARM_RESET_ENABLE 0
#define BP_SRC_SCR_SW_GPU_RST 1
#define BP_SRC_SCR_SW_VPU_RST 2
@@ -23,9 +27,18 @@
#define BP_SRC_SCR_SW_IPU2_RST 12
#define BP_SRC_SCR_CORE1_RST 14
#define BP_SRC_SCR_CORE1_ENABLE 22
+/* below is for i.MX7D */
+#define SRC_A7RCR1 0x008
+#define BP_SRC_A7RCR1_A7_CORE1_ENABLE 1
+#define GPC_CPU_PGC_SW_PUP_REQ 0xf0
+#define GPC_CPU_PGC_SW_PDN_REQ 0xfc
+#define GPC_PGC_C1 0x840
+#define BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7 0x2
static void __iomem *src_base;
static DEFINE_SPINLOCK(scr_lock);
+static bool gpr_v2;
+static void __iomem *gpc_base;
static const int sw_reset_bits[5] = {
BP_SRC_SCR_SW_GPU_RST,
@@ -73,17 +86,54 @@ static struct reset_controller_dev imx_reset_controller = {
.nr_resets = ARRAY_SIZE(sw_reset_bits),
};
+void imx_gpcv2_set_m_core_pgc(bool enable, u32 offset)
+{
+ writel_relaxed(enable, gpc_base + offset);
+}
+
+void imx_gpcv2_set_core1_pdn_pup_by_software(bool pdn)
+{
+ u32 reg = pdn ? GPC_CPU_PGC_SW_PDN_REQ : GPC_CPU_PGC_SW_PUP_REQ;
+ u32 val, pup;
+ int ret;
+
+ val = readl_relaxed(gpc_base + reg);
+ imx_gpcv2_set_m_core_pgc(true, GPC_PGC_C1);
+ val |= BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7;
+ writel_relaxed(val, gpc_base + reg);
+
+ ret = readl_relaxed_poll_timeout_atomic(gpc_base + reg, pup,
+ !(pup & BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7),
+ 5, 1000000);
+ if (WARN_ON(ret)) {
+ val &= ~BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7;
+ writel_relaxed(val, gpc_base + reg);
+ }
+
+ imx_gpcv2_set_m_core_pgc(false, GPC_PGC_C1);
+}
+
void imx_enable_cpu(int cpu, bool enable)
{
u32 mask, val;
cpu = cpu_logical_map(cpu);
- mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
spin_lock(&scr_lock);
- val = readl_relaxed(src_base + SRC_SCR);
- val = enable ? val | mask : val & ~mask;
- val |= 1 << (BP_SRC_SCR_CORE1_RST + cpu - 1);
- writel_relaxed(val, src_base + SRC_SCR);
+ if (gpr_v2) {
+ if (enable)
+ imx_gpcv2_set_core1_pdn_pup_by_software(false);
+
+ mask = 1 << (BP_SRC_A7RCR1_A7_CORE1_ENABLE + cpu - 1);
+ val = readl_relaxed(src_base + SRC_A7RCR1);
+ val = enable ? val | mask : val & ~mask;
+ writel_relaxed(val, src_base + SRC_A7RCR1);
+ } else {
+ mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
+ val = readl_relaxed(src_base + SRC_SCR);
+ val = enable ? val | mask : val & ~mask;
+ val |= 1 << (BP_SRC_SCR_CORE1_RST + cpu - 1);
+ writel_relaxed(val, src_base + SRC_SCR);
+ }
spin_unlock(&scr_lock);
}
@@ -91,19 +141,19 @@ void imx_set_cpu_jump(int cpu, void *jump_addr)
{
cpu = cpu_logical_map(cpu);
writel_relaxed(__pa_symbol(jump_addr),
- src_base + SRC_GPR1 + cpu * 8);
+ src_base + SRC_GPR1(gpr_v2) + cpu * 8);
}
u32 imx_get_cpu_arg(int cpu)
{
cpu = cpu_logical_map(cpu);
- return readl_relaxed(src_base + SRC_GPR1 + cpu * 8 + 4);
+ return readl_relaxed(src_base + SRC_GPR1(gpr_v2) + cpu * 8 + 4);
}
void imx_set_cpu_arg(int cpu, u32 arg)
{
cpu = cpu_logical_map(cpu);
- writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4);
+ writel_relaxed(arg, src_base + SRC_GPR1(gpr_v2) + cpu * 8 + 4);
}
void __init imx_src_init(void)
@@ -131,3 +181,21 @@ void __init imx_src_init(void)
writel_relaxed(val, src_base + SRC_SCR);
spin_unlock(&scr_lock);
}
+
+void __init imx7_src_init(void)
+{
+ struct device_node *np;
+ gpr_v2 = true;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-src");
+ if (!np)
+ return;
+ src_base = of_iomap(np, 0);
+ WARN_ON(!src_base);
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-gpc");
+ if (WARN_ON(!np))
+ return;
+ gpc_base = of_iomap(np, 0);
+ WARN_ON(!gpc_base);
+}
--
2.29.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH V2] ARM: imx: add smp support for imx7d
2021-01-07 12:31 [PATCH V2] ARM: imx: add smp support for imx7d Marek Vasut
@ 2021-01-17 11:46 ` Shawn Guo
2021-01-17 12:31 ` Russell King - ARM Linux admin
0 siblings, 1 reply; 3+ messages in thread
From: Shawn Guo @ 2021-01-17 11:46 UTC (permalink / raw)
To: Marek Vasut
Cc: Arulpandiyan Vadivel, Anson Huang, Leonard Crestez, Fabio Estevam,
linux-arm-kernel, NXP Linux Team
On Thu, Jan 07, 2021 at 01:31:57PM +0100, Marek Vasut wrote:
> From: Anson Huang <b20788@freescale.com>
>
> Add SMP support for i.MX7D, including CPU hotplug support, for
> systems where TFA is not present.
>
> The arm,cpu-registers-not-fw-configured is required, otherwise the
> timer does not work correctly.
As DT change becomes another patch, this should be dropped.
>
> Signed-off-by: Anson Huang <b20788@freescale.com>
> Signed-off-by: Arulpandiyan Vadivel <arulpandiyan_vadivel@mentor.com> # Fix merge conflicts
> Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
> Signed-off-by: Marek Vasut <marex@denx.de> # heavy cleanup
Checkpatch warnings:
WARNING: usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc
#151: FILE: arch/arm/mach-imx/platsmp.c:108:
+ for (i = ncores; i < NR_CPUS; i++)
WARNING: Missing a blank line after declarations
#302: FILE: arch/arm/mach-imx/src.c:188:
+ struct device_node *np;
+ gpr_v2 = true;
> Cc: Fabio Estevam <festevam@gmail.com>
> Cc: NXP Linux Team <linux-imx@nxp.com>
> Cc: Shawn Guo <shawnguo@kernel.org>
> To: linux-arm-kernel@lists.infradead.org
> ---
> V2: - Fix trivial typo in SRC_GPR1() macro
> - Add timeout in imx_gpcv2_set_core1_pdn_pup_by_software()
> ---
> arch/arm/mach-imx/Makefile | 2 +-
> arch/arm/mach-imx/common.h | 3 ++
> arch/arm/mach-imx/headsmp.S | 9 ++++
> arch/arm/mach-imx/hotplug.c | 3 ++
> arch/arm/mach-imx/mach-imx7d.c | 3 +-
> arch/arm/mach-imx/platsmp.c | 26 ++++++++++
> arch/arm/mach-imx/src.c | 86 ++++++++++++++++++++++++++++++----
> 7 files changed, 121 insertions(+), 11 deletions(-)
>
> diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
> index 9cebd360d58e..d1506ef7a537 100644
> --- a/arch/arm/mach-imx/Makefile
> +++ b/arch/arm/mach-imx/Makefile
> @@ -35,7 +35,7 @@ obj-$(CONFIG_HAVE_IMX_ANATOP) += anatop.o
> obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
> obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
> obj-$(CONFIG_HAVE_IMX_SRC) += src.o
> -ifneq ($(CONFIG_SOC_IMX6)$(CONFIG_SOC_LS1021A),)
> +ifneq ($(CONFIG_SOC_IMX6)$(CONFIG_SOC_IMX7D_CA7)$(CONFIG_SOC_LS1021A),)
> AFLAGS_headsmp.o :=-Wa,-march=armv7-a
> obj-$(CONFIG_SMP) += headsmp.o platsmp.o
> obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
> diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
> index 2d76e2c6c99e..e99c65698086 100644
> --- a/arch/arm/mach-imx/common.h
> +++ b/arch/arm/mach-imx/common.h
> @@ -69,11 +69,13 @@ void imx_set_cpu_arg(int cpu, u32 arg);
> void v7_secondary_startup(void);
> void imx_scu_map_io(void);
> void imx_smp_prepare(void);
> +void imx_gpcv2_set_core1_pdn_pup_by_software(bool pdn);
> #else
> static inline void imx_scu_map_io(void) {}
> static inline void imx_smp_prepare(void) {}
> #endif
> void imx_src_init(void);
> +void imx7_src_init(void);
> void imx_gpc_pre_suspend(bool arm_power_off);
> void imx_gpc_post_resume(void);
> void imx_gpc_mask_all(void);
> @@ -133,6 +135,7 @@ static inline void imx_init_l2cache(void) {}
> #endif
>
> extern const struct smp_operations imx_smp_ops;
> +extern const struct smp_operations imx7_smp_ops;
> extern const struct smp_operations ls1021a_smp_ops;
>
> #endif
> diff --git a/arch/arm/mach-imx/headsmp.S b/arch/arm/mach-imx/headsmp.S
> index 766dbdb2ae27..fcba58be8e79 100644
> --- a/arch/arm/mach-imx/headsmp.S
> +++ b/arch/arm/mach-imx/headsmp.S
> @@ -21,6 +21,15 @@ diag_reg_offset:
>
> ENTRY(v7_secondary_startup)
> ARM_BE8(setend be) @ go BE8 if entered LE
> + mrc p15, 0, r0, c0, c0, 0
> + lsl r0, r0, #16
> + lsr r0, r0, #20
> + /* 0xc07 is cortex A7's ID */
> + mov r1, #0xc00
> + orr r1, #0x7
> + cmp r0, r1
> + beq secondary_startup
> +
> set_diag_reg
> b secondary_startup
> ENDPROC(v7_secondary_startup)
> diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c
> index 82e22398d43d..e24a46dc5703 100644
> --- a/arch/arm/mach-imx/hotplug.c
> +++ b/arch/arm/mach-imx/hotplug.c
> @@ -11,6 +11,7 @@
> #include <asm/proc-fns.h>
>
> #include "common.h"
> +#include "hardware.h"
>
> /*
> * platform-specific code to shutdown a CPU
> @@ -40,5 +41,7 @@ int imx_cpu_kill(unsigned int cpu)
> return 0;
> imx_enable_cpu(cpu, false);
> imx_set_cpu_arg(cpu, 0);
> + if (cpu_is_imx7d())
> + imx_gpcv2_set_core1_pdn_pup_by_software(true);
> return 1;
> }
> diff --git a/arch/arm/mach-imx/mach-imx7d.c b/arch/arm/mach-imx/mach-imx7d.c
> index 879c35929a13..1eeb194fab65 100644
> --- a/arch/arm/mach-imx/mach-imx7d.c
> +++ b/arch/arm/mach-imx/mach-imx7d.c
> @@ -91,7 +91,7 @@ static void __init imx7d_init_late(void)
> static void __init imx7d_init_irq(void)
> {
> imx_init_revision_from_anatop();
> - imx_src_init();
> + imx7_src_init();
> irqchip_init();
> }
>
> @@ -102,6 +102,7 @@ static const char *const imx7d_dt_compat[] __initconst = {
> };
>
> DT_MACHINE_START(IMX7D, "Freescale i.MX7 Dual (Device Tree)")
> + .smp = smp_ops(imx7_smp_ops),
> .init_irq = imx7d_init_irq,
> .init_machine = imx7d_init_machine,
> .init_late = imx7d_init_late,
> diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
> index cf4e9335831c..972639038be5 100644
> --- a/arch/arm/mach-imx/platsmp.c
> +++ b/arch/arm/mach-imx/platsmp.c
> @@ -92,6 +92,32 @@ const struct smp_operations imx_smp_ops __initconst = {
> #endif
> };
>
> +/*
> + * Initialise the CPU possible map early - this describes the CPUs
> + * which may be present or become present in the system.
> + */
> +static void __init imx7_smp_init_cpus(void)
> +{
> + struct device_node *np;
> + int i, ncores = 0;
> +
> + /* The iMX7D SCU does not report core count, get it from DT */
> + for_each_of_cpu_node(np)
> + ncores++;
> +
> + for (i = ncores; i < NR_CPUS; i++)
> + set_cpu_possible(i, false);
> +}
> +
> +const struct smp_operations imx7_smp_ops __initconst = {
> + .smp_init_cpus = imx7_smp_init_cpus,
> + .smp_boot_secondary = imx_boot_secondary,
> +#ifdef CONFIG_HOTPLUG_CPU
> + .cpu_die = imx_cpu_die,
> + .cpu_kill = imx_cpu_kill,
> +#endif
> +};
> +
> #define DCFG_CCSR_SCRATCHRW1 0x200
>
> static int ls1021a_boot_secondary(unsigned int cpu, struct task_struct *idle)
> diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c
> index f52f371292ac..37cc2d12e196 100644
> --- a/arch/arm/mach-imx/src.c
> +++ b/arch/arm/mach-imx/src.c
> @@ -6,15 +6,19 @@
>
> #include <linux/init.h>
> #include <linux/io.h>
> +#include <linux/iopoll.h>
> #include <linux/of.h>
> #include <linux/of_address.h>
> #include <linux/reset-controller.h>
> #include <linux/smp.h>
> #include <asm/smp_plat.h>
> #include "common.h"
> +#include "hardware.h"
>
> #define SRC_SCR 0x000
> -#define SRC_GPR1 0x020
> +#define SRC_GPR1_V1 0x020
> +#define SRC_GPR1_V2 0x074
> +#define SRC_GPR1(gpr_v2) ((gpr_v2) ? SRC_GPR1_V2 : SRC_GPR1_V1)
> #define BP_SRC_SCR_WARM_RESET_ENABLE 0
> #define BP_SRC_SCR_SW_GPU_RST 1
> #define BP_SRC_SCR_SW_VPU_RST 2
> @@ -23,9 +27,18 @@
> #define BP_SRC_SCR_SW_IPU2_RST 12
> #define BP_SRC_SCR_CORE1_RST 14
> #define BP_SRC_SCR_CORE1_ENABLE 22
> +/* below is for i.MX7D */
> +#define SRC_A7RCR1 0x008
> +#define BP_SRC_A7RCR1_A7_CORE1_ENABLE 1
> +#define GPC_CPU_PGC_SW_PUP_REQ 0xf0
> +#define GPC_CPU_PGC_SW_PDN_REQ 0xfc
> +#define GPC_PGC_C1 0x840
> +#define BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7 0x2
>
> static void __iomem *src_base;
> static DEFINE_SPINLOCK(scr_lock);
> +static bool gpr_v2;
> +static void __iomem *gpc_base;
>
> static const int sw_reset_bits[5] = {
> BP_SRC_SCR_SW_GPU_RST,
> @@ -73,17 +86,54 @@ static struct reset_controller_dev imx_reset_controller = {
> .nr_resets = ARRAY_SIZE(sw_reset_bits),
> };
>
> +void imx_gpcv2_set_m_core_pgc(bool enable, u32 offset)
static inline?
> +{
> + writel_relaxed(enable, gpc_base + offset);
> +}
> +
> +void imx_gpcv2_set_core1_pdn_pup_by_software(bool pdn)
Can we have some comments about this function, which is the main thing
that makes i.MX7 SMP support special, like what it does and when it
needs to be called?
> +{
> + u32 reg = pdn ? GPC_CPU_PGC_SW_PDN_REQ : GPC_CPU_PGC_SW_PUP_REQ;
> + u32 val, pup;
> + int ret;
> +
> + val = readl_relaxed(gpc_base + reg);
> + imx_gpcv2_set_m_core_pgc(true, GPC_PGC_C1);
Do you really need to call imx_gpcv2_set_m_core_pgc() after reading
PDN/PUP register?
> + val |= BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7;
> + writel_relaxed(val, gpc_base + reg);
> +
> + ret = readl_relaxed_poll_timeout_atomic(gpc_base + reg, pup,
> + !(pup & BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7),
> + 5, 1000000);
> + if (WARN_ON(ret)) {
I think a normal warning or error message is good enough.
> + val &= ~BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7;
> + writel_relaxed(val, gpc_base + reg);
> + }
> +
> + imx_gpcv2_set_m_core_pgc(false, GPC_PGC_C1);
> +}
> +
> void imx_enable_cpu(int cpu, bool enable)
> {
> u32 mask, val;
>
> cpu = cpu_logical_map(cpu);
> - mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
> spin_lock(&scr_lock);
> - val = readl_relaxed(src_base + SRC_SCR);
> - val = enable ? val | mask : val & ~mask;
> - val |= 1 << (BP_SRC_SCR_CORE1_RST + cpu - 1);
> - writel_relaxed(val, src_base + SRC_SCR);
> + if (gpr_v2) {
> + if (enable)
> + imx_gpcv2_set_core1_pdn_pup_by_software(false);
> +
> + mask = 1 << (BP_SRC_A7RCR1_A7_CORE1_ENABLE + cpu - 1);
> + val = readl_relaxed(src_base + SRC_A7RCR1);
> + val = enable ? val | mask : val & ~mask;
> + writel_relaxed(val, src_base + SRC_A7RCR1);
> + } else {
> + mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
> + val = readl_relaxed(src_base + SRC_SCR);
> + val = enable ? val | mask : val & ~mask;
> + val |= 1 << (BP_SRC_SCR_CORE1_RST + cpu - 1);
> + writel_relaxed(val, src_base + SRC_SCR);
> + }
> spin_unlock(&scr_lock);
> }
>
> @@ -91,19 +141,19 @@ void imx_set_cpu_jump(int cpu, void *jump_addr)
> {
> cpu = cpu_logical_map(cpu);
> writel_relaxed(__pa_symbol(jump_addr),
> - src_base + SRC_GPR1 + cpu * 8);
> + src_base + SRC_GPR1(gpr_v2) + cpu * 8);
> }
>
> u32 imx_get_cpu_arg(int cpu)
> {
> cpu = cpu_logical_map(cpu);
> - return readl_relaxed(src_base + SRC_GPR1 + cpu * 8 + 4);
> + return readl_relaxed(src_base + SRC_GPR1(gpr_v2) + cpu * 8 + 4);
> }
>
> void imx_set_cpu_arg(int cpu, u32 arg)
> {
> cpu = cpu_logical_map(cpu);
> - writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4);
> + writel_relaxed(arg, src_base + SRC_GPR1(gpr_v2) + cpu * 8 + 4);
> }
>
> void __init imx_src_init(void)
> @@ -131,3 +181,21 @@ void __init imx_src_init(void)
> writel_relaxed(val, src_base + SRC_SCR);
> spin_unlock(&scr_lock);
> }
> +
> +void __init imx7_src_init(void)
> +{
> + struct device_node *np;
> + gpr_v2 = true;
> +
> + np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-src");
> + if (!np)
> + return;
> + src_base = of_iomap(np, 0);
> + WARN_ON(!src_base);
Don't we need of_node_put()?
> +
> + np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-gpc");
> + if (WARN_ON(!np))
No WARN_ON.
Shawn
> + return;
> + gpc_base = of_iomap(np, 0);
> + WARN_ON(!gpc_base);
> +}
> --
> 2.29.2
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH V2] ARM: imx: add smp support for imx7d
2021-01-17 11:46 ` Shawn Guo
@ 2021-01-17 12:31 ` Russell King - ARM Linux admin
0 siblings, 0 replies; 3+ messages in thread
From: Russell King - ARM Linux admin @ 2021-01-17 12:31 UTC (permalink / raw)
To: Shawn Guo
Cc: Marek Vasut, Arulpandiyan Vadivel, Anson Huang, Leonard Crestez,
Fabio Estevam, linux-arm-kernel, NXP Linux Team
On Sun, Jan 17, 2021 at 07:46:20PM +0800, Shawn Guo wrote:
> On Thu, Jan 07, 2021 at 01:31:57PM +0100, Marek Vasut wrote:
> > From: Anson Huang <b20788@freescale.com>
> >
> > Add SMP support for i.MX7D, including CPU hotplug support, for
> > systems where TFA is not present.
> >
> > The arm,cpu-registers-not-fw-configured is required, otherwise the
> > timer does not work correctly.
>
> As DT change becomes another patch, this should be dropped.
>
> >
> > Signed-off-by: Anson Huang <b20788@freescale.com>
> > Signed-off-by: Arulpandiyan Vadivel <arulpandiyan_vadivel@mentor.com> # Fix merge conflicts
> > Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
> > Signed-off-by: Marek Vasut <marex@denx.de> # heavy cleanup
>
> Checkpatch warnings:
>
> WARNING: usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc
> #151: FILE: arch/arm/mach-imx/platsmp.c:108:
> + for (i = ncores; i < NR_CPUS; i++)
False. This is initialising the cpu possible map, so can't use
cpu_possible().
> > +void imx_gpcv2_set_m_core_pgc(bool enable, u32 offset)
>
> static inline?
Only "static" not "static inline" in a .c file.
> > +void __init imx7_src_init(void)
> > +{
> > + struct device_node *np;
> > + gpr_v2 = true;
> > +
> > + np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-src");
> > + if (!np)
> > + return;
> > + src_base = of_iomap(np, 0);
> > + WARN_ON(!src_base);
>
> Don't we need of_node_put()?
I always worry about this. The resources of the node remains in use
after the initialisation function has completed, so why _shouldn't_
the node also have a reference to it - in the same way that any
bound driver effectively maintains a reference on its DT node for
its lifetime. The only difference is that system devices such as this
have a lifetime of the system.
It's not like you could drop the "fsl,imx7d-src" node at runtime and
the system will do the right thing.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2021-01-17 12:33 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-01-07 12:31 [PATCH V2] ARM: imx: add smp support for imx7d Marek Vasut
2021-01-17 11:46 ` Shawn Guo
2021-01-17 12:31 ` Russell King - ARM Linux admin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).