1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Hi3798CV200 Clock and Reset Generator Driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <dt-bindings/clock/histb-clock.h>
9*4882a593Smuzhiyun #include <linux/clk-provider.h>
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/of_device.h>
12*4882a593Smuzhiyun #include <linux/platform_device.h>
13*4882a593Smuzhiyun #include "clk.h"
14*4882a593Smuzhiyun #include "crg.h"
15*4882a593Smuzhiyun #include "reset.h"
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun /* hi3798CV200 core CRG */
18*4882a593Smuzhiyun #define HI3798CV200_INNER_CLK_OFFSET 64
19*4882a593Smuzhiyun #define HI3798CV200_FIXED_24M 65
20*4882a593Smuzhiyun #define HI3798CV200_FIXED_25M 66
21*4882a593Smuzhiyun #define HI3798CV200_FIXED_50M 67
22*4882a593Smuzhiyun #define HI3798CV200_FIXED_75M 68
23*4882a593Smuzhiyun #define HI3798CV200_FIXED_100M 69
24*4882a593Smuzhiyun #define HI3798CV200_FIXED_150M 70
25*4882a593Smuzhiyun #define HI3798CV200_FIXED_200M 71
26*4882a593Smuzhiyun #define HI3798CV200_FIXED_250M 72
27*4882a593Smuzhiyun #define HI3798CV200_FIXED_300M 73
28*4882a593Smuzhiyun #define HI3798CV200_FIXED_400M 74
29*4882a593Smuzhiyun #define HI3798CV200_MMC_MUX 75
30*4882a593Smuzhiyun #define HI3798CV200_ETH_PUB_CLK 76
31*4882a593Smuzhiyun #define HI3798CV200_ETH_BUS_CLK 77
32*4882a593Smuzhiyun #define HI3798CV200_ETH_BUS0_CLK 78
33*4882a593Smuzhiyun #define HI3798CV200_ETH_BUS1_CLK 79
34*4882a593Smuzhiyun #define HI3798CV200_COMBPHY1_MUX 80
35*4882a593Smuzhiyun #define HI3798CV200_FIXED_12M 81
36*4882a593Smuzhiyun #define HI3798CV200_FIXED_48M 82
37*4882a593Smuzhiyun #define HI3798CV200_FIXED_60M 83
38*4882a593Smuzhiyun #define HI3798CV200_FIXED_166P5M 84
39*4882a593Smuzhiyun #define HI3798CV200_SDIO0_MUX 85
40*4882a593Smuzhiyun #define HI3798CV200_COMBPHY0_MUX 86
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun #define HI3798CV200_CRG_NR_CLKS 128
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun static const struct hisi_fixed_rate_clock hi3798cv200_fixed_rate_clks[] = {
45*4882a593Smuzhiyun { HISTB_OSC_CLK, "clk_osc", NULL, 0, 24000000, },
46*4882a593Smuzhiyun { HISTB_APB_CLK, "clk_apb", NULL, 0, 100000000, },
47*4882a593Smuzhiyun { HISTB_AHB_CLK, "clk_ahb", NULL, 0, 200000000, },
48*4882a593Smuzhiyun { HI3798CV200_FIXED_12M, "12m", NULL, 0, 12000000, },
49*4882a593Smuzhiyun { HI3798CV200_FIXED_24M, "24m", NULL, 0, 24000000, },
50*4882a593Smuzhiyun { HI3798CV200_FIXED_25M, "25m", NULL, 0, 25000000, },
51*4882a593Smuzhiyun { HI3798CV200_FIXED_48M, "48m", NULL, 0, 48000000, },
52*4882a593Smuzhiyun { HI3798CV200_FIXED_50M, "50m", NULL, 0, 50000000, },
53*4882a593Smuzhiyun { HI3798CV200_FIXED_60M, "60m", NULL, 0, 60000000, },
54*4882a593Smuzhiyun { HI3798CV200_FIXED_75M, "75m", NULL, 0, 75000000, },
55*4882a593Smuzhiyun { HI3798CV200_FIXED_100M, "100m", NULL, 0, 100000000, },
56*4882a593Smuzhiyun { HI3798CV200_FIXED_150M, "150m", NULL, 0, 150000000, },
57*4882a593Smuzhiyun { HI3798CV200_FIXED_166P5M, "166p5m", NULL, 0, 165000000, },
58*4882a593Smuzhiyun { HI3798CV200_FIXED_200M, "200m", NULL, 0, 200000000, },
59*4882a593Smuzhiyun { HI3798CV200_FIXED_250M, "250m", NULL, 0, 250000000, },
60*4882a593Smuzhiyun };
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun static const char *const mmc_mux_p[] = {
63*4882a593Smuzhiyun "100m", "50m", "25m", "200m", "150m" };
64*4882a593Smuzhiyun static u32 mmc_mux_table[] = {0, 1, 2, 3, 6};
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun static const char *const comphy_mux_p[] = {
67*4882a593Smuzhiyun "100m", "25m"};
68*4882a593Smuzhiyun static u32 comphy_mux_table[] = {2, 3};
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun static const char *const sdio_mux_p[] = {
71*4882a593Smuzhiyun "100m", "50m", "150m", "166p5m" };
72*4882a593Smuzhiyun static u32 sdio_mux_table[] = {0, 1, 2, 3};
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun static struct hisi_mux_clock hi3798cv200_mux_clks[] = {
75*4882a593Smuzhiyun { HI3798CV200_MMC_MUX, "mmc_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
76*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xa0, 8, 3, 0, mmc_mux_table, },
77*4882a593Smuzhiyun { HI3798CV200_COMBPHY0_MUX, "combphy0_mux",
78*4882a593Smuzhiyun comphy_mux_p, ARRAY_SIZE(comphy_mux_p),
79*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0x188, 2, 2, 0, comphy_mux_table, },
80*4882a593Smuzhiyun { HI3798CV200_COMBPHY1_MUX, "combphy1_mux",
81*4882a593Smuzhiyun comphy_mux_p, ARRAY_SIZE(comphy_mux_p),
82*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0x188, 10, 2, 0, comphy_mux_table, },
83*4882a593Smuzhiyun { HI3798CV200_SDIO0_MUX, "sdio0_mux", sdio_mux_p,
84*4882a593Smuzhiyun ARRAY_SIZE(sdio_mux_p), CLK_SET_RATE_PARENT,
85*4882a593Smuzhiyun 0x9c, 8, 2, 0, sdio_mux_table, },
86*4882a593Smuzhiyun };
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun static u32 mmc_phase_regvals[] = {0, 1, 2, 3, 4, 5, 6, 7};
89*4882a593Smuzhiyun static u32 mmc_phase_degrees[] = {0, 45, 90, 135, 180, 225, 270, 315};
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun static struct hisi_phase_clock hi3798cv200_phase_clks[] = {
92*4882a593Smuzhiyun { HISTB_MMC_SAMPLE_CLK, "mmc_sample", "clk_mmc_ciu",
93*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xa0, 12, 3, mmc_phase_degrees,
94*4882a593Smuzhiyun mmc_phase_regvals, ARRAY_SIZE(mmc_phase_regvals) },
95*4882a593Smuzhiyun { HISTB_MMC_DRV_CLK, "mmc_drive", "clk_mmc_ciu",
96*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xa0, 16, 3, mmc_phase_degrees,
97*4882a593Smuzhiyun mmc_phase_regvals, ARRAY_SIZE(mmc_phase_regvals) },
98*4882a593Smuzhiyun };
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun static const struct hisi_gate_clock hi3798cv200_gate_clks[] = {
101*4882a593Smuzhiyun /* UART */
102*4882a593Smuzhiyun { HISTB_UART2_CLK, "clk_uart2", "75m",
103*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0x68, 4, 0, },
104*4882a593Smuzhiyun /* I2C */
105*4882a593Smuzhiyun { HISTB_I2C0_CLK, "clk_i2c0", "clk_apb",
106*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0x6C, 4, 0, },
107*4882a593Smuzhiyun { HISTB_I2C1_CLK, "clk_i2c1", "clk_apb",
108*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0x6C, 8, 0, },
109*4882a593Smuzhiyun { HISTB_I2C2_CLK, "clk_i2c2", "clk_apb",
110*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0x6C, 12, 0, },
111*4882a593Smuzhiyun { HISTB_I2C3_CLK, "clk_i2c3", "clk_apb",
112*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0x6C, 16, 0, },
113*4882a593Smuzhiyun { HISTB_I2C4_CLK, "clk_i2c4", "clk_apb",
114*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0x6C, 20, 0, },
115*4882a593Smuzhiyun /* SPI */
116*4882a593Smuzhiyun { HISTB_SPI0_CLK, "clk_spi0", "clk_apb",
117*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0x70, 0, 0, },
118*4882a593Smuzhiyun /* SDIO */
119*4882a593Smuzhiyun { HISTB_SDIO0_BIU_CLK, "clk_sdio0_biu", "200m",
120*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0x9c, 0, 0, },
121*4882a593Smuzhiyun { HISTB_SDIO0_CIU_CLK, "clk_sdio0_ciu", "sdio0_mux",
122*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0x9c, 1, 0, },
123*4882a593Smuzhiyun /* EMMC */
124*4882a593Smuzhiyun { HISTB_MMC_BIU_CLK, "clk_mmc_biu", "200m",
125*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xa0, 0, 0, },
126*4882a593Smuzhiyun { HISTB_MMC_CIU_CLK, "clk_mmc_ciu", "mmc_mux",
127*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xa0, 1, 0, },
128*4882a593Smuzhiyun /* PCIE*/
129*4882a593Smuzhiyun { HISTB_PCIE_BUS_CLK, "clk_pcie_bus", "200m",
130*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0x18c, 0, 0, },
131*4882a593Smuzhiyun { HISTB_PCIE_SYS_CLK, "clk_pcie_sys", "100m",
132*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0x18c, 1, 0, },
133*4882a593Smuzhiyun { HISTB_PCIE_PIPE_CLK, "clk_pcie_pipe", "250m",
134*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0x18c, 2, 0, },
135*4882a593Smuzhiyun { HISTB_PCIE_AUX_CLK, "clk_pcie_aux", "24m",
136*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0x18c, 3, 0, },
137*4882a593Smuzhiyun /* Ethernet */
138*4882a593Smuzhiyun { HI3798CV200_ETH_PUB_CLK, "clk_pub", NULL,
139*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xcc, 5, 0, },
140*4882a593Smuzhiyun { HI3798CV200_ETH_BUS_CLK, "clk_bus", "clk_pub",
141*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xcc, 0, 0, },
142*4882a593Smuzhiyun { HI3798CV200_ETH_BUS0_CLK, "clk_bus_m0", "clk_bus",
143*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xcc, 1, 0, },
144*4882a593Smuzhiyun { HI3798CV200_ETH_BUS1_CLK, "clk_bus_m1", "clk_bus",
145*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xcc, 2, 0, },
146*4882a593Smuzhiyun { HISTB_ETH0_MAC_CLK, "clk_mac0", "clk_bus_m0",
147*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xcc, 3, 0, },
148*4882a593Smuzhiyun { HISTB_ETH0_MACIF_CLK, "clk_macif0", "clk_bus_m0",
149*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xcc, 24, 0, },
150*4882a593Smuzhiyun { HISTB_ETH1_MAC_CLK, "clk_mac1", "clk_bus_m1",
151*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xcc, 4, 0, },
152*4882a593Smuzhiyun { HISTB_ETH1_MACIF_CLK, "clk_macif1", "clk_bus_m1",
153*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xcc, 25, 0, },
154*4882a593Smuzhiyun /* COMBPHY0 */
155*4882a593Smuzhiyun { HISTB_COMBPHY0_CLK, "clk_combphy0", "combphy0_mux",
156*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0x188, 0, 0, },
157*4882a593Smuzhiyun /* COMBPHY1 */
158*4882a593Smuzhiyun { HISTB_COMBPHY1_CLK, "clk_combphy1", "combphy1_mux",
159*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0x188, 8, 0, },
160*4882a593Smuzhiyun /* USB2 */
161*4882a593Smuzhiyun { HISTB_USB2_BUS_CLK, "clk_u2_bus", "clk_ahb",
162*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xb8, 0, 0, },
163*4882a593Smuzhiyun { HISTB_USB2_PHY_CLK, "clk_u2_phy", "60m",
164*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xb8, 4, 0, },
165*4882a593Smuzhiyun { HISTB_USB2_12M_CLK, "clk_u2_12m", "12m",
166*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xb8, 2, 0 },
167*4882a593Smuzhiyun { HISTB_USB2_48M_CLK, "clk_u2_48m", "48m",
168*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xb8, 1, 0 },
169*4882a593Smuzhiyun { HISTB_USB2_UTMI_CLK, "clk_u2_utmi", "60m",
170*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xb8, 5, 0 },
171*4882a593Smuzhiyun { HISTB_USB2_OTG_UTMI_CLK, "clk_u2_otg_utmi", "60m",
172*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xb8, 3, 0 },
173*4882a593Smuzhiyun { HISTB_USB2_PHY1_REF_CLK, "clk_u2_phy1_ref", "24m",
174*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xbc, 0, 0 },
175*4882a593Smuzhiyun { HISTB_USB2_PHY2_REF_CLK, "clk_u2_phy2_ref", "24m",
176*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xbc, 2, 0 },
177*4882a593Smuzhiyun /* USB3 */
178*4882a593Smuzhiyun { HISTB_USB3_BUS_CLK, "clk_u3_bus", NULL,
179*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xb0, 0, 0 },
180*4882a593Smuzhiyun { HISTB_USB3_UTMI_CLK, "clk_u3_utmi", NULL,
181*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xb0, 4, 0 },
182*4882a593Smuzhiyun { HISTB_USB3_PIPE_CLK, "clk_u3_pipe", NULL,
183*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xb0, 3, 0 },
184*4882a593Smuzhiyun { HISTB_USB3_SUSPEND_CLK, "clk_u3_suspend", NULL,
185*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xb0, 2, 0 },
186*4882a593Smuzhiyun { HISTB_USB3_BUS_CLK1, "clk_u3_bus1", NULL,
187*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xb0, 16, 0 },
188*4882a593Smuzhiyun { HISTB_USB3_UTMI_CLK1, "clk_u3_utmi1", NULL,
189*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xb0, 20, 0 },
190*4882a593Smuzhiyun { HISTB_USB3_PIPE_CLK1, "clk_u3_pipe1", NULL,
191*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xb0, 19, 0 },
192*4882a593Smuzhiyun { HISTB_USB3_SUSPEND_CLK1, "clk_u3_suspend1", NULL,
193*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0xb0, 18, 0 },
194*4882a593Smuzhiyun };
195*4882a593Smuzhiyun
hi3798cv200_clk_register(struct platform_device * pdev)196*4882a593Smuzhiyun static struct hisi_clock_data *hi3798cv200_clk_register(
197*4882a593Smuzhiyun struct platform_device *pdev)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun struct hisi_clock_data *clk_data;
200*4882a593Smuzhiyun int ret;
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun clk_data = hisi_clk_alloc(pdev, HI3798CV200_CRG_NR_CLKS);
203*4882a593Smuzhiyun if (!clk_data)
204*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun /* hisi_phase_clock is resource managed */
207*4882a593Smuzhiyun ret = hisi_clk_register_phase(&pdev->dev,
208*4882a593Smuzhiyun hi3798cv200_phase_clks,
209*4882a593Smuzhiyun ARRAY_SIZE(hi3798cv200_phase_clks),
210*4882a593Smuzhiyun clk_data);
211*4882a593Smuzhiyun if (ret)
212*4882a593Smuzhiyun return ERR_PTR(ret);
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun ret = hisi_clk_register_fixed_rate(hi3798cv200_fixed_rate_clks,
215*4882a593Smuzhiyun ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
216*4882a593Smuzhiyun clk_data);
217*4882a593Smuzhiyun if (ret)
218*4882a593Smuzhiyun return ERR_PTR(ret);
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun ret = hisi_clk_register_mux(hi3798cv200_mux_clks,
221*4882a593Smuzhiyun ARRAY_SIZE(hi3798cv200_mux_clks),
222*4882a593Smuzhiyun clk_data);
223*4882a593Smuzhiyun if (ret)
224*4882a593Smuzhiyun goto unregister_fixed_rate;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun ret = hisi_clk_register_gate(hi3798cv200_gate_clks,
227*4882a593Smuzhiyun ARRAY_SIZE(hi3798cv200_gate_clks),
228*4882a593Smuzhiyun clk_data);
229*4882a593Smuzhiyun if (ret)
230*4882a593Smuzhiyun goto unregister_mux;
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun ret = of_clk_add_provider(pdev->dev.of_node,
233*4882a593Smuzhiyun of_clk_src_onecell_get, &clk_data->clk_data);
234*4882a593Smuzhiyun if (ret)
235*4882a593Smuzhiyun goto unregister_gate;
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun return clk_data;
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun unregister_gate:
240*4882a593Smuzhiyun hisi_clk_unregister_gate(hi3798cv200_gate_clks,
241*4882a593Smuzhiyun ARRAY_SIZE(hi3798cv200_gate_clks),
242*4882a593Smuzhiyun clk_data);
243*4882a593Smuzhiyun unregister_mux:
244*4882a593Smuzhiyun hisi_clk_unregister_mux(hi3798cv200_mux_clks,
245*4882a593Smuzhiyun ARRAY_SIZE(hi3798cv200_mux_clks),
246*4882a593Smuzhiyun clk_data);
247*4882a593Smuzhiyun unregister_fixed_rate:
248*4882a593Smuzhiyun hisi_clk_unregister_fixed_rate(hi3798cv200_fixed_rate_clks,
249*4882a593Smuzhiyun ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
250*4882a593Smuzhiyun clk_data);
251*4882a593Smuzhiyun return ERR_PTR(ret);
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun
hi3798cv200_clk_unregister(struct platform_device * pdev)254*4882a593Smuzhiyun static void hi3798cv200_clk_unregister(struct platform_device *pdev)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun of_clk_del_provider(pdev->dev.of_node);
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun hisi_clk_unregister_gate(hi3798cv200_gate_clks,
261*4882a593Smuzhiyun ARRAY_SIZE(hi3798cv200_gate_clks),
262*4882a593Smuzhiyun crg->clk_data);
263*4882a593Smuzhiyun hisi_clk_unregister_mux(hi3798cv200_mux_clks,
264*4882a593Smuzhiyun ARRAY_SIZE(hi3798cv200_mux_clks),
265*4882a593Smuzhiyun crg->clk_data);
266*4882a593Smuzhiyun hisi_clk_unregister_fixed_rate(hi3798cv200_fixed_rate_clks,
267*4882a593Smuzhiyun ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
268*4882a593Smuzhiyun crg->clk_data);
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun static const struct hisi_crg_funcs hi3798cv200_crg_funcs = {
272*4882a593Smuzhiyun .register_clks = hi3798cv200_clk_register,
273*4882a593Smuzhiyun .unregister_clks = hi3798cv200_clk_unregister,
274*4882a593Smuzhiyun };
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun /* hi3798CV200 sysctrl CRG */
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun #define HI3798CV200_SYSCTRL_NR_CLKS 16
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun static const struct hisi_gate_clock hi3798cv200_sysctrl_gate_clks[] = {
281*4882a593Smuzhiyun { HISTB_IR_CLK, "clk_ir", "24m",
282*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0x48, 4, 0, },
283*4882a593Smuzhiyun { HISTB_TIMER01_CLK, "clk_timer01", "24m",
284*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0x48, 6, 0, },
285*4882a593Smuzhiyun { HISTB_UART0_CLK, "clk_uart0", "75m",
286*4882a593Smuzhiyun CLK_SET_RATE_PARENT, 0x48, 10, 0, },
287*4882a593Smuzhiyun };
288*4882a593Smuzhiyun
hi3798cv200_sysctrl_clk_register(struct platform_device * pdev)289*4882a593Smuzhiyun static struct hisi_clock_data *hi3798cv200_sysctrl_clk_register(
290*4882a593Smuzhiyun struct platform_device *pdev)
291*4882a593Smuzhiyun {
292*4882a593Smuzhiyun struct hisi_clock_data *clk_data;
293*4882a593Smuzhiyun int ret;
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun clk_data = hisi_clk_alloc(pdev, HI3798CV200_SYSCTRL_NR_CLKS);
296*4882a593Smuzhiyun if (!clk_data)
297*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun ret = hisi_clk_register_gate(hi3798cv200_sysctrl_gate_clks,
300*4882a593Smuzhiyun ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
301*4882a593Smuzhiyun clk_data);
302*4882a593Smuzhiyun if (ret)
303*4882a593Smuzhiyun return ERR_PTR(ret);
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun ret = of_clk_add_provider(pdev->dev.of_node,
306*4882a593Smuzhiyun of_clk_src_onecell_get, &clk_data->clk_data);
307*4882a593Smuzhiyun if (ret)
308*4882a593Smuzhiyun goto unregister_gate;
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun return clk_data;
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun unregister_gate:
313*4882a593Smuzhiyun hisi_clk_unregister_gate(hi3798cv200_sysctrl_gate_clks,
314*4882a593Smuzhiyun ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
315*4882a593Smuzhiyun clk_data);
316*4882a593Smuzhiyun return ERR_PTR(ret);
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun
hi3798cv200_sysctrl_clk_unregister(struct platform_device * pdev)319*4882a593Smuzhiyun static void hi3798cv200_sysctrl_clk_unregister(struct platform_device *pdev)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun of_clk_del_provider(pdev->dev.of_node);
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun hisi_clk_unregister_gate(hi3798cv200_sysctrl_gate_clks,
326*4882a593Smuzhiyun ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
327*4882a593Smuzhiyun crg->clk_data);
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun static const struct hisi_crg_funcs hi3798cv200_sysctrl_funcs = {
331*4882a593Smuzhiyun .register_clks = hi3798cv200_sysctrl_clk_register,
332*4882a593Smuzhiyun .unregister_clks = hi3798cv200_sysctrl_clk_unregister,
333*4882a593Smuzhiyun };
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun static const struct of_device_id hi3798cv200_crg_match_table[] = {
336*4882a593Smuzhiyun { .compatible = "hisilicon,hi3798cv200-crg",
337*4882a593Smuzhiyun .data = &hi3798cv200_crg_funcs },
338*4882a593Smuzhiyun { .compatible = "hisilicon,hi3798cv200-sysctrl",
339*4882a593Smuzhiyun .data = &hi3798cv200_sysctrl_funcs },
340*4882a593Smuzhiyun { }
341*4882a593Smuzhiyun };
342*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, hi3798cv200_crg_match_table);
343*4882a593Smuzhiyun
hi3798cv200_crg_probe(struct platform_device * pdev)344*4882a593Smuzhiyun static int hi3798cv200_crg_probe(struct platform_device *pdev)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun struct hisi_crg_dev *crg;
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);
349*4882a593Smuzhiyun if (!crg)
350*4882a593Smuzhiyun return -ENOMEM;
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun crg->funcs = of_device_get_match_data(&pdev->dev);
353*4882a593Smuzhiyun if (!crg->funcs)
354*4882a593Smuzhiyun return -ENOENT;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun crg->rstc = hisi_reset_init(pdev);
357*4882a593Smuzhiyun if (!crg->rstc)
358*4882a593Smuzhiyun return -ENOMEM;
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun crg->clk_data = crg->funcs->register_clks(pdev);
361*4882a593Smuzhiyun if (IS_ERR(crg->clk_data)) {
362*4882a593Smuzhiyun hisi_reset_exit(crg->rstc);
363*4882a593Smuzhiyun return PTR_ERR(crg->clk_data);
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun platform_set_drvdata(pdev, crg);
367*4882a593Smuzhiyun return 0;
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun
hi3798cv200_crg_remove(struct platform_device * pdev)370*4882a593Smuzhiyun static int hi3798cv200_crg_remove(struct platform_device *pdev)
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun hisi_reset_exit(crg->rstc);
375*4882a593Smuzhiyun crg->funcs->unregister_clks(pdev);
376*4882a593Smuzhiyun return 0;
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun static struct platform_driver hi3798cv200_crg_driver = {
380*4882a593Smuzhiyun .probe = hi3798cv200_crg_probe,
381*4882a593Smuzhiyun .remove = hi3798cv200_crg_remove,
382*4882a593Smuzhiyun .driver = {
383*4882a593Smuzhiyun .name = "hi3798cv200-crg",
384*4882a593Smuzhiyun .of_match_table = hi3798cv200_crg_match_table,
385*4882a593Smuzhiyun },
386*4882a593Smuzhiyun };
387*4882a593Smuzhiyun
hi3798cv200_crg_init(void)388*4882a593Smuzhiyun static int __init hi3798cv200_crg_init(void)
389*4882a593Smuzhiyun {
390*4882a593Smuzhiyun return platform_driver_register(&hi3798cv200_crg_driver);
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun core_initcall(hi3798cv200_crg_init);
393*4882a593Smuzhiyun
hi3798cv200_crg_exit(void)394*4882a593Smuzhiyun static void __exit hi3798cv200_crg_exit(void)
395*4882a593Smuzhiyun {
396*4882a593Smuzhiyun platform_driver_unregister(&hi3798cv200_crg_driver);
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun module_exit(hi3798cv200_crg_exit);
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
401*4882a593Smuzhiyun MODULE_DESCRIPTION("HiSilicon Hi3798CV200 CRG Driver");
402