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"
16 static const struct jh7110_clk_data jh7110_clk_aon_data[] __initconst = {
18 JH7110__DIV(JH7110_OSC_DIV4, "osc_div4", 4, JH7110_OSC),
19 JH7110__MUX(JH7110_AON_APB_FUNC, "aon_apb_func", PARENT_NUMS_2,
23 JH7110_GATE(JH7110_U0_GMAC5_CLK_AHB,
24 "u0_dw_gmac5_axi64_clk_ahb",
25 GATE_FLAG_NORMAL, JH7110_AON_AHB),
26 JH7110_GATE(JH7110_U0_GMAC5_CLK_AXI,
27 "u0_dw_gmac5_axi64_clk_axi",
28 GATE_FLAG_NORMAL, JH7110_AON_AHB),
29 JH7110__DIV(JH7110_GMAC0_RMII_RTX,
30 "gmac0_rmii_rtx", 30, JH7110_GMAC0_RMII_REFIN),
31 JH7110_GMUX(JH7110_U0_GMAC5_CLK_TX,
32 "u0_dw_gmac5_axi64_clk_tx",
33 GATE_FLAG_NORMAL, PARENT_NUMS_2,
35 JH7110_GMAC0_RMII_RTX),
36 JH7110__INV(JH7110_U0_GMAC5_CLK_TX_INV,
37 "u0_dw_gmac5_axi64_clk_tx_inv",
38 JH7110_U0_GMAC5_CLK_TX),
39 JH7110__MUX(JH7110_U0_GMAC5_CLK_RX,
40 "u0_dw_gmac5_axi64_clk_rx", PARENT_NUMS_2,
41 JH7110_GMAC0_RGMII_RXIN,
42 JH7110_GMAC0_RMII_RTX),
43 JH7110__INV(JH7110_U0_GMAC5_CLK_RX_INV,
44 "u0_dw_gmac5_axi64_clk_rx_inv",
45 JH7110_U0_GMAC5_CLK_RX),
47 JH7110_GATE(JH7110_OTPC_CLK_APB,
49 CLK_IGNORE_UNUSED, JH7110_AON_APB),
51 JH7110_GATE(JH7110_RTC_HMS_CLK_APB,
53 CLK_IGNORE_UNUSED, JH7110_AON_APB),
54 JH7110__DIV(JH7110_RTC_INTERNAL,
55 "rtc_internal", 1022, JH7110_OSC),
56 JH7110__MUX(JH7110_RTC_HMS_CLK_OSC32K,
57 "u0_rtc_hms_clk_osc32k", PARENT_NUMS_2,
60 JH7110_GATE(JH7110_RTC_HMS_CLK_CAL,
62 GATE_FLAG_NORMAL, JH7110_OSC),
65 int __init clk_starfive_jh7110_aon_init(struct platform_device *pdev,
66 struct jh7110_clk_priv *priv)
71 priv->aon_base = devm_platform_ioremap_resource_byname(pdev, "aon");
72 if (IS_ERR(priv->aon_base))
73 return PTR_ERR(priv->aon_base);
75 priv->pll[PLL_OF(JH7110_U0_GMAC5_CLK_PTP)] =
76 devm_clk_hw_register_fixed_factor(priv->dev,
77 "u0_dw_gmac5_axi64_clk_ptp", "gmac0_ptp", 0, 1, 1);
78 priv->pll[PLL_OF(JH7110_U0_GMAC5_CLK_RMII)] =
79 devm_clk_hw_register_fixed_factor(priv->dev,
80 "u0_dw_gmac5_axi64_clk_rmii",
81 "gmac0_rmii_refin", 0, 1, 1);
82 priv->pll[PLL_OF(JH7110_AON_SYSCON_PCLK)] =
83 devm_clk_hw_register_fixed_factor(priv->dev,
84 "u0_aon_syscon_pclk", "aon_apb", 0, 1, 1);
85 priv->pll[PLL_OF(JH7110_AON_IOMUX_PCLK)] =
86 devm_clk_hw_register_fixed_factor(priv->dev,
87 "u0_aon_iomux_pclk", "aon_apb", 0, 1, 1);
88 priv->pll[PLL_OF(JH7110_AON_CRG_PCLK)] =
89 devm_clk_hw_register_fixed_factor(priv->dev,
90 "u0_aon_crg_pclk", "aon_apb", 0, 1, 1);
91 priv->pll[PLL_OF(JH7110_PMU_CLK_APB)] =
92 devm_clk_hw_register_fixed_factor(priv->dev,
93 "u0_pmu_clk_apb", "aon_apb", 0, 1, 1);
94 priv->pll[PLL_OF(JH7110_PMU_CLK_WKUP)] =
95 devm_clk_hw_register_fixed_factor(priv->dev,
96 "u0_pmu_clk_wkup", "aon_apb", 0, 1, 1);
97 priv->pll[PLL_OF(JH7110_RTC_HMS_CLK_OSC32K_G)] =
98 devm_clk_hw_register_fixed_factor(priv->dev,
99 "u0_rtc_hms_clk_osc32k_g",
100 "u0_rtc_hms_clk_osc32k", 0, 1, 1);
101 priv->pll[PLL_OF(JH7110_32K_OUT)] =
102 devm_clk_hw_register_fixed_factor(priv->dev,
103 "32k_out", "clk_rtc", 0, 1, 1);
104 priv->pll[PLL_OF(JH7110_RESET0_CTRL_CLK_SRC)] =
105 devm_clk_hw_register_fixed_factor(priv->dev,
106 "u0_reset_ctrl_clk_src", "osc", 0, 1, 1);
107 priv->pll[PLL_OF(JH7110_PCLK_MUX_FUNC_PCLK)] =
108 devm_clk_hw_register_fixed_factor(priv->dev,
109 "u1_pclk_mux_func_pclk", "aon_apb_func", 0, 1, 1);
110 priv->pll[PLL_OF(JH7110_PCLK_MUX_BIST_PCLK)] =
111 devm_clk_hw_register_fixed_factor(priv->dev,
112 "u1_pclk_mux_bist_pclk", "bist_apb", 0, 1, 1);
114 for (idx = JH7110_CLK_STG_REG_END; idx < JH7110_CLK_REG_END; idx++) {
115 u32 max = jh7110_clk_aon_data[idx].max;
116 struct clk_parent_data parents[4] = {};
117 struct clk_init_data init = {
118 .name = jh7110_clk_aon_data[idx].name,
119 .ops = starfive_jh7110_clk_ops(max),
120 .parent_data = parents,
121 .num_parents = ((max & JH7110_CLK_MUX_MASK) \
122 >> JH7110_CLK_MUX_SHIFT) + 1,
123 .flags = jh7110_clk_aon_data[idx].flags,
125 struct jh7110_clk *clk = &priv->reg[idx];
128 for (i = 0; i < init.num_parents; i++) {
129 unsigned int pidx = jh7110_clk_aon_data[idx].parents[i];
131 if (pidx < JH7110_CLK_REG_END)
132 parents[i].hw = &priv->reg[pidx].hw;
133 else if ((pidx < JH7110_CLK_END) && \
134 (pidx > JH7110_RTC_HMS_CLK_CAL))
135 parents[i].hw = priv->pll[PLL_OF(pidx)];
136 else if (pidx == JH7110_GMAC0_RMII_REFIN)
137 parents[i].fw_name = "gmac0_rmii_refin";
138 else if (pidx == JH7110_GMAC0_RGMII_RXIN)
139 parents[i].fw_name = "gmac0_rgmii_rxin";
140 else if (pidx == JH7110_CLK_RTC)
141 parents[i].fw_name = "clk_rtc";
144 clk->hw.init = &init;
146 clk->max_div = max & JH7110_CLK_DIV_MASK;
147 clk->reg_flags = JH7110_CLK_AON_FLAG;
149 ret = devm_clk_hw_register(priv->dev, &clk->hw);
154 dev_dbg(&pdev->dev,"starfive JH7110 clk_aon init successfully.");