berlin2-div.c 6.7 KB

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