ihost_pll_config.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /*
  2. * Copyright (c) 2016-2020, Broadcom
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <stdint.h>
  7. #include <common/debug.h>
  8. #include <lib/mmio.h>
  9. #include <dmu.h>
  10. #define IHOST0_CONFIG_ROOT 0x66000000
  11. #define IHOST1_CONFIG_ROOT 0x66002000
  12. #define IHOST2_CONFIG_ROOT 0x66004000
  13. #define IHOST3_CONFIG_ROOT 0x66006000
  14. #define A72_CRM_PLL_PWR_ON 0x00000070
  15. #define A72_CRM_PLL_PWR_ON__PLL0_RESETB_R 4
  16. #define A72_CRM_PLL_PWR_ON__PLL0_POST_RESETB_R 5
  17. #define A72_CRM_PLL_CHNL_BYPS_EN 0x000000ac
  18. #define A72_CRM_PLL_CHNL_BYPS_EN__PLL_0_CHNL_0_BYPS_EN_R 0
  19. #define A72_CRM_PLL_CHNL_BYPS_EN_DATAMASK 0x0000ec1f
  20. #define A72_CRM_PLL_CMD 0x00000080
  21. #define A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_VCO_R 0
  22. #define A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_POST_R 1
  23. #define A72_CRM_PLL_STATUS 0x00000084
  24. #define A72_CRM_PLL_STATUS__PLL0_LOCK_R 9
  25. #define A72_CRM_PLL0_CTRL1 0x00000100
  26. #define A72_CRM_PLL0_CTRL2 0x00000104
  27. #define A72_CRM_PLL0_CTRL3 0x00000108
  28. #define A72_CRM_PLL0_CTRL3__PLL0_PDIV_R 12
  29. #define A72_CRM_PLL0_CTRL4 0x0000010c
  30. #define A72_CRM_PLL0_CTRL4__PLL0_KP_R 0
  31. #define A72_CRM_PLL0_CTRL4__PLL0_KI_R 4
  32. #define A72_CRM_PLL0_CTRL4__PLL0_KA_R 7
  33. #define A72_CRM_PLL0_CTRL4__PLL0_FREFEFF_INFO_R 10
  34. #define PLL_MODE_VCO 0x0
  35. #define PLL_MODE_BYPASS 0x1
  36. #define PLL_RESET_TYPE_PLL 0x1
  37. #define PLL_RESET_TYPE_POST 0x2
  38. #define PLL_VCO 0x1
  39. #define PLL_POSTDIV 0x2
  40. #define ARM_FREQ_3G PLL_FREQ_FULL
  41. #define ARM_FREQ_1P5G PLL_FREQ_HALF
  42. #define ARM_FREQ_750M PLL_FREQ_QRTR
  43. static unsigned int ARMCOE_crm_getBaseAddress(unsigned int cluster_num)
  44. {
  45. unsigned int ihostx_config_root;
  46. switch (cluster_num) {
  47. case 0:
  48. default:
  49. ihostx_config_root = IHOST0_CONFIG_ROOT;
  50. break;
  51. case 1:
  52. ihostx_config_root = IHOST1_CONFIG_ROOT;
  53. break;
  54. case 2:
  55. ihostx_config_root = IHOST2_CONFIG_ROOT;
  56. break;
  57. case 3:
  58. ihostx_config_root = IHOST3_CONFIG_ROOT;
  59. break;
  60. }
  61. return ihostx_config_root;
  62. }
  63. static void ARMCOE_crm_pllAssertReset(unsigned int cluster_num,
  64. unsigned int reset_type)
  65. {
  66. unsigned long ihostx_config_root;
  67. unsigned int pll_rst_ctrl;
  68. ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
  69. pll_rst_ctrl = mmio_read_32(ihostx_config_root + A72_CRM_PLL_PWR_ON);
  70. // PLL reset
  71. if (reset_type & PLL_RESET_TYPE_PLL) {
  72. pll_rst_ctrl &= ~(0x1<<A72_CRM_PLL_PWR_ON__PLL0_RESETB_R);
  73. }
  74. // post-div channel reset
  75. if (reset_type & PLL_RESET_TYPE_POST) {
  76. pll_rst_ctrl &= ~(0x1<<A72_CRM_PLL_PWR_ON__PLL0_POST_RESETB_R);
  77. }
  78. mmio_write_32(ihostx_config_root + A72_CRM_PLL_PWR_ON, pll_rst_ctrl);
  79. }
  80. static void ARMCOE_crm_pllSetMode(unsigned int cluster_num, unsigned int mode)
  81. {
  82. unsigned long ihostx_config_root;
  83. unsigned int pll_byp_ctrl;
  84. ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
  85. pll_byp_ctrl = mmio_read_32(ihostx_config_root +
  86. A72_CRM_PLL_CHNL_BYPS_EN);
  87. if (mode == PLL_MODE_VCO) {
  88. // use PLL DCO output
  89. pll_byp_ctrl &=
  90. ~BIT(A72_CRM_PLL_CHNL_BYPS_EN__PLL_0_CHNL_0_BYPS_EN_R);
  91. } else {
  92. // use PLL bypass sources
  93. pll_byp_ctrl |=
  94. BIT(A72_CRM_PLL_CHNL_BYPS_EN__PLL_0_CHNL_0_BYPS_EN_R);
  95. }
  96. mmio_write_32(ihostx_config_root + A72_CRM_PLL_CHNL_BYPS_EN,
  97. pll_byp_ctrl);
  98. }
  99. static void ARMCOE_crm_pllFreqSet(unsigned int cluster_num,
  100. unsigned int ihost_pll_freq_sel,
  101. unsigned int pdiv)
  102. {
  103. unsigned int ndiv_int;
  104. unsigned int ndiv_frac_low, ndiv_frac_high;
  105. unsigned long ihostx_config_root;
  106. ndiv_frac_low = 0x0;
  107. ndiv_frac_high = 0x0;
  108. if (ihost_pll_freq_sel == ARM_FREQ_3G) {
  109. ndiv_int = 0x78;
  110. } else if (ihost_pll_freq_sel == ARM_FREQ_1P5G) {
  111. ndiv_int = 0x3c;
  112. } else if (ihost_pll_freq_sel == ARM_FREQ_750M) {
  113. ndiv_int = 0x1e;
  114. } else {
  115. return;
  116. }
  117. ndiv_int &= 0x3FF; // low 10 bits
  118. ndiv_frac_low &= 0x3FF;
  119. ndiv_frac_high &= 0x3FF;
  120. ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
  121. mmio_write_32(ihostx_config_root+A72_CRM_PLL0_CTRL1, ndiv_frac_low);
  122. mmio_write_32(ihostx_config_root+A72_CRM_PLL0_CTRL2, ndiv_frac_high);
  123. mmio_write_32(ihostx_config_root+A72_CRM_PLL0_CTRL3,
  124. ndiv_int |
  125. ((pdiv << A72_CRM_PLL0_CTRL3__PLL0_PDIV_R & 0xF000)));
  126. mmio_write_32(ihostx_config_root + A72_CRM_PLL0_CTRL4,
  127. /* From Section 10 of PLL spec */
  128. (3 << A72_CRM_PLL0_CTRL4__PLL0_KP_R) |
  129. /* From Section 10 of PLL spec */
  130. (2 << A72_CRM_PLL0_CTRL4__PLL0_KI_R) |
  131. /* Normal mode (i.e. not fast-locking) */
  132. (0 << A72_CRM_PLL0_CTRL4__PLL0_KA_R) |
  133. /* 50 MHz */
  134. (50 << A72_CRM_PLL0_CTRL4__PLL0_FREFEFF_INFO_R));
  135. }
  136. static void ARMCOE_crm_pllDeassertReset(unsigned int cluster_num,
  137. unsigned int reset_type)
  138. {
  139. unsigned long ihostx_config_root;
  140. unsigned int pll_rst_ctrl;
  141. ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
  142. pll_rst_ctrl = mmio_read_32(ihostx_config_root + A72_CRM_PLL_PWR_ON);
  143. // PLL reset
  144. if (reset_type & PLL_RESET_TYPE_PLL) {
  145. pll_rst_ctrl |= (0x1 << A72_CRM_PLL_PWR_ON__PLL0_RESETB_R);
  146. }
  147. // post-div channel reset
  148. if (reset_type & PLL_RESET_TYPE_POST) {
  149. pll_rst_ctrl |= (0x1 << A72_CRM_PLL_PWR_ON__PLL0_POST_RESETB_R);
  150. }
  151. mmio_write_32(ihostx_config_root + A72_CRM_PLL_PWR_ON, pll_rst_ctrl);
  152. }
  153. static void ARMCOE_crm_pllUpdate(unsigned int cluster_num, unsigned int type)
  154. {
  155. unsigned long ihostx_config_root;
  156. unsigned int pll_cmd;
  157. ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
  158. pll_cmd = mmio_read_32(ihostx_config_root + A72_CRM_PLL_CMD);
  159. // VCO update
  160. if (type & PLL_VCO) {
  161. pll_cmd |= BIT(A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_VCO_R);
  162. }
  163. // post-div channel update
  164. if (type & PLL_POSTDIV) {
  165. pll_cmd |= BIT(A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_POST_R);
  166. }
  167. mmio_write_32(ihostx_config_root+A72_CRM_PLL_CMD, pll_cmd);
  168. }
  169. static void insert_delay(unsigned int delay)
  170. {
  171. volatile unsigned int index;
  172. for (index = 0; index < delay; index++)
  173. ;
  174. }
  175. /*
  176. * Returns 1 if PLL locked within certain interval
  177. */
  178. static unsigned int ARMCOE_crm_pllIsLocked(unsigned int cluster_num)
  179. {
  180. unsigned long ihostx_config_root;
  181. unsigned int lock_status;
  182. unsigned int i;
  183. ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
  184. /* wait a while for pll to lock before returning from this function */
  185. for (i = 0; i < 1500; i++) {
  186. insert_delay(256);
  187. lock_status = mmio_read_32(ihostx_config_root +
  188. A72_CRM_PLL_STATUS);
  189. if (lock_status & BIT(A72_CRM_PLL_STATUS__PLL0_LOCK_R))
  190. return 1;
  191. }
  192. ERROR("PLL of Cluster #%u failed to lock\n", cluster_num);
  193. return 0;
  194. }
  195. /*
  196. * ihost PLL Variable Frequency Configuration
  197. *
  198. * Frequency Limit {VCO,ARM} (GHz):
  199. * 0 - no limit,
  200. * 1 - {3.0,1.5},
  201. * 2 - {4.0,2.0},
  202. * 3 - {5.0,2.5}
  203. */
  204. uint32_t bcm_set_ihost_pll_freq(uint32_t cluster_num, int ihost_pll_freq_sel)
  205. {
  206. NOTICE("cluster: %u, freq_sel:0x%x\n", cluster_num, ihost_pll_freq_sel);
  207. //bypass PLL
  208. ARMCOE_crm_pllSetMode(cluster_num, PLL_MODE_BYPASS);
  209. //assert reset
  210. ARMCOE_crm_pllAssertReset(cluster_num,
  211. PLL_RESET_TYPE_PLL | PLL_RESET_TYPE_POST);
  212. //set ndiv_int for different freq
  213. ARMCOE_crm_pllFreqSet(cluster_num, ihost_pll_freq_sel, 0x1);
  214. //de-assert reset
  215. ARMCOE_crm_pllDeassertReset(cluster_num, PLL_RESET_TYPE_PLL);
  216. ARMCOE_crm_pllUpdate(cluster_num, PLL_VCO);
  217. //waiting for PLL lock
  218. ARMCOE_crm_pllIsLocked(cluster_num);
  219. ARMCOE_crm_pllDeassertReset(cluster_num, PLL_RESET_TYPE_POST);
  220. //disable bypass PLL
  221. ARMCOE_crm_pllSetMode(cluster_num, PLL_MODE_VCO);
  222. return 0;
  223. }
  224. uint32_t bcm_get_ihost_pll_freq(uint32_t cluster_num)
  225. {
  226. unsigned long ihostx_config_root;
  227. uint32_t ndiv_int;
  228. uint32_t ihost_pll_freq_sel;
  229. ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
  230. ndiv_int = mmio_read_32(ihostx_config_root+A72_CRM_PLL0_CTRL3) & 0x3FF;
  231. if (ndiv_int == 0x78) {
  232. ihost_pll_freq_sel = ARM_FREQ_3G;
  233. } else if (ndiv_int == 0x3c) {
  234. ihost_pll_freq_sel = ARM_FREQ_1P5G;
  235. } else if (ndiv_int == 0x1e) {
  236. ihost_pll_freq_sel = ARM_FREQ_750M;
  237. } else {
  238. /* return unlimit otherwise*/
  239. ihost_pll_freq_sel = 0;
  240. }
  241. return ihost_pll_freq_sel;
  242. }