clk-lan966x.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Microchip LAN966x SoC Clock driver.
  4. *
  5. * Copyright (C) 2021 Microchip Technology, Inc. and its subsidiaries
  6. *
  7. * Author: Kavyasree Kotagiri <kavyasree.kotagiri@microchip.com>
  8. */
  9. #include <linux/bitfield.h>
  10. #include <linux/clk-provider.h>
  11. #include <linux/io.h>
  12. #include <linux/kernel.h>
  13. #include <linux/module.h>
  14. #include <linux/of.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/slab.h>
  17. #define GCK_ENA BIT(0)
  18. #define GCK_SRC_SEL GENMASK(9, 8)
  19. #define GCK_PRESCALER GENMASK(23, 16)
  20. #define DIV_MAX 255
  21. static const char * const lan966x_clk_names[] = {
  22. "qspi0", "qspi1", "qspi2", "sdmmc0",
  23. "pi", "mcan0", "mcan1", "flexcom0",
  24. "flexcom1", "flexcom2", "flexcom3",
  25. "flexcom4", "timer1", "usb_refclk",
  26. };
  27. static const char * const lan969x_clk_names[] = {
  28. "qspi0", "qspi2", "sdmmc0", "sdmmc1",
  29. "mcan0", "mcan1", "flexcom0",
  30. "flexcom1", "flexcom2", "flexcom3",
  31. "timer1", "usb_refclk",
  32. };
  33. struct lan966x_gck {
  34. struct clk_hw hw;
  35. void __iomem *reg;
  36. };
  37. #define to_lan966x_gck(hw) container_of(hw, struct lan966x_gck, hw)
  38. static const struct clk_parent_data lan966x_gck_pdata[] = {
  39. { .fw_name = "cpu", },
  40. { .fw_name = "ddr", },
  41. { .fw_name = "sys", },
  42. };
  43. static struct clk_init_data init = {
  44. .parent_data = lan966x_gck_pdata,
  45. .num_parents = ARRAY_SIZE(lan966x_gck_pdata),
  46. };
  47. struct clk_gate_soc_desc {
  48. const char *name;
  49. int bit_idx;
  50. };
  51. static const struct clk_gate_soc_desc lan966x_clk_gate_desc[] = {
  52. { "uhphs", 11 },
  53. { "udphs", 10 },
  54. { "mcramc", 9 },
  55. { "hmatrix", 8 },
  56. { }
  57. };
  58. static const struct clk_gate_soc_desc lan969x_clk_gate_desc[] = {
  59. { "usb_drd", 10 },
  60. { "mcramc", 9 },
  61. { "hmatrix", 8 },
  62. { }
  63. };
  64. struct lan966x_match_data {
  65. char *name;
  66. const char * const *clk_name;
  67. const struct clk_gate_soc_desc *clk_gate_desc;
  68. u8 num_generic_clks;
  69. u8 num_total_clks;
  70. };
  71. static struct lan966x_match_data lan966x_desc = {
  72. .name = "lan966x",
  73. .clk_name = lan966x_clk_names,
  74. .clk_gate_desc = lan966x_clk_gate_desc,
  75. .num_total_clks = 18,
  76. .num_generic_clks = 14,
  77. };
  78. static struct lan966x_match_data lan969x_desc = {
  79. .name = "lan969x",
  80. .clk_name = lan969x_clk_names,
  81. .clk_gate_desc = lan969x_clk_gate_desc,
  82. .num_total_clks = 15,
  83. .num_generic_clks = 12,
  84. };
  85. static DEFINE_SPINLOCK(clk_gate_lock);
  86. static void __iomem *base;
  87. static int lan966x_gck_enable(struct clk_hw *hw)
  88. {
  89. struct lan966x_gck *gck = to_lan966x_gck(hw);
  90. u32 val = readl(gck->reg);
  91. val |= GCK_ENA;
  92. writel(val, gck->reg);
  93. return 0;
  94. }
  95. static void lan966x_gck_disable(struct clk_hw *hw)
  96. {
  97. struct lan966x_gck *gck = to_lan966x_gck(hw);
  98. u32 val = readl(gck->reg);
  99. val &= ~GCK_ENA;
  100. writel(val, gck->reg);
  101. }
  102. static int lan966x_gck_set_rate(struct clk_hw *hw,
  103. unsigned long rate,
  104. unsigned long parent_rate)
  105. {
  106. struct lan966x_gck *gck = to_lan966x_gck(hw);
  107. u32 div, val = readl(gck->reg);
  108. if (rate == 0 || parent_rate == 0)
  109. return -EINVAL;
  110. /* Set Prescalar */
  111. div = parent_rate / rate;
  112. val &= ~GCK_PRESCALER;
  113. val |= FIELD_PREP(GCK_PRESCALER, (div - 1));
  114. writel(val, gck->reg);
  115. return 0;
  116. }
  117. static unsigned long lan966x_gck_recalc_rate(struct clk_hw *hw,
  118. unsigned long parent_rate)
  119. {
  120. struct lan966x_gck *gck = to_lan966x_gck(hw);
  121. u32 div, val = readl(gck->reg);
  122. div = FIELD_GET(GCK_PRESCALER, val);
  123. return parent_rate / (div + 1);
  124. }
  125. static int lan966x_gck_determine_rate(struct clk_hw *hw,
  126. struct clk_rate_request *req)
  127. {
  128. struct clk_hw *parent;
  129. int i;
  130. for (i = 0; i < clk_hw_get_num_parents(hw); ++i) {
  131. parent = clk_hw_get_parent_by_index(hw, i);
  132. if (!parent)
  133. continue;
  134. /* Allowed prescaler divider range is 0-255 */
  135. if (clk_hw_get_rate(parent) / req->rate <= DIV_MAX) {
  136. req->best_parent_hw = parent;
  137. req->best_parent_rate = clk_hw_get_rate(parent);
  138. return 0;
  139. }
  140. }
  141. return -EINVAL;
  142. }
  143. static u8 lan966x_gck_get_parent(struct clk_hw *hw)
  144. {
  145. struct lan966x_gck *gck = to_lan966x_gck(hw);
  146. u32 val = readl(gck->reg);
  147. return FIELD_GET(GCK_SRC_SEL, val);
  148. }
  149. static int lan966x_gck_set_parent(struct clk_hw *hw, u8 index)
  150. {
  151. struct lan966x_gck *gck = to_lan966x_gck(hw);
  152. u32 val = readl(gck->reg);
  153. val &= ~GCK_SRC_SEL;
  154. val |= FIELD_PREP(GCK_SRC_SEL, index);
  155. writel(val, gck->reg);
  156. return 0;
  157. }
  158. static const struct clk_ops lan966x_gck_ops = {
  159. .enable = lan966x_gck_enable,
  160. .disable = lan966x_gck_disable,
  161. .set_rate = lan966x_gck_set_rate,
  162. .recalc_rate = lan966x_gck_recalc_rate,
  163. .determine_rate = lan966x_gck_determine_rate,
  164. .set_parent = lan966x_gck_set_parent,
  165. .get_parent = lan966x_gck_get_parent,
  166. };
  167. static struct clk_hw *lan966x_gck_clk_register(struct device *dev, int i)
  168. {
  169. struct lan966x_gck *priv;
  170. int ret;
  171. priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  172. if (!priv)
  173. return ERR_PTR(-ENOMEM);
  174. priv->reg = base + (i * 4);
  175. priv->hw.init = &init;
  176. ret = devm_clk_hw_register(dev, &priv->hw);
  177. if (ret)
  178. return ERR_PTR(ret);
  179. return &priv->hw;
  180. };
  181. static int lan966x_gate_clk_register(struct device *dev,
  182. const struct lan966x_match_data *data,
  183. struct clk_hw_onecell_data *hw_data,
  184. void __iomem *gate_base)
  185. {
  186. for (int i = data->num_generic_clks; i < data->num_total_clks; ++i) {
  187. int idx = i - data->num_generic_clks;
  188. const struct clk_gate_soc_desc *desc;
  189. desc = &data->clk_gate_desc[idx];
  190. hw_data->hws[i] =
  191. devm_clk_hw_register_gate(dev, desc->name,
  192. data->name, 0, gate_base,
  193. desc->bit_idx,
  194. 0, &clk_gate_lock);
  195. if (IS_ERR(hw_data->hws[i]))
  196. return dev_err_probe(dev, PTR_ERR(hw_data->hws[i]),
  197. "failed to register %s clock\n",
  198. desc->name);
  199. }
  200. return 0;
  201. }
  202. static int lan966x_clk_probe(struct platform_device *pdev)
  203. {
  204. const struct lan966x_match_data *data;
  205. struct clk_hw_onecell_data *hw_data;
  206. struct device *dev = &pdev->dev;
  207. void __iomem *gate_base;
  208. struct resource *res;
  209. int i, ret;
  210. data = device_get_match_data(dev);
  211. if (!data)
  212. return -EINVAL;
  213. hw_data = devm_kzalloc(dev, struct_size(hw_data, hws, data->num_total_clks),
  214. GFP_KERNEL);
  215. if (!hw_data)
  216. return -ENOMEM;
  217. base = devm_platform_ioremap_resource(pdev, 0);
  218. if (IS_ERR(base))
  219. return PTR_ERR(base);
  220. init.ops = &lan966x_gck_ops;
  221. hw_data->num = data->num_generic_clks;
  222. for (i = 0; i < data->num_generic_clks; i++) {
  223. init.name = data->clk_name[i];
  224. hw_data->hws[i] = lan966x_gck_clk_register(dev, i);
  225. if (IS_ERR(hw_data->hws[i])) {
  226. dev_err(dev, "failed to register %s clock\n",
  227. init.name);
  228. return PTR_ERR(hw_data->hws[i]);
  229. }
  230. }
  231. res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  232. if (res) {
  233. gate_base = devm_ioremap_resource(&pdev->dev, res);
  234. if (IS_ERR(gate_base))
  235. return PTR_ERR(gate_base);
  236. hw_data->num = data->num_total_clks;
  237. ret = lan966x_gate_clk_register(dev, data, hw_data, gate_base);
  238. if (ret)
  239. return ret;
  240. }
  241. return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, hw_data);
  242. }
  243. static const struct of_device_id lan966x_clk_dt_ids[] = {
  244. { .compatible = "microchip,lan966x-gck", .data = &lan966x_desc },
  245. { .compatible = "microchip,lan9691-gck", .data = &lan969x_desc },
  246. { }
  247. };
  248. MODULE_DEVICE_TABLE(of, lan966x_clk_dt_ids);
  249. static struct platform_driver lan966x_clk_driver = {
  250. .probe = lan966x_clk_probe,
  251. .driver = {
  252. .name = "lan966x-clk",
  253. .of_match_table = lan966x_clk_dt_ids,
  254. },
  255. };
  256. module_platform_driver(lan966x_clk_driver);
  257. MODULE_AUTHOR("Kavyasree Kotagiri <kavyasree.kotagiri@microchip.com>");
  258. MODULE_DESCRIPTION("LAN966X clock driver");
  259. MODULE_LICENSE("GPL v2");