pm-mips.c 11 KB

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