soc_sleep_ep.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. /*
  2. * Copyright (c) 2019 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file soc_sleep.c sleep for Actions SoC
  8. */
  9. #include <zephyr.h>
  10. #include <soc.h>
  11. #include <arch/arm/aarch32/cortex_m/cmsis.h>
  12. #include <string.h>
  13. #include <drivers/timer/system_timer.h>
  14. #include <linker/linker-defs.h>
  15. #define MEM_S2_ITEM_MAX 10
  16. struct mem_backup {
  17. void *buf;
  18. uint32_t len;
  19. };
  20. /* COREPLL RW fields range from 0 t0 7 */
  21. //static uint32_t ram_power_backup;
  22. /* Save and restore the registers */
  23. static const uint32_t backup_regs_addr[] = {
  24. CMU_SYSCLK,
  25. CMU_SPI0CLK,
  26. SPI1_CACHE_CTL,
  27. ADC_REF_LDO_CTL,
  28. AVDDLDO_CTL,
  29. PMUADC_CTL,
  30. WIO0_CTL,
  31. WIO1_CTL,
  32. CMU_MEMCLKEN0,
  33. CMU_MEMCLKEN1,
  34. CMU_DEVCLKEN1,
  35. CMU_DEVCLKEN0,
  36. RMU_MRCR1,
  37. RMU_MRCR0,
  38. NVIC_ISER0,
  39. NVIC_ISER1,
  40. };
  41. static void suspend_check(void)
  42. {
  43. }
  44. static void wakeup_check(void)
  45. {
  46. }
  47. struct sleep_wk_data {
  48. uint16_t wksrc;
  49. uint16_t wk_en_bit;
  50. const char *wksrc_msg;
  51. };
  52. struct sleep_wk_data wk_msg[] = {
  53. {SLEEP_WK_SRC_BT, IRQ_ID_BT, "BT" },
  54. {SLEEP_WK_SRC_GPIO, IRQ_ID_GPIO, "GPIO" },
  55. {SLEEP_WK_SRC_PMU, IRQ_ID_PMU, "PMU" },
  56. {SLEEP_WK_SRC_T0, IRQ_ID_TIMER0, "T0" },
  57. {SLEEP_WK_SRC_T1, IRQ_ID_TIMER1, "T1" },
  58. {SLEEP_WK_SRC_TWS, IRQ_ID_TWS, "TWS"},
  59. };
  60. #define SLEEP_WKSRC_NUM ARRAY_SIZE(wk_msg)
  61. static volatile uint16_t g_sleep_wksrc_en, g_sleep_wksrc_src;
  62. void sys_s3_wksrc_set(enum S_WK_SRC_TYPE src)
  63. {
  64. g_sleep_wksrc_en |= (1 << src);
  65. }
  66. enum S_WK_SRC_TYPE sys_s3_wksrc_get(void)
  67. {
  68. return g_sleep_wksrc_src;
  69. }
  70. static enum S_WK_SRC_TYPE sys_sleep_check_wksrc(void)
  71. {
  72. int i;
  73. uint32_t wk_pd0, wk_pd1,wkbit;
  74. g_sleep_wksrc_src = 0;
  75. wk_pd0 = sys_read32(NVIC_ISPR0);
  76. wk_pd1 = sys_read32(NVIC_ISPR1);
  77. //printk("WK NVIC_ISPR0=0x%x\n", wk_pd0);
  78. //printk("WK NVIC_ISPR1=0x%x\n", wk_pd1);
  79. for(i = 0; i < SLEEP_WKSRC_NUM; i++){
  80. if((1<<wk_msg[i].wksrc) & g_sleep_wksrc_en){
  81. wkbit = wk_msg[i].wk_en_bit;
  82. if(wkbit >= 32){
  83. wkbit -= 32;
  84. if(wk_pd1 & (1<<wkbit))
  85. break;
  86. }else{
  87. if(wk_pd0 & (1<<wkbit))
  88. break;
  89. }
  90. }
  91. }
  92. if(i != SLEEP_WKSRC_NUM){
  93. g_sleep_wksrc_src = wk_msg[i].wksrc;
  94. printk("wksrc=%s\n", wk_msg[i].wksrc_msg);
  95. }else{
  96. printk("no wksrc\n");
  97. g_sleep_wksrc_src = 0;
  98. }
  99. return g_sleep_wksrc_src;
  100. }
  101. static void sys_set_wksrc_before_sleep(void)
  102. {
  103. int i;
  104. uint32_t wk_en0, wk_en1;
  105. //printk("NVIC_ISPR0-1=0x%x,0x%x\n", sys_read32(NVIC_ISPR0), sys_read32(NVIC_ISPR1));
  106. //printk("NVIC_ISER0-1=0x%x,0x%x\n", sys_read32(NVIC_ISER0), sys_read32(NVIC_ISER1));
  107. //printk("NVIC_IABR0-1=0x%x,0x%x\n", sys_read32(NVIC_IABR0), sys_read32(NVIC_IABR1));
  108. //printk("g_sleep_wksrc_en =0x%x\n", g_sleep_wksrc_en);
  109. sys_write32(sys_read32(NVIC_ISER0), NVIC_ICER0);
  110. sys_write32(sys_read32(NVIC_ISER1), NVIC_ICER1);
  111. sys_write32(0xffffffff, NVIC_ICPR0);
  112. sys_write32(0xffffffff, NVIC_ICPR1);
  113. if(g_sleep_wksrc_en){
  114. wk_en0 = wk_en1 = 0;
  115. for(i = 0; i < SLEEP_WKSRC_NUM; i++){
  116. if((1 << wk_msg[i].wksrc) & g_sleep_wksrc_en){
  117. printk("%d wksrc=%s \n",i, wk_msg[i].wksrc_msg);
  118. if(wk_msg[i].wk_en_bit >= 32){
  119. wk_en1 |= 1 << (wk_msg[i].wk_en_bit-32);
  120. }else{
  121. wk_en0 |= 1 << (wk_msg[i].wk_en_bit);
  122. }
  123. }
  124. }
  125. if(wk_en0)
  126. sys_write32(wk_en0, NVIC_ISER0);
  127. if(wk_en1)
  128. sys_write32(wk_en1, NVIC_ISER1);
  129. }
  130. //printk("NVIC_ISPR0-1=0x%x,0x%x\n", sys_read32(NVIC_ISPR0), sys_read32(NVIC_ISPR1));
  131. //printk("NVIC_ISER0-1=0x%x,0x%x\n", sys_read32(NVIC_ISER0), sys_read32(NVIC_ISER1));
  132. //printk("NVIC_IABR0-1=0x%x,0x%x\n", sys_read32(NVIC_IABR0), sys_read32(NVIC_IABR1));
  133. }
  134. static uint32_t s2_reg_backups[ARRAY_SIZE(backup_regs_addr)];
  135. static void sys_pm_backup_registers(void)
  136. {
  137. int i;
  138. //ram_power_backup = sys_read32(PWRGATE_RAM);
  139. for (i = 0; i < ARRAY_SIZE(backup_regs_addr); i++)
  140. s2_reg_backups[i] = sys_read32(backup_regs_addr[i]);
  141. }
  142. static void sys_pm_restore_registers(void)
  143. {
  144. int i;
  145. for (i = ARRAY_SIZE(backup_regs_addr) - 1; i >= 0; i--)
  146. sys_write32(s2_reg_backups[i], backup_regs_addr[i]);
  147. }
  148. static struct mem_backup s2_mem_save[MEM_S2_ITEM_MAX];
  149. static uint8_t save_num_item;
  150. static uint32_t save_mem_len;
  151. static void sys_sleep_retention_mem(void)
  152. {
  153. struct mem_backup *bk;
  154. unsigned int i, len = 0;;
  155. char *sbuf = (char *)_image_ram_end;
  156. for(i = 0; i < save_num_item; i++) {
  157. bk = &s2_mem_save[i];
  158. if((bk->buf == NULL) || (bk->len == 0))
  159. continue;
  160. len += bk->len;
  161. memcpy(sbuf, bk->buf, bk->len);
  162. sbuf += bk->len;
  163. }
  164. save_mem_len = len;
  165. printk("retention mem len=%d, num=%d\n", len, save_num_item);
  166. }
  167. static void sys_wakeup_recover_mem(void)
  168. {
  169. struct mem_backup *bk;
  170. unsigned int i, len = 0;;
  171. char *sbuf = (char *)_image_ram_end;
  172. for(i = 0; i < save_num_item; i++) {
  173. bk = &s2_mem_save[i];
  174. if((bk->buf == NULL) || (bk->len == 0))
  175. continue;
  176. len += bk->len;
  177. memcpy(bk->buf, sbuf, bk->len);
  178. sbuf += bk->len;
  179. bk->buf = NULL;
  180. bk->len = 0;
  181. }
  182. printk("wakeup mem len=%d, num=%d\n", len, save_num_item);
  183. save_num_item = 0;
  184. }
  185. void dump_reg(const char *promt)
  186. {
  187. printk("%s: reg dump\n", promt);
  188. #if 0
  189. printk("RMU_MRCR0=0x%x\n", sys_read32(RMU_MRCR0));
  190. printk("RMU_MRCR1=0x%x\n", sys_read32(RMU_MRCR1));
  191. printk("CMU_DEVCLKEN0=0x%x\n", sys_read32(CMU_DEVCLKEN0));
  192. printk("CMU_DEVCLKEN1=0x%x\n", sys_read32(CMU_DEVCLKEN1));
  193. printk("PMU_DET=0x%x\n", sys_read32(PMU_DET));
  194. printk("CMU_S1CLKCTL=0x%x\n", sys_read32(CMU_S1CLKCTL));
  195. printk("CMU_S1BTCLKCTL=0x%x\n", sys_read32(CMU_S1BTCLKCTL));
  196. printk("CMU_S2HCLKCTL=0x%x\n", sys_read32(CMU_S2HCLKCTL));
  197. printk("CMU_S2SCLKCTL=0x%x\n", sys_read32(CMU_S2SCLKCTL));
  198. printk("CMU_S3CLKCTL=0x%x\n", sys_read32(CMU_S3CLKCTL));
  199. printk("CMU_PMUWKUPCLKCTL=0x%x\n", sys_read32(CMU_PMUWKUPCLKCTL));
  200. printk("HOSCOK_CTL=0x%x\n", sys_read32(HOSCOK_CTL));
  201. printk("RC4M_CTL=0x%x\n", sys_read32(RC4M_CTL));
  202. printk("WIO0_CTL=0x%x\n", sys_read32(WIO0_CTL));
  203. printk("PMUINTMASK=0x%x\n", sys_read32(PMU_INTMASK));
  204. printk("WKEN_CTL_SVCC=0x%x\n", sys_read32(WKEN_CTL_SVCC));
  205. #endif
  206. printk("PWRGATE_DIG=0x%x\n", sys_read32(PWRGATE_DIG));
  207. printk("CMU_MEMCLKSRC0=0x%x\n", sys_read32(CMU_MEMCLKSRC0));
  208. printk("CMU_MEMCLKSRC1=0x%x\n", sys_read32(CMU_MEMCLKSRC1));
  209. printk("CMU_MEMCLKEN0=0x%x\n", sys_read32(CMU_MEMCLKEN0));
  210. printk("CMU_MEMCLKEN1=0x%x\n", sys_read32(CMU_MEMCLKEN1));
  211. }
  212. static uint32_t pwgate_dis_bak;
  213. void powergate_prepare_sleep(int isdeep)
  214. {
  215. uint32_t sram_end, use, num, reg_val, i,reg_clk;
  216. printk("PWRGATE_DIG_ACK=0x%x\n", sys_read32(PWRGATE_DIG_ACK));
  217. #if 0
  218. pwgate_dis_bak = sys_read32(PWRGATE_DIG);
  219. if(isdeep)
  220. reg_val = (pwgate_dis_bak & 0xfffff) | 0xb0700000;//m4f & bt on & spicache & io & aduio power on
  221. else
  222. reg_val = (pwgate_dis_bak &0xfffff) | 0xa8700000; // bt off
  223. sys_write32(reg_val, PWRGATE_DIG);
  224. #endif
  225. }
  226. void powergate_prepare_wakeup(void)
  227. {
  228. #if 0
  229. int i;
  230. uint32_t reg_val;
  231. reg_val = sys_read32(PWRGATE_RAM);
  232. for(i = 0; i < 17; i++) {
  233. if(pwgate_ram_bak & (1<<i)) {
  234. if(!(reg_val & (1<<i))) {
  235. sys_set_bit(PWRGATE_RAM, i);
  236. udelay_loop(2);
  237. }
  238. }
  239. }
  240. sys_write32(pwgate_dis_bak, PWRGATE_DIG);
  241. #endif
  242. sys_write32((sys_read32(CMU_MEMCLKSRC0)&~(0x7<<5))|(0x1<<5) , CMU_MEMCLKSRC0);// share ram clk switch to hosc
  243. }
  244. static void soc_cmu_sleep_prepare(int isdeep)
  245. {
  246. sys_sleep_retention_mem();
  247. sys_pm_backup_registers();
  248. powergate_prepare_sleep(isdeep);
  249. SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk ; // deepsleep
  250. /*spi0 clk switch to hosc*/
  251. sys_write32(0x0, CMU_SPI0CLK);
  252. sys_write32(sys_read32(CMU_MEMCLKSRC0)&~(0x7<<5) , CMU_MEMCLKSRC0);// share ram clk switch to RC4M
  253. sys_set_wksrc_before_sleep();
  254. }
  255. #if defined(CONFIG_BOARD_NANDBOOT) || !defined(CONFIG_SPI_FLASH_ACTS)
  256. void sys_norflash_power_ctrl(uint32_t is_powerdown)
  257. {
  258. }
  259. #else
  260. extern void sys_norflash_power_ctrl(uint32_t is_powerdown);
  261. #endif
  262. #ifdef CONFIG_DISABLE_IRQ_STAT
  263. static inline unsigned int n_irq_lock(void)
  264. {
  265. unsigned int key;
  266. unsigned int tmp;
  267. __asm__ volatile(
  268. "mov %1, %2;"
  269. "mrs %0, BASEPRI;"
  270. "msr BASEPRI, %1;"
  271. "isb;"
  272. : "=r"(key), "=r"(tmp)
  273. : "i"(_EXC_IRQ_DEFAULT_PRIO)
  274. : "memory");
  275. return key;
  276. }
  277. static inline void n_irq_unlock(unsigned int key)
  278. {
  279. __asm__ volatile(
  280. "msr BASEPRI, %0;"
  281. "isb;"
  282. : : "r"(key) : "memory");
  283. }
  284. #endif
  285. __ramfunc static void cpu_enter_sleep(void)
  286. {
  287. #if 1
  288. volatile int loop;
  289. uint32_t corepll_backup;
  290. //jtag_enable();
  291. //sys_norflash_power_ctrl(1);/*nor enter deep power down */
  292. /* switch cpu to rc4m */
  293. sys_write32(0x3, CMU_S1CLKCTL); // rc4m+hosc
  294. corepll_backup = sys_read32(COREPLL_CTL);
  295. sys_write32(0x0, CMU_SYSCLK); /*cpu clk select rc4M*/
  296. sys_write32(sys_read32(COREPLL_CTL) & ~(1 << 7), COREPLL_CTL);
  297. sys_write32(0, COREPLL_CTL);
  298. /*spi0 & spi1 cache disable*/
  299. sys_clear_bit(SPICACHE_CTL, 0); //bit0 disable spi 0 cache
  300. sys_clear_bit(AVDDLDO_CTL, 0); /*disable avdd, corepll use must enable*/
  301. loop=100;
  302. while(loop)loop--;
  303. /*enter sleep*/
  304. __asm__ volatile("cpsid i");
  305. #ifdef CONFIG_DISABLE_IRQ_STAT
  306. n_irq_unlock(0);
  307. #else
  308. irq_unlock(0);
  309. #endif
  310. __asm__ volatile("dsb");
  311. __asm__ volatile("wfi");
  312. #ifdef CONFIG_DISABLE_IRQ_STAT
  313. n_irq_lock();
  314. #else
  315. irq_lock();
  316. #endif
  317. __asm__ volatile("cpsie i");
  318. sys_set_bit(AVDDLDO_CTL, 0); /*enable avdd, for pll*/
  319. loop=300;
  320. while(loop)loop--; /*for avdd*/
  321. /*spi0 & spi1 cache enable*/
  322. sys_set_bit(SPICACHE_CTL, 0); //enable spi 0 cache
  323. sys_write32(corepll_backup, COREPLL_CTL);
  324. sys_write32(0x0, CMU_SPI0CLK);// hosc
  325. loop=200;
  326. while(loop--); /*for avdd*/
  327. //sys_norflash_power_ctrl(0);//;//nor exit deep power down
  328. #else
  329. k_busy_wait(2000000); //wati 2s
  330. #endif
  331. }
  332. static void soc_cmu_sleep_exit(void)
  333. {
  334. SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk ;
  335. powergate_prepare_wakeup();
  336. sys_pm_restore_registers();
  337. sys_wakeup_recover_mem();
  338. }
  339. static int check_exit_deep_sleep(void)
  340. {
  341. uint32_t wksrc;
  342. wksrc = sys_sleep_check_wksrc();
  343. return 1;
  344. }
  345. void soc_enter_deep_sleep(void)
  346. {
  347. z_clock_set_timeout(CONFIG_SYS_CLOCK_TICKS_PER_SEC*5, false);
  348. sys_s3_wksrc_set(SLEEP_WK_SRC_BT);
  349. sys_s3_wksrc_set(SLEEP_WK_SRC_T1);
  350. sys_s3_wksrc_set(SLEEP_WK_SRC_TWS);
  351. sys_s3_wksrc_set(SLEEP_WK_SRC_PMU);
  352. suspend_check();
  353. do{
  354. dump_reg("before");
  355. soc_cmu_sleep_prepare(1);
  356. dump_reg("middle");
  357. cpu_enter_sleep();//wfi,enter to sleep
  358. soc_cmu_sleep_exit();
  359. dump_reg("BT after");
  360. check_exit_deep_sleep();
  361. }while(0);
  362. wakeup_check();
  363. }
  364. void soc_enter_light_sleep(void)
  365. {
  366. z_clock_set_timeout(CONFIG_SYS_CLOCK_TICKS_PER_SEC*5, false);
  367. dump_reg("before");
  368. soc_cmu_sleep_prepare(0);
  369. cpu_enter_sleep();//wfi,enter to sleep
  370. soc_cmu_sleep_exit();
  371. dump_reg("after");
  372. }
  373. int sleep_mem_save(void *buf, unsigned int len)
  374. {
  375. if(save_num_item >= MEM_S2_ITEM_MAX) {
  376. printk("sleep:error: save mem fail\n");
  377. return -1;
  378. }
  379. s2_mem_save[save_num_item].buf = buf;
  380. s2_mem_save[save_num_item].len = len;
  381. save_num_item++;
  382. return 0;
  383. }