soc_psram.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /*
  2. * Copyright (c) 2021 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file
  8. * @brief Actions PSRAM Implementation.
  9. */
  10. #include <kernel.h>
  11. #include <device.h>
  12. #include <zephyr.h>
  13. #include <soc.h>
  14. #include <linker/linker-defs.h>
  15. #include <dvfs.h>
  16. #define SPI1_DDR_ADDR0 (SPI1_CTL + 0x2C)
  17. #define SPI1_DDR_ADDR1 (SPI1_CTL + 0x30)
  18. #define SPI1_DDR_TRXLEN (SPI1_CTL + 0x34)
  19. #define SPI1_DDR_CMD (SPI1_CTL + 0x20)
  20. #define SPI1_DDR_START (SPI1_CTL + 0x24)
  21. #define SPI1_TXDAT (SPI1_CTL + 0x08)
  22. #define SPI1_DDR_STATUS (SPI1_CTL + 0x28)
  23. #define SPI1_STA (SPI1_CTL + 0x04)
  24. #define SPI1_RXDAT (SPI1_CTL + 0x0C)
  25. #define PSRAM_CS_PIN (40)
  26. #ifndef CONFIG_SOC_NO_PSRAM
  27. __sleepfunc void __psram_reg_write(unsigned int reg_addr, unsigned int reg_data)
  28. {
  29. uint32_t ctl, mctl;
  30. ctl = sys_read32(SPI1_CTL);
  31. mctl = sys_read32(SPI1_DDR_MODE_CTL);
  32. /* switch to normal */
  33. sys_write32(sys_read32(SPI1_CTL) | (1 << 15), SPI1_CTL);
  34. /* wait ready */
  35. while ((sys_read32(SPI1_STA) & 0x2) != 2) {
  36. ;
  37. }
  38. /* use CPU clock, 8Bit FIFO mode */
  39. sys_write32(sys_read32(SPI1_CTL) & ~(3 << 30), SPI1_CTL);
  40. /* spi1 tx/rx fifo reset */
  41. sys_write32(sys_read32(SPI1_CTL) & ~(3 << 4), SPI1_CTL);
  42. sys_write32(sys_read32(SPI1_CTL) | (3 << 4), SPI1_CTL);
  43. if(soc_boot_is_mini()){
  44. sys_write32((0<<20)|(6<<16)|(5<<12)|(4<<8)|(4<<4)|(4<<0), SPI1_DDR_MODE_CTL); //DDR OPI OKmode
  45. sys_write32(0x600001, SPI1_DDR_ADDR1);
  46. }else{
  47. /* DDR OPI OKmode */
  48. sys_write32((0 << 20) | (5 << 16) | (1 << 0), SPI1_DDR_MODE_CTL);
  49. }
  50. /* psram register address */
  51. sys_write32(reg_addr, SPI1_DDR_ADDR0);
  52. sys_write32(2, SPI1_DDR_TRXLEN);
  53. /* write command is 0xC0 */
  54. sys_write32(0xC0, SPI1_DDR_CMD);
  55. /* TX transmit start */
  56. sys_write32(0x02, SPI1_DDR_START);
  57. if(soc_boot_is_mini()){
  58. sys_write32(reg_data>>8, SPI1_TXDAT);
  59. sys_write32(reg_data&0xff, SPI1_TXDAT); /* must send two bytes */
  60. }else{
  61. sys_write32(reg_data, SPI1_TXDAT);
  62. sys_write32(0, SPI1_TXDAT); /* must send two bytes */
  63. }
  64. soc_udelay(1);/*Must delay to resolve sleep&wakeup panic*/
  65. /* wait transmit complete */
  66. while ((sys_read32(SPI1_DDR_STATUS) & 0x1) != 1);
  67. /* clear status bit */
  68. sys_write32(0x01, SPI1_DDR_STATUS);
  69. sys_write32(0x00, SPI1_DDR_START);
  70. sys_write32(ctl, SPI1_CTL);
  71. sys_write32(mctl, SPI1_DDR_MODE_CTL);
  72. }
  73. __sleepfunc unsigned int __psram_reg_read(unsigned int reg_addr)
  74. {
  75. uint32_t ctl, mctl, reg_data;
  76. ctl = sys_read32(SPI1_CTL);
  77. mctl = sys_read32(SPI1_DDR_MODE_CTL);
  78. /* switch to normal */
  79. sys_write32(sys_read32(SPI1_CTL) | (1 << 15), SPI1_CTL);
  80. /* wait ready */
  81. while ((sys_read32(SPI1_STA) & 0x2) != 2) {
  82. ;
  83. }
  84. /* use CPU clock, 8Bit FIFO mode */
  85. sys_write32(sys_read32(SPI1_CTL) & ~(3 << 30), SPI1_CTL);
  86. /* spi1 tx/rx fifo reset */
  87. sys_write32(sys_read32(SPI1_CTL) & ~(3 << 4), SPI1_CTL);
  88. sys_write32(sys_read32(SPI1_CTL) | (3 << 4), SPI1_CTL);
  89. if(soc_boot_is_mini()){
  90. sys_write32((0<<20)|(6<<16)|(5<<12)|(4<<8)|(4<<4)|(4<<0), SPI1_DDR_MODE_CTL);//DDR OPI OKmode
  91. sys_write32(0xe00001, SPI1_DDR_ADDR1);
  92. }else{
  93. /* DDR OPI OKmode */
  94. sys_write32((0 << 20) | (5 << 16) | (1 << 0), SPI1_DDR_MODE_CTL);
  95. }
  96. /* psram register address */
  97. sys_write32(reg_addr, SPI1_DDR_ADDR0);
  98. sys_write32(2, SPI1_DDR_TRXLEN);
  99. /* read command */
  100. sys_write32(0x40, SPI1_DDR_CMD);
  101. /* RX transmit start */
  102. sys_write32(0x01, SPI1_DDR_START);
  103. while((sys_read32(SPI1_STA) & 0x40) == 0x40) {}; // wait for rx fifo not empty
  104. while((sys_read32(SPI1_DDR_STATUS) & 0x1) != 1) {}; //wait transmit complete
  105. /* clear status bit */
  106. sys_write32(0x01, SPI1_DDR_STATUS);
  107. sys_write32(0x00, SPI1_DDR_START);
  108. if(soc_boot_is_mini()) {
  109. reg_data = sys_read32(SPI1_RXDAT);
  110. reg_data = reg_data << 8;
  111. reg_data |= sys_read32(SPI1_RXDAT);
  112. }else {
  113. reg_data = sys_read32(SPI1_RXDAT);
  114. }
  115. sys_write32(ctl, SPI1_CTL);
  116. sys_write32(mctl, SPI1_DDR_MODE_CTL);
  117. return reg_data;
  118. }
  119. __sleepfunc void psram_self_refresh_control(bool low_refresh_en)
  120. {
  121. uint32_t reg_data;
  122. if(soc_boot_is_mini())
  123. return;
  124. reg_data = __psram_reg_read(4);
  125. if (low_refresh_en) {
  126. /* need follow origin PSRAM write latency bit[7:5], otherwise wkup panic */
  127. reg_data = (reg_data & ~(0x3 << 3)) | (0x1 << 3); /* 0.5x refresh */
  128. } else {
  129. reg_data = reg_data & ~(0x3 << 3); /* 1x refresh */
  130. }
  131. __psram_reg_write(4, reg_data);
  132. }
  133. __sleepfunc void psram_power_control(bool low_power_en)
  134. {
  135. volatile int loop;
  136. uint32_t pinctl_cs_bak;
  137. if (low_power_en) {
  138. if(soc_boot_is_mini())
  139. __psram_reg_write(1, 0x20); //Hybrid Sleep
  140. else
  141. __psram_reg_write(6, 0xf0);
  142. } else {
  143. /* backup psram cs function pin ctl */
  144. pinctl_cs_bak = sys_read32(GPIO_REG_BASE + PSRAM_CS_PIN * 4);
  145. /* spi1 cs low to exit deep power mode */
  146. sys_write32(1 << 8, GPIO_REG_BASE + GPIO_BRR0 + 4);
  147. /* gpio40 cs low */
  148. sys_write32(0x3840, GPIO_REG_BASE + PSRAM_CS_PIN * 4);
  149. /* 60ns keep cs low */
  150. loop = 30;
  151. while(loop)loop--;
  152. /* spi1 cs high exit deep power mode */
  153. sys_write32(1 << 8, GPIO_REG_BASE + GPIO_BSR0 + 4);
  154. /* mini is 70us keep cs high else 150us */
  155. soc_udelay(150);
  156. /* psram gpio40 cs recovery */
  157. sys_write32(pinctl_cs_bak, GPIO_REG_BASE + PSRAM_CS_PIN * 4);
  158. }
  159. }
  160. __sleepfunc void psram_delay_chain_set(uint8_t dqs, uint8_t dqs1, uint8_t clkout)
  161. {
  162. sys_write32((sys_read32(SPI1_DELAYCHAIN) & ~(0x3f << 0) & ~(0x3f << 8)) \
  163. | (dqs << 0) \
  164. | (clkout << 8), SPI1_DELAYCHAIN);
  165. sys_write32((sys_read32(SPI1_DQS1_DELAYCHAIN) & ~(0x3f << 0)) \
  166. | (dqs1 << 0), SPI1_DQS1_DELAYCHAIN);
  167. soc_udelay(1);
  168. }
  169. #ifdef CONFIG_ACTS_DVFS_DYNAMIC_LEVEL
  170. struct psram_delaychain_tbl {
  171. uint16_t vdd_volt;
  172. uint8_t clkout;
  173. uint8_t dqs;
  174. uint8_t dqs1;
  175. };
  176. static const struct psram_delaychain_tbl psram_delaychain_tbl0[] = {
  177. {950, SPI1_DELAYCHAIN_CLKOUT, 6, 6},
  178. {1000, SPI1_DELAYCHAIN_CLKOUT, 6, 6},
  179. {1100, SPI1_DELAYCHAIN_CLKOUT, 10, 10},
  180. {1150, SPI1_DELAYCHAIN_CLKOUT, 10, 10},
  181. {1200, SPI1_DELAYCHAIN_CLKOUT, 10, 10},
  182. };
  183. static const struct psram_delaychain_tbl psram_delaychain_tbl1[] = {
  184. {950, SPI1_DELAYCHAIN_CLKOUT, 3, 4},
  185. {1000, SPI1_DELAYCHAIN_CLKOUT, 3, 4},
  186. {1100, SPI1_DELAYCHAIN_CLKOUT, 3, 4},
  187. {1150, SPI1_DELAYCHAIN_CLKOUT, 3, 4},
  188. {1200, SPI1_DELAYCHAIN_CLKOUT, 3, 4},
  189. };
  190. static const struct psram_delaychain_tbl psram_delaychain_tbl_mini[] = {
  191. {950, SPI1_DELAYCHAIN_CLKOUT, 3, 3},
  192. {1000, SPI1_DELAYCHAIN_CLKOUT, 4, 4},
  193. {1100, SPI1_DELAYCHAIN_CLKOUT, 5, 5},
  194. {1150, SPI1_DELAYCHAIN_CLKOUT, 6, 6},
  195. {1200, SPI1_DELAYCHAIN_CLKOUT, 6, 6},
  196. };
  197. static inline void psram_set_delaychain_by_vdd(uint16_t vdd)
  198. {
  199. uint8_t i, len;
  200. const struct psram_delaychain_tbl *tbl;
  201. if(soc_boot_is_mini()){
  202. tbl = psram_delaychain_tbl_mini;
  203. len = ARRAY_SIZE(psram_delaychain_tbl_mini);
  204. }else {
  205. if (soc_dvfs_opt()) {
  206. tbl = psram_delaychain_tbl1;
  207. len = ARRAY_SIZE(psram_delaychain_tbl1);
  208. } else {
  209. tbl = psram_delaychain_tbl0;
  210. len = ARRAY_SIZE(psram_delaychain_tbl0);
  211. }
  212. }
  213. for (i = 0; i < len; i++) {
  214. if (tbl[i].vdd_volt == vdd) {
  215. psram_delay_chain_set(tbl[i].dqs, tbl[i].dqs1,tbl[i].clkout);
  216. break;
  217. }
  218. }
  219. }
  220. __dvfs_notifier_func static void psram_dvfs_notify(void *user_data, struct dvfs_freqs *dvfs_freq)
  221. {
  222. struct dvfs_level *old_dvfs_level, *new_dvfs_level;
  223. uint32_t key;
  224. ARG_UNUSED(user_data);
  225. if (!dvfs_freq) {
  226. printk("dvfs notify invalid param");
  227. return ;
  228. }
  229. if (dvfs_freq->old_level == dvfs_freq->new_level)
  230. return ;
  231. old_dvfs_level = dvfs_get_info_by_level_id(dvfs_freq->old_level);
  232. new_dvfs_level = dvfs_get_info_by_level_id(dvfs_freq->new_level);
  233. if (old_dvfs_level->vdd_volt == new_dvfs_level->vdd_volt) {
  234. return;
  235. }
  236. key = irq_lock();
  237. if (old_dvfs_level->vdd_volt > new_dvfs_level->vdd_volt) {
  238. /* vdd voltage decrease */
  239. if (dvfs_freq->state == DVFS_EVENT_PRE_CHANGE) {
  240. //spi1 clock may div/2 for psram, so we set psram clock * 2
  241. if (new_dvfs_level->vdd_volt < 1000){
  242. clk_set_rate(CLOCK_ID_SPI1, MHZ(70) * 2);
  243. } else if (new_dvfs_level->vdd_volt < 1200){
  244. clk_set_rate(CLOCK_ID_SPI1, MHZ(93)*2);
  245. }else {
  246. clk_set_rate(CLOCK_ID_SPI1, MHZ(140) * 2);
  247. }
  248. psram_set_delaychain_by_vdd(new_dvfs_level->vdd_volt);
  249. printk("psram delaychain update by vdd:%d => %d\n",
  250. old_dvfs_level->vdd_volt, new_dvfs_level->vdd_volt);
  251. }
  252. } else {
  253. /* vdd voltage increase */
  254. if (dvfs_freq->state == DVFS_EVENT_POST_CHANGE) {
  255. psram_set_delaychain_by_vdd(new_dvfs_level->vdd_volt);
  256. //spi1 clock may div/2 for psram, so we set psram clock * 2
  257. if (new_dvfs_level->vdd_volt < 1000){
  258. clk_set_rate(CLOCK_ID_SPI1, MHZ(70) * 2);
  259. } else if (new_dvfs_level->vdd_volt < 1200){
  260. clk_set_rate(CLOCK_ID_SPI1, MHZ(93)*2);
  261. } else {
  262. clk_set_rate(CLOCK_ID_SPI1, MHZ(140) * 2);
  263. }
  264. printk("psram delaychain update by vdd:%d => %d\n",
  265. old_dvfs_level->vdd_volt, new_dvfs_level->vdd_volt);
  266. }
  267. }
  268. irq_unlock(key);
  269. }
  270. static struct dvfs_notifier __dvfs_notifier_data psram_dvsf_notifier = {
  271. .dvfs_notify_func_t = psram_dvfs_notify,
  272. };
  273. static int soc_psram_init(const struct device *dev)
  274. {
  275. ARG_UNUSED(dev);
  276. dvfs_register_notifier(&psram_dvsf_notifier);
  277. return 0;
  278. }
  279. SYS_INIT(soc_psram_init, PRE_KERNEL_1, 21);
  280. #endif /* CONFIG_ACTS_DVFS_DYNAMIC_LEVEL */
  281. #else // no psram
  282. __sleepfunc void __psram_reg_write(unsigned int reg_addr, unsigned int reg_data)
  283. {
  284. }
  285. __sleepfunc void psram_self_refresh_control(bool low_refresh_en)
  286. {
  287. }
  288. __sleepfunc void psram_power_control(bool low_power_en)
  289. {
  290. if(!low_power_en)
  291. soc_udelay(150);
  292. }
  293. __sleepfunc void psram_delay_chain_set(uint8_t dqs, uint8_t dqs1, uint8_t clkout)
  294. {
  295. }
  296. #endif // #ifndef CONFIG_SOC_NO_PSRAM