1 // SPDX-License-Identifier: GPL-2.0
3 * StarFive JH7110 aon Clock Generator Driver
5 * Copyright (C) 2022 Xingyu Wu <xingyu.wu@starfivetech.com>
9 #include <linux/clk-provider.h>
10 #include <linux/init.h>
11 #include <linux/platform_device.h>
13 #include <dt-bindings/clock/starfive-jh7110-clkgen.h>
14 #include "clk-starfive-jh7110.h"
17 #define JH7110_OSC (JH7110_CLK_END + 0)
18 /* aon external clocks */
19 #define JH7110_GMAC0_RMII_REFIN (JH7110_CLK_END + 12)
20 #define JH7110_GMAC0_RGMII_RXIN (JH7110_CLK_END + 13)
21 #define JH7110_CLK_RTC (JH7110_CLK_END + 14)
23 static const struct jh7110_clk_data jh7110_clk_aon_data[] __initconst = {
25 JH7110__DIV(JH7110_OSC_DIV4, "osc_div4", 4, JH7110_OSC),
26 JH7110__MUX(JH7110_AON_APB_FUNC, "aon_apb_func", PARENT_NUMS_2,
30 JH7110_GATE(JH7110_U0_GMAC5_CLK_AHB,
31 "u0_dw_gmac5_axi64_clk_ahb",
32 GATE_FLAG_NORMAL, JH7110_AON_AHB),
33 JH7110_GATE(JH7110_U0_GMAC5_CLK_AXI,
34 "u0_dw_gmac5_axi64_clk_axi",
35 GATE_FLAG_NORMAL, JH7110_AON_AHB),
36 JH7110__DIV(JH7110_GMAC0_RMII_RTX,
37 "gmac0_rmii_rtx", 30, JH7110_GMAC0_RMII_REFIN),
38 JH7110_GMUX(JH7110_U0_GMAC5_CLK_TX,
39 "u0_dw_gmac5_axi64_clk_tx",
40 GATE_FLAG_NORMAL, PARENT_NUMS_2,
42 JH7110_GMAC0_RMII_RTX),
43 JH7110__INV(JH7110_U0_GMAC5_CLK_TX_INV,
44 "u0_dw_gmac5_axi64_clk_tx_inv",
45 JH7110_U0_GMAC5_CLK_TX),
46 JH7110__MUX(JH7110_U0_GMAC5_CLK_RX,
47 "u0_dw_gmac5_axi64_clk_rx", PARENT_NUMS_2,
48 JH7110_GMAC0_RGMII_RXIN,
49 JH7110_GMAC0_RMII_RTX),
50 JH7110__INV(JH7110_U0_GMAC5_CLK_RX_INV,
51 "u0_dw_gmac5_axi64_clk_rx_inv",
52 JH7110_U0_GMAC5_CLK_RX),
54 JH7110_GATE(JH7110_OTPC_CLK_APB,
56 CLK_IGNORE_UNUSED, JH7110_AON_APB),
58 JH7110_GATE(JH7110_RTC_HMS_CLK_APB,
60 CLK_IGNORE_UNUSED, JH7110_AON_APB),
61 JH7110__DIV(JH7110_RTC_INTERNAL,
62 "rtc_internal", 1022, JH7110_OSC),
63 JH7110__MUX(JH7110_RTC_HMS_CLK_OSC32K,
64 "u0_rtc_hms_clk_osc32k", PARENT_NUMS_2,
67 JH7110_GATE(JH7110_RTC_HMS_CLK_CAL,
69 GATE_FLAG_NORMAL, JH7110_OSC),
72 int __init clk_starfive_jh7110_aon_init(struct platform_device *pdev,
73 struct jh7110_clk_priv *priv)
78 priv->aon_base = devm_platform_ioremap_resource_byname(pdev, "aon");
79 if (IS_ERR(priv->aon_base))
80 return PTR_ERR(priv->aon_base);
82 priv->pll[PLL_OF(JH7110_U0_GMAC5_CLK_PTP)] =
83 devm_clk_hw_register_fixed_factor(priv->dev,
84 "u0_dw_gmac5_axi64_clk_ptp", "gmac0_ptp", 0, 1, 1);
85 priv->pll[PLL_OF(JH7110_U0_GMAC5_CLK_RMII)] =
86 devm_clk_hw_register_fixed_factor(priv->dev,
87 "u0_dw_gmac5_axi64_clk_rmii",
88 "gmac0_rmii_refin", 0, 1, 1);
89 priv->pll[PLL_OF(JH7110_AON_SYSCON_PCLK)] =
90 devm_clk_hw_register_fixed_factor(priv->dev,
91 "u0_aon_syscon_pclk", "aon_apb", 0, 1, 1);
92 priv->pll[PLL_OF(JH7110_AON_IOMUX_PCLK)] =
93 devm_clk_hw_register_fixed_factor(priv->dev,
94 "u0_aon_iomux_pclk", "aon_apb", 0, 1, 1);
95 priv->pll[PLL_OF(JH7110_AON_CRG_PCLK)] =
96 devm_clk_hw_register_fixed_factor(priv->dev,
97 "u0_aon_crg_pclk", "aon_apb", 0, 1, 1);
98 priv->pll[PLL_OF(JH7110_PMU_CLK_APB)] =
99 devm_clk_hw_register_fixed_factor(priv->dev,
100 "u0_pmu_clk_apb", "aon_apb", 0, 1, 1);
101 priv->pll[PLL_OF(JH7110_PMU_CLK_WKUP)] =
102 devm_clk_hw_register_fixed_factor(priv->dev,
103 "u0_pmu_clk_wkup", "aon_apb", 0, 1, 1);
104 priv->pll[PLL_OF(JH7110_RTC_HMS_CLK_OSC32K_G)] =
105 devm_clk_hw_register_fixed_factor(priv->dev,
106 "u0_rtc_hms_clk_osc32k_g",
107 "u0_rtc_hms_clk_osc32k", 0, 1, 1);
108 priv->pll[PLL_OF(JH7110_32K_OUT)] =
109 devm_clk_hw_register_fixed_factor(priv->dev,
110 "32k_out", "clk_rtc", 0, 1, 1);
111 priv->pll[PLL_OF(JH7110_RESET0_CTRL_CLK_SRC)] =
112 devm_clk_hw_register_fixed_factor(priv->dev,
113 "u0_reset_ctrl_clk_src", "osc", 0, 1, 1);
114 priv->pll[PLL_OF(JH7110_PCLK_MUX_FUNC_PCLK)] =
115 devm_clk_hw_register_fixed_factor(priv->dev,
116 "u1_pclk_mux_func_pclk", "aon_apb_func", 0, 1, 1);
117 priv->pll[PLL_OF(JH7110_PCLK_MUX_BIST_PCLK)] =
118 devm_clk_hw_register_fixed_factor(priv->dev,
119 "u1_pclk_mux_bist_pclk", "bist_apb", 0, 1, 1);
121 for (idx = JH7110_CLK_STG_REG_END; idx < JH7110_CLK_REG_END; idx++) {
122 u32 max = jh7110_clk_aon_data[idx].max;
123 struct clk_parent_data parents[4] = {};
124 struct clk_init_data init = {
125 .name = jh7110_clk_aon_data[idx].name,
126 .ops = starfive_jh7110_clk_ops(max),
127 .parent_data = parents,
128 .num_parents = ((max & JH7110_CLK_MUX_MASK) \
129 >> JH7110_CLK_MUX_SHIFT) + 1,
130 .flags = jh7110_clk_aon_data[idx].flags,
132 struct jh7110_clk *clk = &priv->reg[idx];
135 for (i = 0; i < init.num_parents; i++) {
136 unsigned int pidx = jh7110_clk_aon_data[idx].parents[i];
138 if (pidx < JH7110_CLK_REG_END)
139 parents[i].hw = &priv->reg[pidx].hw;
140 else if ((pidx < JH7110_CLK_END) && \
141 (pidx > JH7110_RTC_HMS_CLK_CAL))
142 parents[i].hw = priv->pll[PLL_OF(pidx)];
143 else if (pidx == JH7110_OSC)
144 parents[i].fw_name = "osc";
145 else if (pidx == JH7110_GMAC0_RMII_REFIN)
146 parents[i].fw_name = "gmac0_rmii_refin";
147 else if (pidx == JH7110_GMAC0_RGMII_RXIN)
148 parents[i].fw_name = "gmac0_rgmii_rxin";
149 else if (pidx == JH7110_CLK_RTC)
150 parents[i].fw_name = "clk_rtc";
153 clk->hw.init = &init;
155 clk->max_div = max & JH7110_CLK_DIV_MASK;
156 clk->reg_flags = JH7110_CLK_AON_FLAG;
158 ret = devm_clk_hw_register(priv->dev, &clk->hw);
163 dev_dbg(&pdev->dev,"starfive JH7110 clk_aon init successfully.");