100-oxnas-clk-plla-pllb.patch 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. --- a/drivers/clk/clk-oxnas.c
  2. +++ b/drivers/clk/clk-oxnas.c
  3. @@ -5,19 +5,42 @@
  4. * Copyright (C) 2016 Neil Armstrong <[email protected]>
  5. */
  6. +#include <linux/clk.h>
  7. +#include <linux/clkdev.h>
  8. #include <linux/clk-provider.h>
  9. #include <linux/kernel.h>
  10. #include <linux/init.h>
  11. +#include <linux/delay.h>
  12. #include <linux/of.h>
  13. #include <linux/of_device.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/stringify.h>
  16. #include <linux/regmap.h>
  17. #include <linux/mfd/syscon.h>
  18. +#include <linux/reset.h>
  19. #include <dt-bindings/clock/oxsemi,ox810se.h>
  20. #include <dt-bindings/clock/oxsemi,ox820.h>
  21. +#define REF300_DIV_INT_SHIFT 8
  22. +#define REF300_DIV_FRAC_SHIFT 0
  23. +#define REF300_DIV_INT(val) ((val) << REF300_DIV_INT_SHIFT)
  24. +#define REF300_DIV_FRAC(val) ((val) << REF300_DIV_FRAC_SHIFT)
  25. +
  26. +#define PLLB_BYPASS 1
  27. +#define PLLB_ENSAT 3
  28. +#define PLLB_OUTDIV 4
  29. +#define PLLB_REFDIV 8
  30. +#define PLLB_DIV_INT_SHIFT 8
  31. +#define PLLB_DIV_FRAC_SHIFT 0
  32. +#define PLLB_DIV_INT(val) ((val) << PLLB_DIV_INT_SHIFT)
  33. +#define PLLB_DIV_FRAC(val) ((val) << PLLB_DIV_FRAC_SHIFT)
  34. +
  35. +#define PLLA_REFDIV_MASK 0x3F
  36. +#define PLLA_REFDIV_SHIFT 8
  37. +#define PLLA_OUTDIV_MASK 0x7
  38. +#define PLLA_OUTDIV_SHIFT 4
  39. +
  40. /* Standard regmap gate clocks */
  41. struct clk_oxnas_gate {
  42. struct clk_hw hw;
  43. @@ -36,6 +59,135 @@ struct oxnas_stdclk_data {
  44. #define CLK_SET_REGOFFSET 0x2c
  45. #define CLK_CLR_REGOFFSET 0x30
  46. +#define PLLA_CTRL0_REGOFFSET 0x1f0
  47. +#define PLLA_CTRL1_REGOFFSET 0x1f4
  48. +#define PLLB_CTRL0_REGOFFSET 0x1001f0
  49. +#define MHZ (1000 * 1000)
  50. +
  51. +struct clk_oxnas_pll {
  52. + struct clk_hw hw;
  53. + struct device_node *devnode;
  54. + struct reset_control *rstc;
  55. + struct regmap *syscon;
  56. +};
  57. +
  58. +#define to_clk_oxnas_pll(_hw) container_of(_hw, struct clk_oxnas_pll, hw)
  59. +
  60. +static unsigned long plla_clk_recalc_rate(struct clk_hw *hw,
  61. + unsigned long parent_rate)
  62. +{
  63. + struct clk_oxnas_pll *plla = to_clk_oxnas_pll(hw);
  64. + unsigned long fin = parent_rate;
  65. + unsigned long refdiv, outdiv;
  66. + unsigned int pll0, fbdiv;
  67. +
  68. + BUG_ON(regmap_read(plla->syscon, PLLA_CTRL0_REGOFFSET, &pll0));
  69. +
  70. + refdiv = (pll0 >> PLLA_REFDIV_SHIFT) & PLLA_REFDIV_MASK;
  71. + refdiv += 1;
  72. + outdiv = (pll0 >> PLLA_OUTDIV_SHIFT) & PLLA_OUTDIV_MASK;
  73. + outdiv += 1;
  74. +
  75. + BUG_ON(regmap_read(plla->syscon, PLLA_CTRL1_REGOFFSET, &fbdiv));
  76. + /* seems we will not be here when pll is bypassed, so ignore this
  77. + * case */
  78. +
  79. + return fin / MHZ * fbdiv / (refdiv * outdiv) / 32768 * MHZ;
  80. +}
  81. +
  82. +static const char *pll_clk_parents[] = {
  83. + "oscillator",
  84. +};
  85. +
  86. +static struct clk_ops plla_ops = {
  87. + .recalc_rate = plla_clk_recalc_rate,
  88. +};
  89. +
  90. +static struct clk_init_data clk_plla_init = {
  91. + .name = "plla",
  92. + .ops = &plla_ops,
  93. + .parent_names = pll_clk_parents,
  94. + .num_parents = ARRAY_SIZE(pll_clk_parents),
  95. +};
  96. +
  97. +static int pllb_clk_is_prepared(struct clk_hw *hw)
  98. +{
  99. + struct clk_oxnas_pll *pllb = to_clk_oxnas_pll(hw);
  100. +
  101. + return !!pllb->rstc;
  102. +}
  103. +
  104. +static int pllb_clk_prepare(struct clk_hw *hw)
  105. +{
  106. + struct clk_oxnas_pll *pllb = to_clk_oxnas_pll(hw);
  107. +
  108. + pllb->rstc = of_reset_control_get(pllb->devnode, NULL);
  109. +
  110. + return IS_ERR(pllb->rstc) ? PTR_ERR(pllb->rstc) : 0;
  111. +}
  112. +
  113. +static void pllb_clk_unprepare(struct clk_hw *hw)
  114. +{
  115. + struct clk_oxnas_pll *pllb = to_clk_oxnas_pll(hw);
  116. +
  117. + BUG_ON(IS_ERR(pllb->rstc));
  118. +
  119. + reset_control_put(pllb->rstc);
  120. + pllb->rstc = NULL;
  121. +}
  122. +
  123. +static int pllb_clk_enable(struct clk_hw *hw)
  124. +{
  125. + struct clk_oxnas_pll *pllb = to_clk_oxnas_pll(hw);
  126. +
  127. + BUG_ON(IS_ERR(pllb->rstc));
  128. +
  129. + /* put PLL into bypass */
  130. + regmap_update_bits(pllb->syscon, PLLB_CTRL0_REGOFFSET, BIT(PLLB_BYPASS), BIT(PLLB_BYPASS));
  131. + wmb();
  132. + udelay(10);
  133. + reset_control_assert(pllb->rstc);
  134. + udelay(10);
  135. + /* set PLL B control information */
  136. + regmap_write_bits(pllb->syscon, PLLB_CTRL0_REGOFFSET, 0xffff,
  137. + (1 << PLLB_ENSAT) | (1 << PLLB_OUTDIV) | (2 << PLLB_REFDIV));
  138. + reset_control_deassert(pllb->rstc);
  139. + udelay(100);
  140. + regmap_update_bits(pllb->syscon, PLLB_CTRL0_REGOFFSET, BIT(PLLB_BYPASS), 0);
  141. +
  142. + return 0;
  143. +}
  144. +
  145. +static void pllb_clk_disable(struct clk_hw *hw)
  146. +{
  147. + struct clk_oxnas_pll *pllb = to_clk_oxnas_pll(hw);
  148. +
  149. + BUG_ON(IS_ERR(pllb->rstc));
  150. +
  151. + /* put PLL into bypass */
  152. + regmap_update_bits(pllb->syscon, PLLB_CTRL0_REGOFFSET, BIT(PLLB_BYPASS), BIT(PLLB_BYPASS));
  153. +
  154. + wmb();
  155. + udelay(10);
  156. +
  157. + reset_control_assert(pllb->rstc);
  158. +}
  159. +
  160. +static struct clk_ops pllb_ops = {
  161. + .prepare = pllb_clk_prepare,
  162. + .unprepare = pllb_clk_unprepare,
  163. + .is_prepared = pllb_clk_is_prepared,
  164. + .enable = pllb_clk_enable,
  165. + .disable = pllb_clk_disable,
  166. +};
  167. +
  168. +static struct clk_init_data clk_pllb_init = {
  169. + .name = "pllb",
  170. + .ops = &pllb_ops,
  171. + .parent_names = pll_clk_parents,
  172. + .num_parents = ARRAY_SIZE(pll_clk_parents),
  173. +};
  174. +
  175. static inline struct clk_oxnas_gate *to_clk_oxnas_gate(struct clk_hw *hw)
  176. {
  177. return container_of(hw, struct clk_oxnas_gate, hw);
  178. @@ -251,3 +403,42 @@ static struct platform_driver oxnas_stdc
  179. },
  180. };
  181. builtin_platform_driver(oxnas_stdclk_driver);
  182. +
  183. +void __init oxnas_init_plla(struct device_node *np)
  184. +{
  185. + struct clk *clk;
  186. + struct clk_oxnas_pll *plla;
  187. +
  188. + plla = kmalloc(sizeof(*plla), GFP_KERNEL);
  189. + BUG_ON(!plla);
  190. +
  191. + plla->syscon = syscon_node_to_regmap(of_get_parent(np));
  192. + plla->hw.init = &clk_plla_init;
  193. + plla->devnode = np;
  194. + plla->rstc = NULL;
  195. + clk = clk_register(NULL, &plla->hw);
  196. + BUG_ON(IS_ERR(clk));
  197. + /* mark it as enabled */
  198. + clk_prepare_enable(clk);
  199. + of_clk_add_provider(np, of_clk_src_simple_get, clk);
  200. +}
  201. +CLK_OF_DECLARE(oxnas_plla, "plxtech,nas782x-plla", oxnas_init_plla);
  202. +
  203. +void __init oxnas_init_pllb(struct device_node *np)
  204. +{
  205. + struct clk *clk;
  206. + struct clk_oxnas_pll *pllb;
  207. +
  208. + pllb = kmalloc(sizeof(*pllb), GFP_KERNEL);
  209. + BUG_ON(!pllb);
  210. +
  211. + pllb->syscon = syscon_node_to_regmap(of_get_parent(np));
  212. + pllb->hw.init = &clk_pllb_init;
  213. + pllb->devnode = np;
  214. + pllb->rstc = NULL;
  215. +
  216. + clk = clk_register(NULL, &pllb->hw);
  217. + BUG_ON(IS_ERR(clk));
  218. + of_clk_add_provider(np, of_clk_src_simple_get, clk);
  219. +}
  220. +CLK_OF_DECLARE(oxnas_pllb, "plxtech,nas782x-pllb", oxnas_init_pllb);
  221. --- a/arch/arm/boot/dts/ox820.dtsi
  222. +++ b/arch/arm/boot/dts/ox820.dtsi
  223. @@ -61,12 +61,6 @@
  224. clocks = <&osc>;
  225. };
  226. - plla: plla {
  227. - compatible = "fixed-clock";
  228. - #clock-cells = <0>;
  229. - clock-frequency = <850000000>;
  230. - };
  231. -
  232. armclk: armclk {
  233. compatible = "fixed-factor-clock";
  234. #clock-cells = <0>;
  235. @@ -266,6 +260,19 @@
  236. compatible = "oxsemi,ox820-stdclk", "oxsemi,ox810se-stdclk";
  237. #clock-cells = <1>;
  238. };
  239. +
  240. + plla: plla {
  241. + compatible = "plxtech,nas782x-plla";
  242. + #clock-cells = <0>;
  243. + clocks = <&osc>;
  244. + };
  245. +
  246. + pllb: pllb {
  247. + compatible = "plxtech,nas782x-pllb";
  248. + #clock-cells = <0>;
  249. + clocks = <&osc>;
  250. + resets = <&reset RESET_PLLB>;
  251. + };
  252. };
  253. };
  254. @@ -287,6 +294,13 @@
  255. clocks = <&armclk>;
  256. };
  257. + watchdog@620 {
  258. + compatible = "mpcore_wdt";
  259. + reg = <0x620 0x20>;
  260. + interrupts = <GIC_PPI 14 (GIC_CPU_MASK_RAW(3)|IRQ_TYPE_LEVEL_HIGH)>;
  261. + clocks = <&armclk>;
  262. + };
  263. +
  264. gic: interrupt-controller@1000 {
  265. compatible = "arm,arm11mp-gic";
  266. interrupt-controller;