0011-clk-sifive-Sync-up-main-driver-with-upstream-Linux.patch 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. From 43295ddfa3caa2494d682962cb358e9c1177facf Mon Sep 17 00:00:00 2001
  2. From: Anup Patel <anup.patel@wdc.com>
  3. Date: Tue, 18 Jun 2019 14:20:23 +0530
  4. Subject: [PATCH 11/21] clk: sifive: Sync-up main driver with upstream Linux
  5. The DT bindings of SiFive clock driver in upstream Linux has
  6. changes. As-per latest DT bindings, the clock driver takes two
  7. parent clocks and compatible string has also changed.
  8. This patch sync-up SiFive clock driver implementation as-per
  9. upstream Linux so that we now use latest DT bindings.
  10. Signed-off-by: Anup Patel <anup.patel@wdc.com>
  11. Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
  12. Upstream-Status: Submitted
  13. ---
  14. drivers/clk/sifive/fu540-prci.c | 96 ++++++++++++++++++++-------------
  15. 1 file changed, 60 insertions(+), 36 deletions(-)
  16. diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c
  17. index ceb318e062..ce0769f2d1 100644
  18. --- a/drivers/clk/sifive/fu540-prci.c
  19. +++ b/drivers/clk/sifive/fu540-prci.c
  20. @@ -158,30 +158,32 @@
  21. * PRCI per-device instance data
  22. */
  23. struct __prci_data {
  24. - void *base;
  25. - struct clk parent;
  26. + void *va;
  27. + struct clk parent_hfclk;
  28. + struct clk parent_rtcclk;
  29. };
  30. /**
  31. * struct __prci_wrpll_data - WRPLL configuration and integration data
  32. * @c: WRPLL current configuration record
  33. - * @bypass: fn ptr to code to bypass the WRPLL (if applicable; else NULL)
  34. - * @no_bypass: fn ptr to code to not bypass the WRPLL (if applicable; else NULL)
  35. + * @enable_bypass: fn ptr to code to bypass the WRPLL (if applicable; else NULL)
  36. + * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL)
  37. * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI base address
  38. *
  39. - * @bypass and @no_bypass are used for WRPLL instances that contain a separate
  40. - * external glitchless clock mux downstream from the PLL. The WRPLL internal
  41. - * bypass mux is not glitchless.
  42. + * @enable_bypass and @disable_bypass are used for WRPLL instances
  43. + * that contain a separate external glitchless clock mux downstream
  44. + * from the PLL. The WRPLL internal bypass mux is not glitchless.
  45. */
  46. struct __prci_wrpll_data {
  47. struct wrpll_cfg c;
  48. - void (*bypass)(struct __prci_data *pd);
  49. - void (*no_bypass)(struct __prci_data *pd);
  50. + void (*enable_bypass)(struct __prci_data *pd);
  51. + void (*disable_bypass)(struct __prci_data *pd);
  52. u8 cfg0_offs;
  53. };
  54. struct __prci_clock;
  55. +/* struct __prci_clock_ops - clock operations */
  56. struct __prci_clock_ops {
  57. int (*set_rate)(struct __prci_clock *pc,
  58. unsigned long rate,
  59. @@ -197,8 +199,7 @@ struct __prci_clock_ops {
  60. * struct __prci_clock - describes a clock device managed by PRCI
  61. * @name: user-readable clock name string - should match the manual
  62. * @parent_name: parent name for this clock
  63. - * @ops: struct clk_ops for the Linux clock framework to use for control
  64. - * @hw: Linux-private clock data
  65. + * @ops: struct __prci_clock_ops for control
  66. * @pwd: WRPLL-specific data, associated with this clock (if not NULL)
  67. * @pd: PRCI-specific data associated with this clock (if not NULL)
  68. *
  69. @@ -232,12 +233,12 @@ struct __prci_clock {
  70. */
  71. static u32 __prci_readl(struct __prci_data *pd, u32 offs)
  72. {
  73. - return readl(pd->base + offs);
  74. + return readl(pd->va + offs);
  75. }
  76. static void __prci_writel(u32 v, u32 offs, struct __prci_data *pd)
  77. {
  78. - return writel(v, pd->base + offs);
  79. + writel(v, pd->va + offs);
  80. }
  81. /* WRPLL-related private functions */
  82. @@ -279,10 +280,8 @@ static void __prci_wrpll_unpack(struct wrpll_cfg *c, u32 r)
  83. c->flags &= (WRPLL_FLAGS_INT_FEEDBACK_MASK |
  84. WRPLL_FLAGS_EXT_FEEDBACK_MASK);
  85. - if (r & PRCI_COREPLLCFG0_FSE_MASK)
  86. - c->flags |= WRPLL_FLAGS_INT_FEEDBACK_MASK;
  87. - else
  88. - c->flags |= WRPLL_FLAGS_EXT_FEEDBACK_MASK;
  89. + /* external feedback mode not supported */
  90. + c->flags |= WRPLL_FLAGS_INT_FEEDBACK_MASK;
  91. }
  92. /**
  93. @@ -300,7 +299,7 @@ static void __prci_wrpll_unpack(struct wrpll_cfg *c, u32 r)
  94. * Returns: a value suitable for writing into a PRCI PLL configuration
  95. * register
  96. */
  97. -static u32 __prci_wrpll_pack(struct wrpll_cfg *c)
  98. +static u32 __prci_wrpll_pack(const struct wrpll_cfg *c)
  99. {
  100. u32 r = 0;
  101. @@ -308,8 +307,9 @@ static u32 __prci_wrpll_pack(struct wrpll_cfg *c)
  102. r |= c->divf << PRCI_COREPLLCFG0_DIVF_SHIFT;
  103. r |= c->divq << PRCI_COREPLLCFG0_DIVQ_SHIFT;
  104. r |= c->range << PRCI_COREPLLCFG0_RANGE_SHIFT;
  105. - if (c->flags & WRPLL_FLAGS_INT_FEEDBACK_MASK)
  106. - r |= PRCI_COREPLLCFG0_FSE_MASK;
  107. +
  108. + /* external feedback mode not supported */
  109. + r |= PRCI_COREPLLCFG0_FSE_MASK;
  110. return r;
  111. }
  112. @@ -352,7 +352,7 @@ static void __prci_wrpll_write_cfg(struct __prci_data *pd,
  113. {
  114. __prci_writel(__prci_wrpll_pack(c), pwd->cfg0_offs, pd);
  115. - memcpy(&pwd->c, c, sizeof(struct wrpll_cfg));
  116. + memcpy(&pwd->c, c, sizeof(*c));
  117. }
  118. /* Core clock mux control */
  119. @@ -431,17 +431,17 @@ static int sifive_fu540_prci_wrpll_set_rate(struct __prci_clock *pc,
  120. r = wrpll_configure_for_rate(&pwd->c, rate, parent_rate);
  121. if (r)
  122. - return -ERANGE;
  123. + return r;
  124. - if (pwd->bypass)
  125. - pwd->bypass(pd);
  126. + if (pwd->enable_bypass)
  127. + pwd->enable_bypass(pd);
  128. __prci_wrpll_write_cfg(pd, pwd, &pwd->c);
  129. udelay(wrpll_calc_max_lock_us(&pwd->c));
  130. - if (pwd->no_bypass)
  131. - pwd->no_bypass(pd);
  132. + if (pwd->disable_bypass)
  133. + pwd->disable_bypass(pd);
  134. return 0;
  135. }
  136. @@ -483,8 +483,8 @@ static const struct __prci_clock_ops sifive_fu540_prci_tlclksel_clk_ops = {
  137. static struct __prci_wrpll_data __prci_corepll_data = {
  138. .cfg0_offs = PRCI_COREPLLCFG0_OFFSET,
  139. - .bypass = __prci_coreclksel_use_hfclk,
  140. - .no_bypass = __prci_coreclksel_use_corepll,
  141. + .enable_bypass = __prci_coreclksel_use_hfclk,
  142. + .disable_bypass = __prci_coreclksel_use_corepll,
  143. };
  144. static struct __prci_wrpll_data __prci_ddrpll_data = {
  145. @@ -525,6 +525,27 @@ static struct __prci_clock __prci_init_clocks[] = {
  146. },
  147. };
  148. +static ulong sifive_fu540_prci_parent_rate(struct __prci_clock *pc)
  149. +{
  150. + ulong parent_rate;
  151. + struct __prci_clock *p;
  152. +
  153. + if (strcmp(pc->parent_name, "corepll") == 0) {
  154. + p = &__prci_init_clocks[PRCI_CLK_COREPLL];
  155. + if (!p->pd || !p->ops->recalc_rate)
  156. + return -ENXIO;
  157. +
  158. + return p->ops->recalc_rate(p, sifive_fu540_prci_parent_rate(p));
  159. + }
  160. +
  161. + if (strcmp(pc->parent_name, "rtcclk") == 0)
  162. + parent_rate = clk_get_rate(&pc->pd->parent_rtcclk);
  163. + else
  164. + parent_rate = clk_get_rate(&pc->pd->parent_hfclk);
  165. +
  166. + return parent_rate;
  167. +}
  168. +
  169. static ulong sifive_fu540_prci_get_rate(struct clk *clk)
  170. {
  171. struct __prci_clock *pc;
  172. @@ -536,7 +557,7 @@ static ulong sifive_fu540_prci_get_rate(struct clk *clk)
  173. if (!pc->pd || !pc->ops->recalc_rate)
  174. return -ENXIO;
  175. - return pc->ops->recalc_rate(pc, clk_get_rate(&pc->pd->parent));
  176. + return pc->ops->recalc_rate(pc, sifive_fu540_prci_parent_rate(pc));
  177. }
  178. static ulong sifive_fu540_prci_set_rate(struct clk *clk, ulong rate)
  179. @@ -551,7 +572,7 @@ static ulong sifive_fu540_prci_set_rate(struct clk *clk, ulong rate)
  180. if (!pc->pd || !pc->ops->set_rate)
  181. return -ENXIO;
  182. - err = pc->ops->set_rate(pc, rate, clk_get_rate(&pc->pd->parent));
  183. + err = pc->ops->set_rate(pc, rate, sifive_fu540_prci_parent_rate(pc));
  184. if (err)
  185. return err;
  186. @@ -564,11 +585,15 @@ static int sifive_fu540_prci_probe(struct udevice *dev)
  187. struct __prci_clock *pc;
  188. struct __prci_data *pd = dev_get_priv(dev);
  189. - pd->base = (void *)dev_read_addr(dev);
  190. - if (IS_ERR(pd->base))
  191. - return PTR_ERR(pd->base);
  192. + pd->va = (void *)dev_read_addr(dev);
  193. + if (IS_ERR(pd->va))
  194. + return PTR_ERR(pd->va);
  195. +
  196. + err = clk_get_by_index(dev, 0, &pd->parent_hfclk);
  197. + if (err)
  198. + return err;
  199. - err = clk_get_by_index(dev, 0, &pd->parent);
  200. + err = clk_get_by_index(dev, 1, &pd->parent_rtcclk);
  201. if (err)
  202. return err;
  203. @@ -588,8 +613,7 @@ static struct clk_ops sifive_fu540_prci_ops = {
  204. };
  205. static const struct udevice_id sifive_fu540_prci_ids[] = {
  206. - { .compatible = "sifive,fu540-c000-prci0" },
  207. - { .compatible = "sifive,aloeprci0" },
  208. + { .compatible = "sifive,fu540-c000-prci" },
  209. { }
  210. };
  211. --
  212. 2.22.0