apusys_power.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. /*
  2. * Copyright (c) 2024, MediaTek Inc. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <inttypes.h>
  7. #define SPMI_ENABLE (0)
  8. #if SPMI_ENABLE
  9. #include <include/drivers/spmi_api.h>
  10. #endif
  11. #include <common/debug.h>
  12. #include <drivers/delay_timer.h>
  13. #include <lib/mmio.h>
  14. #include <lib/spinlock.h>
  15. #include <lib/utils_def.h>
  16. #include <lib/xlat_tables/xlat_tables_v2.h>
  17. #include "apusys_power.h"
  18. static void apu_w_are(int entry, uint32_t reg, uint32_t data)
  19. {
  20. uint32_t are_entry_addr;
  21. are_entry_addr = APUSYS_BASE + APU_ARE + ARE_REG_SIZE * ARE_ENTRY(entry);
  22. mmio_write_32(are_entry_addr, reg);
  23. mmio_write_32((are_entry_addr + ARE_REG_SIZE), data);
  24. }
  25. static void get_pll_pcw(uint32_t clk_rate, uint32_t *r1, uint32_t *r2)
  26. {
  27. unsigned int fvco = clk_rate;
  28. unsigned int pcw_val;
  29. unsigned int postdiv_val = 1;
  30. unsigned int postdiv_reg = 0;
  31. while (fvco <= OUT_CLK_FREQ_MIN) {
  32. postdiv_val = postdiv_val << 1;
  33. postdiv_reg = postdiv_reg + 1;
  34. fvco = fvco << 1;
  35. }
  36. pcw_val = (fvco * (1 << DDS_SHIFT)) / BASIC_CLK_FREQ;
  37. if (postdiv_reg == 0) {
  38. pcw_val = pcw_val * 2;
  39. postdiv_val = postdiv_val << 1;
  40. postdiv_reg = postdiv_reg + 1;
  41. }
  42. *r1 = postdiv_reg;
  43. *r2 = pcw_val;
  44. }
  45. static void buck_off_by_pcu(uint32_t ofs, uint32_t shift, uint32_t slv_id)
  46. {
  47. uint32_t pmif_id = 0x0;
  48. int retry = 10;
  49. mmio_setbits_32(APUSYS_PCU + APU_PCUTOP_CTRL_SET, PMIC_IRQ_EN);
  50. mmio_write_32(APUSYS_PCU + APU_PCU_PMIC_TAR_BUF1,
  51. (ofs << PMIC_OFF_ADDR_OFF) | BIT(shift));
  52. mmio_write_32(APUSYS_PCU + APU_PCU_PMIC_TAR_BUF2,
  53. (slv_id << PMIC_SLVID_OFF) | (pmif_id << PMIC_PMIFID_OFF) | PCU_BUCK_OFF_CMD);
  54. mmio_write_32(APUSYS_PCU + APU_PCU_PMIC_CMD, PMIC_CMD_EN);
  55. while ((mmio_read_32(APUSYS_PCU + APU_PCU_PMIC_IRQ) & PMIC_CMD_IRQ) == 0) {
  56. udelay(10);
  57. if (--retry < 0)
  58. ERROR("%s wait APU_PCU_PMIC_IRQ timeout !\n", __func__);
  59. }
  60. mmio_write_32(APUSYS_PCU + APU_PCU_PMIC_IRQ, PMIC_CMD_IRQ);
  61. }
  62. static void apu_buck_off_cfg(void)
  63. {
  64. mmio_setbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_SET, BIT(10));
  65. mmio_setbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_CLR, BIT(9));
  66. mmio_setbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_CLR, BIT(12));
  67. mmio_setbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_CLR, BIT(14));
  68. mmio_clrbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_SET, BIT(10));
  69. mmio_clrbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_CLR, BIT(9));
  70. mmio_clrbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_CLR, BIT(12));
  71. mmio_clrbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_CLR, BIT(14));
  72. udelay(1);
  73. mmio_write_32(APUSYS_RPC + APU_RPC_HW_CON, BUCK_PROT_REQ_SET);
  74. udelay(1);
  75. mmio_write_32(APUSYS_RPC + APU_RPC_HW_CON, SRAM_AOC_LHENB_SET);
  76. udelay(1);
  77. mmio_write_32(APUSYS_RPC + APU_RPC_HW_CON, SRAM_AOC_ISO_SET);
  78. udelay(1);
  79. mmio_write_32(APUSYS_RPC + APU_RPC_HW_CON, PLL_AOC_ISO_EN_SET);
  80. udelay(1);
  81. mmio_write_32(APUSYS_RPC + APU_RPC_HW_CON, BUCK_ELS_EN_SET);
  82. udelay(1);
  83. mmio_write_32(APUSYS_RPC + APU_RPC_HW_CON, BUCK_AO_RST_B_CLR);
  84. udelay(1);
  85. buck_off_by_pcu(BUCK_VAPU_PMIC_REG_EN_CLR_ADDR, BUCK_VAPU_PMIC_REG_EN_SHIFT,
  86. BUCK_VAPU_PMIC_ID);
  87. mmio_setbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_SET, BIT(6));
  88. udelay(1);
  89. mmio_setbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_SET, BIT(7));
  90. udelay(1);
  91. mmio_clrbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_SET, BIT(6));
  92. udelay(1);
  93. mmio_clrbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_SET, BIT(7));
  94. udelay(1);
  95. }
  96. static void apu_acc_init(void)
  97. {
  98. uint32_t top_acc_base_arr[] = {MNOC_ACC_BASE, UP_ACC_BASE};
  99. uint32_t eng_acc_base_arr[] = {MVPU_ACC_BASE, MDLA_ACC_BASE};
  100. int acc_idx;
  101. int are_idx = ACC_ENTRY_BEGIN;
  102. uint32_t base_reg;
  103. for (acc_idx = 0 ; acc_idx < ARRAY_SIZE(top_acc_base_arr) ; acc_idx++) {
  104. base_reg = APUSYS_ACC + top_acc_base_arr[acc_idx];
  105. #if CFG_APU_ARDCM_ENABLE
  106. apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL1, APU_ARDCM_CTRL1_VAL_0);
  107. apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL0, APU_ARDCM_CTRL0_VAL_0);
  108. apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL1, APU_ARDCM_CTRL1_VAL_1);
  109. apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL0, APU_ARDCM_CTRL0_VAL_1);
  110. #endif
  111. apu_w_are(are_idx++, base_reg + APU_ACC_CONFG_CLR0, CGEN_SOC);
  112. apu_w_are(are_idx++, base_reg + APU_ACC_CONFG_SET0, HW_CTRL_EN);
  113. }
  114. for (acc_idx = 0 ; acc_idx < ARRAY_SIZE(eng_acc_base_arr) ; acc_idx++) {
  115. base_reg = APUSYS_ACC + eng_acc_base_arr[acc_idx];
  116. #if CFG_APU_ARDCM_ENABLE
  117. apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL1, APU_ARDCM_CTRL1_VAL_0);
  118. apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL0, APU_ARDCM_CTRL0_VAL_0);
  119. apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL1, APU_ARDCM_CTRL1_VAL_1);
  120. apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL0, APU_ARDCM_CTRL0_VAL_1);
  121. #endif
  122. apu_w_are(are_idx++, base_reg + APU_ACC_CONFG_CLR0, CGEN_SOC);
  123. apu_w_are(are_idx++, base_reg + APU_ACC_CONFG_SET0, HW_CTRL_EN);
  124. apu_w_are(are_idx++, base_reg + APU_ACC_AUTO_CTRL_SET0, CLK_REQ_SW_EN);
  125. }
  126. }
  127. static void apu_pll_init(void)
  128. {
  129. uint32_t pll_base_arr[] = {MNOC_PLL_BASE, UP_PLL_BASE, MVPU_PLL_BASE, MDLA_PLL_BASE};
  130. int32_t pll_freq_out[] = {
  131. APUPLL0_DEFAULT_FREQ,
  132. APUPLL1_DEFAULT_FREQ,
  133. APUPLL2_DEFAULT_FREQ,
  134. APUPLL3_DEFAULT_FREQ
  135. };
  136. uint32_t pcw_val, posdiv_val;
  137. int pll_idx, are_idx;
  138. uint32_t base_reg;
  139. mmio_setbits_32(APUSYS_BASE + APU_ARE, ARE_RCX_AO_EN);
  140. mmio_setbits_32(APUSYS_BASE + APU_ARE_REG, ARE_RCX_AO_EN);
  141. mmio_write_32(APUSYS_BASE + APU_ARE + ARE_RCX_AO_CONFIG, ARE_ENTRY(RCX_AO_BEGIN) |
  142. (ARE_ENTRIES(RCX_AO_BEGIN, RCX_AO_END) << ARE_RCX_AO_CONFIG_HIGH_OFF));
  143. are_idx = PLL_ENTRY_BEGIN;
  144. for (pll_idx = 0 ; pll_idx < ARRAY_SIZE(pll_base_arr) ; pll_idx++) {
  145. base_reg = APUSYS_PLL + pll_base_arr[pll_idx];
  146. apu_w_are(are_idx++, base_reg + RG_PLLGP_LVR_REFSEL, RG_PLLGP_LVR_REFSEL_VAL);
  147. apu_w_are(are_idx++, base_reg + PLL1CPLL_FHCTL_HP_EN, FHCTL_CTRL);
  148. apu_w_are(are_idx++, base_reg + PLL1CPLL_FHCTL_RST_CON, FHCTL_NO_RESET);
  149. apu_w_are(are_idx++, base_reg + PLL1CPLL_FHCTL_CLK_CON, FHCTL_CLKEN);
  150. apu_w_are(are_idx++, base_reg + PLL1CPLL_FHCTL0_CFG,
  151. FHCTL_HOPPING_EN | FHCTL_SFSTR0_EN);
  152. posdiv_val = 0;
  153. pcw_val = 0;
  154. get_pll_pcw(pll_freq_out[pll_idx], &posdiv_val, &pcw_val);
  155. apu_w_are(are_idx++, base_reg + PLL1C_PLL1_CON1,
  156. ((0x1U << RG_PLL_SDM_PCW_CHG_OFF) |
  157. (posdiv_val << RG_PLL_POSDIV_OFF) | pcw_val));
  158. apu_w_are(are_idx++, base_reg + PLL1CPLL_FHCTL0_DDS,
  159. ((0x1U << FHCTL0_PLL_TGL_ORG) | pcw_val));
  160. }
  161. }
  162. static void apu_are_init(void)
  163. {
  164. int entry = 0;
  165. mmio_clrbits_32(APUSYS_BASE + APU_ARE, 0xFFFU << ARE_VCORE_OFF);
  166. mmio_setbits_32(APUSYS_BASE + APU_ARE, ARE_VCORE_EN);
  167. mmio_setbits_32(APUSYS_BASE + APU_ARE_REG, ARE_VCORE_EN);
  168. for (entry = ARE_CONF_START; entry < ARE_CONF_END; entry += 4)
  169. mmio_write_32(APUSYS_BASE + APU_ARE + entry, 0);
  170. }
  171. static void apu_rpclite_init(void)
  172. {
  173. uint32_t sleep_type_offset[] = {
  174. APU_RPC_SW_TYPE1_OFF,
  175. APU_RPC_SW_TYPE2_OFF,
  176. APU_RPC_SW_TYPE3_OFF,
  177. APU_RPC_SW_TYPE4_OFF
  178. };
  179. uint32_t rpc_lite_base[] = {
  180. APU_ACX0_RPC_LITE,
  181. APU_ACX1_RPC_LITE,
  182. APU_ACX2_RPC_LITE,
  183. };
  184. int ofs_idx, rpc_lite_idx;
  185. uint32_t base;
  186. for (rpc_lite_idx = 0; rpc_lite_idx < ARRAY_SIZE(rpc_lite_base); rpc_lite_idx++) {
  187. base = APUSYS_BASE + rpc_lite_base[rpc_lite_idx];
  188. for (ofs_idx = 0; ofs_idx < ARRAY_SIZE(sleep_type_offset); ofs_idx++)
  189. mmio_clrbits_32(base + sleep_type_offset[ofs_idx],
  190. SW_TYPE_MVPU_MDLA_RV);
  191. mmio_setbits_32(base + APU_RPC_TOP_SEL, TOP_SEL_VAL);
  192. }
  193. }
  194. static void apu_rpc_mdla_init(void)
  195. {
  196. mmio_clrbits_32(APUSYS_BASE + APU_RPCTOP_MDLA + APU_RPC_SW_TYPE0_OFF, SW_TYPE_MVPU_MDLA_RV);
  197. }
  198. static void apu_rpc_init(void)
  199. {
  200. mmio_write_32(APUSYS_RPC + APU_RPC_SW_TYPE0_OFF, RPC_TYPE_INIT_VAL);
  201. mmio_setbits_32(APUSYS_RPC + APU_RPC_TOP_SEL, RPC_TOP_SEL_VAL);
  202. #if !CFG_CTL_RPC_BY_CE
  203. mmio_clrbits_32(APUSYS_RPC + APU_RPC_TOP_SEL, CE_ENABLE);
  204. #endif
  205. mmio_setbits_32(APUSYS_RPC + APU_RPC_TOP_SEL_1, BUCK_PROT_SEL);
  206. }
  207. static int apu_pcu_init(void)
  208. {
  209. uint32_t pmif_id = 0x0;
  210. uint32_t slave_id = BUCK_VAPU_PMIC_ID;
  211. uint32_t en_set_offset = BUCK_VAPU_PMIC_REG_EN_SET_ADDR;
  212. uint32_t en_clr_offset = BUCK_VAPU_PMIC_REG_EN_CLR_ADDR;
  213. uint32_t en_shift = BUCK_VAPU_PMIC_REG_EN_SHIFT;
  214. #if SPMI_ENABLE
  215. struct spmi_device *vsram_sdev;
  216. #endif
  217. unsigned char vsram = 0;
  218. mmio_write_32(APUSYS_PCU + APU_PCUTOP_CTRL_SET, AUTO_BUCK_EN);
  219. mmio_write_32((APUSYS_PCU + APU_PCU_BUCK_STEP_SEL), BUCK_STEP_SEL_VAL);
  220. #if SPMI_ENABLE
  221. vsram_sdev = get_spmi_device(SPMI_MASTER_1, SPMI_SLAVE_4);
  222. if (!vsram_sdev) {
  223. ERROR("[APUPW] VSRAM BUCK4 get device fail\n");
  224. return -1;
  225. }
  226. if (spmi_ext_register_readl(vsram_sdev, MT6363_RG_BUCK_VBUCK4_VOSEL_ADDR, &vsram, 1)) {
  227. ERROR("[APUPW] VSRAM BUCK4 read fail\n");
  228. return -1;
  229. }
  230. #endif
  231. mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_ON_DAT0_L,
  232. (BUCK_VAPU_PMIC_REG_VOSEL_ADDR << PMIC_OFF_ADDR_OFF) | vsram);
  233. mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_ON_DAT0_H,
  234. (slave_id << PMIC_SLVID_OFF) | (pmif_id << PMIC_PMIFID_OFF) | PCU_CMD_OP_W);
  235. mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_ON_DAT1_L,
  236. (en_set_offset << PMIC_OFF_ADDR_OFF) | (0x1U << en_shift));
  237. mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_ON_DAT1_H,
  238. (slave_id << PMIC_SLVID_OFF) | (pmif_id << PMIC_PMIFID_OFF) | PCU_CMD_OP_W);
  239. mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_OFF_DAT0_L,
  240. (en_clr_offset << PMIC_OFF_ADDR_OFF) | (0x1U << en_shift));
  241. mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_OFF_DAT0_H,
  242. (slave_id << PMIC_SLVID_OFF) | (pmif_id << PMIC_PMIFID_OFF) | PCU_CMD_OP_W);
  243. mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_ON_SLE0, 0);
  244. mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_ON_SLE1, VAPU_BUCK_ON_SETTLE_TIME);
  245. return 0;
  246. }
  247. static void apu_aoc_init(void)
  248. {
  249. uint32_t reg;
  250. mmio_setbits_32(SPM_BASE + 0xF6C, BIT(4));
  251. mmio_clrbits_32(SPM_BASE + 0x414, BIT(1));
  252. mmio_write_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_CONFIG, APUSYS_AO_SRAM_EN);
  253. udelay(1);
  254. reg = APUSYS_AO_CTL + APUSYS_AO_SRAM_SET;
  255. #if !CFG_CTL_RPC_BY_CE
  256. mmio_setbits_32(reg, BIT(8));
  257. udelay(1);
  258. mmio_setbits_32(reg, BIT(11));
  259. udelay(1);
  260. mmio_setbits_32(reg, BIT(13));
  261. udelay(1);
  262. mmio_clrbits_32(reg, BIT(8));
  263. udelay(1);
  264. mmio_clrbits_32(reg, BIT(11));
  265. udelay(1);
  266. mmio_clrbits_32(reg, BIT(13));
  267. #else
  268. mmio_setbits_32(reg, BIT(9));
  269. mmio_setbits_32(reg, BIT(12));
  270. mmio_setbits_32(reg, BIT(14));
  271. mmio_clrbits_32(reg, BIT(9));
  272. mmio_clrbits_32(reg, BIT(12));
  273. mmio_clrbits_32(reg, BIT(14));
  274. udelay(1);
  275. #endif
  276. reg = APUSYS_RPC + APU_RPC_HW_CON;
  277. mmio_write_32(reg, BUCK_ELS_EN_CLR);
  278. udelay(1);
  279. mmio_write_32(reg, BUCK_AO_RST_B_SET);
  280. udelay(1);
  281. mmio_write_32(reg, BUCK_PROT_REQ_CLR);
  282. udelay(1);
  283. mmio_write_32(reg, SRAM_AOC_ISO_CLR);
  284. udelay(1);
  285. mmio_write_32(reg, PLL_AOC_ISO_EN_CLR);
  286. udelay(1);
  287. }
  288. static int init_hw_setting(void)
  289. {
  290. int ret;
  291. apu_aoc_init();
  292. ret = apu_pcu_init();
  293. apu_rpc_init();
  294. apu_rpc_mdla_init();
  295. apu_rpclite_init();
  296. apu_are_init();
  297. apu_pll_init();
  298. apu_acc_init();
  299. apu_buck_off_cfg();
  300. return ret;
  301. }
  302. int apusys_power_init(void)
  303. {
  304. int ret;
  305. ret = init_hw_setting();
  306. if (ret != 0)
  307. ERROR("%s init HW failed\n", __func__);
  308. else
  309. INFO("%s init HW done\n", __func__);
  310. mmio_write_32(APU_ACE_HW_FLAG_DIS, APU_ACE_DIS_FLAG_VAL);
  311. return ret;
  312. }