ccu-sun50i-a100.c 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2020 Yangtao Li <[email protected]>
  4. */
  5. #include <linux/clk-provider.h>
  6. #include <linux/io.h>
  7. #include <linux/module.h>
  8. #include <linux/platform_device.h>
  9. #include "ccu_common.h"
  10. #include "ccu_reset.h"
  11. #include "ccu_div.h"
  12. #include "ccu_gate.h"
  13. #include "ccu_mp.h"
  14. #include "ccu_mult.h"
  15. #include "ccu_nk.h"
  16. #include "ccu_nkm.h"
  17. #include "ccu_nkmp.h"
  18. #include "ccu_nm.h"
  19. #include "ccu-sun50i-a100.h"
  20. #define SUN50I_A100_PLL_SDM_ENABLE BIT(24)
  21. #define SUN50I_A100_PLL_OUTPUT_ENABLE BIT(27)
  22. #define SUN50I_A100_PLL_LOCK BIT(28)
  23. #define SUN50I_A100_PLL_LOCK_ENABLE BIT(29)
  24. #define SUN50I_A100_PLL_ENABLE BIT(31)
  25. #define SUN50I_A100_PLL_PERIPH1_PATTERN0 0xd1303333
  26. /*
  27. * The CPU PLL is actually NP clock, with P being /1, /2 or /4. However
  28. * P should only be used for output frequencies lower than 288 MHz.
  29. *
  30. * For now we can just model it as a multiplier clock, and force P to /1.
  31. *
  32. * The M factor is present in the register's description, but not in the
  33. * frequency formula, and it's documented as "M is only used for backdoor
  34. * testing", so it's not modelled and then force to 0.
  35. */
  36. #define SUN50I_A100_PLL_CPUX_REG 0x000
  37. static struct ccu_mult pll_cpux_clk = {
  38. .enable = SUN50I_A100_PLL_OUTPUT_ENABLE,
  39. .lock = SUN50I_A100_PLL_LOCK,
  40. .mult = _SUNXI_CCU_MULT_MIN(8, 8, 12),
  41. .common = {
  42. .reg = 0x000,
  43. .hw.init = CLK_HW_INIT("pll-cpux", "dcxo24M",
  44. &ccu_mult_ops,
  45. CLK_SET_RATE_UNGATE),
  46. },
  47. };
  48. /* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
  49. #define SUN50I_A100_PLL_DDR0_REG 0x010
  50. static struct ccu_nkmp pll_ddr0_clk = {
  51. .enable = SUN50I_A100_PLL_OUTPUT_ENABLE,
  52. .lock = SUN50I_A100_PLL_LOCK,
  53. .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
  54. .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
  55. .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
  56. .common = {
  57. .reg = 0x010,
  58. .hw.init = CLK_HW_INIT("pll-ddr0", "dcxo24M",
  59. &ccu_nkmp_ops,
  60. CLK_SET_RATE_UNGATE |
  61. CLK_IS_CRITICAL),
  62. },
  63. };
  64. #define SUN50I_A100_PLL_PERIPH0_REG 0x020
  65. static struct ccu_nkmp pll_periph0_clk = {
  66. .enable = SUN50I_A100_PLL_OUTPUT_ENABLE,
  67. .lock = SUN50I_A100_PLL_LOCK,
  68. .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
  69. .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
  70. .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
  71. .fixed_post_div = 2,
  72. .common = {
  73. .reg = 0x020,
  74. .features = CCU_FEATURE_FIXED_POSTDIV,
  75. .hw.init = CLK_HW_INIT("pll-periph0", "dcxo24M",
  76. &ccu_nkmp_ops,
  77. CLK_SET_RATE_UNGATE),
  78. },
  79. };
  80. #define SUN50I_A100_PLL_PERIPH1_REG 0x028
  81. static struct ccu_nkmp pll_periph1_clk = {
  82. .enable = SUN50I_A100_PLL_OUTPUT_ENABLE,
  83. .lock = SUN50I_A100_PLL_LOCK,
  84. .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
  85. .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
  86. .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
  87. .fixed_post_div = 2,
  88. .common = {
  89. .reg = 0x028,
  90. .features = CCU_FEATURE_FIXED_POSTDIV,
  91. .hw.init = CLK_HW_INIT("pll-periph1", "dcxo24M",
  92. &ccu_nkmp_ops,
  93. CLK_SET_RATE_UNGATE),
  94. },
  95. };
  96. #define SUN50I_A100_PLL_PERIPH1_PATTERN0_REG 0x128
  97. #define SUN50I_A100_PLL_GPU_REG 0x030
  98. static struct ccu_nkmp pll_gpu_clk = {
  99. .enable = SUN50I_A100_PLL_OUTPUT_ENABLE,
  100. .lock = SUN50I_A100_PLL_LOCK,
  101. .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
  102. .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
  103. .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
  104. .common = {
  105. .reg = 0x030,
  106. .hw.init = CLK_HW_INIT("pll-gpu", "dcxo24M",
  107. &ccu_nkmp_ops,
  108. CLK_SET_RATE_UNGATE),
  109. },
  110. };
  111. /*
  112. * For Video PLLs, the output divider is described as "used for testing"
  113. * in the user manual. So it's not modelled and forced to 0.
  114. */
  115. #define SUN50I_A100_PLL_VIDEO0_REG 0x040
  116. static struct ccu_nm pll_video0_clk = {
  117. .enable = SUN50I_A100_PLL_OUTPUT_ENABLE,
  118. .lock = SUN50I_A100_PLL_LOCK,
  119. .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
  120. .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
  121. .fixed_post_div = 4,
  122. .common = {
  123. .reg = 0x040,
  124. .features = CCU_FEATURE_FIXED_POSTDIV,
  125. .hw.init = CLK_HW_INIT("pll-video0", "dcxo24M",
  126. &ccu_nm_ops,
  127. CLK_SET_RATE_UNGATE),
  128. },
  129. };
  130. #define SUN50I_A100_PLL_VIDEO1_REG 0x048
  131. static struct ccu_nm pll_video1_clk = {
  132. .enable = SUN50I_A100_PLL_OUTPUT_ENABLE,
  133. .lock = SUN50I_A100_PLL_LOCK,
  134. .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
  135. .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
  136. .fixed_post_div = 4,
  137. .common = {
  138. .reg = 0x048,
  139. .features = CCU_FEATURE_FIXED_POSTDIV,
  140. .hw.init = CLK_HW_INIT("pll-video1", "dcxo24M",
  141. &ccu_nm_ops,
  142. CLK_SET_RATE_UNGATE),
  143. },
  144. };
  145. #define SUN50I_A100_PLL_VIDEO2_REG 0x050
  146. static struct ccu_nm pll_video2_clk = {
  147. .enable = SUN50I_A100_PLL_OUTPUT_ENABLE,
  148. .lock = SUN50I_A100_PLL_LOCK,
  149. .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
  150. .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
  151. .fixed_post_div = 4,
  152. .common = {
  153. .reg = 0x050,
  154. .features = CCU_FEATURE_FIXED_POSTDIV,
  155. .hw.init = CLK_HW_INIT("pll-video2", "dcxo24M",
  156. &ccu_nm_ops,
  157. CLK_SET_RATE_UNGATE),
  158. },
  159. };
  160. #define SUN50I_A100_PLL_VE_REG 0x058
  161. static struct ccu_nkmp pll_ve_clk = {
  162. .enable = SUN50I_A100_PLL_OUTPUT_ENABLE,
  163. .lock = SUN50I_A100_PLL_LOCK,
  164. .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
  165. .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
  166. .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
  167. .common = {
  168. .reg = 0x058,
  169. .hw.init = CLK_HW_INIT("pll-ve", "dcxo24M",
  170. &ccu_nkmp_ops,
  171. CLK_SET_RATE_UNGATE),
  172. },
  173. };
  174. /*
  175. * The COM PLL has m0 dividers in addition to the usual N, M
  176. * factors. Since we only need 1 frequencies from this PLL: 45.1584 MHz,
  177. * ignore it for now.
  178. */
  179. #define SUN50I_A100_PLL_COM_REG 0x060
  180. static struct ccu_sdm_setting pll_com_sdm_table[] = {
  181. { .rate = 451584000, .pattern = 0xc0014396, .m = 2, .n = 37 },
  182. };
  183. static struct ccu_nm pll_com_clk = {
  184. .enable = SUN50I_A100_PLL_OUTPUT_ENABLE,
  185. .lock = SUN50I_A100_PLL_LOCK,
  186. .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
  187. .m = _SUNXI_CCU_DIV(0, 1),
  188. .sdm = _SUNXI_CCU_SDM(pll_com_sdm_table, BIT(24),
  189. 0x160, BIT(31)),
  190. .common = {
  191. .reg = 0x060,
  192. .features = CCU_FEATURE_SIGMA_DELTA_MOD,
  193. .hw.init = CLK_HW_INIT("pll-com", "dcxo24M",
  194. &ccu_nm_ops,
  195. CLK_SET_RATE_UNGATE),
  196. },
  197. };
  198. #define SUN50I_A100_PLL_VIDEO3_REG 0x068
  199. static struct ccu_nm pll_video3_clk = {
  200. .enable = SUN50I_A100_PLL_OUTPUT_ENABLE,
  201. .lock = SUN50I_A100_PLL_LOCK,
  202. .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
  203. .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
  204. .fixed_post_div = 4,
  205. .common = {
  206. .reg = 0x068,
  207. .features = CCU_FEATURE_FIXED_POSTDIV,
  208. .hw.init = CLK_HW_INIT("pll-video3", "dcxo24M",
  209. &ccu_nm_ops,
  210. CLK_SET_RATE_UNGATE),
  211. },
  212. };
  213. /*
  214. * The Audio PLL has m0, m1 dividers in addition to the usual N, M
  215. * factors. Since we only need 4 frequencies from this PLL: 22.5792 MHz,
  216. * 24.576 MHz, 90.3168MHz and 98.304MHz ignore them for now.
  217. * Enforce the default for them, which is m0 = 1, m1 = 0.
  218. */
  219. #define SUN50I_A100_PLL_AUDIO_REG 0x078
  220. static struct ccu_sdm_setting pll_audio_sdm_table[] = {
  221. { .rate = 45158400, .pattern = 0xc001bcd3, .m = 18, .n = 33 },
  222. { .rate = 49152000, .pattern = 0xc001eb85, .m = 20, .n = 40 },
  223. { .rate = 180633600, .pattern = 0xc001288d, .m = 3, .n = 22 },
  224. { .rate = 196608000, .pattern = 0xc001eb85, .m = 5, .n = 40 },
  225. };
  226. static struct ccu_nm pll_audio_clk = {
  227. .enable = SUN50I_A100_PLL_OUTPUT_ENABLE,
  228. .lock = SUN50I_A100_PLL_LOCK,
  229. .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
  230. .m = _SUNXI_CCU_DIV(16, 6),
  231. .fixed_post_div = 2,
  232. .sdm = _SUNXI_CCU_SDM(pll_audio_sdm_table, BIT(24),
  233. 0x178, BIT(31)),
  234. .common = {
  235. .reg = 0x078,
  236. .features = CCU_FEATURE_FIXED_POSTDIV |
  237. CCU_FEATURE_SIGMA_DELTA_MOD,
  238. .hw.init = CLK_HW_INIT("pll-audio", "dcxo24M",
  239. &ccu_nm_ops,
  240. CLK_SET_RATE_UNGATE),
  241. },
  242. };
  243. static const char * const cpux_parents[] = { "dcxo24M", "osc32k",
  244. "iosc", "pll-cpux",
  245. "pll-periph0" };
  246. static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents,
  247. 0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
  248. static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x500, 0, 2, 0);
  249. static SUNXI_CCU_M(cpux_apb_clk, "cpux-apb", "cpux", 0x500, 8, 2, 0);
  250. static const char * const psi_ahb1_ahb2_parents[] = { "dcxo24M", "osc32k",
  251. "iosc", "pll-periph0",
  252. "pll-periph0-2x" };
  253. static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2",
  254. psi_ahb1_ahb2_parents, 0x510,
  255. 0, 2, /* M */
  256. 8, 2, /* P */
  257. 24, 3, /* mux */
  258. 0);
  259. static const char * const ahb3_apb1_apb2_parents[] = { "dcxo24M", "osc32k",
  260. "psi-ahb1-ahb2",
  261. "pll-periph0",
  262. "pll-periph0-2x" };
  263. static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3", ahb3_apb1_apb2_parents, 0x51c,
  264. 0, 2, /* M */
  265. 8, 2, /* P */
  266. 24, 3, /* mux */
  267. 0);
  268. static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", ahb3_apb1_apb2_parents, 0x520,
  269. 0, 2, /* M */
  270. 8, 2, /* P */
  271. 24, 3, /* mux */
  272. 0);
  273. static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", ahb3_apb1_apb2_parents, 0x524,
  274. 0, 2, /* M */
  275. 8, 2, /* P */
  276. 24, 3, /* mux */
  277. 0);
  278. static const char * const mbus_parents[] = { "dcxo24M", "pll-ddr0",
  279. "pll-periph0",
  280. "pll-periph0-2x" };
  281. static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, 0x540,
  282. 0, 3, /* M */
  283. 24, 2, /* mux */
  284. BIT(31), /* gate */
  285. CLK_IS_CRITICAL);
  286. static const char * const de_parents[] = { "pll-com", "pll-periph0-2x" };
  287. static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de0", de_parents, 0x600,
  288. 0, 4, /* M */
  289. 24, 1, /* mux */
  290. BIT(31), /* gate */
  291. CLK_SET_RATE_PARENT);
  292. static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "psi-ahb1-ahb2",
  293. 0x60c, BIT(0), 0);
  294. static const char * const g2d_parents[] = { "pll-com", "pll-periph0-2x",
  295. "pll-video0-2x", "pll-video1-2x",
  296. "pll-video2-2x"};
  297. static SUNXI_CCU_M_WITH_MUX_GATE(g2d_clk, "g2d",
  298. g2d_parents,
  299. 0x630,
  300. 0, 4, /* M */
  301. 24, 3, /* mux */
  302. BIT(31), /* gate */
  303. 0);
  304. static SUNXI_CCU_GATE(bus_g2d_clk, "bus-g2d", "psi-ahb1-ahb2",
  305. 0x63c, BIT(0), 0);
  306. static const char * const gpu_parents[] = { "pll-gpu" };
  307. static SUNXI_CCU_M_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670,
  308. 0, 2, /* M */
  309. 24, 1, /* mux */
  310. BIT(31), /* gate */
  311. 0);
  312. static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "psi-ahb1-ahb2",
  313. 0x67c, BIT(0), 0);
  314. static const char * const ce_parents[] = { "dcxo24M", "pll-periph0-2x" };
  315. static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
  316. 0, 4, /* M */
  317. 8, 2, /* P */
  318. 24, 1, /* mux */
  319. BIT(31), /* gate */
  320. 0);
  321. static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "psi-ahb1-ahb2",
  322. 0x68c, BIT(0), 0);
  323. static const char * const ve_parents[] = { "pll-ve" };
  324. static SUNXI_CCU_M_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
  325. 0, 3, /* M */
  326. 24, 1, /* mux */
  327. BIT(31), /* gate */
  328. CLK_SET_RATE_PARENT);
  329. static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "psi-ahb1-ahb2",
  330. 0x69c, BIT(0), 0);
  331. static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "psi-ahb1-ahb2",
  332. 0x70c, BIT(0), 0);
  333. static SUNXI_CCU_GATE(bus_msgbox_clk, "bus-msgbox", "psi-ahb1-ahb2",
  334. 0x71c, BIT(0), 0);
  335. static SUNXI_CCU_GATE(bus_spinlock_clk, "bus-spinlock", "psi-ahb1-ahb2",
  336. 0x72c, BIT(0), 0);
  337. static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "psi-ahb1-ahb2",
  338. 0x73c, BIT(0), 0);
  339. static SUNXI_CCU_GATE(avs_clk, "avs", "dcxo24M", 0x740, BIT(31), 0);
  340. static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "psi-ahb1-ahb2",
  341. 0x78c, BIT(0), 0);
  342. static SUNXI_CCU_GATE(bus_psi_clk, "bus-psi", "psi-ahb1-ahb2",
  343. 0x79c, BIT(0), 0);
  344. static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x7ac, BIT(0), 0);
  345. static SUNXI_CCU_GATE(bus_iommu_clk, "bus-iommu", "apb1", 0x7bc, BIT(0), 0);
  346. static SUNXI_CCU_GATE(mbus_dma_clk, "mbus-dma", "mbus",
  347. 0x804, BIT(0), 0);
  348. static SUNXI_CCU_GATE(mbus_ve_clk, "mbus-ve", "mbus",
  349. 0x804, BIT(1), 0);
  350. static SUNXI_CCU_GATE(mbus_ce_clk, "mbus-ce", "mbus",
  351. 0x804, BIT(2), 0);
  352. static SUNXI_CCU_GATE(mbus_nand_clk, "mbus-nand", "mbus",
  353. 0x804, BIT(5), 0);
  354. static SUNXI_CCU_GATE(mbus_csi_clk, "mbus-csi", "mbus",
  355. 0x804, BIT(8), 0);
  356. static SUNXI_CCU_GATE(mbus_isp_clk, "mbus-isp", "mbus",
  357. 0x804, BIT(9), 0);
  358. static SUNXI_CCU_GATE(mbus_g2d_clk, "mbus-g2d", "mbus",
  359. 0x804, BIT(10), 0);
  360. static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "psi-ahb1-ahb2",
  361. 0x80c, BIT(0), CLK_IS_CRITICAL);
  362. static const char * const nand_spi_parents[] = { "dcxo24M",
  363. "pll-periph0",
  364. "pll-periph1",
  365. "pll-periph0-2x",
  366. "pll-periph1-2x" };
  367. static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_clk, "nand0", nand_spi_parents, 0x810,
  368. 0, 4, /* M */
  369. 8, 2, /* P */
  370. 24, 3, /* mux */
  371. BIT(31), /* gate */
  372. 0);
  373. static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_clk, "nand1", nand_spi_parents, 0x814,
  374. 0, 4, /* M */
  375. 8, 2, /* P */
  376. 24, 3, /* mux */
  377. BIT(31), /* gate */
  378. 0);
  379. static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb3", 0x82c, BIT(0), 0);
  380. static const char * const mmc_parents[] = { "dcxo24M", "pll-periph0-2x",
  381. "pll-periph1-2x" };
  382. static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0", mmc_parents, 0x830,
  383. 0, 4, /* M */
  384. 8, 2, /* P */
  385. 24, 2, /* mux */
  386. BIT(31), /* gate */
  387. 2, /* post-div */
  388. CLK_SET_RATE_NO_REPARENT);
  389. static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1", mmc_parents, 0x834,
  390. 0, 4, /* M */
  391. 8, 2, /* P */
  392. 24, 2, /* mux */
  393. BIT(31), /* gate */
  394. 2, /* post-div */
  395. CLK_SET_RATE_NO_REPARENT);
  396. static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc2_clk, "mmc2", mmc_parents, 0x838,
  397. 0, 4, /* M */
  398. 8, 2, /* P */
  399. 24, 2, /* mux */
  400. BIT(31), /* gate */
  401. 2, /* post-div */
  402. CLK_SET_RATE_NO_REPARENT);
  403. static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb3", 0x84c, BIT(0), 0);
  404. static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb3", 0x84c, BIT(1), 0);
  405. static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2", "ahb3", 0x84c, BIT(2), 0);
  406. static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", 0x90c, BIT(0), 0);
  407. static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", 0x90c, BIT(1), 0);
  408. static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", 0x90c, BIT(2), 0);
  409. static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", 0x90c, BIT(3), 0);
  410. static SUNXI_CCU_GATE(bus_uart4_clk, "bus-uart4", "apb2", 0x90c, BIT(4), 0);
  411. static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", 0x91c, BIT(0), 0);
  412. static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", 0x91c, BIT(1), 0);
  413. static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2", 0x91c, BIT(2), 0);
  414. static SUNXI_CCU_GATE(bus_i2c3_clk, "bus-i2c3", "apb2", 0x91c, BIT(3), 0);
  415. static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", nand_spi_parents, 0x940,
  416. 0, 4, /* M */
  417. 8, 2, /* P */
  418. 24, 3, /* mux */
  419. BIT(31), /* gate */
  420. 0);
  421. static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", nand_spi_parents, 0x944,
  422. 0, 4, /* M */
  423. 8, 2, /* P */
  424. 24, 3, /* mux */
  425. BIT(31), /* gate */
  426. 0);
  427. static SUNXI_CCU_MP_WITH_MUX_GATE(spi2_clk, "spi2", nand_spi_parents, 0x948,
  428. 0, 4, /* M */
  429. 8, 2, /* P */
  430. 24, 3, /* mux */
  431. BIT(31), /* gate */
  432. 0);
  433. static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb3", 0x96c, BIT(0), 0);
  434. static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb3", 0x96c, BIT(1), 0);
  435. static SUNXI_CCU_GATE(bus_spi2_clk, "bus-spi2", "ahb3", 0x96c, BIT(2), 0);
  436. static SUNXI_CCU_GATE(emac_25m_clk, "emac-25m", "ahb3", 0x970,
  437. BIT(31) | BIT(30), 0);
  438. static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac", "ahb3", 0x97c, BIT(0), 0);
  439. static const char * const ir_parents[] = { "osc32k", "iosc",
  440. "pll-periph0", "pll-periph1" };
  441. static SUNXI_CCU_MP_WITH_MUX_GATE(ir_rx_clk, "ir-rx", ir_parents, 0x990,
  442. 0, 4, /* M */
  443. 8, 2, /* P */
  444. 24, 3, /* mux */
  445. BIT(31), /* gate */
  446. 0);
  447. static SUNXI_CCU_GATE(bus_ir_rx_clk, "bus-ir-rx", "ahb3", 0x99c, BIT(0), 0);
  448. static SUNXI_CCU_MP_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_parents, 0x9c0,
  449. 0, 4, /* M */
  450. 8, 2, /* P */
  451. 24, 3, /* mux */
  452. BIT(31), /* gate */
  453. 0);
  454. static SUNXI_CCU_GATE(bus_ir_tx_clk, "bus-ir-tx", "apb1", 0x9cc, BIT(0), 0);
  455. static SUNXI_CCU_GATE(bus_gpadc_clk, "bus-gpadc", "apb1", 0x9ec, BIT(0), 0);
  456. static SUNXI_CCU_GATE(bus_ths_clk, "bus-ths", "apb1", 0x9fc, BIT(0), 0);
  457. static const char * const audio_parents[] = { "pll-audio", "pll-com-audio" };
  458. static struct ccu_div i2s0_clk = {
  459. .enable = BIT(31),
  460. .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
  461. .mux = _SUNXI_CCU_MUX(24, 2),
  462. .common = {
  463. .reg = 0xa10,
  464. .hw.init = CLK_HW_INIT_PARENTS("i2s0",
  465. audio_parents,
  466. &ccu_div_ops,
  467. CLK_SET_RATE_PARENT),
  468. },
  469. };
  470. static struct ccu_div i2s1_clk = {
  471. .enable = BIT(31),
  472. .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
  473. .mux = _SUNXI_CCU_MUX(24, 2),
  474. .common = {
  475. .reg = 0xa14,
  476. .hw.init = CLK_HW_INIT_PARENTS("i2s1",
  477. audio_parents,
  478. &ccu_div_ops,
  479. CLK_SET_RATE_PARENT),
  480. },
  481. };
  482. static struct ccu_div i2s2_clk = {
  483. .enable = BIT(31),
  484. .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
  485. .mux = _SUNXI_CCU_MUX(24, 2),
  486. .common = {
  487. .reg = 0xa18,
  488. .hw.init = CLK_HW_INIT_PARENTS("i2s2",
  489. audio_parents,
  490. &ccu_div_ops,
  491. CLK_SET_RATE_PARENT),
  492. },
  493. };
  494. static struct ccu_div i2s3_clk = {
  495. .enable = BIT(31),
  496. .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
  497. .mux = _SUNXI_CCU_MUX(24, 2),
  498. .common = {
  499. .reg = 0xa1c,
  500. .hw.init = CLK_HW_INIT_PARENTS("i2s3",
  501. audio_parents,
  502. &ccu_div_ops,
  503. CLK_SET_RATE_PARENT),
  504. },
  505. };
  506. static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb1", 0xa20, BIT(0), 0);
  507. static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1", "apb1", 0xa20, BIT(1), 0);
  508. static SUNXI_CCU_GATE(bus_i2s2_clk, "bus-i2s2", "apb1", 0xa20, BIT(2), 0);
  509. static SUNXI_CCU_GATE(bus_i2s3_clk, "bus-i2s3", "apb1", 0xa20, BIT(3), 0);
  510. static struct ccu_div spdif_clk = {
  511. .enable = BIT(31),
  512. .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
  513. .mux = _SUNXI_CCU_MUX(24, 2),
  514. .common = {
  515. .reg = 0xa24,
  516. .hw.init = CLK_HW_INIT_PARENTS("spdif",
  517. audio_parents,
  518. &ccu_div_ops,
  519. 0),
  520. },
  521. };
  522. static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", 0xa2c, BIT(0), 0);
  523. static struct ccu_div dmic_clk = {
  524. .enable = BIT(31),
  525. .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
  526. .mux = _SUNXI_CCU_MUX(24, 2),
  527. .common = {
  528. .reg = 0xa40,
  529. .hw.init = CLK_HW_INIT_PARENTS("dmic",
  530. audio_parents,
  531. &ccu_div_ops,
  532. 0),
  533. },
  534. };
  535. static SUNXI_CCU_GATE(bus_dmic_clk, "bus-dmic", "apb1", 0xa4c, BIT(0), 0);
  536. static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_dac_clk, "audio-codec-dac",
  537. audio_parents, 0xa50,
  538. 0, 4, /* M */
  539. 24, 2, /* mux */
  540. BIT(31), /* gate */
  541. 0);
  542. static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_adc_clk, "audio-codec-adc",
  543. audio_parents, 0xa54,
  544. 0, 4, /* M */
  545. 24, 2, /* mux */
  546. BIT(31), /* gate */
  547. 0);
  548. static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_4x_clk, "audio-codec-4x",
  549. audio_parents, 0xa58,
  550. 0, 4, /* M */
  551. 24, 2, /* mux */
  552. BIT(31), /* gate */
  553. 0);
  554. static SUNXI_CCU_GATE(bus_audio_codec_clk, "bus-audio-codec", "apb1", 0xa5c,
  555. BIT(0), 0);
  556. /*
  557. * There are OHCI 12M clock source selection bits for 2 USB 2.0 ports.
  558. * We will force them to 0 (12M divided from 48M).
  559. */
  560. #define SUN50I_A100_USB0_CLK_REG 0xa70
  561. #define SUN50I_A100_USB1_CLK_REG 0xa74
  562. static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", 0xa70, BIT(31), 0);
  563. static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "dcxo24M", 0xa70, BIT(29), 0);
  564. static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "osc12M", 0xa74, BIT(31), 0);
  565. static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "dcxo24M", 0xa74, BIT(29), 0);
  566. static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb3", 0xa8c, BIT(0), 0);
  567. static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb3", 0xa8c, BIT(1), 0);
  568. static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb3", 0xa8c, BIT(4), 0);
  569. static SUNXI_CCU_GATE(bus_ehci1_clk, "bus-ehci1", "ahb3", 0xa8c, BIT(5), 0);
  570. static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb3", 0xa8c, BIT(8), 0);
  571. static SUNXI_CCU_GATE(bus_lradc_clk, "bus-lradc", "ahb3", 0xa9c, BIT(0), 0);
  572. static SUNXI_CCU_GATE(bus_dpss_top0_clk, "bus-dpss-top0", "ahb3",
  573. 0xabc, BIT(0), 0);
  574. static SUNXI_CCU_GATE(bus_dpss_top1_clk, "bus-dpss-top1", "ahb3",
  575. 0xacc, BIT(0), 0);
  576. static const char * const mipi_dsi_parents[] = { "dcxo24M", "pll-periph0-2x",
  577. "pll-periph0" };
  578. static SUNXI_CCU_M_WITH_MUX_GATE(mipi_dsi_clk, "mipi-dsi",
  579. mipi_dsi_parents,
  580. 0xb24,
  581. 0, 4, /* M */
  582. 24, 2, /* mux */
  583. BIT(31), /* gate */
  584. 0);
  585. static SUNXI_CCU_GATE(bus_mipi_dsi_clk, "bus-mipi-dsi", "ahb3",
  586. 0xb4c, BIT(0), 0);
  587. static const char * const tcon_lcd_parents[] = { "pll-video0-4x",
  588. "pll-video1-4x",
  589. "pll-video2-4x",
  590. "pll-video3-4x",
  591. "pll-periph0-2x" };
  592. static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_lcd_clk, "tcon-lcd0",
  593. tcon_lcd_parents, 0xb60,
  594. 0, 4, /* M */
  595. 8, 2, /* P */
  596. 24, 3, /* mux */
  597. BIT(31), /* gate */
  598. 0);
  599. static SUNXI_CCU_GATE(bus_tcon_lcd_clk, "bus-tcon-lcd0", "ahb3",
  600. 0xb7c, BIT(0), 0);
  601. static const char * const ledc_parents[] = { "dcxo24M",
  602. "pll-periph0" };
  603. static SUNXI_CCU_MP_WITH_MUX_GATE(ledc_clk, "ledc",
  604. ledc_parents, 0xbf0,
  605. 0, 4, /* M */
  606. 8, 2, /* P */
  607. 24, 3, /* mux */
  608. BIT(31), /* gate */
  609. 0);
  610. static SUNXI_CCU_GATE(bus_ledc_clk, "bus-ledc", "ahb3", 0xbfc, BIT(0), 0);
  611. static const char * const csi_top_parents[] = { "pll-periph0-2x",
  612. "pll-video0-2x",
  613. "pll-video1-2x",
  614. "pll-video2-2x",
  615. "pll-video3-2x" };
  616. static SUNXI_CCU_M_WITH_MUX_GATE(csi_top_clk, "csi-top",
  617. csi_top_parents, 0xc04,
  618. 0, 4, /* M */
  619. 24, 3, /* mux */
  620. BIT(31), /* gate */
  621. 0);
  622. static const char * const csi0_mclk_parents[] = { "dcxo24M", "pll-video2",
  623. "pll-video3", "pll-video0",
  624. "pll-video1" };
  625. static SUNXI_CCU_M_WITH_MUX_GATE(csi0_mclk_clk, "csi0-mclk",
  626. csi0_mclk_parents, 0xc08,
  627. 0, 5, /* M */
  628. 24, 3, /* mux */
  629. BIT(31), /* gate */
  630. 0);
  631. static const char * const csi1_mclk_parents[] = { "dcxo24M", "pll-video3",
  632. "pll-video0", "pll-video1",
  633. "pll-video2" };
  634. static SUNXI_CCU_M_WITH_MUX_GATE(csi1_mclk_clk, "csi1-mclk",
  635. csi1_mclk_parents, 0xc0c,
  636. 0, 5, /* M */
  637. 24, 3, /* mux */
  638. BIT(31), /* gate */
  639. 0);
  640. static SUNXI_CCU_GATE(bus_csi_clk, "bus-csi", "ahb3", 0xc1c, BIT(0), 0);
  641. static const char * const csi_isp_parents[] = { "pll-periph0-2x",
  642. "pll-video0-2x",
  643. "pll-video1-2x",
  644. "pll-video2-2x",
  645. "pll-video3-2x" };
  646. static SUNXI_CCU_M_WITH_MUX_GATE(csi_isp_clk, "csi-isp",
  647. csi_isp_parents, 0xc20,
  648. 0, 5, /* M */
  649. 24, 3, /* mux */
  650. BIT(31), /* gate */
  651. 0);
  652. /* Fixed factor clocks */
  653. static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0);
  654. static CLK_FIXED_FACTOR_HW(pll_com_audio_clk, "pll-com-audio",
  655. &pll_com_clk.common.hw,
  656. 5, 1, CLK_SET_RATE_PARENT);
  657. static CLK_FIXED_FACTOR_HW(pll_periph0_2x_clk, "pll-periph0-2x",
  658. &pll_periph0_clk.common.hw,
  659. 1, 2, 0);
  660. static CLK_FIXED_FACTOR_HW(pll_periph1_2x_clk, "pll-periph1-2x",
  661. &pll_periph1_clk.common.hw,
  662. 1, 2, 0);
  663. static const struct clk_hw *pll_video0_parents[] = {
  664. &pll_video0_clk.common.hw
  665. };
  666. static CLK_FIXED_FACTOR_HWS(pll_video0_4x_clk, "pll-video0-4x",
  667. pll_video0_parents,
  668. 1, 4, CLK_SET_RATE_PARENT);
  669. static CLK_FIXED_FACTOR_HWS(pll_video0_2x_clk, "pll-video0-2x",
  670. pll_video0_parents,
  671. 1, 2, CLK_SET_RATE_PARENT);
  672. static const struct clk_hw *pll_video1_parents[] = {
  673. &pll_video1_clk.common.hw
  674. };
  675. static CLK_FIXED_FACTOR_HWS(pll_video1_4x_clk, "pll-video1-4x",
  676. pll_video1_parents,
  677. 1, 4, CLK_SET_RATE_PARENT);
  678. static CLK_FIXED_FACTOR_HWS(pll_video1_2x_clk, "pll-video1-2x",
  679. pll_video1_parents,
  680. 1, 2, CLK_SET_RATE_PARENT);
  681. static const struct clk_hw *pll_video2_parents[] = {
  682. &pll_video2_clk.common.hw
  683. };
  684. static CLK_FIXED_FACTOR_HWS(pll_video2_4x_clk, "pll-video2-4x",
  685. pll_video2_parents,
  686. 1, 4, CLK_SET_RATE_PARENT);
  687. static CLK_FIXED_FACTOR_HWS(pll_video2_2x_clk, "pll-video2-2x",
  688. pll_video2_parents,
  689. 1, 2, CLK_SET_RATE_PARENT);
  690. static const struct clk_hw *pll_video3_parents[] = {
  691. &pll_video3_clk.common.hw
  692. };
  693. static CLK_FIXED_FACTOR_HWS(pll_video3_4x_clk, "pll-video3-4x",
  694. pll_video3_parents,
  695. 1, 4, CLK_SET_RATE_PARENT);
  696. static CLK_FIXED_FACTOR_HWS(pll_video3_2x_clk, "pll-video3-2x",
  697. pll_video3_parents,
  698. 1, 2, CLK_SET_RATE_PARENT);
  699. static struct ccu_common *sun50i_a100_ccu_clks[] = {
  700. &pll_cpux_clk.common,
  701. &pll_ddr0_clk.common,
  702. &pll_periph0_clk.common,
  703. &pll_periph1_clk.common,
  704. &pll_gpu_clk.common,
  705. &pll_video0_clk.common,
  706. &pll_video1_clk.common,
  707. &pll_video2_clk.common,
  708. &pll_video3_clk.common,
  709. &pll_ve_clk.common,
  710. &pll_com_clk.common,
  711. &pll_audio_clk.common,
  712. &cpux_clk.common,
  713. &axi_clk.common,
  714. &cpux_apb_clk.common,
  715. &psi_ahb1_ahb2_clk.common,
  716. &ahb3_clk.common,
  717. &apb1_clk.common,
  718. &apb2_clk.common,
  719. &mbus_clk.common,
  720. &de_clk.common,
  721. &bus_de_clk.common,
  722. &g2d_clk.common,
  723. &bus_g2d_clk.common,
  724. &gpu_clk.common,
  725. &bus_gpu_clk.common,
  726. &ce_clk.common,
  727. &bus_ce_clk.common,
  728. &ve_clk.common,
  729. &bus_ve_clk.common,
  730. &bus_dma_clk.common,
  731. &bus_msgbox_clk.common,
  732. &bus_spinlock_clk.common,
  733. &bus_hstimer_clk.common,
  734. &avs_clk.common,
  735. &bus_dbg_clk.common,
  736. &bus_psi_clk.common,
  737. &bus_pwm_clk.common,
  738. &bus_iommu_clk.common,
  739. &mbus_dma_clk.common,
  740. &mbus_ve_clk.common,
  741. &mbus_ce_clk.common,
  742. &mbus_nand_clk.common,
  743. &mbus_csi_clk.common,
  744. &mbus_isp_clk.common,
  745. &mbus_g2d_clk.common,
  746. &bus_dram_clk.common,
  747. &nand0_clk.common,
  748. &nand1_clk.common,
  749. &bus_nand_clk.common,
  750. &mmc0_clk.common,
  751. &mmc1_clk.common,
  752. &mmc2_clk.common,
  753. &bus_mmc0_clk.common,
  754. &bus_mmc1_clk.common,
  755. &bus_mmc2_clk.common,
  756. &bus_uart0_clk.common,
  757. &bus_uart1_clk.common,
  758. &bus_uart2_clk.common,
  759. &bus_uart3_clk.common,
  760. &bus_uart4_clk.common,
  761. &bus_i2c0_clk.common,
  762. &bus_i2c1_clk.common,
  763. &bus_i2c2_clk.common,
  764. &bus_i2c3_clk.common,
  765. &spi0_clk.common,
  766. &spi1_clk.common,
  767. &spi2_clk.common,
  768. &bus_spi0_clk.common,
  769. &bus_spi1_clk.common,
  770. &bus_spi2_clk.common,
  771. &emac_25m_clk.common,
  772. &bus_emac_clk.common,
  773. &ir_rx_clk.common,
  774. &bus_ir_rx_clk.common,
  775. &ir_tx_clk.common,
  776. &bus_ir_tx_clk.common,
  777. &bus_gpadc_clk.common,
  778. &bus_ths_clk.common,
  779. &i2s0_clk.common,
  780. &i2s1_clk.common,
  781. &i2s2_clk.common,
  782. &i2s3_clk.common,
  783. &bus_i2s0_clk.common,
  784. &bus_i2s1_clk.common,
  785. &bus_i2s2_clk.common,
  786. &bus_i2s3_clk.common,
  787. &spdif_clk.common,
  788. &bus_spdif_clk.common,
  789. &dmic_clk.common,
  790. &bus_dmic_clk.common,
  791. &audio_codec_dac_clk.common,
  792. &audio_codec_adc_clk.common,
  793. &audio_codec_4x_clk.common,
  794. &bus_audio_codec_clk.common,
  795. &usb_ohci0_clk.common,
  796. &usb_phy0_clk.common,
  797. &usb_ohci1_clk.common,
  798. &usb_phy1_clk.common,
  799. &bus_ohci0_clk.common,
  800. &bus_ohci1_clk.common,
  801. &bus_ehci0_clk.common,
  802. &bus_ehci1_clk.common,
  803. &bus_otg_clk.common,
  804. &bus_lradc_clk.common,
  805. &bus_dpss_top0_clk.common,
  806. &bus_dpss_top1_clk.common,
  807. &mipi_dsi_clk.common,
  808. &bus_mipi_dsi_clk.common,
  809. &tcon_lcd_clk.common,
  810. &bus_tcon_lcd_clk.common,
  811. &ledc_clk.common,
  812. &bus_ledc_clk.common,
  813. &csi_top_clk.common,
  814. &csi0_mclk_clk.common,
  815. &csi1_mclk_clk.common,
  816. &bus_csi_clk.common,
  817. &csi_isp_clk.common,
  818. };
  819. static struct clk_hw_onecell_data sun50i_a100_hw_clks = {
  820. .hws = {
  821. [CLK_OSC12M] = &osc12M_clk.hw,
  822. [CLK_PLL_CPUX] = &pll_cpux_clk.common.hw,
  823. [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw,
  824. [CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw,
  825. [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.hw,
  826. [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw,
  827. [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw,
  828. [CLK_PLL_GPU] = &pll_gpu_clk.common.hw,
  829. [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw,
  830. [CLK_PLL_VIDEO0_2X] = &pll_video0_2x_clk.hw,
  831. [CLK_PLL_VIDEO0_4X] = &pll_video0_4x_clk.hw,
  832. [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw,
  833. [CLK_PLL_VIDEO1_2X] = &pll_video1_2x_clk.hw,
  834. [CLK_PLL_VIDEO1_4X] = &pll_video1_4x_clk.hw,
  835. [CLK_PLL_VIDEO2] = &pll_video2_clk.common.hw,
  836. [CLK_PLL_VIDEO2_2X] = &pll_video2_2x_clk.hw,
  837. [CLK_PLL_VIDEO2_4X] = &pll_video2_4x_clk.hw,
  838. [CLK_PLL_VIDEO3] = &pll_video3_clk.common.hw,
  839. [CLK_PLL_VIDEO3_2X] = &pll_video3_2x_clk.hw,
  840. [CLK_PLL_VIDEO3_4X] = &pll_video3_4x_clk.hw,
  841. [CLK_PLL_VE] = &pll_ve_clk.common.hw,
  842. [CLK_PLL_COM] = &pll_com_clk.common.hw,
  843. [CLK_PLL_COM_AUDIO] = &pll_com_audio_clk.hw,
  844. [CLK_PLL_AUDIO] = &pll_audio_clk.common.hw,
  845. [CLK_CPUX] = &cpux_clk.common.hw,
  846. [CLK_AXI] = &axi_clk.common.hw,
  847. [CLK_CPUX_APB] = &cpux_apb_clk.common.hw,
  848. [CLK_PSI_AHB1_AHB2] = &psi_ahb1_ahb2_clk.common.hw,
  849. [CLK_AHB3] = &ahb3_clk.common.hw,
  850. [CLK_APB1] = &apb1_clk.common.hw,
  851. [CLK_APB2] = &apb2_clk.common.hw,
  852. [CLK_MBUS] = &mbus_clk.common.hw,
  853. [CLK_DE] = &de_clk.common.hw,
  854. [CLK_BUS_DE] = &bus_de_clk.common.hw,
  855. [CLK_G2D] = &g2d_clk.common.hw,
  856. [CLK_BUS_G2D] = &bus_g2d_clk.common.hw,
  857. [CLK_GPU] = &gpu_clk.common.hw,
  858. [CLK_BUS_GPU] = &bus_gpu_clk.common.hw,
  859. [CLK_CE] = &ce_clk.common.hw,
  860. [CLK_BUS_CE] = &bus_ce_clk.common.hw,
  861. [CLK_VE] = &ve_clk.common.hw,
  862. [CLK_BUS_VE] = &bus_ve_clk.common.hw,
  863. [CLK_BUS_DMA] = &bus_dma_clk.common.hw,
  864. [CLK_BUS_MSGBOX] = &bus_msgbox_clk.common.hw,
  865. [CLK_BUS_SPINLOCK] = &bus_spinlock_clk.common.hw,
  866. [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw,
  867. [CLK_AVS] = &avs_clk.common.hw,
  868. [CLK_BUS_DBG] = &bus_dbg_clk.common.hw,
  869. [CLK_BUS_PSI] = &bus_psi_clk.common.hw,
  870. [CLK_BUS_PWM] = &bus_pwm_clk.common.hw,
  871. [CLK_BUS_IOMMU] = &bus_iommu_clk.common.hw,
  872. [CLK_MBUS_DMA] = &mbus_dma_clk.common.hw,
  873. [CLK_MBUS_VE] = &mbus_ve_clk.common.hw,
  874. [CLK_MBUS_CE] = &mbus_ce_clk.common.hw,
  875. [CLK_MBUS_NAND] = &mbus_nand_clk.common.hw,
  876. [CLK_MBUS_CSI] = &mbus_csi_clk.common.hw,
  877. [CLK_MBUS_ISP] = &mbus_isp_clk.common.hw,
  878. [CLK_MBUS_G2D] = &mbus_g2d_clk.common.hw,
  879. [CLK_BUS_DRAM] = &bus_dram_clk.common.hw,
  880. [CLK_NAND0] = &nand0_clk.common.hw,
  881. [CLK_NAND1] = &nand1_clk.common.hw,
  882. [CLK_BUS_NAND] = &bus_nand_clk.common.hw,
  883. [CLK_MMC0] = &mmc0_clk.common.hw,
  884. [CLK_MMC1] = &mmc1_clk.common.hw,
  885. [CLK_MMC2] = &mmc2_clk.common.hw,
  886. [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw,
  887. [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw,
  888. [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw,
  889. [CLK_BUS_UART0] = &bus_uart0_clk.common.hw,
  890. [CLK_BUS_UART1] = &bus_uart1_clk.common.hw,
  891. [CLK_BUS_UART2] = &bus_uart2_clk.common.hw,
  892. [CLK_BUS_UART3] = &bus_uart3_clk.common.hw,
  893. [CLK_BUS_UART4] = &bus_uart4_clk.common.hw,
  894. [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw,
  895. [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw,
  896. [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw,
  897. [CLK_BUS_I2C3] = &bus_i2c3_clk.common.hw,
  898. [CLK_SPI0] = &spi0_clk.common.hw,
  899. [CLK_SPI1] = &spi1_clk.common.hw,
  900. [CLK_SPI2] = &spi2_clk.common.hw,
  901. [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw,
  902. [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw,
  903. [CLK_BUS_SPI2] = &bus_spi2_clk.common.hw,
  904. [CLK_EMAC_25M] = &emac_25m_clk.common.hw,
  905. [CLK_BUS_EMAC] = &bus_emac_clk.common.hw,
  906. [CLK_IR_RX] = &ir_rx_clk.common.hw,
  907. [CLK_BUS_IR_RX] = &bus_ir_rx_clk.common.hw,
  908. [CLK_IR_TX] = &ir_tx_clk.common.hw,
  909. [CLK_BUS_IR_TX] = &bus_ir_tx_clk.common.hw,
  910. [CLK_BUS_GPADC] = &bus_gpadc_clk.common.hw,
  911. [CLK_BUS_THS] = &bus_ths_clk.common.hw,
  912. [CLK_I2S0] = &i2s0_clk.common.hw,
  913. [CLK_I2S1] = &i2s1_clk.common.hw,
  914. [CLK_I2S2] = &i2s2_clk.common.hw,
  915. [CLK_I2S3] = &i2s3_clk.common.hw,
  916. [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw,
  917. [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw,
  918. [CLK_BUS_I2S2] = &bus_i2s2_clk.common.hw,
  919. [CLK_BUS_I2S3] = &bus_i2s3_clk.common.hw,
  920. [CLK_SPDIF] = &spdif_clk.common.hw,
  921. [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw,
  922. [CLK_DMIC] = &dmic_clk.common.hw,
  923. [CLK_BUS_DMIC] = &bus_dmic_clk.common.hw,
  924. [CLK_AUDIO_DAC] = &audio_codec_dac_clk.common.hw,
  925. [CLK_AUDIO_ADC] = &audio_codec_adc_clk.common.hw,
  926. [CLK_AUDIO_4X] = &audio_codec_4x_clk.common.hw,
  927. [CLK_BUS_AUDIO_CODEC] = &bus_audio_codec_clk.common.hw,
  928. [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw,
  929. [CLK_USB_PHY0] = &usb_phy0_clk.common.hw,
  930. [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw,
  931. [CLK_USB_PHY1] = &usb_phy1_clk.common.hw,
  932. [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw,
  933. [CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw,
  934. [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw,
  935. [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw,
  936. [CLK_BUS_OTG] = &bus_otg_clk.common.hw,
  937. [CLK_BUS_LRADC] = &bus_lradc_clk.common.hw,
  938. [CLK_BUS_DPSS_TOP0] = &bus_dpss_top0_clk.common.hw,
  939. [CLK_BUS_DPSS_TOP1] = &bus_dpss_top1_clk.common.hw,
  940. [CLK_MIPI_DSI] = &mipi_dsi_clk.common.hw,
  941. [CLK_BUS_MIPI_DSI] = &bus_mipi_dsi_clk.common.hw,
  942. [CLK_TCON_LCD] = &tcon_lcd_clk.common.hw,
  943. [CLK_BUS_TCON_LCD] = &bus_tcon_lcd_clk.common.hw,
  944. [CLK_LEDC] = &ledc_clk.common.hw,
  945. [CLK_BUS_LEDC] = &bus_ledc_clk.common.hw,
  946. [CLK_CSI_TOP] = &csi_top_clk.common.hw,
  947. [CLK_CSI0_MCLK] = &csi0_mclk_clk.common.hw,
  948. [CLK_CSI1_MCLK] = &csi1_mclk_clk.common.hw,
  949. [CLK_BUS_CSI] = &bus_csi_clk.common.hw,
  950. [CLK_CSI_ISP] = &csi_isp_clk.common.hw,
  951. },
  952. .num = CLK_NUMBER,
  953. };
  954. static struct ccu_reset_map sun50i_a100_ccu_resets[] = {
  955. [RST_MBUS] = { 0x540, BIT(30) },
  956. [RST_BUS_DE] = { 0x60c, BIT(16) },
  957. [RST_BUS_G2D] = { 0x63c, BIT(16) },
  958. [RST_BUS_GPU] = { 0x67c, BIT(16) },
  959. [RST_BUS_CE] = { 0x68c, BIT(16) },
  960. [RST_BUS_VE] = { 0x69c, BIT(16) },
  961. [RST_BUS_DMA] = { 0x70c, BIT(16) },
  962. [RST_BUS_MSGBOX] = { 0x71c, BIT(16) },
  963. [RST_BUS_SPINLOCK] = { 0x72c, BIT(16) },
  964. [RST_BUS_HSTIMER] = { 0x73c, BIT(16) },
  965. [RST_BUS_DBG] = { 0x78c, BIT(16) },
  966. [RST_BUS_PSI] = { 0x79c, BIT(16) },
  967. [RST_BUS_PWM] = { 0x7ac, BIT(16) },
  968. [RST_BUS_DRAM] = { 0x80c, BIT(16) },
  969. [RST_BUS_NAND] = { 0x82c, BIT(16) },
  970. [RST_BUS_MMC0] = { 0x84c, BIT(16) },
  971. [RST_BUS_MMC1] = { 0x84c, BIT(17) },
  972. [RST_BUS_MMC2] = { 0x84c, BIT(18) },
  973. [RST_BUS_UART0] = { 0x90c, BIT(16) },
  974. [RST_BUS_UART1] = { 0x90c, BIT(17) },
  975. [RST_BUS_UART2] = { 0x90c, BIT(18) },
  976. [RST_BUS_UART3] = { 0x90c, BIT(19) },
  977. [RST_BUS_UART4] = { 0x90c, BIT(20) },
  978. [RST_BUS_I2C0] = { 0x91c, BIT(16) },
  979. [RST_BUS_I2C1] = { 0x91c, BIT(17) },
  980. [RST_BUS_I2C2] = { 0x91c, BIT(18) },
  981. [RST_BUS_I2C3] = { 0x91c, BIT(19) },
  982. [RST_BUS_SPI0] = { 0x96c, BIT(16) },
  983. [RST_BUS_SPI1] = { 0x96c, BIT(17) },
  984. [RST_BUS_SPI2] = { 0x96c, BIT(18) },
  985. [RST_BUS_EMAC] = { 0x97c, BIT(16) },
  986. [RST_BUS_IR_RX] = { 0x99c, BIT(16) },
  987. [RST_BUS_IR_TX] = { 0x9cc, BIT(16) },
  988. [RST_BUS_GPADC] = { 0x9ec, BIT(16) },
  989. [RST_BUS_THS] = { 0x9fc, BIT(16) },
  990. [RST_BUS_I2S0] = { 0xa20, BIT(16) },
  991. [RST_BUS_I2S1] = { 0xa20, BIT(17) },
  992. [RST_BUS_I2S2] = { 0xa20, BIT(18) },
  993. [RST_BUS_I2S3] = { 0xa20, BIT(19) },
  994. [RST_BUS_SPDIF] = { 0xa2c, BIT(16) },
  995. [RST_BUS_DMIC] = { 0xa4c, BIT(16) },
  996. [RST_BUS_AUDIO_CODEC] = { 0xa5c, BIT(16) },
  997. [RST_USB_PHY0] = { 0xa70, BIT(30) },
  998. [RST_USB_PHY1] = { 0xa74, BIT(30) },
  999. [RST_BUS_OHCI0] = { 0xa8c, BIT(16) },
  1000. [RST_BUS_OHCI1] = { 0xa8c, BIT(17) },
  1001. [RST_BUS_EHCI0] = { 0xa8c, BIT(20) },
  1002. [RST_BUS_EHCI1] = { 0xa8c, BIT(21) },
  1003. [RST_BUS_OTG] = { 0xa8c, BIT(24) },
  1004. [RST_BUS_LRADC] = { 0xa9c, BIT(16) },
  1005. [RST_BUS_DPSS_TOP0] = { 0xabc, BIT(16) },
  1006. [RST_BUS_DPSS_TOP1] = { 0xacc, BIT(16) },
  1007. [RST_BUS_MIPI_DSI] = { 0xb4c, BIT(16) },
  1008. [RST_BUS_TCON_LCD] = { 0xb7c, BIT(16) },
  1009. [RST_BUS_LVDS] = { 0xbac, BIT(16) },
  1010. [RST_BUS_LEDC] = { 0xbfc, BIT(16) },
  1011. [RST_BUS_CSI] = { 0xc1c, BIT(16) },
  1012. [RST_BUS_CSI_ISP] = { 0xc2c, BIT(16) },
  1013. };
  1014. static const struct sunxi_ccu_desc sun50i_a100_ccu_desc = {
  1015. .ccu_clks = sun50i_a100_ccu_clks,
  1016. .num_ccu_clks = ARRAY_SIZE(sun50i_a100_ccu_clks),
  1017. .hw_clks = &sun50i_a100_hw_clks,
  1018. .resets = sun50i_a100_ccu_resets,
  1019. .num_resets = ARRAY_SIZE(sun50i_a100_ccu_resets),
  1020. };
  1021. static const u32 sun50i_a100_pll_regs[] = {
  1022. SUN50I_A100_PLL_CPUX_REG,
  1023. SUN50I_A100_PLL_DDR0_REG,
  1024. SUN50I_A100_PLL_PERIPH0_REG,
  1025. SUN50I_A100_PLL_PERIPH1_REG,
  1026. SUN50I_A100_PLL_GPU_REG,
  1027. SUN50I_A100_PLL_VIDEO0_REG,
  1028. SUN50I_A100_PLL_VIDEO1_REG,
  1029. SUN50I_A100_PLL_VIDEO2_REG,
  1030. SUN50I_A100_PLL_VIDEO3_REG,
  1031. SUN50I_A100_PLL_VE_REG,
  1032. SUN50I_A100_PLL_COM_REG,
  1033. SUN50I_A100_PLL_AUDIO_REG,
  1034. };
  1035. static const u32 sun50i_a100_pll_video_regs[] = {
  1036. SUN50I_A100_PLL_VIDEO0_REG,
  1037. SUN50I_A100_PLL_VIDEO1_REG,
  1038. SUN50I_A100_PLL_VIDEO2_REG,
  1039. SUN50I_A100_PLL_VIDEO3_REG,
  1040. };
  1041. static const u32 sun50i_a100_usb2_clk_regs[] = {
  1042. SUN50I_A100_USB0_CLK_REG,
  1043. SUN50I_A100_USB1_CLK_REG,
  1044. };
  1045. static struct ccu_pll_nb sun50i_a100_pll_cpu_nb = {
  1046. .common = &pll_cpux_clk.common,
  1047. /* copy from pll_cpux_clk */
  1048. .enable = BIT(27),
  1049. .lock = BIT(28),
  1050. };
  1051. static struct ccu_mux_nb sun50i_a100_cpu_nb = {
  1052. .common = &cpux_clk.common,
  1053. .cm = &cpux_clk.mux,
  1054. .delay_us = 1,
  1055. .bypass_index = 4, /* index of pll periph0 */
  1056. };
  1057. static int sun50i_a100_ccu_probe(struct platform_device *pdev)
  1058. {
  1059. void __iomem *reg;
  1060. u32 val;
  1061. int i, ret;
  1062. reg = devm_platform_ioremap_resource(pdev, 0);
  1063. if (IS_ERR(reg))
  1064. return PTR_ERR(reg);
  1065. /*
  1066. * Enable lock and enable bits on all PLLs.
  1067. *
  1068. * Due to the current design, multiple PLLs share one power switch,
  1069. * so switching PLL is easy to cause stability problems.
  1070. * When initializing, we enable them by default. When disable,
  1071. * we only turn off the output of PLL.
  1072. */
  1073. for (i = 0; i < ARRAY_SIZE(sun50i_a100_pll_regs); i++) {
  1074. val = readl(reg + sun50i_a100_pll_regs[i]);
  1075. val |= SUN50I_A100_PLL_LOCK_ENABLE | SUN50I_A100_PLL_ENABLE;
  1076. writel(val, reg + sun50i_a100_pll_regs[i]);
  1077. }
  1078. /*
  1079. * In order to pass the EMI certification, the SDM function of
  1080. * the peripheral 1 bus is enabled, and the frequency is still
  1081. * calculated using the previous division factor.
  1082. */
  1083. writel(SUN50I_A100_PLL_PERIPH1_PATTERN0,
  1084. reg + SUN50I_A100_PLL_PERIPH1_PATTERN0_REG);
  1085. val = readl(reg + SUN50I_A100_PLL_PERIPH1_REG);
  1086. val |= SUN50I_A100_PLL_SDM_ENABLE;
  1087. writel(val, reg + SUN50I_A100_PLL_PERIPH1_REG);
  1088. /*
  1089. * Force the output divider of video PLLs to 0.
  1090. *
  1091. * See the comment before pll-video0 definition for the reason.
  1092. */
  1093. for (i = 0; i < ARRAY_SIZE(sun50i_a100_pll_video_regs); i++) {
  1094. val = readl(reg + sun50i_a100_pll_video_regs[i]);
  1095. val &= ~BIT(0);
  1096. writel(val, reg + sun50i_a100_pll_video_regs[i]);
  1097. }
  1098. /*
  1099. * Enforce m1 = 0, m0 = 1 for Audio PLL
  1100. *
  1101. * See the comment before pll-audio definition for the reason.
  1102. */
  1103. val = readl(reg + SUN50I_A100_PLL_AUDIO_REG);
  1104. val &= ~BIT(1);
  1105. val |= BIT(0);
  1106. writel(val, reg + SUN50I_A100_PLL_AUDIO_REG);
  1107. /*
  1108. * Force OHCI 12M clock sources to 00 (12MHz divided from 48MHz)
  1109. *
  1110. * This clock mux is still mysterious, and the code just enforces
  1111. * it to have a valid clock parent.
  1112. */
  1113. for (i = 0; i < ARRAY_SIZE(sun50i_a100_usb2_clk_regs); i++) {
  1114. val = readl(reg + sun50i_a100_usb2_clk_regs[i]);
  1115. val &= ~GENMASK(25, 24);
  1116. writel(val, reg + sun50i_a100_usb2_clk_regs[i]);
  1117. }
  1118. ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a100_ccu_desc);
  1119. if (ret)
  1120. return ret;
  1121. /* Gate then ungate PLL CPU after any rate changes */
  1122. ccu_pll_notifier_register(&sun50i_a100_pll_cpu_nb);
  1123. /* Reparent CPU during PLL CPU rate changes */
  1124. ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk,
  1125. &sun50i_a100_cpu_nb);
  1126. return 0;
  1127. }
  1128. static const struct of_device_id sun50i_a100_ccu_ids[] = {
  1129. { .compatible = "allwinner,sun50i-a100-ccu" },
  1130. { }
  1131. };
  1132. static struct platform_driver sun50i_a100_ccu_driver = {
  1133. .probe = sun50i_a100_ccu_probe,
  1134. .driver = {
  1135. .name = "sun50i-a100-ccu",
  1136. .suppress_bind_attrs = true,
  1137. .of_match_table = sun50i_a100_ccu_ids,
  1138. },
  1139. };
  1140. module_platform_driver(sun50i_a100_ccu_driver);
  1141. MODULE_IMPORT_NS(SUNXI_CCU);
  1142. MODULE_LICENSE("GPL");