]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/mips/ingenic/jz4780_clock.c
Factor-out hardware-independent part of USB HID support to new module
[FreeBSD/FreeBSD.git] / sys / mips / ingenic / jz4780_clock.c
1 /*-
2  * Copyright 2015 Alexander Kabaev <kan@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 /*
28  * Ingenic JZ4780 CGU driver.
29  *
30  */
31
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/conf.h>
38 #include <sys/bus.h>
39 #include <sys/kernel.h>
40 #include <sys/module.h>
41 #include <sys/lock.h>
42 #include <sys/mutex.h>
43 #include <sys/resource.h>
44 #include <sys/rman.h>
45
46 #include <machine/bus.h>
47
48 #include <dev/fdt/fdt_common.h>
49 #include <dev/ofw/ofw_bus.h>
50 #include <dev/ofw/ofw_bus_subr.h>
51
52 #include <mips/ingenic/jz4780_clk.h>
53 #include <mips/ingenic/jz4780_regs.h>
54 #include <mips/ingenic/jz4780_clock.h>
55
56 #include "clkdev_if.h"
57
58 #include <gnu/dts/include/dt-bindings/clock/jz4780-cgu.h>
59
60 /**********************************************************************
61  *  JZ4780 CGU clock domain
62  **********************************************************************/
63 struct jz4780_clock_softc {
64         device_t        dev;
65         struct resource *res[1];
66         struct mtx      mtx;
67         struct clkdom   *clkdom;
68 };
69
70 static struct resource_spec jz4780_clock_spec[] = {
71         { SYS_RES_MEMORY, 0, RF_ACTIVE },
72         { -1, 0 }
73 };
74
75 struct jz4780_clk_pll_def {
76         uint16_t   clk_id;
77         uint16_t   clk_reg;
78         const char *clk_name;
79         const char *clk_pname[1];
80 };
81
82 #define PLL(_id, cname, pname, reg) {           \
83         .clk_id         = _id,                  \
84         .clk_reg        = reg,                  \
85         .clk_name       = cname,                \
86         .clk_pname[0]   = pname,                \
87 }
88
89 struct jz4780_clk_gate_def {
90         uint16_t   clk_id;
91         uint16_t   clk_bit;
92         const char *clk_name;
93         const char *clk_pname[1];
94 };
95
96 #define GATE(_id, cname, pname, bit) {          \
97         .clk_id         = _id,                  \
98         .clk_bit        = bit,                  \
99         .clk_name       = cname,                \
100         .clk_pname[0]   = pname,                \
101 }
102
103 #define MUX(reg, shift, bits, map)                      \
104     .clk_mux.mux_reg = (reg),                           \
105     .clk_mux.mux_shift = (shift),                       \
106     .clk_mux.mux_bits = (bits),                         \
107     .clk_mux.mux_map = (map),
108 #define NO_MUX
109
110 #define DIV(reg, shift, lg, bits, ce, st, bb)           \
111     .clk_div.div_reg = (reg),                           \
112     .clk_div.div_shift = (shift),                       \
113     .clk_div.div_bits = (bits),                         \
114     .clk_div.div_lg = (lg),                             \
115     .clk_div.div_ce_bit = (ce),                         \
116     .clk_div.div_st_bit = (st),                         \
117     .clk_div.div_busy_bit = (bb),
118 #define NO_DIV                                          \
119
120 #define GATEBIT(bit)                                    \
121     .clk_gate_bit = (bit),
122 #define NO_GATE                                         \
123     .clk_gate_bit = (-1),
124
125 #define PLIST(pnames...)                                \
126     .clk_pnames = { pnames },
127
128 #define GENCLK(id, name, type, parents, mux, div, gt) { \
129         .clk_id         = id,                           \
130         .clk_type       = type,                         \
131         .clk_name       = name,                         \
132         parents                                         \
133         mux                                             \
134         div                                             \
135         gt                                              \
136 }
137
138 /* PLL definitions */
139 static struct jz4780_clk_pll_def pll_clks[] = {
140         PLL(JZ4780_CLK_APLL, "apll", "ext", JZ_CPAPCR),
141         PLL(JZ4780_CLK_MPLL, "mpll", "ext", JZ_CPMPCR),
142         PLL(JZ4780_CLK_EPLL, "epll", "ext", JZ_CPEPCR),
143         PLL(JZ4780_CLK_VPLL, "vpll", "ext", JZ_CPVPCR),
144 };
145
146 /* OTG PHY clock (reuse gate def structure */
147 static struct jz4780_clk_gate_def otg_clks[] = {
148         GATE(JZ4780_CLK_OTGPHY, "otg_phy",      "ext", 0),
149 };
150
151 static const struct jz4780_clk_descr gen_clks[] = {
152         GENCLK(JZ4780_CLK_SCLKA, "sclk_a", CLK_MASK_MUX,
153             PLIST("apll", "ext", "rtc"),
154             MUX(JZ_CPCCR, 30, 2, 0x7),
155             NO_DIV,
156             NO_GATE
157         ),
158
159         GENCLK(JZ4780_CLK_CPUMUX, "cpumux", CLK_MASK_MUX,
160             PLIST("sclk_a", "mpll", "epll"),
161             MUX(JZ_CPCCR, 28, 2, 0x7),
162             NO_DIV,
163             NO_GATE
164         ),
165
166         GENCLK(JZ4780_CLK_CPU, "cpu", CLK_MASK_DIV,
167             PLIST("cpumux"),
168             NO_MUX,
169             DIV(JZ_CPCCR, 0, 0, 4, 22, -1, -1),
170             NO_GATE
171         ),
172
173         GENCLK(JZ4780_CLK_L2CACHE, "l2cache", CLK_MASK_DIV,
174             PLIST("cpumux"),
175             NO_MUX,
176             DIV(JZ_CPCCR, 4, 0, 4, -1, -1, -1),
177             NO_GATE
178         ),
179
180         GENCLK(JZ4780_CLK_AHB0, "ahb0", CLK_MASK_MUX | CLK_MASK_DIV,
181             PLIST("sclk_a", "mpll", "epll"),
182             MUX(JZ_CPCCR, 26, 2, 0x7),
183             DIV(JZ_CPCCR, 8, 0, 4, 21, -1, -1),
184             NO_GATE
185         ),
186
187         GENCLK(JZ4780_CLK_AHB2PMUX, "ahb2_apb_mux", CLK_MASK_MUX,
188             PLIST("sclk_a", "mpll", "rtc"),
189             MUX(JZ_CPCCR, 24, 2, 0x7),
190             NO_DIV,
191             NO_GATE
192         ),
193
194         GENCLK(JZ4780_CLK_AHB2, "ahb2", CLK_MASK_DIV,
195             PLIST("ahb2_apb_mux"),
196             NO_MUX,
197             DIV(JZ_CPCCR, 12, 0, 4, 20, -1, -1),
198             NO_GATE
199         ),
200
201         GENCLK(JZ4780_CLK_PCLK, "pclk", CLK_MASK_DIV,
202             PLIST("ahb2_apb_mux"),
203             NO_MUX,
204             DIV(JZ_CPCCR, 16, 0, 4, 20, -1, -1),
205             NO_GATE
206         ),
207
208         GENCLK(JZ4780_CLK_DDR, "ddr", CLK_MASK_MUX | CLK_MASK_DIV,
209             PLIST("sclk_a", "mpll"),
210             MUX(JZ_DDCDR, 30, 2, 0x6),
211             DIV(JZ_DDCDR, 0, 0, 4, 29, 28, 27),
212             NO_GATE
213         ),
214
215         GENCLK(JZ4780_CLK_VPU, "vpu", CLK_MASK_MUX | CLK_MASK_DIV | CLK_MASK_GATE,
216             PLIST("sclk_a", "mpll", "epll"),
217             MUX(JZ_VPUCDR, 30, 2, 0xe),
218             DIV(JZ_VPUCDR, 0, 0, 4, 29, 28, 27),
219             GATEBIT(32 + 2)
220         ),
221
222         GENCLK(JZ4780_CLK_I2SPLL, "i2s_pll", CLK_MASK_MUX | CLK_MASK_DIV,
223             PLIST("sclk_a", "epll"),
224             MUX(JZ_I2SCDR, 30, 1, 0xc),
225             DIV(JZ_I2SCDR, 0, 0, 8, 29, 28, 27),
226             NO_GATE
227         ),
228
229         GENCLK(JZ4780_CLK_I2S, "i2s", CLK_MASK_MUX,
230             PLIST("ext", "i2s_pll"),
231             MUX(JZ_I2SCDR, 31, 1, 0xc),
232             NO_DIV,
233             NO_GATE
234         ),
235
236         GENCLK(JZ4780_CLK_LCD0PIXCLK, "lcd0pixclk", CLK_MASK_MUX | CLK_MASK_DIV,
237             PLIST("sclk_a", "mpll", "vpll"),
238             MUX(JZ_LP0CDR, 30, 2, 0xe),
239             DIV(JZ_LP0CDR, 0, 0, 8, 28, 27, 26),
240             NO_GATE
241         ),
242
243         GENCLK(JZ4780_CLK_LCD1PIXCLK, "lcd1pixclk", CLK_MASK_MUX | CLK_MASK_DIV,
244             PLIST("sclk_a", "mpll", "vpll"),
245             MUX(JZ_LP1CDR, 30, 2, 0xe),
246             DIV(JZ_LP1CDR, 0, 0, 8, 28, 27, 26),
247             NO_GATE
248         ),
249
250         GENCLK(JZ4780_CLK_MSCMUX, "msc_mux", CLK_MASK_MUX,
251             PLIST("sclk_a", "mpll"),
252             MUX(JZ_MSC0CDR, 30, 2, 0x6),
253             NO_DIV,
254             NO_GATE
255         ),
256
257         GENCLK(JZ4780_CLK_MSC0, "msc0", CLK_MASK_DIV | CLK_MASK_GATE,
258             PLIST("msc_mux"),
259             NO_MUX,
260             DIV(JZ_MSC0CDR, 0, 1, 8, 29, 28, 27),
261             GATEBIT(3)
262         ),
263
264         GENCLK(JZ4780_CLK_MSC1, "msc1", CLK_MASK_DIV | CLK_MASK_GATE,
265             PLIST("msc_mux"),
266             NO_MUX,
267             DIV(JZ_MSC1CDR, 0, 1, 8, 29, 28, 27),
268             GATEBIT(11)
269         ),
270
271         GENCLK(JZ4780_CLK_MSC2, "msc2", CLK_MASK_DIV | CLK_MASK_GATE,
272             PLIST("msc_mux"),
273             NO_MUX,
274             DIV(JZ_MSC2CDR, 0, 1, 8, 29, 28, 27),
275             GATEBIT(12)
276         ),
277
278         GENCLK(JZ4780_CLK_UHC, "uhc", CLK_MASK_MUX | CLK_MASK_DIV | CLK_MASK_GATE,
279             PLIST("sclk_a", "mpll", "epll", "otg_phy"),
280             MUX(JZ_UHCCDR, 30, 2, 0xf),
281             DIV(JZ_UHCCDR, 0, 0, 8, 29, 28, 27),
282             GATEBIT(24)
283         ),
284
285         GENCLK(JZ4780_CLK_SSIPLL, "ssi_pll", CLK_MASK_MUX | CLK_MASK_DIV,
286             PLIST("sclk_a", "mpll"),
287             MUX(JZ_SSICDR, 30, 1, 0xc),
288             DIV(JZ_SSICDR, 0, 0, 8, 29, 28, 27),
289             NO_GATE
290         ),
291
292         GENCLK(JZ4780_CLK_SSI, "ssi", CLK_MASK_MUX,
293             PLIST("ext", "ssi_pll"),
294             MUX(JZ_SSICDR, 31, 1, 0xc),
295             NO_DIV,
296             NO_GATE
297         ),
298
299         GENCLK(JZ4780_CLK_CIMMCLK, "cim_mclk", CLK_MASK_MUX | CLK_MASK_DIV,
300             PLIST("sclk_a", "mpll"),
301             MUX(JZ_CIMCDR, 31, 1, 0xc),
302             DIV(JZ_CIMCDR, 0, 0, 8, 30, 29, 28),
303             NO_GATE
304         ),
305
306         GENCLK(JZ4780_CLK_PCMPLL, "pcm_pll", CLK_MASK_MUX | CLK_MASK_DIV,
307             PLIST("sclk_a", "mpll", "epll", "vpll"),
308             MUX(JZ_PCMCDR, 29, 2, 0xf),
309             DIV(JZ_PCMCDR, 0, 0, 8, 28, 27, 26),
310             NO_GATE
311         ),
312
313         GENCLK(JZ4780_CLK_PCM, "pcm", CLK_MASK_MUX | CLK_MASK_GATE,
314             PLIST("ext", "pcm_pll"),
315             MUX(JZ_PCMCDR, 31, 1, 0xc),
316             NO_DIV,
317             GATEBIT(32 + 3)
318         ),
319
320         GENCLK(JZ4780_CLK_GPU, "gpu", CLK_MASK_MUX | CLK_MASK_DIV | CLK_MASK_GATE,
321             PLIST("sclk_a", "mpll", "epll"),
322             MUX(JZ_GPUCDR, 30, 2, 0x7),
323             DIV(JZ_GPUCDR, 0, 0, 4, 29, 28, 27),
324             GATEBIT(32 + 4)
325         ),
326
327         GENCLK(JZ4780_CLK_HDMI, "hdmi", CLK_MASK_MUX | CLK_MASK_DIV | CLK_MASK_GATE,
328             PLIST("sclk_a", "mpll", "vpll"),
329             MUX(JZ_HDMICDR, 30, 2, 0xe),
330             DIV(JZ_HDMICDR, 0, 0, 8, 29, 28, 26),
331             GATEBIT(32 + 9)
332         ),
333
334         GENCLK(JZ4780_CLK_BCH, "bch", CLK_MASK_MUX | CLK_MASK_DIV | CLK_MASK_GATE,
335             PLIST("sclk_a", "mpll", "epll"),
336             MUX(JZ_BCHCDR, 30, 2, 0x7),
337             DIV(JZ_BCHCDR, 0, 0, 4, 29, 28, 27),
338             GATEBIT(1)
339         ),
340 };
341
342 static struct jz4780_clk_gate_def gate_clks[] = {
343         GATE(JZ4780_CLK_NEMC,   "nemc",         "ahb2", 0),
344         GATE(JZ4780_CLK_OTG0,   "otg0",         "ext",  2),
345         GATE(JZ4780_CLK_SSI0,   "ssi0",         "ssi",  4),
346         GATE(JZ4780_CLK_SMB0,   "smb0",         "pclk", 5),
347         GATE(JZ4780_CLK_SMB1,   "smb1",         "pclk", 6),
348         GATE(JZ4780_CLK_SCC,    "scc",          "ext",  7),
349         GATE(JZ4780_CLK_AIC,    "aic",          "ext",  8),
350         GATE(JZ4780_CLK_TSSI0,  "tssi0",        "ext",  9),
351         GATE(JZ4780_CLK_OWI,    "owi",          "ext",  10),
352         GATE(JZ4780_CLK_KBC,    "kbc",          "ext",  13),
353         GATE(JZ4780_CLK_SADC,   "sadc",         "ext",  14),
354         GATE(JZ4780_CLK_UART0,  "uart0",        "ext",  15),
355         GATE(JZ4780_CLK_UART1,  "uart1",        "ext",  16),
356         GATE(JZ4780_CLK_UART2,  "uart2",        "ext",  17),
357         GATE(JZ4780_CLK_UART3,  "uart3",        "ext",  18),
358         GATE(JZ4780_CLK_SSI1,   "ssi1",         "ssi",  19),
359         GATE(JZ4780_CLK_SSI2,   "ssi2",         "ssi",  20),
360         GATE(JZ4780_CLK_PDMA,   "pdma",         "ext",  21),
361         GATE(JZ4780_CLK_GPS,    "gps",          "ext",  22),
362         GATE(JZ4780_CLK_MAC,    "mac",          "ext",  23),
363         GATE(JZ4780_CLK_SMB2,   "smb2",         "pclk", 25),
364         GATE(JZ4780_CLK_CIM,    "cim",          "ext",  26),
365         GATE(JZ4780_CLK_LCD,    "lcd",          "ext",  28),
366         GATE(JZ4780_CLK_TVE,    "tve",          "lcd",  27),
367         GATE(JZ4780_CLK_IPU,    "ipu",          "ext",  29),
368         GATE(JZ4780_CLK_DDR0,   "ddr0",         "ddr",  30),
369         GATE(JZ4780_CLK_DDR1,   "ddr1",         "ddr",  31),
370         GATE(JZ4780_CLK_SMB3,   "smb3",         "pclk", 32 + 0),
371         GATE(JZ4780_CLK_TSSI1,  "tssi1",        "ext",  32 + 1),
372         GATE(JZ4780_CLK_COMPRESS, "compress",   "ext",  32 + 5),
373         GATE(JZ4780_CLK_AIC1,   "aic1",         "ext",  32 + 6),
374         GATE(JZ4780_CLK_GPVLC,  "gpvlc",        "ext",  32 + 7),
375         GATE(JZ4780_CLK_OTG1,   "otg1",         "ext",  32 + 8),
376         GATE(JZ4780_CLK_UART4,  "uart4",        "ext",  32 + 10),
377         GATE(JZ4780_CLK_AHBMON, "ahb_mon",      "ext",  32 + 11),
378         GATE(JZ4780_CLK_SMB4,   "smb4",         "pclk", 32 + 12),
379         GATE(JZ4780_CLK_DES,    "des",          "ext",  32 + 13),
380         GATE(JZ4780_CLK_X2D,    "x2d",          "ext",  32 + 14),
381         GATE(JZ4780_CLK_CORE1,  "core1",        "cpu",  32 + 15),
382 };
383
384 static int
385 jz4780_clock_register(struct jz4780_clock_softc *sc)
386 {
387         int i, ret;
388
389         /* Register PLLs */
390         for (i = 0; i < nitems(pll_clks); i++) {
391                 struct clknode_init_def clkdef;
392
393                 clkdef.id = pll_clks[i].clk_id;
394                 clkdef.name = __DECONST(char *, pll_clks[i].clk_name);
395                 clkdef.parent_names = pll_clks[i].clk_pname;
396                 clkdef.parent_cnt = 1;
397                 clkdef.flags = CLK_NODE_STATIC_STRINGS;
398
399                 ret = jz4780_clk_pll_register(sc->clkdom, &clkdef, &sc->mtx,
400                     sc->res[0], pll_clks[i].clk_reg);
401                 if (ret != 0)
402                         return (ret);
403         }
404
405         /* Register OTG clock */
406         for (i = 0; i < nitems(otg_clks); i++) {
407                 struct clknode_init_def clkdef;
408
409                 clkdef.id = otg_clks[i].clk_id;
410                 clkdef.name = __DECONST(char *, otg_clks[i].clk_name);
411                 clkdef.parent_names = otg_clks[i].clk_pname;
412                 clkdef.parent_cnt = 1;
413                 clkdef.flags = CLK_NODE_STATIC_STRINGS;
414
415                 ret = jz4780_clk_otg_register(sc->clkdom, &clkdef, &sc->mtx,
416                     sc->res[0]);
417                 if (ret != 0)
418                         return (ret);
419         }
420
421         /* Register muxes and divisors */
422         for (i = 0; i < nitems(gen_clks); i++) {
423                 ret = jz4780_clk_gen_register(sc->clkdom, &gen_clks[i],
424                     &sc->mtx, sc->res[0]);
425                 if (ret != 0)
426                         return (ret);
427         }
428
429         /* Register simple gates */
430         for (i = 0; i < nitems(gate_clks); i++) {
431                 struct clk_gate_def gatedef;
432
433                 gatedef.clkdef.id = gate_clks[i].clk_id;
434                 gatedef.clkdef.name = __DECONST(char *, gate_clks[i].clk_name);
435                 gatedef.clkdef.parent_names = gate_clks[i].clk_pname;
436                 gatedef.clkdef.parent_cnt = 1;
437                 gatedef.clkdef.flags = CLK_NODE_STATIC_STRINGS;
438
439                 if (gate_clks[i].clk_bit < 32) {
440                         gatedef.offset = JZ_CLKGR0;
441                         gatedef.shift = gate_clks[i].clk_bit;
442                 } else {
443                         gatedef.offset = JZ_CLKGR1;
444                         gatedef.shift = gate_clks[i].clk_bit - 32;
445                 }
446                 gatedef.mask = 1;
447                 gatedef.on_value = 0;
448                 gatedef.off_value = 1;
449                 gatedef.gate_flags = 0;
450
451                 ret = clknode_gate_register(sc->clkdom, &gatedef);
452                 if (ret != 0)
453                         return (ret);
454         }
455
456         return (0);
457 }
458
459 static int
460 jz4780_clock_fixup(struct jz4780_clock_softc *sc)
461 {
462         struct clknode *clk_uhc;
463         int ret;
464
465         /*
466          * Make UHC mux use MPLL as the source. It defaults to OTG_PHY
467          * and that somehow just does not work.
468          */
469         clkdom_xlock(sc->clkdom);
470
471         /* Assume the worst */
472         ret = ENXIO;
473
474         clk_uhc = clknode_find_by_id(sc->clkdom, JZ4780_CLK_UHC);
475         if (clk_uhc != NULL) {
476                 ret = clknode_set_parent_by_name(clk_uhc, "mpll");
477                 if (ret != 0)
478                         device_printf(sc->dev,
479                             "unable to reparent uhc clock\n");
480                 else
481                         ret = clknode_set_freq(clk_uhc, 48000000, 0, 0);
482                 if (ret != 0)
483                         device_printf(sc->dev, "unable to init uhc clock\n");
484         } else
485                 device_printf(sc->dev, "unable to lookup uhc clock\n");
486
487         clkdom_unlock(sc->clkdom);
488         return (ret);
489 }
490
491 #define CGU_LOCK(sc)            mtx_lock(&(sc)->mtx)
492 #define CGU_UNLOCK(sc)          mtx_unlock(&(sc)->mtx)
493 #define CGU_LOCK_INIT(sc)       \
494     mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev),        \
495     "jz4780-cgu", MTX_DEF)
496 #define CGU_LOCK_DESTROY(sc)    mtx_destroy(&(sc)->mtx);
497
498 #define CSR_WRITE_4(sc, reg, val)       bus_write_4((sc)->res[0], (reg), (val))
499 #define CSR_READ_4(sc, reg)             bus_read_4((sc)->res[0], (reg))
500
501 static int
502 jz4780_clock_probe(device_t dev)
503 {
504
505         if (!ofw_bus_status_okay(dev))
506                 return (ENXIO);
507
508         if (!ofw_bus_is_compatible(dev, "ingenic,jz4780-cgu"))
509                 return (ENXIO);
510
511         device_set_desc(dev, "Ingenic jz4780 CGU");
512
513         return (BUS_PROBE_DEFAULT);
514 }
515
516 static int
517 jz4780_clock_attach(device_t dev)
518 {
519         struct jz4780_clock_softc *sc;
520
521         sc = device_get_softc(dev);
522         if (bus_alloc_resources(dev, jz4780_clock_spec, sc->res)) {
523                 device_printf(dev, "could not allocate resources for device\n");
524                 return (ENXIO);
525         }
526
527         sc->dev = dev;
528         CGU_LOCK_INIT(sc);
529
530         sc->clkdom = clkdom_create(dev);
531         if (sc->clkdom == NULL)
532                 goto fail;
533         if (jz4780_clock_register(sc) != 0)
534                 goto fail;
535         if (clkdom_finit(sc->clkdom) != 0)
536                 goto fail;
537         if (jz4780_clock_fixup(sc) != 0)
538                 goto fail;
539         if (bootverbose)
540                 clkdom_dump(sc->clkdom);
541
542         return (0);
543 fail:
544         bus_release_resources(dev, jz4780_clock_spec, sc->res);
545         CGU_LOCK_DESTROY(sc);
546
547         return (ENXIO);
548 }
549
550 static int
551 jz4780_clock_detach(device_t dev)
552 {
553         struct jz4780_clock_softc *sc;
554
555         sc = device_get_softc(dev);
556         bus_release_resources(dev, jz4780_clock_spec, sc->res);
557         CGU_LOCK_DESTROY(sc);
558
559         return (0);
560 }
561
562 static int
563 jz4780_clock_write_4(device_t dev, bus_addr_t addr, uint32_t val)
564 {
565         struct jz4780_clock_softc *sc;
566
567         sc = device_get_softc(dev);
568         CSR_WRITE_4(sc, addr, val);
569         return (0);
570 }
571
572 static int
573 jz4780_clock_read_4(device_t dev, bus_addr_t addr, uint32_t *val)
574 {
575         struct jz4780_clock_softc *sc;
576
577         sc = device_get_softc(dev);
578         *val = CSR_READ_4(sc, addr);
579         return (0);
580 }
581
582 static int
583 jz4780_clock_modify_4(device_t dev, bus_addr_t addr, uint32_t clear_mask,
584     uint32_t set_mask)
585 {
586         struct jz4780_clock_softc *sc;
587         uint32_t val;
588
589         sc = device_get_softc(dev);
590         val = CSR_READ_4(sc, addr);
591         val &= ~clear_mask;
592         val |= set_mask;
593         CSR_WRITE_4(sc, addr, val);
594         return (0);
595 }
596
597 static void
598 jz4780_clock_device_lock(device_t dev)
599 {
600         struct jz4780_clock_softc *sc;
601
602         sc = device_get_softc(dev);
603         CGU_LOCK(sc);
604 }
605
606 static void
607 jz4780_clock_device_unlock(device_t dev)
608 {
609         struct jz4780_clock_softc *sc;
610
611         sc = device_get_softc(dev);
612         CGU_UNLOCK(sc);
613 }
614
615 static device_method_t jz4780_clock_methods[] = {
616         /* Device interface */
617         DEVMETHOD(device_probe,         jz4780_clock_probe),
618         DEVMETHOD(device_attach,        jz4780_clock_attach),
619         DEVMETHOD(device_detach,        jz4780_clock_detach),
620
621         /* Clock device interface */
622         DEVMETHOD(clkdev_write_4,       jz4780_clock_write_4),
623         DEVMETHOD(clkdev_read_4,        jz4780_clock_read_4),
624         DEVMETHOD(clkdev_modify_4,      jz4780_clock_modify_4),
625         DEVMETHOD(clkdev_device_lock,   jz4780_clock_device_lock),
626         DEVMETHOD(clkdev_device_unlock, jz4780_clock_device_unlock),
627
628         DEVMETHOD_END
629 };
630
631 static driver_t jz4780_clock_driver = {
632         "cgu",
633         jz4780_clock_methods,
634         sizeof(struct jz4780_clock_softc),
635 };
636
637 static devclass_t jz4780_clock_devclass;
638
639 EARLY_DRIVER_MODULE(jz4780_clock, simplebus, jz4780_clock_driver,
640     jz4780_clock_devclass, 0, 0,  BUS_PASS_CPU + BUS_PASS_ORDER_LATE);
641
642 static int
643 jz4780_ehci_clk_config(struct jz4780_clock_softc *sc)
644 {
645         clk_t phy_clk, ext_clk;
646         uint64_t phy_freq;
647         int err;
648
649         phy_clk = NULL;
650         ext_clk = NULL;
651         err = -1;
652
653         /* Set phy timing by copying it from ext */
654         if (clk_get_by_id(sc->dev, sc->clkdom, JZ4780_CLK_OTGPHY,
655             &phy_clk) != 0)
656                 goto done;
657         if (clk_get_parent(phy_clk, &ext_clk) != 0)
658                 goto done;
659         if (clk_get_freq(ext_clk, &phy_freq) != 0)
660                 goto done;
661         if (clk_set_freq(phy_clk, phy_freq, 0) != 0)
662                 goto done;
663         err = 0;
664 done:
665         clk_release(ext_clk);
666         clk_release(phy_clk);
667
668         return (err);
669 }
670
671 int
672 jz4780_ohci_enable(void)
673 {
674         device_t dev;
675         struct jz4780_clock_softc *sc;
676         uint32_t reg;
677
678         dev = devclass_get_device(jz4780_clock_devclass, 0);
679         if (dev == NULL)
680                 return (-1);
681
682         sc = device_get_softc(dev);
683         CGU_LOCK(sc);
684
685         /* Do not force port1 to suspend mode */
686         reg = CSR_READ_4(sc, JZ_OPCR);
687         reg |= OPCR_SPENDN1;
688         CSR_WRITE_4(sc, JZ_OPCR, reg);
689
690         CGU_UNLOCK(sc);
691         return (0);
692 }
693
694 int
695 jz4780_ehci_enable(void)
696 {
697         device_t dev;
698         struct jz4780_clock_softc *sc;
699         uint32_t reg;
700
701         dev = devclass_get_device(jz4780_clock_devclass, 0);
702         if (dev == NULL)
703                 return (-1);
704
705         sc = device_get_softc(dev);
706
707         /*
708          * EHCI should use MPPL as a parent, but Linux configures OTG
709          * clock anyway. Follow their lead blindly.
710          */
711         if (jz4780_ehci_clk_config(sc) != 0)
712                 return (-1);
713
714         CGU_LOCK(sc);
715
716         /* Enable OTG, should not be necessary since we use PLL clock */
717         reg = CSR_READ_4(sc, JZ_USBPCR);
718         reg &= ~(PCR_OTG_DISABLE);
719         CSR_WRITE_4(sc, JZ_USBPCR, reg);
720
721         /* Do not force port1 to suspend mode */
722         reg = CSR_READ_4(sc, JZ_OPCR);
723         reg |= OPCR_SPENDN1;
724         CSR_WRITE_4(sc, JZ_OPCR, reg);
725
726         /* D- pulldown */
727         reg = CSR_READ_4(sc, JZ_USBPCR1);
728         reg |= PCR_DMPD1;
729         CSR_WRITE_4(sc, JZ_USBPCR1, reg);
730
731         /* D+ pulldown */
732         reg = CSR_READ_4(sc, JZ_USBPCR1);
733         reg |= PCR_DPPD1;
734         CSR_WRITE_4(sc, JZ_USBPCR1, reg);
735
736         /* 16 bit bus witdth for port 1*/
737         reg = CSR_READ_4(sc, JZ_USBPCR1);
738         reg |= PCR_WORD_I_F1 | PCR_WORD_I_F0;
739         CSR_WRITE_4(sc, JZ_USBPCR1, reg);
740
741         /* Reset USB */
742         reg = CSR_READ_4(sc, JZ_USBPCR);
743         reg |= PCR_POR;
744         CSR_WRITE_4(sc, JZ_USBPCR, reg);
745         DELAY(1);
746         reg = CSR_READ_4(sc, JZ_USBPCR);
747         reg &= ~(PCR_POR);
748         CSR_WRITE_4(sc, JZ_USBPCR, reg);
749
750         /* Soft-reset USB */
751         reg = CSR_READ_4(sc, JZ_SRBC);
752         reg |= SRBC_UHC_SR;
753         CSR_WRITE_4(sc, JZ_SRBC, reg);
754         /* 300ms */
755         DELAY(300*hz/1000);
756
757         reg = CSR_READ_4(sc, JZ_SRBC);
758         reg &= ~(SRBC_UHC_SR);
759         CSR_WRITE_4(sc, JZ_SRBC, reg);
760
761         /* 300ms */
762         DELAY(300*hz/1000);
763
764         CGU_UNLOCK(sc);
765         return (0);
766 }
767
768 #define USBRESET_DETECT_TIME    0x96
769
770 int
771 jz4780_otg_enable(void)
772 {
773         device_t dev;
774         struct jz4780_clock_softc *sc;
775         uint32_t reg;
776
777         dev = devclass_get_device(jz4780_clock_devclass, 0);
778         if (dev == NULL)
779                 return (-1);
780
781         sc = device_get_softc(dev);
782
783         CGU_LOCK(sc);
784
785         /* Select Synopsys OTG mode */
786         reg = CSR_READ_4(sc, JZ_USBPCR1);
787         reg |= PCR_SYNOPSYS;
788
789         /* Set UTMI bus width to 16 bit */
790         reg |= PCR_WORD_I_F0 | PCR_WORD_I_F1;
791         CSR_WRITE_4(sc, JZ_USBPCR1, reg);
792
793         /* Blah */
794         reg = CSR_READ_4(sc, JZ_USBVBFIL);
795         reg = REG_SET(reg, USBVBFIL_IDDIGFIL, 0);
796         reg = REG_SET(reg, USBVBFIL_USBVBFIL, 0);
797         CSR_WRITE_4(sc, JZ_USBVBFIL, reg);
798
799         /* Setup reset detect time */
800         reg = CSR_READ_4(sc, JZ_USBRDT);
801         reg = REG_SET(reg, USBRDT_USBRDT, USBRESET_DETECT_TIME);
802         reg |= USBRDT_VBFIL_LD_EN;
803         CSR_WRITE_4(sc, JZ_USBRDT, reg);
804
805         /* Setup USBPCR bits */
806         reg = CSR_READ_4(sc, JZ_USBPCR);
807         reg |= PCR_USB_MODE;
808         reg |= PCR_COMMONONN;
809         reg |= PCR_VBUSVLDEXT;
810         reg |= PCR_VBUSVLDEXTSEL;
811         reg &= ~(PCR_OTG_DISABLE);
812         CSR_WRITE_4(sc, JZ_USBPCR, reg);
813
814         /* Reset USB */
815         reg = CSR_READ_4(sc, JZ_USBPCR);
816         reg |= PCR_POR;
817         CSR_WRITE_4(sc, JZ_USBPCR, reg);
818         DELAY(1000);
819         reg = CSR_READ_4(sc, JZ_USBPCR);
820         reg &= ~(PCR_POR);
821         CSR_WRITE_4(sc, JZ_USBPCR, reg);
822
823         /* Unsuspend OTG port */
824         reg = CSR_READ_4(sc, JZ_OPCR);
825         reg |= OPCR_SPENDN0;
826         CSR_WRITE_4(sc, JZ_OPCR, reg);
827
828         CGU_UNLOCK(sc);
829         return (0);
830 }