clk:starfive: Add isp clock tree driver
[platform/kernel/linux-starfive.git] / drivers / clk / starfive / clk-starfive-jh7110-isp.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * StarFive JH7110 Isp Clock Driver
4  *
5  * Copyright (C) 2022 Xingyu Wu <xingyu.wu@starfivetech.com>
6  */
7
8 #include <linux/bits.h>
9 #include <linux/clk.h>
10 #include <linux/clk-provider.h>
11 #include <linux/debugfs.h>
12 #include <linux/device.h>
13 #include <linux/init.h>
14 #include <linux/io.h>
15 #include <linux/kernel.h>
16 #include <linux/mod_devicetable.h>
17 #include <linux/module.h>
18 #include <linux/platform_device.h>
19 #include <linux/of_device.h>
20 #include <linux/reset.h>
21 #include <linux/reset-controller.h>
22 #include <dt-bindings/clock/starfive-jh7110-isp.h>
23 #include <soc/starfive/jh7110_pmu.h>
24
25 #include "clk-starfive-jh7110.h"
26
27 static const struct jh7110_clk_data jh7110_clk_isp_data[] __initconst = {
28         //syscon
29         JH7110__DIV(JH7110_DOM4_APB_FUNC, "dom4_apb_func",
30                         15, JH7110_ISP_TOP_CLK_ISP_AXI_CLKGEN),
31         //crg
32         JH7110__DIV(JH7110_MIPI_RX0_PXL, "mipi_rx0_pxl",
33                         8, JH7110_ISP_TOP_CLK_ISPCORE_2X_CLKGEN),
34         JH7110__INV(JH7110_DVP_INV, "dvp_inv", JH7110_ISP_TOP_CLK_DVP_CLKGEN),
35         //vin
36         JH7110__DIV(JH7110_U0_M31DPHY_CFGCLK_IN, "u0_m31dphy_cfgclk_in",
37                         16, JH7110_ISP_TOP_CLK_ISPCORE_2X_CLKGEN),
38         JH7110__DIV(JH7110_U0_M31DPHY_REFCLK_IN, "u0_m31dphy_refclk_in",
39                         16, JH7110_ISP_TOP_CLK_ISPCORE_2X_CLKGEN),
40         JH7110__DIV(JH7110_U0_M31DPHY_TXCLKESC_LAN0, "u0_m31dphy_txclkesc_lan0",
41                         60, JH7110_ISP_TOP_CLK_ISPCORE_2X_CLKGEN),
42         JH7110_GATE(JH7110_U0_VIN_PCLK, "u0_vin_pclk", 0, JH7110_DOM4_APB),
43         JH7110__DIV(JH7110_U0_VIN_SYS_CLK, "u0_vin_sys_clk",
44                         8, JH7110_ISP_TOP_CLK_ISPCORE_2X_CLKGEN),
45         JH7110_GATE(JH7110_U0_VIN_PIXEL_CLK_IF0, "u0_vin_pixel_clk_if0",
46                         0, JH7110_MIPI_RX0_PXL),
47         JH7110_GATE(JH7110_U0_VIN_PIXEL_CLK_IF1, "u0_vin_pixel_clk_if1",
48                         0, JH7110_MIPI_RX0_PXL),
49         JH7110_GATE(JH7110_U0_VIN_PIXEL_CLK_IF2, "u0_vin_pixel_clk_if2",
50                         0, JH7110_MIPI_RX0_PXL),
51         JH7110_GATE(JH7110_U0_VIN_PIXEL_CLK_IF3, "u0_vin_pixel_clk_if3",
52                         0, JH7110_MIPI_RX0_PXL),
53         JH7110__MUX(JH7110_U0_VIN_CLK_P_AXIWR, "u0_vin_clk_p_axiwr", 2,
54                         JH7110_MIPI_RX0_PXL,
55                         JH7110_DVP_INV),
56         //ispv2_top_wrapper
57         JH7110_GMUX(JH7110_U0_ISPV2_TOP_WRAPPER_CLK_C,
58                         "u0_ispv2_top_wrapper_clk_c", 0, 2,
59                         JH7110_MIPI_RX0_PXL,
60                         JH7110_DVP_INV),
61 };
62
63 static struct clk_hw *jh7110_isp_clk_get(struct of_phandle_args *clkspec,
64                                         void *data)
65 {
66         struct jh7110_clk_priv *priv = data;
67         unsigned int idx = clkspec->args[0];
68
69         if (idx < JH7110_CLK_ISP_REG_END)
70                 return &priv->reg[idx].hw;
71
72         if (idx < JH7110_CLK_ISP_END)
73                 return priv->pll[PLL_OFI(idx)];
74
75         return ERR_PTR(-EINVAL);
76 }
77
78 static int __init clk_starfive_jh7110_isp_probe(struct platform_device *pdev)
79 {
80         struct jh7110_clk_priv *priv;
81         unsigned int idx;
82         struct clk *clk_isp_2x;
83         struct clk *clk_isp_axi;
84         struct reset_control *rst_isp_n;
85         struct reset_control *rst_isp_axi;
86         int ret = 0;
87
88         priv = devm_kzalloc(&pdev->dev, struct_size(priv, reg,
89                                 JH7110_CLK_ISP_END), GFP_KERNEL);
90         if (!priv)
91                 return -ENOMEM;
92
93         spin_lock_init(&priv->rmw_lock);
94         priv->dev = &pdev->dev;
95         priv->isp_base = devm_platform_ioremap_resource(pdev, 0);
96         if (IS_ERR(priv->isp_base))
97                 return PTR_ERR(priv->isp_base);
98
99         starfive_power_domain_set(POWER_DOMAIN_ISP, 1);
100
101         clk_isp_2x = devm_clk_get(priv->dev,
102                         "u0_dom_isp_top_clk_dom_isp_top_clk_ispcore_2x");
103         if (!IS_ERR(clk_isp_2x)){
104                 ret = clk_prepare_enable(clk_isp_2x);
105                 if(ret){
106                         dev_err(priv->dev, "clk_isp_2x enable failed\n");
107                         return ret;
108                 }
109         }else{
110                 dev_err(priv->dev, "clk_isp_2x get failed\n");
111                 return PTR_ERR(clk_isp_2x);
112         }
113
114         clk_isp_axi = devm_clk_get(priv->dev,
115                         "u0_dom_isp_top_clk_dom_isp_top_clk_isp_axi");
116         if (!IS_ERR(clk_isp_axi)){
117                 ret = clk_prepare_enable(clk_isp_axi);
118                 if(ret){
119                         dev_err(priv->dev, "clk_isp_axi enable failed\n");
120                         return ret;
121                 }
122         }else{
123                 dev_err(priv->dev, "clk_isp_axi get failed\n");
124                 return PTR_ERR(clk_isp_axi);
125         }
126
127         rst_isp_n = devm_reset_control_get_exclusive(
128                         priv->dev, "rst_isp_top_n");
129         if (!IS_ERR(rst_isp_n)) {
130                 ret = reset_control_deassert(rst_isp_n);
131                 if(ret){
132                         dev_err(priv->dev, "rst_isp_n deassert failed.\n");
133                         return ret;
134                 }
135         }else{
136                 dev_err(priv->dev, "rst_isp_n get failed.\n");
137                 return PTR_ERR(rst_isp_n);
138         }
139
140         rst_isp_axi = devm_reset_control_get_exclusive(
141                         priv->dev, "rst_isp_top_axi");
142         if (!IS_ERR(rst_isp_axi)) {
143                 ret = reset_control_deassert(rst_isp_axi);
144                 if(ret){
145                         dev_err(priv->dev, "rst_isp_axi deassert failed.\n");
146                         return ret;
147                 }
148         }else{
149                 dev_err(priv->dev, "rst_isp_axi get failed.\n");
150                 return PTR_ERR(rst_isp_axi);
151         }
152
153         priv->pll[PLL_OFI(JH7110_U3_PCLK_MUX_FUNC_PCLK)] =
154                         devm_clk_hw_register_fixed_factor(
155                         priv->dev, "u3_pclk_mux_func_pclk",
156                         "dom4_apb_func", 0, 1, 1);
157         priv->pll[PLL_OFI(JH7110_U3_PCLK_MUX_BIST_PCLK)] =
158                         devm_clk_hw_register_fixed_factor(
159                         priv->dev, "u3_pclk_mux_bist_pclk",
160                         "u0_dom_isp_top_clk_dom_isp_top_clk_bist_apb", 0, 1, 1);
161         priv->pll[PLL_OFI(JH7110_DOM4_APB)] =
162                         devm_clk_hw_register_fixed_factor(priv->dev, "dom4_apb",
163                         "u3_pclk_mux_pclk", 0, 1, 1);
164         //vin
165         priv->pll[PLL_OFI(JH7110_U0_VIN_PCLK_FREE)] =
166                         devm_clk_hw_register_fixed_factor(
167                         priv->dev, "u0_vin_pclk_free",
168                         "dom4_apb", 0, 1, 1);
169         priv->pll[PLL_OFI(JH7110_U0_VIN_CLK_P_AXIRD)] =
170                         devm_clk_hw_register_fixed_factor(
171                         priv->dev, "u0_vin_clk_p_axird",
172                         "mipi_rx0_pxl", 0, 1, 1);
173         priv->pll[PLL_OFI(JH7110_U0_VIN_ACLK)] =
174                         devm_clk_hw_register_fixed_factor(
175                         priv->dev, "u0_vin_ACLK",
176                         "u0_dom_isp_top_clk_dom_isp_top_clk_isp_axi", 0, 1, 1);
177         priv->pll[PLL_OFI(JH7110_U0_ISPV2_TOP_WRAPPER_CLK_ISP_AXI_IN)] =
178                         devm_clk_hw_register_fixed_factor(priv->dev,
179                         "u0_ispv2_top_wrapper_clk_isp_axi_in",
180                         "u0_dom_isp_top_clk_dom_isp_top_clk_isp_axi", 0, 1, 1);
181         priv->pll[PLL_OFI(JH7110_U0_ISPV2_TOP_WRAPPER_CLK_ISP_X2)] =
182                         devm_clk_hw_register_fixed_factor(priv->dev,
183                         "u0_ispv2_top_wrapper_clk_isp_x2",
184                         "u0_dom_isp_top_clk_dom_isp_top_clk_ispcore_2x",
185                         0, 1, 1);
186         //wrapper
187         priv->pll[PLL_OFI(JH7110_U0_ISPV2_TOP_WRAPPER_CLK_ISP)] =
188                         devm_clk_hw_register_fixed_factor(priv->dev,
189                         "u0_ispv2_top_wrapper_clk_isp",
190                         "u0_dom_isp_top_clk_dom_isp_top_clk_isp_axi", 0, 1, 1);
191         priv->pll[PLL_OFI(JH7110_U0_ISPV2_TOP_WRAPPER_CLK_P)] =
192                         devm_clk_hw_register_fixed_factor(priv->dev,
193                         "u0_ispv2_top_wrapper_clk_p",
194                         "mipi_rx0_pxl", 0, 1, 1);
195         priv->pll[PLL_OFI(JH7110_U0_CRG_PCLK)] =
196                         devm_clk_hw_register_fixed_factor(priv->dev,
197                         "u0_crg_pclk", "dom4_apb", 0, 1, 1);
198         priv->pll[PLL_OFI(JH7110_U0_SYSCON_PCLK)] =
199                         devm_clk_hw_register_fixed_factor(priv->dev,
200                         "u0_syscon_pclk", "dom4_apb", 0, 1, 1);
201         priv->pll[PLL_OFI(JH7110_U0_M31DPHY_APBCFG_PCLK)] =
202                         devm_clk_hw_register_fixed_factor(priv->dev,
203                         "u0_m31dphy_apbcfg_pclk", "dom4_apb", 0, 1, 1);
204         priv->pll[PLL_OFI(JH7110_U0_AXI2APB_BRIDGE_CLK_DOM4_APB)] =
205                         devm_clk_hw_register_fixed_factor(priv->dev,
206                         "u0_axi2apb_bridge_clk_dom4_apb", "dom4_apb", 0, 1, 1);
207         priv->pll[PLL_OFI(JH7110_U0_AXI2APB_BRIDGE_ISP_AXI4SLV_CLK)] =
208                         devm_clk_hw_register_fixed_factor(priv->dev,
209                         "u0_axi2apb_bridge_isp_axi4slv_clk",
210                         "u0_dom_isp_top_clk_dom_isp_top_clk_isp_axi", 0, 1, 1);
211         priv->pll[PLL_OFI(JH7110_U3_PCLK_MUX_PCLK)] =
212                         devm_clk_hw_register_fixed_factor(priv->dev,
213                         "u3_pclk_mux_pclk", "u3_pclk_mux_func_pclk", 0, 1, 1);
214
215         for (idx = 0; idx < JH7110_CLK_ISP_REG_END; idx++) {
216                 u32 max = jh7110_clk_isp_data[idx].max;
217                 struct clk_parent_data parents[2] = {};
218                 struct clk_init_data init = {
219                         .name = jh7110_clk_isp_data[idx].name,
220                         .ops = starfive_jh7110_clk_ops(max),
221                         .parent_data = parents,
222                         .num_parents = ((max & JH7110_CLK_MUX_MASK) \
223                                         >> JH7110_CLK_MUX_SHIFT) + 1,
224                         .flags = jh7110_clk_isp_data[idx].flags,
225                 };
226                 struct jh7110_clk *clk = &priv->reg[idx];
227                 unsigned int i;
228
229                 for (i = 0; i < init.num_parents; i++) {
230                         unsigned int pidx = jh7110_clk_isp_data[idx].parents[i];
231
232                         if (pidx < JH7110_CLK_ISP_REG_END)
233                                 parents[i].hw = &priv->reg[pidx].hw;
234                         else if (pidx < JH7110_CLK_ISP_END)
235                                 parents[i].hw = priv->pll[PLL_OFI(pidx)];
236                         else if (pidx == JH7110_ISP_TOP_CLK_ISPCORE_2X_CLKGEN)
237                                 parents[i].fw_name = \
238                                 "u0_dom_isp_top_clk_dom_isp_top_clk_ispcore_2x";
239                         else if (pidx == JH7110_ISP_TOP_CLK_ISP_AXI_CLKGEN)
240                                 parents[i].fw_name = \
241                                 "u0_dom_isp_top_clk_dom_isp_top_clk_isp_axi";
242                         else if (pidx == JH7110_ISP_TOP_CLK_BIST_APB_CLKGEN)
243                                 parents[i].fw_name = \
244                                 "u0_dom_isp_top_clk_dom_isp_top_clk_bist_apb";
245                         else if (pidx == JH7110_ISP_TOP_CLK_DVP_CLKGEN)
246                                 parents[i].fw_name = \
247                                 "u0_dom_isp_top_clk_dom_isp_top_clk_dvp";
248                 }
249
250                 clk->hw.init = &init;
251                 clk->idx = idx;
252                 clk->max_div = max & JH7110_CLK_DIV_MASK;
253                 clk->reg_flags = JH7110_CLK_ISP_FLAG;
254
255                 ret = devm_clk_hw_register(priv->dev, &clk->hw);
256                 if (ret)
257                         return ret;
258         }
259
260         ret = devm_of_clk_add_hw_provider(priv->dev, jh7110_isp_clk_get, priv);
261         if (ret)
262                 return ret;
263
264         dev_info(&pdev->dev,"starfive JH7110 clk_isp init successfully.");
265         return 0;
266 }
267
268 static const struct of_device_id clk_starfive_jh7110_isp_match[] = {
269                 {.compatible = "starfive,jh7110-clk-isp" },
270                 { /* sentinel */ }
271 };
272
273 static struct platform_driver clk_starfive_jh7110_isp_driver = {
274         .probe = clk_starfive_jh7110_isp_probe,
275                 .driver = {
276                 .name = "clk-starfive-jh7110-isp",
277                 .of_match_table = clk_starfive_jh7110_isp_match,
278         },
279 };
280 module_platform_driver(clk_starfive_jh7110_isp_driver);
281
282 MODULE_AUTHOR("Xingyu Wu <xingyu.wu@starfivetech.com>");
283 MODULE_DESCRIPTION("StarFive JH7110 isp clock driver");
284 MODULE_LICENSE("GPL");