mt_spm_internal.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. #include <linux/kernel.h>
  2. #include <linux/module.h>
  3. #include <linux/spinlock.h>
  4. #include <linux/delay.h>
  5. #include <linux/atomic.h>
  6. #include <linux/string.h>
  7. #include <linux/of_fdt.h>
  8. #include <uapi/asm/setup.h>
  9. #include <mt-plat/upmu_common.h>
  10. #include "mt_spm_internal.h"
  11. #if !defined(CONFIG_ARCH_MT6580)
  12. #include "mt_vcore_dvfs.h"
  13. #endif
  14. void __weak aee_sram_printk(const char *fmt, ...)
  15. {
  16. }
  17. int __weak is_ext_buck_exist(void)
  18. {
  19. return 0;
  20. }
  21. void __attribute__((weak)) __iomem *spm_get_i2c_base(void)
  22. {
  23. return NULL;
  24. }
  25. /*
  26. * Config and Parameter
  27. */
  28. #define LOG_BUF_SIZE 256
  29. /*
  30. * Define and Declare
  31. */
  32. DEFINE_SPINLOCK(__spm_lock);
  33. atomic_t __spm_mainpll_req = ATOMIC_INIT(0);
  34. #if !defined(CONFIG_ARCH_MT6580)
  35. static const char *wakesrc_str[32] = {
  36. [0] = "SPM_MERGE",
  37. [1] = "LTE_PTP",
  38. [2] = "KP",
  39. [3] = "WDT",
  40. [4] = "GPT",
  41. [5] = "EINT",
  42. [6] = "CONN_WDT",
  43. [7] = "CCIF0_MD",
  44. [8] = "CCIF1_MD",
  45. [9] = "LOW_BAT",
  46. [10] = "CONN2AP",
  47. [11] = "F26M_WAKE",
  48. [12] = "F26M_SLEEP",
  49. [13] = "PCM_WDT",
  50. [14] = "USB_CD ",
  51. [15] = "USB_PDN",
  52. [16] = "LTE_WAKE",
  53. [17] = "LTE_SLEEP",
  54. [18] = "SEJ",
  55. [19] = "UART0",
  56. [20] = "AFE",
  57. [21] = "THERM",
  58. [22] = "CIRQ",
  59. [23] = "MD1_VRF18_WAKE",
  60. [24] = "SYSPWREQ",
  61. [25] = "MD_WDT",
  62. [26] = "C2K_WDT",
  63. [27] = "CLDMA_WDT",
  64. [28] = "MD1_VRF18_SLEEP",
  65. [29] = "CPU_IRQ",
  66. [30] = "APSRC_WAKE",
  67. [31] = "APSRC_SLEEP",
  68. };
  69. #else /* CONFIG_ARCH_MT6580 */
  70. static const char *wakesrc_str[32] = {
  71. [0] = "SPM_MERGE",
  72. [1] = "AUDIO_REQ",
  73. [2] = "KP",
  74. [3] = "WDT",
  75. [4] = "GPT",
  76. [5] = "EINT",
  77. [6] = "CONN_WDT",
  78. [7] = "GCE",
  79. [8] = "CCIF0_MD",
  80. [9] = "LOW_BAT",
  81. [10] = "CONN2AP",
  82. [11] = "F26M_WAKE",
  83. [12] = "F26M_SLEE",
  84. [13] = "PCM_WDT",
  85. [14] = "USB_CD ",
  86. [15] = "USB_PDN",
  87. [16] = "MD1_VRF18_WAKE",
  88. [17] = "MD1_VRF18_SLEEP",
  89. [18] = "DBGSYS",
  90. [19] = "UART0",
  91. [20] = "AFE",
  92. [21] = "THERM",
  93. [22] = "CIRQ",
  94. [23] = "SEJ",
  95. [24] = "SYSPWREQ",
  96. [25] = "MD1_WDT",
  97. [26] = "CPU0_IRQ",
  98. [27] = "CPU1_IRQ",
  99. [28] = "CPU2_IRQ",
  100. [29] = "CPU3_IRQ",
  101. [30] = "APSRC_WAKE",
  102. [31] = "APSRC_SLEEP",
  103. };
  104. #endif
  105. unsigned int __attribute__((weak))
  106. pmic_read_interface_nolock(unsigned int RegNum,
  107. unsigned int *val,
  108. unsigned int MASK,
  109. unsigned int SHIFT)
  110. {
  111. return 0;
  112. }
  113. unsigned int __attribute__((weak))
  114. pmic_config_interface_nolock(unsigned int RegNum,
  115. unsigned int val,
  116. unsigned int MASK,
  117. unsigned int SHIFT)
  118. {
  119. return 0;
  120. }
  121. /*
  122. * Function and API
  123. */
  124. void __spm_reset_and_init_pcm(const struct pcm_desc *pcmdesc)
  125. {
  126. u32 con1;
  127. #ifdef SPM_VCORE_EN
  128. if (spm_read(SPM_PCM_REG1_DATA) == 0x1) {
  129. /* SPM code swapping (force high voltage) */
  130. spm_write(SPM_SLEEP_CPU_WAKEUP_EVENT, 1);
  131. while (spm_read(SPM_PCM_REG11_DATA) != 0x55AA55AA)
  132. udelay(1);
  133. spm_write(SPM_SLEEP_CPU_WAKEUP_EVENT, 0);
  134. }
  135. #endif
  136. /* reset PCM */
  137. spm_write(SPM_PCM_CON0, CON0_CFG_KEY | CON0_PCM_SW_RESET);
  138. spm_write(SPM_PCM_CON0, CON0_CFG_KEY);
  139. BUG_ON((spm_read(SPM_PCM_FSM_STA) & 0x3fffff) != PCM_FSM_STA_DEF); /* PCM reset failed */
  140. /* init PCM_CON0 (disable event vector) */
  141. spm_write(SPM_PCM_CON0, CON0_CFG_KEY | CON0_IM_SLEEP_DVS);
  142. /* init PCM_CON1 (disable PCM timer but keep PCM WDT setting) */
  143. con1 = spm_read(SPM_PCM_CON1) & (CON1_PCM_WDT_WAKE_MODE | CON1_PCM_WDT_EN);
  144. spm_write(SPM_PCM_CON1, con1 | CON1_CFG_KEY | CON1_EVENT_LOCK_EN |
  145. CON1_SPM_SRAM_ISO_B | CON1_SPM_SRAM_SLP_B |
  146. (pcmdesc->replace ? 0 : CON1_IM_NONRP_EN) |
  147. CON1_MIF_APBEN | CON1_MD32_APB_INTERNAL_EN);
  148. }
  149. void __spm_kick_im_to_fetch(const struct pcm_desc *pcmdesc)
  150. {
  151. u32 ptr, len, con0;
  152. /* tell IM where is PCM code (use slave mode if code existed) */
  153. ptr = base_va_to_pa(pcmdesc->base);
  154. len = pcmdesc->size - 1;
  155. if (spm_read(SPM_PCM_IM_PTR) != ptr || spm_read(SPM_PCM_IM_LEN) != len || pcmdesc->sess > 2) {
  156. spm_write(SPM_PCM_IM_PTR, ptr);
  157. spm_write(SPM_PCM_IM_LEN, len);
  158. } else {
  159. spm_write(SPM_PCM_CON1, spm_read(SPM_PCM_CON1) | CON1_CFG_KEY | CON1_IM_SLAVE);
  160. }
  161. /* kick IM to fetch (only toggle IM_KICK) */
  162. con0 = spm_read(SPM_PCM_CON0) & ~(CON0_IM_KICK | CON0_PCM_KICK);
  163. spm_write(SPM_PCM_CON0, con0 | CON0_CFG_KEY | CON0_IM_KICK);
  164. spm_write(SPM_PCM_CON0, con0 | CON0_CFG_KEY);
  165. }
  166. void __spm_init_pcm_register(void)
  167. {
  168. /* init r0 with POWER_ON_VAL0 */
  169. spm_write(SPM_PCM_REG_DATA_INI, spm_read(SPM_POWER_ON_VAL0));
  170. spm_write(SPM_PCM_PWR_IO_EN, PCM_RF_SYNC_R0);
  171. spm_write(SPM_PCM_PWR_IO_EN, 0);
  172. /* init r7 with POWER_ON_VAL1 */
  173. spm_write(SPM_PCM_REG_DATA_INI, spm_read(SPM_POWER_ON_VAL1));
  174. spm_write(SPM_PCM_PWR_IO_EN, PCM_RF_SYNC_R7);
  175. spm_write(SPM_PCM_PWR_IO_EN, 0);
  176. }
  177. void __spm_init_event_vector(const struct pcm_desc *pcmdesc)
  178. {
  179. /* init event vector register */
  180. spm_write(SPM_PCM_EVENT_VECTOR0, pcmdesc->vec0);
  181. spm_write(SPM_PCM_EVENT_VECTOR1, pcmdesc->vec1);
  182. spm_write(SPM_PCM_EVENT_VECTOR2, pcmdesc->vec2);
  183. spm_write(SPM_PCM_EVENT_VECTOR3, pcmdesc->vec3);
  184. spm_write(SPM_PCM_EVENT_VECTOR4, pcmdesc->vec4);
  185. spm_write(SPM_PCM_EVENT_VECTOR5, pcmdesc->vec5);
  186. spm_write(SPM_PCM_EVENT_VECTOR6, pcmdesc->vec6);
  187. spm_write(SPM_PCM_EVENT_VECTOR7, pcmdesc->vec7);
  188. /* event vector will be enabled by PCM itself */
  189. }
  190. void __spm_set_power_control(const struct pwr_ctrl *pwrctrl)
  191. {
  192. /* set other SYS request mask */
  193. spm_write(SPM_AP_STANBY_CON, (!pwrctrl->md_vrf18_req_mask_b << 29) |
  194. (!pwrctrl->lte_mask << 26) |
  195. #if !defined(CONFIG_ARCH_MT6580)
  196. (spm_read(SPM_AP_STANBY_CON) & ASC_SRCCLKENI_MASK) |
  197. #else
  198. (!pwrctrl->srclkenai_mask << 25) |
  199. #endif
  200. (!!pwrctrl->md2_apsrc_sel << 24) |
  201. (!pwrctrl->conn_mask << 23) |
  202. (!!pwrctrl->md_apsrc_sel << 22) |
  203. (!pwrctrl->md32_req_mask << 21) |
  204. (!pwrctrl->md2_req_mask << 20) |
  205. (!pwrctrl->md1_req_mask << 19) |
  206. (!pwrctrl->gce_req_mask << 18) |
  207. (!pwrctrl->mfg_req_mask << 17) |
  208. (!pwrctrl->disp_req_mask << 16) |
  209. (!!pwrctrl->mcusys_idle_mask << 7) |
  210. (!!pwrctrl->ca15top_idle_mask << 6) |
  211. (!!pwrctrl->ca7top_idle_mask << 5) | (!!pwrctrl->wfi_op << 4));
  212. spm_write(SPM_PCM_SRC_REQ, (!pwrctrl->ccifmd_md2_event_mask << 8) |
  213. (!pwrctrl->ccifmd_md1_event_mask << 7) |
  214. (!pwrctrl->ccif1_to_ap_mask << 5) |
  215. (!pwrctrl->ccif1_to_md_mask << 4) |
  216. (!pwrctrl->ccif0_to_ap_mask << 3) |
  217. (!pwrctrl->ccif0_to_md_mask << 2) |
  218. (!!pwrctrl->pcm_f26m_req << 1) | (!!pwrctrl->pcm_apsrc_req << 0));
  219. spm_write(SPM_PCM_PASR_DPD_2, (!pwrctrl->isp1_ddr_en_mask << 4) |
  220. (!pwrctrl->isp0_ddr_en_mask << 3) |
  221. (!pwrctrl->dpi_ddr_en_mask << 2) |
  222. (!pwrctrl->dsi1_ddr_en_mask << 1) | (!pwrctrl->dsi0_ddr_en_mask << 0));
  223. /* set CPU WFI mask */
  224. spm_write(SPM_SLEEP_CA15_WFI0_EN, !!pwrctrl->ca15_wfi0_en);
  225. spm_write(SPM_SLEEP_CA15_WFI1_EN, !!pwrctrl->ca15_wfi1_en);
  226. spm_write(SPM_SLEEP_CA15_WFI2_EN, !!pwrctrl->ca15_wfi2_en);
  227. spm_write(SPM_SLEEP_CA15_WFI3_EN, !!pwrctrl->ca15_wfi3_en);
  228. spm_write(SPM_SLEEP_CA7_WFI0_EN, !!pwrctrl->ca7_wfi0_en);
  229. spm_write(SPM_SLEEP_CA7_WFI1_EN, !!pwrctrl->ca7_wfi1_en);
  230. spm_write(SPM_SLEEP_CA7_WFI2_EN, !!pwrctrl->ca7_wfi2_en);
  231. spm_write(SPM_SLEEP_CA7_WFI3_EN, !!pwrctrl->ca7_wfi3_en);
  232. }
  233. void __spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl)
  234. {
  235. u32 val, mask, isr;
  236. /* set PCM timer (set to max when disable) */
  237. if (pwrctrl->timer_val_cust == 0)
  238. val = pwrctrl->timer_val ? : PCM_TIMER_MAX;
  239. else
  240. val = pwrctrl->timer_val_cust;
  241. spm_write(SPM_PCM_TIMER_VAL, val);
  242. spm_write(SPM_PCM_CON1, spm_read(SPM_PCM_CON1) | CON1_CFG_KEY | CON1_PCM_TIMER_EN);
  243. /* unmask AP wakeup source */
  244. if (pwrctrl->wake_src_cust == 0)
  245. mask = pwrctrl->wake_src;
  246. else
  247. mask = pwrctrl->wake_src_cust;
  248. if (pwrctrl->syspwreq_mask)
  249. mask &= ~WAKE_SRC_SYSPWREQ;
  250. spm_write(SPM_SLEEP_WAKEUP_EVENT_MASK, ~mask);
  251. /* unmask SPM ISR (keep TWAM setting) */
  252. isr = spm_read(SPM_SLEEP_ISR_MASK) & ISRM_TWAM;
  253. spm_write(SPM_SLEEP_ISR_MASK, isr | ISRM_RET_IRQ_AUX);
  254. }
  255. void __spm_kick_pcm_to_run(const struct pwr_ctrl *pwrctrl)
  256. {
  257. u32 con0;
  258. /* init register to match PCM expectation */
  259. spm_write(SPM_PCM_MAS_PAUSE_MASK, 0xffffffff);
  260. spm_write(SPM_PCM_REG_DATA_INI, 0);
  261. /* spm_write(SPM_CLK_CON, spm_read(SPM_CLK_CON) & ~CC_DISABLE_DORM_PWR); */
  262. /* set PCM flags and data */
  263. spm_write(SPM_PCM_FLAGS, pwrctrl->pcm_flags);
  264. spm_write(SPM_PCM_RESERVE, pwrctrl->pcm_reserve);
  265. /* lock Infra DCM when PCM runs */
  266. spm_write(SPM_CLK_CON, (spm_read(SPM_CLK_CON) & ~CC_LOCK_INFRA_DCM) |
  267. (pwrctrl->infra_dcm_lock ? CC_LOCK_INFRA_DCM : 0));
  268. /* enable r0 and r7 to control power */
  269. spm_write(SPM_PCM_PWR_IO_EN, (pwrctrl->r0_ctrl_en ? PCM_PWRIO_EN_R0 : 0) |
  270. (pwrctrl->r7_ctrl_en ? PCM_PWRIO_EN_R7 : 0));
  271. /* kick PCM to run (only toggle PCM_KICK) */
  272. con0 = spm_read(SPM_PCM_CON0) & ~(CON0_IM_KICK | CON0_PCM_KICK);
  273. spm_write(SPM_PCM_CON0, con0 | CON0_CFG_KEY | CON0_PCM_KICK);
  274. spm_write(SPM_PCM_CON0, con0 | CON0_CFG_KEY);
  275. }
  276. void __spm_get_wakeup_status(struct wake_status *wakesta)
  277. {
  278. /* get PC value if PCM assert (pause abort) */
  279. wakesta->assert_pc = spm_read(SPM_PCM_REG_DATA_INI);
  280. /* get wakeup event */
  281. #if !defined(CONFIG_ARCH_MT6580)
  282. wakesta->r12 = spm_read(SPM_PCM_RESERVE3);
  283. #else
  284. wakesta->r12 = spm_read(SPM_PCM_REG12_DATA);
  285. #endif
  286. wakesta->raw_sta = spm_read(SPM_SLEEP_ISR_RAW_STA);
  287. wakesta->wake_misc = spm_read(SPM_SLEEP_WAKEUP_MISC);
  288. /* get sleep time */
  289. wakesta->timer_out = spm_read(SPM_PCM_TIMER_OUT);
  290. /* get other SYS and co-clock status */
  291. wakesta->r13 = spm_read(SPM_PCM_REG13_DATA);
  292. wakesta->idle_sta = spm_read(SPM_SLEEP_SUBSYS_IDLE_STA);
  293. /* get debug flag for PCM execution check */
  294. wakesta->debug_flag = spm_read(SPM_PCM_RESERVE4);
  295. /* get special pattern (0xf0000 or 0x10000) if sleep abort */
  296. #if !defined(CONFIG_ARCH_MT6580)
  297. wakesta->event_reg = spm_read(SPM_PCM_PASR_DPD_2);
  298. #else
  299. wakesta->event_reg = spm_read(SPM_PCM_EVENT_REG_STA);
  300. #endif
  301. /* get ISR status */
  302. wakesta->isr = spm_read(SPM_SLEEP_ISR_STATUS);
  303. }
  304. void __spm_clean_after_wakeup(void)
  305. {
  306. /* disable r0 and r7 to control power */
  307. spm_write(SPM_PCM_PWR_IO_EN, 0);
  308. /* clean CPU wakeup event */
  309. spm_write(SPM_SLEEP_CPU_WAKEUP_EVENT, 0);
  310. /* clean PCM timer event */
  311. spm_write(SPM_PCM_CON1, CON1_CFG_KEY | (spm_read(SPM_PCM_CON1) & ~CON1_PCM_TIMER_EN));
  312. /* clean wakeup event raw status (for edge trigger event) */
  313. spm_write(SPM_SLEEP_WAKEUP_EVENT_MASK, ~0);
  314. /* clean ISR status (except TWAM) */
  315. spm_write(SPM_SLEEP_ISR_MASK, spm_read(SPM_SLEEP_ISR_MASK) | ISRM_ALL_EXC_TWAM);
  316. spm_write(SPM_SLEEP_ISR_STATUS, ISRC_ALL_EXC_TWAM);
  317. spm_write(SPM_PCM_SW_INT_CLEAR, PCM_SW_INT_ALL);
  318. }
  319. #define spm_print(suspend, fmt, args...) \
  320. do { \
  321. if (!suspend) \
  322. spm_debug(fmt, ##args); \
  323. else \
  324. spm_crit2(fmt, ##args); \
  325. } while (0)
  326. wake_reason_t __spm_output_wake_reason(const struct wake_status *wakesta,
  327. const struct pcm_desc *pcmdesc, bool suspend)
  328. {
  329. int i;
  330. char buf[LOG_BUF_SIZE] = { 0 };
  331. wake_reason_t wr = WR_UNKNOWN;
  332. if (wakesta->assert_pc != 0) {
  333. spm_print(suspend, "PCM ASSERT AT %u (%s), r13 = 0x%x, debug_flag = 0x%x\n",
  334. wakesta->assert_pc, pcmdesc->version, wakesta->r13, wakesta->debug_flag);
  335. return WR_PCM_ASSERT;
  336. }
  337. if (wakesta->r12 & WAKE_SRC_SPM_MERGE) {
  338. if (wakesta->wake_misc & WAKE_MISC_PCM_TIMER) {
  339. strcat(buf, " PCM_TIMER");
  340. wr = WR_PCM_TIMER;
  341. }
  342. if (wakesta->wake_misc & WAKE_MISC_TWAM) {
  343. strcat(buf, " TWAM");
  344. wr = WR_WAKE_SRC;
  345. }
  346. if (wakesta->wake_misc & WAKE_MISC_CPU_WAKE) {
  347. strcat(buf, " CPU");
  348. wr = WR_WAKE_SRC;
  349. }
  350. }
  351. for (i = 1; i < 32; i++) {
  352. if (wakesta->r12 & (1U << i)) {
  353. if ((strlen(buf) + strlen(wakesrc_str[i])) < LOG_BUF_SIZE)
  354. strncat(buf, wakesrc_str[i], strlen(wakesrc_str[i]));
  355. wr = WR_WAKE_SRC;
  356. }
  357. }
  358. #if !defined(CONFIG_ARCH_MT6580)
  359. BUG_ON(strlen(buf) >= LOG_BUF_SIZE);
  360. #endif
  361. spm_warn("wake up by%s, timer_out = %u, r13 = 0x%x, debug_flag = 0x%x\n",
  362. buf, wakesta->timer_out, wakesta->r13, wakesta->debug_flag);
  363. spm_warn(
  364. "r12 = 0x%x, raw_sta = 0x%x, idle_sta = 0x%x, event_reg = 0x%x, isr = 0x%x\n",
  365. wakesta->r12, wakesta->raw_sta, wakesta->idle_sta, wakesta->event_reg,
  366. wakesta->isr);
  367. return wr;
  368. }
  369. void __spm_dbgout_md_ddr_en(bool enable)
  370. {
  371. /* set TEST_MODE_CFG */
  372. spm_write(0xf0000230, (spm_read(0xf0000230) & ~(0x7fff << 16)) |
  373. (0x3 << 26) | (0x3 << 21) | (0x3 << 16));
  374. /* set md_ddr_en to GPIO150 */
  375. spm_write(0xf0001500, 0x70e);
  376. spm_write(0xf00057e4, 0x7);
  377. /* set emi_clk_off_req to GPIO140 */
  378. spm_write(0xf000150c, 0x3fe);
  379. spm_write(0xf00057c4, 0x7);
  380. /* enable debug output */
  381. spm_write(SPM_PCM_DEBUG_CON, !!enable);
  382. }
  383. #if !defined(CONFIG_ARCH_MT6580)
  384. u32 __spm_dpidle_sodi_set_pmic_setting(void)
  385. {
  386. u32 vsram_vosel_on_lb = 0;
  387. u32 vsram_vosel_offset = 0;
  388. u32 vsram_vosel_delta = 0;
  389. pmic_read_interface_nolock(MT6328_PMIC_VSRAM_VOSEL_ON_LB_ADDR,
  390. &vsram_vosel_on_lb,
  391. MT6328_PMIC_VSRAM_VOSEL_ON_LB_MASK,
  392. MT6328_PMIC_VSRAM_VOSEL_ON_LB_SHIFT);
  393. pmic_read_interface_nolock(MT6328_PMIC_VSRAM_VOSEL_OFFSET_ADDR,
  394. &vsram_vosel_offset,
  395. MT6328_PMIC_VSRAM_VOSEL_OFFSET_MASK,
  396. MT6328_PMIC_VSRAM_VOSEL_OFFSET_SHIFT);
  397. pmic_read_interface_nolock(MT6328_PMIC_VSRAM_VOSEL_DELTA_ADDR,
  398. &vsram_vosel_delta,
  399. MT6328_PMIC_VSRAM_VOSEL_DELTA_MASK,
  400. MT6328_PMIC_VSRAM_VOSEL_DELTA_SHIFT);
  401. /* delta = 0v */
  402. spm_write(SPM_PCM_RESERVE3, (vsram_vosel_offset << 8) | vsram_vosel_delta);
  403. /* 0.85v */
  404. pmic_config_interface_nolock(MT6328_PMIC_VSRAM_VOSEL_ON_LB_ADDR,
  405. (vsram_vosel_on_lb & 0xff80) | 0x28,
  406. MT6328_PMIC_VSRAM_VOSEL_ON_LB_MASK,
  407. MT6328_PMIC_VSRAM_VOSEL_ON_LB_SHIFT);
  408. return vsram_vosel_on_lb;
  409. }
  410. void __spm_dpidle_sodi_restore_pmic_setting(u32 vsram_vosel_on_lb)
  411. {
  412. pmic_config_interface_nolock(MT6328_PMIC_VSRAM_VOSEL_ON_LB_ADDR,
  413. vsram_vosel_on_lb,
  414. MT6328_PMIC_VSRAM_VOSEL_ON_LB_MASK,
  415. MT6328_PMIC_VSRAM_VOSEL_ON_LB_SHIFT);
  416. }
  417. #ifdef CONFIG_ARCH_MT6753
  418. #include <mach/mt_clkmgr.h>
  419. #include <linux/i2c.h>
  420. #include "mt_i2c.h"
  421. static u32 i2c4_conf_backup;
  422. static u32 i2c4_conf_backup1;
  423. void __spm_enable_i2c4_clk(void)
  424. {
  425. if (is_ext_buck_exist()) {
  426. i2c4_base = spm_get_i2c_base();
  427. if (i2c4_base == NULL)
  428. BUG();
  429. enable_clock(MT_CG_PERI_I2C4, "suspend");
  430. /* Backup I2C setting */
  431. i2c4_conf_backup = spm_read(i2c4_base + 0x10);
  432. spm_write(i2c4_base + 0x10, (i2c4_conf_backup & ~(0x1 << 4)));
  433. i2c4_conf_backup1 = spm_read(i2c4_base + 0x48);
  434. spm_write(i2c4_base + 0x48, (i2c4_conf_backup1 & ~(0x1)));
  435. }
  436. }
  437. void __spm_disable_i2c4_clk(void)
  438. {
  439. if (is_ext_buck_exist()) {
  440. i2c4_base = spm_get_i2c_base();
  441. if (i2c4_base == NULL)
  442. BUG();
  443. /* Restore I2C setting */
  444. spm_write(i2c4_base + 0x48, i2c4_conf_backup1);
  445. spm_write(i2c4_base + 0x10, i2c4_conf_backup);
  446. disable_clock(MT_CG_PERI_I2C4, "suspend");
  447. }
  448. }
  449. #endif
  450. static u32 spm_dram_dummy_read_flags;
  451. #ifdef CONFIG_OF
  452. static int dt_scan_memory(unsigned long node, const char *uname, int depth, void *data)
  453. {
  454. const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
  455. const __be32 *reg;
  456. const struct dram_info *dram_info = NULL;
  457. /* We are scanning "memory" nodes only */
  458. if (type == NULL) {
  459. /*
  460. * The longtrail doesn't have a device_type on the
  461. * /memory node, so look for the node called /memory@0.
  462. */
  463. if (depth != 1 || strcmp(uname, "memory@0") != 0)
  464. return 0;
  465. } else if (strcmp(type, "memory") != 0)
  466. return 0;
  467. reg = (const __be32 *)of_get_flat_dt_prop(node, "reg", NULL);
  468. if (reg == NULL)
  469. return 0;
  470. if (node) {
  471. /* orig_dram_info */
  472. dram_info = (const struct dram_info *)of_get_flat_dt_prop(node, "orig_dram_info", NULL);
  473. }
  474. if ((dram_info->rank_info[1].start == 0x60000000)
  475. || (dram_info->rank_info[1].start == 0x70000000))
  476. spm_dram_dummy_read_flags |= SPM_DRAM_RANK1_ADDR_SEL0;
  477. else if (dram_info->rank_info[1].start == 0x80000000)
  478. spm_dram_dummy_read_flags |= SPM_DRAM_RANK1_ADDR_SEL1;
  479. else if (dram_info->rank_info[1].start == 0xc0000000)
  480. spm_dram_dummy_read_flags |= SPM_DRAM_RANK1_ADDR_SEL2;
  481. else if (dram_info->rank_info[1].start == 0xa0000000)
  482. spm_dram_dummy_read_flags |= SPM_DRAM_RANK1_ADDR_SEL3;
  483. else if (dram_info->rank_info[1].size != 0x0) {
  484. pr_err("dram rank1_info_error: no rank info\n");
  485. BUG_ON(1);
  486. }
  487. return node;
  488. }
  489. #endif
  490. void spm_set_dram_bank_info_pcm_flag(u32 *pcm_flags)
  491. {
  492. *pcm_flags |= spm_dram_dummy_read_flags;
  493. }
  494. bool spm_set_pcm_init_flag(void)
  495. {
  496. #ifdef CONFIG_OF
  497. int node;
  498. node = of_scan_flat_dt(dt_scan_memory, NULL);
  499. #else
  500. pr_err("dram rank1_info_error: no rank info\n");
  501. BUG_ON(1);
  502. #endif
  503. return true;
  504. }
  505. #endif /* !defined(CONFIG_ARCH_MT6580) */
  506. MODULE_DESCRIPTION("SPM-Internal Driver v0.1");