• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2020 frank@allwinnertech.com
4  */
5 
6 #include <linux/clk-provider.h>
7 #include <linux/module.h>
8 #include <linux/of_address.h>
9 #include <linux/platform_device.h>
10 
11 #include "ccu_common.h"
12 #include "ccu_reset.h"
13 
14 #include "ccu_div.h"
15 #include "ccu_gate.h"
16 #include "ccu_mp.h"
17 #include "ccu_nm.h"
18 
19 #include "ccu-sun50iw12-r.h"
20 
21 
22 static const char * const cpus_r_apb_parents[] = { "dcxo24M", "osc32k",
23 						     "iosc", "pll-periph0" };
24 static const struct ccu_mux_var_prediv cpus_r_apb_predivs[] = {
25 	{ .index = 3, .shift = 0, .width = 5 },
26 };
27 
28 static struct ccu_div cpus_clk = {
29 	.div		= _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
30 
31 	.mux		= {
32 		.shift	= 24,
33 		.width	= 2,
34 
35 		.var_predivs	= cpus_r_apb_predivs,
36 		.n_var_predivs	= ARRAY_SIZE(cpus_r_apb_predivs),
37 	},
38 
39 	.common		= {
40 		.reg		= 0x000,
41 		.features	= CCU_FEATURE_VARIABLE_PREDIV,
42 		.hw.init	= CLK_HW_INIT_PARENTS("cpus",
43 						      cpus_r_apb_parents,
44 						      &ccu_div_ops,
45 						      0),
46 	},
47 };
48 
49 static CLK_FIXED_FACTOR_HW(r_ahb_clk, "r-ahb", &cpus_clk.common.hw, 1, 1, 0);
50 
51 static struct ccu_div r_apb0_clk = {
52 	.div		= _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
53 
54 	.mux		= {
55 		.shift	= 24,
56 		.width	= 2,
57 
58 		.var_predivs	= cpus_r_apb_predivs,
59 		.n_var_predivs	= ARRAY_SIZE(cpus_r_apb_predivs),
60 	},
61 
62 	.common		= {
63 		.reg		= 0x0C,
64 		.features	= CCU_FEATURE_VARIABLE_PREDIV,
65 		.hw.init	= CLK_HW_INIT_PARENTS("r-apb0",
66 						      cpus_r_apb_parents,
67 						      &ccu_div_ops,
68 						      0),
69 	},
70 };
71 
72 static struct ccu_div r_apb1_clk = {
73 	.div		= _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
74 
75 	.mux		= {
76 		.shift	= 24,
77 		.width	= 2,
78 
79 		.var_predivs	= cpus_r_apb_predivs,
80 		.n_var_predivs	= ARRAY_SIZE(cpus_r_apb_predivs),
81 	},
82 
83 	.common		= {
84 		.reg		= 0x10,
85 		.features	= CCU_FEATURE_VARIABLE_PREDIV,
86 		.hw.init	= CLK_HW_INIT_PARENTS("r-apb1",
87 						      cpus_r_apb_parents,
88 						      &ccu_div_ops,
89 						      0),
90 	},
91 };
92 
93 static const char * const r_timer_parents[] = { "dcxo24M", "iosc",
94 						     "osc32k", "r-ahb" };
95 static struct ccu_div r_apb0_timer0_clk = {
96 	.enable		= BIT(0),
97 	.div		= _SUNXI_CCU_DIV_FLAGS(1, 3, CLK_DIVIDER_POWER_OF_TWO),
98 	.mux		= _SUNXI_CCU_MUX(4, 2),
99 	.common		= {
100 		.reg		= 0x110,
101 		.hw.init	= CLK_HW_INIT_PARENTS("r-timer0",
102 						      r_timer_parents,
103 						      &ccu_div_ops,
104 						      0),
105 	},
106 };
107 
108 static struct ccu_div r_apb0_timer1_clk = {
109 	.enable		= BIT(0),
110 	.div		= _SUNXI_CCU_DIV_FLAGS(1, 3, CLK_DIVIDER_POWER_OF_TWO),
111 	.mux		= _SUNXI_CCU_MUX(4, 2),
112 	.common		= {
113 		.reg		= 0x114,
114 		.hw.init	= CLK_HW_INIT_PARENTS("r-timer1",
115 						      r_timer_parents,
116 						      &ccu_div_ops,
117 						      0),
118 	},
119 };
120 
121 static struct ccu_div r_apb0_timer2_clk = {
122 	.enable		= BIT(0),
123 	.div		= _SUNXI_CCU_DIV_FLAGS(1, 3, CLK_DIVIDER_POWER_OF_TWO),
124 	.mux		= _SUNXI_CCU_MUX(4, 2),
125 	.common		= {
126 		.reg		= 0x118,
127 		.hw.init	= CLK_HW_INIT_PARENTS("r-timer2",
128 						      r_timer_parents,
129 						      &ccu_div_ops,
130 						      0),
131 	},
132 };
133 static SUNXI_CCU_GATE(bus_r_apb0_timer0_clk, "bus-r-timer0", "r-apb0",
134 		      0x11c, BIT(0), 0);
135 
136 static SUNXI_CCU_MP_WITH_MUX_GATE(r_apb0_edid_clk, "r-edid",
137 				  cpus_r_apb_parents, 0x124,
138 				  0, 5,		/* M */
139 				  8, 2,		/* P */
140 				  24, 2,	/* mux */
141 				  BIT(31),	/* gate */
142 				  0);
143 
144 static SUNXI_CCU_GATE(bus_r_apb0_wdt1_clk, "bus-r-wdt1", "r-apb0",
145 		      0x12c, BIT(0), 0);
146 
147 static const char * const r_pwm_parents[] = { "dcxo24M", "osc32k",
148 						   "iosc" };
149 static SUNXI_CCU_MUX_WITH_GATE(r_apb0_pwm_clk, "r-pwm",
150 			       r_pwm_parents, 0x130,
151 			       24, 2,		/* mux */
152 			       BIT(31),		/* gate */
153 			       0);
154 
155 static SUNXI_CCU_GATE(bus_r_apb0_pwm_clk, "bus-r-pwm", "r-apb0",
156 		      0x13c, BIT(0), 0);
157 
158 static SUNXI_CCU_GATE(bus_apb1_r_uart_clk, "bus-r-uart", "r-apb1",
159 		      0x18c, BIT(0), 0);
160 static SUNXI_CCU_GATE(bus_r_apb1_i2c0_clk, "bus-r-i2c0", "r-apb1",
161 		      0x19c, BIT(0), 0);
162 static SUNXI_CCU_GATE(bus_r_apb1_i2c1_clk, "bus-r-i2c1", "r-apb1",
163 		      0x19c, BIT(1), 0);
164 
165 static SUNXI_CCU_GATE(bus_r_apb1_ppu_clk, "bus-r-ppu", "r-apb1",
166 		      0x1ac, BIT(0), 0);
167 
168 static SUNXI_CCU_GATE(bus_r_apb1_bus_tzma_clk, "bus-r-tzma", "r-apb1",
169 		      0x1b0, BIT(0), 0);
170 
171 static SUNXI_CCU_GATE(bus_r_cpus_bist_clk, "bus-r-cpus_bist", "r-apb1",
172 		      0x1bc, BIT(0), 0);
173 
174 static const char * const r_ir_parents[] = { "osc32k", "dcxo24M" };
175 static SUNXI_CCU_MP_WITH_MUX_GATE(r_apb0_ir_clk, "r-ir",
176 				  r_ir_parents, 0x1c0,
177 				  0, 5,		/* M */
178 				  8, 2,		/* P */
179 				  24, 1,	/* mux */
180 				  BIT(31),	/* gate */
181 				  0);
182 
183 static SUNXI_CCU_GATE(bus_r_apb0_ir_clk, "bus-r-ir", "r-apb0",
184 		      0x1cc, BIT(0), 0);
185 
186 static SUNXI_CCU_GATE(bus_r_ahb_rtc_clk, "bus-r-rtc", "r-ahb",
187 		      0x20c, BIT(0), 0);
188 
189 static SUNXI_CCU_GATE(bus_r_ahb_cpucfg_clk, "bus-r-cpucfg", "r-ahb",
190 		      0x22c, BIT(0), 0);
191 
192 static struct ccu_common *sun50iw12_r_ccu_clks[] = {
193 	&cpus_clk.common,
194 	&r_apb0_clk.common,
195 	&r_apb1_clk.common,
196 	&r_apb0_timer0_clk.common,
197 	&r_apb0_timer1_clk.common,
198 	&r_apb0_timer2_clk.common,
199 	&bus_r_apb0_timer0_clk.common,
200 	&r_apb0_edid_clk.common,
201 	&bus_r_apb0_wdt1_clk.common,
202 	&r_apb0_pwm_clk.common,
203 	&bus_r_apb0_pwm_clk.common,
204 	&bus_apb1_r_uart_clk.common,
205 	&bus_r_apb1_i2c0_clk.common,
206 	&bus_r_apb1_i2c1_clk.common,
207 	&bus_r_apb1_ppu_clk.common,
208 	&bus_r_apb1_bus_tzma_clk.common,
209 	&bus_r_cpus_bist_clk.common,
210 	&r_apb0_ir_clk.common,
211 	&bus_r_apb0_ir_clk.common,
212 	&bus_r_ahb_rtc_clk.common,
213 	&bus_r_ahb_cpucfg_clk.common,
214 };
215 
216 static struct clk_hw_onecell_data sun50iw12_r_hw_clks = {
217 	.hws	= {
218 		[CLK_CPUS]		= &cpus_clk.common.hw,
219 		[CLK_R_AHB]		= &r_ahb_clk.hw,
220 		[CLK_R_APB0]		= &r_apb0_clk.common.hw,
221 		[CLK_R_APB1]		= &r_apb1_clk.common.hw,
222 		[CLK_R_APB0_TIMER0]	= &r_apb0_timer0_clk.common.hw,
223 		[CLK_R_APB0_TIMER1]	= &r_apb0_timer1_clk.common.hw,
224 		[CLK_R_APB0_TIMER2]	= &r_apb0_timer2_clk.common.hw,
225 		[CLK_R_APB0_BUS_TIMER0]	= &bus_r_apb0_timer0_clk.common.hw,
226 		[CLK_R_APB0_EDID]	= &r_apb0_edid_clk.common.hw,
227 		[CLK_R_APB0_BUS_WDT1]	= &bus_r_apb0_wdt1_clk.common.hw,
228 		[CLK_R_APB0_PWM]	= &r_apb0_pwm_clk.common.hw,
229 		[CLK_R_APB0_BUS_PWM]	= &bus_r_apb0_pwm_clk.common.hw,
230 		[CLK_R_APB1_BUS_UART]	= &bus_apb1_r_uart_clk.common.hw,
231 		[CLK_R_APB1_BUS_I2C0]	= &bus_r_apb1_i2c0_clk.common.hw,
232 		[CLK_R_APB1_BUS_I2C1]	= &bus_r_apb1_i2c1_clk.common.hw,
233 		[CLK_R_APB1_BUS_PPU]	= &bus_r_apb1_ppu_clk.common.hw,
234 		[CLK_R_APB1_BUS_TZMA]	= &bus_r_apb1_bus_tzma_clk.common.hw,
235 		[CLK_R_CPUS_BUS_BIST]	= &bus_r_cpus_bist_clk.common.hw,
236 		[CLK_R_APB0_IR]		= &r_apb0_ir_clk.common.hw,
237 		[CLK_R_APB0_BUS_IR]	= &bus_r_apb0_ir_clk.common.hw,
238 		[CLK_R_AHB_BUS_RTC]	= &bus_r_ahb_rtc_clk.common.hw,
239 		[CLK_R_AHB_BUS_CPUCFG]	= &bus_r_ahb_cpucfg_clk.common.hw,
240 	},
241 	.num	= CLK_NUMBER,
242 };
243 
244 static struct ccu_reset_map sun50iw12_r_ccu_resets[] = {
245 	[RST_R_APB0_BUS_TIMER0]	=  { 0x11c, BIT(16) },
246 	[RST_R_APB0_BUS_EDID]	=  { 0x120, BIT(16) },
247 	[RST_R_APB0_BUS_PWM]	=  { 0x13c, BIT(16) },
248 	[RST_R_APB1_BUS_UART0]	=  { 0x18c, BIT(16) },
249 	[RST_R_APB1_BUS_I2C0]	=  { 0x19c, BIT(16) },
250 	[RST_R_APB1_BUS_I2C1]	=  { 0x19c, BIT(17) },
251 	[RST_R_APB1_BUS_PPU]	=  { 0x1ac, BIT(16) },
252 	[RST_R_APB0_BUS_IR_RX]	=  { 0x1cc, BIT(16) },
253 	[RST_R_AHB_BUS_RTC]	=  { 0x20c, BIT(16) },
254 	[RST_R_AHB_BUS_CPUCFG]	=  { 0x22c, BIT(16) },
255 	[RST_R_MODULE]		=  { 0x260, BIT(0) },
256 };
257 
258 static const struct sunxi_ccu_desc sun50iw12_r_ccu_desc = {
259 	.ccu_clks	= sun50iw12_r_ccu_clks,
260 	.num_ccu_clks	= ARRAY_SIZE(sun50iw12_r_ccu_clks),
261 
262 	.hw_clks	= &sun50iw12_r_hw_clks,
263 
264 	.resets		= sun50iw12_r_ccu_resets,
265 	.num_resets	= ARRAY_SIZE(sun50iw12_r_ccu_resets),
266 };
267 
of_sun50iw12_r_ccu_init(struct device_node * node)268 static void __init of_sun50iw12_r_ccu_init(struct device_node *node)
269 {
270 	void __iomem *reg;
271 	int ret;
272 
273 	reg = of_iomap(node, 0);
274 	if (IS_ERR(reg))
275 		return;
276 
277 	ret = sunxi_ccu_probe(node, reg, &sun50iw12_r_ccu_desc);
278 	if (ret)
279 		return;
280 
281 	sunxi_ccu_sleep_init(reg, sun50iw12_r_ccu_clks,
282 			     ARRAY_SIZE(sun50iw12_r_ccu_clks),
283 			     NULL, 0);
284 }
285 
286 CLK_OF_DECLARE(sun50iw12_r_ccu_init, "allwinner,sun50iw12-r-ccu", of_sun50iw12_r_ccu_init);
287