psci.c 7.0 KB

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