[PATCH v3 5/6] ARM: rockchip: add basic smp support for rk3288
Heiko Stübner
heiko at sntech.de
Sat Oct 11 10:55:23 PDT 2014
Am Freitag, 10. Oktober 2014, 14:26:09 schrieb Kever Yang:
> This patch add basic rk3288 smp support.
>
> Only cortex-A9 need invalid L1, A7/A12/A15/A17 should not invalid L1, since
> for A7/A12/A15, the invalidation would be taken as clean and invalidate.
>
> If you use the software manual invalidation instead of hardware invalidation
> (assert l1/l2rstdisable during reset) after reset, there is tiny change
> that some cachelines would be in dirty and valid state after reset(since
> the ram content would be random value after reset), then the unexpected
> clean might lead to system crash.
>
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> Signed-off-by: Kever Yang <kever.yang at rock-chips.com>
> ---
>
> Changes in v3:
> - use one ops and secondary_starup for all rockchip SOCs
> - pick back the power domain operation for cpu hotplug
>
> Changes in v2:
> - use rk3288_boot_secondary instead ofsmp_boot_secondary
> - discards the power domain operation
> - handle the per cpu starup when actived by 'sev'
>
> arch/arm/mach-rockchip/headsmp.S | 5 ++-
> arch/arm/mach-rockchip/platsmp.c | 81
> ++++++++++++++++++++++++++++------------ 2 files changed, 61 insertions(+),
> 25 deletions(-)
>
> diff --git a/arch/arm/mach-rockchip/headsmp.S
> b/arch/arm/mach-rockchip/headsmp.S index 73206e3..46c22de 100644
> --- a/arch/arm/mach-rockchip/headsmp.S
> +++ b/arch/arm/mach-rockchip/headsmp.S
> @@ -16,7 +16,10 @@
> #include <linux/init.h>
>
> ENTRY(rockchip_secondary_startup)
> - bl v7_invalidate_l1
> + mrc p15, 0, r0, c0, c0, 0 @ read main ID register
> + ldr r1, =0x00000c09 @ Cortex-A9 primary part number
> + teq r0, r1
> + beq v7_invalidate_l1
> b secondary_startup
> ENDPROC(rockchip_secondary_startup)
>
> diff --git a/arch/arm/mach-rockchip/platsmp.c
> b/arch/arm/mach-rockchip/platsmp.c index 57b53b3..d1f858e 100644
> --- a/arch/arm/mach-rockchip/platsmp.c
> +++ b/arch/arm/mach-rockchip/platsmp.c
> @@ -84,6 +84,8 @@ static int pmu_set_power_domain(int pd, bool on)
> static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
> struct task_struct *idle)
> {
> + int ret;
> +
> if (!sram_base_addr || !pmu) {
> pr_err("%s: sram or pmu missing for cpu boot\n", __func__);
> return -ENXIO;
> @@ -96,7 +98,26 @@ static int __cpuinit rockchip_boot_secondary(unsigned int
> cpu, }
>
> /* start the core */
> - return pmu_set_power_domain(0 + cpu, true);
> + ret = pmu_set_power_domain(0 + cpu, true);
> + if (ret < 0)
> + return ret;
> +
> + if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
> + /* We communicate with the bootrom to active the cpus other
> + * than cpu0, after a blob of initialize code, they will
> + * stay at wfe state, once they are actived, they will check
> + * the mailbox:
> + * sram_base_addr + 4: 0xdeadbeaf
> + * sram_base_addr + 8: start address for pc
> + * */
> + udelay(10);
> + writel(virt_to_phys(rockchip_secondary_startup),
> + sram_base_addr + 8);
> + writel(0xDEADBEAF, sram_base_addr + 4);
> + dsb_sev();
> + }
> +
> + return 0;
> }
>
> /**
> @@ -129,8 +150,6 @@ static int __init rockchip_smp_prepare_sram(struct
> device_node *node) return -EINVAL;
> }
>
> - sram_base_addr = of_iomap(node, 0);
> -
> /* set the boot function for the sram code */
> rockchip_boot_fn = virt_to_phys(rockchip_secondary_startup);
>
> @@ -203,18 +222,7 @@ static void __init rockchip_smp_prepare_cpus(unsigned
> int max_cpus) {
> struct device_node *node;
> unsigned int i;
> -
> - node = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
> - if (!node) {
> - pr_err("%s: missing scu\n", __func__);
> - return;
> - }
> -
> - scu_base_addr = of_iomap(node, 0);
> - if (!scu_base_addr) {
> - pr_err("%s: could not map scu registers\n", __func__);
> - return;
> - }
> + unsigned int l2ctlr;
please move this l2ctlr below inside the else branch - as it's only used
there.
>
> node = of_find_compatible_node(NULL, NULL, "rockchip,rk3066-smp-sram");
> if (!node) {
> @@ -222,22 +230,47 @@ static void __init rockchip_smp_prepare_cpus(unsigned
> int max_cpus) return;
> }
>
> - if (rockchip_smp_prepare_sram(node))
> + sram_base_addr = of_iomap(node, 0);
> + if (!sram_base_addr) {
> + pr_err("%s: could not map sram registers\n", __func__);
> return;
> + }
>
> if (rockchip_smp_prepare_pmu())
> return;
>
> - /* enable the SCU power domain */
> - pmu_set_power_domain(PMU_PWRDN_SCU, true);
> + if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
> + if (rockchip_smp_prepare_sram(node))
> + return;
>
> - /*
> - * While the number of cpus is gathered from dt, also get the number
> - * of cores from the scu to verify this value when booting the cores.
> - */
> - ncores = scu_get_core_count(scu_base_addr);
> + /* enable the SCU power domain */
> + pmu_set_power_domain(PMU_PWRDN_SCU, true);
> +
> + node = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
> + if (!node) {
> + pr_err("%s: missing scu\n", __func__);
> + return;
> + }
>
> - scu_enable(scu_base_addr);
> + scu_base_addr = of_iomap(node, 0);
> + if (!scu_base_addr) {
> + pr_err("%s: could not map scu registers\n", __func__);
> + return;
> + }
> +
> + /*
> + * While the number of cpus is gathered from dt, also get the
> + * number of cores from the scu to verify this value when
> + * booting the cores.
> + */
> + ncores = scu_get_core_count(scu_base_addr);
> + pr_err("%s: ncores %d\n", __func__, ncores);
> +
> + scu_enable(scu_base_addr);
> + } else {
-> here
> + asm ("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr));
> + ncores = ((l2ctlr >> 24) & 0x3) + 1;
> + }
>
> /* Make sure that all cores except the first are really off */
> for (i = 1; i < ncores; i++)
More information about the linux-arm-kernel
mailing list