]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/mips/ingenic/jz4780_clock.c
MFV r354378,r354379,r354386: 10499 Multi-modifier protection (MMP)
[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
457         return (0);
458 }
459
460 static int
461 jz4780_clock_fixup(struct jz4780_clock_softc *sc)
462 {
463         struct clknode *clk_uhc;
464         int ret;
465
466         /*
467          * Make UHC mux use MPLL as the source. It defaults to OTG_PHY
468          * and that somehow just does not work.
469          */
470         clkdom_xlock(sc->clkdom);
471
472         /* Assume the worst */
473         ret = ENXIO;
474
475         clk_uhc = clknode_find_by_id(sc->clkdom, JZ4780_CLK_UHC);
476         if (clk_uhc != NULL) {
477                 ret = clknode_set_parent_by_name(clk_uhc, "mpll");
478                 if (ret != 0)
479                         device_printf(sc->dev,
480                             "unable to reparent uhc clock\n");
481                 else
482                         ret = clknode_set_freq(clk_uhc, 48000000, 0, 0);
483                 if (ret != 0)
484                         device_printf(sc->dev, "unable to init uhc clock\n");
485         } else
486                 device_printf(sc->dev, "unable to lookup uhc clock\n");
487
488         clkdom_unlock(sc->clkdom);
489         return (ret);
490 }
491
492 #define CGU_LOCK(sc)            mtx_lock(&(sc)->mtx)
493 #define CGU_UNLOCK(sc)          mtx_unlock(&(sc)->mtx)
494 #define CGU_LOCK_INIT(sc)       \
495     mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev),        \
496     "jz4780-cgu", MTX_DEF)
497 #define CGU_LOCK_DESTROY(sc)    mtx_destroy(&(sc)->mtx);
498
499 #define CSR_WRITE_4(sc, reg, val)       bus_write_4((sc)->res[0], (reg), (val))
500 #define CSR_READ_4(sc, reg)             bus_read_4((sc)->res[0], (reg))
501
502 static int
503 jz4780_clock_probe(device_t dev)
504 {
505
506         if (!ofw_bus_status_okay(dev))
507                 return (ENXIO);
508
509         if (!ofw_bus_is_compatible(dev, "ingenic,jz4780-cgu"))
510                 return (ENXIO);
511
512         device_set_desc(dev, "Ingenic jz4780 CGU");
513
514         return (BUS_PROBE_DEFAULT);
515 }
516
517 static int
518 jz4780_clock_attach(device_t dev)
519 {
520         struct jz4780_clock_softc *sc;
521
522         sc = device_get_softc(dev);
523         if (bus_alloc_resources(dev, jz4780_clock_spec, sc->res)) {
524                 device_printf(dev, "could not allocate resources for device\n");
525                 return (ENXIO);
526         }
527
528         sc->dev = dev;
529         CGU_LOCK_INIT(sc);
530
531         sc->clkdom = clkdom_create(dev);
532         if (sc->clkdom == NULL)
533                 goto fail;
534         if (jz4780_clock_register(sc) != 0)
535                 goto fail;
536         if (clkdom_finit(sc->clkdom) != 0)
537                 goto fail;
538         if (jz4780_clock_fixup(sc) != 0)
539                 goto fail;
540         if (bootverbose)
541                 clkdom_dump(sc->clkdom);
542
543         return (0);
544 fail:
545         bus_release_resources(dev, jz4780_clock_spec, sc->res);
546         CGU_LOCK_DESTROY(sc);
547
548         return (ENXIO);
549 }
550
551 static int
552 jz4780_clock_detach(device_t dev)
553 {
554         struct jz4780_clock_softc *sc;
555
556         sc = device_get_softc(dev);
557         bus_release_resources(dev, jz4780_clock_spec, sc->res);
558         CGU_LOCK_DESTROY(sc);
559
560         return (0);
561 }
562
563 static int
564 jz4780_clock_write_4(device_t dev, bus_addr_t addr, uint32_t val)
565 {
566         struct jz4780_clock_softc *sc;
567
568         sc = device_get_softc(dev);
569         CSR_WRITE_4(sc, addr, val);
570         return (0);
571 }
572
573 static int
574 jz4780_clock_read_4(device_t dev, bus_addr_t addr, uint32_t *val)
575 {
576         struct jz4780_clock_softc *sc;
577
578         sc = device_get_softc(dev);
579         *val = CSR_READ_4(sc, addr);
580         return (0);
581 }
582
583 static int
584 jz4780_clock_modify_4(device_t dev, bus_addr_t addr, uint32_t clear_mask,
585     uint32_t set_mask)
586 {
587         struct jz4780_clock_softc *sc;
588         uint32_t val;
589
590         sc = device_get_softc(dev);
591         val = CSR_READ_4(sc, addr);
592         val &= ~clear_mask;
593         val |= set_mask;
594         CSR_WRITE_4(sc, addr, val);
595         return (0);
596 }
597
598 static void
599 jz4780_clock_device_lock(device_t dev)
600 {
601         struct jz4780_clock_softc *sc;
602
603         sc = device_get_softc(dev);
604         CGU_LOCK(sc);
605 }
606
607 static void
608 jz4780_clock_device_unlock(device_t dev)
609 {
610         struct jz4780_clock_softc *sc;
611
612         sc = device_get_softc(dev);
613         CGU_UNLOCK(sc);
614 }
615
616 static device_method_t jz4780_clock_methods[] = {
617         /* Device interface */
618         DEVMETHOD(device_probe,         jz4780_clock_probe),
619         DEVMETHOD(device_attach,        jz4780_clock_attach),
620         DEVMETHOD(device_detach,        jz4780_clock_detach),
621
622         /* Clock device interface */
623         DEVMETHOD(clkdev_write_4,       jz4780_clock_write_4),
624         DEVMETHOD(clkdev_read_4,        jz4780_clock_read_4),
625         DEVMETHOD(clkdev_modify_4,      jz4780_clock_modify_4),
626         DEVMETHOD(clkdev_device_lock,   jz4780_clock_device_lock),
627         DEVMETHOD(clkdev_device_unlock, jz4780_clock_device_unlock),
628
629         DEVMETHOD_END
630 };
631
632 static driver_t jz4780_clock_driver = {
633         "cgu",
634         jz4780_clock_methods,
635         sizeof(struct jz4780_clock_softc),
636 };
637
638 static devclass_t jz4780_clock_devclass;
639
640 EARLY_DRIVER_MODULE(jz4780_clock, simplebus, jz4780_clock_driver,
641     jz4780_clock_devclass, 0, 0,  BUS_PASS_CPU + BUS_PASS_ORDER_LATE);
642
643 static int
644 jz4780_ehci_clk_config(struct jz4780_clock_softc *sc)
645 {
646         clk_t phy_clk, ext_clk;
647         uint64_t phy_freq;
648         int err;
649
650         phy_clk = NULL;
651         ext_clk = NULL;
652         err = -1;
653
654         /* Set phy timing by copying it from ext */
655         if (clk_get_by_id(sc->dev, sc->clkdom, JZ4780_CLK_OTGPHY,
656             &phy_clk) != 0)
657                 goto done;
658         if (clk_get_parent(phy_clk, &ext_clk) != 0)
659                 goto done;
660         if (clk_get_freq(ext_clk, &phy_freq) != 0)
661                 goto done;
662         if (clk_set_freq(phy_clk, phy_freq, 0) != 0)
663                 goto done;
664         err = 0;
665 done:
666         clk_release(ext_clk);
667         clk_release(phy_clk);
668
669         return (err);
670 }
671
672 int
673 jz4780_ohci_enable(void)
674 {
675         device_t dev;
676         struct jz4780_clock_softc *sc;
677         uint32_t reg;
678
679         dev = devclass_get_device(jz4780_clock_devclass, 0);
680         if (dev == NULL)
681                 return (-1);
682
683         sc = device_get_softc(dev);
684         CGU_LOCK(sc);
685
686         /* Do not force port1 to suspend mode */
687         reg = CSR_READ_4(sc, JZ_OPCR);
688         reg |= OPCR_SPENDN1;
689         CSR_WRITE_4(sc, JZ_OPCR, reg);
690
691         CGU_UNLOCK(sc);
692         return (0);
693 }
694
695 int
696 jz4780_ehci_enable(void)
697 {
698         device_t dev;
699         struct jz4780_clock_softc *sc;
700         uint32_t reg;
701
702         dev = devclass_get_device(jz4780_clock_devclass, 0);
703         if (dev == NULL)
704                 return (-1);
705
706         sc = device_get_softc(dev);
707
708         /*
709          * EHCI should use MPPL as a parent, but Linux configures OTG
710          * clock anyway. Follow their lead blindly.
711          */
712         if (jz4780_ehci_clk_config(sc) != 0)
713                 return (-1);
714
715         CGU_LOCK(sc);
716
717         /* Enable OTG, should not be necessary since we use PLL clock */
718         reg = CSR_READ_4(sc, JZ_USBPCR);
719         reg &= ~(PCR_OTG_DISABLE);
720         CSR_WRITE_4(sc, JZ_USBPCR, reg);
721
722         /* Do not force port1 to suspend mode */
723         reg = CSR_READ_4(sc, JZ_OPCR);
724         reg |= OPCR_SPENDN1;
725         CSR_WRITE_4(sc, JZ_OPCR, reg);
726
727         /* D- pulldown */
728         reg = CSR_READ_4(sc, JZ_USBPCR1);
729         reg |= PCR_DMPD1;
730         CSR_WRITE_4(sc, JZ_USBPCR1, reg);
731
732         /* D+ pulldown */
733         reg = CSR_READ_4(sc, JZ_USBPCR1);
734         reg |= PCR_DPPD1;
735         CSR_WRITE_4(sc, JZ_USBPCR1, reg);
736
737         /* 16 bit bus witdth for port 1*/
738         reg = CSR_READ_4(sc, JZ_USBPCR1);
739         reg |= PCR_WORD_I_F1 | PCR_WORD_I_F0;
740         CSR_WRITE_4(sc, JZ_USBPCR1, reg);
741
742         /* Reset USB */
743         reg = CSR_READ_4(sc, JZ_USBPCR);
744         reg |= PCR_POR;
745         CSR_WRITE_4(sc, JZ_USBPCR, reg);
746         DELAY(1);
747         reg = CSR_READ_4(sc, JZ_USBPCR);
748         reg &= ~(PCR_POR);
749         CSR_WRITE_4(sc, JZ_USBPCR, reg);
750
751         /* Soft-reset USB */
752         reg = CSR_READ_4(sc, JZ_SRBC);
753         reg |= SRBC_UHC_SR;
754         CSR_WRITE_4(sc, JZ_SRBC, reg);
755         /* 300ms */
756         DELAY(300*hz/1000);
757
758         reg = CSR_READ_4(sc, JZ_SRBC);
759         reg &= ~(SRBC_UHC_SR);
760         CSR_WRITE_4(sc, JZ_SRBC, reg);
761
762         /* 300ms */
763         DELAY(300*hz/1000);
764
765         CGU_UNLOCK(sc);
766         return (0);
767 }
768
769 #define USBRESET_DETECT_TIME    0x96
770
771 int
772 jz4780_otg_enable(void)
773 {
774         device_t dev;
775         struct jz4780_clock_softc *sc;
776         uint32_t reg;
777
778         dev = devclass_get_device(jz4780_clock_devclass, 0);
779         if (dev == NULL)
780                 return (-1);
781
782         sc = device_get_softc(dev);
783
784         CGU_LOCK(sc);
785
786         /* Select Synopsys OTG mode */
787         reg = CSR_READ_4(sc, JZ_USBPCR1);
788         reg |= PCR_SYNOPSYS;
789
790         /* Set UTMI bus width to 16 bit */
791         reg |= PCR_WORD_I_F0 | PCR_WORD_I_F1;
792         CSR_WRITE_4(sc, JZ_USBPCR1, reg);
793
794         /* Blah */
795         reg = CSR_READ_4(sc, JZ_USBVBFIL);
796         reg = REG_SET(reg, USBVBFIL_IDDIGFIL, 0);
797         reg = REG_SET(reg, USBVBFIL_USBVBFIL, 0);
798         CSR_WRITE_4(sc, JZ_USBVBFIL, reg);
799
800         /* Setup reset detect time */
801         reg = CSR_READ_4(sc, JZ_USBRDT);
802         reg = REG_SET(reg, USBRDT_USBRDT, USBRESET_DETECT_TIME);
803         reg |= USBRDT_VBFIL_LD_EN;
804         CSR_WRITE_4(sc, JZ_USBRDT, reg);
805
806         /* Setup USBPCR bits */
807         reg = CSR_READ_4(sc, JZ_USBPCR);
808         reg |= PCR_USB_MODE;
809         reg |= PCR_COMMONONN;
810         reg |= PCR_VBUSVLDEXT;
811         reg |= PCR_VBUSVLDEXTSEL;
812         reg &= ~(PCR_OTG_DISABLE);
813         CSR_WRITE_4(sc, JZ_USBPCR, reg);
814
815         /* Reset USB */
816         reg = CSR_READ_4(sc, JZ_USBPCR);
817         reg |= PCR_POR;
818         CSR_WRITE_4(sc, JZ_USBPCR, reg);
819         DELAY(1000);
820         reg = CSR_READ_4(sc, JZ_USBPCR);
821         reg &= ~(PCR_POR);
822         CSR_WRITE_4(sc, JZ_USBPCR, reg);
823
824         /* Unsuspend OTG port */
825         reg = CSR_READ_4(sc, JZ_OPCR);
826         reg |= OPCR_SPENDN0;
827         CSR_WRITE_4(sc, JZ_OPCR, reg);
828
829         CGU_UNLOCK(sc);
830         return (0);
831 }