ccu-sun9i-a80.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2016 Chen-Yu Tsai. All rights reserved.
  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_nkmp.h"
  15. #include "ccu_nm.h"
  16. #include "ccu_phase.h"
  17. #include "ccu-sun9i-a80.h"
  18. #define CCU_SUN9I_LOCK_REG 0x09c
  19. /*
  20. * The CPU PLLs are actually NP clocks, with P being /1 or /4. However
  21. * P should only be used for output frequencies lower than 228 MHz.
  22. * Neither mainline Linux, U-boot, nor the vendor BSPs use these.
  23. *
  24. * For now we can just model it as a multiplier clock, and force P to /1.
  25. */
  26. #define SUN9I_A80_PLL_C0CPUX_REG 0x000
  27. #define SUN9I_A80_PLL_C1CPUX_REG 0x004
  28. static struct ccu_mult pll_c0cpux_clk = {
  29. .enable = BIT(31),
  30. .lock = BIT(0),
  31. .mult = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
  32. .common = {
  33. .reg = SUN9I_A80_PLL_C0CPUX_REG,
  34. .lock_reg = CCU_SUN9I_LOCK_REG,
  35. .features = CCU_FEATURE_LOCK_REG,
  36. .hw.init = CLK_HW_INIT("pll-c0cpux", "osc24M",
  37. &ccu_mult_ops,
  38. CLK_SET_RATE_UNGATE),
  39. },
  40. };
  41. static struct ccu_mult pll_c1cpux_clk = {
  42. .enable = BIT(31),
  43. .lock = BIT(1),
  44. .mult = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
  45. .common = {
  46. .reg = SUN9I_A80_PLL_C1CPUX_REG,
  47. .lock_reg = CCU_SUN9I_LOCK_REG,
  48. .features = CCU_FEATURE_LOCK_REG,
  49. .hw.init = CLK_HW_INIT("pll-c1cpux", "osc24M",
  50. &ccu_mult_ops,
  51. CLK_SET_RATE_UNGATE),
  52. },
  53. };
  54. /*
  55. * The Audio PLL has d1, d2 dividers in addition to the usual N, M
  56. * factors. Since we only need 2 frequencies from this PLL: 22.5792 MHz
  57. * and 24.576 MHz, ignore them for now. Enforce d1 = 0 and d2 = 0.
  58. */
  59. #define SUN9I_A80_PLL_AUDIO_REG 0x008
  60. static struct ccu_nm pll_audio_clk = {
  61. .enable = BIT(31),
  62. .lock = BIT(2),
  63. .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
  64. .m = _SUNXI_CCU_DIV_OFFSET(0, 6, 0),
  65. .common = {
  66. .reg = 0x008,
  67. .lock_reg = CCU_SUN9I_LOCK_REG,
  68. .features = CCU_FEATURE_LOCK_REG,
  69. .hw.init = CLK_HW_INIT("pll-audio", "osc24M",
  70. &ccu_nm_ops, CLK_SET_RATE_UNGATE),
  71. },
  72. };
  73. /* Some PLLs are input * N / div1 / div2. Model them as NKMP with no K */
  74. static struct ccu_nkmp pll_periph0_clk = {
  75. .enable = BIT(31),
  76. .lock = BIT(3),
  77. .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
  78. .m = _SUNXI_CCU_DIV(16, 1), /* input divider */
  79. .p = _SUNXI_CCU_DIV(18, 1), /* output divider */
  80. .common = {
  81. .reg = 0x00c,
  82. .lock_reg = CCU_SUN9I_LOCK_REG,
  83. .features = CCU_FEATURE_LOCK_REG,
  84. .hw.init = CLK_HW_INIT("pll-periph0", "osc24M",
  85. &ccu_nkmp_ops,
  86. CLK_SET_RATE_UNGATE),
  87. },
  88. };
  89. static struct ccu_nkmp pll_ve_clk = {
  90. .enable = BIT(31),
  91. .lock = BIT(4),
  92. .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
  93. .m = _SUNXI_CCU_DIV(16, 1), /* input divider */
  94. .p = _SUNXI_CCU_DIV(18, 1), /* output divider */
  95. .common = {
  96. .reg = 0x010,
  97. .lock_reg = CCU_SUN9I_LOCK_REG,
  98. .features = CCU_FEATURE_LOCK_REG,
  99. .hw.init = CLK_HW_INIT("pll-ve", "osc24M",
  100. &ccu_nkmp_ops,
  101. CLK_SET_RATE_UNGATE),
  102. },
  103. };
  104. static struct ccu_nkmp pll_ddr_clk = {
  105. .enable = BIT(31),
  106. .lock = BIT(5),
  107. .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
  108. .m = _SUNXI_CCU_DIV(16, 1), /* input divider */
  109. .p = _SUNXI_CCU_DIV(18, 1), /* output divider */
  110. .common = {
  111. .reg = 0x014,
  112. .lock_reg = CCU_SUN9I_LOCK_REG,
  113. .features = CCU_FEATURE_LOCK_REG,
  114. .hw.init = CLK_HW_INIT("pll-ddr", "osc24M",
  115. &ccu_nkmp_ops,
  116. CLK_SET_RATE_UNGATE),
  117. },
  118. };
  119. static struct ccu_nm pll_video0_clk = {
  120. .enable = BIT(31),
  121. .lock = BIT(6),
  122. .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
  123. .m = _SUNXI_CCU_DIV(16, 1), /* input divider */
  124. .common = {
  125. .reg = 0x018,
  126. .lock_reg = CCU_SUN9I_LOCK_REG,
  127. .features = CCU_FEATURE_LOCK_REG,
  128. .hw.init = CLK_HW_INIT("pll-video0", "osc24M",
  129. &ccu_nm_ops,
  130. CLK_SET_RATE_UNGATE),
  131. },
  132. };
  133. static struct ccu_nkmp pll_video1_clk = {
  134. .enable = BIT(31),
  135. .lock = BIT(7),
  136. .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
  137. .m = _SUNXI_CCU_DIV(16, 1), /* input divider */
  138. .p = _SUNXI_CCU_DIV(0, 2), /* external divider p */
  139. .common = {
  140. .reg = 0x01c,
  141. .lock_reg = CCU_SUN9I_LOCK_REG,
  142. .features = CCU_FEATURE_LOCK_REG,
  143. .hw.init = CLK_HW_INIT("pll-video1", "osc24M",
  144. &ccu_nkmp_ops,
  145. CLK_SET_RATE_UNGATE),
  146. },
  147. };
  148. static struct ccu_nkmp pll_gpu_clk = {
  149. .enable = BIT(31),
  150. .lock = BIT(8),
  151. .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
  152. .m = _SUNXI_CCU_DIV(16, 1), /* input divider */
  153. .p = _SUNXI_CCU_DIV(18, 1), /* output divider */
  154. .common = {
  155. .reg = 0x020,
  156. .lock_reg = CCU_SUN9I_LOCK_REG,
  157. .features = CCU_FEATURE_LOCK_REG,
  158. .hw.init = CLK_HW_INIT("pll-gpu", "osc24M",
  159. &ccu_nkmp_ops,
  160. CLK_SET_RATE_UNGATE),
  161. },
  162. };
  163. static struct ccu_nkmp pll_de_clk = {
  164. .enable = BIT(31),
  165. .lock = BIT(9),
  166. .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
  167. .m = _SUNXI_CCU_DIV(16, 1), /* input divider */
  168. .p = _SUNXI_CCU_DIV(18, 1), /* output divider */
  169. .common = {
  170. .reg = 0x024,
  171. .lock_reg = CCU_SUN9I_LOCK_REG,
  172. .features = CCU_FEATURE_LOCK_REG,
  173. .hw.init = CLK_HW_INIT("pll-de", "osc24M",
  174. &ccu_nkmp_ops,
  175. CLK_SET_RATE_UNGATE),
  176. },
  177. };
  178. static struct ccu_nkmp pll_isp_clk = {
  179. .enable = BIT(31),
  180. .lock = BIT(10),
  181. .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
  182. .m = _SUNXI_CCU_DIV(16, 1), /* input divider */
  183. .p = _SUNXI_CCU_DIV(18, 1), /* output divider */
  184. .common = {
  185. .reg = 0x028,
  186. .lock_reg = CCU_SUN9I_LOCK_REG,
  187. .features = CCU_FEATURE_LOCK_REG,
  188. .hw.init = CLK_HW_INIT("pll-isp", "osc24M",
  189. &ccu_nkmp_ops,
  190. CLK_SET_RATE_UNGATE),
  191. },
  192. };
  193. static struct ccu_nkmp pll_periph1_clk = {
  194. .enable = BIT(31),
  195. .lock = BIT(11),
  196. .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
  197. .m = _SUNXI_CCU_DIV(16, 1), /* input divider */
  198. .p = _SUNXI_CCU_DIV(18, 1), /* output divider */
  199. .common = {
  200. .reg = 0x028,
  201. .lock_reg = CCU_SUN9I_LOCK_REG,
  202. .features = CCU_FEATURE_LOCK_REG,
  203. .hw.init = CLK_HW_INIT("pll-periph1", "osc24M",
  204. &ccu_nkmp_ops,
  205. CLK_SET_RATE_UNGATE),
  206. },
  207. };
  208. static const char * const c0cpux_parents[] = { "osc24M", "pll-c0cpux" };
  209. static SUNXI_CCU_MUX(c0cpux_clk, "c0cpux", c0cpux_parents,
  210. 0x50, 0, 1, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
  211. static const char * const c1cpux_parents[] = { "osc24M", "pll-c1cpux" };
  212. static SUNXI_CCU_MUX(c1cpux_clk, "c1cpux", c1cpux_parents,
  213. 0x50, 8, 1, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
  214. static struct clk_div_table axi_div_table[] = {
  215. { .val = 0, .div = 1 },
  216. { .val = 1, .div = 2 },
  217. { .val = 2, .div = 3 },
  218. { .val = 3, .div = 4 },
  219. { .val = 4, .div = 4 },
  220. { .val = 5, .div = 4 },
  221. { .val = 6, .div = 4 },
  222. { .val = 7, .div = 4 },
  223. { /* Sentinel */ },
  224. };
  225. static SUNXI_CCU_M(atb0_clk, "atb0", "c0cpux", 0x054, 8, 2, 0);
  226. static SUNXI_CCU_DIV_TABLE(axi0_clk, "axi0", "c0cpux",
  227. 0x054, 0, 3, axi_div_table, 0);
  228. static SUNXI_CCU_M(atb1_clk, "atb1", "c1cpux", 0x058, 8, 2, 0);
  229. static SUNXI_CCU_DIV_TABLE(axi1_clk, "axi1", "c1cpux",
  230. 0x058, 0, 3, axi_div_table, 0);
  231. static const char * const gtbus_parents[] = { "osc24M", "pll-periph0",
  232. "pll-periph1", "pll-periph1" };
  233. static SUNXI_CCU_M_WITH_MUX(gtbus_clk, "gtbus", gtbus_parents,
  234. 0x05c, 0, 2, 24, 2, CLK_IS_CRITICAL);
  235. static const char * const ahb_parents[] = { "gtbus", "pll-periph0",
  236. "pll-periph1", "pll-periph1" };
  237. static struct ccu_div ahb0_clk = {
  238. .div = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
  239. .mux = _SUNXI_CCU_MUX(24, 2),
  240. .common = {
  241. .reg = 0x060,
  242. .hw.init = CLK_HW_INIT_PARENTS("ahb0",
  243. ahb_parents,
  244. &ccu_div_ops,
  245. 0),
  246. },
  247. };
  248. static struct ccu_div ahb1_clk = {
  249. .div = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
  250. .mux = _SUNXI_CCU_MUX(24, 2),
  251. .common = {
  252. .reg = 0x064,
  253. .hw.init = CLK_HW_INIT_PARENTS("ahb1",
  254. ahb_parents,
  255. &ccu_div_ops,
  256. 0),
  257. },
  258. };
  259. static struct ccu_div ahb2_clk = {
  260. .div = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
  261. .mux = _SUNXI_CCU_MUX(24, 2),
  262. .common = {
  263. .reg = 0x068,
  264. .hw.init = CLK_HW_INIT_PARENTS("ahb2",
  265. ahb_parents,
  266. &ccu_div_ops,
  267. 0),
  268. },
  269. };
  270. static const char * const apb_parents[] = { "osc24M", "pll-periph0" };
  271. static struct ccu_div apb0_clk = {
  272. .div = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
  273. .mux = _SUNXI_CCU_MUX(24, 1),
  274. .common = {
  275. .reg = 0x070,
  276. .hw.init = CLK_HW_INIT_PARENTS("apb0",
  277. apb_parents,
  278. &ccu_div_ops,
  279. 0),
  280. },
  281. };
  282. static struct ccu_div apb1_clk = {
  283. .div = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
  284. .mux = _SUNXI_CCU_MUX(24, 1),
  285. .common = {
  286. .reg = 0x074,
  287. .hw.init = CLK_HW_INIT_PARENTS("apb1",
  288. apb_parents,
  289. &ccu_div_ops,
  290. 0),
  291. },
  292. };
  293. static struct ccu_div cci400_clk = {
  294. .div = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
  295. .mux = _SUNXI_CCU_MUX(24, 2),
  296. .common = {
  297. .reg = 0x078,
  298. .hw.init = CLK_HW_INIT_PARENTS("cci400",
  299. ahb_parents,
  300. &ccu_div_ops,
  301. CLK_IS_CRITICAL),
  302. },
  303. };
  304. static SUNXI_CCU_M_WITH_MUX_GATE(ats_clk, "ats", apb_parents,
  305. 0x080, 0, 3, 24, 2, BIT(31), 0);
  306. static SUNXI_CCU_M_WITH_MUX_GATE(trace_clk, "trace", apb_parents,
  307. 0x084, 0, 3, 24, 2, BIT(31), 0);
  308. static const char * const out_parents[] = { "osc24M", "osc32k", "osc24M" };
  309. static const struct ccu_mux_fixed_prediv out_prediv = {
  310. .index = 0, .div = 750
  311. };
  312. static struct ccu_mp out_a_clk = {
  313. .enable = BIT(31),
  314. .m = _SUNXI_CCU_DIV(8, 5),
  315. .p = _SUNXI_CCU_DIV(20, 2),
  316. .mux = {
  317. .shift = 24,
  318. .width = 4,
  319. .fixed_predivs = &out_prediv,
  320. .n_predivs = 1,
  321. },
  322. .common = {
  323. .reg = 0x180,
  324. .features = CCU_FEATURE_FIXED_PREDIV,
  325. .hw.init = CLK_HW_INIT_PARENTS("out-a",
  326. out_parents,
  327. &ccu_mp_ops,
  328. 0),
  329. },
  330. };
  331. static struct ccu_mp out_b_clk = {
  332. .enable = BIT(31),
  333. .m = _SUNXI_CCU_DIV(8, 5),
  334. .p = _SUNXI_CCU_DIV(20, 2),
  335. .mux = {
  336. .shift = 24,
  337. .width = 4,
  338. .fixed_predivs = &out_prediv,
  339. .n_predivs = 1,
  340. },
  341. .common = {
  342. .reg = 0x184,
  343. .features = CCU_FEATURE_FIXED_PREDIV,
  344. .hw.init = CLK_HW_INIT_PARENTS("out-b",
  345. out_parents,
  346. &ccu_mp_ops,
  347. 0),
  348. },
  349. };
  350. static const char * const mod0_default_parents[] = { "osc24M", "pll-periph0" };
  351. static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_0_clk, "nand0-0", mod0_default_parents,
  352. 0x400,
  353. 0, 4, /* M */
  354. 16, 2, /* P */
  355. 24, 4, /* mux */
  356. BIT(31), /* gate */
  357. 0);
  358. static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_1_clk, "nand0-1", mod0_default_parents,
  359. 0x404,
  360. 0, 4, /* M */
  361. 16, 2, /* P */
  362. 24, 4, /* mux */
  363. BIT(31), /* gate */
  364. 0);
  365. static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_0_clk, "nand1-0", mod0_default_parents,
  366. 0x408,
  367. 0, 4, /* M */
  368. 16, 2, /* P */
  369. 24, 4, /* mux */
  370. BIT(31), /* gate */
  371. 0);
  372. static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_1_clk, "nand1-1", mod0_default_parents,
  373. 0x40c,
  374. 0, 4, /* M */
  375. 16, 2, /* P */
  376. 24, 4, /* mux */
  377. BIT(31), /* gate */
  378. 0);
  379. static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mod0_default_parents,
  380. 0x410,
  381. 0, 4, /* M */
  382. 16, 2, /* P */
  383. 24, 4, /* mux */
  384. BIT(31), /* gate */
  385. 0);
  386. static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0-sample", "mmc0",
  387. 0x410, 20, 3, 0);
  388. static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0-output", "mmc0",
  389. 0x410, 8, 3, 0);
  390. static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mod0_default_parents,
  391. 0x414,
  392. 0, 4, /* M */
  393. 16, 2, /* P */
  394. 24, 4, /* mux */
  395. BIT(31), /* gate */
  396. 0);
  397. static SUNXI_CCU_PHASE(mmc1_sample_clk, "mmc1-sample", "mmc1",
  398. 0x414, 20, 3, 0);
  399. static SUNXI_CCU_PHASE(mmc1_output_clk, "mmc1-output", "mmc1",
  400. 0x414, 8, 3, 0);
  401. static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mod0_default_parents,
  402. 0x418,
  403. 0, 4, /* M */
  404. 16, 2, /* P */
  405. 24, 4, /* mux */
  406. BIT(31), /* gate */
  407. 0);
  408. static SUNXI_CCU_PHASE(mmc2_sample_clk, "mmc2-sample", "mmc2",
  409. 0x418, 20, 3, 0);
  410. static SUNXI_CCU_PHASE(mmc2_output_clk, "mmc2-output", "mmc2",
  411. 0x418, 8, 3, 0);
  412. static SUNXI_CCU_MP_WITH_MUX_GATE(mmc3_clk, "mmc3", mod0_default_parents,
  413. 0x41c,
  414. 0, 4, /* M */
  415. 16, 2, /* P */
  416. 24, 4, /* mux */
  417. BIT(31), /* gate */
  418. 0);
  419. static SUNXI_CCU_PHASE(mmc3_sample_clk, "mmc3-sample", "mmc3",
  420. 0x41c, 20, 3, 0);
  421. static SUNXI_CCU_PHASE(mmc3_output_clk, "mmc3-output", "mmc3",
  422. 0x41c, 8, 3, 0);
  423. static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", mod0_default_parents,
  424. 0x428,
  425. 0, 4, /* M */
  426. 16, 2, /* P */
  427. 24, 4, /* mux */
  428. BIT(31), /* gate */
  429. 0);
  430. static const char * const ss_parents[] = { "osc24M", "pll-periph",
  431. "pll-periph1" };
  432. static const u8 ss_table[] = { 0, 1, 13 };
  433. static struct ccu_mp ss_clk = {
  434. .enable = BIT(31),
  435. .m = _SUNXI_CCU_DIV(0, 4),
  436. .p = _SUNXI_CCU_DIV(16, 2),
  437. .mux = _SUNXI_CCU_MUX_TABLE(24, 4, ss_table),
  438. .common = {
  439. .reg = 0x42c,
  440. .hw.init = CLK_HW_INIT_PARENTS("ss",
  441. ss_parents,
  442. &ccu_mp_ops,
  443. 0),
  444. },
  445. };
  446. static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents,
  447. 0x430,
  448. 0, 4, /* M */
  449. 16, 2, /* P */
  450. 24, 4, /* mux */
  451. BIT(31), /* gate */
  452. 0);
  453. static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents,
  454. 0x434,
  455. 0, 4, /* M */
  456. 16, 2, /* P */
  457. 24, 4, /* mux */
  458. BIT(31), /* gate */
  459. 0);
  460. static SUNXI_CCU_MP_WITH_MUX_GATE(spi2_clk, "spi2", mod0_default_parents,
  461. 0x438,
  462. 0, 4, /* M */
  463. 16, 2, /* P */
  464. 24, 4, /* mux */
  465. BIT(31), /* gate */
  466. 0);
  467. static SUNXI_CCU_MP_WITH_MUX_GATE(spi3_clk, "spi3", mod0_default_parents,
  468. 0x43c,
  469. 0, 4, /* M */
  470. 16, 2, /* P */
  471. 24, 4, /* mux */
  472. BIT(31), /* gate */
  473. 0);
  474. static SUNXI_CCU_M_WITH_GATE(i2s0_clk, "i2s0", "pll-audio",
  475. 0x440, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
  476. static SUNXI_CCU_M_WITH_GATE(i2s1_clk, "i2s1", "pll-audio",
  477. 0x444, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
  478. static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio",
  479. 0x44c, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
  480. static const char * const sdram_parents[] = { "pll-periph0", "pll-ddr" };
  481. static const u8 sdram_table[] = { 0, 3 };
  482. static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(sdram_clk, "sdram",
  483. sdram_parents, sdram_table,
  484. 0x484,
  485. 8, 4, /* M */
  486. 12, 4, /* mux */
  487. 0, /* no gate */
  488. CLK_IS_CRITICAL);
  489. static SUNXI_CCU_M_WITH_GATE(de_clk, "de", "pll-de", 0x490,
  490. 0, 4, BIT(31), CLK_SET_RATE_PARENT);
  491. static SUNXI_CCU_GATE(edp_clk, "edp", "osc24M", 0x494, BIT(31), 0);
  492. static const char * const mp_parents[] = { "pll-video1", "pll-gpu", "pll-de" };
  493. static const u8 mp_table[] = { 9, 10, 11 };
  494. static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(mp_clk, "mp", mp_parents, mp_table,
  495. 0x498,
  496. 0, 4, /* M */
  497. 24, 4, /* mux */
  498. BIT(31), /* gate */
  499. 0);
  500. static const char * const display_parents[] = { "pll-video0", "pll-video1" };
  501. static const u8 display_table[] = { 8, 9 };
  502. static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(lcd0_clk, "lcd0",
  503. display_parents, display_table,
  504. 0x49c,
  505. 0, 4, /* M */
  506. 24, 4, /* mux */
  507. BIT(31), /* gate */
  508. CLK_SET_RATE_NO_REPARENT |
  509. CLK_SET_RATE_PARENT);
  510. static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(lcd1_clk, "lcd1",
  511. display_parents, display_table,
  512. 0x4a0,
  513. 0, 4, /* M */
  514. 24, 4, /* mux */
  515. BIT(31), /* gate */
  516. CLK_SET_RATE_NO_REPARENT |
  517. CLK_SET_RATE_PARENT);
  518. static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(mipi_dsi0_clk, "mipi-dsi0",
  519. display_parents, display_table,
  520. 0x4a8,
  521. 0, 4, /* M */
  522. 24, 4, /* mux */
  523. BIT(31), /* gate */
  524. CLK_SET_RATE_PARENT);
  525. static const char * const mipi_dsi1_parents[] = { "osc24M", "pll-video1" };
  526. static const u8 mipi_dsi1_table[] = { 0, 9 };
  527. static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(mipi_dsi1_clk, "mipi-dsi1",
  528. mipi_dsi1_parents, mipi_dsi1_table,
  529. 0x4ac,
  530. 0, 4, /* M */
  531. 24, 4, /* mux */
  532. BIT(31), /* gate */
  533. CLK_SET_RATE_PARENT);
  534. static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(hdmi_clk, "hdmi",
  535. display_parents, display_table,
  536. 0x4b0,
  537. 0, 4, /* M */
  538. 24, 4, /* mux */
  539. BIT(31), /* gate */
  540. CLK_SET_RATE_NO_REPARENT |
  541. CLK_SET_RATE_PARENT);
  542. static SUNXI_CCU_GATE(hdmi_slow_clk, "hdmi-slow", "osc24M", 0x4b4, BIT(31), 0);
  543. static SUNXI_CCU_M_WITH_GATE(mipi_csi_clk, "mipi-csi", "osc24M", 0x4bc,
  544. 0, 4, BIT(31), 0);
  545. static SUNXI_CCU_M_WITH_GATE(csi_isp_clk, "csi-isp", "pll-isp", 0x4c0,
  546. 0, 4, BIT(31), CLK_SET_RATE_PARENT);
  547. static SUNXI_CCU_GATE(csi_misc_clk, "csi-misc", "osc24M", 0x4c0, BIT(16), 0);
  548. static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi0_mclk_clk, "csi0-mclk",
  549. mipi_dsi1_parents, mipi_dsi1_table,
  550. 0x4c4,
  551. 0, 4, /* M */
  552. 24, 4, /* mux */
  553. BIT(31), /* gate */
  554. CLK_SET_RATE_PARENT);
  555. static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi1_mclk_clk, "csi1-mclk",
  556. mipi_dsi1_parents, mipi_dsi1_table,
  557. 0x4c8,
  558. 0, 4, /* M */
  559. 24, 4, /* mux */
  560. BIT(31), /* gate */
  561. CLK_SET_RATE_PARENT);
  562. static const char * const fd_parents[] = { "pll-periph0", "pll-isp" };
  563. static const u8 fd_table[] = { 1, 12 };
  564. static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(fd_clk, "fd", fd_parents, fd_table,
  565. 0x4cc,
  566. 0, 4, /* M */
  567. 24, 4, /* mux */
  568. BIT(31), /* gate */
  569. 0);
  570. static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve", 0x4d0,
  571. 16, 3, BIT(31), CLK_SET_RATE_PARENT);
  572. static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x4d4, BIT(31), 0);
  573. static SUNXI_CCU_M_WITH_GATE(gpu_core_clk, "gpu-core", "pll-gpu", 0x4f0,
  574. 0, 3, BIT(31), CLK_SET_RATE_PARENT);
  575. static SUNXI_CCU_M_WITH_GATE(gpu_memory_clk, "gpu-memory", "pll-gpu", 0x4f4,
  576. 0, 3, BIT(31), CLK_SET_RATE_PARENT);
  577. static const char * const gpu_axi_parents[] = { "pll-periph0", "pll-gpu" };
  578. static const u8 gpu_axi_table[] = { 1, 10 };
  579. static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(gpu_axi_clk, "gpu-axi",
  580. gpu_axi_parents, gpu_axi_table,
  581. 0x4f8,
  582. 0, 4, /* M */
  583. 24, 4, /* mux */
  584. BIT(31), /* gate */
  585. CLK_SET_RATE_PARENT);
  586. static SUNXI_CCU_M_WITH_GATE(sata_clk, "sata", "pll-periph0", 0x500,
  587. 0, 4, BIT(31), 0);
  588. static SUNXI_CCU_M_WITH_GATE(ac97_clk, "ac97", "pll-audio",
  589. 0x504, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
  590. static SUNXI_CCU_M_WITH_MUX_GATE(mipi_hsi_clk, "mipi-hsi",
  591. mod0_default_parents, 0x508,
  592. 0, 4, /* M */
  593. 24, 4, /* mux */
  594. BIT(31), /* gate */
  595. 0);
  596. static const char * const gpadc_parents[] = { "osc24M", "pll-audio", "osc32k" };
  597. static const u8 gpadc_table[] = { 0, 4, 7 };
  598. static struct ccu_mp gpadc_clk = {
  599. .enable = BIT(31),
  600. .m = _SUNXI_CCU_DIV(0, 4),
  601. .p = _SUNXI_CCU_DIV(16, 2),
  602. .mux = _SUNXI_CCU_MUX_TABLE(24, 4, gpadc_table),
  603. .common = {
  604. .reg = 0x50c,
  605. .hw.init = CLK_HW_INIT_PARENTS("gpadc",
  606. gpadc_parents,
  607. &ccu_mp_ops,
  608. 0),
  609. },
  610. };
  611. static const char * const cir_tx_parents[] = { "osc24M", "osc32k" };
  612. static const u8 cir_tx_table[] = { 0, 7 };
  613. static struct ccu_mp cir_tx_clk = {
  614. .enable = BIT(31),
  615. .m = _SUNXI_CCU_DIV(0, 4),
  616. .p = _SUNXI_CCU_DIV(16, 2),
  617. .mux = _SUNXI_CCU_MUX_TABLE(24, 4, cir_tx_table),
  618. .common = {
  619. .reg = 0x510,
  620. .hw.init = CLK_HW_INIT_PARENTS("cir-tx",
  621. cir_tx_parents,
  622. &ccu_mp_ops,
  623. 0),
  624. },
  625. };
  626. /* AHB0 bus gates */
  627. static SUNXI_CCU_GATE(bus_fd_clk, "bus-fd", "ahb0",
  628. 0x580, BIT(0), 0);
  629. static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "ahb0",
  630. 0x580, BIT(1), 0);
  631. static SUNXI_CCU_GATE(bus_gpu_ctrl_clk, "bus-gpu-ctrl", "ahb0",
  632. 0x580, BIT(3), 0);
  633. static SUNXI_CCU_GATE(bus_ss_clk, "bus-ss", "ahb0",
  634. 0x580, BIT(5), 0);
  635. static SUNXI_CCU_GATE(bus_mmc_clk, "bus-mmc", "ahb0",
  636. 0x580, BIT(8), 0);
  637. static SUNXI_CCU_GATE(bus_nand0_clk, "bus-nand0", "ahb0",
  638. 0x580, BIT(12), 0);
  639. static SUNXI_CCU_GATE(bus_nand1_clk, "bus-nand1", "ahb0",
  640. 0x580, BIT(13), 0);
  641. static SUNXI_CCU_GATE(bus_sdram_clk, "bus-sdram", "ahb0",
  642. 0x580, BIT(14), 0);
  643. static SUNXI_CCU_GATE(bus_mipi_hsi_clk, "bus-mipi-hsi", "ahb0",
  644. 0x580, BIT(15), 0);
  645. static SUNXI_CCU_GATE(bus_sata_clk, "bus-sata", "ahb0",
  646. 0x580, BIT(16), 0);
  647. static SUNXI_CCU_GATE(bus_ts_clk, "bus-ts", "ahb0",
  648. 0x580, BIT(18), 0);
  649. static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb0",
  650. 0x580, BIT(20), 0);
  651. static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb0",
  652. 0x580, BIT(21), 0);
  653. static SUNXI_CCU_GATE(bus_spi2_clk, "bus-spi2", "ahb0",
  654. 0x580, BIT(22), 0);
  655. static SUNXI_CCU_GATE(bus_spi3_clk, "bus-spi3", "ahb0",
  656. 0x580, BIT(23), 0);
  657. /* AHB1 bus gates */
  658. static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb1",
  659. 0x584, BIT(0), 0);
  660. static SUNXI_CCU_GATE(bus_usb_clk, "bus-usb", "ahb1",
  661. 0x584, BIT(1), 0);
  662. static SUNXI_CCU_GATE(bus_gmac_clk, "bus-gmac", "ahb1",
  663. 0x584, BIT(17), 0);
  664. static SUNXI_CCU_GATE(bus_msgbox_clk, "bus-msgbox", "ahb1",
  665. 0x584, BIT(21), 0);
  666. static SUNXI_CCU_GATE(bus_spinlock_clk, "bus-spinlock", "ahb1",
  667. 0x584, BIT(22), 0);
  668. static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "ahb1",
  669. 0x584, BIT(23), 0);
  670. static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "ahb1",
  671. 0x584, BIT(24), 0);
  672. /* AHB2 bus gates */
  673. static SUNXI_CCU_GATE(bus_lcd0_clk, "bus-lcd0", "ahb2",
  674. 0x588, BIT(0), 0);
  675. static SUNXI_CCU_GATE(bus_lcd1_clk, "bus-lcd1", "ahb2",
  676. 0x588, BIT(1), 0);
  677. static SUNXI_CCU_GATE(bus_edp_clk, "bus-edp", "ahb2",
  678. 0x588, BIT(2), 0);
  679. static SUNXI_CCU_GATE(bus_csi_clk, "bus-csi", "ahb2",
  680. 0x588, BIT(4), 0);
  681. static SUNXI_CCU_GATE(bus_hdmi_clk, "bus-hdmi", "ahb2",
  682. 0x588, BIT(5), 0);
  683. static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "ahb2",
  684. 0x588, BIT(7), 0);
  685. static SUNXI_CCU_GATE(bus_mp_clk, "bus-mp", "ahb2",
  686. 0x588, BIT(8), 0);
  687. static SUNXI_CCU_GATE(bus_mipi_dsi_clk, "bus-mipi-dsi", "ahb2",
  688. 0x588, BIT(11), 0);
  689. /* APB0 bus gates */
  690. static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb0",
  691. 0x590, BIT(1), 0);
  692. static SUNXI_CCU_GATE(bus_pio_clk, "bus-pio", "apb0",
  693. 0x590, BIT(5), 0);
  694. static SUNXI_CCU_GATE(bus_ac97_clk, "bus-ac97", "apb0",
  695. 0x590, BIT(11), 0);
  696. static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb0",
  697. 0x590, BIT(12), 0);
  698. static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1", "apb0",
  699. 0x590, BIT(13), 0);
  700. static SUNXI_CCU_GATE(bus_lradc_clk, "bus-lradc", "apb0",
  701. 0x590, BIT(15), 0);
  702. static SUNXI_CCU_GATE(bus_gpadc_clk, "bus-gpadc", "apb0",
  703. 0x590, BIT(17), 0);
  704. static SUNXI_CCU_GATE(bus_twd_clk, "bus-twd", "apb0",
  705. 0x590, BIT(18), 0);
  706. static SUNXI_CCU_GATE(bus_cir_tx_clk, "bus-cir-tx", "apb0",
  707. 0x590, BIT(19), 0);
  708. /* APB1 bus gates */
  709. static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb1",
  710. 0x594, BIT(0), 0);
  711. static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb1",
  712. 0x594, BIT(1), 0);
  713. static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb1",
  714. 0x594, BIT(2), 0);
  715. static SUNXI_CCU_GATE(bus_i2c3_clk, "bus-i2c3", "apb1",
  716. 0x594, BIT(3), 0);
  717. static SUNXI_CCU_GATE(bus_i2c4_clk, "bus-i2c4", "apb1",
  718. 0x594, BIT(4), 0);
  719. static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb1",
  720. 0x594, BIT(16), 0);
  721. static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb1",
  722. 0x594, BIT(17), 0);
  723. static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb1",
  724. 0x594, BIT(18), 0);
  725. static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb1",
  726. 0x594, BIT(19), 0);
  727. static SUNXI_CCU_GATE(bus_uart4_clk, "bus-uart4", "apb1",
  728. 0x594, BIT(20), 0);
  729. static SUNXI_CCU_GATE(bus_uart5_clk, "bus-uart5", "apb1",
  730. 0x594, BIT(21), 0);
  731. static struct ccu_common *sun9i_a80_ccu_clks[] = {
  732. &pll_c0cpux_clk.common,
  733. &pll_c1cpux_clk.common,
  734. &pll_audio_clk.common,
  735. &pll_periph0_clk.common,
  736. &pll_ve_clk.common,
  737. &pll_ddr_clk.common,
  738. &pll_video0_clk.common,
  739. &pll_video1_clk.common,
  740. &pll_gpu_clk.common,
  741. &pll_de_clk.common,
  742. &pll_isp_clk.common,
  743. &pll_periph1_clk.common,
  744. &c0cpux_clk.common,
  745. &c1cpux_clk.common,
  746. &atb0_clk.common,
  747. &axi0_clk.common,
  748. &atb1_clk.common,
  749. &axi1_clk.common,
  750. &gtbus_clk.common,
  751. &ahb0_clk.common,
  752. &ahb1_clk.common,
  753. &ahb2_clk.common,
  754. &apb0_clk.common,
  755. &apb1_clk.common,
  756. &cci400_clk.common,
  757. &ats_clk.common,
  758. &trace_clk.common,
  759. &out_a_clk.common,
  760. &out_b_clk.common,
  761. /* module clocks */
  762. &nand0_0_clk.common,
  763. &nand0_1_clk.common,
  764. &nand1_0_clk.common,
  765. &nand1_1_clk.common,
  766. &mmc0_clk.common,
  767. &mmc0_sample_clk.common,
  768. &mmc0_output_clk.common,
  769. &mmc1_clk.common,
  770. &mmc1_sample_clk.common,
  771. &mmc1_output_clk.common,
  772. &mmc2_clk.common,
  773. &mmc2_sample_clk.common,
  774. &mmc2_output_clk.common,
  775. &mmc3_clk.common,
  776. &mmc3_sample_clk.common,
  777. &mmc3_output_clk.common,
  778. &ts_clk.common,
  779. &ss_clk.common,
  780. &spi0_clk.common,
  781. &spi1_clk.common,
  782. &spi2_clk.common,
  783. &spi3_clk.common,
  784. &i2s0_clk.common,
  785. &i2s1_clk.common,
  786. &spdif_clk.common,
  787. &sdram_clk.common,
  788. &de_clk.common,
  789. &edp_clk.common,
  790. &mp_clk.common,
  791. &lcd0_clk.common,
  792. &lcd1_clk.common,
  793. &mipi_dsi0_clk.common,
  794. &mipi_dsi1_clk.common,
  795. &hdmi_clk.common,
  796. &hdmi_slow_clk.common,
  797. &mipi_csi_clk.common,
  798. &csi_isp_clk.common,
  799. &csi_misc_clk.common,
  800. &csi0_mclk_clk.common,
  801. &csi1_mclk_clk.common,
  802. &fd_clk.common,
  803. &ve_clk.common,
  804. &avs_clk.common,
  805. &gpu_core_clk.common,
  806. &gpu_memory_clk.common,
  807. &gpu_axi_clk.common,
  808. &sata_clk.common,
  809. &ac97_clk.common,
  810. &mipi_hsi_clk.common,
  811. &gpadc_clk.common,
  812. &cir_tx_clk.common,
  813. /* AHB0 bus gates */
  814. &bus_fd_clk.common,
  815. &bus_ve_clk.common,
  816. &bus_gpu_ctrl_clk.common,
  817. &bus_ss_clk.common,
  818. &bus_mmc_clk.common,
  819. &bus_nand0_clk.common,
  820. &bus_nand1_clk.common,
  821. &bus_sdram_clk.common,
  822. &bus_mipi_hsi_clk.common,
  823. &bus_sata_clk.common,
  824. &bus_ts_clk.common,
  825. &bus_spi0_clk.common,
  826. &bus_spi1_clk.common,
  827. &bus_spi2_clk.common,
  828. &bus_spi3_clk.common,
  829. /* AHB1 bus gates */
  830. &bus_otg_clk.common,
  831. &bus_usb_clk.common,
  832. &bus_gmac_clk.common,
  833. &bus_msgbox_clk.common,
  834. &bus_spinlock_clk.common,
  835. &bus_hstimer_clk.common,
  836. &bus_dma_clk.common,
  837. /* AHB2 bus gates */
  838. &bus_lcd0_clk.common,
  839. &bus_lcd1_clk.common,
  840. &bus_edp_clk.common,
  841. &bus_csi_clk.common,
  842. &bus_hdmi_clk.common,
  843. &bus_de_clk.common,
  844. &bus_mp_clk.common,
  845. &bus_mipi_dsi_clk.common,
  846. /* APB0 bus gates */
  847. &bus_spdif_clk.common,
  848. &bus_pio_clk.common,
  849. &bus_ac97_clk.common,
  850. &bus_i2s0_clk.common,
  851. &bus_i2s1_clk.common,
  852. &bus_lradc_clk.common,
  853. &bus_gpadc_clk.common,
  854. &bus_twd_clk.common,
  855. &bus_cir_tx_clk.common,
  856. /* APB1 bus gates */
  857. &bus_i2c0_clk.common,
  858. &bus_i2c1_clk.common,
  859. &bus_i2c2_clk.common,
  860. &bus_i2c3_clk.common,
  861. &bus_i2c4_clk.common,
  862. &bus_uart0_clk.common,
  863. &bus_uart1_clk.common,
  864. &bus_uart2_clk.common,
  865. &bus_uart3_clk.common,
  866. &bus_uart4_clk.common,
  867. &bus_uart5_clk.common,
  868. };
  869. static struct clk_hw_onecell_data sun9i_a80_hw_clks = {
  870. .hws = {
  871. [CLK_PLL_C0CPUX] = &pll_c0cpux_clk.common.hw,
  872. [CLK_PLL_C1CPUX] = &pll_c1cpux_clk.common.hw,
  873. [CLK_PLL_AUDIO] = &pll_audio_clk.common.hw,
  874. [CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw,
  875. [CLK_PLL_VE] = &pll_ve_clk.common.hw,
  876. [CLK_PLL_DDR] = &pll_ddr_clk.common.hw,
  877. [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw,
  878. [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw,
  879. [CLK_PLL_GPU] = &pll_gpu_clk.common.hw,
  880. [CLK_PLL_DE] = &pll_de_clk.common.hw,
  881. [CLK_PLL_ISP] = &pll_isp_clk.common.hw,
  882. [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw,
  883. [CLK_C0CPUX] = &c0cpux_clk.common.hw,
  884. [CLK_C1CPUX] = &c1cpux_clk.common.hw,
  885. [CLK_ATB0] = &atb0_clk.common.hw,
  886. [CLK_AXI0] = &axi0_clk.common.hw,
  887. [CLK_ATB1] = &atb1_clk.common.hw,
  888. [CLK_AXI1] = &axi1_clk.common.hw,
  889. [CLK_GTBUS] = &gtbus_clk.common.hw,
  890. [CLK_AHB0] = &ahb0_clk.common.hw,
  891. [CLK_AHB1] = &ahb1_clk.common.hw,
  892. [CLK_AHB2] = &ahb2_clk.common.hw,
  893. [CLK_APB0] = &apb0_clk.common.hw,
  894. [CLK_APB1] = &apb1_clk.common.hw,
  895. [CLK_CCI400] = &cci400_clk.common.hw,
  896. [CLK_ATS] = &ats_clk.common.hw,
  897. [CLK_TRACE] = &trace_clk.common.hw,
  898. [CLK_OUT_A] = &out_a_clk.common.hw,
  899. [CLK_OUT_B] = &out_b_clk.common.hw,
  900. [CLK_NAND0_0] = &nand0_0_clk.common.hw,
  901. [CLK_NAND0_1] = &nand0_1_clk.common.hw,
  902. [CLK_NAND1_0] = &nand1_0_clk.common.hw,
  903. [CLK_NAND1_1] = &nand1_1_clk.common.hw,
  904. [CLK_MMC0] = &mmc0_clk.common.hw,
  905. [CLK_MMC0_SAMPLE] = &mmc0_sample_clk.common.hw,
  906. [CLK_MMC0_OUTPUT] = &mmc0_output_clk.common.hw,
  907. [CLK_MMC1] = &mmc1_clk.common.hw,
  908. [CLK_MMC1_SAMPLE] = &mmc1_sample_clk.common.hw,
  909. [CLK_MMC1_OUTPUT] = &mmc1_output_clk.common.hw,
  910. [CLK_MMC2] = &mmc2_clk.common.hw,
  911. [CLK_MMC2_SAMPLE] = &mmc2_sample_clk.common.hw,
  912. [CLK_MMC2_OUTPUT] = &mmc2_output_clk.common.hw,
  913. [CLK_MMC3] = &mmc3_clk.common.hw,
  914. [CLK_MMC3_SAMPLE] = &mmc3_sample_clk.common.hw,
  915. [CLK_MMC3_OUTPUT] = &mmc3_output_clk.common.hw,
  916. [CLK_TS] = &ts_clk.common.hw,
  917. [CLK_SS] = &ss_clk.common.hw,
  918. [CLK_SPI0] = &spi0_clk.common.hw,
  919. [CLK_SPI1] = &spi1_clk.common.hw,
  920. [CLK_SPI2] = &spi2_clk.common.hw,
  921. [CLK_SPI3] = &spi3_clk.common.hw,
  922. [CLK_I2S0] = &i2s0_clk.common.hw,
  923. [CLK_I2S1] = &i2s1_clk.common.hw,
  924. [CLK_SPDIF] = &spdif_clk.common.hw,
  925. [CLK_SDRAM] = &sdram_clk.common.hw,
  926. [CLK_DE] = &de_clk.common.hw,
  927. [CLK_EDP] = &edp_clk.common.hw,
  928. [CLK_MP] = &mp_clk.common.hw,
  929. [CLK_LCD0] = &lcd0_clk.common.hw,
  930. [CLK_LCD1] = &lcd1_clk.common.hw,
  931. [CLK_MIPI_DSI0] = &mipi_dsi0_clk.common.hw,
  932. [CLK_MIPI_DSI1] = &mipi_dsi1_clk.common.hw,
  933. [CLK_HDMI] = &hdmi_clk.common.hw,
  934. [CLK_HDMI_SLOW] = &hdmi_slow_clk.common.hw,
  935. [CLK_MIPI_CSI] = &mipi_csi_clk.common.hw,
  936. [CLK_CSI_ISP] = &csi_isp_clk.common.hw,
  937. [CLK_CSI_MISC] = &csi_misc_clk.common.hw,
  938. [CLK_CSI0_MCLK] = &csi0_mclk_clk.common.hw,
  939. [CLK_CSI1_MCLK] = &csi1_mclk_clk.common.hw,
  940. [CLK_FD] = &fd_clk.common.hw,
  941. [CLK_VE] = &ve_clk.common.hw,
  942. [CLK_AVS] = &avs_clk.common.hw,
  943. [CLK_GPU_CORE] = &gpu_core_clk.common.hw,
  944. [CLK_GPU_MEMORY] = &gpu_memory_clk.common.hw,
  945. [CLK_GPU_AXI] = &gpu_axi_clk.common.hw,
  946. [CLK_SATA] = &sata_clk.common.hw,
  947. [CLK_AC97] = &ac97_clk.common.hw,
  948. [CLK_MIPI_HSI] = &mipi_hsi_clk.common.hw,
  949. [CLK_GPADC] = &gpadc_clk.common.hw,
  950. [CLK_CIR_TX] = &cir_tx_clk.common.hw,
  951. [CLK_BUS_FD] = &bus_fd_clk.common.hw,
  952. [CLK_BUS_VE] = &bus_ve_clk.common.hw,
  953. [CLK_BUS_GPU_CTRL] = &bus_gpu_ctrl_clk.common.hw,
  954. [CLK_BUS_SS] = &bus_ss_clk.common.hw,
  955. [CLK_BUS_MMC] = &bus_mmc_clk.common.hw,
  956. [CLK_BUS_NAND0] = &bus_nand0_clk.common.hw,
  957. [CLK_BUS_NAND1] = &bus_nand1_clk.common.hw,
  958. [CLK_BUS_SDRAM] = &bus_sdram_clk.common.hw,
  959. [CLK_BUS_MIPI_HSI] = &bus_mipi_hsi_clk.common.hw,
  960. [CLK_BUS_SATA] = &bus_sata_clk.common.hw,
  961. [CLK_BUS_TS] = &bus_ts_clk.common.hw,
  962. [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw,
  963. [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw,
  964. [CLK_BUS_SPI2] = &bus_spi2_clk.common.hw,
  965. [CLK_BUS_SPI3] = &bus_spi3_clk.common.hw,
  966. [CLK_BUS_OTG] = &bus_otg_clk.common.hw,
  967. [CLK_BUS_USB] = &bus_usb_clk.common.hw,
  968. [CLK_BUS_GMAC] = &bus_gmac_clk.common.hw,
  969. [CLK_BUS_MSGBOX] = &bus_msgbox_clk.common.hw,
  970. [CLK_BUS_SPINLOCK] = &bus_spinlock_clk.common.hw,
  971. [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw,
  972. [CLK_BUS_DMA] = &bus_dma_clk.common.hw,
  973. [CLK_BUS_LCD0] = &bus_lcd0_clk.common.hw,
  974. [CLK_BUS_LCD1] = &bus_lcd1_clk.common.hw,
  975. [CLK_BUS_EDP] = &bus_edp_clk.common.hw,
  976. [CLK_BUS_CSI] = &bus_csi_clk.common.hw,
  977. [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw,
  978. [CLK_BUS_DE] = &bus_de_clk.common.hw,
  979. [CLK_BUS_MP] = &bus_mp_clk.common.hw,
  980. [CLK_BUS_MIPI_DSI] = &bus_mipi_dsi_clk.common.hw,
  981. [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw,
  982. [CLK_BUS_PIO] = &bus_pio_clk.common.hw,
  983. [CLK_BUS_AC97] = &bus_ac97_clk.common.hw,
  984. [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw,
  985. [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw,
  986. [CLK_BUS_LRADC] = &bus_lradc_clk.common.hw,
  987. [CLK_BUS_GPADC] = &bus_gpadc_clk.common.hw,
  988. [CLK_BUS_TWD] = &bus_twd_clk.common.hw,
  989. [CLK_BUS_CIR_TX] = &bus_cir_tx_clk.common.hw,
  990. [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw,
  991. [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw,
  992. [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw,
  993. [CLK_BUS_I2C3] = &bus_i2c3_clk.common.hw,
  994. [CLK_BUS_I2C4] = &bus_i2c4_clk.common.hw,
  995. [CLK_BUS_UART0] = &bus_uart0_clk.common.hw,
  996. [CLK_BUS_UART1] = &bus_uart1_clk.common.hw,
  997. [CLK_BUS_UART2] = &bus_uart2_clk.common.hw,
  998. [CLK_BUS_UART3] = &bus_uart3_clk.common.hw,
  999. [CLK_BUS_UART4] = &bus_uart4_clk.common.hw,
  1000. [CLK_BUS_UART5] = &bus_uart5_clk.common.hw,
  1001. },
  1002. .num = CLK_NUMBER,
  1003. };
  1004. static struct ccu_reset_map sun9i_a80_ccu_resets[] = {
  1005. /* AHB0 reset controls */
  1006. [RST_BUS_FD] = { 0x5a0, BIT(0) },
  1007. [RST_BUS_VE] = { 0x5a0, BIT(1) },
  1008. [RST_BUS_GPU_CTRL] = { 0x5a0, BIT(3) },
  1009. [RST_BUS_SS] = { 0x5a0, BIT(5) },
  1010. [RST_BUS_MMC] = { 0x5a0, BIT(8) },
  1011. [RST_BUS_NAND0] = { 0x5a0, BIT(12) },
  1012. [RST_BUS_NAND1] = { 0x5a0, BIT(13) },
  1013. [RST_BUS_SDRAM] = { 0x5a0, BIT(14) },
  1014. [RST_BUS_SATA] = { 0x5a0, BIT(16) },
  1015. [RST_BUS_TS] = { 0x5a0, BIT(18) },
  1016. [RST_BUS_SPI0] = { 0x5a0, BIT(20) },
  1017. [RST_BUS_SPI1] = { 0x5a0, BIT(21) },
  1018. [RST_BUS_SPI2] = { 0x5a0, BIT(22) },
  1019. [RST_BUS_SPI3] = { 0x5a0, BIT(23) },
  1020. /* AHB1 reset controls */
  1021. [RST_BUS_OTG] = { 0x5a4, BIT(0) },
  1022. [RST_BUS_OTG_PHY] = { 0x5a4, BIT(1) },
  1023. [RST_BUS_MIPI_HSI] = { 0x5a4, BIT(9) },
  1024. [RST_BUS_GMAC] = { 0x5a4, BIT(17) },
  1025. [RST_BUS_MSGBOX] = { 0x5a4, BIT(21) },
  1026. [RST_BUS_SPINLOCK] = { 0x5a4, BIT(22) },
  1027. [RST_BUS_HSTIMER] = { 0x5a4, BIT(23) },
  1028. [RST_BUS_DMA] = { 0x5a4, BIT(24) },
  1029. /* AHB2 reset controls */
  1030. [RST_BUS_LCD0] = { 0x5a8, BIT(0) },
  1031. [RST_BUS_LCD1] = { 0x5a8, BIT(1) },
  1032. [RST_BUS_EDP] = { 0x5a8, BIT(2) },
  1033. [RST_BUS_LVDS] = { 0x5a8, BIT(3) },
  1034. [RST_BUS_CSI] = { 0x5a8, BIT(4) },
  1035. [RST_BUS_HDMI0] = { 0x5a8, BIT(5) },
  1036. [RST_BUS_HDMI1] = { 0x5a8, BIT(6) },
  1037. [RST_BUS_DE] = { 0x5a8, BIT(7) },
  1038. [RST_BUS_MP] = { 0x5a8, BIT(8) },
  1039. [RST_BUS_GPU] = { 0x5a8, BIT(9) },
  1040. [RST_BUS_MIPI_DSI] = { 0x5a8, BIT(11) },
  1041. /* APB0 reset controls */
  1042. [RST_BUS_SPDIF] = { 0x5b0, BIT(1) },
  1043. [RST_BUS_AC97] = { 0x5b0, BIT(11) },
  1044. [RST_BUS_I2S0] = { 0x5b0, BIT(12) },
  1045. [RST_BUS_I2S1] = { 0x5b0, BIT(13) },
  1046. [RST_BUS_LRADC] = { 0x5b0, BIT(15) },
  1047. [RST_BUS_GPADC] = { 0x5b0, BIT(17) },
  1048. [RST_BUS_CIR_TX] = { 0x5b0, BIT(19) },
  1049. /* APB1 reset controls */
  1050. [RST_BUS_I2C0] = { 0x5b4, BIT(0) },
  1051. [RST_BUS_I2C1] = { 0x5b4, BIT(1) },
  1052. [RST_BUS_I2C2] = { 0x5b4, BIT(2) },
  1053. [RST_BUS_I2C3] = { 0x5b4, BIT(3) },
  1054. [RST_BUS_I2C4] = { 0x5b4, BIT(4) },
  1055. [RST_BUS_UART0] = { 0x5b4, BIT(16) },
  1056. [RST_BUS_UART1] = { 0x5b4, BIT(17) },
  1057. [RST_BUS_UART2] = { 0x5b4, BIT(18) },
  1058. [RST_BUS_UART3] = { 0x5b4, BIT(19) },
  1059. [RST_BUS_UART4] = { 0x5b4, BIT(20) },
  1060. [RST_BUS_UART5] = { 0x5b4, BIT(21) },
  1061. };
  1062. static const struct sunxi_ccu_desc sun9i_a80_ccu_desc = {
  1063. .ccu_clks = sun9i_a80_ccu_clks,
  1064. .num_ccu_clks = ARRAY_SIZE(sun9i_a80_ccu_clks),
  1065. .hw_clks = &sun9i_a80_hw_clks,
  1066. .resets = sun9i_a80_ccu_resets,
  1067. .num_resets = ARRAY_SIZE(sun9i_a80_ccu_resets),
  1068. };
  1069. #define SUN9I_A80_PLL_P_SHIFT 16
  1070. #define SUN9I_A80_PLL_N_SHIFT 8
  1071. #define SUN9I_A80_PLL_N_WIDTH 8
  1072. static void sun9i_a80_cpu_pll_fixup(void __iomem *reg)
  1073. {
  1074. u32 val = readl(reg);
  1075. /* bail out if P divider is not used */
  1076. if (!(val & BIT(SUN9I_A80_PLL_P_SHIFT)))
  1077. return;
  1078. /*
  1079. * If P is used, output should be less than 288 MHz. When we
  1080. * set P to 1, we should also decrease the multiplier so the
  1081. * output doesn't go out of range, but not too much such that
  1082. * the multiplier stays above 12, the minimal operation value.
  1083. *
  1084. * To keep it simple, set the multiplier to 17, the reset value.
  1085. */
  1086. val &= ~GENMASK(SUN9I_A80_PLL_N_SHIFT + SUN9I_A80_PLL_N_WIDTH - 1,
  1087. SUN9I_A80_PLL_N_SHIFT);
  1088. val |= 17 << SUN9I_A80_PLL_N_SHIFT;
  1089. /* And clear P */
  1090. val &= ~BIT(SUN9I_A80_PLL_P_SHIFT);
  1091. writel(val, reg);
  1092. }
  1093. static int sun9i_a80_ccu_probe(struct platform_device *pdev)
  1094. {
  1095. void __iomem *reg;
  1096. u32 val;
  1097. reg = devm_platform_ioremap_resource(pdev, 0);
  1098. if (IS_ERR(reg))
  1099. return PTR_ERR(reg);
  1100. /* Enforce d1 = 0, d2 = 0 for Audio PLL */
  1101. val = readl(reg + SUN9I_A80_PLL_AUDIO_REG);
  1102. val &= ~(BIT(16) | BIT(18));
  1103. writel(val, reg + SUN9I_A80_PLL_AUDIO_REG);
  1104. /* Enforce P = 1 for both CPU cluster PLLs */
  1105. sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C0CPUX_REG);
  1106. sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C1CPUX_REG);
  1107. return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun9i_a80_ccu_desc);
  1108. }
  1109. static const struct of_device_id sun9i_a80_ccu_ids[] = {
  1110. { .compatible = "allwinner,sun9i-a80-ccu" },
  1111. { }
  1112. };
  1113. static struct platform_driver sun9i_a80_ccu_driver = {
  1114. .probe = sun9i_a80_ccu_probe,
  1115. .driver = {
  1116. .name = "sun9i-a80-ccu",
  1117. .suppress_bind_attrs = true,
  1118. .of_match_table = sun9i_a80_ccu_ids,
  1119. },
  1120. };
  1121. module_platform_driver(sun9i_a80_ccu_driver);
  1122. MODULE_IMPORT_NS(SUNXI_CCU);
  1123. MODULE_LICENSE("GPL");