ccu-suniv-f1c100s.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2016 Icenowy Zheng <[email protected]>
  4. *
  5. */
  6. #include <linux/clk-provider.h>
  7. #include <linux/io.h>
  8. #include <linux/module.h>
  9. #include <linux/platform_device.h>
  10. #include "ccu_common.h"
  11. #include "ccu_reset.h"
  12. #include "ccu_div.h"
  13. #include "ccu_gate.h"
  14. #include "ccu_mp.h"
  15. #include "ccu_mult.h"
  16. #include "ccu_nk.h"
  17. #include "ccu_nkm.h"
  18. #include "ccu_nkmp.h"
  19. #include "ccu_nm.h"
  20. #include "ccu_phase.h"
  21. #include "ccu-suniv-f1c100s.h"
  22. static struct ccu_nkmp pll_cpu_clk = {
  23. .enable = BIT(31),
  24. .lock = BIT(28),
  25. .n = _SUNXI_CCU_MULT(8, 5),
  26. .k = _SUNXI_CCU_MULT(4, 2),
  27. .m = _SUNXI_CCU_DIV(0, 2),
  28. /* MAX is guessed by the BSP table */
  29. .p = _SUNXI_CCU_DIV_MAX(16, 2, 4),
  30. .common = {
  31. .reg = 0x000,
  32. .hw.init = CLK_HW_INIT("pll-cpu", "osc24M",
  33. &ccu_nkmp_ops,
  34. CLK_SET_RATE_UNGATE),
  35. },
  36. };
  37. /*
  38. * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from
  39. * the base (2x, 4x and 8x), and one variable divider (the one true
  40. * pll audio).
  41. *
  42. * We don't have any need for the variable divider for now, so we just
  43. * hardcode it to match with the clock names
  44. */
  45. #define SUNIV_PLL_AUDIO_REG 0x008
  46. static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
  47. "osc24M", 0x008,
  48. 8, 7, /* N */
  49. 0, 5, /* M */
  50. BIT(31), /* gate */
  51. BIT(28), /* lock */
  52. CLK_SET_RATE_UNGATE);
  53. static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video_clk, "pll-video",
  54. "osc24M", 0x010,
  55. 8, 7, /* N */
  56. 0, 4, /* M */
  57. BIT(24), /* frac enable */
  58. BIT(25), /* frac select */
  59. 270000000, /* frac rate 0 */
  60. 297000000, /* frac rate 1 */
  61. BIT(31), /* gate */
  62. BIT(28), /* lock */
  63. CLK_SET_RATE_UNGATE);
  64. static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve",
  65. "osc24M", 0x018,
  66. 8, 7, /* N */
  67. 0, 4, /* M */
  68. BIT(24), /* frac enable */
  69. BIT(25), /* frac select */
  70. 270000000, /* frac rate 0 */
  71. 297000000, /* frac rate 1 */
  72. BIT(31), /* gate */
  73. BIT(28), /* lock */
  74. CLK_SET_RATE_UNGATE);
  75. static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr0_clk, "pll-ddr",
  76. "osc24M", 0x020,
  77. 8, 5, /* N */
  78. 4, 2, /* K */
  79. 0, 2, /* M */
  80. BIT(31), /* gate */
  81. BIT(28), /* lock */
  82. CLK_IS_CRITICAL);
  83. static struct ccu_nk pll_periph_clk = {
  84. .enable = BIT(31),
  85. .lock = BIT(28),
  86. .k = _SUNXI_CCU_MULT(4, 2),
  87. .n = _SUNXI_CCU_MULT(8, 5),
  88. .common = {
  89. .reg = 0x028,
  90. .hw.init = CLK_HW_INIT("pll-periph", "osc24M",
  91. &ccu_nk_ops, 0),
  92. },
  93. };
  94. static const char * const cpu_parents[] = { "osc32k", "osc24M",
  95. "pll-cpu", "pll-cpu" };
  96. static SUNXI_CCU_MUX(cpu_clk, "cpu", cpu_parents,
  97. 0x050, 16, 2, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT);
  98. static const char * const ahb_parents[] = { "osc32k", "osc24M",
  99. "cpu", "pll-periph" };
  100. static const struct ccu_mux_var_prediv ahb_predivs[] = {
  101. { .index = 3, .shift = 6, .width = 2 },
  102. };
  103. static struct ccu_div ahb_clk = {
  104. .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
  105. .mux = {
  106. .shift = 12,
  107. .width = 2,
  108. .var_predivs = ahb_predivs,
  109. .n_var_predivs = ARRAY_SIZE(ahb_predivs),
  110. },
  111. .common = {
  112. .reg = 0x054,
  113. .features = CCU_FEATURE_VARIABLE_PREDIV,
  114. .hw.init = CLK_HW_INIT_PARENTS("ahb",
  115. ahb_parents,
  116. &ccu_div_ops,
  117. 0),
  118. },
  119. };
  120. static struct clk_div_table apb_div_table[] = {
  121. { .val = 0, .div = 2 },
  122. { .val = 1, .div = 2 },
  123. { .val = 2, .div = 4 },
  124. { .val = 3, .div = 8 },
  125. { /* Sentinel */ },
  126. };
  127. static SUNXI_CCU_DIV_TABLE(apb_clk, "apb", "ahb",
  128. 0x054, 8, 2, apb_div_table, 0);
  129. static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "ahb",
  130. 0x060, BIT(6), 0);
  131. static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb",
  132. 0x060, BIT(8), 0);
  133. static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb",
  134. 0x060, BIT(9), 0);
  135. static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "ahb",
  136. 0x060, BIT(14), 0);
  137. static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb",
  138. 0x060, BIT(20), 0);
  139. static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb",
  140. 0x060, BIT(21), 0);
  141. static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb",
  142. 0x060, BIT(24), 0);
  143. static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "ahb",
  144. 0x064, BIT(0), 0);
  145. static SUNXI_CCU_GATE(bus_lcd_clk, "bus-lcd", "ahb",
  146. 0x064, BIT(4), 0);
  147. static SUNXI_CCU_GATE(bus_deinterlace_clk, "bus-deinterlace", "ahb",
  148. 0x064, BIT(5), 0);
  149. static SUNXI_CCU_GATE(bus_csi_clk, "bus-csi", "ahb",
  150. 0x064, BIT(8), 0);
  151. static SUNXI_CCU_GATE(bus_tvd_clk, "bus-tvd", "ahb",
  152. 0x064, BIT(9), 0);
  153. static SUNXI_CCU_GATE(bus_tve_clk, "bus-tve", "ahb",
  154. 0x064, BIT(10), 0);
  155. static SUNXI_CCU_GATE(bus_de_be_clk, "bus-de-be", "ahb",
  156. 0x064, BIT(12), 0);
  157. static SUNXI_CCU_GATE(bus_de_fe_clk, "bus-de-fe", "ahb",
  158. 0x064, BIT(14), 0);
  159. static SUNXI_CCU_GATE(bus_codec_clk, "bus-codec", "apb",
  160. 0x068, BIT(0), 0);
  161. static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb",
  162. 0x068, BIT(1), 0);
  163. static SUNXI_CCU_GATE(bus_ir_clk, "bus-ir", "apb",
  164. 0x068, BIT(2), 0);
  165. static SUNXI_CCU_GATE(bus_rsb_clk, "bus-rsb", "apb",
  166. 0x068, BIT(3), 0);
  167. static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb",
  168. 0x068, BIT(12), 0);
  169. static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb",
  170. 0x068, BIT(16), 0);
  171. static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb",
  172. 0x068, BIT(17), 0);
  173. static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb",
  174. 0x068, BIT(18), 0);
  175. static SUNXI_CCU_GATE(bus_pio_clk, "bus-pio", "apb",
  176. 0x068, BIT(19), 0);
  177. static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb",
  178. 0x068, BIT(20), 0);
  179. static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb",
  180. 0x068, BIT(21), 0);
  181. static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb",
  182. 0x068, BIT(22), 0);
  183. static const char * const mod0_default_parents[] = { "osc24M", "pll-periph" };
  184. static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mod0_default_parents, 0x088,
  185. 0, 4, /* M */
  186. 16, 2, /* P */
  187. 24, 2, /* mux */
  188. BIT(31), /* gate */
  189. 0);
  190. static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0_sample", "mmc0",
  191. 0x088, 20, 3, 0);
  192. static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0_output", "mmc0",
  193. 0x088, 8, 3, 0);
  194. static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mod0_default_parents, 0x08c,
  195. 0, 4, /* M */
  196. 16, 2, /* P */
  197. 24, 2, /* mux */
  198. BIT(31), /* gate */
  199. 0);
  200. static SUNXI_CCU_PHASE(mmc1_sample_clk, "mmc1_sample", "mmc1",
  201. 0x08c, 20, 3, 0);
  202. static SUNXI_CCU_PHASE(mmc1_output_clk, "mmc1_output", "mmc1",
  203. 0x08c, 8, 3, 0);
  204. static const char * const i2s_spdif_parents[] = { "pll-audio-8x",
  205. "pll-audio-4x",
  206. "pll-audio-2x",
  207. "pll-audio" };
  208. static SUNXI_CCU_MUX_WITH_GATE(i2s_clk, "i2s", i2s_spdif_parents,
  209. 0x0b0, 16, 2, BIT(31), 0);
  210. static SUNXI_CCU_MUX_WITH_GATE(spdif_clk, "spdif", i2s_spdif_parents,
  211. 0x0b4, 16, 2, BIT(31), 0);
  212. /* The BSP header file has a CIR_CFG, but no mod clock uses this definition */
  213. static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M",
  214. 0x0cc, BIT(1), 0);
  215. static SUNXI_CCU_GATE(dram_ve_clk, "dram-ve", "pll-ddr",
  216. 0x100, BIT(0), 0);
  217. static SUNXI_CCU_GATE(dram_csi_clk, "dram-csi", "pll-ddr",
  218. 0x100, BIT(1), 0);
  219. static SUNXI_CCU_GATE(dram_deinterlace_clk, "dram-deinterlace",
  220. "pll-ddr", 0x100, BIT(2), 0);
  221. static SUNXI_CCU_GATE(dram_tvd_clk, "dram-tvd", "pll-ddr",
  222. 0x100, BIT(3), 0);
  223. static SUNXI_CCU_GATE(dram_de_fe_clk, "dram-de-fe", "pll-ddr",
  224. 0x100, BIT(24), 0);
  225. static SUNXI_CCU_GATE(dram_de_be_clk, "dram-de-be", "pll-ddr",
  226. 0x100, BIT(26), 0);
  227. static const char * const de_parents[] = { "pll-video", "pll-periph" };
  228. static const u8 de_table[] = { 0, 2, };
  229. static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(de_be_clk, "de-be",
  230. de_parents, de_table,
  231. 0x104, 0, 4, 24, 3, BIT(31), 0);
  232. static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(de_fe_clk, "de-fe",
  233. de_parents, de_table,
  234. 0x10c, 0, 4, 24, 3, BIT(31), 0);
  235. static const char * const tcon_parents[] = { "pll-video", "pll-video-2x" };
  236. static const u8 tcon_table[] = { 0, 2, };
  237. static SUNXI_CCU_MUX_TABLE_WITH_GATE(tcon_clk, "tcon",
  238. tcon_parents, tcon_table,
  239. 0x118, 24, 3, BIT(31),
  240. CLK_SET_RATE_PARENT);
  241. static const char * const deinterlace_parents[] = { "pll-video",
  242. "pll-video-2x" };
  243. static const u8 deinterlace_table[] = { 0, 2, };
  244. static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(deinterlace_clk, "deinterlace",
  245. deinterlace_parents, deinterlace_table,
  246. 0x11c, 0, 4, 24, 3, BIT(31), 0);
  247. static const char * const tve_clk2_parents[] = { "pll-video",
  248. "pll-video-2x" };
  249. static const u8 tve_clk2_table[] = { 0, 2, };
  250. static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(tve_clk2_clk, "tve-clk2",
  251. tve_clk2_parents, tve_clk2_table,
  252. 0x120, 0, 4, 24, 3, BIT(31), 0);
  253. static SUNXI_CCU_M_WITH_GATE(tve_clk1_clk, "tve-clk1", "tve-clk2",
  254. 0x120, 8, 1, BIT(15), 0);
  255. static const char * const tvd_parents[] = { "pll-video", "osc24M",
  256. "pll-video-2x" };
  257. static SUNXI_CCU_M_WITH_MUX_GATE(tvd_clk, "tvd", tvd_parents,
  258. 0x124, 0, 4, 24, 3, BIT(31), 0);
  259. static const char * const csi_parents[] = { "pll-video", "osc24M" };
  260. static const u8 csi_table[] = { 0, 5, };
  261. static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi_clk, "csi", csi_parents, csi_table,
  262. 0x120, 0, 4, 8, 3, BIT(15), 0);
  263. /*
  264. * TODO: BSP says the parent is pll-audio, however common sense and experience
  265. * told us it should be pll-ve. pll-ve is totally not used in BSP code.
  266. */
  267. static SUNXI_CCU_GATE(ve_clk, "ve", "pll-audio", 0x13c, BIT(31), 0);
  268. static SUNXI_CCU_GATE(codec_clk, "codec", "pll-audio", 0x140, BIT(31), 0);
  269. static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x144, BIT(31), 0);
  270. static struct ccu_common *suniv_ccu_clks[] = {
  271. &pll_cpu_clk.common,
  272. &pll_audio_base_clk.common,
  273. &pll_video_clk.common,
  274. &pll_ve_clk.common,
  275. &pll_ddr0_clk.common,
  276. &pll_periph_clk.common,
  277. &cpu_clk.common,
  278. &ahb_clk.common,
  279. &apb_clk.common,
  280. &bus_dma_clk.common,
  281. &bus_mmc0_clk.common,
  282. &bus_mmc1_clk.common,
  283. &bus_dram_clk.common,
  284. &bus_spi0_clk.common,
  285. &bus_spi1_clk.common,
  286. &bus_otg_clk.common,
  287. &bus_ve_clk.common,
  288. &bus_lcd_clk.common,
  289. &bus_deinterlace_clk.common,
  290. &bus_csi_clk.common,
  291. &bus_tve_clk.common,
  292. &bus_tvd_clk.common,
  293. &bus_de_be_clk.common,
  294. &bus_de_fe_clk.common,
  295. &bus_codec_clk.common,
  296. &bus_spdif_clk.common,
  297. &bus_ir_clk.common,
  298. &bus_rsb_clk.common,
  299. &bus_i2s0_clk.common,
  300. &bus_i2c0_clk.common,
  301. &bus_i2c1_clk.common,
  302. &bus_i2c2_clk.common,
  303. &bus_pio_clk.common,
  304. &bus_uart0_clk.common,
  305. &bus_uart1_clk.common,
  306. &bus_uart2_clk.common,
  307. &mmc0_clk.common,
  308. &mmc0_sample_clk.common,
  309. &mmc0_output_clk.common,
  310. &mmc1_clk.common,
  311. &mmc1_sample_clk.common,
  312. &mmc1_output_clk.common,
  313. &i2s_clk.common,
  314. &spdif_clk.common,
  315. &usb_phy0_clk.common,
  316. &dram_ve_clk.common,
  317. &dram_csi_clk.common,
  318. &dram_deinterlace_clk.common,
  319. &dram_tvd_clk.common,
  320. &dram_de_fe_clk.common,
  321. &dram_de_be_clk.common,
  322. &de_be_clk.common,
  323. &de_fe_clk.common,
  324. &tcon_clk.common,
  325. &deinterlace_clk.common,
  326. &tve_clk2_clk.common,
  327. &tve_clk1_clk.common,
  328. &tvd_clk.common,
  329. &csi_clk.common,
  330. &ve_clk.common,
  331. &codec_clk.common,
  332. &avs_clk.common,
  333. };
  334. static const struct clk_hw *clk_parent_pll_audio[] = {
  335. &pll_audio_base_clk.common.hw
  336. };
  337. static CLK_FIXED_FACTOR_HWS(pll_audio_clk, "pll-audio",
  338. clk_parent_pll_audio,
  339. 4, 1, CLK_SET_RATE_PARENT);
  340. static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
  341. clk_parent_pll_audio,
  342. 2, 1, CLK_SET_RATE_PARENT);
  343. static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
  344. clk_parent_pll_audio,
  345. 1, 1, CLK_SET_RATE_PARENT);
  346. static CLK_FIXED_FACTOR_HWS(pll_audio_8x_clk, "pll-audio-8x",
  347. clk_parent_pll_audio,
  348. 1, 2, CLK_SET_RATE_PARENT);
  349. static CLK_FIXED_FACTOR_HW(pll_video_2x_clk, "pll-video-2x",
  350. &pll_video_clk.common.hw,
  351. 1, 2, 0);
  352. static struct clk_hw_onecell_data suniv_hw_clks = {
  353. .hws = {
  354. [CLK_PLL_CPU] = &pll_cpu_clk.common.hw,
  355. [CLK_PLL_AUDIO_BASE] = &pll_audio_base_clk.common.hw,
  356. [CLK_PLL_AUDIO] = &pll_audio_clk.hw,
  357. [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw,
  358. [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw,
  359. [CLK_PLL_AUDIO_8X] = &pll_audio_8x_clk.hw,
  360. [CLK_PLL_VIDEO] = &pll_video_clk.common.hw,
  361. [CLK_PLL_VIDEO_2X] = &pll_video_2x_clk.hw,
  362. [CLK_PLL_VE] = &pll_ve_clk.common.hw,
  363. [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw,
  364. [CLK_PLL_PERIPH] = &pll_periph_clk.common.hw,
  365. [CLK_CPU] = &cpu_clk.common.hw,
  366. [CLK_AHB] = &ahb_clk.common.hw,
  367. [CLK_APB] = &apb_clk.common.hw,
  368. [CLK_BUS_DMA] = &bus_dma_clk.common.hw,
  369. [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw,
  370. [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw,
  371. [CLK_BUS_DRAM] = &bus_dram_clk.common.hw,
  372. [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw,
  373. [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw,
  374. [CLK_BUS_OTG] = &bus_otg_clk.common.hw,
  375. [CLK_BUS_VE] = &bus_ve_clk.common.hw,
  376. [CLK_BUS_LCD] = &bus_lcd_clk.common.hw,
  377. [CLK_BUS_DEINTERLACE] = &bus_deinterlace_clk.common.hw,
  378. [CLK_BUS_CSI] = &bus_csi_clk.common.hw,
  379. [CLK_BUS_TVD] = &bus_tvd_clk.common.hw,
  380. [CLK_BUS_TVE] = &bus_tve_clk.common.hw,
  381. [CLK_BUS_DE_BE] = &bus_de_be_clk.common.hw,
  382. [CLK_BUS_DE_FE] = &bus_de_fe_clk.common.hw,
  383. [CLK_BUS_CODEC] = &bus_codec_clk.common.hw,
  384. [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw,
  385. [CLK_BUS_IR] = &bus_ir_clk.common.hw,
  386. [CLK_BUS_RSB] = &bus_rsb_clk.common.hw,
  387. [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw,
  388. [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw,
  389. [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw,
  390. [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw,
  391. [CLK_BUS_PIO] = &bus_pio_clk.common.hw,
  392. [CLK_BUS_UART0] = &bus_uart0_clk.common.hw,
  393. [CLK_BUS_UART1] = &bus_uart1_clk.common.hw,
  394. [CLK_BUS_UART2] = &bus_uart2_clk.common.hw,
  395. [CLK_MMC0] = &mmc0_clk.common.hw,
  396. [CLK_MMC0_SAMPLE] = &mmc0_sample_clk.common.hw,
  397. [CLK_MMC0_OUTPUT] = &mmc0_output_clk.common.hw,
  398. [CLK_MMC1] = &mmc1_clk.common.hw,
  399. [CLK_MMC1_SAMPLE] = &mmc1_sample_clk.common.hw,
  400. [CLK_MMC1_OUTPUT] = &mmc1_output_clk.common.hw,
  401. [CLK_I2S] = &i2s_clk.common.hw,
  402. [CLK_SPDIF] = &spdif_clk.common.hw,
  403. [CLK_USB_PHY0] = &usb_phy0_clk.common.hw,
  404. [CLK_DRAM_VE] = &dram_ve_clk.common.hw,
  405. [CLK_DRAM_CSI] = &dram_csi_clk.common.hw,
  406. [CLK_DRAM_DEINTERLACE] = &dram_deinterlace_clk.common.hw,
  407. [CLK_DRAM_TVD] = &dram_tvd_clk.common.hw,
  408. [CLK_DRAM_DE_FE] = &dram_de_fe_clk.common.hw,
  409. [CLK_DRAM_DE_BE] = &dram_de_be_clk.common.hw,
  410. [CLK_DE_BE] = &de_be_clk.common.hw,
  411. [CLK_DE_FE] = &de_fe_clk.common.hw,
  412. [CLK_TCON] = &tcon_clk.common.hw,
  413. [CLK_DEINTERLACE] = &deinterlace_clk.common.hw,
  414. [CLK_TVE2_CLK] = &tve_clk2_clk.common.hw,
  415. [CLK_TVE1_CLK] = &tve_clk1_clk.common.hw,
  416. [CLK_TVD] = &tvd_clk.common.hw,
  417. [CLK_CSI] = &csi_clk.common.hw,
  418. [CLK_VE] = &ve_clk.common.hw,
  419. [CLK_CODEC] = &codec_clk.common.hw,
  420. [CLK_AVS] = &avs_clk.common.hw,
  421. },
  422. .num = CLK_NUMBER,
  423. };
  424. static struct ccu_reset_map suniv_ccu_resets[] = {
  425. [RST_USB_PHY0] = { 0x0cc, BIT(0) },
  426. [RST_BUS_DMA] = { 0x2c0, BIT(6) },
  427. [RST_BUS_MMC0] = { 0x2c0, BIT(8) },
  428. [RST_BUS_MMC1] = { 0x2c0, BIT(9) },
  429. [RST_BUS_DRAM] = { 0x2c0, BIT(14) },
  430. [RST_BUS_SPI0] = { 0x2c0, BIT(20) },
  431. [RST_BUS_SPI1] = { 0x2c0, BIT(21) },
  432. [RST_BUS_OTG] = { 0x2c0, BIT(24) },
  433. [RST_BUS_VE] = { 0x2c4, BIT(0) },
  434. [RST_BUS_LCD] = { 0x2c4, BIT(4) },
  435. [RST_BUS_DEINTERLACE] = { 0x2c4, BIT(5) },
  436. [RST_BUS_CSI] = { 0x2c4, BIT(8) },
  437. [RST_BUS_TVD] = { 0x2c4, BIT(9) },
  438. [RST_BUS_TVE] = { 0x2c4, BIT(10) },
  439. [RST_BUS_DE_BE] = { 0x2c4, BIT(12) },
  440. [RST_BUS_DE_FE] = { 0x2c4, BIT(14) },
  441. [RST_BUS_CODEC] = { 0x2d0, BIT(0) },
  442. [RST_BUS_SPDIF] = { 0x2d0, BIT(1) },
  443. [RST_BUS_IR] = { 0x2d0, BIT(2) },
  444. [RST_BUS_RSB] = { 0x2d0, BIT(3) },
  445. [RST_BUS_I2S0] = { 0x2d0, BIT(12) },
  446. [RST_BUS_I2C0] = { 0x2d0, BIT(16) },
  447. [RST_BUS_I2C1] = { 0x2d0, BIT(17) },
  448. [RST_BUS_I2C2] = { 0x2d0, BIT(18) },
  449. [RST_BUS_UART0] = { 0x2d0, BIT(20) },
  450. [RST_BUS_UART1] = { 0x2d0, BIT(21) },
  451. [RST_BUS_UART2] = { 0x2d0, BIT(22) },
  452. };
  453. static const struct sunxi_ccu_desc suniv_ccu_desc = {
  454. .ccu_clks = suniv_ccu_clks,
  455. .num_ccu_clks = ARRAY_SIZE(suniv_ccu_clks),
  456. .hw_clks = &suniv_hw_clks,
  457. .resets = suniv_ccu_resets,
  458. .num_resets = ARRAY_SIZE(suniv_ccu_resets),
  459. };
  460. static struct ccu_pll_nb suniv_pll_cpu_nb = {
  461. .common = &pll_cpu_clk.common,
  462. /* copy from pll_cpu_clk */
  463. .enable = BIT(31),
  464. .lock = BIT(28),
  465. };
  466. static struct ccu_mux_nb suniv_cpu_nb = {
  467. .common = &cpu_clk.common,
  468. .cm = &cpu_clk.mux,
  469. .delay_us = 1, /* > 8 clock cycles at 24 MHz */
  470. .bypass_index = 1, /* index of 24 MHz oscillator */
  471. };
  472. static int suniv_f1c100s_ccu_probe(struct platform_device *pdev)
  473. {
  474. void __iomem *reg;
  475. int ret;
  476. u32 val;
  477. reg = devm_platform_ioremap_resource(pdev, 0);
  478. if (IS_ERR(reg))
  479. return PTR_ERR(reg);
  480. /* Force the PLL-Audio-1x divider to 4 */
  481. val = readl(reg + SUNIV_PLL_AUDIO_REG);
  482. val &= ~GENMASK(19, 16);
  483. writel(val | (3 << 16), reg + SUNIV_PLL_AUDIO_REG);
  484. ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &suniv_ccu_desc);
  485. if (ret)
  486. return ret;
  487. /* Gate then ungate PLL CPU after any rate changes */
  488. ccu_pll_notifier_register(&suniv_pll_cpu_nb);
  489. /* Reparent CPU during PLL CPU rate changes */
  490. ccu_mux_notifier_register(pll_cpu_clk.common.hw.clk,
  491. &suniv_cpu_nb);
  492. return 0;
  493. }
  494. static const struct of_device_id suniv_f1c100s_ccu_ids[] = {
  495. { .compatible = "allwinner,suniv-f1c100s-ccu" },
  496. { }
  497. };
  498. static struct platform_driver suniv_f1c100s_ccu_driver = {
  499. .probe = suniv_f1c100s_ccu_probe,
  500. .driver = {
  501. .name = "suniv-f1c100s-ccu",
  502. .suppress_bind_attrs = true,
  503. .of_match_table = suniv_f1c100s_ccu_ids,
  504. },
  505. };
  506. module_platform_driver(suniv_f1c100s_ccu_driver);
  507. MODULE_IMPORT_NS(SUNXI_CCU);
  508. MODULE_LICENSE("GPL");