clk-starfive-jh7110-aon.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * StarFive JH7110 Always-On Clock Driver
  4. *
  5. * Copyright (C) 2022 Emil Renner Berthing <kernel@esmil.dk>
  6. * Copyright (C) 2022 StarFive Technology Co., Ltd.
  7. */
  8. #include <linux/clk-provider.h>
  9. #include <linux/io.h>
  10. #include <linux/platform_device.h>
  11. #include <dt-bindings/clock/starfive,jh7110-crg.h>
  12. #include "clk-starfive-jh7110.h"
  13. /* external clocks */
  14. #define JH7110_AONCLK_OSC (JH7110_AONCLK_END + 0)
  15. #define JH7110_AONCLK_GMAC0_RMII_REFIN (JH7110_AONCLK_END + 1)
  16. #define JH7110_AONCLK_GMAC0_RGMII_RXIN (JH7110_AONCLK_END + 2)
  17. #define JH7110_AONCLK_STG_AXIAHB (JH7110_AONCLK_END + 3)
  18. #define JH7110_AONCLK_APB_BUS (JH7110_AONCLK_END + 4)
  19. #define JH7110_AONCLK_GMAC0_GTXCLK (JH7110_AONCLK_END + 5)
  20. #define JH7110_AONCLK_RTC_OSC (JH7110_AONCLK_END + 6)
  21. static const struct jh71x0_clk_data jh7110_aonclk_data[] = {
  22. /* source */
  23. JH71X0__DIV(JH7110_AONCLK_OSC_DIV4, "osc_div4", 4, JH7110_AONCLK_OSC),
  24. JH71X0__MUX(JH7110_AONCLK_APB_FUNC, "apb_func", 0, 2,
  25. JH7110_AONCLK_OSC_DIV4,
  26. JH7110_AONCLK_OSC),
  27. /* gmac0 */
  28. JH71X0_GATE(JH7110_AONCLK_GMAC0_AHB, "gmac0_ahb", 0, JH7110_AONCLK_STG_AXIAHB),
  29. JH71X0_GATE(JH7110_AONCLK_GMAC0_AXI, "gmac0_axi", 0, JH7110_AONCLK_STG_AXIAHB),
  30. JH71X0__DIV(JH7110_AONCLK_GMAC0_RMII_RTX, "gmac0_rmii_rtx", 30,
  31. JH7110_AONCLK_GMAC0_RMII_REFIN),
  32. JH71X0_GMUX(JH7110_AONCLK_GMAC0_TX, "gmac0_tx",
  33. CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, 2,
  34. JH7110_AONCLK_GMAC0_GTXCLK,
  35. JH7110_AONCLK_GMAC0_RMII_RTX),
  36. JH71X0__INV(JH7110_AONCLK_GMAC0_TX_INV, "gmac0_tx_inv", JH7110_AONCLK_GMAC0_TX),
  37. JH71X0__MUX(JH7110_AONCLK_GMAC0_RX, "gmac0_rx", 0, 2,
  38. JH7110_AONCLK_GMAC0_RGMII_RXIN,
  39. JH7110_AONCLK_GMAC0_RMII_RTX),
  40. JH71X0__INV(JH7110_AONCLK_GMAC0_RX_INV, "gmac0_rx_inv", JH7110_AONCLK_GMAC0_RX),
  41. /* otpc */
  42. JH71X0_GATE(JH7110_AONCLK_OTPC_APB, "otpc_apb", 0, JH7110_AONCLK_APB_BUS),
  43. /* rtc */
  44. JH71X0_GATE(JH7110_AONCLK_RTC_APB, "rtc_apb", 0, JH7110_AONCLK_APB_BUS),
  45. JH71X0__DIV(JH7110_AONCLK_RTC_INTERNAL, "rtc_internal", 1022, JH7110_AONCLK_OSC),
  46. JH71X0__MUX(JH7110_AONCLK_RTC_32K, "rtc_32k", 0, 2,
  47. JH7110_AONCLK_RTC_OSC,
  48. JH7110_AONCLK_RTC_INTERNAL),
  49. JH71X0_GATE(JH7110_AONCLK_RTC_CAL, "rtc_cal", 0, JH7110_AONCLK_OSC),
  50. };
  51. static int jh7110_aoncrg_probe(struct platform_device *pdev)
  52. {
  53. struct jh71x0_clk_priv *priv;
  54. unsigned int idx;
  55. int ret;
  56. priv = devm_kzalloc(&pdev->dev,
  57. struct_size(priv, reg, JH7110_AONCLK_END),
  58. GFP_KERNEL);
  59. if (!priv)
  60. return -ENOMEM;
  61. spin_lock_init(&priv->rmw_lock);
  62. priv->num_reg = JH7110_AONCLK_END;
  63. priv->dev = &pdev->dev;
  64. priv->base = devm_platform_ioremap_resource(pdev, 0);
  65. if (IS_ERR(priv->base))
  66. return PTR_ERR(priv->base);
  67. for (idx = 0; idx < JH7110_AONCLK_END; idx++) {
  68. u32 max = jh7110_aonclk_data[idx].max;
  69. struct clk_parent_data parents[4] = {};
  70. struct clk_init_data init = {
  71. .name = jh7110_aonclk_data[idx].name,
  72. .ops = starfive_jh71x0_clk_ops(max),
  73. .parent_data = parents,
  74. .num_parents =
  75. ((max & JH71X0_CLK_MUX_MASK) >> JH71X0_CLK_MUX_SHIFT) + 1,
  76. .flags = jh7110_aonclk_data[idx].flags,
  77. };
  78. struct jh71x0_clk *clk = &priv->reg[idx];
  79. unsigned int i;
  80. for (i = 0; i < init.num_parents; i++) {
  81. unsigned int pidx = jh7110_aonclk_data[idx].parents[i];
  82. if (pidx < JH7110_AONCLK_END)
  83. parents[i].hw = &priv->reg[pidx].hw;
  84. else if (pidx == JH7110_AONCLK_OSC)
  85. parents[i].fw_name = "osc";
  86. else if (pidx == JH7110_AONCLK_GMAC0_RMII_REFIN)
  87. parents[i].fw_name = "gmac0_rmii_refin";
  88. else if (pidx == JH7110_AONCLK_GMAC0_RGMII_RXIN)
  89. parents[i].fw_name = "gmac0_rgmii_rxin";
  90. else if (pidx == JH7110_AONCLK_STG_AXIAHB)
  91. parents[i].fw_name = "stg_axiahb";
  92. else if (pidx == JH7110_AONCLK_APB_BUS)
  93. parents[i].fw_name = "apb_bus";
  94. else if (pidx == JH7110_AONCLK_GMAC0_GTXCLK)
  95. parents[i].fw_name = "gmac0_gtxclk";
  96. else if (pidx == JH7110_AONCLK_RTC_OSC)
  97. parents[i].fw_name = "rtc_osc";
  98. }
  99. clk->hw.init = &init;
  100. clk->idx = idx;
  101. clk->max_div = max & JH71X0_CLK_DIV_MASK;
  102. ret = devm_clk_hw_register(&pdev->dev, &clk->hw);
  103. if (ret)
  104. return ret;
  105. }
  106. ret = devm_of_clk_add_hw_provider(&pdev->dev, jh71x0_clk_get, priv);
  107. if (ret)
  108. return ret;
  109. return jh7110_reset_controller_register(priv, "rst-aon", 1);
  110. }
  111. static const struct of_device_id jh7110_aoncrg_match[] = {
  112. { .compatible = "starfive,jh7110-aoncrg" },
  113. { /* sentinel */ }
  114. };
  115. MODULE_DEVICE_TABLE(of, jh7110_aoncrg_match);
  116. static struct platform_driver jh7110_aoncrg_driver = {
  117. .probe = jh7110_aoncrg_probe,
  118. .driver = {
  119. .name = "clk-starfive-jh7110-aon",
  120. .of_match_table = jh7110_aoncrg_match,
  121. },
  122. };
  123. module_platform_driver(jh7110_aoncrg_driver);
  124. MODULE_AUTHOR("Emil Renner Berthing");
  125. MODULE_DESCRIPTION("StarFive JH7110 always-on clock driver");
  126. MODULE_LICENSE("GPL");