psci.c 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2015, Siemens AG
  4. * Author: Jan Kiszka <jan.kiszka@siemens.com>
  5. */
  6. #include <common.h>
  7. #include <asm/io.h>
  8. #include <asm/psci.h>
  9. #include <asm/arch/flow.h>
  10. #include <asm/arch/powergate.h>
  11. #include <asm/arch-tegra/ap.h>
  12. #include <asm/arch-tegra/pmc.h>
  13. static void park_cpu(void)
  14. {
  15. while (1)
  16. asm volatile("wfi");
  17. }
  18. /**
  19. * Initialize power management for application processors
  20. */
  21. void psci_board_init(void)
  22. {
  23. struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE;
  24. writel((u32)park_cpu, EXCEP_VECTOR_CPU_RESET_VECTOR);
  25. /*
  26. * The naturally expected order of putting these CPUs under Flow
  27. * Controller regime would be
  28. * - configure the Flow Controller
  29. * - power up the CPUs
  30. * - wait for the CPUs to hit wfi and be powered down again
  31. *
  32. * However, this doesn't work in practice. We rather need to power them
  33. * up first and park them in wfi. While they are waiting there, we can
  34. * indeed program the Flow Controller to powergate them on wfi, which
  35. * will then happen immediately as they are already in that state.
  36. */
  37. tegra_powergate_power_on(TEGRA_POWERGATE_CPU1);
  38. tegra_powergate_power_on(TEGRA_POWERGATE_CPU2);
  39. tegra_powergate_power_on(TEGRA_POWERGATE_CPU3);
  40. writel((2 << CSR_WAIT_WFI_SHIFT) | CSR_ENABLE, &flow->cpu1_csr);
  41. writel((4 << CSR_WAIT_WFI_SHIFT) | CSR_ENABLE, &flow->cpu2_csr);
  42. writel((8 << CSR_WAIT_WFI_SHIFT) | CSR_ENABLE, &flow->cpu3_csr);
  43. writel(EVENT_MODE_STOP, &flow->halt_cpu1_events);
  44. writel(EVENT_MODE_STOP, &flow->halt_cpu2_events);
  45. writel(EVENT_MODE_STOP, &flow->halt_cpu3_events);
  46. while (!(readl(&flow->cpu1_csr) & CSR_PWR_OFF_STS) ||
  47. !(readl(&flow->cpu2_csr) & CSR_PWR_OFF_STS) ||
  48. !(readl(&flow->cpu3_csr) & CSR_PWR_OFF_STS))
  49. /* wait */;
  50. }