xref: /netbsd-src/sys/arch/arm/samsung/exynos5410_clock.c (revision 6e54367a22fbc89a1139d033e95bec0c0cf0975b)
1 /* $NetBSD: exynos5410_clock.c,v 1.7 2021/01/27 03:10:19 thorpej Exp $ */
2 
3 /*-
4  * Copyright (c) 2015-2017 Jared McNeill <jmcneill@invisible.ca>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: exynos5410_clock.c,v 1.7 2021/01/27 03:10:19 thorpej Exp $");
31 
32 #include <sys/param.h>
33 #include <sys/bus.h>
34 #include <sys/device.h>
35 #include <sys/intr.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/atomic.h>
39 
40 #include <dev/clk/clk_backend.h>
41 
42 #include <arm/samsung/exynos_reg.h>
43 #include <arm/samsung/exynos_var.h>
44 #include <arm/samsung/exynos_clock.h>
45 
46 #include <dev/fdt/fdtvar.h>
47 
48 static struct clk *exynos5410_clock_decode(device_t, int, const void *, size_t);
49 
50 static const struct fdtbus_clock_controller_func exynos5410_car_fdtclock_funcs = {
51 	.decode = exynos5410_clock_decode
52 };
53 
54 /* DT clock ID to clock name mappings */
55 static struct exynos5410_clock_id {
56 	u_int		id;
57 	const char	*name;
58 } exynos5410_clock_ids[] = {
59     /* core clocks */
60     { 1, "fin_pll" },
61     { 2, "fout_apll" },
62     { 3, "fout_cpll" },
63     { 4, "fout_dpll" },
64     { 5, "fout_mpll" },
65     { 6, "fout_kpll" },
66     { 7, "fout_epll" },
67 
68     /* gate for special clocks (sclk) */
69     { 128, "sclk_uart0" },
70     { 129, "sclk_uart1" },
71     { 130, "sclk_uart2" },
72     { 131, "sclk_uart3" },
73     { 132, "sclk_mmc0" },
74     { 133, "sclk_mmc1" },
75     { 134, "sclk_mmc2" },
76     { 150, "sclk_usbd300" },
77     { 151, "sclk_usbd301" },
78     { 152, "sclk_usbphy300" },
79     { 153, "sclk_usbphy301" },
80     { 155, "sclk_pwm" },
81 
82     /* gate clocks */
83     { 257, "uart0" },
84     { 258, "uart1" },
85     { 259, "uart2" },
86     { 260, "uart3" },
87     { 261, "i2c0" },
88     { 262, "i2c1" },
89     { 263, "i2c2" },
90     { 264, "i2c3" },
91     { 265, "usi0" },
92     { 266, "usi1" },
93     { 267, "usi2" },
94     { 268, "usi3" },
95     { 279, "pwm" },
96     { 315, "mct" },
97     { 316, "wdt" },
98     { 317, "rtc" },
99     { 318, "tmu" },
100     { 351, "mmc0" },
101     { 352, "mmc1" },
102     { 353, "mmc2" },
103     { 362, "pdma0" },
104     { 363, "pdma1" },
105     { 365, "usbh20" },
106     { 366, "usbd300" },
107     { 367, "usbd301" },
108     { 471, "sss" },
109 };
110 
111 static struct clk *exynos5410_clock_get(void *, const char *);
112 static void	exynos5410_clock_put(void *, struct clk *);
113 static u_int	exynos5410_clock_get_rate(void *, struct clk *);
114 static int	exynos5410_clock_set_rate(void *, struct clk *, u_int);
115 static int	exynos5410_clock_enable(void *, struct clk *);
116 static int	exynos5410_clock_disable(void *, struct clk *);
117 static int	exynos5410_clock_set_parent(void *, struct clk *, struct clk *);
118 static struct clk *exynos5410_clock_get_parent(void *, struct clk *);
119 
120 static const struct clk_funcs exynos5410_clock_funcs = {
121 	.get = exynos5410_clock_get,
122 	.put = exynos5410_clock_put,
123 	.get_rate = exynos5410_clock_get_rate,
124 	.set_rate = exynos5410_clock_set_rate,
125 	.enable = exynos5410_clock_enable,
126 	.disable = exynos5410_clock_disable,
127 	.set_parent = exynos5410_clock_set_parent,
128 	.get_parent = exynos5410_clock_get_parent,
129 };
130 
131 #define CLK_FIXED(_name, _rate)	{				\
132 	.base = { .name = (_name) }, .type = EXYNOS_CLK_FIXED,	\
133 	.u = { .fixed = { .rate = (_rate) } }			\
134 }
135 
136 #define CLK_PLL(_name, _parent, _lock, _con0) {			\
137 	.base = { .name = (_name) }, .type = EXYNOS_CLK_PLL,	\
138 	.parent = (_parent),					\
139 	.u = {							\
140 		.pll = {					\
141 			.lock_reg = (_lock),			\
142 			.con0_reg = (_con0),			\
143 		}						\
144 	}							\
145 }
146 
147 #define CLK_MUXF(_name, _alias, _reg, _bits, _f, _p) {		\
148 	.base = { .name = (_name), .flags = (_f) },		\
149 	.type = EXYNOS_CLK_MUX,					\
150 	.alias = (_alias),					\
151 	.u = {							\
152 		.mux = {					\
153 	  		.nparents = __arraycount(_p),		\
154 	  		.parents = (_p),			\
155 			.reg = (_reg),				\
156 			.bits = (_bits)				\
157 		}						\
158 	}							\
159 }
160 
161 #define CLK_MUXA(_name, _alias, _reg, _bits, _p)		\
162 	CLK_MUXF(_name, _alias, _reg, _bits, 0, _p)
163 
164 #define CLK_MUX(_name, _reg, _bits, _p)				\
165 	CLK_MUXF(_name, NULL, _reg, _bits, 0, _p)
166 
167 #define CLK_DIVF(_name, _parent, _reg, _bits, _f) {		\
168 	.base = { .name = (_name), .flags = (_f) },		\
169 	.type = EXYNOS_CLK_DIV,					\
170 	.parent = (_parent),					\
171 	.u = {							\
172 		.div = {					\
173 			.reg = (_reg),				\
174 			.bits = (_bits)				\
175 		}						\
176 	}							\
177 }
178 
179 #define CLK_DIV(_name, _parent, _reg, _bits)			\
180 	CLK_DIVF(_name, _parent, _reg, _bits, 0)
181 
182 #define CLK_GATE(_name, _parent, _reg, _bits, _f) {		\
183 	.base = { .name = (_name), .flags = (_f) },		\
184 	.type = EXYNOS_CLK_GATE,				\
185 	.parent = (_parent),					\
186 	.u = {							\
187 		.gate = {					\
188 			.reg = (_reg),				\
189 			.bits = (_bits)				\
190 		}						\
191 	}							\
192 }
193 
194 #define EXYNOS5410_APLL_LOCK		0x00000
195 #define EXYNOS5410_APLL_CON0		0x00100
196 #define EXYNOS5410_MPLL_LOCK		0x04000
197 #define EXYNOS5410_MPLL_CON0		0x04100
198 #define EXYNOS5410_CPLL_LOCK		0x10020
199 #define EXYNOS5410_EPLL_LOCK		0x10040
200 #define EXYNOS5410_CPLL_CON0		0x10120
201 #define EXYNOS5410_EPLL_CON0		0x10130
202 #define EXYNOS5410_EPLL_CON1		0x10134
203 #define EXYNOS5410_EPLL_CON2		0x10138
204 #define EXYNOS5410_BPLL_LOCK		0x20010
205 #define EXYNOS5410_BPLL_CON0		0x20110
206 #define EXYNOS5410_KPLL_LOCK		0x28000
207 #define EXYNOS5410_KPLL_CON0		0x28100
208 
209 #define EXYNOS5410_SRC_CPU		0x00200
210 #define EXYNOS5410_SRC_CPERI1		0x04204
211 #define EXYNOS5410_SRC_TOP0		0x10210
212 #define EXYNOS5410_SRC_TOP1		0x10214
213 #define EXYNOS5410_SRC_TOP2		0x10218
214 #define EXYNOS5410_SRC_FSYS		0x10244
215 #define EXYNOS5410_SRC_PERIC0		0x10250
216 #define EXYNOS5410_SRC_MASK_FSYS	0x10340
217 #define EXYNOS5410_SRC_MASK_PERIC0	0x10350
218 #define EXYNOS5410_SRC_CDREX		0x20200
219 #define EXYNOS5410_SRC_KFC		0x28200
220 
221 #define EXYNOS5410_DIV_CPU0		0x00500
222 #define EXYNOS5410_DIV_TOP0		0x10510
223 #define EXYNOS5410_DIV_TOP1		0x10514
224 #define EXYNOS5410_DIV_FSYS0		0x10548
225 #define EXYNOS5410_DIV_FSYS1		0x1054c
226 #define EXYNOS5410_DIV_FSYS2		0x10550
227 #define EXYNOS5410_DIV_PERIC0		0x10558
228 #define EXYNOS5410_DIV_PERIC3		0x10564
229 #define EXYNOS5410_DIV_KFC0		0x28500
230 
231 #define EXYNOS5410_GATE_IP_G2D		0x08800
232 #define EXYNOS5410_GATE_BUS_FSYS0	0x10740
233 #define EXYNOS5410_GATE_TOP_SCLK_FSYS	0x10840
234 #define EXYNOS5410_GATE_TOP_SCLK_PERIC	0x10850
235 #define EXYNOS5410_GATE_IP_FSYS		0x10944
236 #define EXYNOS5410_GATE_IP_PERIC	0x10950
237 #define EXYNOS5410_GATE_IP_PERIS	0x10960
238 
239 static const char *mout_apll_p[] = { "fin_pll", "fout_apll" };
240 static const char *mout_bpll_p[] = { "fin_pll", "fout_bpll" };
241 static const char *mout_cpll_p[] = { "fin_pll", "fout_cpll" };
242 static const char *mout_epll_p[] = { "fin_pll", "fout_epll" };
243 static const char *mout_mpll_p[] = { "fin_pll", "fout_mpll" };
244 static const char *mout_kpll_p[] = { "fin_pll", "fout_kpll" };
245 
246 static const char *mout_cpu_p[] = { "mout_apll", "sclk_mpll" };
247 static const char *mout_kfc_p[] = { "mout_kpll", "sclk_mpll" };
248 
249 static const char *mout_mpll_user_p[] = { "fin_pll", "sclk_mpll" };
250 static const char *mout_bpll_user_p[] = { "fin_pll", "sclk_bpll" };
251 static const char *mout_mpll_bpll_p[] =
252 	{ "sclk_mpll_muxed", "sclk_bpll_muxed" };
253 static const char *mout_sclk_mpll_bpll_p[] = { "sclk_mpll_bpll", "fin_pll" };
254 
255 static const char *mout_group2_p[] =
256 	{ "fin_pll", "fin_pll", "none", "none", "none", "none",
257 	  "sclk_mpll_bpll", "none", "none", "sclk_cpll" };
258 
259 static struct exynos_clk exynos5410_clocks[] = {
260 	CLK_FIXED("fin_pll", EXYNOS_F_IN_FREQ),
261 
262 	CLK_PLL("fout_apll", "fin_pll", EXYNOS5410_APLL_LOCK,
263 					EXYNOS5410_APLL_CON0),
264 	CLK_PLL("fout_bpll", "fin_pll", EXYNOS5410_BPLL_LOCK,
265 					EXYNOS5410_BPLL_CON0),
266 	CLK_PLL("fout_cpll", "fin_pll", EXYNOS5410_CPLL_LOCK,
267 					EXYNOS5410_CPLL_CON0),
268 	CLK_PLL("fout_epll", "fin_pll", EXYNOS5410_EPLL_LOCK,
269 					EXYNOS5410_EPLL_CON0),
270 	CLK_PLL("fout_mpll", "fin_pll", EXYNOS5410_MPLL_LOCK,
271 					EXYNOS5410_MPLL_CON0),
272 	CLK_PLL("fout_kpll", "fin_pll", EXYNOS5410_KPLL_LOCK,
273 					EXYNOS5410_KPLL_CON0),
274 
275 	CLK_MUX("mout_apll", EXYNOS5410_SRC_CPU, __BIT(0), mout_apll_p),
276 	CLK_MUX("mout_cpu", EXYNOS5410_SRC_CPU, __BIT(16), mout_cpu_p),
277 	CLK_MUX("mout_kpll", EXYNOS5410_SRC_KFC, __BIT(0), mout_kpll_p),
278 	CLK_MUX("mout_kfc", EXYNOS5410_SRC_KFC, __BIT(16), mout_kfc_p),
279 
280 	CLK_MUX("sclk_mpll", EXYNOS5410_SRC_CPERI1, __BIT(8), mout_mpll_p),
281 	CLK_MUX("sclk_mpll_muxed", EXYNOS5410_SRC_TOP2, __BIT(20), mout_mpll_user_p),
282 	CLK_MUX("sclk_bpll", EXYNOS5410_SRC_CDREX, __BIT(0), mout_bpll_p),
283 	CLK_MUX("sclk_bpll_muxed", EXYNOS5410_SRC_TOP2, __BIT(24), mout_bpll_user_p),
284 	CLK_MUX("sclk_epll", EXYNOS5410_SRC_TOP2, __BIT(12), mout_epll_p),
285 	CLK_MUX("sclk_cpll", EXYNOS5410_SRC_TOP2, __BIT(8), mout_cpll_p),
286 	CLK_MUX("sclk_mpll_bpll", EXYNOS5410_SRC_TOP1, __BIT(20), mout_mpll_bpll_p),
287 
288 	CLK_MUX("mout_mmc0", EXYNOS5410_SRC_FSYS, __BITS(3,0), mout_group2_p),
289 	CLK_MUX("mout_mmc1", EXYNOS5410_SRC_FSYS, __BITS(7,4), mout_group2_p),
290 	CLK_MUX("mout_mmc2", EXYNOS5410_SRC_FSYS, __BITS(11,8), mout_group2_p),
291 	CLK_MUX("mout_usbd300", EXYNOS5410_SRC_FSYS, __BIT(28), mout_sclk_mpll_bpll_p),
292 	CLK_MUX("mout_usbd301", EXYNOS5410_SRC_FSYS, __BIT(29), mout_sclk_mpll_bpll_p),
293 	CLK_MUX("mout_uart0", EXYNOS5410_SRC_PERIC0, __BITS(3,0), mout_group2_p),
294 	CLK_MUX("mout_uart1", EXYNOS5410_SRC_PERIC0, __BITS(7,4), mout_group2_p),
295 	CLK_MUX("mout_uart2", EXYNOS5410_SRC_PERIC0, __BITS(11,8), mout_group2_p),
296 	CLK_MUX("mout_uart3", EXYNOS5410_SRC_PERIC0, __BITS(15,12), mout_group2_p),
297 	CLK_MUX("mout_pwm", EXYNOS5410_SRC_PERIC0, __BITS(27,24), mout_group2_p),
298 	CLK_MUX("mout_aclk200", EXYNOS5410_SRC_TOP0, __BIT(12), mout_mpll_bpll_p),
299 	CLK_MUX("mout_aclk400", EXYNOS5410_SRC_TOP0, __BIT(20), mout_mpll_bpll_p),
300 
301 	CLK_DIV("div_arm", "mout_cpu", EXYNOS5410_DIV_CPU0, __BITS(2,0)),
302 	CLK_DIV("div_arm2", "div_arm", EXYNOS5410_DIV_CPU0, __BITS(30,28)),
303 
304 	CLK_DIV("div_acp", "div_arm2", EXYNOS5410_DIV_CPU0, __BITS(10,8)),
305 	CLK_DIV("div_cpud", "div_arm2", EXYNOS5410_DIV_CPU0, __BITS(6,4)),
306 	CLK_DIV("div_atb", "div_arm2", EXYNOS5410_DIV_CPU0, __BITS(18,16)),
307 	CLK_DIV("pclk_dbg", "div_arm2", EXYNOS5410_DIV_CPU0, __BITS(22,20)),
308 
309 	CLK_DIV("div_kfc", "mout_kfc", EXYNOS5410_DIV_KFC0, __BITS(2,0)),
310 	CLK_DIV("div_aclk", "div_kfc", EXYNOS5410_DIV_KFC0, __BITS(6,4)),
311 	CLK_DIV("div_pclk", "div_kfc", EXYNOS5410_DIV_KFC0, __BITS(22,20)),
312 
313 	CLK_DIV("aclk66_pre", "sclk_mpll_muxed", EXYNOS5410_DIV_TOP1, __BITS(26,24)),
314 	CLK_DIV("aclk66", "aclk66_pre", EXYNOS5410_DIV_TOP0, __BITS(2,0)),
315 
316 	CLK_DIV("dout_usbphy300", "mout_usbd300", EXYNOS5410_DIV_FSYS0, __BITS(19,16)),
317 	CLK_DIV("dout_usbphy301", "mout_usbd301", EXYNOS5410_DIV_FSYS0, __BITS(23,20)),
318 	CLK_DIV("dout_usbd300", "mout_usbd300", EXYNOS5410_DIV_FSYS0, __BITS(27,24)),
319 	CLK_DIV("dout_usbd301", "mout_usbd301", EXYNOS5410_DIV_FSYS0, __BITS(31,28)),
320 
321 	CLK_DIV("dout_mmc0", "mout_mmc0", EXYNOS5410_DIV_FSYS1, __BITS(3,0)),
322 	CLK_DIV("dout_mmc1", "mout_mmc1", EXYNOS5410_DIV_FSYS1, __BITS(19,16)),
323 	CLK_DIV("dout_mmc2", "mout_mmc2", EXYNOS5410_DIV_FSYS2, __BITS(3,0)),
324 
325 	CLK_DIVF("dout_mmc_pre0", "dout_mmc0", EXYNOS5410_DIV_FSYS1, __BITS(15,8),
326 	    CLK_SET_RATE_PARENT),
327 	CLK_DIVF("dout_mmc_pre1", "dout_mmc1", EXYNOS5410_DIV_FSYS1, __BITS(31,24),
328 	    CLK_SET_RATE_PARENT),
329 	CLK_DIVF("dout_mmc_pre2", "dout_mmc2", EXYNOS5410_DIV_FSYS2, __BITS(15,8),
330 	    CLK_SET_RATE_PARENT),
331 
332 	CLK_DIV("div_uart0", "mout_uart0", EXYNOS5410_DIV_PERIC0, __BITS(3,0)),
333 	CLK_DIV("div_uart1", "mout_uart1", EXYNOS5410_DIV_PERIC0, __BITS(7,4)),
334 	CLK_DIV("div_uart2", "mout_uart2", EXYNOS5410_DIV_PERIC0, __BITS(11,8)),
335 	CLK_DIV("div_uart3", "mout_uart3", EXYNOS5410_DIV_PERIC0, __BITS(15,12)),
336 
337 	CLK_DIV("dout_pwm", "mout_pwm", EXYNOS5410_DIV_PERIC3, __BITS(3,0)),
338 
339 	CLK_DIV("aclk200", "mout_aclk200", EXYNOS5410_DIV_TOP0, __BITS(14,12)),
340 	CLK_DIV("aclk266", "sclk_mpll_muxed", EXYNOS5410_DIV_TOP0, __BITS(18,16)),
341 	CLK_DIV("aclk400", "mout_aclk400", EXYNOS5410_DIV_TOP0, __BITS(26,24)),
342 
343 	CLK_GATE("sss", "aclk266", EXYNOS5410_GATE_IP_G2D, __BIT(2), 0),
344 
345 	CLK_GATE("mct", "aclk66", EXYNOS5410_GATE_IP_PERIS, __BIT(18), 0),
346 	CLK_GATE("wdt", "aclk66", EXYNOS5410_GATE_IP_PERIS, __BIT(19), 0),
347 	CLK_GATE("rtc", "aclk66", EXYNOS5410_GATE_IP_PERIS, __BIT(20), 0),
348 	CLK_GATE("tmu", "aclk66", EXYNOS5410_GATE_IP_PERIS, __BIT(21), 0),
349 
350 	CLK_GATE("sclk_mmc0", "dout_mmc_pre0", EXYNOS5410_SRC_MASK_FSYS,
351 	    __BIT(0), CLK_SET_RATE_PARENT),
352 	CLK_GATE("sclk_mmc1", "dout_mmc_pre1", EXYNOS5410_SRC_MASK_FSYS,
353 	    __BIT(4), CLK_SET_RATE_PARENT),
354 	CLK_GATE("sclk_mmc2", "dout_mmc_pre2", EXYNOS5410_SRC_MASK_FSYS,
355 	    __BIT(8), CLK_SET_RATE_PARENT),
356 
357 	CLK_GATE("mmc0", "aclk200", EXYNOS5410_GATE_BUS_FSYS0, __BIT(12), 0),
358 	CLK_GATE("mmc1", "aclk200", EXYNOS5410_GATE_BUS_FSYS0, __BIT(13), 0),
359 	CLK_GATE("mmc2", "aclk200", EXYNOS5410_GATE_BUS_FSYS0, __BIT(14), 0),
360 	CLK_GATE("pdma1", "aclk200", EXYNOS5410_GATE_BUS_FSYS0, __BIT(2), 0),
361 	CLK_GATE("pdma0", "aclk200", EXYNOS5410_GATE_BUS_FSYS0, __BIT(1), 0),
362 
363 	CLK_GATE("sclk_usbphy301", "dout_usbphy301", EXYNOS5410_GATE_TOP_SCLK_FSYS,
364 	    __BIT(7), CLK_SET_RATE_PARENT),
365 	CLK_GATE("sclk_usbphy300", "dout_usbphy300", EXYNOS5410_GATE_TOP_SCLK_FSYS,
366 	    __BIT(8), CLK_SET_RATE_PARENT),
367 	CLK_GATE("sclk_usbd301", "dout_usbd301", EXYNOS5410_GATE_TOP_SCLK_FSYS,
368 	    __BIT(9), CLK_SET_RATE_PARENT),
369 	CLK_GATE("sclk_usbd301", "dout_usbd301", EXYNOS5410_GATE_TOP_SCLK_FSYS,
370 	    __BIT(10), CLK_SET_RATE_PARENT),
371 
372 	CLK_GATE("sclk_pwm", "dout_pwm", EXYNOS5410_GATE_TOP_SCLK_PERIC,
373 	    __BIT(11), CLK_SET_RATE_PARENT),
374 
375 	CLK_GATE("uart0", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(0), 0),
376 	CLK_GATE("uart1", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(1), 0),
377 	CLK_GATE("uart2", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(2), 0),
378 	CLK_GATE("uart3", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(3), 0),
379 	CLK_GATE("i2c0", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(6), 0),
380 	CLK_GATE("i2c1", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(7), 0),
381 	CLK_GATE("i2c2", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(8), 0),
382 	CLK_GATE("i2c3", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(9), 0),
383 	CLK_GATE("usi0", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(10), 0),
384 	CLK_GATE("usi1", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(11), 0),
385 	CLK_GATE("usi2", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(12), 0),
386 	CLK_GATE("usi3", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(13), 0),
387 	CLK_GATE("pwm", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(24), 0),
388 
389 	CLK_GATE("sclk_uart0", "div_uart0", EXYNOS5410_SRC_MASK_PERIC0,
390 	    __BIT(0), CLK_SET_RATE_PARENT),
391 	CLK_GATE("sclk_uart1", "div_uart1", EXYNOS5410_SRC_MASK_PERIC0,
392 	    __BIT(4), CLK_SET_RATE_PARENT),
393 	CLK_GATE("sclk_uart2", "div_uart2", EXYNOS5410_SRC_MASK_PERIC0,
394 	    __BIT(8), CLK_SET_RATE_PARENT),
395 	CLK_GATE("sclk_uart3", "div_uart3", EXYNOS5410_SRC_MASK_PERIC0,
396 	    __BIT(12), CLK_SET_RATE_PARENT),
397 
398 	CLK_GATE("usbh20", "aclk200", EXYNOS5410_GATE_IP_FSYS, __BIT(18), 0),
399 	CLK_GATE("usbd301", "aclk200", EXYNOS5410_GATE_IP_FSYS, __BIT(19), 0),
400 	CLK_GATE("usbd300", "aclk200", EXYNOS5410_GATE_IP_FSYS, __BIT(20), 0),
401 };
402 
403 static int	exynos5410_clock_match(device_t, cfdata_t, void *);
404 static void	exynos5410_clock_attach(device_t, device_t, void *);
405 
406 struct exynos5410_clock_softc {
407 	device_t		sc_dev;
408 	bus_space_tag_t		sc_bst;
409 	bus_space_handle_t	sc_bsh;
410 
411 	struct clk_domain	sc_clkdom;
412 };
413 
414 static void	exynos5410_clock_print_header(void);
415 static void	exynos5410_clock_print(struct exynos5410_clock_softc *,
416 		    struct exynos_clk *);
417 
418 CFATTACH_DECL_NEW(exynos5410_clock, sizeof(struct exynos5410_clock_softc),
419 	exynos5410_clock_match, exynos5410_clock_attach, NULL, NULL);
420 
421 #define CLOCK_READ(sc, reg)		\
422     bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
423 #define CLOCK_WRITE(sc, reg, val)	\
424     bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
425 
426 static const struct device_compatible_entry compat_data[] = {
427 	{ .compat = "samsung,exynos5410-clock" },
428 	DEVICE_COMPAT_EOL
429 };
430 
431 static int
exynos5410_clock_match(device_t parent,cfdata_t cf,void * aux)432 exynos5410_clock_match(device_t parent, cfdata_t cf, void *aux)
433 {
434 	struct fdt_attach_args * const faa = aux;
435 
436 	return of_compatible_match(faa->faa_phandle, compat_data);
437 }
438 
439 static void
exynos5410_clock_attach(device_t parent,device_t self,void * aux)440 exynos5410_clock_attach(device_t parent, device_t self, void *aux)
441 {
442 	struct exynos5410_clock_softc * const sc = device_private(self);
443 	struct fdt_attach_args * const faa = aux;
444 	bus_addr_t addr;
445 	bus_size_t size;
446 	int error;
447 
448 	if (fdtbus_get_reg(faa->faa_phandle, 0, &addr, &size) != 0) {
449 		aprint_error(": couldn't get registers\n");
450 		return;
451 	}
452 
453 	sc->sc_dev = self;
454 	sc->sc_bst = faa->faa_bst;
455 
456 	error = bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh);
457 	if (error) {
458 		aprint_error(": couldn't map %#" PRIxBUSADDR ": %d",
459 			     addr, error);
460 		return;
461 	}
462 
463 	aprint_naive("\n");
464 	aprint_normal(": Exynos5410 Clock Controller\n");
465 
466 	sc->sc_clkdom.funcs = &exynos5410_clock_funcs;
467 	sc->sc_clkdom.priv = sc;
468 	for (u_int n = 0; n < __arraycount(exynos5410_clocks); n++) {
469 		exynos5410_clocks[n].base.domain = &sc->sc_clkdom;
470 	}
471 
472 	fdtbus_register_clock_controller(self, faa->faa_phandle,
473 	    &exynos5410_car_fdtclock_funcs);
474 
475 	exynos5410_clock_print_header();
476 	for (u_int n = 0; n < __arraycount(exynos5410_clocks); n++) {
477 		exynos5410_clock_print(sc, &exynos5410_clocks[n]);
478 	}
479 }
480 
481 static struct exynos_clk *
exynos5410_clock_find(const char * name)482 exynos5410_clock_find(const char *name)
483 {
484 	u_int n;
485 
486 	for (n = 0; n < __arraycount(exynos5410_clocks); n++) {
487 		if (strcmp(exynos5410_clocks[n].base.name, name) == 0) {
488 			return &exynos5410_clocks[n];
489 		}
490 	}
491 
492 	return NULL;
493 }
494 
495 static struct exynos_clk *
exynos5410_clock_find_by_id(u_int clock_id)496 exynos5410_clock_find_by_id(u_int clock_id)
497 {
498 	u_int n;
499 
500 	for (n = 0; n < __arraycount(exynos5410_clock_ids); n++) {
501 		if (exynos5410_clock_ids[n].id == clock_id) {
502 			const char *name = exynos5410_clock_ids[n].name;
503 			return exynos5410_clock_find(name);
504 		}
505 	}
506 
507 	return NULL;
508 }
509 
510 static void
exynos5410_clock_print_header(void)511 exynos5410_clock_print_header(void)
512 {
513 	printf("  %-10s %2s %-10s %-5s %10s\n",
514 	    "clock", "", "parent", "type", "rate");
515 	printf("  %-10s %2s %-10s %-5s %10s\n",
516 	    "=====", "", "======", "====", "====");
517 }
518 
519 static void
exynos5410_clock_print(struct exynos5410_clock_softc * sc,struct exynos_clk * eclk)520 exynos5410_clock_print(struct exynos5410_clock_softc *sc,
521     struct exynos_clk *eclk)
522 {
523 	struct exynos_clk *eclk_parent;
524 	struct clk *clk_parent;
525 	const char *type = "?";
526 
527 	switch (eclk->type) {
528 	case EXYNOS_CLK_FIXED:
529 		type = "fixed";
530 		break;
531 	case EXYNOS_CLK_PLL:
532 		type = "pll";
533 		break;
534 	case EXYNOS_CLK_MUX:
535 		type = "mux";
536 		break;
537 	case EXYNOS_CLK_DIV:
538 		type = "div";
539 		break;
540 	case EXYNOS_CLK_GATE:
541 		type = "gate";
542 		break;
543 	}
544 
545 	clk_parent = exynos5410_clock_get_parent(sc, &eclk->base);
546 	eclk_parent = (struct exynos_clk *)clk_parent;
547 
548 	printf("  %-10s %2s %-10s %-5s %10d Hz\n",
549 	    eclk->base.name,
550 	    eclk_parent ? "<-" : "",
551 	    eclk_parent ? eclk_parent->base.name : "",
552 	    type, clk_get_rate(&eclk->base));
553 }
554 
555 static struct clk *
exynos5410_clock_decode(device_t dev,int cc_phandle,const void * data,size_t len)556 exynos5410_clock_decode(device_t dev, int cc_phandle, const void *data,
557 			size_t len)
558 {
559 	struct exynos_clk *eclk;
560 
561 	/* #clock-cells should be 1 */
562 	if (len != 4) {
563 		return NULL;
564 	}
565 
566 	const u_int clock_id = be32dec(data);
567 
568 	eclk = exynos5410_clock_find_by_id(clock_id);
569 	if (eclk)
570 		return &eclk->base;
571 
572 	return NULL;
573 }
574 
575 static u_int
exynos5410_clock_get_rate_pll(struct exynos5410_clock_softc * sc,struct exynos_clk * eclk)576 exynos5410_clock_get_rate_pll(struct exynos5410_clock_softc *sc,
577     struct exynos_clk *eclk)
578 {
579 	struct exynos_pll_clk *epll = &eclk->u.pll;
580 	struct exynos_clk *clk_parent;
581 
582 	KASSERT(eclk->type == EXYNOS_CLK_PLL);
583 
584 	clk_parent = exynos5410_clock_find(eclk->parent);
585 	KASSERT(clk_parent != NULL);
586 	const u_int rate_parent = exynos5410_clock_get_rate(sc,
587 	    &clk_parent->base);
588 
589 	const uint32_t v = CLOCK_READ(sc, epll->con0_reg);
590 
591 	return PLL_FREQ(rate_parent, v);
592 }
593 
594 static int
exynos5410_clock_set_rate_pll(struct exynos5410_clock_softc * sc,struct exynos_clk * eclk,u_int rate)595 exynos5410_clock_set_rate_pll(struct exynos5410_clock_softc *sc,
596     struct exynos_clk *eclk, u_int rate)
597 {
598 	/* TODO */
599 	return EOPNOTSUPP;
600 }
601 
602 static int
exynos5410_clock_set_parent_mux(struct exynos5410_clock_softc * sc,struct exynos_clk * eclk,struct exynos_clk * eclk_parent)603 exynos5410_clock_set_parent_mux(struct exynos5410_clock_softc *sc,
604     struct exynos_clk *eclk, struct exynos_clk *eclk_parent)
605 {
606 	struct exynos_mux_clk *emux = &eclk->u.mux;
607 	const char *pname = eclk_parent->base.name;
608 	u_int sel;
609 
610 	KASSERT(eclk->type == EXYNOS_CLK_MUX);
611 
612 	for (sel = 0; sel < emux->nparents; sel++) {
613 		if (strcmp(pname, emux->parents[sel]) == 0) {
614 			break;
615 		}
616 	}
617 	if (sel == emux->nparents) {
618 		return EINVAL;
619 	}
620 
621 	uint32_t v = CLOCK_READ(sc, emux->reg);
622 	v &= ~emux->bits;
623 	v |= __SHIFTIN(sel, emux->bits);
624 	CLOCK_WRITE(sc, emux->reg, v);
625 
626 	return 0;
627 }
628 
629 static struct exynos_clk *
exynos5410_clock_get_parent_mux(struct exynos5410_clock_softc * sc,struct exynos_clk * eclk)630 exynos5410_clock_get_parent_mux(struct exynos5410_clock_softc *sc,
631     struct exynos_clk *eclk)
632 {
633 	struct exynos_mux_clk *emux = &eclk->u.mux;
634 
635 	KASSERT(eclk->type == EXYNOS_CLK_MUX);
636 
637 	const uint32_t v = CLOCK_READ(sc, emux->reg);
638 	const u_int sel = __SHIFTOUT(v, emux->bits);
639 
640 	KASSERT(sel < emux->nparents);
641 
642 	return exynos5410_clock_find(emux->parents[sel]);
643 }
644 
645 static u_int
exynos5410_clock_get_rate_div(struct exynos5410_clock_softc * sc,struct exynos_clk * eclk)646 exynos5410_clock_get_rate_div(struct exynos5410_clock_softc *sc,
647     struct exynos_clk *eclk)
648 {
649 	struct exynos_div_clk *ediv = &eclk->u.div;
650 	struct clk *clk_parent;
651 
652 	KASSERT(eclk->type == EXYNOS_CLK_DIV);
653 
654 	clk_parent = exynos5410_clock_get_parent(sc, &eclk->base);
655 	const u_int parent_rate = exynos5410_clock_get_rate(sc, clk_parent);
656 
657 	const uint32_t v = CLOCK_READ(sc, ediv->reg);
658 	const u_int div = __SHIFTOUT(v, ediv->bits);
659 
660 	return parent_rate / (div + 1);
661 }
662 
663 static int
exynos5410_clock_set_rate_div(struct exynos5410_clock_softc * sc,struct exynos_clk * eclk,u_int rate)664 exynos5410_clock_set_rate_div(struct exynos5410_clock_softc *sc,
665     struct exynos_clk *eclk, u_int rate)
666 {
667 	struct exynos_div_clk *ediv = &eclk->u.div;
668 	struct clk *clk_parent;
669 	int tmp_div, new_div = -1;
670 	u_int tmp_rate;
671 
672 	KASSERT(eclk->type == EXYNOS_CLK_DIV);
673 
674 	clk_parent = exynos5410_clock_get_parent(sc, &eclk->base);
675 	const u_int parent_rate = exynos5410_clock_get_rate(sc, clk_parent);
676 
677 	for (tmp_div = 0; tmp_div < __SHIFTOUT_MASK(ediv->bits); tmp_div++) {
678 		tmp_rate = parent_rate / (tmp_div + 1);
679 		if (tmp_rate <= rate) {
680 			new_div = tmp_div;
681 			break;
682 		}
683 	}
684 	if (new_div == -1)
685 		return EINVAL;
686 
687 	uint32_t v = CLOCK_READ(sc, ediv->reg);
688 	v &= ~ediv->bits;
689 	v |= __SHIFTIN(new_div, ediv->bits);
690 	CLOCK_WRITE(sc, ediv->reg, v);
691 
692 	return 0;
693 }
694 
695 static int
exynos5410_clock_enable_gate(struct exynos5410_clock_softc * sc,struct exynos_clk * eclk,bool enable)696 exynos5410_clock_enable_gate(struct exynos5410_clock_softc *sc,
697     struct exynos_clk *eclk, bool enable)
698 {
699 	struct exynos_gate_clk *egate = &eclk->u.gate;
700 
701 	KASSERT(eclk->type == EXYNOS_CLK_GATE);
702 
703 	uint32_t v = CLOCK_READ(sc, egate->reg);
704 	if (enable) {
705 		v |= egate->bits;
706 	} else {
707 		v &= ~egate->bits;
708 	}
709 	CLOCK_WRITE(sc, egate->reg, v);
710 
711 	return 0;
712 }
713 
714 /*
715  * clk api
716  */
717 
718 static struct clk *
exynos5410_clock_get(void * priv,const char * name)719 exynos5410_clock_get(void *priv, const char *name)
720 {
721 	struct exynos_clk *eclk;
722 
723 	eclk = exynos5410_clock_find(name);
724 	if (eclk == NULL)
725 		return NULL;
726 
727 	atomic_inc_uint(&eclk->refcnt);
728 
729 	return &eclk->base;
730 }
731 
732 static void
exynos5410_clock_put(void * priv,struct clk * clk)733 exynos5410_clock_put(void *priv, struct clk *clk)
734 {
735 	struct exynos_clk *eclk = (struct exynos_clk *)clk;
736 
737 	KASSERT(eclk->refcnt > 0);
738 
739 	atomic_dec_uint(&eclk->refcnt);
740 }
741 
742 static u_int
exynos5410_clock_get_rate(void * priv,struct clk * clk)743 exynos5410_clock_get_rate(void *priv, struct clk *clk)
744 {
745 	struct exynos_clk *eclk = (struct exynos_clk *)clk;
746 	struct clk *clk_parent;
747 
748 	switch (eclk->type) {
749 	case EXYNOS_CLK_FIXED:
750 		return eclk->u.fixed.rate;
751 	case EXYNOS_CLK_PLL:
752 		return exynos5410_clock_get_rate_pll(priv, eclk);
753 	case EXYNOS_CLK_MUX:
754 	case EXYNOS_CLK_GATE:
755 		clk_parent = exynos5410_clock_get_parent(priv, clk);
756 		return exynos5410_clock_get_rate(priv, clk_parent);
757 	case EXYNOS_CLK_DIV:
758 		return exynos5410_clock_get_rate_div(priv, eclk);
759 	default:
760 		panic("exynos5410: unknown eclk type %d", eclk->type);
761 	}
762 }
763 
764 static int
exynos5410_clock_set_rate(void * priv,struct clk * clk,u_int rate)765 exynos5410_clock_set_rate(void *priv, struct clk *clk, u_int rate)
766 {
767 	struct exynos_clk *eclk = (struct exynos_clk *)clk;
768 
769 	KASSERT((clk->flags & CLK_SET_RATE_PARENT) == 0);
770 
771 	switch (eclk->type) {
772 	case EXYNOS_CLK_FIXED:
773 		return EIO;
774 	case EXYNOS_CLK_PLL:
775 		return exynos5410_clock_set_rate_pll(priv, eclk, rate);
776 	case EXYNOS_CLK_MUX:
777 		return EIO;
778 	case EXYNOS_CLK_DIV:
779 		return exynos5410_clock_set_rate_div(priv, eclk, rate);
780 	case EXYNOS_CLK_GATE:
781 		return EINVAL;
782 	default:
783 		panic("exynos5410: unknown eclk type %d", eclk->type);
784 	}
785 }
786 
787 static int
exynos5410_clock_enable(void * priv,struct clk * clk)788 exynos5410_clock_enable(void *priv, struct clk *clk)
789 {
790 	struct exynos_clk *eclk = (struct exynos_clk *)clk;
791 
792 	switch (eclk->type) {
793 	case EXYNOS_CLK_FIXED:
794 		return 0;	/* always on */
795 	case EXYNOS_CLK_PLL:
796 		return 0;	/* XXX */
797 	case EXYNOS_CLK_MUX:
798 	case EXYNOS_CLK_DIV:
799 		return 0;
800 	case EXYNOS_CLK_GATE:
801 		return exynos5410_clock_enable_gate(priv, eclk, true);
802 	default:
803 		panic("exynos5410: unknown eclk type %d", eclk->type);
804 	}
805 }
806 
807 static int
exynos5410_clock_disable(void * priv,struct clk * clk)808 exynos5410_clock_disable(void *priv, struct clk *clk)
809 {
810 	struct exynos_clk *eclk = (struct exynos_clk *)clk;
811 
812 	switch (eclk->type) {
813 	case EXYNOS_CLK_FIXED:
814 		return EINVAL;	/* always on */
815 	case EXYNOS_CLK_PLL:
816 		return EINVAL;	/* XXX */
817 	case EXYNOS_CLK_MUX:
818 	case EXYNOS_CLK_DIV:
819 		return EINVAL;
820 	case EXYNOS_CLK_GATE:
821 		return exynos5410_clock_enable_gate(priv, eclk, false);
822 	default:
823 		panic("exynos5410: unknown eclk type %d", eclk->type);
824 	}
825 }
826 
827 static int
exynos5410_clock_set_parent(void * priv,struct clk * clk,struct clk * clk_parent)828 exynos5410_clock_set_parent(void *priv, struct clk *clk, struct clk *clk_parent)
829 {
830 	struct exynos_clk *eclk = (struct exynos_clk *)clk;
831 	struct exynos_clk *eclk_parent = (struct exynos_clk *)clk_parent;
832 
833 	switch (eclk->type) {
834 	case EXYNOS_CLK_FIXED:
835 	case EXYNOS_CLK_PLL:
836 	case EXYNOS_CLK_DIV:
837 	case EXYNOS_CLK_GATE:
838 		return EINVAL;
839 	case EXYNOS_CLK_MUX:
840 		return exynos5410_clock_set_parent_mux(priv, eclk, eclk_parent);
841 	default:
842 		panic("exynos5410: unknown eclk type %d", eclk->type);
843 	}
844 }
845 
846 static struct clk *
exynos5410_clock_get_parent(void * priv,struct clk * clk)847 exynos5410_clock_get_parent(void *priv, struct clk *clk)
848 {
849 	struct exynos_clk *eclk = (struct exynos_clk *)clk;
850 	struct exynos_clk *eclk_parent = NULL;
851 
852 	switch (eclk->type) {
853 	case EXYNOS_CLK_FIXED:
854 	case EXYNOS_CLK_PLL:
855 	case EXYNOS_CLK_DIV:
856 	case EXYNOS_CLK_GATE:
857 		if (eclk->parent != NULL) {
858 			eclk_parent = exynos5410_clock_find(eclk->parent);
859 		}
860 		break;
861 	case EXYNOS_CLK_MUX:
862 		eclk_parent = exynos5410_clock_get_parent_mux(priv, eclk);
863 		break;
864 	default:
865 		panic("exynos5410: unknown eclk type %d", eclk->type);
866 	}
867 
868 	return (struct clk *)eclk_parent;
869 }
870