clock.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  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. #ifdef AMT630HV160S
  106. .u.sys_property.div_value = 8,
  107. #else
  108. .u.sys_property.div_value = 5,
  109. #endif
  110. .u.sys_property.div_mode = DIVMODE_PLUSONE,
  111. #ifdef LCD_CLK_INVERSE
  112. .u.sys_property.inv_reg = REGS_SYSCTL_BASE + SYS_VOU_CLK_CFG, .u.sys_property.inv_offset = 8,
  113. .u.sys_property.inv_mask = 0x1, .u.sys_property.inv_value = 1,
  114. #endif
  115. },
  116. {.clkid = CLK_QOI, .clktype = SYS_CLOCK, .clksource = {CLK_SYSPLL, CLK_MFCPLL, CLK_XTAL24M},
  117. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN, REGS_SYSCTL_BASE + SYS_BUS_CLK_EN,
  118. REGS_SYSCTL_BASE + SYS_PER_CLK_EN1},
  119. .enable_offset = {20, 5, 5}, .enable_bits = 3,
  120. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_BUS_CLK1_CFG, .u.sys_property.index_offset = 16,
  121. .u.sys_property.index_mask = 0x3, .u.sys_property.index_value = 1,
  122. .u.sys_property.div_offset = 19, .u.sys_property.div_mask = 0x1f,
  123. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,
  124. },
  125. {.clkid = CLK_GPU, .clktype = SYS_CLOCK, .clksource = {CLK_SYSPLL, CLK_GPUPLL, CLK_XTAL24M},
  126. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN, REGS_SYSCTL_BASE + SYS_BUS_CLK_EN,
  127. REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  128. .enable_offset = {19, 3, 24}, .enable_bits = 3,
  129. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_TIMER1_CLK_CFG, .u.sys_property.index_offset = 0,
  130. .u.sys_property.index_mask = 0x3, .u.sys_property.index_value = 1,
  131. .u.sys_property.div_offset = 3, .u.sys_property.div_mask = 0x1f,
  132. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,
  133. },
  134. {.clkid = CLK_SDMMC0, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_AHBPLL},
  135. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN, REGS_SYSCTL_BASE + SYS_PER_CLK_EN,
  136. REGS_SYSCTL_BASE + SYS_SDMMC_CLK_CFG},
  137. .enable_offset = {15, 15, 6}, .enable_bits = 3,
  138. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_SDMMC_CLK_CFG, .u.sys_property.index_offset = 7,
  139. .u.sys_property.index_mask = 1, .u.sys_property.index_value = 1,
  140. .u.sys_property.div_offset = 0, .u.sys_property.div_mask = 0x1f,
  141. .u.sys_property.div_value = 5, .u.sys_property.div_mode = DIVMODE_PLUSONE,
  142. },
  143. {.clkid = CLK_SDMMC1, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_AHBPLL},
  144. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN, REGS_SYSCTL_BASE + SYS_PER_CLK_EN,
  145. REGS_SYSCTL_BASE + SYS_SDMMC1_CLK_CFG},
  146. .enable_offset = {16, 31, 6}, .enable_bits = 3,
  147. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_SDMMC1_CLK_CFG, .u.sys_property.index_offset = 7,
  148. .u.sys_property.index_mask = 1, .u.sys_property.index_value = 1,
  149. .u.sys_property.div_offset = 0, .u.sys_property.div_mask = 0x1f,
  150. .u.sys_property.div_value = 5, .u.sys_property.div_mode = DIVMODE_PLUSONE,
  151. },
  152. {.clkid = CLK_TIMER, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_AHBPLL},
  153. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  154. .enable_offset = {7, 9}, .enable_bits = 2,
  155. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_TIMER_CLK_CFG, .u.sys_property.index_offset = 4,
  156. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 0,
  157. .u.sys_property.div_offset = 0, .u.sys_property.div_mask = 0xf,
  158. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  159. {.clkid = CLK_TIMER1, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_AHBPLL},
  160. .enable_reg = {REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  161. .enable_offset = {26}, .enable_bits = 1,
  162. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_TIMER1_CLK_CFG, .u.sys_property.index_offset = 20,
  163. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 0,
  164. .u.sys_property.div_offset = 16, .u.sys_property.div_mask = 0xf,
  165. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  166. {.clkid = CLK_TIMER2_3, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_AHBPLL},
  167. .enable_reg = {REGS_SYSCTL_BASE + SYS_PER_CLK_EN, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  168. .enable_offset = {27, 28}, .enable_bits = 2,
  169. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_TIMER1_CLK_CFG, .u.sys_property.index_offset = 28,
  170. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 0,
  171. .u.sys_property.div_offset = 24, .u.sys_property.div_mask = 0xf,
  172. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  173. {.clkid = CLK_MFC, .clktype = SYS_CLOCK, .clksource = {CLK_SYSPLL, CLK_MFCPLL, CLK_XTAL24M},
  174. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN, REGS_SYSCTL_BASE + SYS_BUS_CLK_EN,
  175. REGS_SYSCTL_BASE + SYS_PER_CLK_EN, REGS_SYSCTL_BASE + SYS_DDR_CTL1_CFG},
  176. .enable_offset = {21, 4, 23, 17}, .enable_bits = 4,
  177. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_TIMER_CLK_CFG, .u.sys_property.index_offset = 8,
  178. .u.sys_property.index_mask = 0x3, .u.sys_property.index_value = 1,
  179. .u.sys_property.div_offset = 11, .u.sys_property.div_mask = 0x1f,
  180. .u.sys_property.div_value = 2, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  181. {.clkid = CLK_UART0, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_AHBPLL},
  182. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  183. .enable_offset = {11, 4}, .enable_bits = 2,
  184. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_PERCTL_CFG, .u.sys_property.index_offset = 0,
  185. .u.sys_property.index_mask = 1, .u.sys_property.index_value = 0,
  186. .u.sys_property.div_offset = 1, .u.sys_property.div_mask = 0xf,
  187. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  188. {.clkid = CLK_UART1, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_AHBPLL},
  189. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  190. .enable_offset = {12, 5}, .enable_bits = 2,
  191. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_PERCTL_CFG, .u.sys_property.index_offset = 16,
  192. .u.sys_property.index_mask = 1, .u.sys_property.index_value = 0,
  193. .u.sys_property.div_offset = 17, .u.sys_property.div_mask = 0xf,
  194. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  195. {.clkid = CLK_UART2, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_AHBPLL},
  196. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  197. .enable_offset = {13, 6}, .enable_bits = 2,
  198. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_PERCTL_CFG, .u.sys_property.index_offset = 8,
  199. .u.sys_property.index_mask = 1, .u.sys_property.index_value = 0,
  200. .u.sys_property.div_offset = 9, .u.sys_property.div_mask = 0xf,
  201. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  202. {.clkid = CLK_UART3, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_AHBPLL},
  203. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  204. .enable_offset = {14, 7}, .enable_bits = 2,
  205. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_PERCTL_CFG, .u.sys_property.index_offset = 24,
  206. .u.sys_property.index_mask = 1, .u.sys_property.index_value = 0,
  207. .u.sys_property.div_offset = 25, .u.sys_property.div_mask = 0xf,
  208. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  209. #ifdef DW_SPI0_SUPPORT
  210. {.clkid = CLK_SPI0, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_CPUPLL},
  211. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  212. .enable_offset = {26, 0}, .enable_bits = 2,
  213. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_SSP_CLK_CFG, .u.sys_property.index_offset = 4,
  214. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 1,
  215. .u.sys_property.div_offset = 0, .u.sys_property.div_mask = 0xf, .u.sys_property.div_mode = DIVMODE_PLUSONE,
  216. #ifndef SPI0_QSPI_MODE
  217. .u.sys_property.div_value = 5,},
  218. #else
  219. .u.sys_property.div_value = 4,},
  220. #endif
  221. #endif
  222. #ifdef EC_SPI1_SUPPORT
  223. {.clkid = CLK_SPI1, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_CPUPLL},
  224. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  225. .enable_offset = {2, 1}, .enable_bits = 2,
  226. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_SSP_CLK_CFG, .u.sys_property.index_offset = 20,
  227. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 0,
  228. .u.sys_property.div_offset = 16, .u.sys_property.div_mask = 0xf,
  229. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  230. #endif
  231. #ifdef DW_SPI2_SUPPORT
  232. {.clkid = CLK_SPI2, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_CPUPLL},
  233. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  234. .enable_offset = {27, 29}, .enable_bits = 2,
  235. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_SSP_CLK_CFG, .u.sys_property.index_offset = 28,
  236. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 1,
  237. .u.sys_property.div_offset = 24, .u.sys_property.div_mask = 0xf, .u.sys_property.div_mode = DIVMODE_PLUSONE,
  238. #ifndef SPI2_QSPI_MODE
  239. .u.sys_property.div_value = 5,},
  240. #else
  241. .u.sys_property.div_value = 4,},
  242. #endif
  243. #endif
  244. //PWM时钟配置和MCU_PWM是复用的,默认是24Mhz,如果要修改的话需要在MCU工程修改
  245. {.clkid = CLK_PWM, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_SYSPLL},
  246. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  247. .enable_offset = {15, 10}, .enable_bits = 2,
  248. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_PER_CLK_CFG, .u.sys_property.index_offset = 8,
  249. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = -1,
  250. .u.sys_property.div_offset = 4, .u.sys_property.div_mask = 0xf,
  251. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  252. #ifdef ADC0_SUPPORT
  253. {.clkid = CLK_ADC, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M},
  254. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  255. .enable_offset = {5, 13}, .enable_bits = 2,
  256. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_TIMER_CLK_CFG, .u.sys_property.div_offset = 16,
  257. .u.sys_property.div_mask = 0x7fff, .u.sys_property.div_value = 2400,
  258. .u.sys_property.div_mode = DIVMODE_PONEDOUBLE,},
  259. #endif
  260. #ifdef ADC1_SUPPORT
  261. {.clkid = CLK_ADC1, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M},
  262. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN1},
  263. .enable_offset = {25, 14}, .enable_bits = 2,
  264. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_ADC_CLK1_CFG, .u.sys_property.div_offset = 0,
  265. .u.sys_property.div_mask = 0x7fff, .u.sys_property.div_value = 2400,
  266. .u.sys_property.div_mode = DIVMODE_PONEDOUBLE,},
  267. #endif
  268. #ifdef ADC2_SUPPORT
  269. {.clkid = CLK_ADC2, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M},
  270. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN1},
  271. .enable_offset = {26, 15}, .enable_bits = 2,
  272. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_ADC_CLK1_CFG, .u.sys_property.div_offset = 16,
  273. .u.sys_property.div_mask = 0x7fff, .u.sys_property.div_value = 2400,
  274. .u.sys_property.div_mode = DIVMODE_PONEDOUBLE,},
  275. #endif
  276. {.clkid = CLK_I2S, .clktype = SYS_CLOCK, .clksource = {CLK_SYSPLL, CLK_AHBPLL},
  277. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN,
  278. REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  279. .enable_offset = {0, 12, 11}, .enable_bits = 3,
  280. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_PER_CLK_CFG, .u.sys_property.index_offset = 16,
  281. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 0,
  282. .u.sys_property.div_value = 1,},
  283. {.clkid = CLK_I2S1, .clktype = SYS_CLOCK, .clksource = {CLK_SYSPLL, CLK_AHBPLL},
  284. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN1,
  285. REGS_SYSCTL_BASE + SYS_PER_CLK_EN1},
  286. .enable_offset = {1, 1, 0}, .enable_bits = 3,
  287. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_BUS_CLK1_CFG, .u.sys_property.index_offset = 4,
  288. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 0,
  289. .u.sys_property.div_value = 1,},
  290. {.clkid = CLK_RTC, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL32K},
  291. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1},
  292. .enable_offset = {8}, .enable_bits = 1,},
  293. {.clkid = CLK_ETH, .clktype = SYS_CLOCK, .clksource = {CLK_AHB},},
  294. };
  295. #define CLOCK_NUM (sizeof(xClocks) / sizeof(xClocks[0]))
  296. static xClockProperty *clk_get(uint32_t clkid)
  297. {
  298. int i;
  299. for (i = 0; i < CLOCK_NUM; i++) {
  300. if (xClocks[i].clkid == clkid) {
  301. return &xClocks[i];
  302. }
  303. }
  304. return NULL;
  305. }
  306. static uint32_t clk_fixed_get_rate(xClockProperty *clk)
  307. {
  308. return clk->u.fixed_freq;
  309. }
  310. static uint32_t clk_fixed_factor_get_rate(xClockProperty *clk)
  311. {
  312. xClockProperty *parentclk = clk_get(clk->clksource[0]);
  313. configASSERT(parentclk);
  314. return clk_fixed_get_rate(parentclk) * clk->u.fixed_fator_property.mult
  315. / clk->u.fixed_fator_property.div;
  316. }
  317. static uint32_t clk_pll_get_rate(xClockProperty *clk)
  318. {
  319. uint32_t reg, parent_rate;
  320. uint32_t posdiv2, posdiv1, fbdiv, refdiv;
  321. uint32_t pllclk;
  322. configASSERT(clk);
  323. parent_rate = ulClkGetRate(clk->clksource[clk->source_index]);
  324. reg = readl(clk->u.pll_property.cfgreg);
  325. if (reg & PLL_BYPASS) {
  326. pllclk = parent_rate;
  327. } else {
  328. posdiv2 = (reg >> PLL_POSTDIV2_OFFSET) & PLL_POSTDIV2_MASK;
  329. posdiv1 = (reg >> PLL_POSTDIV1_OFFSET) & PLL_POSTDIV1_MASK;
  330. fbdiv = (reg >> PLL_FBDIV_OFFSET) & PLL_FBDIV_MASK;
  331. refdiv = (reg >> PLL_REFDIV_OFFSET) & PLL_REFDIV_MASK;
  332. pllclk = (uint64_t)parent_rate * fbdiv / posdiv2 / posdiv1 / refdiv;
  333. }
  334. return pllclk;
  335. }
  336. static uint32_t clk_sys_get_rate(xClockProperty *clk)
  337. {
  338. uint32_t parent_rate;
  339. configASSERT(clk);
  340. configASSERT(clk->div);
  341. parent_rate = ulClkGetRate(clk->clksource[clk->source_index]);
  342. return parent_rate / clk->div;
  343. }
  344. static void clk_pll_init(xClockProperty *clk)
  345. {
  346. configASSERT(clk);
  347. clk->source_index = 0;
  348. }
  349. static int clk_get_div(int div, int divmode)
  350. {
  351. switch(divmode) {
  352. case DIVMODE_NOZERO:
  353. div = div ? div : 1;
  354. break;
  355. case DIVMODE_PLUSONE:
  356. div = div + 1;
  357. break;
  358. case DIVMODE_DOUBLE:
  359. div *= 2;
  360. break;
  361. case DIVMODE_EXPONENT:
  362. div = 1 << div;
  363. break;
  364. case DIVMODE_PONEDOUBLE:
  365. div = (div + 1) * 2;
  366. break;
  367. }
  368. return div;
  369. }
  370. static __INLINE int clk_set_div(int div, int divmode)
  371. {
  372. switch(divmode) {
  373. case DIVMODE_PLUSONE:
  374. div = div - 1;
  375. break;
  376. case DIVMODE_DOUBLE:
  377. div /= 2;
  378. break;
  379. case DIVMODE_EXPONENT:
  380. div = fls(div) - 1;
  381. break;
  382. case DIVMODE_PONEDOUBLE:
  383. div = div / 2 - 1;
  384. break;
  385. }
  386. return div;
  387. }
  388. static void clk_sys_set_rate(xClockProperty *clk, uint32_t freq)
  389. {
  390. int div;
  391. uint32_t reg;
  392. uint32_t parent_rate;
  393. configASSERT(clk);
  394. parent_rate = ulClkGetRate(clk->clksource[clk->source_index]);
  395. div = DIV_ROUND_UP(parent_rate, freq);
  396. clk->div = div;
  397. div = clk_set_div(div, clk->u.sys_property.div_mode);
  398. reg = readl(clk->u.sys_property.cfgreg);
  399. reg &= ~(clk->u.sys_property.div_mask << clk->u.sys_property.div_offset);
  400. reg |= (div & clk->u.sys_property.div_mask) << clk->u.sys_property.div_offset;
  401. writel(reg, clk->u.sys_property.cfgreg);
  402. }
  403. static void clk_sys_init(xClockProperty *clk)
  404. {
  405. uint32_t reg;
  406. uint32_t val;
  407. configASSERT(clk);
  408. if (clk->u.sys_property.index_value >= 0 && clk->u.sys_property.index_mask) {
  409. clk->source_index = clk->u.sys_property.index_value;
  410. val = clk->u.sys_property.index_value == 3 ? 4 : clk->u.sys_property.index_value;
  411. reg = readl(clk->u.sys_property.cfgreg);
  412. reg &= ~(clk->u.sys_property.index_mask << clk->u.sys_property.index_offset);
  413. reg |= (val & clk->u.sys_property.index_mask) << clk->u.sys_property.index_offset;
  414. writel(reg, clk->u.sys_property.cfgreg);
  415. } else if (clk->u.sys_property.index_mask) {
  416. reg = readl(clk->u.sys_property.cfgreg);
  417. val = (reg >> clk->u.sys_property.index_offset) & clk->u.sys_property.index_mask;
  418. clk->source_index = val == 4 ? 3 : val;
  419. }
  420. if (clk->u.sys_property.div_value >= 0 && clk->u.sys_property.div_mask) {
  421. val = clk_set_div(clk->u.sys_property.div_value, clk->u.sys_property.div_mode);
  422. clk->div = clk_get_div(val, clk->u.sys_property.div_mode);
  423. reg = readl(clk->u.sys_property.cfgreg);
  424. reg &= ~(clk->u.sys_property.div_mask << clk->u.sys_property.div_offset);
  425. reg |= (val & clk->u.sys_property.div_mask) << clk->u.sys_property.div_offset;
  426. writel(reg, clk->u.sys_property.cfgreg);
  427. } else if (clk->u.sys_property.div_mask) {
  428. reg = readl(clk->u.sys_property.cfgreg);
  429. val = (reg >> clk->u.sys_property.div_offset) & clk->u.sys_property.div_mask;
  430. clk->div = clk_get_div(val, clk->u.sys_property.div_mode);
  431. } else if (clk->u.sys_property.div_value > 0) {
  432. clk->div = clk->u.sys_property.div_value;
  433. } else {
  434. clk->div = 1;
  435. }
  436. if (clk->u.sys_property.inv_reg) {
  437. reg = readl(clk->u.sys_property.inv_reg);
  438. reg &= ~(clk->u.sys_property.inv_mask << clk->u.sys_property.inv_offset);
  439. reg |= (clk->u.sys_property.inv_value & clk->u.sys_property.inv_mask)
  440. << clk->u.sys_property.inv_offset;
  441. writel(reg, clk->u.sys_property.inv_reg);
  442. }
  443. }
  444. static void clk_sys_enable(xClockProperty *clk)
  445. {
  446. int i;
  447. configASSERT(clk);
  448. for (i = 0; i < clk->enable_bits; i++)
  449. writel(readl(clk->enable_reg[i]) | (1 << clk->enable_offset[i]),
  450. clk->enable_reg[i]);
  451. }
  452. static void clk_sys_disable(xClockProperty *clk)
  453. {
  454. int i;
  455. configASSERT(clk);
  456. for (i = 0; i < clk->enable_bits; i++)
  457. writel(readl(clk->enable_reg[i]) & ~(1 << clk->enable_offset[i]),
  458. clk->enable_reg[i]);
  459. }
  460. void vClkInit(void)
  461. {
  462. int i;
  463. xClockProperty *clk;
  464. for (i = 0; i < CLOCK_NUM; i++) {
  465. clk = &xClocks[i];
  466. if (clk->clktype == PLL_CLOCK) {
  467. clk_pll_init(clk);
  468. } else if (clk->clktype == SYS_CLOCK) {
  469. clk_sys_init(clk);
  470. }
  471. }
  472. }
  473. uint32_t ulClkGetRate(uint32_t clkid)
  474. {
  475. xClockProperty *clk = clk_get(clkid);
  476. if (clk == NULL)
  477. return 0;
  478. switch (clk->clktype) {
  479. case FIXED_CLOCK:
  480. return clk_fixed_get_rate(clk);
  481. case FIXED_FACTOR_CLOCK:
  482. return clk_fixed_factor_get_rate(clk);
  483. case PLL_CLOCK:
  484. return clk_pll_get_rate(clk);
  485. case SYS_CLOCK:
  486. return clk_sys_get_rate(clk);
  487. }
  488. return 0;
  489. }
  490. void vClkSetRate(uint32_t clkid, uint32_t freq)
  491. {
  492. xClockProperty *clk = clk_get(clkid);
  493. if (clk == NULL)
  494. return;
  495. if (clk->clktype == SYS_CLOCK)
  496. clk_sys_set_rate(clk, freq);
  497. }
  498. void vClkEnable(uint32_t clkid)
  499. {
  500. xClockProperty *clk = clk_get(clkid);
  501. if (clk == NULL)
  502. return;
  503. if (clk->clktype == SYS_CLOCK)
  504. clk_sys_enable(clk);
  505. }
  506. void vClkDisable(uint32_t clkid)
  507. {
  508. xClockProperty *clk = clk_get(clkid);
  509. if (clk == NULL)
  510. return;
  511. if (clk->clktype == SYS_CLOCK)
  512. clk_sys_disable(clk);
  513. }