
On Wed, Feb 18, 2015 at 09:14:03AM +0100, Jan Kiszka wrote: [...]
diff --git a/arch/arm/cpu/armv7/tegra124/ap.c b/arch/arm/cpu/armv7/tegra124/ap.c
[...]
+void ap_pm_init(void) +{
- struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE;
- struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
- writel((u32)park_cpu, EXCEP_VECTOR_CPU_RESET_VECTOR);
- tegra_powergate_power_on(TEGRA_POWERGATE_CPU1);
- tegra_powergate_power_on(TEGRA_POWERGATE_CPU2);
- tegra_powergate_power_on(TEGRA_POWERGATE_CPU3);
- writel((2 << CSR_WAIT_WFI_SHIFT) | CSR_ENABLE, &flow->cpu1_csr);
- writel((4 << CSR_WAIT_WFI_SHIFT) | CSR_ENABLE, &flow->cpu2_csr);
- writel((8 << CSR_WAIT_WFI_SHIFT) | CSR_ENABLE, &flow->cpu3_csr);
- writel(EVENT_MODE_STOP, &flow->halt_cpu1_events);
- writel(EVENT_MODE_STOP, &flow->halt_cpu2_events);
- writel(EVENT_MODE_STOP, &flow->halt_cpu3_events);
- while (readl(&pmc->pmc_pwrgate_status) & ((1 << TEGRA_POWERGATE_CPU1) |
(1 << TEGRA_POWERGATE_CPU2) |
(1 << TEGRA_POWERGATE_CPU3)))
/* wait */;
+}
As discussed previously I don't quite understand why the sequence:
1) program CSR registers 2) program halt events 3) power on CPUs
does not work. Testing shows that PSCI will work with that sequence once the kernel is loaded. However I can also confirm that U-Boot doesn't see the power partition status updated to "off", so I assume the partitions will indeed still be powered on if we change the sequence.
So until we find out why that's happening I think it's safe to go with the above sequence, since it does what we want. Perhaps add a comment describing the ambiguity?
Also as a cosmetic cleanup, perhaps rather than checking the PMC power gate status register you check bit 16 of each CPU's CSR register, which should mirror the corresponding power gate status bit. That way you don't need to access the PMC registers but restrict register accesses to a single IP block in this code.
Thierry