clk-sunxi.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. /*
  2. * Copyright 2013 Emilio López
  3. *
  4. * Emilio López <emilio@elopez.com.ar>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. */
  16. #include <linux/clk-provider.h>
  17. #include <linux/clkdev.h>
  18. #include <linux/of.h>
  19. #include <linux/of_address.h>
  20. #include "clk-factors.h"
  21. static DEFINE_SPINLOCK(clk_lock);
  22. /**
  23. * sun4i_osc_clk_setup() - Setup function for gatable oscillator
  24. */
  25. #define SUNXI_OSC24M_GATE 0
  26. static void __init sun4i_osc_clk_setup(struct device_node *node)
  27. {
  28. struct clk *clk;
  29. struct clk_fixed_rate *fixed;
  30. struct clk_gate *gate;
  31. const char *clk_name = node->name;
  32. u32 rate;
  33. if (of_property_read_u32(node, "clock-frequency", &rate))
  34. return;
  35. /* allocate fixed-rate and gate clock structs */
  36. fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL);
  37. if (!fixed)
  38. return;
  39. gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
  40. if (!gate)
  41. goto err_free_fixed;
  42. /* set up gate and fixed rate properties */
  43. gate->reg = of_iomap(node, 0);
  44. gate->bit_idx = SUNXI_OSC24M_GATE;
  45. gate->lock = &clk_lock;
  46. fixed->fixed_rate = rate;
  47. clk = clk_register_composite(NULL, clk_name,
  48. NULL, 0,
  49. NULL, NULL,
  50. &fixed->hw, &clk_fixed_rate_ops,
  51. &gate->hw, &clk_gate_ops,
  52. CLK_IS_ROOT);
  53. if (IS_ERR(clk))
  54. goto err_free_gate;
  55. of_clk_add_provider(node, of_clk_src_simple_get, clk);
  56. clk_register_clkdev(clk, clk_name, NULL);
  57. return;
  58. err_free_gate:
  59. kfree(gate);
  60. err_free_fixed:
  61. kfree(fixed);
  62. }
  63. CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-osc-clk", sun4i_osc_clk_setup);
  64. /**
  65. * sun4i_get_pll1_factors() - calculates n, k, m, p factors for PLL1
  66. * PLL1 rate is calculated as follows
  67. * rate = (parent_rate * n * (k + 1) >> p) / (m + 1);
  68. * parent_rate is always 24Mhz
  69. */
  70. static void sun4i_get_pll1_factors(u32 *freq, u32 parent_rate,
  71. u8 *n, u8 *k, u8 *m, u8 *p)
  72. {
  73. u8 div;
  74. /* Normalize value to a 6M multiple */
  75. div = *freq / 6000000;
  76. *freq = 6000000 * div;
  77. /* we were called to round the frequency, we can now return */
  78. if (n == NULL)
  79. return;
  80. /* m is always zero for pll1 */
  81. *m = 0;
  82. /* k is 1 only on these cases */
  83. if (*freq >= 768000000 || *freq == 42000000 || *freq == 54000000)
  84. *k = 1;
  85. else
  86. *k = 0;
  87. /* p will be 3 for divs under 10 */
  88. if (div < 10)
  89. *p = 3;
  90. /* p will be 2 for divs between 10 - 20 and odd divs under 32 */
  91. else if (div < 20 || (div < 32 && (div & 1)))
  92. *p = 2;
  93. /* p will be 1 for even divs under 32, divs under 40 and odd pairs
  94. * of divs between 40-62 */
  95. else if (div < 40 || (div < 64 && (div & 2)))
  96. *p = 1;
  97. /* any other entries have p = 0 */
  98. else
  99. *p = 0;
  100. /* calculate a suitable n based on k and p */
  101. div <<= *p;
  102. div /= (*k + 1);
  103. *n = div / 4;
  104. }
  105. /**
  106. * sun6i_a31_get_pll1_factors() - calculates n, k and m factors for PLL1
  107. * PLL1 rate is calculated as follows
  108. * rate = parent_rate * (n + 1) * (k + 1) / (m + 1);
  109. * parent_rate should always be 24MHz
  110. */
  111. static void sun6i_a31_get_pll1_factors(u32 *freq, u32 parent_rate,
  112. u8 *n, u8 *k, u8 *m, u8 *p)
  113. {
  114. /*
  115. * We can operate only on MHz, this will make our life easier
  116. * later.
  117. */
  118. u32 freq_mhz = *freq / 1000000;
  119. u32 parent_freq_mhz = parent_rate / 1000000;
  120. /*
  121. * Round down the frequency to the closest multiple of either
  122. * 6 or 16
  123. */
  124. u32 round_freq_6 = round_down(freq_mhz, 6);
  125. u32 round_freq_16 = round_down(freq_mhz, 16);
  126. if (round_freq_6 > round_freq_16)
  127. freq_mhz = round_freq_6;
  128. else
  129. freq_mhz = round_freq_16;
  130. *freq = freq_mhz * 1000000;
  131. /*
  132. * If the factors pointer are null, we were just called to
  133. * round down the frequency.
  134. * Exit.
  135. */
  136. if (n == NULL)
  137. return;
  138. /* If the frequency is a multiple of 32 MHz, k is always 3 */
  139. if (!(freq_mhz % 32))
  140. *k = 3;
  141. /* If the frequency is a multiple of 9 MHz, k is always 2 */
  142. else if (!(freq_mhz % 9))
  143. *k = 2;
  144. /* If the frequency is a multiple of 8 MHz, k is always 1 */
  145. else if (!(freq_mhz % 8))
  146. *k = 1;
  147. /* Otherwise, we don't use the k factor */
  148. else
  149. *k = 0;
  150. /*
  151. * If the frequency is a multiple of 2 but not a multiple of
  152. * 3, m is 3. This is the first time we use 6 here, yet we
  153. * will use it on several other places.
  154. * We use this number because it's the lowest frequency we can
  155. * generate (with n = 0, k = 0, m = 3), so every other frequency
  156. * somehow relates to this frequency.
  157. */
  158. if ((freq_mhz % 6) == 2 || (freq_mhz % 6) == 4)
  159. *m = 2;
  160. /*
  161. * If the frequency is a multiple of 6MHz, but the factor is
  162. * odd, m will be 3
  163. */
  164. else if ((freq_mhz / 6) & 1)
  165. *m = 3;
  166. /* Otherwise, we end up with m = 1 */
  167. else
  168. *m = 1;
  169. /* Calculate n thanks to the above factors we already got */
  170. *n = freq_mhz * (*m + 1) / ((*k + 1) * parent_freq_mhz) - 1;
  171. /*
  172. * If n end up being outbound, and that we can still decrease
  173. * m, do it.
  174. */
  175. if ((*n + 1) > 31 && (*m + 1) > 1) {
  176. *n = (*n + 1) / 2 - 1;
  177. *m = (*m + 1) / 2 - 1;
  178. }
  179. }
  180. /**
  181. * sun4i_get_apb1_factors() - calculates m, p factors for APB1
  182. * APB1 rate is calculated as follows
  183. * rate = (parent_rate >> p) / (m + 1);
  184. */
  185. static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate,
  186. u8 *n, u8 *k, u8 *m, u8 *p)
  187. {
  188. u8 calcm, calcp;
  189. if (parent_rate < *freq)
  190. *freq = parent_rate;
  191. parent_rate = (parent_rate + (*freq - 1)) / *freq;
  192. /* Invalid rate! */
  193. if (parent_rate > 32)
  194. return;
  195. if (parent_rate <= 4)
  196. calcp = 0;
  197. else if (parent_rate <= 8)
  198. calcp = 1;
  199. else if (parent_rate <= 16)
  200. calcp = 2;
  201. else
  202. calcp = 3;
  203. calcm = (parent_rate >> calcp) - 1;
  204. *freq = (parent_rate >> calcp) / (calcm + 1);
  205. /* we were called to round the frequency, we can now return */
  206. if (n == NULL)
  207. return;
  208. *m = calcm;
  209. *p = calcp;
  210. }
  211. /**
  212. * sunxi_factors_clk_setup() - Setup function for factor clocks
  213. */
  214. struct factors_data {
  215. struct clk_factors_config *table;
  216. void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
  217. };
  218. static struct clk_factors_config sun4i_pll1_config = {
  219. .nshift = 8,
  220. .nwidth = 5,
  221. .kshift = 4,
  222. .kwidth = 2,
  223. .mshift = 0,
  224. .mwidth = 2,
  225. .pshift = 16,
  226. .pwidth = 2,
  227. };
  228. static struct clk_factors_config sun6i_a31_pll1_config = {
  229. .nshift = 8,
  230. .nwidth = 5,
  231. .kshift = 4,
  232. .kwidth = 2,
  233. .mshift = 0,
  234. .mwidth = 2,
  235. };
  236. static struct clk_factors_config sun4i_apb1_config = {
  237. .mshift = 0,
  238. .mwidth = 5,
  239. .pshift = 16,
  240. .pwidth = 2,
  241. };
  242. static const struct factors_data sun4i_pll1_data __initconst = {
  243. .table = &sun4i_pll1_config,
  244. .getter = sun4i_get_pll1_factors,
  245. };
  246. static const struct factors_data sun6i_a31_pll1_data __initconst = {
  247. .table = &sun6i_a31_pll1_config,
  248. .getter = sun6i_a31_get_pll1_factors,
  249. };
  250. static const struct factors_data sun4i_apb1_data __initconst = {
  251. .table = &sun4i_apb1_config,
  252. .getter = sun4i_get_apb1_factors,
  253. };
  254. static void __init sunxi_factors_clk_setup(struct device_node *node,
  255. struct factors_data *data)
  256. {
  257. struct clk *clk;
  258. const char *clk_name = node->name;
  259. const char *parent;
  260. void *reg;
  261. reg = of_iomap(node, 0);
  262. parent = of_clk_get_parent_name(node, 0);
  263. clk = clk_register_factors(NULL, clk_name, parent, 0, reg,
  264. data->table, data->getter, &clk_lock);
  265. if (!IS_ERR(clk)) {
  266. of_clk_add_provider(node, of_clk_src_simple_get, clk);
  267. clk_register_clkdev(clk, clk_name, NULL);
  268. }
  269. }
  270. /**
  271. * sunxi_mux_clk_setup() - Setup function for muxes
  272. */
  273. #define SUNXI_MUX_GATE_WIDTH 2
  274. struct mux_data {
  275. u8 shift;
  276. };
  277. static const struct mux_data sun4i_cpu_mux_data __initconst = {
  278. .shift = 16,
  279. };
  280. static const struct mux_data sun6i_a31_ahb1_mux_data __initconst = {
  281. .shift = 12,
  282. };
  283. static const struct mux_data sun4i_apb1_mux_data __initconst = {
  284. .shift = 24,
  285. };
  286. static void __init sunxi_mux_clk_setup(struct device_node *node,
  287. struct mux_data *data)
  288. {
  289. struct clk *clk;
  290. const char *clk_name = node->name;
  291. const char *parents[5];
  292. void *reg;
  293. int i = 0;
  294. reg = of_iomap(node, 0);
  295. while (i < 5 && (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
  296. i++;
  297. clk = clk_register_mux(NULL, clk_name, parents, i,
  298. CLK_SET_RATE_NO_REPARENT, reg,
  299. data->shift, SUNXI_MUX_GATE_WIDTH,
  300. 0, &clk_lock);
  301. if (clk) {
  302. of_clk_add_provider(node, of_clk_src_simple_get, clk);
  303. clk_register_clkdev(clk, clk_name, NULL);
  304. }
  305. }
  306. /**
  307. * sunxi_divider_clk_setup() - Setup function for simple divider clocks
  308. */
  309. struct div_data {
  310. u8 shift;
  311. u8 pow;
  312. u8 width;
  313. };
  314. static const struct div_data sun4i_axi_data __initconst = {
  315. .shift = 0,
  316. .pow = 0,
  317. .width = 2,
  318. };
  319. static const struct div_data sun4i_ahb_data __initconst = {
  320. .shift = 4,
  321. .pow = 1,
  322. .width = 2,
  323. };
  324. static const struct div_data sun4i_apb0_data __initconst = {
  325. .shift = 8,
  326. .pow = 1,
  327. .width = 2,
  328. };
  329. static const struct div_data sun6i_a31_apb2_div_data __initconst = {
  330. .shift = 0,
  331. .pow = 0,
  332. .width = 4,
  333. };
  334. static void __init sunxi_divider_clk_setup(struct device_node *node,
  335. struct div_data *data)
  336. {
  337. struct clk *clk;
  338. const char *clk_name = node->name;
  339. const char *clk_parent;
  340. void *reg;
  341. reg = of_iomap(node, 0);
  342. clk_parent = of_clk_get_parent_name(node, 0);
  343. clk = clk_register_divider(NULL, clk_name, clk_parent, 0,
  344. reg, data->shift, data->width,
  345. data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0,
  346. &clk_lock);
  347. if (clk) {
  348. of_clk_add_provider(node, of_clk_src_simple_get, clk);
  349. clk_register_clkdev(clk, clk_name, NULL);
  350. }
  351. }
  352. /**
  353. * sunxi_gates_clk_setup() - Setup function for leaf gates on clocks
  354. */
  355. #define SUNXI_GATES_MAX_SIZE 64
  356. struct gates_data {
  357. DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE);
  358. };
  359. static const struct gates_data sun4i_axi_gates_data __initconst = {
  360. .mask = {1},
  361. };
  362. static const struct gates_data sun4i_ahb_gates_data __initconst = {
  363. .mask = {0x7F77FFF, 0x14FB3F},
  364. };
  365. static const struct gates_data sun5i_a10s_ahb_gates_data __initconst = {
  366. .mask = {0x147667e7, 0x185915},
  367. };
  368. static const struct gates_data sun5i_a13_ahb_gates_data __initconst = {
  369. .mask = {0x107067e7, 0x185111},
  370. };
  371. static const struct gates_data sun6i_a31_ahb1_gates_data __initconst = {
  372. .mask = {0xEDFE7F62, 0x794F931},
  373. };
  374. static const struct gates_data sun7i_a20_ahb_gates_data __initconst = {
  375. .mask = { 0x12f77fff, 0x16ff3f },
  376. };
  377. static const struct gates_data sun4i_apb0_gates_data __initconst = {
  378. .mask = {0x4EF},
  379. };
  380. static const struct gates_data sun5i_a10s_apb0_gates_data __initconst = {
  381. .mask = {0x469},
  382. };
  383. static const struct gates_data sun5i_a13_apb0_gates_data __initconst = {
  384. .mask = {0x61},
  385. };
  386. static const struct gates_data sun7i_a20_apb0_gates_data __initconst = {
  387. .mask = { 0x4ff },
  388. };
  389. static const struct gates_data sun4i_apb1_gates_data __initconst = {
  390. .mask = {0xFF00F7},
  391. };
  392. static const struct gates_data sun5i_a10s_apb1_gates_data __initconst = {
  393. .mask = {0xf0007},
  394. };
  395. static const struct gates_data sun5i_a13_apb1_gates_data __initconst = {
  396. .mask = {0xa0007},
  397. };
  398. static const struct gates_data sun6i_a31_apb1_gates_data __initconst = {
  399. .mask = {0x3031},
  400. };
  401. static const struct gates_data sun6i_a31_apb2_gates_data __initconst = {
  402. .mask = {0x3F000F},
  403. };
  404. static const struct gates_data sun7i_a20_apb1_gates_data __initconst = {
  405. .mask = { 0xff80ff },
  406. };
  407. static void __init sunxi_gates_clk_setup(struct device_node *node,
  408. struct gates_data *data)
  409. {
  410. struct clk_onecell_data *clk_data;
  411. const char *clk_parent;
  412. const char *clk_name;
  413. void *reg;
  414. int qty;
  415. int i = 0;
  416. int j = 0;
  417. int ignore;
  418. reg = of_iomap(node, 0);
  419. clk_parent = of_clk_get_parent_name(node, 0);
  420. /* Worst-case size approximation and memory allocation */
  421. qty = find_last_bit(data->mask, SUNXI_GATES_MAX_SIZE);
  422. clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
  423. if (!clk_data)
  424. return;
  425. clk_data->clks = kzalloc((qty+1) * sizeof(struct clk *), GFP_KERNEL);
  426. if (!clk_data->clks) {
  427. kfree(clk_data);
  428. return;
  429. }
  430. for_each_set_bit(i, data->mask, SUNXI_GATES_MAX_SIZE) {
  431. of_property_read_string_index(node, "clock-output-names",
  432. j, &clk_name);
  433. /* No driver claims this clock, but it should remain gated */
  434. ignore = !strcmp("ahb_sdram", clk_name) ? CLK_IGNORE_UNUSED : 0;
  435. clk_data->clks[i] = clk_register_gate(NULL, clk_name,
  436. clk_parent, ignore,
  437. reg + 4 * (i/32), i % 32,
  438. 0, &clk_lock);
  439. WARN_ON(IS_ERR(clk_data->clks[i]));
  440. j++;
  441. }
  442. /* Adjust to the real max */
  443. clk_data->clk_num = i;
  444. of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
  445. }
  446. /* Matches for factors clocks */
  447. static const struct of_device_id clk_factors_match[] __initconst = {
  448. {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,},
  449. {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,},
  450. {.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,},
  451. {}
  452. };
  453. /* Matches for divider clocks */
  454. static const struct of_device_id clk_div_match[] __initconst = {
  455. {.compatible = "allwinner,sun4i-axi-clk", .data = &sun4i_axi_data,},
  456. {.compatible = "allwinner,sun4i-ahb-clk", .data = &sun4i_ahb_data,},
  457. {.compatible = "allwinner,sun4i-apb0-clk", .data = &sun4i_apb0_data,},
  458. {.compatible = "allwinner,sun6i-a31-apb2-div-clk", .data = &sun6i_a31_apb2_div_data,},
  459. {}
  460. };
  461. /* Matches for mux clocks */
  462. static const struct of_device_id clk_mux_match[] __initconst = {
  463. {.compatible = "allwinner,sun4i-cpu-clk", .data = &sun4i_cpu_mux_data,},
  464. {.compatible = "allwinner,sun4i-apb1-mux-clk", .data = &sun4i_apb1_mux_data,},
  465. {.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,},
  466. {}
  467. };
  468. /* Matches for gate clocks */
  469. static const struct of_device_id clk_gates_match[] __initconst = {
  470. {.compatible = "allwinner,sun4i-axi-gates-clk", .data = &sun4i_axi_gates_data,},
  471. {.compatible = "allwinner,sun4i-ahb-gates-clk", .data = &sun4i_ahb_gates_data,},
  472. {.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,},
  473. {.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,},
  474. {.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,},
  475. {.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,},
  476. {.compatible = "allwinner,sun4i-apb0-gates-clk", .data = &sun4i_apb0_gates_data,},
  477. {.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,},
  478. {.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,},
  479. {.compatible = "allwinner,sun7i-a20-apb0-gates-clk", .data = &sun7i_a20_apb0_gates_data,},
  480. {.compatible = "allwinner,sun4i-apb1-gates-clk", .data = &sun4i_apb1_gates_data,},
  481. {.compatible = "allwinner,sun5i-a10s-apb1-gates-clk", .data = &sun5i_a10s_apb1_gates_data,},
  482. {.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,},
  483. {.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,},
  484. {.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,},
  485. {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,},
  486. {}
  487. };
  488. static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_match,
  489. void *function)
  490. {
  491. struct device_node *np;
  492. const struct div_data *data;
  493. const struct of_device_id *match;
  494. void (*setup_function)(struct device_node *, const void *) = function;
  495. for_each_matching_node(np, clk_match) {
  496. match = of_match_node(clk_match, np);
  497. data = match->data;
  498. setup_function(np, data);
  499. }
  500. }
  501. /**
  502. * System clock protection
  503. *
  504. * By enabling these critical clocks, we prevent their accidental gating
  505. * by the framework
  506. */
  507. static void __init sunxi_clock_protect(void)
  508. {
  509. struct clk *clk;
  510. /* memory bus clock - sun5i+ */
  511. clk = clk_get(NULL, "mbus");
  512. if (!IS_ERR(clk)) {
  513. clk_prepare_enable(clk);
  514. clk_put(clk);
  515. }
  516. /* DDR clock - sun4i+ */
  517. clk = clk_get(NULL, "pll5_ddr");
  518. if (!IS_ERR(clk)) {
  519. clk_prepare_enable(clk);
  520. clk_put(clk);
  521. }
  522. }
  523. static void __init sunxi_init_clocks(void)
  524. {
  525. /* Register factor clocks */
  526. of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup);
  527. /* Register divider clocks */
  528. of_sunxi_table_clock_setup(clk_div_match, sunxi_divider_clk_setup);
  529. /* Register mux clocks */
  530. of_sunxi_table_clock_setup(clk_mux_match, sunxi_mux_clk_setup);
  531. /* Register gate clocks */
  532. of_sunxi_table_clock_setup(clk_gates_match, sunxi_gates_clk_setup);
  533. /* Enable core system clocks */
  534. sunxi_clock_protect();
  535. }
  536. CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sunxi_init_clocks);
  537. CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sunxi_init_clocks);
  538. CLK_OF_DECLARE(sun5i_a13_clk_init, "allwinner,sun5i-a13", sunxi_init_clocks);
  539. CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sunxi_init_clocks);
  540. CLK_OF_DECLARE(sun7i_a20_clk_init, "allwinner,sun7i-a20", sunxi_init_clocks);