psci.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /*
  2. * Copyright (C) 2016
  3. * Author: Chen-Yu Tsai <wens@csie.org>
  4. *
  5. * Based on assembly code by Marc Zyngier <marc.zyngier@arm.com>,
  6. * which was based on code by Carl van Schaik <carl@ok-labs.com>.
  7. *
  8. * SPDX-License-Identifier: GPL-2.0
  9. */
  10. #include <config.h>
  11. #include <common.h>
  12. #include <asm/arch/cpu.h>
  13. #include <asm/arch/cpucfg.h>
  14. #include <asm/arch/prcm.h>
  15. #include <asm/armv7.h>
  16. #include <asm/gic.h>
  17. #include <asm/io.h>
  18. #include <asm/psci.h>
  19. #include <asm/secure.h>
  20. #include <asm/system.h>
  21. #include <linux/bitops.h>
  22. #define __irq __attribute__ ((interrupt ("IRQ")))
  23. #define GICD_BASE (SUNXI_GIC400_BASE + GIC_DIST_OFFSET)
  24. #define GICC_BASE (SUNXI_GIC400_BASE + GIC_CPU_OFFSET_A15)
  25. static void __secure cp15_write_cntp_tval(u32 tval)
  26. {
  27. asm volatile ("mcr p15, 0, %0, c14, c2, 0" : : "r" (tval));
  28. }
  29. static void __secure cp15_write_cntp_ctl(u32 val)
  30. {
  31. asm volatile ("mcr p15, 0, %0, c14, c2, 1" : : "r" (val));
  32. }
  33. static u32 __secure cp15_read_cntp_ctl(void)
  34. {
  35. u32 val;
  36. asm volatile ("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
  37. return val;
  38. }
  39. #define ONE_MS (CONFIG_TIMER_CLK_FREQ / 1000)
  40. static void __secure __mdelay(u32 ms)
  41. {
  42. u32 reg = ONE_MS * ms;
  43. cp15_write_cntp_tval(reg);
  44. ISB;
  45. cp15_write_cntp_ctl(3);
  46. do {
  47. ISB;
  48. reg = cp15_read_cntp_ctl();
  49. } while (!(reg & BIT(2)));
  50. cp15_write_cntp_ctl(0);
  51. ISB;
  52. }
  53. static void __secure clamp_release(u32 __maybe_unused *clamp)
  54. {
  55. #if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \
  56. defined(CONFIG_MACH_SUN8I_H3)
  57. u32 tmp = 0x1ff;
  58. do {
  59. tmp >>= 1;
  60. writel(tmp, clamp);
  61. } while (tmp);
  62. __mdelay(10);
  63. #endif
  64. }
  65. static void __secure clamp_set(u32 __maybe_unused *clamp)
  66. {
  67. #if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \
  68. defined(CONFIG_MACH_SUN8I_H3)
  69. writel(0xff, clamp);
  70. #endif
  71. }
  72. static void __secure sunxi_power_switch(u32 *clamp, u32 *pwroff, bool on,
  73. int cpu)
  74. {
  75. if (on) {
  76. /* Release power clamp */
  77. clamp_release(clamp);
  78. /* Clear power gating */
  79. clrbits_le32(pwroff, BIT(cpu));
  80. } else {
  81. /* Set power gating */
  82. setbits_le32(pwroff, BIT(cpu));
  83. /* Activate power clamp */
  84. clamp_set(clamp);
  85. }
  86. }
  87. #ifdef CONFIG_MACH_SUN7I
  88. /* sun7i (A20) is different from other single cluster SoCs */
  89. static void __secure sunxi_cpu_set_power(int __always_unused cpu, bool on)
  90. {
  91. struct sunxi_cpucfg_reg *cpucfg =
  92. (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
  93. sunxi_power_switch(&cpucfg->cpu1_pwr_clamp, &cpucfg->cpu1_pwroff,
  94. on, 0);
  95. }
  96. #else /* ! CONFIG_MACH_SUN7I */
  97. static void __secure sunxi_cpu_set_power(int cpu, bool on)
  98. {
  99. struct sunxi_prcm_reg *prcm =
  100. (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
  101. sunxi_power_switch(&prcm->cpu_pwr_clamp[cpu], &prcm->cpu_pwroff,
  102. on, cpu);
  103. }
  104. #endif /* CONFIG_MACH_SUN7I */
  105. void __secure sunxi_cpu_power_off(u32 cpuid)
  106. {
  107. struct sunxi_cpucfg_reg *cpucfg =
  108. (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
  109. u32 cpu = cpuid & 0x3;
  110. /* Wait for the core to enter WFI */
  111. while (1) {
  112. if (readl(&cpucfg->cpu[cpu].status) & BIT(2))
  113. break;
  114. __mdelay(1);
  115. }
  116. /* Assert reset on target CPU */
  117. writel(0, &cpucfg->cpu[cpu].rst);
  118. /* Lock CPU (Disable external debug access) */
  119. clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
  120. /* Power down CPU */
  121. sunxi_cpu_set_power(cpuid, false);
  122. /* Unlock CPU (Disable external debug access) */
  123. setbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
  124. }
  125. static u32 __secure cp15_read_scr(void)
  126. {
  127. u32 scr;
  128. asm volatile ("mrc p15, 0, %0, c1, c1, 0" : "=r" (scr));
  129. return scr;
  130. }
  131. static void __secure cp15_write_scr(u32 scr)
  132. {
  133. asm volatile ("mcr p15, 0, %0, c1, c1, 0" : : "r" (scr));
  134. ISB;
  135. }
  136. /*
  137. * Although this is an FIQ handler, the FIQ is processed in monitor mode,
  138. * which means there's no FIQ banked registers. This is the same as IRQ
  139. * mode, so use the IRQ attribute to ask the compiler to handler entry
  140. * and return.
  141. */
  142. void __secure __irq psci_fiq_enter(void)
  143. {
  144. u32 scr, reg, cpu;
  145. /* Switch to secure mode */
  146. scr = cp15_read_scr();
  147. cp15_write_scr(scr & ~BIT(0));
  148. /* Validate reason based on IAR and acknowledge */
  149. reg = readl(GICC_BASE + GICC_IAR);
  150. /* Skip spurious interrupts 1022 and 1023 */
  151. if (reg == 1023 || reg == 1022)
  152. goto out;
  153. /* End of interrupt */
  154. writel(reg, GICC_BASE + GICC_EOIR);
  155. DSB;
  156. /* Get CPU number */
  157. cpu = (reg >> 10) & 0x7;
  158. /* Power off the CPU */
  159. sunxi_cpu_power_off(cpu);
  160. out:
  161. /* Restore security level */
  162. cp15_write_scr(scr);
  163. }
  164. int __secure psci_cpu_on(u32 __always_unused unused, u32 mpidr, u32 pc)
  165. {
  166. struct sunxi_cpucfg_reg *cpucfg =
  167. (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
  168. u32 cpu = (mpidr & 0x3);
  169. /* store target PC */
  170. psci_save_target_pc(cpu, pc);
  171. /* Set secondary core power on PC */
  172. writel((u32)&psci_cpu_entry, &cpucfg->priv0);
  173. /* Assert reset on target CPU */
  174. writel(0, &cpucfg->cpu[cpu].rst);
  175. /* Invalidate L1 cache */
  176. clrbits_le32(&cpucfg->gen_ctrl, BIT(cpu));
  177. /* Lock CPU (Disable external debug access) */
  178. clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
  179. /* Power up target CPU */
  180. sunxi_cpu_set_power(cpu, true);
  181. /* De-assert reset on target CPU */
  182. writel(BIT(1) | BIT(0), &cpucfg->cpu[cpu].rst);
  183. /* Unlock CPU (Disable external debug access) */
  184. setbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
  185. return ARM_PSCI_RET_SUCCESS;
  186. }
  187. void __secure psci_cpu_off(void)
  188. {
  189. psci_cpu_off_common();
  190. /* Ask CPU0 via SGI15 to pull the rug... */
  191. writel(BIT(16) | 15, GICD_BASE + GICD_SGIR);
  192. DSB;
  193. /* Wait to be turned off */
  194. while (1)
  195. wfi();
  196. }
  197. void __secure psci_arch_init(void)
  198. {
  199. u32 reg;
  200. /* SGI15 as Group-0 */
  201. clrbits_le32(GICD_BASE + GICD_IGROUPRn, BIT(15));
  202. /* Set SGI15 priority to 0 */
  203. writeb(0, GICD_BASE + GICD_IPRIORITYRn + 15);
  204. /* Be cool with non-secure */
  205. writel(0xff, GICC_BASE + GICC_PMR);
  206. /* Switch FIQEn on */
  207. setbits_le32(GICC_BASE + GICC_CTLR, BIT(3));
  208. reg = cp15_read_scr();
  209. reg |= BIT(2); /* Enable FIQ in monitor mode */
  210. reg &= ~BIT(0); /* Secure mode */
  211. cp15_write_scr(reg);
  212. }