1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (c) 2020 Rockchip Electronics Co. Ltd.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Author: Wyon Bi <bivvy.bi@rock-chips.com>
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <linux/clk.h>
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/platform_device.h>
11*4882a593Smuzhiyun #include <linux/clk-provider.h>
12*4882a593Smuzhiyun #include <linux/reset-controller.h>
13*4882a593Smuzhiyun #include <linux/mfd/rk628.h>
14*4882a593Smuzhiyun #include <dt-bindings/reset/rk628-rgu.h>
15*4882a593Smuzhiyun #include <dt-bindings/clock/rk628-cgu.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include "clk-regmap.h"
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #define RK628_PLL(_id, _name, _parent_name, _reg, _flags) \
20*4882a593Smuzhiyun PLL(_id, _name, _parent_name, _reg, 13, 12, 10, _flags)
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #define REG(x) ((x) + 0xc0000)
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #define CRU_CPLL_CON0 REG(0x0000)
25*4882a593Smuzhiyun #define CRU_CPLL_CON1 REG(0x0004)
26*4882a593Smuzhiyun #define CRU_CPLL_CON2 REG(0x0008)
27*4882a593Smuzhiyun #define CRU_CPLL_CON3 REG(0x000c)
28*4882a593Smuzhiyun #define CRU_CPLL_CON4 REG(0x0010)
29*4882a593Smuzhiyun #define CRU_GPLL_CON0 REG(0x0020)
30*4882a593Smuzhiyun #define CRU_GPLL_CON1 REG(0x0024)
31*4882a593Smuzhiyun #define CRU_GPLL_CON2 REG(0x0028)
32*4882a593Smuzhiyun #define CRU_GPLL_CON3 REG(0x002c)
33*4882a593Smuzhiyun #define CRU_GPLL_CON4 REG(0x0030)
34*4882a593Smuzhiyun #define CRU_MODE_CON REG(0x0060)
35*4882a593Smuzhiyun #define CRU_CLKSEL_CON00 REG(0x0080)
36*4882a593Smuzhiyun #define CRU_CLKSEL_CON01 REG(0x0084)
37*4882a593Smuzhiyun #define CRU_CLKSEL_CON02 REG(0x0088)
38*4882a593Smuzhiyun #define CRU_CLKSEL_CON03 REG(0x008c)
39*4882a593Smuzhiyun #define CRU_CLKSEL_CON04 REG(0x0090)
40*4882a593Smuzhiyun #define CRU_CLKSEL_CON05 REG(0x0094)
41*4882a593Smuzhiyun #define CRU_CLKSEL_CON06 REG(0x0098)
42*4882a593Smuzhiyun #define CRU_CLKSEL_CON07 REG(0x009c)
43*4882a593Smuzhiyun #define CRU_CLKSEL_CON08 REG(0x00a0)
44*4882a593Smuzhiyun #define CRU_CLKSEL_CON09 REG(0x00a4)
45*4882a593Smuzhiyun #define CRU_CLKSEL_CON10 REG(0x00a8)
46*4882a593Smuzhiyun #define CRU_CLKSEL_CON11 REG(0x00ac)
47*4882a593Smuzhiyun #define CRU_CLKSEL_CON12 REG(0x00b0)
48*4882a593Smuzhiyun #define CRU_CLKSEL_CON13 REG(0x00b4)
49*4882a593Smuzhiyun #define CRU_CLKSEL_CON14 REG(0x00b8)
50*4882a593Smuzhiyun #define CRU_CLKSEL_CON15 REG(0x00bc)
51*4882a593Smuzhiyun #define CRU_CLKSEL_CON16 REG(0x00c0)
52*4882a593Smuzhiyun #define CRU_CLKSEL_CON17 REG(0x00c4)
53*4882a593Smuzhiyun #define CRU_CLKSEL_CON18 REG(0x00c8)
54*4882a593Smuzhiyun #define CRU_CLKSEL_CON20 REG(0x00d0)
55*4882a593Smuzhiyun #define CRU_CLKSEL_CON21 REG(0x00d4)
56*4882a593Smuzhiyun #define CRU_GATE_CON00 REG(0x0180)
57*4882a593Smuzhiyun #define CRU_GATE_CON01 REG(0x0184)
58*4882a593Smuzhiyun #define CRU_GATE_CON02 REG(0x0188)
59*4882a593Smuzhiyun #define CRU_GATE_CON03 REG(0x018c)
60*4882a593Smuzhiyun #define CRU_GATE_CON04 REG(0x0190)
61*4882a593Smuzhiyun #define CRU_GATE_CON05 REG(0x0194)
62*4882a593Smuzhiyun #define CRU_SOFTRST_CON00 REG(0x0200)
63*4882a593Smuzhiyun #define CRU_SOFTRST_CON01 REG(0x0204)
64*4882a593Smuzhiyun #define CRU_SOFTRST_CON02 REG(0x0208)
65*4882a593Smuzhiyun #define CRU_SOFTRST_CON04 REG(0x0210)
66*4882a593Smuzhiyun #define CRU_MAX_REGISTER CRU_SOFTRST_CON04
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun #define reset_to_cru(_rst) container_of(_rst, struct rk628_cru, rcdev)
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun struct rk628_cru {
71*4882a593Smuzhiyun struct device *dev;
72*4882a593Smuzhiyun struct rk628 *parent;
73*4882a593Smuzhiyun struct regmap *regmap;
74*4882a593Smuzhiyun struct reset_controller_dev rcdev;
75*4882a593Smuzhiyun struct clk_onecell_data clk_data;
76*4882a593Smuzhiyun };
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun #define CNAME(x) "rk628_" x
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun #define PNAME(x) static const char *const x[]
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun PNAME(mux_cpll_osc_p) = { CNAME("xin_osc0_func"), CNAME("clk_cpll") };
83*4882a593Smuzhiyun PNAME(mux_gpll_osc_p) = { CNAME("xin_osc0_func"), CNAME("clk_gpll") };
84*4882a593Smuzhiyun PNAME(mux_cpll_gpll_mux_p) = { CNAME("clk_cpll_mux"), CNAME("clk_gpll_mux") };
85*4882a593Smuzhiyun PNAME(mux_mclk_i2s_8ch_p) = { CNAME("clk_i2s_8ch_src"),
86*4882a593Smuzhiyun CNAME("clk_i2s_8ch_frac"), CNAME("i2s_mclkin"),
87*4882a593Smuzhiyun CNAME("xin_osc0_half") };
88*4882a593Smuzhiyun PNAME(mux_i2s_mclkout_p) = { CNAME("mclk_i2s_8ch"), CNAME("xin_osc0_half") };
89*4882a593Smuzhiyun PNAME(mux_clk_testout_p) = { CNAME("xin_osc0_func"), CNAME("xin_osc0_half"),
90*4882a593Smuzhiyun CNAME("clk_gpll"), CNAME("clk_gpll_mux"),
91*4882a593Smuzhiyun CNAME("clk_cpll"), CNAME("clk_gpll_mux"),
92*4882a593Smuzhiyun CNAME("pclk_logic"), CNAME("sclk_vop"),
93*4882a593Smuzhiyun CNAME("mclk_i2s_8ch"), CNAME("i2s_mclkout"),
94*4882a593Smuzhiyun CNAME("dummy"), CNAME("clk_hdmirx_aud"),
95*4882a593Smuzhiyun CNAME("clk_hdmirx_cec"), CNAME("clk_imodet"),
96*4882a593Smuzhiyun CNAME("clk_txesc"), CNAME("clk_gpio_db0") };
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun static const struct clk_pll_data rk628_clk_plls[] = {
99*4882a593Smuzhiyun RK628_PLL(CGU_CLK_CPLL, CNAME("clk_cpll"), CNAME("xin_osc0_func"),
100*4882a593Smuzhiyun CRU_CPLL_CON0,
101*4882a593Smuzhiyun 0),
102*4882a593Smuzhiyun RK628_PLL(CGU_CLK_GPLL, CNAME("clk_gpll"), CNAME("xin_osc0_func"),
103*4882a593Smuzhiyun CRU_GPLL_CON0,
104*4882a593Smuzhiyun 0),
105*4882a593Smuzhiyun };
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun static const struct clk_mux_data rk628_clk_muxes[] = {
108*4882a593Smuzhiyun MUX(CGU_CLK_CPLL_MUX, CNAME("clk_cpll_mux"), mux_cpll_osc_p,
109*4882a593Smuzhiyun CRU_MODE_CON, 0, 1,
110*4882a593Smuzhiyun 0),
111*4882a593Smuzhiyun MUX(CGU_CLK_GPLL_MUX, CNAME("clk_gpll_mux"), mux_gpll_osc_p,
112*4882a593Smuzhiyun CRU_MODE_CON, 2, 1,
113*4882a593Smuzhiyun CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT),
114*4882a593Smuzhiyun };
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun static const struct clk_gate_data rk628_clk_gates[] = {
117*4882a593Smuzhiyun GATE(CGU_PCLK_GPIO0, CNAME("pclk_gpio0"), CNAME("pclk_logic"),
118*4882a593Smuzhiyun CRU_GATE_CON01, 0,
119*4882a593Smuzhiyun 0),
120*4882a593Smuzhiyun GATE(CGU_PCLK_GPIO1, CNAME("pclk_gpio1"), CNAME("pclk_logic"),
121*4882a593Smuzhiyun CRU_GATE_CON01, 1,
122*4882a593Smuzhiyun 0),
123*4882a593Smuzhiyun GATE(CGU_PCLK_GPIO2, CNAME("pclk_gpio2"), CNAME("pclk_logic"),
124*4882a593Smuzhiyun CRU_GATE_CON01, 2,
125*4882a593Smuzhiyun 0),
126*4882a593Smuzhiyun GATE(CGU_PCLK_GPIO3, CNAME("pclk_gpio3"), CNAME("pclk_logic"),
127*4882a593Smuzhiyun CRU_GATE_CON01, 3,
128*4882a593Smuzhiyun 0),
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun GATE(CGU_PCLK_TXPHY_CON, CNAME("pclk_txphy_con"), CNAME("pclk_logic"),
131*4882a593Smuzhiyun CRU_GATE_CON02, 3,
132*4882a593Smuzhiyun CLK_IGNORE_UNUSED),
133*4882a593Smuzhiyun GATE(CGU_PCLK_EFUSE, CNAME("pclk_efuse"), CNAME("pclk_logic"),
134*4882a593Smuzhiyun CRU_GATE_CON00, 5,
135*4882a593Smuzhiyun 0),
136*4882a593Smuzhiyun GATE(0, CNAME("pclk_i2c2apb"), CNAME("pclk_logic"),
137*4882a593Smuzhiyun CRU_GATE_CON00, 3,
138*4882a593Smuzhiyun CLK_IGNORE_UNUSED),
139*4882a593Smuzhiyun GATE(0, CNAME("pclk_cru"), CNAME("pclk_logic"),
140*4882a593Smuzhiyun CRU_GATE_CON00, 1,
141*4882a593Smuzhiyun CLK_IGNORE_UNUSED),
142*4882a593Smuzhiyun GATE(0, CNAME("pclk_adapter"), CNAME("pclk_logic"),
143*4882a593Smuzhiyun CRU_GATE_CON00, 7,
144*4882a593Smuzhiyun CLK_IGNORE_UNUSED),
145*4882a593Smuzhiyun GATE(0, CNAME("pclk_regfile"), CNAME("pclk_logic"),
146*4882a593Smuzhiyun CRU_GATE_CON00, 2,
147*4882a593Smuzhiyun CLK_IGNORE_UNUSED),
148*4882a593Smuzhiyun GATE(CGU_PCLK_DSI0, CNAME("pclk_dsi0"), CNAME("pclk_logic"),
149*4882a593Smuzhiyun CRU_GATE_CON02, 6,
150*4882a593Smuzhiyun 0),
151*4882a593Smuzhiyun GATE(CGU_PCLK_DSI1, CNAME("pclk_dsi1"), CNAME("pclk_logic"),
152*4882a593Smuzhiyun CRU_GATE_CON02, 7,
153*4882a593Smuzhiyun 0),
154*4882a593Smuzhiyun GATE(CGU_PCLK_CSI, CNAME("pclk_csi"), CNAME("pclk_logic"),
155*4882a593Smuzhiyun CRU_GATE_CON02, 8,
156*4882a593Smuzhiyun 0),
157*4882a593Smuzhiyun GATE(CGU_PCLK_HDMITX, CNAME("pclk_hdmitx"), CNAME("pclk_logic"),
158*4882a593Smuzhiyun CRU_GATE_CON02, 4,
159*4882a593Smuzhiyun 0),
160*4882a593Smuzhiyun GATE(CGU_PCLK_RXPHY, CNAME("pclk_rxphy"), CNAME("pclk_logic"),
161*4882a593Smuzhiyun CRU_GATE_CON02, 0,
162*4882a593Smuzhiyun 0),
163*4882a593Smuzhiyun GATE(CGU_PCLK_HDMIRX, CNAME("pclk_hdmirx"), CNAME("pclk_logic"),
164*4882a593Smuzhiyun CRU_GATE_CON02, 2,
165*4882a593Smuzhiyun 0),
166*4882a593Smuzhiyun GATE(CGU_PCLK_GVIHOST, CNAME("pclk_gvihost"), CNAME("pclk_logic"),
167*4882a593Smuzhiyun CRU_GATE_CON02, 5,
168*4882a593Smuzhiyun 0),
169*4882a593Smuzhiyun GATE(CGU_CLK_CFG_DPHY0, CNAME("clk_cfg_dphy0"), CNAME("xin_osc0_func"),
170*4882a593Smuzhiyun CRU_GATE_CON02, 13,
171*4882a593Smuzhiyun 0),
172*4882a593Smuzhiyun GATE(CGU_CLK_CFG_DPHY1, CNAME("clk_cfg_dphy1"), CNAME("xin_osc0_func"),
173*4882a593Smuzhiyun CRU_GATE_CON02, 14,
174*4882a593Smuzhiyun 0),
175*4882a593Smuzhiyun GATE(CGU_CLK_TXESC, CNAME("clk_txesc"), CNAME("xin_osc0_func"),
176*4882a593Smuzhiyun CRU_GATE_CON02, 12,
177*4882a593Smuzhiyun 0),
178*4882a593Smuzhiyun };
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun static const struct clk_composite_data rk628_clk_composites[] = {
181*4882a593Smuzhiyun COMPOSITE(CGU_CLK_IMODET, CNAME("clk_imodet"), mux_cpll_gpll_mux_p,
182*4882a593Smuzhiyun CRU_CLKSEL_CON05, 5, 1,
183*4882a593Smuzhiyun CRU_CLKSEL_CON05, 0, 5,
184*4882a593Smuzhiyun CRU_GATE_CON02, 11,
185*4882a593Smuzhiyun 0),
186*4882a593Smuzhiyun COMPOSITE(CGU_CLK_HDMIRX_AUD, CNAME("clk_hdmirx_aud"),
187*4882a593Smuzhiyun mux_cpll_gpll_mux_p,
188*4882a593Smuzhiyun CRU_CLKSEL_CON05, 15, 1,
189*4882a593Smuzhiyun CRU_CLKSEL_CON05, 6, 8,
190*4882a593Smuzhiyun CRU_GATE_CON02, 10,
191*4882a593Smuzhiyun CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT),
192*4882a593Smuzhiyun COMPOSITE_FRAC_NOMUX(CGU_CLK_HDMIRX_CEC, CNAME("clk_hdmirx_cec"),
193*4882a593Smuzhiyun CNAME("xin_osc0_func"),
194*4882a593Smuzhiyun CRU_CLKSEL_CON12,
195*4882a593Smuzhiyun CRU_GATE_CON01, 15,
196*4882a593Smuzhiyun 0),
197*4882a593Smuzhiyun COMPOSITE_FRAC(CGU_CLK_RX_READ, CNAME("clk_rx_read"),
198*4882a593Smuzhiyun mux_cpll_gpll_mux_p,
199*4882a593Smuzhiyun CRU_CLKSEL_CON02, 8, 1,
200*4882a593Smuzhiyun CRU_CLKSEL_CON14,
201*4882a593Smuzhiyun CRU_GATE_CON00, 11,
202*4882a593Smuzhiyun 0),
203*4882a593Smuzhiyun COMPOSITE_FRAC(CGU_SCLK_VOP, CNAME("sclk_vop"), mux_cpll_gpll_mux_p,
204*4882a593Smuzhiyun CRU_CLKSEL_CON02, 9, 1,
205*4882a593Smuzhiyun CRU_CLKSEL_CON13,
206*4882a593Smuzhiyun CRU_GATE_CON00, 13,
207*4882a593Smuzhiyun CLK_SET_RATE_NO_REPARENT),
208*4882a593Smuzhiyun COMPOSITE(CGU_PCLK_LOGIC, CNAME("pclk_logic"), mux_cpll_gpll_mux_p,
209*4882a593Smuzhiyun CRU_CLKSEL_CON00, 7, 1,
210*4882a593Smuzhiyun CRU_CLKSEL_CON00, 0, 5,
211*4882a593Smuzhiyun CRU_GATE_CON00, 0,
212*4882a593Smuzhiyun 0),
213*4882a593Smuzhiyun COMPOSITE_NOMUX(CGU_CLK_GPIO_DB0, CNAME("clk_gpio_db0"),
214*4882a593Smuzhiyun CNAME("xin_osc0_func"),
215*4882a593Smuzhiyun CRU_CLKSEL_CON08, 0, 10,
216*4882a593Smuzhiyun CRU_GATE_CON01, 4,
217*4882a593Smuzhiyun 0),
218*4882a593Smuzhiyun COMPOSITE_NOMUX(CGU_CLK_GPIO_DB1, CNAME("clk_gpio_db1"),
219*4882a593Smuzhiyun CNAME("xin_osc0_func"),
220*4882a593Smuzhiyun CRU_CLKSEL_CON09, 0, 10,
221*4882a593Smuzhiyun CRU_GATE_CON01, 5,
222*4882a593Smuzhiyun 0),
223*4882a593Smuzhiyun COMPOSITE_NOMUX(CGU_CLK_GPIO_DB2, CNAME("clk_gpio_db2"),
224*4882a593Smuzhiyun CNAME("xin_osc0_func"),
225*4882a593Smuzhiyun CRU_CLKSEL_CON10, 0, 10,
226*4882a593Smuzhiyun CRU_GATE_CON01, 6,
227*4882a593Smuzhiyun 0),
228*4882a593Smuzhiyun COMPOSITE_NOMUX(CGU_CLK_GPIO_DB3, CNAME("clk_gpio_db3"),
229*4882a593Smuzhiyun CNAME("xin_osc0_func"),
230*4882a593Smuzhiyun CRU_CLKSEL_CON11, 0, 10,
231*4882a593Smuzhiyun CRU_GATE_CON01, 7,
232*4882a593Smuzhiyun 0),
233*4882a593Smuzhiyun COMPOSITE(CGU_CLK_I2S_8CH_SRC, CNAME("clk_i2s_8ch_src"),
234*4882a593Smuzhiyun mux_cpll_gpll_mux_p,
235*4882a593Smuzhiyun CRU_CLKSEL_CON03, 13, 1,
236*4882a593Smuzhiyun CRU_CLKSEL_CON03, 8, 5,
237*4882a593Smuzhiyun CRU_GATE_CON03, 9,
238*4882a593Smuzhiyun 0),
239*4882a593Smuzhiyun COMPOSITE_FRAC_NOMUX(CGU_CLK_I2S_8CH_FRAC, CNAME("clk_i2s_8ch_frac"),
240*4882a593Smuzhiyun CNAME("clk_i2s_8ch_src"),
241*4882a593Smuzhiyun CRU_CLKSEL_CON04,
242*4882a593Smuzhiyun CRU_GATE_CON03, 10,
243*4882a593Smuzhiyun 0),
244*4882a593Smuzhiyun COMPOSITE_NODIV(CGU_MCLK_I2S_8CH, CNAME("mclk_i2s_8ch"),
245*4882a593Smuzhiyun mux_mclk_i2s_8ch_p,
246*4882a593Smuzhiyun CRU_CLKSEL_CON03, 14, 2,
247*4882a593Smuzhiyun CRU_GATE_CON03, 11,
248*4882a593Smuzhiyun CLK_SET_RATE_PARENT),
249*4882a593Smuzhiyun COMPOSITE_NODIV(CGU_I2S_MCLKOUT, CNAME("i2s_mclkout"),
250*4882a593Smuzhiyun mux_i2s_mclkout_p,
251*4882a593Smuzhiyun CRU_CLKSEL_CON03, 7, 1,
252*4882a593Smuzhiyun CRU_GATE_CON03, 12,
253*4882a593Smuzhiyun CLK_SET_RATE_PARENT),
254*4882a593Smuzhiyun COMPOSITE(CGU_BT1120DEC, CNAME("clk_bt1120dec"), mux_cpll_gpll_mux_p,
255*4882a593Smuzhiyun CRU_CLKSEL_CON02, 7, 1,
256*4882a593Smuzhiyun CRU_CLKSEL_CON02, 0, 5,
257*4882a593Smuzhiyun CRU_GATE_CON00, 12,
258*4882a593Smuzhiyun 0),
259*4882a593Smuzhiyun COMPOSITE(CGU_CLK_TESTOUT, CNAME("clk_testout"), mux_clk_testout_p,
260*4882a593Smuzhiyun CRU_CLKSEL_CON06, 0, 4,
261*4882a593Smuzhiyun CRU_CLKSEL_CON06, 8, 6,
262*4882a593Smuzhiyun CRU_GATE_CON04, 7,
263*4882a593Smuzhiyun 0),
264*4882a593Smuzhiyun };
265*4882a593Smuzhiyun
rk628_clk_add_lookup(struct rk628_cru * cru,struct clk * clk,unsigned int id)266*4882a593Smuzhiyun static void rk628_clk_add_lookup(struct rk628_cru *cru, struct clk *clk,
267*4882a593Smuzhiyun unsigned int id)
268*4882a593Smuzhiyun {
269*4882a593Smuzhiyun if (cru->clk_data.clks && id)
270*4882a593Smuzhiyun cru->clk_data.clks[id] = clk;
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun
rk628_clk_register_muxes(struct rk628_cru * cru)273*4882a593Smuzhiyun static void rk628_clk_register_muxes(struct rk628_cru *cru)
274*4882a593Smuzhiyun {
275*4882a593Smuzhiyun struct clk *clk;
276*4882a593Smuzhiyun unsigned int i;
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(rk628_clk_muxes); i++) {
279*4882a593Smuzhiyun const struct clk_mux_data *data = &rk628_clk_muxes[i];
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun clk = devm_clk_regmap_register_mux(cru->dev, data->name,
282*4882a593Smuzhiyun data->parent_names,
283*4882a593Smuzhiyun data->num_parents,
284*4882a593Smuzhiyun cru->regmap, data->reg,
285*4882a593Smuzhiyun data->shift, data->width,
286*4882a593Smuzhiyun data->flags);
287*4882a593Smuzhiyun if (IS_ERR(clk)) {
288*4882a593Smuzhiyun dev_err(cru->dev, "failed to register clock %s\n",
289*4882a593Smuzhiyun data->name);
290*4882a593Smuzhiyun continue;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun rk628_clk_add_lookup(cru, clk, data->id);
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun
rk628_clk_register_gates(struct rk628_cru * cru)297*4882a593Smuzhiyun static void rk628_clk_register_gates(struct rk628_cru *cru)
298*4882a593Smuzhiyun {
299*4882a593Smuzhiyun struct clk *clk;
300*4882a593Smuzhiyun unsigned int i;
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(rk628_clk_gates); i++) {
303*4882a593Smuzhiyun const struct clk_gate_data *data = &rk628_clk_gates[i];
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun clk = devm_clk_regmap_register_gate(cru->dev, data->name,
306*4882a593Smuzhiyun data->parent_name,
307*4882a593Smuzhiyun cru->regmap,
308*4882a593Smuzhiyun data->reg, data->shift,
309*4882a593Smuzhiyun data->flags);
310*4882a593Smuzhiyun if (IS_ERR(clk)) {
311*4882a593Smuzhiyun dev_err(cru->dev, "failed to register clock %s\n",
312*4882a593Smuzhiyun data->name);
313*4882a593Smuzhiyun continue;
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun rk628_clk_add_lookup(cru, clk, data->id);
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun
rk628_clk_register_composites(struct rk628_cru * cru)320*4882a593Smuzhiyun static void rk628_clk_register_composites(struct rk628_cru *cru)
321*4882a593Smuzhiyun {
322*4882a593Smuzhiyun struct clk *clk;
323*4882a593Smuzhiyun unsigned int i;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(rk628_clk_composites); i++) {
326*4882a593Smuzhiyun const struct clk_composite_data *data =
327*4882a593Smuzhiyun &rk628_clk_composites[i];
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun clk = devm_clk_regmap_register_composite(cru->dev, data->name,
330*4882a593Smuzhiyun data->parent_names,
331*4882a593Smuzhiyun data->num_parents,
332*4882a593Smuzhiyun cru->regmap,
333*4882a593Smuzhiyun data->mux_reg,
334*4882a593Smuzhiyun data->mux_shift,
335*4882a593Smuzhiyun data->mux_width,
336*4882a593Smuzhiyun data->div_reg,
337*4882a593Smuzhiyun data->div_shift,
338*4882a593Smuzhiyun data->div_width,
339*4882a593Smuzhiyun data->div_flags,
340*4882a593Smuzhiyun data->gate_reg,
341*4882a593Smuzhiyun data->gate_shift,
342*4882a593Smuzhiyun data->flags);
343*4882a593Smuzhiyun if (IS_ERR(clk)) {
344*4882a593Smuzhiyun dev_err(cru->dev, "failed to register clock %s\n",
345*4882a593Smuzhiyun data->name);
346*4882a593Smuzhiyun continue;
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun rk628_clk_add_lookup(cru, clk, data->id);
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun
rk628_clk_register_plls(struct rk628_cru * cru)353*4882a593Smuzhiyun static void rk628_clk_register_plls(struct rk628_cru *cru)
354*4882a593Smuzhiyun {
355*4882a593Smuzhiyun struct clk *clk;
356*4882a593Smuzhiyun unsigned int i;
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(rk628_clk_plls); i++) {
359*4882a593Smuzhiyun const struct clk_pll_data *data = &rk628_clk_plls[i];
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun clk = devm_clk_regmap_register_pll(cru->dev, data->name,
362*4882a593Smuzhiyun data->parent_name,
363*4882a593Smuzhiyun cru->regmap,
364*4882a593Smuzhiyun data->reg,
365*4882a593Smuzhiyun data->pd_shift,
366*4882a593Smuzhiyun data->dsmpd_shift,
367*4882a593Smuzhiyun data->lock_shift,
368*4882a593Smuzhiyun data->flags);
369*4882a593Smuzhiyun if (IS_ERR(clk)) {
370*4882a593Smuzhiyun dev_err(cru->dev, "failed to register clock %s\n",
371*4882a593Smuzhiyun data->name);
372*4882a593Smuzhiyun continue;
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun rk628_clk_add_lookup(cru, clk, data->id);
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun struct rk628_rgu_data {
380*4882a593Smuzhiyun unsigned int id;
381*4882a593Smuzhiyun unsigned int reg;
382*4882a593Smuzhiyun unsigned int bit;
383*4882a593Smuzhiyun };
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun #define RSTGEN(_id, _reg, _bit) \
386*4882a593Smuzhiyun { \
387*4882a593Smuzhiyun .id = (_id), \
388*4882a593Smuzhiyun .reg = (_reg), \
389*4882a593Smuzhiyun .bit = (_bit), \
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun static const struct rk628_rgu_data rk628_rgu_data[] = {
393*4882a593Smuzhiyun RSTGEN(RGU_LOGIC, CRU_SOFTRST_CON00, 0),
394*4882a593Smuzhiyun RSTGEN(RGU_CRU, CRU_SOFTRST_CON00, 1),
395*4882a593Smuzhiyun RSTGEN(RGU_REGFILE, CRU_SOFTRST_CON00, 2),
396*4882a593Smuzhiyun RSTGEN(RGU_I2C2APB, CRU_SOFTRST_CON00, 3),
397*4882a593Smuzhiyun RSTGEN(RGU_EFUSE, CRU_SOFTRST_CON00, 5),
398*4882a593Smuzhiyun RSTGEN(RGU_ADAPTER, CRU_SOFTRST_CON00, 7),
399*4882a593Smuzhiyun RSTGEN(RGU_CLK_RX, CRU_SOFTRST_CON00, 11),
400*4882a593Smuzhiyun RSTGEN(RGU_BT1120DEC, CRU_SOFTRST_CON00, 12),
401*4882a593Smuzhiyun RSTGEN(RGU_VOP, CRU_SOFTRST_CON00, 13),
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun RSTGEN(RGU_GPIO0, CRU_SOFTRST_CON01, 0),
404*4882a593Smuzhiyun RSTGEN(RGU_GPIO1, CRU_SOFTRST_CON01, 1),
405*4882a593Smuzhiyun RSTGEN(RGU_GPIO2, CRU_SOFTRST_CON01, 2),
406*4882a593Smuzhiyun RSTGEN(RGU_GPIO3, CRU_SOFTRST_CON01, 3),
407*4882a593Smuzhiyun RSTGEN(RGU_GPIO_DB0, CRU_SOFTRST_CON01, 4),
408*4882a593Smuzhiyun RSTGEN(RGU_GPIO_DB1, CRU_SOFTRST_CON01, 5),
409*4882a593Smuzhiyun RSTGEN(RGU_GPIO_DB2, CRU_SOFTRST_CON01, 6),
410*4882a593Smuzhiyun RSTGEN(RGU_GPIO_DB3, CRU_SOFTRST_CON01, 7),
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun RSTGEN(RGU_RXPHY, CRU_SOFTRST_CON02, 0),
413*4882a593Smuzhiyun RSTGEN(RGU_HDMIRX, CRU_SOFTRST_CON02, 2),
414*4882a593Smuzhiyun RSTGEN(RGU_TXPHY_CON, CRU_SOFTRST_CON02, 3),
415*4882a593Smuzhiyun RSTGEN(RGU_HDMITX, CRU_SOFTRST_CON02, 4),
416*4882a593Smuzhiyun RSTGEN(RGU_GVIHOST, CRU_SOFTRST_CON02, 5),
417*4882a593Smuzhiyun RSTGEN(RGU_DSI0, CRU_SOFTRST_CON02, 6),
418*4882a593Smuzhiyun RSTGEN(RGU_DSI1, CRU_SOFTRST_CON02, 7),
419*4882a593Smuzhiyun RSTGEN(RGU_CSI, CRU_SOFTRST_CON02, 8),
420*4882a593Smuzhiyun RSTGEN(RGU_TXDATA, CRU_SOFTRST_CON02, 9),
421*4882a593Smuzhiyun RSTGEN(RGU_DECODER, CRU_SOFTRST_CON02, 10),
422*4882a593Smuzhiyun RSTGEN(RGU_ENCODER, CRU_SOFTRST_CON02, 11),
423*4882a593Smuzhiyun RSTGEN(RGU_HDMIRX_PON, CRU_SOFTRST_CON02, 12),
424*4882a593Smuzhiyun RSTGEN(RGU_TXBYTEHS, CRU_SOFTRST_CON02, 13),
425*4882a593Smuzhiyun RSTGEN(RGU_TXESC, CRU_SOFTRST_CON02, 14),
426*4882a593Smuzhiyun };
427*4882a593Smuzhiyun
rk628_rgu_update(struct rk628_cru * cru,unsigned long id,int assert)428*4882a593Smuzhiyun static int rk628_rgu_update(struct rk628_cru *cru, unsigned long id, int assert)
429*4882a593Smuzhiyun {
430*4882a593Smuzhiyun const struct rk628_rgu_data *data = &rk628_rgu_data[id];
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun return regmap_write(cru->regmap, data->reg,
433*4882a593Smuzhiyun BIT(data->bit + 16) | (assert << data->bit));
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun
rk628_rgu_assert(struct reset_controller_dev * rcdev,unsigned long id)436*4882a593Smuzhiyun static int rk628_rgu_assert(struct reset_controller_dev *rcdev,
437*4882a593Smuzhiyun unsigned long id)
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun struct rk628_cru *cru = reset_to_cru(rcdev);
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun return rk628_rgu_update(cru, id, 1);
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun
rk628_rgu_deassert(struct reset_controller_dev * rcdev,unsigned long id)444*4882a593Smuzhiyun static int rk628_rgu_deassert(struct reset_controller_dev *rcdev,
445*4882a593Smuzhiyun unsigned long id)
446*4882a593Smuzhiyun {
447*4882a593Smuzhiyun struct rk628_cru *cru = reset_to_cru(rcdev);
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun return rk628_rgu_update(cru, id, 0);
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun static struct reset_control_ops rk628_rgu_ops = {
453*4882a593Smuzhiyun .assert = rk628_rgu_assert,
454*4882a593Smuzhiyun .deassert = rk628_rgu_deassert,
455*4882a593Smuzhiyun };
456*4882a593Smuzhiyun
rk628_reset_controller_register(struct rk628_cru * cru)457*4882a593Smuzhiyun static int rk628_reset_controller_register(struct rk628_cru *cru)
458*4882a593Smuzhiyun {
459*4882a593Smuzhiyun struct device *dev = cru->dev;
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun cru->rcdev.owner = THIS_MODULE;
462*4882a593Smuzhiyun cru->rcdev.nr_resets = ARRAY_SIZE(rk628_rgu_data);
463*4882a593Smuzhiyun cru->rcdev.of_node = dev->of_node;
464*4882a593Smuzhiyun cru->rcdev.ops = &rk628_rgu_ops;
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun return devm_reset_controller_register(dev, &cru->rcdev);
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun static const struct regmap_range rk628_cru_readable_ranges[] = {
470*4882a593Smuzhiyun regmap_reg_range(CRU_CPLL_CON0, CRU_CPLL_CON4),
471*4882a593Smuzhiyun regmap_reg_range(CRU_GPLL_CON0, CRU_GPLL_CON4),
472*4882a593Smuzhiyun regmap_reg_range(CRU_MODE_CON, CRU_MODE_CON),
473*4882a593Smuzhiyun regmap_reg_range(CRU_CLKSEL_CON00, CRU_CLKSEL_CON21),
474*4882a593Smuzhiyun regmap_reg_range(CRU_GATE_CON00, CRU_GATE_CON05),
475*4882a593Smuzhiyun regmap_reg_range(CRU_SOFTRST_CON00, CRU_SOFTRST_CON04),
476*4882a593Smuzhiyun };
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun static const struct regmap_access_table rk628_cru_readable_table = {
479*4882a593Smuzhiyun .yes_ranges = rk628_cru_readable_ranges,
480*4882a593Smuzhiyun .n_yes_ranges = ARRAY_SIZE(rk628_cru_readable_ranges),
481*4882a593Smuzhiyun };
482*4882a593Smuzhiyun
483*4882a593Smuzhiyun static const struct regmap_config rk628_cru_regmap_config = {
484*4882a593Smuzhiyun .name = "cru",
485*4882a593Smuzhiyun .reg_bits = 32,
486*4882a593Smuzhiyun .val_bits = 32,
487*4882a593Smuzhiyun .reg_stride = 4,
488*4882a593Smuzhiyun .max_register = CRU_MAX_REGISTER,
489*4882a593Smuzhiyun .reg_format_endian = REGMAP_ENDIAN_LITTLE,
490*4882a593Smuzhiyun .val_format_endian = REGMAP_ENDIAN_LITTLE,
491*4882a593Smuzhiyun .rd_table = &rk628_cru_readable_table,
492*4882a593Smuzhiyun };
493*4882a593Smuzhiyun
rk628_cru_init(struct rk628_cru * cru)494*4882a593Smuzhiyun static void rk628_cru_init(struct rk628_cru *cru)
495*4882a593Smuzhiyun {
496*4882a593Smuzhiyun u32 val = 0;
497*4882a593Smuzhiyun u8 mcu_mode;
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun regmap_read(cru->parent->grf, GRF_SYSTEM_STATUS0, &val);
500*4882a593Smuzhiyun mcu_mode = (val & I2C_ONLY_FLAG) ? 0 : 1;
501*4882a593Smuzhiyun if (mcu_mode)
502*4882a593Smuzhiyun return;
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun /* clock switch and first set gpll almost 99MHz */
505*4882a593Smuzhiyun regmap_write(cru->regmap, CRU_GPLL_CON0, 0xffff701d);
506*4882a593Smuzhiyun usleep_range(1000, 1100);
507*4882a593Smuzhiyun /* set clk_gpll_mux from gpll */
508*4882a593Smuzhiyun regmap_write(cru->regmap, CRU_MODE_CON, 0xffff0004);
509*4882a593Smuzhiyun usleep_range(1000, 1100);
510*4882a593Smuzhiyun /* set pclk_logic from clk_gpll_mux and set pclk div 4 */
511*4882a593Smuzhiyun regmap_write(cru->regmap, CRU_CLKSEL_CON00, 0xff0080);
512*4882a593Smuzhiyun regmap_write(cru->regmap, CRU_CLKSEL_CON00, 0xff0083);
513*4882a593Smuzhiyun /* set cpll almost 400MHz */
514*4882a593Smuzhiyun regmap_write(cru->regmap, CRU_CPLL_CON0, 0xffff3063);
515*4882a593Smuzhiyun usleep_range(1000, 1100);
516*4882a593Smuzhiyun /* set clk_cpll_mux from clk_cpll */
517*4882a593Smuzhiyun regmap_write(cru->regmap, CRU_MODE_CON, 0xffff0005);
518*4882a593Smuzhiyun /* set pclk use cpll, now div is 4 */
519*4882a593Smuzhiyun regmap_write(cru->regmap, CRU_CLKSEL_CON00, 0xff0003);
520*4882a593Smuzhiyun /* set pclk use cpll, now div is 12 */
521*4882a593Smuzhiyun regmap_write(cru->regmap, CRU_CLKSEL_CON00, 0xff000b);
522*4882a593Smuzhiyun /* gpll 983.04MHz */
523*4882a593Smuzhiyun regmap_write(cru->regmap, CRU_GPLL_CON0, 0xffff1028);
524*4882a593Smuzhiyun usleep_range(1000, 1100);
525*4882a593Smuzhiyun /* set pclk use gpll, nuw div is 0xb */
526*4882a593Smuzhiyun regmap_write(cru->regmap, CRU_CLKSEL_CON00, 0xff008b);
527*4882a593Smuzhiyun /* set cpll 1188MHz */
528*4882a593Smuzhiyun regmap_write(cru->regmap, CRU_CPLL_CON0, 0xffff1063);
529*4882a593Smuzhiyun usleep_range(1000, 1100);
530*4882a593Smuzhiyun /* set pclk use cpll, and set pclk 99MHz */
531*4882a593Smuzhiyun regmap_write(cru->regmap, CRU_CLKSEL_CON00, 0xff000b);
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun
rk628_cru_probe(struct platform_device * pdev)534*4882a593Smuzhiyun static int rk628_cru_probe(struct platform_device *pdev)
535*4882a593Smuzhiyun {
536*4882a593Smuzhiyun struct rk628 *rk628 = dev_get_drvdata(pdev->dev.parent);
537*4882a593Smuzhiyun struct device *dev = &pdev->dev;
538*4882a593Smuzhiyun struct rk628_cru *cru;
539*4882a593Smuzhiyun struct clk **clk_table;
540*4882a593Smuzhiyun unsigned int i;
541*4882a593Smuzhiyun int ret;
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun cru = devm_kzalloc(dev, sizeof(*cru), GFP_KERNEL);
544*4882a593Smuzhiyun if (!cru)
545*4882a593Smuzhiyun return -ENOMEM;
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun cru->dev = dev;
548*4882a593Smuzhiyun cru->parent = rk628;
549*4882a593Smuzhiyun platform_set_drvdata(pdev, cru);
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun cru->regmap = devm_regmap_init_i2c(rk628->client,
552*4882a593Smuzhiyun &rk628_cru_regmap_config);
553*4882a593Smuzhiyun if (IS_ERR(cru->regmap)) {
554*4882a593Smuzhiyun ret = PTR_ERR(cru->regmap);
555*4882a593Smuzhiyun dev_err(dev, "failed to allocate register map: %d\n", ret);
556*4882a593Smuzhiyun return ret;
557*4882a593Smuzhiyun }
558*4882a593Smuzhiyun
559*4882a593Smuzhiyun rk628_cru_init(cru);
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun clk_table = devm_kcalloc(dev, CGU_NR_CLKS, sizeof(struct clk *),
562*4882a593Smuzhiyun GFP_KERNEL);
563*4882a593Smuzhiyun if (!clk_table)
564*4882a593Smuzhiyun return -ENOMEM;
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun for (i = 0; i < CGU_NR_CLKS; i++)
567*4882a593Smuzhiyun clk_table[i] = ERR_PTR(-ENOENT);
568*4882a593Smuzhiyun
569*4882a593Smuzhiyun cru->clk_data.clks = clk_table;
570*4882a593Smuzhiyun cru->clk_data.clk_num = CGU_NR_CLKS;
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun rk628_clk_register_plls(cru);
573*4882a593Smuzhiyun rk628_clk_register_muxes(cru);
574*4882a593Smuzhiyun rk628_clk_register_gates(cru);
575*4882a593Smuzhiyun rk628_clk_register_composites(cru);
576*4882a593Smuzhiyun rk628_reset_controller_register(cru);
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun clk_prepare_enable(clk_table[CGU_PCLK_LOGIC]);
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
581*4882a593Smuzhiyun &cru->clk_data);
582*4882a593Smuzhiyun }
583*4882a593Smuzhiyun
rk628_cru_remove(struct platform_device * pdev)584*4882a593Smuzhiyun static int rk628_cru_remove(struct platform_device *pdev)
585*4882a593Smuzhiyun {
586*4882a593Smuzhiyun of_clk_del_provider(pdev->dev.of_node);
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun return 0;
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun static const struct of_device_id rk628_cru_of_match[] = {
592*4882a593Smuzhiyun { .compatible = "rockchip,rk628-cru", },
593*4882a593Smuzhiyun {},
594*4882a593Smuzhiyun };
595*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, rk628_cru_of_match);
596*4882a593Smuzhiyun
597*4882a593Smuzhiyun static struct platform_driver rk628_cru_driver = {
598*4882a593Smuzhiyun .driver = {
599*4882a593Smuzhiyun .name = "rk628-cru",
600*4882a593Smuzhiyun .of_match_table = of_match_ptr(rk628_cru_of_match),
601*4882a593Smuzhiyun },
602*4882a593Smuzhiyun .probe = rk628_cru_probe,
603*4882a593Smuzhiyun .remove = rk628_cru_remove,
604*4882a593Smuzhiyun };
605*4882a593Smuzhiyun module_platform_driver(rk628_cru_driver);
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun MODULE_AUTHOR("Wyon Bi <bivvy.bi@rock-chips.com>");
608*4882a593Smuzhiyun MODULE_DESCRIPTION("Rockchip RK628 CRU driver");
609*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
610