On Sat, Apr 26, 2014 at 05:05:47PM +0100, Abhilash Kesavan wrote: [...] > + if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) { > + arch_spin_unlock(&exynos_mcpm_lock); > + I missed it on first review, but you do need to disable L2 prefetching on A15 here as we do in TC2 (tc2_pm.c), this power down procedure is not compliant otherwise. Thanks, Lorenzo > + /* Flush all cache levels for this cluster. */ > + exynos_v7_exit_coherency_flush(all); > + > + /* > + * Disable cluster-level coherency by masking > + * incoming snoops and DVM messages: > + */ > + cci_disable_port_by_cpu(mpidr); > + > + __mcpm_outbound_leave_critical(cluster, CLUSTER_DOWN); > + } else { > + arch_spin_unlock(&exynos_mcpm_lock); > + > + /* Disable and flush the local CPU cache. */ > + exynos_v7_exit_coherency_flush(louis); > + } > + > + __mcpm_cpu_down(cpu, cluster); > + > + /* Now we are prepared for power-down, do it: */ > + if (!skip_wfi) > + wfi(); > + > + /* Not dead at this point? Let our caller cope. */ > +} > + > +static int exynos_power_down_finish(unsigned int cpu, unsigned int cluster) > +{ > + unsigned int tries = 100; > + unsigned int cpunr = cpu + (cluster * EXYNOS5420_CPUS_PER_CLUSTER); > + > + pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster); > + BUG_ON(cpu >= EXYNOS5420_CPUS_PER_CLUSTER || > + cluster >= EXYNOS5420_NR_CLUSTERS); > + > + /* Wait for the core state to be OFF */ > + while (tries--) { > + if (ACCESS_ONCE(cpu_use_count[cpu][cluster]) == 0) { > + if ((exynos_cpu_power_state(cpunr) == 0)) > + return 0; /* success: the CPU is halted */ > + } > + > + /* Otherwise, wait and retry: */ > + msleep(1); > + } > + > + return -ETIMEDOUT; /* timeout */ > +} > + > +static const struct mcpm_platform_ops exynos_power_ops = { > + .power_up = exynos_power_up, > + .power_down = exynos_power_down, > + .power_down_finish = exynos_power_down_finish, > +}; > + > +static void __init exynos_mcpm_usage_count_init(void) > +{ > + unsigned int mpidr, cpu, cluster; > + > + mpidr = read_cpuid_mpidr(); > + cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0); > + cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); > + > + pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster); > + BUG_ON(cpu >= EXYNOS5420_CPUS_PER_CLUSTER || > + cluster >= EXYNOS5420_NR_CLUSTERS); > + > + cpu_use_count[cpu][cluster] = 1; > +} > + > +/* > + * Enable cluster-level coherency, in preparation for turning on the MMU. > + */ > +static void __naked exynos_pm_power_up_setup(unsigned int affinity_level) > +{ > + asm volatile ("\n" > + "cmp r0, #1\n" > + "bxne lr\n" > + "b cci_enable_port_for_self"); > +} > + > +static int __init exynos_mcpm_init(void) > +{ > + int ret = 0; > + > + if (!soc_is_exynos5420()) > + return -ENODEV; > + > + if (!cci_probed()) > + return -ENODEV; > + > + /* > + * To increase the stability of KFC reset we need to program > + * the PMU SPARE3 register > + */ > + __raw_writel(EXYNOS5420_SWRESET_KFC_SEL, S5P_PMU_SPARE3); > + > + exynos_mcpm_usage_count_init(); > + > + ret = mcpm_platform_register(&exynos_power_ops); > + if (!ret) > + ret = mcpm_sync_init(exynos_pm_power_up_setup); > + if (ret) > + return ret; > + > + mcpm_smp_set_ops(); > + > + pr_info("Exynos MCPM support installed\n"); > + > + /* > + * Future entries into the kernel can now go > + * through the cluster entry vectors. > + */ > + __raw_writel(virt_to_phys(mcpm_entry_point), > + REG_ENTRY_ADDR); > + > + return ret; > +} > + > +early_initcall(exynos_mcpm_init); > diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h > index 6685ebf..f44d318 100644 > --- a/arch/arm/mach-exynos/regs-pmu.h > +++ b/arch/arm/mach-exynos/regs-pmu.h > @@ -38,6 +38,7 @@ > #define S5P_INFORM5 S5P_PMUREG(0x0814) > #define S5P_INFORM6 S5P_PMUREG(0x0818) > #define S5P_INFORM7 S5P_PMUREG(0x081C) > +#define S5P_PMU_SPARE3 S5P_PMUREG(0x090C) > > #define S5P_ARM_CORE0_LOWPWR S5P_PMUREG(0x1000) > #define S5P_DIS_IRQ_CORE0 S5P_PMUREG(0x1004) > @@ -325,4 +326,6 @@ > > #define EXYNOS5_OPTION_USE_RETENTION (1 << 4) > > +#define EXYNOS5420_SWRESET_KFC_SEL 0x3 > + > #endif /* __ASM_ARCH_REGS_PMU_H */ > -- > 1.8.3.2 > > -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html