dt-bindings:clock:Delete external clock definitions
[platform/kernel/linux-starfive.git] / drivers / clk / starfive / clk-starfive-jh7110-vout.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * StarFive JH7110 vout 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/pm_runtime.h>
21 #include <linux/reset.h>
22
23 #include <dt-bindings/clock/starfive-jh7110-vout.h>
24 #include "clk-starfive-jh7110.h"
25
26 /* external clocks */
27 #define JH7110_HDMITX0_PIXELCLK                 (JH7110_CLK_VOUT_END + 0)
28 #define JH7110_MIPITX_DPHY_RXESC                (JH7110_CLK_VOUT_END + 1)
29 #define JH7110_MIPITX_DPHY_TXBYTEHS             (JH7110_CLK_VOUT_END + 2)
30
31 static const struct jh7110_clk_data jh7110_clk_vout_data[] __initconst = {
32         //divider
33         JH7110__DIV(JH7110_APB, "apb", 8, JH7110_DISP_AHB),
34         JH7110__DIV(JH7110_DC8200_PIX0, "dc8200_pix0", 63, JH7110_DISP_ROOT),
35         JH7110__DIV(JH7110_DSI_SYS, "dsi_sys", 31, JH7110_DISP_ROOT),
36         JH7110__DIV(JH7110_TX_ESC, "tx_esc", 31, JH7110_DISP_AHB),
37         //dc8200
38         JH7110_GATE(JH7110_U0_DC8200_CLK_AXI, "u0_dc8200_clk_axi",
39                         GATE_FLAG_NORMAL, JH7110_DISP_AXI),
40         JH7110_GATE(JH7110_U0_DC8200_CLK_CORE, "u0_dc8200_clk_core",
41                         GATE_FLAG_NORMAL, JH7110_DISP_AXI),
42         JH7110_GATE(JH7110_U0_DC8200_CLK_AHB, "u0_dc8200_clk_ahb",
43                         GATE_FLAG_NORMAL, JH7110_DISP_AHB),
44         JH7110_GMUX(JH7110_U0_DC8200_CLK_PIX0, "u0_dc8200_clk_pix0",
45                         GATE_FLAG_NORMAL, PARENT_NUMS_2,
46                         JH7110_DC8200_PIX0,
47                         JH7110_HDMITX0_PIXELCLK),
48         JH7110_GMUX(JH7110_U0_DC8200_CLK_PIX1, "u0_dc8200_clk_pix1",
49                         GATE_FLAG_NORMAL, PARENT_NUMS_2,
50                         JH7110_DC8200_PIX0,
51                         JH7110_HDMITX0_PIXELCLK),
52         
53         JH7110_GMUX(JH7110_DOM_VOUT_TOP_LCD_CLK, "dom_vout_top_lcd_clk",
54                         GATE_FLAG_NORMAL, PARENT_NUMS_2,
55                         JH7110_U0_DC8200_CLK_PIX0_OUT,
56                         JH7110_U0_DC8200_CLK_PIX1_OUT),
57         //dsiTx
58         JH7110_GATE(JH7110_U0_CDNS_DSITX_CLK_APB, "u0_cdns_dsiTx_clk_apb",
59                         GATE_FLAG_NORMAL, JH7110_DSI_SYS),
60         JH7110_GATE(JH7110_U0_CDNS_DSITX_CLK_SYS, "u0_cdns_dsiTx_clk_sys",
61                         GATE_FLAG_NORMAL, JH7110_DSI_SYS),
62         JH7110_GMUX(JH7110_U0_CDNS_DSITX_CLK_DPI, "u0_cdns_dsiTx_clk_api",
63                         GATE_FLAG_NORMAL, PARENT_NUMS_2,
64                         JH7110_DC8200_PIX0,
65                         JH7110_HDMITX0_PIXELCLK),
66         JH7110_GATE(JH7110_U0_CDNS_DSITX_CLK_TXESC, "u0_cdns_dsiTx_clk_txesc",
67                         GATE_FLAG_NORMAL, JH7110_TX_ESC),
68         //mipitx DPHY
69         JH7110_GATE(JH7110_U0_MIPITX_DPHY_CLK_TXESC, "u0_mipitx_dphy_clk_txesc",
70                         GATE_FLAG_NORMAL, JH7110_TX_ESC),
71         //hdmi
72         JH7110_GATE(JH7110_U0_HDMI_TX_CLK_MCLK, "u0_hdmi_tx_clk_mclk",
73                         GATE_FLAG_NORMAL, JH7110_HDMITX0_MCLK),
74         JH7110_GATE(JH7110_U0_HDMI_TX_CLK_BCLK, "u0_hdmi_tx_clk_bclk",
75                         GATE_FLAG_NORMAL, JH7110_HDMITX0_SCK),
76         JH7110_GATE(JH7110_U0_HDMI_TX_CLK_SYS, "u0_hdmi_tx_clk_sys",
77                         GATE_FLAG_NORMAL, JH7110_DISP_APB),
78 };
79
80 static struct clk_hw *jh7110_vout_clk_get(struct of_phandle_args *clkspec,
81                                         void *data)
82 {
83         struct jh7110_clk_priv *priv = data;
84         unsigned int idx = clkspec->args[0];
85
86         if (idx < JH7110_CLK_VOUT_REG_END)
87                 return &priv->reg[idx].hw;
88
89         if (idx < JH7110_CLK_VOUT_END)
90                 return priv->pll[PLL_OFV(idx)];
91
92         return ERR_PTR(-EINVAL);
93 }
94
95 static int __init clk_starfive_jh7110_vout_probe(struct platform_device *pdev)
96 {
97         struct jh7110_clk_priv *priv;
98         unsigned int idx;
99         struct clk *clk_vout_src;
100         struct clk *clk_vout_top_ahb;
101         struct reset_control *rst_vout_src;
102         int ret = 0;
103
104         priv = devm_kzalloc(&pdev->dev, struct_size(priv,
105                                 reg, JH7110_DISP_ROOT), GFP_KERNEL);
106         if (!priv)
107                 return -ENOMEM;
108
109         spin_lock_init(&priv->rmw_lock);
110         priv->dev = &pdev->dev;
111         priv->vout_base = devm_platform_ioremap_resource(pdev, 0);
112         if (IS_ERR(priv->vout_base))
113                 return PTR_ERR(priv->vout_base);
114
115         pm_runtime_enable(&pdev->dev);
116         ret = pm_runtime_get_sync(&pdev->dev);
117         if (ret < 0) {
118                 dev_err(&pdev->dev, "failed to get pm runtime: %d\n", ret);
119                 return ret;
120         }
121
122         clk_vout_src = devm_clk_get(priv->dev, "vout_src");
123         if (!IS_ERR(clk_vout_src)){
124                 ret = clk_prepare_enable(clk_vout_src);
125                 if(ret){
126                         dev_err(priv->dev, "clk_vout_src enable failed\n");
127                         goto clk_src_enable_failed;
128                 }
129         }else{
130                 dev_err(priv->dev, "clk_vout_src get failed\n");
131                 return PTR_ERR(clk_vout_src);
132         }
133
134         rst_vout_src = devm_reset_control_get_exclusive(
135                         priv->dev, "vout_src");
136         if (!IS_ERR(rst_vout_src)) {
137                 ret = reset_control_deassert(rst_vout_src);
138                 if(ret){
139                         dev_err(priv->dev, "rst_vout_src deassert failed.\n");
140                         goto rst_src_deassert_failed;
141                 }
142         }else{
143                 dev_err(priv->dev, "rst_vout_src get failed.\n");
144                 ret = PTR_ERR(rst_vout_src);
145                 goto rst_src_get_failed;
146         }
147
148         clk_vout_top_ahb = devm_clk_get(priv->dev, "vout_top_ahb");
149         if (!IS_ERR(clk_vout_top_ahb)){
150                 ret = clk_prepare_enable(clk_vout_top_ahb);
151                 if(ret){
152                         dev_err(priv->dev, "clk_vout_top_ahb enable failed\n");
153                         goto clk_ahb_enable_failed;
154                 }
155         }else{
156                 dev_err(priv->dev, "clk_vout_top_ahb get failed\n");
157                 ret = PTR_ERR(clk_vout_top_ahb);
158                 goto clk_ahb_get_failed;
159         }
160
161         //source
162         priv->pll[PLL_OFV(JH7110_DISP_ROOT)] =
163                         devm_clk_hw_register_fixed_factor(
164                         priv->dev, "disp_root",
165                         "u0_dom_vout_top_clk_dom_vout_top_clk_vout_src",
166                         0, 1, 1);
167         priv->pll[PLL_OFV(JH7110_DISP_AXI)] =
168                         devm_clk_hw_register_fixed_factor(
169                         priv->dev, "disp_axi",
170                         "u0_dom_vout_top_clk_dom_vout_top_clk_vout_axi",
171                         0, 1, 1);
172         priv->pll[PLL_OFV(JH7110_DISP_AHB)] =
173                         devm_clk_hw_register_fixed_factor(
174                         priv->dev, "disp_ahb",
175                         "u0_dom_vout_top_clk_dom_vout_top_clk_vout_ahb",
176                         0, 1, 1);
177         priv->pll[PLL_OFV(JH7110_HDMI_PHY_REF)] =
178                         devm_clk_hw_register_fixed_factor(
179                         priv->dev, "hdmi_phy_ref",
180                         "u0_dom_vout_top_clk_dom_vout_top_clk_hdmiphy_ref",
181                         0, 1, 1);
182         priv->pll[PLL_OFV(JH7110_HDMITX0_MCLK)] =
183                         devm_clk_hw_register_fixed_factor(
184                         priv->dev, "hdmitx0_mclk",
185                         "u0_dom_vout_top_clk_dom_vout_top_clk_hdmitx0_mclk",
186                         0, 1, 1);
187         priv->pll[PLL_OFV(JH7110_HDMITX0_SCK)] =
188                         devm_clk_hw_register_fixed_factor(
189                         priv->dev, "hdmitx0_sck",
190                         "u0_dom_vout_top_clk_dom_vout_top_clk_hdmitx0_bclk",
191                         0, 1, 1);
192         
193         priv->pll[PLL_OFV(JH7110_MIPI_DPHY_REF)] =
194                         devm_clk_hw_register_fixed_factor(
195                         priv->dev, "mipi_dphy_ref",
196                         "u0_dom_vout_top_clk_dom_vout_top_clk_mipiphy_ref",
197                         0, 1, 1);
198         //divider
199         priv->pll[PLL_OFV(JH7110_U0_PCLK_MUX_BIST_PCLK)] =
200                         devm_clk_hw_register_fixed_factor(
201                         priv->dev, "u0_pclk_mux_bist_pclk",
202                         "u0_dom_vout_top_clk_dom_vout_top_bist_pclk",
203                         0, 1, 1);
204         priv->pll[PLL_OFV(JH7110_DISP_APB)] =
205                         clk_hw_register_fixed_rate(priv->dev,
206                         "disp_apb", NULL, 0, 51200000);
207         priv->pll[PLL_OFV(JH7110_U0_PCLK_MUX_FUNC_PCLK)] =
208                         devm_clk_hw_register_fixed_factor(priv->dev,
209                         "u0_pclk_mux_func_pclk", "apb", 0, 1, 1);
210         //bus
211         priv->pll[PLL_OFV(JH7110_U0_DOM_VOUT_CRG_PCLK)] =
212                         devm_clk_hw_register_fixed_factor(priv->dev,
213                         "u0_dom_vout_crg_pclk", "disp_apb", 0, 1, 1);
214         priv->pll[PLL_OFV(JH7110_U0_DOM_VOUT_SYSCON_PCLK)] =
215                         devm_clk_hw_register_fixed_factor(priv->dev,
216                         "u0_dom_vout_syscon_pclk", "disp_apb", 0, 1, 1);
217         priv->pll[PLL_OFV(JH7110_U0_SAIF_AMBA_DOM_VOUT_AHB_DEC_CLK_AHB)] =
218                         devm_clk_hw_register_fixed_factor(priv->dev,
219                         "u0_saif_amba_dom_vout_ahb_dec_clk_ahb",
220                         "disp_ahb", 0, 1, 1);
221         priv->pll[PLL_OFV(JH7110_U0_AHB2APB_CLK_AHB)] =
222                         devm_clk_hw_register_fixed_factor(priv->dev,
223                         "u0_ahb2apb_clk_ahb", "disp_ahb", 0, 1, 1);
224         priv->pll[PLL_OFV(JH7110_U0_P2P_ASYNC_CLK_APBS)] =
225                         devm_clk_hw_register_fixed_factor(priv->dev,
226                         "u0_p2p_async_clk_apbs", "disp_apb", 0, 1, 1);
227         //dsiTx
228         priv->pll[PLL_OFV(JH7110_U0_CDNS_DSITX_CLK_RXESC)] =
229                         devm_clk_hw_register_fixed_factor(priv->dev,
230                         "u0_cdns_dsiTx_clk_rxesc",
231                         "mipitx_dphy_rxesc", 0, 1, 1);
232         priv->pll[PLL_OFV(JH7110_U0_CDNS_DSITX_CLK_TXBYTEHS)] =
233                         devm_clk_hw_register_fixed_factor(priv->dev,
234                         "u0_cdns_dsiTx_clk_txbytehs",
235                         "mipitx_dphy_txbytehs", 0, 1, 1);
236         //mipitx DPHY
237         priv->pll[PLL_OFV(JH7110_U0_MIPITX_DPHY_CLK_SYS)] =
238                         devm_clk_hw_register_fixed_factor(priv->dev,
239                         "u0_mipitx_dphy_clk_sys", "disp_apb", 0, 1, 1);
240         priv->pll[PLL_OFV(JH7110_U0_MIPITX_DPHY_CLK_DPHY_REF)] =
241                         devm_clk_hw_register_fixed_factor(priv->dev,
242                         "u0_mipitx_dphy_clk_dphy_ref",
243                         "mipi_dphy_ref", 0, 1, 1);
244         priv->pll[PLL_OFV(JH7110_U0_MIPITX_APBIF_PCLK)] =
245                         devm_clk_hw_register_fixed_factor(priv->dev,
246                         "u0_mipitx_apbif_pclk", "disp_apb", 0, 1, 1);
247         //hdmi
248         priv->pll[PLL_OFV(JH7110_HDMI_TX_CLK_REF)] =
249                         devm_clk_hw_register_fixed_factor(priv->dev,
250                         "u0_hdmi_tx_clk_ref", "hdmi_phy_ref", 0, 1, 1);
251         
252         priv->pll[PLL_OFV(JH7110_U0_DC8200_CLK_PIX0_OUT)] =
253                         devm_clk_hw_register_fixed_factor(priv->dev,
254                         "u0_dc8200_clk_pix0_out",
255                         "u0_dc8200_clk_pix0", 0, 1, 1);
256         priv->pll[PLL_OFV(JH7110_U0_DC8200_CLK_PIX1_OUT)] =
257                         devm_clk_hw_register_fixed_factor(priv->dev,
258                         "u0_dc8200_clk_pix1_out",
259                         "u0_dc8200_clk_pix1", 0, 1, 1);
260
261         for (idx = 0; idx < JH7110_DISP_ROOT; idx++) {
262                 u32 max = jh7110_clk_vout_data[idx].max;
263                 struct clk_parent_data parents[2] = {};
264                 struct clk_init_data init = {
265                         .name = jh7110_clk_vout_data[idx].name,
266                         .ops = starfive_jh7110_clk_ops(max),
267                         .parent_data = parents,
268                         .num_parents = ((max & JH7110_CLK_MUX_MASK) \
269                                         >> JH7110_CLK_MUX_SHIFT) + 1,
270                         .flags = jh7110_clk_vout_data[idx].flags,
271                 };
272                 struct jh7110_clk *clk = &priv->reg[idx];
273                 unsigned int i;
274
275                 for (i = 0; i < init.num_parents; i++) {
276                         unsigned int pidx = jh7110_clk_vout_data[idx].parents[i];
277
278                         if (pidx < JH7110_DISP_ROOT)
279                                 parents[i].hw = &priv->reg[pidx].hw;
280                         else if (pidx < JH7110_CLK_VOUT_END)
281                                 parents[i].hw = \
282                                         priv->pll[PLL_OFV(pidx)];
283                         else if (pidx == JH7110_HDMITX0_PIXELCLK)
284                                 parents[i].fw_name = "hdmitx0_pixelclk";
285                         else if (pidx == JH7110_MIPITX_DPHY_RXESC)
286                                 parents[i].fw_name = "mipitx_dphy_rxesc";
287                         else if (pidx == JH7110_MIPITX_DPHY_TXBYTEHS)
288                                 parents[i].fw_name = "mipitx_dphy_txbytehs";
289                         else if (pidx == JH7110_U0_DC8200_CLK_PIX0_OUT)
290                                 parents[i].fw_name = "u0_dc8200_clk_pix0_out";
291                         else if (pidx == JH7110_U0_DC8200_CLK_PIX1_OUT)
292                                 parents[i].fw_name = "u0_dc8200_clk_pix1_out";
293                 }
294
295                 clk->hw.init = &init;
296                 clk->idx = idx;
297                 clk->max_div = max & JH7110_CLK_DIV_MASK;
298                 clk->reg_flags = JH7110_CLK_VOUT_FLAG;
299
300                 ret = devm_clk_hw_register(priv->dev, &clk->hw);
301                 if (ret)
302                         return ret;
303         }
304
305         ret = devm_of_clk_add_hw_provider(priv->dev, jh7110_vout_clk_get, priv);
306         if (ret)
307                 return ret;
308
309         devm_clk_put(priv->dev, clk_vout_src);
310         reset_control_put(rst_vout_src);
311         devm_clk_put(priv->dev, clk_vout_top_ahb);
312
313         dev_info(&pdev->dev,"starfive JH7110 clk_vout init successfully.");
314         return 0;
315
316 clk_ahb_enable_failed:
317         devm_clk_put(priv->dev, clk_vout_top_ahb);
318 clk_ahb_get_failed:
319         reset_control_assert(rst_vout_src);
320 rst_src_deassert_failed:
321         reset_control_put(rst_vout_src);
322 rst_src_get_failed:
323         clk_disable_unprepare(clk_vout_src);
324 clk_src_enable_failed:
325         devm_clk_put(priv->dev, clk_vout_src);
326
327         return ret;
328
329 }
330
331 static const struct of_device_id clk_starfive_jh7110_vout_match[] = {   
332                 {.compatible = "starfive,jh7110-clk-vout" },
333                 { /* sentinel */ }
334 };
335
336 static struct platform_driver clk_starfive_jh7110_vout_driver = {
337         .probe = clk_starfive_jh7110_vout_probe,
338                 .driver = {
339                 .name = "clk-starfive-jh7110-vout",
340                 .of_match_table = clk_starfive_jh7110_vout_match,
341         },
342 };
343 module_platform_driver(clk_starfive_jh7110_vout_driver);
344
345 MODULE_AUTHOR("Xingyu Wu <xingyu.wu@starfivetech.com>");
346 MODULE_DESCRIPTION("StarFive JH7110 vout clock driver");
347 MODULE_LICENSE("GPL");