clock.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  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. #ifdef DW_SPI0_SUPPORT
  205. {.clkid = CLK_SPI0, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_CPUPLL},
  206. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  207. .enable_offset = {26, 0}, .enable_bits = 2,
  208. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_SSP_CLK_CFG, .u.sys_property.index_offset = 4,
  209. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 1,
  210. .u.sys_property.div_offset = 0, .u.sys_property.div_mask = 0xf, .u.sys_property.div_mode = DIVMODE_PLUSONE,
  211. #ifndef SPI0_QSPI_MODE
  212. .u.sys_property.div_value = 5,},
  213. #else
  214. .u.sys_property.div_value = 4,},
  215. #endif
  216. #endif
  217. #ifdef EC_SPI1_SUPPORT
  218. {.clkid = CLK_SPI1, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_CPUPLL},
  219. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  220. .enable_offset = {2, 1}, .enable_bits = 2,
  221. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_SSP_CLK_CFG, .u.sys_property.index_offset = 20,
  222. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 0,
  223. .u.sys_property.div_offset = 16, .u.sys_property.div_mask = 0xf,
  224. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  225. #endif
  226. #ifdef DW_SPI2_SUPPORT
  227. {.clkid = CLK_SPI2, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_CPUPLL},
  228. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  229. .enable_offset = {27, 29}, .enable_bits = 2,
  230. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_SSP_CLK_CFG, .u.sys_property.index_offset = 28,
  231. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 0,
  232. .u.sys_property.div_offset = 24, .u.sys_property.div_mask = 0xf,
  233. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  234. #endif
  235. //PWM时钟配置和MCU_PWM是复用的,默认是24Mhz,如果要修改的话需要在MCU工程修改
  236. {.clkid = CLK_PWM, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M, CLK_SYSPLL},
  237. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  238. .enable_offset = {15, 10}, .enable_bits = 2,
  239. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_PER_CLK_CFG, .u.sys_property.index_offset = 8,
  240. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = -1,
  241. .u.sys_property.div_offset = 4, .u.sys_property.div_mask = 0xf,
  242. .u.sys_property.div_value = 1, .u.sys_property.div_mode = DIVMODE_PLUSONE,},
  243. #ifdef ADC0_SUPPORT
  244. {.clkid = CLK_ADC, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M},
  245. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  246. .enable_offset = {5, 13}, .enable_bits = 2,
  247. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_TIMER_CLK_CFG, .u.sys_property.div_offset = 16,
  248. .u.sys_property.div_mask = 0x7fff, .u.sys_property.div_value = 2400,
  249. .u.sys_property.div_mode = DIVMODE_PONEDOUBLE,},
  250. #endif
  251. #ifdef ADC1_SUPPORT
  252. {.clkid = CLK_ADC1, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M},
  253. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN1},
  254. .enable_offset = {25, 14}, .enable_bits = 2,
  255. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_ADC_CLK1_CFG, .u.sys_property.div_offset = 0,
  256. .u.sys_property.div_mask = 0x7fff, .u.sys_property.div_value = 2400,
  257. .u.sys_property.div_mode = DIVMODE_PONEDOUBLE,},
  258. #endif
  259. #ifdef ADC2_SUPPORT
  260. {.clkid = CLK_ADC2, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL24M},
  261. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN1},
  262. .enable_offset = {26, 15}, .enable_bits = 2,
  263. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_ADC_CLK1_CFG, .u.sys_property.div_offset = 16,
  264. .u.sys_property.div_mask = 0x7fff, .u.sys_property.div_value = 2400,
  265. .u.sys_property.div_mode = DIVMODE_PONEDOUBLE,},
  266. #endif
  267. {.clkid = CLK_I2S, .clktype = SYS_CLOCK, .clksource = {CLK_SYSPLL, CLK_AHBPLL},
  268. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN,
  269. REGS_SYSCTL_BASE + SYS_PER_CLK_EN},
  270. .enable_offset = {0, 12, 11}, .enable_bits = 3,
  271. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_PER_CLK_CFG, .u.sys_property.index_offset = 16,
  272. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 0,
  273. .u.sys_property.div_value = 1,},
  274. {.clkid = CLK_I2S1, .clktype = SYS_CLOCK, .clksource = {CLK_SYSPLL, CLK_AHBPLL},
  275. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1, REGS_SYSCTL_BASE + SYS_PER_CLK_EN1,
  276. REGS_SYSCTL_BASE + SYS_PER_CLK_EN1},
  277. .enable_offset = {1, 1, 0}, .enable_bits = 3,
  278. .u.sys_property.cfgreg = REGS_SYSCTL_BASE + SYS_BUS_CLK1_CFG, .u.sys_property.index_offset = 4,
  279. .u.sys_property.index_mask = 0x1, .u.sys_property.index_value = 0,
  280. .u.sys_property.div_value = 1,},
  281. {.clkid = CLK_RTC, .clktype = SYS_CLOCK, .clksource = {CLK_XTAL32K},
  282. .enable_reg = {REGS_SYSCTL_BASE + SYS_BUS_CLK_EN1},
  283. .enable_offset = {8}, .enable_bits = 1,},
  284. {.clkid = CLK_ETH, .clktype = SYS_CLOCK, .clksource = {CLK_AHB},},
  285. };
  286. #define CLOCK_NUM (sizeof(xClocks) / sizeof(xClocks[0]))
  287. static xClockProperty *clk_get(uint32_t clkid)
  288. {
  289. int i;
  290. for (i = 0; i < CLOCK_NUM; i++) {
  291. if (xClocks[i].clkid == clkid) {
  292. return &xClocks[i];
  293. }
  294. }
  295. return NULL;
  296. }
  297. static uint32_t clk_fixed_get_rate(xClockProperty *clk)
  298. {
  299. return clk->u.fixed_freq;
  300. }
  301. static uint32_t clk_fixed_factor_get_rate(xClockProperty *clk)
  302. {
  303. xClockProperty *parentclk = clk_get(clk->clksource[0]);
  304. configASSERT(parentclk);
  305. return clk_fixed_get_rate(parentclk) * clk->u.fixed_fator_property.mult
  306. / clk->u.fixed_fator_property.div;
  307. }
  308. static uint32_t clk_pll_get_rate(xClockProperty *clk)
  309. {
  310. uint32_t reg, parent_rate;
  311. uint32_t posdiv2, posdiv1, fbdiv, refdiv;
  312. uint32_t pllclk;
  313. configASSERT(clk);
  314. parent_rate = ulClkGetRate(clk->clksource[clk->source_index]);
  315. reg = readl(clk->u.pll_property.cfgreg);
  316. if (reg & PLL_BYPASS) {
  317. pllclk = parent_rate;
  318. } else {
  319. posdiv2 = (reg >> PLL_POSTDIV2_OFFSET) & PLL_POSTDIV2_MASK;
  320. posdiv1 = (reg >> PLL_POSTDIV1_OFFSET) & PLL_POSTDIV1_MASK;
  321. fbdiv = (reg >> PLL_FBDIV_OFFSET) & PLL_FBDIV_MASK;
  322. refdiv = (reg >> PLL_REFDIV_OFFSET) & PLL_REFDIV_MASK;
  323. pllclk = (uint64_t)parent_rate * fbdiv / posdiv2 / posdiv1 / refdiv;
  324. }
  325. return pllclk;
  326. }
  327. static uint32_t clk_sys_get_rate(xClockProperty *clk)
  328. {
  329. uint32_t parent_rate;
  330. configASSERT(clk);
  331. configASSERT(clk->div);
  332. parent_rate = ulClkGetRate(clk->clksource[clk->source_index]);
  333. return parent_rate / clk->div;
  334. }
  335. static void clk_pll_init(xClockProperty *clk)
  336. {
  337. configASSERT(clk);
  338. clk->source_index = 0;
  339. }
  340. static int clk_get_div(int div, int divmode)
  341. {
  342. switch(divmode) {
  343. case DIVMODE_NOZERO:
  344. div = div ? div : 1;
  345. break;
  346. case DIVMODE_PLUSONE:
  347. div = div + 1;
  348. break;
  349. case DIVMODE_DOUBLE:
  350. div *= 2;
  351. break;
  352. case DIVMODE_EXPONENT:
  353. div = 1 << div;
  354. break;
  355. case DIVMODE_PONEDOUBLE:
  356. div = (div + 1) * 2;
  357. break;
  358. }
  359. return div;
  360. }
  361. static __INLINE int clk_set_div(int div, int divmode)
  362. {
  363. switch(divmode) {
  364. case DIVMODE_PLUSONE:
  365. div = div - 1;
  366. break;
  367. case DIVMODE_DOUBLE:
  368. div /= 2;
  369. break;
  370. case DIVMODE_EXPONENT:
  371. div = fls(div) - 1;
  372. break;
  373. case DIVMODE_PONEDOUBLE:
  374. div = div / 2 - 1;
  375. break;
  376. }
  377. return div;
  378. }
  379. static void clk_sys_set_rate(xClockProperty *clk, uint32_t freq)
  380. {
  381. int div;
  382. uint32_t reg;
  383. uint32_t parent_rate;
  384. configASSERT(clk);
  385. parent_rate = ulClkGetRate(clk->clksource[clk->source_index]);
  386. div = DIV_ROUND_UP(parent_rate, freq);
  387. clk->div = div;
  388. div = clk_set_div(div, clk->u.sys_property.div_mode);
  389. reg = readl(clk->u.sys_property.cfgreg);
  390. reg &= ~(clk->u.sys_property.div_mask << clk->u.sys_property.div_offset);
  391. reg |= (div & clk->u.sys_property.div_mask) << clk->u.sys_property.div_offset;
  392. writel(reg, clk->u.sys_property.cfgreg);
  393. }
  394. static void clk_sys_init(xClockProperty *clk)
  395. {
  396. uint32_t reg;
  397. uint32_t val;
  398. configASSERT(clk);
  399. if (clk->u.sys_property.index_value >= 0 && clk->u.sys_property.index_mask) {
  400. clk->source_index = clk->u.sys_property.index_value;
  401. val = clk->u.sys_property.index_value == 3 ? 4 : clk->u.sys_property.index_value;
  402. reg = readl(clk->u.sys_property.cfgreg);
  403. reg &= ~(clk->u.sys_property.index_mask << clk->u.sys_property.index_offset);
  404. reg |= (val & clk->u.sys_property.index_mask) << clk->u.sys_property.index_offset;
  405. writel(reg, clk->u.sys_property.cfgreg);
  406. } else if (clk->u.sys_property.index_mask) {
  407. reg = readl(clk->u.sys_property.cfgreg);
  408. val = (reg >> clk->u.sys_property.index_offset) & clk->u.sys_property.index_mask;
  409. clk->source_index = val == 4 ? 3 : val;
  410. }
  411. if (clk->u.sys_property.div_value >= 0 && clk->u.sys_property.div_mask) {
  412. val = clk_set_div(clk->u.sys_property.div_value, clk->u.sys_property.div_mode);
  413. clk->div = clk_get_div(val, clk->u.sys_property.div_mode);
  414. reg = readl(clk->u.sys_property.cfgreg);
  415. reg &= ~(clk->u.sys_property.div_mask << clk->u.sys_property.div_offset);
  416. reg |= (val & clk->u.sys_property.div_mask) << clk->u.sys_property.div_offset;
  417. writel(reg, clk->u.sys_property.cfgreg);
  418. } else if (clk->u.sys_property.div_mask) {
  419. reg = readl(clk->u.sys_property.cfgreg);
  420. val = (reg >> clk->u.sys_property.div_offset) & clk->u.sys_property.div_mask;
  421. clk->div = clk_get_div(val, clk->u.sys_property.div_mode);
  422. } else if (clk->u.sys_property.div_value > 0) {
  423. clk->div = clk->u.sys_property.div_value;
  424. } else {
  425. clk->div = 1;
  426. }
  427. if (clk->u.sys_property.inv_reg) {
  428. reg = readl(clk->u.sys_property.inv_reg);
  429. reg &= ~(clk->u.sys_property.inv_mask << clk->u.sys_property.inv_offset);
  430. reg |= (clk->u.sys_property.inv_value & clk->u.sys_property.inv_mask)
  431. << clk->u.sys_property.inv_offset;
  432. writel(reg, clk->u.sys_property.inv_reg);
  433. }
  434. }
  435. static void clk_sys_enable(xClockProperty *clk)
  436. {
  437. int i;
  438. configASSERT(clk);
  439. for (i = 0; i < clk->enable_bits; i++)
  440. writel(readl(clk->enable_reg[i]) | (1 << clk->enable_offset[i]),
  441. clk->enable_reg[i]);
  442. }
  443. static void clk_sys_disable(xClockProperty *clk)
  444. {
  445. int i;
  446. configASSERT(clk);
  447. for (i = 0; i < clk->enable_bits; i++)
  448. writel(readl(clk->enable_reg[i]) & ~(1 << clk->enable_offset[i]),
  449. clk->enable_reg[i]);
  450. }
  451. void vClkInit(void)
  452. {
  453. int i;
  454. xClockProperty *clk;
  455. for (i = 0; i < CLOCK_NUM; i++) {
  456. clk = &xClocks[i];
  457. if (clk->clktype == PLL_CLOCK) {
  458. clk_pll_init(clk);
  459. } else if (clk->clktype == SYS_CLOCK) {
  460. clk_sys_init(clk);
  461. }
  462. }
  463. }
  464. uint32_t ulClkGetRate(uint32_t clkid)
  465. {
  466. xClockProperty *clk = clk_get(clkid);
  467. if (clk == NULL)
  468. return 0;
  469. switch (clk->clktype) {
  470. case FIXED_CLOCK:
  471. return clk_fixed_get_rate(clk);
  472. case FIXED_FACTOR_CLOCK:
  473. return clk_fixed_factor_get_rate(clk);
  474. case PLL_CLOCK:
  475. return clk_pll_get_rate(clk);
  476. case SYS_CLOCK:
  477. return clk_sys_get_rate(clk);
  478. }
  479. return 0;
  480. }
  481. void vClkSetRate(uint32_t clkid, uint32_t freq)
  482. {
  483. xClockProperty *clk = clk_get(clkid);
  484. if (clk == NULL)
  485. return;
  486. if (clk->clktype == SYS_CLOCK)
  487. clk_sys_set_rate(clk, freq);
  488. }
  489. void vClkEnable(uint32_t clkid)
  490. {
  491. xClockProperty *clk = clk_get(clkid);
  492. if (clk == NULL)
  493. return;
  494. if (clk->clktype == SYS_CLOCK)
  495. clk_sys_enable(clk);
  496. }
  497. void vClkDisable(uint32_t clkid)
  498. {
  499. xClockProperty *clk = clk_get(clkid);
  500. if (clk == NULL)
  501. return;
  502. if (clk->clktype == SYS_CLOCK)
  503. clk_sys_disable(clk);
  504. }