berlin2-div.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. * Copyright (c) 2014 Marvell Technology Group Ltd.
  3. *
  4. * Alexandre Belloni <alexandre.belloni@free-electrons.com>
  5. * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify it
  8. * under the terms and conditions of the GNU General Public License,
  9. * version 2, as published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope it will be useful, but WITHOUT
  12. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  14. * more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along with
  17. * this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <linux/bitops.h>
  20. #include <linux/clk-provider.h>
  21. #include <linux/of.h>
  22. #include <linux/of_address.h>
  23. #include <linux/slab.h>
  24. #include <linux/spinlock.h>
  25. #include "berlin2-div.h"
  26. /*
  27. * Clock dividers in Berlin2 SoCs comprise a complex cell to select
  28. * input pll and divider. The virtual structure as it is used in Marvell
  29. * BSP code can be seen as:
  30. *
  31. * +---+
  32. * pll0 --------------->| 0 | +---+
  33. * +---+ |(B)|--+--------------->| 0 | +---+
  34. * pll1.0 -->| 0 | +-->| 1 | | +--------+ |(E)|----->| 0 | +---+
  35. * pll1.1 -->| 1 | | +---+ +-->|(C) 1:M |-->| 1 | |(F)|-->|(G)|->
  36. * ... -->|(A)|--+ | +--------+ +---+ +-->| 1 | +---+
  37. * ... -->| | +-->|(D) 1:3 |----------+ +---+
  38. * pll1.N -->| N | +---------
  39. * +---+
  40. *
  41. * (A) input pll clock mux controlled by <PllSelect[1:n]>
  42. * (B) input pll bypass mux controlled by <PllSwitch>
  43. * (C) programmable clock divider controlled by <Select[1:n]>
  44. * (D) constant div-by-3 clock divider
  45. * (E) programmable clock divider bypass controlled by <Switch>
  46. * (F) constant div-by-3 clock mux controlled by <D3Switch>
  47. * (G) clock gate controlled by <Enable>
  48. *
  49. * For whatever reason, above control signals come in two flavors:
  50. * - single register dividers with all bits in one register
  51. * - shared register dividers with bits spread over multiple registers
  52. * (including signals for the same cell spread over consecutive registers)
  53. *
  54. * Also, clock gate and pll mux is not available on every div cell, so
  55. * we have to deal with those, too. We reuse common clock composite driver
  56. * for it.
  57. */
  58. #define PLL_SELECT_MASK 0x7
  59. #define DIV_SELECT_MASK 0x7
  60. struct berlin2_div {
  61. struct clk_hw hw;
  62. void __iomem *base;
  63. struct berlin2_div_map map;
  64. spinlock_t *lock;
  65. };
  66. #define to_berlin2_div(hw) container_of(hw, struct berlin2_div, hw)
  67. static u8 clk_div[] = { 1, 2, 4, 6, 8, 12, 1, 1 };
  68. static int berlin2_div_is_enabled(struct clk_hw *hw)
  69. {
  70. struct berlin2_div *div = to_berlin2_div(hw);
  71. struct berlin2_div_map *map = &div->map;
  72. u32 reg;
  73. if (div->lock)
  74. spin_lock(div->lock);
  75. reg = readl_relaxed(div->base + map->gate_offs);
  76. reg >>= map->gate_shift;
  77. if (div->lock)
  78. spin_unlock(div->lock);
  79. return (reg & 0x1);
  80. }
  81. static int berlin2_div_enable(struct clk_hw *hw)
  82. {
  83. struct berlin2_div *div = to_berlin2_div(hw);
  84. struct berlin2_div_map *map = &div->map;
  85. u32 reg;
  86. if (div->lock)
  87. spin_lock(div->lock);
  88. reg = readl_relaxed(div->base + map->gate_offs);
  89. reg |= BIT(map->gate_shift);
  90. writel_relaxed(reg, div->base + map->gate_offs);
  91. if (div->lock)
  92. spin_unlock(div->lock);
  93. return 0;
  94. }
  95. static void berlin2_div_disable(struct clk_hw *hw)
  96. {
  97. struct berlin2_div *div = to_berlin2_div(hw);
  98. struct berlin2_div_map *map = &div->map;
  99. u32 reg;
  100. if (div->lock)
  101. spin_lock(div->lock);
  102. reg = readl_relaxed(div->base + map->gate_offs);
  103. reg &= ~BIT(map->gate_shift);
  104. writel_relaxed(reg, div->base + map->gate_offs);
  105. if (div->lock)
  106. spin_unlock(div->lock);
  107. }
  108. static int berlin2_div_set_parent(struct clk_hw *hw, u8 index)
  109. {
  110. struct berlin2_div *div = to_berlin2_div(hw);
  111. struct berlin2_div_map *map = &div->map;
  112. u32 reg;
  113. if (div->lock)
  114. spin_lock(div->lock);
  115. /* index == 0 is PLL_SWITCH */
  116. reg = readl_relaxed(div->base + map->pll_switch_offs);
  117. if (index == 0)
  118. reg &= ~BIT(map->pll_switch_shift);
  119. else
  120. reg |= BIT(map->pll_switch_shift);
  121. writel_relaxed(reg, div->base + map->pll_switch_offs);
  122. /* index > 0 is PLL_SELECT */
  123. if (index > 0) {
  124. reg = readl_relaxed(div->base + map->pll_select_offs);
  125. reg &= ~(PLL_SELECT_MASK << map->pll_select_shift);
  126. reg |= (index - 1) << map->pll_select_shift;
  127. writel_relaxed(reg, div->base + map->pll_select_offs);
  128. }
  129. if (div->lock)
  130. spin_unlock(div->lock);
  131. return 0;
  132. }
  133. static u8 berlin2_div_get_parent(struct clk_hw *hw)
  134. {
  135. struct berlin2_div *div = to_berlin2_div(hw);
  136. struct berlin2_div_map *map = &div->map;
  137. u32 reg;
  138. u8 index = 0;
  139. if (div->lock)
  140. spin_lock(div->lock);
  141. /* PLL_SWITCH == 0 is index 0 */
  142. reg = readl_relaxed(div->base + map->pll_switch_offs);
  143. reg &= BIT(map->pll_switch_shift);
  144. if (reg) {
  145. reg = readl_relaxed(div->base + map->pll_select_offs);
  146. reg >>= map->pll_select_shift;
  147. reg &= PLL_SELECT_MASK;
  148. index = 1 + reg;
  149. }
  150. if (div->lock)
  151. spin_unlock(div->lock);
  152. return index;
  153. }
  154. static unsigned long berlin2_div_recalc_rate(struct clk_hw *hw,
  155. unsigned long parent_rate)
  156. {
  157. struct berlin2_div *div = to_berlin2_div(hw);
  158. struct berlin2_div_map *map = &div->map;
  159. u32 divsw, div3sw, divider = 1;
  160. if (div->lock)
  161. spin_lock(div->lock);
  162. divsw = readl_relaxed(div->base + map->div_switch_offs) &
  163. (1 << map->div_switch_shift);
  164. div3sw = readl_relaxed(div->base + map->div3_switch_offs) &
  165. (1 << map->div3_switch_shift);
  166. /* constant divide-by-3 (dominant) */
  167. if (div3sw != 0) {
  168. divider = 3;
  169. /* divider can be bypassed with DIV_SWITCH == 0 */
  170. } else if (divsw == 0) {
  171. divider = 1;
  172. /* clock divider determined by DIV_SELECT */
  173. } else {
  174. u32 reg;
  175. reg = readl_relaxed(div->base + map->div_select_offs);
  176. reg >>= map->div_select_shift;
  177. reg &= DIV_SELECT_MASK;
  178. divider = clk_div[reg];
  179. }
  180. if (div->lock)
  181. spin_unlock(div->lock);
  182. return parent_rate / divider;
  183. }
  184. static const struct clk_ops berlin2_div_rate_ops = {
  185. .recalc_rate = berlin2_div_recalc_rate,
  186. };
  187. static const struct clk_ops berlin2_div_gate_ops = {
  188. .is_enabled = berlin2_div_is_enabled,
  189. .enable = berlin2_div_enable,
  190. .disable = berlin2_div_disable,
  191. };
  192. static const struct clk_ops berlin2_div_mux_ops = {
  193. .set_parent = berlin2_div_set_parent,
  194. .get_parent = berlin2_div_get_parent,
  195. };
  196. struct clk_hw * __init
  197. berlin2_div_register(const struct berlin2_div_map *map,
  198. void __iomem *base, const char *name, u8 div_flags,
  199. const char **parent_names, int num_parents,
  200. unsigned long flags, spinlock_t *lock)
  201. {
  202. const struct clk_ops *mux_ops = &berlin2_div_mux_ops;
  203. const struct clk_ops *rate_ops = &berlin2_div_rate_ops;
  204. const struct clk_ops *gate_ops = &berlin2_div_gate_ops;
  205. struct berlin2_div *div;
  206. div = kzalloc(sizeof(*div), GFP_KERNEL);
  207. if (!div)
  208. return ERR_PTR(-ENOMEM);
  209. /* copy div_map to allow __initconst */
  210. memcpy(&div->map, map, sizeof(*map));
  211. div->base = base;
  212. div->lock = lock;
  213. if ((div_flags & BERLIN2_DIV_HAS_GATE) == 0)
  214. gate_ops = NULL;
  215. if ((div_flags & BERLIN2_DIV_HAS_MUX) == 0)
  216. mux_ops = NULL;
  217. return clk_hw_register_composite(NULL, name, parent_names, num_parents,
  218. &div->hw, mux_ops, &div->hw, rate_ops,
  219. &div->hw, gate_ops, flags);
  220. }