xref: /OK3568_Linux_fs/kernel/drivers/clk/hisilicon/crg-hi3798cv200.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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