apupwr_clkctl.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. /*
  2. * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <errno.h>
  7. #include <arch_helpers.h>
  8. #include <common/debug.h>
  9. #include <drivers/delay_timer.h>
  10. #include <apupwr_clkctl.h>
  11. #include <apupwr_clkctl_def.h>
  12. #include <mtk_plat_common.h>
  13. #include <platform_def.h>
  14. /* 8195 use PCW mode to change freq directly */
  15. enum pll_set_rate_mode PLL_MODE = CON0_PCW;
  16. char *buck_domain_str[APUSYS_BUCK_DOMAIN_NUM] = {
  17. "V_VPU0",
  18. "V_VPU1",
  19. "V_MDLA0",
  20. "V_MDLA1",
  21. "V_APU_CONN",
  22. "V_TOP_IOMMU",
  23. "V_VCORE",
  24. };
  25. uint32_t aacc_set[APUSYS_BUCK_DOMAIN_NUM] = {
  26. APU_ACC_CONFG_SET1, APU_ACC_CONFG_SET2,
  27. APU_ACC_CONFG_SET4, APU_ACC_CONFG_SET5,
  28. APU_ACC_CONFG_SET0, APU_ACC_CONFG_SET7
  29. };
  30. uint32_t aacc_clr[APUSYS_BUCK_DOMAIN_NUM] = {
  31. APU_ACC_CONFG_CLR1, APU_ACC_CONFG_CLR2,
  32. APU_ACC_CONFG_CLR4, APU_ACC_CONFG_CLR5,
  33. APU_ACC_CONFG_CLR0, APU_ACC_CONFG_CLR7
  34. };
  35. struct reg_seq {
  36. uint32_t address;
  37. uint32_t val;
  38. };
  39. static const struct reg_seq init_acc_cfg[] = {
  40. { APU_ACC_CONFG_SET0, BIT(BIT_SEL_APU) },
  41. { APU_ACC_CONFG_CLR0, BIT(BIT_CGEN_SOC) },
  42. { APU_ACC_CONFG_SET0, BIT(BIT_SEL_APU_DIV2) },
  43. { APU_ACC_CONFG_SET7, BIT(BIT_SEL_APU) },
  44. { APU_ACC_CONFG_CLR7, BIT(BIT_CGEN_SOC) },
  45. { APU_ACC_CONFG_SET7, BIT(BIT_SEL_APU_DIV2) },
  46. { APU_ACC_CONFG_SET1, BIT(BIT_SEL_APU) },
  47. { APU_ACC_CONFG_CLR1, BIT(BIT_CGEN_SOC) },
  48. { APU_ACC_CONFG_SET1, BIT(BIT_SEL_APU_DIV2) },
  49. { APU_ACC_CONFG_SET2, BIT(BIT_INVEN_OUT) },
  50. { APU_ACC_CONFG_SET2, BIT(BIT_SEL_APU) },
  51. { APU_ACC_CONFG_CLR2, BIT(BIT_CGEN_SOC) },
  52. { APU_ACC_CONFG_SET2, BIT(BIT_SEL_APU_DIV2) },
  53. { APU_ACC_CONFG_SET4, BIT(BIT_SEL_APU) },
  54. { APU_ACC_CONFG_CLR4, BIT(BIT_CGEN_SOC) },
  55. { APU_ACC_CONFG_SET4, BIT(BIT_SEL_APU_DIV2) },
  56. { APU_ACC_CONFG_SET5, BIT(BIT_INVEN_OUT) },
  57. { APU_ACC_CONFG_SET5, BIT(BIT_SEL_APU) },
  58. { APU_ACC_CONFG_CLR5, BIT(BIT_CGEN_SOC) },
  59. { APU_ACC_CONFG_SET5, BIT(BIT_SEL_APU_DIV2) },
  60. };
  61. int32_t apupwr_smc_acc_init_all(void)
  62. {
  63. int32_t i;
  64. for (i = 0; i < ARRAY_SIZE(init_acc_cfg); i++) {
  65. apupwr_writel(init_acc_cfg[i].val,
  66. init_acc_cfg[i].address);
  67. }
  68. /* Deault ACC will raise APU_DIV_2 */
  69. apupwr_smc_pll_set_rate(BUCK_VCONN_DOMAIN_DEFAULT_FREQ,
  70. true, V_APU_CONN);
  71. apupwr_smc_pll_set_rate(BUCK_VCONN_DOMAIN_DEFAULT_FREQ,
  72. true, V_TOP_IOMMU);
  73. apupwr_smc_pll_set_rate(BUCK_VVPU_DOMAIN_DEFAULT_FREQ,
  74. true, V_VPU0);
  75. apupwr_smc_pll_set_rate(BUCK_VMDLA_DOMAIN_DEFAULT_FREQ,
  76. true, V_MDLA0);
  77. return 0;
  78. }
  79. void apupwr_smc_acc_top(bool enable)
  80. {
  81. if (enable) {
  82. apupwr_writel(BIT(BIT_CGEN_APU), aacc_set[V_APU_CONN]);
  83. apupwr_writel(BIT(BIT_CGEN_APU), aacc_set[V_TOP_IOMMU]);
  84. } else {
  85. apupwr_writel(BIT(BIT_CGEN_APU), aacc_clr[V_APU_CONN]);
  86. apupwr_writel(BIT(BIT_CGEN_APU), aacc_clr[V_TOP_IOMMU]);
  87. }
  88. }
  89. /*
  90. * acc_clk_set_parent:ACC MUX select
  91. * 0. freq parameters here, only ACC clksrc is valid
  92. * 1. Switch between APUPLL <=> Parking (F26M, PARK)
  93. * 2. Turn on/off CG_F26M, CG_PARK, CG_SOC, but no CG_APU
  94. * 3. Clear APU Div2 while Parking
  95. * 4. Only use clksrc of APUPLL while ACC CG_APU is on
  96. */
  97. int32_t apupwr_smc_acc_set_parent(uint32_t freq, uint32_t domain)
  98. {
  99. uint32_t acc_set = 0;
  100. uint32_t acc_clr = 0;
  101. int32_t ret = 0;
  102. if (freq > DVFS_FREQ_ACC_APUPLL) {
  103. ERROR("%s wrong clksrc: %d\n", __func__, freq);
  104. ret = -EIO;
  105. goto err;
  106. }
  107. switch (domain) {
  108. case V_VPU1:
  109. case V_VPU0:
  110. case V_MDLA1:
  111. case V_MDLA0:
  112. case V_APU_CONN:
  113. case V_TOP_IOMMU:
  114. acc_set = aacc_set[domain];
  115. acc_clr = aacc_clr[domain];
  116. break;
  117. default:
  118. ret = -EIO;
  119. break;
  120. }
  121. /* Select park source */
  122. switch (freq) {
  123. case DVFS_FREQ_ACC_PARKING:
  124. /* Select park source */
  125. apupwr_writel(BIT(BIT_SEL_PARK), acc_set);
  126. apupwr_writel(BIT(BIT_SEL_F26M), acc_clr);
  127. /* Enable park cg */
  128. apupwr_writel(BIT(BIT_CGEN_PARK), acc_set);
  129. apupwr_writel(BIT(BIT_CGEN_F26M) | BIT(BIT_CGEN_SOC), acc_clr);
  130. /* Select park path */
  131. apupwr_writel(BIT(BIT_SEL_APU), acc_clr);
  132. /* clear apu div 2 */
  133. apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_clr);
  134. break;
  135. case DVFS_FREQ_ACC_APUPLL:
  136. /* Select park path */
  137. apupwr_writel(BIT(BIT_SEL_APU), acc_set);
  138. /* Clear park cg */
  139. apupwr_writel(BIT(BIT_CGEN_PARK) | BIT(BIT_CGEN_F26M) |
  140. BIT(BIT_CGEN_SOC), acc_clr);
  141. break;
  142. case DVFS_FREQ_ACC_SOC:
  143. /* Select park source */
  144. apupwr_writel(BIT(BIT_SEL_PARK), acc_clr);
  145. apupwr_writel(BIT(BIT_SEL_F26M), acc_clr);
  146. /* Enable park cg */
  147. apupwr_writel(BIT(BIT_CGEN_SOC), acc_set);
  148. apupwr_writel(BIT(BIT_CGEN_F26M) | BIT(BIT_CGEN_PARK), acc_clr);
  149. /* Select park path */
  150. apupwr_writel(BIT(BIT_SEL_APU), acc_clr);
  151. /* clear apu div 2 */
  152. apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_clr);
  153. break;
  154. case DVFS_FREQ_ACC_26M:
  155. case DVFS_FREQ_NOT_SUPPORT:
  156. default:
  157. /* Select park source */
  158. apupwr_writel(BIT(BIT_SEL_F26M), acc_set);
  159. apupwr_writel(BIT(BIT_SEL_PARK), acc_clr);
  160. /* Enable park cg */
  161. apupwr_writel(BIT(BIT_CGEN_F26M), acc_set);
  162. apupwr_writel(BIT(BIT_CGEN_PARK) | BIT(BIT_CGEN_SOC), acc_clr);
  163. /* Select park path */
  164. apupwr_writel(BIT(BIT_SEL_APU), acc_clr);
  165. /* clear apu div 2 */
  166. apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_clr);
  167. ERROR("[APUPWR] %s wrong ACC clksrc : %d, force assign 26M\n",
  168. __func__, freq);
  169. break;
  170. }
  171. err:
  172. return ret;
  173. }
  174. int32_t apupwr_smc_pll_set_rate(uint32_t freq, bool div2, uint32_t domain)
  175. {
  176. int32_t ret = 0;
  177. uint32_t acc_set0 = 0, acc_set1 = 0;
  178. if (freq > DVFS_FREQ_MAX) {
  179. ERROR("%s wrong freq: %d\n", __func__, freq);
  180. ret = -EIO;
  181. goto err;
  182. }
  183. /*
  184. * Switch to Parking src
  185. * 1. Need to switch out all ACCs sharing the same apupll
  186. */
  187. switch (domain) {
  188. case V_MDLA0:
  189. case V_MDLA1:
  190. acc_set0 = APU_ACC_CONFG_SET4;
  191. acc_set1 = APU_ACC_CONFG_SET5;
  192. ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
  193. V_MDLA0);
  194. ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
  195. V_MDLA1);
  196. break;
  197. case V_VPU0:
  198. case V_VPU1:
  199. acc_set0 = APU_ACC_CONFG_SET1;
  200. acc_set1 = APU_ACC_CONFG_SET2;
  201. ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
  202. V_VPU0);
  203. ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
  204. V_VPU1);
  205. break;
  206. case V_APU_CONN:
  207. acc_set0 = APU_ACC_CONFG_SET0;
  208. ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
  209. V_APU_CONN);
  210. break;
  211. case V_TOP_IOMMU:
  212. acc_set0 = APU_ACC_CONFG_SET7;
  213. ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
  214. V_TOP_IOMMU);
  215. break;
  216. default:
  217. ERROR("[APUPWR] %s %d invalid domain (%d)\n",
  218. __func__, __LINE__, domain);
  219. ret = -EIO;
  220. goto err;
  221. }
  222. anpu_pll_set_rate(domain, PLL_MODE, (div2) ? (freq * 2) : freq);
  223. if (div2) {
  224. apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_set0);
  225. if (acc_set1) {
  226. apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_set1);
  227. }
  228. }
  229. /*
  230. * Switch back to APUPLL
  231. * Only switch back to APUPLL while CG_APU on
  232. * And clksrc is not APUPLL
  233. */
  234. switch (domain) {
  235. case V_VPU0:
  236. case V_VPU1:
  237. if ((apupwr_readl(acc_set0) & BIT(BIT_CGEN_APU)) &&
  238. !(apupwr_readl(acc_set0) & BIT(BIT_SEL_APU))) {
  239. ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL,
  240. V_VPU0);
  241. }
  242. if ((apupwr_readl(acc_set1) & BIT(BIT_CGEN_APU)) &&
  243. !(apupwr_readl(acc_set1) & BIT(BIT_SEL_APU))) {
  244. ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL,
  245. V_VPU1);
  246. }
  247. break;
  248. case V_MDLA0:
  249. case V_MDLA1:
  250. if ((apupwr_readl(acc_set0) & BIT(BIT_CGEN_APU)) &&
  251. !(apupwr_readl(acc_set0) & BIT(BIT_SEL_APU))) {
  252. ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL,
  253. V_MDLA0);
  254. }
  255. if ((apupwr_readl(acc_set1) & BIT(BIT_CGEN_APU)) &&
  256. !(apupwr_readl(acc_set1) & BIT(BIT_SEL_APU))) {
  257. ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL,
  258. V_MDLA1);
  259. }
  260. break;
  261. case V_APU_CONN:
  262. case V_TOP_IOMMU:
  263. if ((apupwr_readl(acc_set0) & BIT(BIT_CGEN_APU)) &&
  264. !(apupwr_readl(acc_set0) & BIT(BIT_SEL_APU))) {
  265. ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL,
  266. domain);
  267. }
  268. break;
  269. default:
  270. ERROR("[APUPWR] %s %d invalid domain (%d)\n",
  271. __func__, __LINE__, domain);
  272. ret = -EIO;
  273. break;
  274. }
  275. INFO("[%s][%d] set domain %d to freq %d\n",
  276. __func__, __LINE__, domain, (div2) ? (freq * 2) : freq);
  277. err:
  278. return ret;
  279. }
  280. int32_t apupwr_smc_bulk_pll(bool enable)
  281. {
  282. int32_t ret = 0;
  283. int32_t pll_idx;
  284. if (enable) {
  285. for (pll_idx = APUPLL; pll_idx < APUPLL_MAX; pll_idx++) {
  286. ret = apu_pll_enable(pll_idx, enable, false);
  287. if (ret != 0) {
  288. goto err;
  289. }
  290. }
  291. } else {
  292. for (pll_idx = APUPLL2; pll_idx >= APUPLL; pll_idx--) {
  293. ret = apu_pll_enable(pll_idx, enable, false);
  294. if (ret != 0) {
  295. goto err;
  296. }
  297. }
  298. }
  299. err:
  300. return ret;
  301. }
  302. void apupwr_smc_bus_prot_cg_on(void)
  303. {
  304. apupwr_clrbits(AO_MD32_MNOC_MASK, APU_CSR_DUMMY_0);
  305. }