clk.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /*
  2. * Copyright (c) 2014 MundoReader S.L.
  3. * Author: Heiko Stuebner <heiko@sntech.de>
  4. *
  5. * based on
  6. *
  7. * samsung/clk.c
  8. * Copyright (c) 2013 Samsung Electronics Co., Ltd.
  9. * Copyright (c) 2013 Linaro Ltd.
  10. * Author: Thomas Abraham <thomas.ab@samsung.com>
  11. *
  12. * This program is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation; either version 2 of the License, or
  15. * (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. */
  22. #include <linux/slab.h>
  23. #include <linux/clk.h>
  24. #include <linux/clk-provider.h>
  25. #include <linux/mfd/syscon.h>
  26. #include <linux/regmap.h>
  27. #include <linux/reboot.h>
  28. #include "clk.h"
  29. /**
  30. * Register a clock branch.
  31. * Most clock branches have a form like
  32. *
  33. * src1 --|--\
  34. * |M |--[GATE]-[DIV]-
  35. * src2 --|--/
  36. *
  37. * sometimes without one of those components.
  38. */
  39. static struct clk *rockchip_clk_register_branch(const char *name,
  40. const char *const *parent_names, u8 num_parents, void __iomem *base,
  41. int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags,
  42. u8 div_shift, u8 div_width, u8 div_flags,
  43. struct clk_div_table *div_table, int gate_offset,
  44. u8 gate_shift, u8 gate_flags, unsigned long flags,
  45. spinlock_t *lock)
  46. {
  47. struct clk *clk;
  48. struct clk_mux *mux = NULL;
  49. struct clk_gate *gate = NULL;
  50. struct clk_divider *div = NULL;
  51. const struct clk_ops *mux_ops = NULL, *div_ops = NULL,
  52. *gate_ops = NULL;
  53. if (num_parents > 1) {
  54. mux = kzalloc(sizeof(*mux), GFP_KERNEL);
  55. if (!mux)
  56. return ERR_PTR(-ENOMEM);
  57. mux->reg = base + muxdiv_offset;
  58. mux->shift = mux_shift;
  59. mux->mask = BIT(mux_width) - 1;
  60. mux->flags = mux_flags;
  61. mux->lock = lock;
  62. mux_ops = (mux_flags & CLK_MUX_READ_ONLY) ? &clk_mux_ro_ops
  63. : &clk_mux_ops;
  64. }
  65. if (gate_offset >= 0) {
  66. gate = kzalloc(sizeof(*gate), GFP_KERNEL);
  67. if (!gate)
  68. return ERR_PTR(-ENOMEM);
  69. gate->flags = gate_flags;
  70. gate->reg = base + gate_offset;
  71. gate->bit_idx = gate_shift;
  72. gate->lock = lock;
  73. gate_ops = &clk_gate_ops;
  74. }
  75. if (div_width > 0) {
  76. div = kzalloc(sizeof(*div), GFP_KERNEL);
  77. if (!div)
  78. return ERR_PTR(-ENOMEM);
  79. div->flags = div_flags;
  80. div->reg = base + muxdiv_offset;
  81. div->shift = div_shift;
  82. div->width = div_width;
  83. div->lock = lock;
  84. div->table = div_table;
  85. div_ops = &clk_divider_ops;
  86. }
  87. clk = clk_register_composite(NULL, name, parent_names, num_parents,
  88. mux ? &mux->hw : NULL, mux_ops,
  89. div ? &div->hw : NULL, div_ops,
  90. gate ? &gate->hw : NULL, gate_ops,
  91. flags);
  92. return clk;
  93. }
  94. static struct clk *rockchip_clk_register_frac_branch(const char *name,
  95. const char *const *parent_names, u8 num_parents,
  96. void __iomem *base, int muxdiv_offset, u8 div_flags,
  97. int gate_offset, u8 gate_shift, u8 gate_flags,
  98. unsigned long flags, spinlock_t *lock)
  99. {
  100. struct clk *clk;
  101. struct clk_gate *gate = NULL;
  102. struct clk_fractional_divider *div = NULL;
  103. const struct clk_ops *div_ops = NULL, *gate_ops = NULL;
  104. if (gate_offset >= 0) {
  105. gate = kzalloc(sizeof(*gate), GFP_KERNEL);
  106. if (!gate)
  107. return ERR_PTR(-ENOMEM);
  108. gate->flags = gate_flags;
  109. gate->reg = base + gate_offset;
  110. gate->bit_idx = gate_shift;
  111. gate->lock = lock;
  112. gate_ops = &clk_gate_ops;
  113. }
  114. if (muxdiv_offset < 0)
  115. return ERR_PTR(-EINVAL);
  116. div = kzalloc(sizeof(*div), GFP_KERNEL);
  117. if (!div)
  118. return ERR_PTR(-ENOMEM);
  119. div->flags = div_flags;
  120. div->reg = base + muxdiv_offset;
  121. div->mshift = 16;
  122. div->mmask = 0xffff0000;
  123. div->nshift = 0;
  124. div->nmask = 0xffff;
  125. div->lock = lock;
  126. div_ops = &clk_fractional_divider_ops;
  127. clk = clk_register_composite(NULL, name, parent_names, num_parents,
  128. NULL, NULL,
  129. &div->hw, div_ops,
  130. gate ? &gate->hw : NULL, gate_ops,
  131. flags);
  132. return clk;
  133. }
  134. static DEFINE_SPINLOCK(clk_lock);
  135. static struct clk **clk_table;
  136. static void __iomem *reg_base;
  137. static struct clk_onecell_data clk_data;
  138. static struct device_node *cru_node;
  139. static struct regmap *grf;
  140. void __init rockchip_clk_init(struct device_node *np, void __iomem *base,
  141. unsigned long nr_clks)
  142. {
  143. reg_base = base;
  144. cru_node = np;
  145. grf = ERR_PTR(-EPROBE_DEFER);
  146. clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL);
  147. if (!clk_table)
  148. pr_err("%s: could not allocate clock lookup table\n", __func__);
  149. clk_data.clks = clk_table;
  150. clk_data.clk_num = nr_clks;
  151. of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
  152. }
  153. struct regmap *rockchip_clk_get_grf(void)
  154. {
  155. if (IS_ERR(grf))
  156. grf = syscon_regmap_lookup_by_phandle(cru_node, "rockchip,grf");
  157. return grf;
  158. }
  159. void rockchip_clk_add_lookup(struct clk *clk, unsigned int id)
  160. {
  161. if (clk_table && id)
  162. clk_table[id] = clk;
  163. }
  164. void __init rockchip_clk_register_plls(struct rockchip_pll_clock *list,
  165. unsigned int nr_pll, int grf_lock_offset)
  166. {
  167. struct clk *clk;
  168. int idx;
  169. for (idx = 0; idx < nr_pll; idx++, list++) {
  170. clk = rockchip_clk_register_pll(list->type, list->name,
  171. list->parent_names, list->num_parents,
  172. reg_base, list->con_offset, grf_lock_offset,
  173. list->lock_shift, list->mode_offset,
  174. list->mode_shift, list->rate_table,
  175. list->pll_flags, &clk_lock);
  176. if (IS_ERR(clk)) {
  177. pr_err("%s: failed to register clock %s\n", __func__,
  178. list->name);
  179. continue;
  180. }
  181. rockchip_clk_add_lookup(clk, list->id);
  182. }
  183. }
  184. void __init rockchip_clk_register_branches(
  185. struct rockchip_clk_branch *list,
  186. unsigned int nr_clk)
  187. {
  188. struct clk *clk = NULL;
  189. unsigned int idx;
  190. unsigned long flags;
  191. for (idx = 0; idx < nr_clk; idx++, list++) {
  192. flags = list->flags;
  193. /* catch simple muxes */
  194. switch (list->branch_type) {
  195. case branch_mux:
  196. clk = clk_register_mux(NULL, list->name,
  197. list->parent_names, list->num_parents,
  198. flags, reg_base + list->muxdiv_offset,
  199. list->mux_shift, list->mux_width,
  200. list->mux_flags, &clk_lock);
  201. break;
  202. case branch_divider:
  203. if (list->div_table)
  204. clk = clk_register_divider_table(NULL,
  205. list->name, list->parent_names[0],
  206. flags, reg_base + list->muxdiv_offset,
  207. list->div_shift, list->div_width,
  208. list->div_flags, list->div_table,
  209. &clk_lock);
  210. else
  211. clk = clk_register_divider(NULL, list->name,
  212. list->parent_names[0], flags,
  213. reg_base + list->muxdiv_offset,
  214. list->div_shift, list->div_width,
  215. list->div_flags, &clk_lock);
  216. break;
  217. case branch_fraction_divider:
  218. clk = rockchip_clk_register_frac_branch(list->name,
  219. list->parent_names, list->num_parents,
  220. reg_base, list->muxdiv_offset, list->div_flags,
  221. list->gate_offset, list->gate_shift,
  222. list->gate_flags, flags, &clk_lock);
  223. break;
  224. case branch_gate:
  225. flags |= CLK_SET_RATE_PARENT;
  226. clk = clk_register_gate(NULL, list->name,
  227. list->parent_names[0], flags,
  228. reg_base + list->gate_offset,
  229. list->gate_shift, list->gate_flags, &clk_lock);
  230. break;
  231. case branch_composite:
  232. clk = rockchip_clk_register_branch(list->name,
  233. list->parent_names, list->num_parents,
  234. reg_base, list->muxdiv_offset, list->mux_shift,
  235. list->mux_width, list->mux_flags,
  236. list->div_shift, list->div_width,
  237. list->div_flags, list->div_table,
  238. list->gate_offset, list->gate_shift,
  239. list->gate_flags, flags, &clk_lock);
  240. break;
  241. case branch_mmc:
  242. clk = rockchip_clk_register_mmc(
  243. list->name,
  244. list->parent_names, list->num_parents,
  245. reg_base + list->muxdiv_offset,
  246. list->div_shift
  247. );
  248. break;
  249. }
  250. /* none of the cases above matched */
  251. if (!clk) {
  252. pr_err("%s: unknown clock type %d\n",
  253. __func__, list->branch_type);
  254. continue;
  255. }
  256. if (IS_ERR(clk)) {
  257. pr_err("%s: failed to register clock %s: %ld\n",
  258. __func__, list->name, PTR_ERR(clk));
  259. continue;
  260. }
  261. rockchip_clk_add_lookup(clk, list->id);
  262. }
  263. }
  264. void __init rockchip_clk_register_armclk(unsigned int lookup_id,
  265. const char *name, const char *const *parent_names,
  266. u8 num_parents,
  267. const struct rockchip_cpuclk_reg_data *reg_data,
  268. const struct rockchip_cpuclk_rate_table *rates,
  269. int nrates)
  270. {
  271. struct clk *clk;
  272. clk = rockchip_clk_register_cpuclk(name, parent_names, num_parents,
  273. reg_data, rates, nrates, reg_base,
  274. &clk_lock);
  275. if (IS_ERR(clk)) {
  276. pr_err("%s: failed to register clock %s: %ld\n",
  277. __func__, name, PTR_ERR(clk));
  278. return;
  279. }
  280. rockchip_clk_add_lookup(clk, lookup_id);
  281. }
  282. void __init rockchip_clk_protect_critical(const char *const clocks[],
  283. int nclocks)
  284. {
  285. int i;
  286. /* Protect the clocks that needs to stay on */
  287. for (i = 0; i < nclocks; i++) {
  288. struct clk *clk = __clk_lookup(clocks[i]);
  289. if (clk)
  290. clk_prepare_enable(clk);
  291. }
  292. }
  293. static unsigned int reg_restart;
  294. static int rockchip_restart_notify(struct notifier_block *this,
  295. unsigned long mode, void *cmd)
  296. {
  297. writel(0xfdb9, reg_base + reg_restart);
  298. return NOTIFY_DONE;
  299. }
  300. static struct notifier_block rockchip_restart_handler = {
  301. .notifier_call = rockchip_restart_notify,
  302. .priority = 128,
  303. };
  304. void __init rockchip_register_restart_notifier(unsigned int reg)
  305. {
  306. int ret;
  307. reg_restart = reg;
  308. ret = register_restart_handler(&rockchip_restart_handler);
  309. if (ret)
  310. pr_err("%s: cannot register restart handler, %d\n",
  311. __func__, ret);
  312. }