pm-mips.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * MIPS-specific support for Broadcom STB S2/S3/S5 power management
  4. *
  5. * Copyright (C) 2016-2017 Broadcom
  6. */
  7. #include <linux/kernel.h>
  8. #include <linux/printk.h>
  9. #include <linux/io.h>
  10. #include <linux/of.h>
  11. #include <linux/of_address.h>
  12. #include <linux/delay.h>
  13. #include <linux/suspend.h>
  14. #include <asm/bmips.h>
  15. #include <asm/tlbflush.h>
  16. #include "pm.h"
  17. #define S2_NUM_PARAMS 6
  18. #define MAX_NUM_MEMC 3
  19. /* S3 constants */
  20. #define MAX_GP_REGS 16
  21. #define MAX_CP0_REGS 32
  22. #define NUM_MEMC_CLIENTS 128
  23. #define AON_CTRL_RAM_SIZE 128
  24. #define BRCMSTB_S3_MAGIC 0x5AFEB007
  25. #define CLEAR_RESET_MASK 0x01
  26. /* Index each CP0 register that needs to be saved */
  27. #define CONTEXT 0
  28. #define USER_LOCAL 1
  29. #define PGMK 2
  30. #define HWRENA 3
  31. #define COMPARE 4
  32. #define STATUS 5
  33. #define CONFIG 6
  34. #define MODE 7
  35. #define EDSP 8
  36. #define BOOT_VEC 9
  37. #define EBASE 10
  38. struct brcmstb_memc {
  39. void __iomem *ddr_phy_base;
  40. void __iomem *arb_base;
  41. };
  42. struct brcmstb_pm_control {
  43. void __iomem *aon_ctrl_base;
  44. void __iomem *aon_sram_base;
  45. void __iomem *timers_base;
  46. struct brcmstb_memc memcs[MAX_NUM_MEMC];
  47. int num_memc;
  48. };
  49. struct brcm_pm_s3_context {
  50. u32 cp0_regs[MAX_CP0_REGS];
  51. u32 memc0_rts[NUM_MEMC_CLIENTS];
  52. u32 sc_boot_vec;
  53. };
  54. struct brcmstb_mem_transfer;
  55. struct brcmstb_mem_transfer {
  56. struct brcmstb_mem_transfer *next;
  57. void *src;
  58. void *dst;
  59. dma_addr_t pa_src;
  60. dma_addr_t pa_dst;
  61. u32 len;
  62. u8 key;
  63. u8 mode;
  64. u8 src_remapped;
  65. u8 dst_remapped;
  66. u8 src_dst_remapped;
  67. };
  68. #define AON_SAVE_SRAM(base, idx, val) \
  69. __raw_writel(val, base + (idx << 2))
  70. /* Used for saving registers in asm */
  71. u32 gp_regs[MAX_GP_REGS];
  72. #define BSP_CLOCK_STOP 0x00
  73. #define PM_INITIATE 0x01
  74. static struct brcmstb_pm_control ctrl;
  75. static void brcm_pm_save_cp0_context(struct brcm_pm_s3_context *ctx)
  76. {
  77. /* Generic MIPS */
  78. ctx->cp0_regs[CONTEXT] = read_c0_context();
  79. ctx->cp0_regs[USER_LOCAL] = read_c0_userlocal();
  80. ctx->cp0_regs[PGMK] = read_c0_pagemask();
  81. ctx->cp0_regs[HWRENA] = read_c0_cache();
  82. ctx->cp0_regs[COMPARE] = read_c0_compare();
  83. ctx->cp0_regs[STATUS] = read_c0_status();
  84. /* Broadcom specific */
  85. ctx->cp0_regs[CONFIG] = read_c0_brcm_config();
  86. ctx->cp0_regs[MODE] = read_c0_brcm_mode();
  87. ctx->cp0_regs[EDSP] = read_c0_brcm_edsp();
  88. ctx->cp0_regs[BOOT_VEC] = read_c0_brcm_bootvec();
  89. ctx->cp0_regs[EBASE] = read_c0_ebase();
  90. ctx->sc_boot_vec = bmips_read_zscm_reg(0xa0);
  91. }
  92. static void brcm_pm_restore_cp0_context(struct brcm_pm_s3_context *ctx)
  93. {
  94. /* Restore cp0 state */
  95. bmips_write_zscm_reg(0xa0, ctx->sc_boot_vec);
  96. /* Generic MIPS */
  97. write_c0_context(ctx->cp0_regs[CONTEXT]);
  98. write_c0_userlocal(ctx->cp0_regs[USER_LOCAL]);
  99. write_c0_pagemask(ctx->cp0_regs[PGMK]);
  100. write_c0_cache(ctx->cp0_regs[HWRENA]);
  101. write_c0_compare(ctx->cp0_regs[COMPARE]);
  102. write_c0_status(ctx->cp0_regs[STATUS]);
  103. /* Broadcom specific */
  104. write_c0_brcm_config(ctx->cp0_regs[CONFIG]);
  105. write_c0_brcm_mode(ctx->cp0_regs[MODE]);
  106. write_c0_brcm_edsp(ctx->cp0_regs[EDSP]);
  107. write_c0_brcm_bootvec(ctx->cp0_regs[BOOT_VEC]);
  108. write_c0_ebase(ctx->cp0_regs[EBASE]);
  109. }
  110. static void brcmstb_pm_handshake(void)
  111. {
  112. void __iomem *base = ctrl.aon_ctrl_base;
  113. u32 tmp;
  114. /* BSP power handshake, v1 */
  115. tmp = __raw_readl(base + AON_CTRL_HOST_MISC_CMDS);
  116. tmp &= ~1UL;
  117. __raw_writel(tmp, base + AON_CTRL_HOST_MISC_CMDS);
  118. (void)__raw_readl(base + AON_CTRL_HOST_MISC_CMDS);
  119. __raw_writel(0, base + AON_CTRL_PM_INITIATE);
  120. (void)__raw_readl(base + AON_CTRL_PM_INITIATE);
  121. __raw_writel(BSP_CLOCK_STOP | PM_INITIATE,
  122. base + AON_CTRL_PM_INITIATE);
  123. /*
  124. * HACK: BSP may have internal race on the CLOCK_STOP command.
  125. * Avoid touching the BSP for a few milliseconds.
  126. */
  127. mdelay(3);
  128. }
  129. static void brcmstb_pm_s5(void)
  130. {
  131. void __iomem *base = ctrl.aon_ctrl_base;
  132. brcmstb_pm_handshake();
  133. /* Clear magic s3 warm-boot value */
  134. AON_SAVE_SRAM(ctrl.aon_sram_base, 0, 0);
  135. /* Set the countdown */
  136. __raw_writel(0x10, base + AON_CTRL_PM_CPU_WAIT_COUNT);
  137. (void)__raw_readl(base + AON_CTRL_PM_CPU_WAIT_COUNT);
  138. /* Prepare to S5 cold boot */
  139. __raw_writel(PM_COLD_CONFIG, base + AON_CTRL_PM_CTRL);
  140. (void)__raw_readl(base + AON_CTRL_PM_CTRL);
  141. __raw_writel((PM_COLD_CONFIG | PM_PWR_DOWN), base +
  142. AON_CTRL_PM_CTRL);
  143. (void)__raw_readl(base + AON_CTRL_PM_CTRL);
  144. __asm__ __volatile__(
  145. " wait\n"
  146. : : : "memory");
  147. }
  148. static int brcmstb_pm_s3(void)
  149. {
  150. struct brcm_pm_s3_context s3_context;
  151. void __iomem *memc_arb_base;
  152. unsigned long flags;
  153. u32 tmp;
  154. int i;
  155. /* Prepare for s3 */
  156. AON_SAVE_SRAM(ctrl.aon_sram_base, 0, BRCMSTB_S3_MAGIC);
  157. AON_SAVE_SRAM(ctrl.aon_sram_base, 1, (u32)&s3_reentry);
  158. AON_SAVE_SRAM(ctrl.aon_sram_base, 2, 0);
  159. /* Clear RESET_HISTORY */
  160. tmp = __raw_readl(ctrl.aon_ctrl_base + AON_CTRL_RESET_CTRL);
  161. tmp &= ~CLEAR_RESET_MASK;
  162. __raw_writel(tmp, ctrl.aon_ctrl_base + AON_CTRL_RESET_CTRL);
  163. local_irq_save(flags);
  164. /* Inhibit DDR_RSTb pulse for both MMCs*/
  165. for (i = 0; i < ctrl.num_memc; i++) {
  166. tmp = __raw_readl(ctrl.memcs[i].ddr_phy_base +
  167. DDR40_PHY_CONTROL_REGS_0_STANDBY_CTRL);
  168. tmp &= ~0x0f;
  169. __raw_writel(tmp, ctrl.memcs[i].ddr_phy_base +
  170. DDR40_PHY_CONTROL_REGS_0_STANDBY_CTRL);
  171. tmp |= (0x05 | BIT(5));
  172. __raw_writel(tmp, ctrl.memcs[i].ddr_phy_base +
  173. DDR40_PHY_CONTROL_REGS_0_STANDBY_CTRL);
  174. }
  175. /* Save CP0 context */
  176. brcm_pm_save_cp0_context(&s3_context);
  177. /* Save RTS(skip debug register) */
  178. memc_arb_base = ctrl.memcs[0].arb_base + 4;
  179. for (i = 0; i < NUM_MEMC_CLIENTS; i++) {
  180. s3_context.memc0_rts[i] = __raw_readl(memc_arb_base);
  181. memc_arb_base += 4;
  182. }
  183. /* Save I/O context */
  184. local_flush_tlb_all();
  185. _dma_cache_wback_inv(0, ~0);
  186. brcm_pm_do_s3(ctrl.aon_ctrl_base, current_cpu_data.dcache.linesz);
  187. /* CPU reconfiguration */
  188. local_flush_tlb_all();
  189. bmips_cpu_setup();
  190. cpumask_clear(&bmips_booted_mask);
  191. /* Restore RTS (skip debug register) */
  192. memc_arb_base = ctrl.memcs[0].arb_base + 4;
  193. for (i = 0; i < NUM_MEMC_CLIENTS; i++) {
  194. __raw_writel(s3_context.memc0_rts[i], memc_arb_base);
  195. memc_arb_base += 4;
  196. }
  197. /* restore CP0 context */
  198. brcm_pm_restore_cp0_context(&s3_context);
  199. local_irq_restore(flags);
  200. return 0;
  201. }
  202. static int brcmstb_pm_s2(void)
  203. {
  204. /*
  205. * We need to pass 6 arguments to an assembly function. Lets avoid the
  206. * stack and pass arguments in a explicit 4 byte array. The assembly
  207. * code assumes all arguments are 4 bytes and arguments are ordered
  208. * like so:
  209. *
  210. * 0: AON_CTRl base register
  211. * 1: DDR_PHY base register
  212. * 2: TIMERS base resgister
  213. * 3: I-Cache line size
  214. * 4: Restart vector address
  215. * 5: Restart vector size
  216. */
  217. u32 s2_params[6];
  218. /* Prepare s2 parameters */
  219. s2_params[0] = (u32)ctrl.aon_ctrl_base;
  220. s2_params[1] = (u32)ctrl.memcs[0].ddr_phy_base;
  221. s2_params[2] = (u32)ctrl.timers_base;
  222. s2_params[3] = (u32)current_cpu_data.icache.linesz;
  223. s2_params[4] = (u32)BMIPS_WARM_RESTART_VEC;
  224. s2_params[5] = (u32)(bmips_smp_int_vec_end -
  225. bmips_smp_int_vec);
  226. /* Drop to standby */
  227. brcm_pm_do_s2(s2_params);
  228. return 0;
  229. }
  230. static int brcmstb_pm_standby(bool deep_standby)
  231. {
  232. brcmstb_pm_handshake();
  233. /* Send IRQs to BMIPS_WARM_RESTART_VEC */
  234. clear_c0_cause(CAUSEF_IV);
  235. irq_disable_hazard();
  236. set_c0_status(ST0_BEV);
  237. irq_disable_hazard();
  238. if (deep_standby)
  239. brcmstb_pm_s3();
  240. else
  241. brcmstb_pm_s2();
  242. /* Send IRQs to normal runtime vectors */
  243. clear_c0_status(ST0_BEV);
  244. irq_disable_hazard();
  245. set_c0_cause(CAUSEF_IV);
  246. irq_disable_hazard();
  247. return 0;
  248. }
  249. static int brcmstb_pm_enter(suspend_state_t state)
  250. {
  251. int ret = -EINVAL;
  252. switch (state) {
  253. case PM_SUSPEND_STANDBY:
  254. ret = brcmstb_pm_standby(false);
  255. break;
  256. case PM_SUSPEND_MEM:
  257. ret = brcmstb_pm_standby(true);
  258. break;
  259. }
  260. return ret;
  261. }
  262. static int brcmstb_pm_valid(suspend_state_t state)
  263. {
  264. switch (state) {
  265. case PM_SUSPEND_STANDBY:
  266. return true;
  267. case PM_SUSPEND_MEM:
  268. return true;
  269. default:
  270. return false;
  271. }
  272. }
  273. static const struct platform_suspend_ops brcmstb_pm_ops = {
  274. .enter = brcmstb_pm_enter,
  275. .valid = brcmstb_pm_valid,
  276. };
  277. static const struct of_device_id aon_ctrl_dt_ids[] = {
  278. { .compatible = "brcm,brcmstb-aon-ctrl" },
  279. { /* sentinel */ }
  280. };
  281. static const struct of_device_id ddr_phy_dt_ids[] = {
  282. { .compatible = "brcm,brcmstb-ddr-phy" },
  283. { /* sentinel */ }
  284. };
  285. static const struct of_device_id arb_dt_ids[] = {
  286. { .compatible = "brcm,brcmstb-memc-arb" },
  287. { /* sentinel */ }
  288. };
  289. static const struct of_device_id timers_ids[] = {
  290. { .compatible = "brcm,brcmstb-timers" },
  291. { /* sentinel */ }
  292. };
  293. static inline void __iomem *brcmstb_ioremap_node(struct device_node *dn,
  294. int index)
  295. {
  296. return of_io_request_and_map(dn, index, dn->full_name);
  297. }
  298. static void __iomem *brcmstb_ioremap_match(const struct of_device_id *matches,
  299. int index, const void **ofdata)
  300. {
  301. struct device_node *dn;
  302. const struct of_device_id *match;
  303. dn = of_find_matching_node_and_match(NULL, matches, &match);
  304. if (!dn)
  305. return ERR_PTR(-EINVAL);
  306. if (ofdata)
  307. *ofdata = match->data;
  308. return brcmstb_ioremap_node(dn, index);
  309. }
  310. static int brcmstb_pm_init(void)
  311. {
  312. struct device_node *dn;
  313. void __iomem *base;
  314. int i;
  315. /* AON ctrl registers */
  316. base = brcmstb_ioremap_match(aon_ctrl_dt_ids, 0, NULL);
  317. if (IS_ERR(base)) {
  318. pr_err("error mapping AON_CTRL\n");
  319. goto aon_err;
  320. }
  321. ctrl.aon_ctrl_base = base;
  322. /* AON SRAM registers */
  323. base = brcmstb_ioremap_match(aon_ctrl_dt_ids, 1, NULL);
  324. if (IS_ERR(base)) {
  325. pr_err("error mapping AON_SRAM\n");
  326. goto sram_err;
  327. }
  328. ctrl.aon_sram_base = base;
  329. ctrl.num_memc = 0;
  330. /* Map MEMC DDR PHY registers */
  331. for_each_matching_node(dn, ddr_phy_dt_ids) {
  332. i = ctrl.num_memc;
  333. if (i >= MAX_NUM_MEMC) {
  334. pr_warn("Too many MEMCs (max %d)\n", MAX_NUM_MEMC);
  335. break;
  336. }
  337. base = brcmstb_ioremap_node(dn, 0);
  338. if (IS_ERR(base))
  339. goto ddr_err;
  340. ctrl.memcs[i].ddr_phy_base = base;
  341. ctrl.num_memc++;
  342. }
  343. /* MEMC ARB registers */
  344. base = brcmstb_ioremap_match(arb_dt_ids, 0, NULL);
  345. if (IS_ERR(base)) {
  346. pr_err("error mapping MEMC ARB\n");
  347. goto ddr_err;
  348. }
  349. ctrl.memcs[0].arb_base = base;
  350. /* Timer registers */
  351. base = brcmstb_ioremap_match(timers_ids, 0, NULL);
  352. if (IS_ERR(base)) {
  353. pr_err("error mapping timers\n");
  354. goto tmr_err;
  355. }
  356. ctrl.timers_base = base;
  357. /* s3 cold boot aka s5 */
  358. pm_power_off = brcmstb_pm_s5;
  359. suspend_set_ops(&brcmstb_pm_ops);
  360. return 0;
  361. tmr_err:
  362. iounmap(ctrl.memcs[0].arb_base);
  363. ddr_err:
  364. for (i = 0; i < ctrl.num_memc; i++)
  365. iounmap(ctrl.memcs[i].ddr_phy_base);
  366. iounmap(ctrl.aon_sram_base);
  367. sram_err:
  368. iounmap(ctrl.aon_ctrl_base);
  369. aon_err:
  370. return PTR_ERR(base);
  371. }
  372. arch_initcall(brcmstb_pm_init);