clock.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. #include "FreeRTOS.h"
  2. #include "chip.h"
  3. #include "board.h"
  4. #define PLL_BYPASS (1 << 30)
  5. #define PLL_FOUTVCOPD (1 << 29)
  6. #define PLL_FOUTPOSTDIVPD (1 << 28)
  7. #define PLL_DSMPD (1 << 27)
  8. #define PLL_PD (1 << 26)
  9. #define PLL_POSTDIV2_OFFSET (23)
  10. #define PLL_POSTDIV2_MASK (0x7)
  11. #define PLL_POSTDIV1_OFFSET (20)
  12. #define PLL_POSTDIV1_MASK (0x7)
  13. #define PLL_FBDIV_OFFSET (8)
  14. #define PLL_FBDIV_MASK (0xfff)
  15. #define PLL_REFDIV_OFFSET (0)
  16. #define PLL_REFDIV_MASK (0x3f)
  17. typedef struct {
  18. uint32_t clkid;
  19. uint32_t clktype;
  20. uint32_t source;
  21. int clksource[MAX_CLK_SOURCE_NUM];
  22. int source_index;
  23. int div;
  24. uint32_t enable_reg[MAX_CLK_ENABLE_BITS];
  25. int enable_offset[MAX_CLK_ENABLE_BITS];
  26. int enable_bits;
  27. union {
  28. uint32_t fixed_freq;
  29. struct {
  30. int div;
  31. int mult;
  32. } fixed_fator_property;
  33. struct {
  34. uint32_t cfgreg;
  35. uint32_t sup_sprd;
  36. } pll_property;
  37. struct {
  38. uint32_t cfgreg;
  39. uint32_t analogreg;
  40. } dds_property;
  41. struct {
  42. uint32_t cfgreg;
  43. int index_offset;
  44. int index_value;
  45. uint32_t index_mask;
  46. int div_offset;
  47. int div_value;
  48. uint32_t div_mask;
  49. int div_mode;
  50. uint32_t inv_reg;
  51. int inv_offset;
  52. uint32_t inv_mask;
  53. int inv_value;
  54. } sys_property;
  55. } u;
  56. } xClockProperty;
  57. xClockProperty xClocks[] = {
  58. {.clkid = CLK_XTAL32K, .clktype = FIXED_CLOCK, .u.fixed_freq = 32768},
  59. {.clkid = CLK_XTAL24M, .clktype = FIXED_CLOCK, .u.fixed_freq = 24000000},
  60. {.clkid = CLK_CPUPLL, .clktype = PLL_CLOCK, .clksource = {CLK_XTAL24M},
  61. .u.pll_property.cfgreg = REGS_SYSCTL_BASE + SYS_CPUPLL_CFG,
  62. .u.pll_property.sup_sprd = 0},
  63. {.clkid = CLK_SYSPLL, .clktype = PLL_CLOCK, .clksource = {CLK_XTAL24M},
  64. .u.pll_property.cfgreg = REGS_SYSCTL_BASE + SYS_SYSPLL_CFG,
  65. .u.pll_property.sup_sprd = 1},
  66. {.clkid = CLK_VPUPLL, .clktype = PLL_CLOCK, .clksource = {CLK_XTAL24M},
  67. .u.pll_property.cfgreg = REGS_SYSCTL_BASE + SYS_VPUPLL_CFG,
  68. .u.pll_property.sup_sprd = 1},
  69. {.clkid = CLK_DDRPLL, .clktype = PLL_CLOCK, .clksource = {CLK_XTAL24M},
  70. .u.pll_property.cfgreg = REGS_SYSCTL_BASE + SYS_DDRPLL_CFG,
  71. .u.pll_property.sup_sprd = 0},
  72. {.clkid = CLK_MFCPLL, .clktype = PLL_CLOCK, .clksource = {CLK_XTAL24M},
  73. .u.pll_property.cfgreg = REGS_SYSCTL_BASE + SYS_MFCPLL_CFG,
  74. .u.pll_property.sup_sprd = 0},
  75. {.clkid = CLK_AHBPLL, .clktype = PLL_CLOCK, .clksource = {CLK_XTAL24M},
  76. .u.pll_property.cfgreg = REGS_SYSCTL_BASE + SYS_AHBPLL_CFG,
  77. .u.pll_property.sup_sprd = 1},
  78. {.clkid = CLK_GPUPLL, .clktype = PLL_CLOCK, .clksource = {CLK_XTAL24M},
  79. .u.pll_property.cfgreg = REGS_SYSCTL_BASE + SYS_GPUPLL_CFG,
  80. .u.pll_property.sup_sprd = 0},
  81. {.clkid = CLK_DDR, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_DDRPLL},
  82. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_BUS_CLK_CFG, .u.sys_property.index_offset = 1,
  83. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = -1 },
  84. {.clkid = CLK_CPU, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_CPUPLL},
  85. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_BUS_CLK_CFG, .u.sys_property.index_offset = 0,
  86. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = -1 },
  87. {.clkid = CLK_AXI, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_SYSPLL},
  88. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_BUS_CLK_CFG, .u.sys_property.index_offset = 2,
  89. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = -1 },
  90. {.clkid = CLK_AHB, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_AHBPLL},
  91. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_BUS_CLK_CFG, .u.sys_property.index_offset = 3,
  92. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = -1 },
  93. {.clkid = CLK_APB, .clktype = SYS_CLOCK, .clksource = {CLK_AHB},
  94. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_BUS_CLK_CFG, .u.sys_property.div_offset = 4,
  95. .u.sys_property.div_mask = 3, .u.sys_property.div_value = -1,
  96. .u.sys_property.div_mode = DIVMODE_EXPONENT},
  97. {.clkid = CLK_LCD, .clktype = SYS_CLOCK, .clksource = {CLK_SYSPLL, CLK_VPUPLL, CLK_XTAL24M},
  98. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN, REGS_SYSCTL_BASE + SYS_BUS_CLK_EN,
  99. REGS_SYSCTL_BASE + SYS_PER_CLK_EN, REGS_SYSCTL_BASE + SYS_PER_CLK_EN,
  100. REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  101. .enable_offset = {17, 0, 18, 17, 16}, .enable_bits = 5,
  102. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_VOU_CLK_CFG, .u.sys_property.index_offset = 0,
  103. .u.sys_property.index_mask = 0x3, .u.sys_property.index_value = 1,
  104. .u.sys_property.div_offset = 3, .u.sys_property.div_mask = 0x1f,
  105. .u.sys_property.div_value = 5, .u.sys_property.div_mode = DIVMODE_PLUSONE,
  106. #ifdef LCD_CLK_INVERSE
  107. .u.sys_property.inv_reg = REGS_SYSCTL_BASE + SYS_VOU_CLK_CFG, .u.sys_property.inv_offset = 8,
  108. .u.sys_property.inv_mask = 0x1, .u.sys_property.inv_value = 1,
  109. #endif
  110. },
  111. {.clkid = CLK_QOI, .clktype = SYS_CLOCK, .clksource = {CLK_SYSPLL, CLK_MFCPLL, CLK_XTAL24M},
  112. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN, REGS_SYSCTL_BASE + SYS_BUS_CLK_EN,
  113. REGS_SYSCTL_BASE + SYS_PER_CLK_EN1},
  114. .enable_offset = {20, 5, 5}, .enable_bits = 3,
  115. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_BUS_CLK1_CFG, .u.sys_property.index_offset = 16,
  116. .u.sys_property.index_mask = 0x3, .u.sys_property.index_value = 1,
  117. .u.sys_property.div_offset = 19, .u.sys_property.div_mask = 0x1f,
  118. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,
  119. },
  120. {.clkid = CLK_GPU, .clktype = SYS_CLOCK, .clksource = {CLK_SYSPLL, CLK_GPUPLL, CLK_XTAL24M},
  121. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN, REGS_SYSCTL_BASE + SYS_BUS_CLK_EN,
  122. REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  123. .enable_offset = {19, 3, 24}, .enable_bits = 3,
  124. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_TIMER1_CLK_CFG, .u.sys_property.index_offset = 0,
  125. .u.sys_property.index_mask = 0x3, .u.sys_property.index_value = 1,
  126. .u.sys_property.div_offset = 3, .u.sys_property.div_mask = 0x1f,
  127. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,
  128. },
  129. {.clkid = CLK_SDMMC0, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_AHBPLL},
  130. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN, REGS_SYSCTL_BASE + SYS_PER_CLK_EN,
  131. REGS_SYSCTL_BASE + SYS_SDMMC_CLK_CFG},
  132. .enable_offset = {15, 15, 6}, .enable_bits = 3,
  133. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_SDMMC_CLK_CFG, .u.sys_property.index_offset = 7,
  134. .u.sys_property.index_mask = 1, .u.sys_property.index_value = 1,
  135. .u.sys_property.div_offset = 0, .u.sys_property.div_mask = 0x1f,
  136. .u.sys_property.div_value = 5, .u.sys_property.div_mode = DIVMODE_PLUSONE,
  137. },
  138. {.clkid = CLK_SDMMC1, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_AHBPLL},
  139. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN, REGS_SYSCTL_BASE + SYS_PER_CLK_EN,
  140. REGS_SYSCTL_BASE + SYS_SDMMC1_CLK_CFG},
  141. .enable_offset = {16, 31, 6}, .enable_bits = 3,
  142. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_SDMMC1_CLK_CFG, .u.sys_property.index_offset = 7,
  143. .u.sys_property.index_mask = 1, .u.sys_property.index_value = 1,
  144. .u.sys_property.div_offset = 0, .u.sys_property.div_mask = 0x1f,
  145. .u.sys_property.div_value = 5, .u.sys_property.div_mode = DIVMODE_PLUSONE,
  146. },
  147. {.clkid = CLK_TIMER, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_AHBPLL},
  148. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  149. .enable_offset = {7, 9}, .enable_bits = 2,
  150. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_TIMER_CLK_CFG, .u.sys_property.index_offset = 4,
  151. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 0,
  152. .u.sys_property.div_offset = 0, .u.sys_property.div_mask = 0xf,
  153. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  154. {.clkid = CLK_TIMER1, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_AHBPLL},
  155. .enable_reg = {REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  156. .enable_offset = {26}, .enable_bits = 1,
  157. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_TIMER1_CLK_CFG, .u.sys_property.index_offset = 20,
  158. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 0,
  159. .u.sys_property.div_offset = 16, .u.sys_property.div_mask = 0xf,
  160. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  161. {.clkid = CLK_TIMER2_3, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_AHBPLL},
  162. .enable_reg = {REGS_SYSCTL_BASE + SYS_PER_CLK_EN, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  163. .enable_offset = {27, 28}, .enable_bits = 2,
  164. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_TIMER1_CLK_CFG, .u.sys_property.index_offset = 28,
  165. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 0,
  166. .u.sys_property.div_offset = 24, .u.sys_property.div_mask = 0xf,
  167. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  168. {.clkid = CLK_MFC, .clktype = SYS_CLOCK, .clksource = {CLK_SYSPLL, CLK_MFCPLL, CLK_XTAL24M},
  169. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN, REGS_SYSCTL_BASE + SYS_BUS_CLK_EN,
  170. REGS_SYSCTL_BASE + SYS_PER_CLK_EN, REGS_SYSCTL_BASE + SYS_DDR_CTL1_CFG},
  171. .enable_offset = {21, 4, 23, 17}, .enable_bits = 4,
  172. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_TIMER_CLK_CFG, .u.sys_property.index_offset = 8,
  173. .u.sys_property.index_mask = 0x3, .u.sys_property.index_value = 1,
  174. .u.sys_property.div_offset = 11, .u.sys_property.div_mask = 0x1f,
  175. .u.sys_property.div_value = 2, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  176. {.clkid = CLK_UART0, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_AHBPLL},
  177. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  178. .enable_offset = {11, 4}, .enable_bits = 2,
  179. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_PERCTL_CFG, .u.sys_property.index_offset = 0,
  180. .u.sys_property.index_mask = 1, .u.sys_property.index_value = 0,
  181. .u.sys_property.div_offset = 1, .u.sys_property.div_mask = 0xf,
  182. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  183. {.clkid = CLK_UART1, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_AHBPLL},
  184. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  185. .enable_offset = {12, 5}, .enable_bits = 2,
  186. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_PERCTL_CFG, .u.sys_property.index_offset = 16,
  187. .u.sys_property.index_mask = 1, .u.sys_property.index_value = 0,
  188. .u.sys_property.div_offset = 17, .u.sys_property.div_mask = 0xf,
  189. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  190. {.clkid = CLK_UART2, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_AHBPLL},
  191. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  192. .enable_offset = {13, 6}, .enable_bits = 2,
  193. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_PERCTL_CFG, .u.sys_property.index_offset = 8,
  194. .u.sys_property.index_mask = 1, .u.sys_property.index_value = 0,
  195. .u.sys_property.div_offset = 9, .u.sys_property.div_mask = 0xf,
  196. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  197. {.clkid = CLK_UART3, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_AHBPLL},
  198. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  199. .enable_offset = {14, 7}, .enable_bits = 2,
  200. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_PERCTL_CFG, .u.sys_property.index_offset = 24,
  201. .u.sys_property.index_mask = 1, .u.sys_property.index_value = 0,
  202. .u.sys_property.div_offset = 25, .u.sys_property.div_mask = 0xf,
  203. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  204. {.clkid = CLK_SPI0, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_CPUPLL},
  205. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  206. .enable_offset = {26, 0}, .enable_bits = 2,
  207. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_SSP_CLK_CFG, .u.sys_property.index_offset = 4,
  208. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 1,
  209. .u.sys_property.div_offset = 0, .u.sys_property.div_mask = 0xf, .u.sys_property.div_mode = DIVMODE_PLUSONE,
  210. #ifndef SPI0_QSPI_MODE
  211. .u.sys_property.div_value = 5,},
  212. #else
  213. .u.sys_property.div_value = 4,},
  214. #endif
  215. {.clkid = CLK_SPI1, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_CPUPLL},
  216. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  217. .enable_offset = {2, 1}, .enable_bits = 2,
  218. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_SSP_CLK_CFG, .u.sys_property.index_offset = 20,
  219. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 0,
  220. .u.sys_property.div_offset = 16, .u.sys_property.div_mask = 0xf,
  221. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  222. {.clkid = CLK_SPI2, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_CPUPLL},
  223. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  224. .enable_offset = {27, 29}, .enable_bits = 2,
  225. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_SSP_CLK_CFG, .u.sys_property.index_offset = 28,
  226. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 0,
  227. .u.sys_property.div_offset = 24, .u.sys_property.div_mask = 0xf,
  228. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  229. {.clkid = CLK_PWM, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_SYSPLL},
  230. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  231. .enable_offset = {15, 10}, .enable_bits = 2,
  232. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_PER_CLK_CFG, .u.sys_property.index_offset = 8,
  233. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 0,
  234. .u.sys_property.div_offset = 4, .u.sys_property.div_mask = 0xf,
  235. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  236. {.clkid = CLK_ADC, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M},
  237. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  238. .enable_offset = {5, 13}, .enable_bits = 2,
  239. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_TIMER_CLK_CFG, .u.sys_property.div_offset = 16,
  240. .u.sys_property.div_mask = 0x7fff, .u.sys_property.div_value = 642,
  241. .u.sys_property.div_mode = DIVMODE_PONEDOUBLE,},
  242. {.clkid = CLK_ADC1, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M},
  243. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN1},
  244. .enable_offset = {25, 14}, .enable_bits = 2,
  245. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_ADC_CLK1_CFG, .u.sys_property.div_offset = 0,
  246. .u.sys_property.div_mask = 0x7fff, .u.sys_property.div_value = 642,
  247. .u.sys_property.div_mode = DIVMODE_PONEDOUBLE,},
  248. {.clkid = CLK_ADC2, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M},
  249. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN1},
  250. .enable_offset = {26, 15}, .enable_bits = 2,
  251. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_ADC_CLK1_CFG, .u.sys_property.div_offset = 16,
  252. .u.sys_property.div_mask = 0x7fff, .u.sys_property.div_value = 642,
  253. .u.sys_property.div_mode = DIVMODE_PONEDOUBLE,},
  254. {.clkid = CLK_I2S, .clktype = SYS_CLOCK, .clksource = {CLK_SYSPLL, CLK_AHBPLL},
  255. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN,
  256. REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  257. .enable_offset = {0, 12, 11}, .enable_bits = 3,
  258. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_PER_CLK_CFG, .u.sys_property.index_offset = 16,
  259. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 0,
  260. .u.sys_property.div_value = 1,},
  261. {.clkid = CLK_I2S1, .clktype = SYS_CLOCK, .clksource = {CLK_SYSPLL, CLK_AHBPLL},
  262. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN1,
  263. REGS_SYSCTL_BASE + SYS_PER_CLK_EN1},
  264. .enable_offset = {1, 1, 0}, .enable_bits = 3,
  265. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_BUS_CLK1_CFG, .u.sys_property.index_offset = 4,
  266. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 0,
  267. .u.sys_property.div_value = 1,},
  268. {.clkid = CLK_RTC, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL32K},
  269. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1},
  270. .enable_offset = {8}, .enable_bits = 1,},
  271. {.clkid = CLK_ETH, .clktype = SYS_CLOCK, .clksource = {CLK_AHB},},
  272. };
  273. #define CLOCK_NUM (sizeof(xClocks) / sizeof(xClocks[0]))
  274. static xClockProperty *clk_get(uint32_t clkid)
  275. {
  276. int i;
  277. for (i = 0; i < CLOCK_NUM; i++) {
  278. if (xClocks[i].clkid == clkid) {
  279. return &xClocks[i];
  280. }
  281. }
  282. return NULL;
  283. }
  284. static uint32_t clk_fixed_get_rate(xClockProperty *clk)
  285. {
  286. return clk->u.fixed_freq;
  287. }
  288. static uint32_t clk_fixed_factor_get_rate(xClockProperty *clk)
  289. {
  290. xClockProperty *parentclk = clk_get(clk->clksource[0]);
  291. configASSERT(parentclk);
  292. return clk_fixed_get_rate(parentclk) * clk->u.fixed_fator_property.mult
  293. / clk->u.fixed_fator_property.div;
  294. }
  295. static uint32_t clk_pll_get_rate(xClockProperty *clk)
  296. {
  297. uint32_t reg, parent_rate;
  298. uint32_t posdiv2, posdiv1, fbdiv, refdiv;
  299. uint32_t pllclk;
  300. configASSERT(clk);
  301. parent_rate = ulClkGetRate(clk->clksource[clk->source_index]);
  302. reg = readl(clk->u.pll_property.cfgreg);
  303. if (reg & PLL_BYPASS) {
  304. pllclk = parent_rate;
  305. } else {
  306. posdiv2 = (reg >> PLL_POSTDIV2_OFFSET) & PLL_POSTDIV2_MASK;
  307. posdiv1 = (reg >> PLL_POSTDIV1_OFFSET) & PLL_POSTDIV1_MASK;
  308. fbdiv = (reg >> PLL_FBDIV_OFFSET) & PLL_FBDIV_MASK;
  309. refdiv = (reg >> PLL_REFDIV_OFFSET) & PLL_REFDIV_MASK;
  310. pllclk = (uint64_t)parent_rate * fbdiv / posdiv2 / posdiv1 / refdiv;
  311. }
  312. return pllclk;
  313. }
  314. static uint32_t clk_sys_get_rate(xClockProperty *clk)
  315. {
  316. uint32_t parent_rate;
  317. configASSERT(clk);
  318. configASSERT(clk->div);
  319. parent_rate = ulClkGetRate(clk->clksource[clk->source_index]);
  320. return parent_rate / clk->div;
  321. }
  322. static void clk_pll_init(xClockProperty *clk)
  323. {
  324. configASSERT(clk);
  325. clk->source_index = 0;
  326. }
  327. static int clk_get_div(int div, int divmode)
  328. {
  329. switch(divmode) {
  330. case DIVMODE_NOZERO:
  331. div = div ? div : 1;
  332. break;
  333. case DIVMODE_PLUSONE:
  334. div = div + 1;
  335. break;
  336. case DIVMODE_DOUBLE:
  337. div *= 2;
  338. break;
  339. case DIVMODE_EXPONENT:
  340. div = 1 << div;
  341. break;
  342. case DIVMODE_PONEDOUBLE:
  343. div = (div + 1) * 2;
  344. break;
  345. }
  346. return div;
  347. }
  348. static __INLINE int clk_set_div(int div, int divmode)
  349. {
  350. switch(divmode) {
  351. case DIVMODE_PLUSONE:
  352. div = div - 1;
  353. break;
  354. case DIVMODE_DOUBLE:
  355. div /= 2;
  356. break;
  357. case DIVMODE_EXPONENT:
  358. div = fls(div) - 1;
  359. break;
  360. case DIVMODE_PONEDOUBLE:
  361. div = div / 2 - 1;
  362. break;
  363. }
  364. return div;
  365. }
  366. static void clk_sys_set_rate(xClockProperty *clk, uint32_t freq)
  367. {
  368. int div;
  369. uint32_t reg;
  370. uint32_t parent_rate;
  371. configASSERT(clk);
  372. parent_rate = ulClkGetRate(clk->clksource[clk->source_index]);
  373. div = DIV_ROUND_UP(parent_rate, freq);
  374. clk->div = div;
  375. div = clk_set_div(div, clk->u.sys_property.div_mode);
  376. reg = readl(clk->u.sys_property.cfgreg);
  377. reg &= ~(clk->u.sys_property.div_mask << clk->u.sys_property.div_offset);
  378. reg |= (div & clk->u.sys_property.div_mask) << clk->u.sys_property.div_offset;
  379. writel(reg, clk->u.sys_property.cfgreg);
  380. }
  381. static void clk_sys_init(xClockProperty *clk)
  382. {
  383. uint32_t reg;
  384. uint32_t val;
  385. configASSERT(clk);
  386. if (clk->u.sys_property.index_value >= 0 && clk->u.sys_property.index_mask) {
  387. clk->source_index = clk->u.sys_property.index_value;
  388. val = clk->u.sys_property.index_value == 3 ? 4 : clk->u.sys_property.index_value;
  389. reg = readl(clk->u.sys_property.cfgreg);
  390. reg &= ~(clk->u.sys_property.index_mask << clk->u.sys_property.index_offset);
  391. reg |= (val & clk->u.sys_property.index_mask) << clk->u.sys_property.index_offset;
  392. writel(reg, clk->u.sys_property.cfgreg);
  393. } else if (clk->u.sys_property.index_mask) {
  394. reg = readl(clk->u.sys_property.cfgreg);
  395. val = (reg >> clk->u.sys_property.index_offset) & clk->u.sys_property.index_mask;
  396. clk->source_index = val == 4 ? 3 : val;
  397. }
  398. if (clk->u.sys_property.div_value >= 0 && clk->u.sys_property.div_mask) {
  399. val = clk_set_div(clk->u.sys_property.div_value, clk->u.sys_property.div_mode);
  400. clk->div = clk_get_div(val, clk->u.sys_property.div_mode);
  401. reg = readl(clk->u.sys_property.cfgreg);
  402. reg &= ~(clk->u.sys_property.div_mask << clk->u.sys_property.div_offset);
  403. reg |= (val & clk->u.sys_property.div_mask) << clk->u.sys_property.div_offset;
  404. writel(reg, clk->u.sys_property.cfgreg);
  405. } else if (clk->u.sys_property.div_mask) {
  406. reg = readl(clk->u.sys_property.cfgreg);
  407. val = (reg >> clk->u.sys_property.div_offset) & clk->u.sys_property.div_mask;
  408. clk->div = clk_get_div(val, clk->u.sys_property.div_mode);
  409. } else if (clk->u.sys_property.div_value > 0) {
  410. clk->div = clk->u.sys_property.div_value;
  411. } else {
  412. clk->div = 1;
  413. }
  414. if (clk->u.sys_property.inv_reg) {
  415. reg = readl(clk->u.sys_property.inv_reg);
  416. reg &= ~(clk->u.sys_property.inv_mask << clk->u.sys_property.inv_offset);
  417. reg |= (clk->u.sys_property.inv_value & clk->u.sys_property.inv_mask)
  418. << clk->u.sys_property.inv_offset;
  419. writel(reg, clk->u.sys_property.inv_reg);
  420. }
  421. }
  422. static void clk_sys_enable(xClockProperty *clk)
  423. {
  424. int i;
  425. configASSERT(clk);
  426. for (i = 0; i < clk->enable_bits; i++)
  427. writel(readl(clk->enable_reg[i]) | (1 << clk->enable_offset[i]),
  428. clk->enable_reg[i]);
  429. }
  430. static void clk_sys_disable(xClockProperty *clk)
  431. {
  432. int i;
  433. configASSERT(clk);
  434. for (i = 0; i < clk->enable_bits; i++)
  435. writel(readl(clk->enable_reg[i]) & ~(1 << clk->enable_offset[i]),
  436. clk->enable_reg[i]);
  437. }
  438. void vClkInit(void)
  439. {
  440. int i;
  441. xClockProperty *clk;
  442. for (i = 0; i < CLOCK_NUM; i++) {
  443. clk = &xClocks[i];
  444. if (clk->clktype == PLL_CLOCK) {
  445. clk_pll_init(clk);
  446. } else if (clk->clktype == SYS_CLOCK) {
  447. clk_sys_init(clk);
  448. }
  449. }
  450. }
  451. uint32_t ulClkGetRate(uint32_t clkid)
  452. {
  453. xClockProperty *clk = clk_get(clkid);
  454. if (clk == NULL)
  455. return 0;
  456. switch (clk->clktype) {
  457. case FIXED_CLOCK:
  458. return clk_fixed_get_rate(clk);
  459. case FIXED_FACTOR_CLOCK:
  460. return clk_fixed_factor_get_rate(clk);
  461. case PLL_CLOCK:
  462. return clk_pll_get_rate(clk);
  463. case SYS_CLOCK:
  464. return clk_sys_get_rate(clk);
  465. }
  466. return 0;
  467. }
  468. void vClkSetRate(uint32_t clkid, uint32_t freq)
  469. {
  470. xClockProperty *clk = clk_get(clkid);
  471. if (clk == NULL)
  472. return;
  473. if (clk->clktype == SYS_CLOCK)
  474. clk_sys_set_rate(clk, freq);
  475. }
  476. void vClkEnable(uint32_t clkid)
  477. {
  478. xClockProperty *clk = clk_get(clkid);
  479. if (clk == NULL)
  480. return;
  481. if (clk->clktype == SYS_CLOCK)
  482. clk_sys_enable(clk);
  483. }
  484. void vClkDisable(uint32_t clkid)
  485. {
  486. xClockProperty *clk = clk_get(clkid);
  487. if (clk == NULL)
  488. return;
  489. if (clk->clktype == SYS_CLOCK)
  490. clk_sys_disable(clk);
  491. }