xref: /openbsd/sys/arch/armv7/omap/prcm.c (revision 8eda2d14)
1*8eda2d14Spatrick /* $OpenBSD: prcm.c,v 1.1 2013/09/04 14:38:31 patrick Exp $ */
2*8eda2d14Spatrick /*
3*8eda2d14Spatrick  * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
4*8eda2d14Spatrick  *
5*8eda2d14Spatrick  * Permission to use, copy, modify, and distribute this software for any
6*8eda2d14Spatrick  * purpose with or without fee is hereby granted, provided that the above
7*8eda2d14Spatrick  * copyright notice and this permission notice appear in all copies.
8*8eda2d14Spatrick  *
9*8eda2d14Spatrick  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10*8eda2d14Spatrick  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*8eda2d14Spatrick  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12*8eda2d14Spatrick  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*8eda2d14Spatrick  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*8eda2d14Spatrick  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15*8eda2d14Spatrick  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*8eda2d14Spatrick  */
17*8eda2d14Spatrick 
18*8eda2d14Spatrick /*-
19*8eda2d14Spatrick  * Copyright (c) 2011
20*8eda2d14Spatrick  *	Ben Gray <ben.r.gray@gmail.com>.
21*8eda2d14Spatrick  * All rights reserved.
22*8eda2d14Spatrick  *
23*8eda2d14Spatrick  * Redistribution and use in source and binary forms, with or without
24*8eda2d14Spatrick  * modification, are permitted provided that the following conditions
25*8eda2d14Spatrick  * are met:
26*8eda2d14Spatrick  * 1. Redistributions of source code must retain the above copyright
27*8eda2d14Spatrick  *    notice, this list of conditions and the following disclaimer.
28*8eda2d14Spatrick  * 2. Redistributions in binary form must reproduce the above copyright
29*8eda2d14Spatrick  *    notice, this list of conditions and the following disclaimer in the
30*8eda2d14Spatrick  *    documentation and/or other materials provided with the distribution.
31*8eda2d14Spatrick  * 3. The name of the company nor the name of the author may be used to
32*8eda2d14Spatrick  *    endorse or promote products derived from this software without specific
33*8eda2d14Spatrick  *    prior written permission.
34*8eda2d14Spatrick  *
35*8eda2d14Spatrick  * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
36*8eda2d14Spatrick  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37*8eda2d14Spatrick  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
38*8eda2d14Spatrick  * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
39*8eda2d14Spatrick  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
40*8eda2d14Spatrick  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
41*8eda2d14Spatrick  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42*8eda2d14Spatrick  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
43*8eda2d14Spatrick  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
44*8eda2d14Spatrick  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45*8eda2d14Spatrick  */
46*8eda2d14Spatrick 
47*8eda2d14Spatrick /*
48*8eda2d14Spatrick  * Driver for the Power, Reset and Clock Management Module (PRCM).
49*8eda2d14Spatrick  */
50*8eda2d14Spatrick 
51*8eda2d14Spatrick #include <sys/types.h>
52*8eda2d14Spatrick #include <sys/param.h>
53*8eda2d14Spatrick #include <sys/systm.h>
54*8eda2d14Spatrick #include <sys/kernel.h>
55*8eda2d14Spatrick #include <sys/time.h>
56*8eda2d14Spatrick #include <sys/device.h>
57*8eda2d14Spatrick 
58*8eda2d14Spatrick #include <machine/bus.h>
59*8eda2d14Spatrick #include <machine/intr.h>
60*8eda2d14Spatrick #include <arm/cpufunc.h>
61*8eda2d14Spatrick #include <armv7/omap/omapvar.h>
62*8eda2d14Spatrick #include <armv7/omap/prcmvar.h>
63*8eda2d14Spatrick 
64*8eda2d14Spatrick #include <armv7/omap/am335x_prcmreg.h>
65*8eda2d14Spatrick #include <armv7/omap/omap3_prcmreg.h>
66*8eda2d14Spatrick #include <armv7/omap/omap4_prcmreg.h>
67*8eda2d14Spatrick 
68*8eda2d14Spatrick #define PRCM_REVISION		0x0800
69*8eda2d14Spatrick #define PRCM_SYSCONFIG		0x0810
70*8eda2d14Spatrick 
71*8eda2d14Spatrick uint32_t prcm_imask_mask[PRCM_REG_MAX];
72*8eda2d14Spatrick uint32_t prcm_fmask_mask[PRCM_REG_MAX];
73*8eda2d14Spatrick uint32_t prcm_imask_addr[PRCM_REG_MAX];
74*8eda2d14Spatrick uint32_t prcm_fmask_addr[PRCM_REG_MAX];
75*8eda2d14Spatrick 
76*8eda2d14Spatrick #define SYS_CLK		13 /* SYS_CLK speed in MHz */
77*8eda2d14Spatrick 
78*8eda2d14Spatrick struct prcm_softc {
79*8eda2d14Spatrick 	struct device		sc_dev;
80*8eda2d14Spatrick 	bus_space_tag_t		sc_iot;
81*8eda2d14Spatrick 	bus_space_handle_t	sc_prcm;
82*8eda2d14Spatrick 	bus_space_handle_t	sc_cm1;
83*8eda2d14Spatrick 	bus_space_handle_t	sc_cm2;
84*8eda2d14Spatrick 	void (*sc_setup)(struct prcm_softc *sc);
85*8eda2d14Spatrick 	void (*sc_enablemodule)(struct prcm_softc *sc, int mod);
86*8eda2d14Spatrick 	void (*sc_setclock)(struct prcm_softc *sc,
87*8eda2d14Spatrick 	    int clock, int speed);
88*8eda2d14Spatrick 	uint32_t		cm1_avail;
89*8eda2d14Spatrick 	uint32_t		cm2_avail;
90*8eda2d14Spatrick };
91*8eda2d14Spatrick 
92*8eda2d14Spatrick int	prcm_match(struct device *, void *, void *);
93*8eda2d14Spatrick void	prcm_attach(struct device *, struct device *, void *);
94*8eda2d14Spatrick int	prcm_setup_dpll5(struct prcm_softc *);
95*8eda2d14Spatrick uint32_t prcm_v3_bit(int mod);
96*8eda2d14Spatrick uint32_t prcm_am335x_clkctrl(int mod);
97*8eda2d14Spatrick 
98*8eda2d14Spatrick void prcm_am335x_enablemodule(struct prcm_softc *, int);
99*8eda2d14Spatrick void prcm_am335x_setclock(struct prcm_softc *, int, int);
100*8eda2d14Spatrick 
101*8eda2d14Spatrick void prcm_v3_setup(struct prcm_softc *);
102*8eda2d14Spatrick void prcm_v3_enablemodule(struct prcm_softc *, int);
103*8eda2d14Spatrick void prcm_v3_setclock(struct prcm_softc *, int, int);
104*8eda2d14Spatrick 
105*8eda2d14Spatrick void prcm_v4_enablemodule(struct prcm_softc *, int);
106*8eda2d14Spatrick int prcm_v4_hsusbhost_activate(int);
107*8eda2d14Spatrick int prcm_v4_hsusbhost_set_source(int, int);
108*8eda2d14Spatrick 
109*8eda2d14Spatrick struct cfattach	prcm_ca = {
110*8eda2d14Spatrick 	sizeof (struct prcm_softc), NULL, prcm_attach
111*8eda2d14Spatrick };
112*8eda2d14Spatrick 
113*8eda2d14Spatrick struct cfdriver prcm_cd = {
114*8eda2d14Spatrick 	NULL, "prcm", DV_DULL
115*8eda2d14Spatrick };
116*8eda2d14Spatrick 
117*8eda2d14Spatrick void
118*8eda2d14Spatrick prcm_attach(struct device *parent, struct device *self, void *args)
119*8eda2d14Spatrick {
120*8eda2d14Spatrick 	struct omap_attach_args *oa = args;
121*8eda2d14Spatrick 	struct prcm_softc *sc = (struct prcm_softc *) self;
122*8eda2d14Spatrick 	u_int32_t reg;
123*8eda2d14Spatrick 
124*8eda2d14Spatrick 	sc->sc_iot = oa->oa_iot;
125*8eda2d14Spatrick 
126*8eda2d14Spatrick 	switch (board_id) {
127*8eda2d14Spatrick 	case BOARD_ID_AM335X_BEAGLEBONE:
128*8eda2d14Spatrick 		sc->sc_setup = NULL;
129*8eda2d14Spatrick 		sc->sc_enablemodule = prcm_am335x_enablemodule;
130*8eda2d14Spatrick 		sc->sc_setclock = prcm_am335x_setclock;
131*8eda2d14Spatrick 		break;
132*8eda2d14Spatrick 	case BOARD_ID_OMAP3_BEAGLE:
133*8eda2d14Spatrick 	case BOARD_ID_OMAP3_OVERO:
134*8eda2d14Spatrick 		sc->sc_setup = prcm_v3_setup;
135*8eda2d14Spatrick 		sc->sc_enablemodule = prcm_v3_enablemodule;
136*8eda2d14Spatrick 		sc->sc_setclock = prcm_v3_setclock;
137*8eda2d14Spatrick 		break;
138*8eda2d14Spatrick 	case BOARD_ID_OMAP4_PANDA:
139*8eda2d14Spatrick 		sc->sc_setup = NULL;
140*8eda2d14Spatrick 		sc->sc_enablemodule = prcm_v4_enablemodule;
141*8eda2d14Spatrick 		sc->sc_setclock = NULL;
142*8eda2d14Spatrick 		sc->cm1_avail = 1;
143*8eda2d14Spatrick 		sc->cm2_avail = 1;
144*8eda2d14Spatrick 		break;
145*8eda2d14Spatrick 	}
146*8eda2d14Spatrick 
147*8eda2d14Spatrick 	if (bus_space_map(sc->sc_iot, oa->oa_dev->mem[0].addr,
148*8eda2d14Spatrick 	    oa->oa_dev->mem[0].size, 0, &sc->sc_prcm))
149*8eda2d14Spatrick 		panic("prcm_attach: bus_space_map failed!");
150*8eda2d14Spatrick 
151*8eda2d14Spatrick 	if (sc->cm1_avail &&
152*8eda2d14Spatrick 	    bus_space_map(sc->sc_iot, oa->oa_dev->mem[1].addr,
153*8eda2d14Spatrick 	    oa->oa_dev->mem[1].size, 0, &sc->sc_cm1))
154*8eda2d14Spatrick 		panic("prcm_attach: bus_space_map failed!");
155*8eda2d14Spatrick 
156*8eda2d14Spatrick 	if (sc->cm2_avail &&
157*8eda2d14Spatrick 	    bus_space_map(sc->sc_iot, oa->oa_dev->mem[2].addr,
158*8eda2d14Spatrick 	    oa->oa_dev->mem[2].size, 0, &sc->sc_cm2))
159*8eda2d14Spatrick 		panic("prcm_attach: bus_space_map failed!");
160*8eda2d14Spatrick 
161*8eda2d14Spatrick 	reg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_REVISION);
162*8eda2d14Spatrick 	printf(" rev %d.%d\n", reg >> 4 & 0xf, reg & 0xf);
163*8eda2d14Spatrick 
164*8eda2d14Spatrick 	if (sc->sc_setup)
165*8eda2d14Spatrick 		sc->sc_setup(sc);
166*8eda2d14Spatrick 
167*8eda2d14Spatrick 	printf("\n");
168*8eda2d14Spatrick }
169*8eda2d14Spatrick 
170*8eda2d14Spatrick void
171*8eda2d14Spatrick prcm_v3_setup(struct prcm_softc *sc)
172*8eda2d14Spatrick {
173*8eda2d14Spatrick 	/* Setup the 120MHZ DPLL5 clock, to be used by USB. */
174*8eda2d14Spatrick 	prcm_setup_dpll5(sc);
175*8eda2d14Spatrick 
176*8eda2d14Spatrick 	prcm_fmask_mask[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_FMASK;
177*8eda2d14Spatrick 	prcm_imask_mask[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_IMASK;
178*8eda2d14Spatrick 	prcm_fmask_addr[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_FADDR;
179*8eda2d14Spatrick 	prcm_imask_addr[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_IADDR;
180*8eda2d14Spatrick 
181*8eda2d14Spatrick 	prcm_fmask_mask[PRCM_REG_CORE_CLK2] = PRCM_REG_CORE_CLK2_FMASK;
182*8eda2d14Spatrick 	prcm_imask_mask[PRCM_REG_CORE_CLK2] = PRCM_REG_CORE_CLK2_IMASK;
183*8eda2d14Spatrick 	prcm_fmask_addr[PRCM_REG_CORE_CLK2] = PRCM_REG_CORE_CLK2_FADDR;
184*8eda2d14Spatrick 	prcm_imask_addr[PRCM_REG_CORE_CLK2] = PRCM_REG_CORE_CLK2_IADDR;
185*8eda2d14Spatrick 
186*8eda2d14Spatrick 	prcm_fmask_mask[PRCM_REG_CORE_CLK3] = PRCM_REG_CORE_CLK3_FMASK;
187*8eda2d14Spatrick 	prcm_imask_mask[PRCM_REG_CORE_CLK3] = PRCM_REG_CORE_CLK3_IMASK;
188*8eda2d14Spatrick 	prcm_fmask_addr[PRCM_REG_CORE_CLK3] = PRCM_REG_CORE_CLK3_FADDR;
189*8eda2d14Spatrick 	prcm_imask_addr[PRCM_REG_CORE_CLK3] = PRCM_REG_CORE_CLK3_IADDR;
190*8eda2d14Spatrick 
191*8eda2d14Spatrick 	prcm_fmask_mask[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_FMASK;
192*8eda2d14Spatrick 	prcm_imask_mask[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_IMASK;
193*8eda2d14Spatrick 	prcm_fmask_addr[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_FADDR;
194*8eda2d14Spatrick 	prcm_imask_addr[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_IADDR;
195*8eda2d14Spatrick }
196*8eda2d14Spatrick 
197*8eda2d14Spatrick void
198*8eda2d14Spatrick prcm_setclock(int clock, int speed)
199*8eda2d14Spatrick {
200*8eda2d14Spatrick 	struct prcm_softc *sc = prcm_cd.cd_devs[0];
201*8eda2d14Spatrick 
202*8eda2d14Spatrick 	if (!sc->sc_setclock)
203*8eda2d14Spatrick 		panic("%s: not initialised!", __func__);
204*8eda2d14Spatrick 
205*8eda2d14Spatrick 	sc->sc_setclock(sc, clock, speed);
206*8eda2d14Spatrick }
207*8eda2d14Spatrick 
208*8eda2d14Spatrick void
209*8eda2d14Spatrick prcm_am335x_setclock(struct prcm_softc *sc, int clock, int speed)
210*8eda2d14Spatrick {
211*8eda2d14Spatrick 	u_int32_t oreg, reg, mask;
212*8eda2d14Spatrick 
213*8eda2d14Spatrick 	/* set CLKSEL register */
214*8eda2d14Spatrick 	if (clock == 1) {
215*8eda2d14Spatrick 		oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm,
216*8eda2d14Spatrick 		    PRCM_AM335X_CLKSEL_TIMER2_CLK);
217*8eda2d14Spatrick 		mask = 3;
218*8eda2d14Spatrick 		reg = oreg & ~mask;
219*8eda2d14Spatrick 		reg |=0x02;
220*8eda2d14Spatrick 		bus_space_write_4(sc->sc_iot, sc->sc_prcm,
221*8eda2d14Spatrick 		    PRCM_AM335X_CLKSEL_TIMER2_CLK, reg);
222*8eda2d14Spatrick 	} else if (clock == 2) {
223*8eda2d14Spatrick 		oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm,
224*8eda2d14Spatrick 		    PRCM_AM335X_CLKSEL_TIMER3_CLK);
225*8eda2d14Spatrick 		mask = 3;
226*8eda2d14Spatrick 		reg = oreg & ~mask;
227*8eda2d14Spatrick 		reg |=0x02;
228*8eda2d14Spatrick 		bus_space_write_4(sc->sc_iot, sc->sc_prcm,
229*8eda2d14Spatrick 		    PRCM_AM335X_CLKSEL_TIMER3_CLK, reg);
230*8eda2d14Spatrick 	}
231*8eda2d14Spatrick }
232*8eda2d14Spatrick 
233*8eda2d14Spatrick void
234*8eda2d14Spatrick prcm_v3_setclock(struct prcm_softc *sc, int clock, int speed)
235*8eda2d14Spatrick {
236*8eda2d14Spatrick 	u_int32_t oreg, reg, mask;
237*8eda2d14Spatrick 
238*8eda2d14Spatrick 	if (clock == 1) {
239*8eda2d14Spatrick 		oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL_WKUP);
240*8eda2d14Spatrick 		mask = 1;
241*8eda2d14Spatrick 		reg = (oreg &~mask) | (speed & mask);
242*8eda2d14Spatrick 		bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL_WKUP, reg);
243*8eda2d14Spatrick 	} else if (clock >= 2 && clock <= 9) {
244*8eda2d14Spatrick 		int shift =  (clock-2);
245*8eda2d14Spatrick 		oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL_PER);
246*8eda2d14Spatrick 		mask = 1 << (shift);
247*8eda2d14Spatrick 		reg =  (oreg & ~mask) | ( (speed << shift) & mask);
248*8eda2d14Spatrick 		bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL_PER, reg);
249*8eda2d14Spatrick 	} else
250*8eda2d14Spatrick 		panic("%s: invalid clock %d", __func__, clock);
251*8eda2d14Spatrick }
252*8eda2d14Spatrick 
253*8eda2d14Spatrick uint32_t
254*8eda2d14Spatrick prcm_v3_bit(int mod)
255*8eda2d14Spatrick {
256*8eda2d14Spatrick 	switch(mod) {
257*8eda2d14Spatrick 	case PRCM_MMC:
258*8eda2d14Spatrick 		return PRCM_CLK_EN_MMC1;
259*8eda2d14Spatrick 	case PRCM_USB:
260*8eda2d14Spatrick 		return PRCM_CLK_EN_USB;
261*8eda2d14Spatrick 	default:
262*8eda2d14Spatrick 		panic("%s: module not found\n", __func__);
263*8eda2d14Spatrick 	}
264*8eda2d14Spatrick }
265*8eda2d14Spatrick 
266*8eda2d14Spatrick uint32_t
267*8eda2d14Spatrick prcm_am335x_clkctrl(int mod)
268*8eda2d14Spatrick {
269*8eda2d14Spatrick 	switch(mod) {
270*8eda2d14Spatrick 	case PRCM_TIMER2:
271*8eda2d14Spatrick 		return PRCM_AM335X_TIMER2_CLKCTRL;
272*8eda2d14Spatrick 	case PRCM_TIMER3:
273*8eda2d14Spatrick 		return PRCM_AM335X_TIMER3_CLKCTRL;
274*8eda2d14Spatrick 	case PRCM_MMC:
275*8eda2d14Spatrick 		return PRCM_AM335X_MMC0_CLKCTRL;
276*8eda2d14Spatrick 	case PRCM_USB:
277*8eda2d14Spatrick 		return PRCM_AM335X_USB0_CLKCTRL;
278*8eda2d14Spatrick 	default:
279*8eda2d14Spatrick 		panic("%s: module not found\n", __func__);
280*8eda2d14Spatrick 	}
281*8eda2d14Spatrick }
282*8eda2d14Spatrick 
283*8eda2d14Spatrick void
284*8eda2d14Spatrick prcm_enablemodule(int mod)
285*8eda2d14Spatrick {
286*8eda2d14Spatrick 	struct prcm_softc *sc = prcm_cd.cd_devs[0];
287*8eda2d14Spatrick 
288*8eda2d14Spatrick 	if (!sc->sc_enablemodule)
289*8eda2d14Spatrick 		panic("%s: not initialised!", __func__);
290*8eda2d14Spatrick 
291*8eda2d14Spatrick 	sc->sc_enablemodule(sc, mod);
292*8eda2d14Spatrick }
293*8eda2d14Spatrick 
294*8eda2d14Spatrick void
295*8eda2d14Spatrick prcm_am335x_enablemodule(struct prcm_softc *sc, int mod)
296*8eda2d14Spatrick {
297*8eda2d14Spatrick 	uint32_t clkctrl;
298*8eda2d14Spatrick 	int reg;
299*8eda2d14Spatrick 
300*8eda2d14Spatrick 	/*set enable bits in CLKCTRL register */
301*8eda2d14Spatrick 	reg = prcm_am335x_clkctrl(mod);
302*8eda2d14Spatrick 	clkctrl = bus_space_read_4(sc->sc_iot, sc->sc_prcm, reg);
303*8eda2d14Spatrick 	clkctrl &=~AM335X_CLKCTRL_MODULEMODE_MASK;
304*8eda2d14Spatrick 	clkctrl |= AM335X_CLKCTRL_MODULEMODE_ENABLE;
305*8eda2d14Spatrick 	bus_space_write_4(sc->sc_iot, sc->sc_prcm, reg, clkctrl);
306*8eda2d14Spatrick 
307*8eda2d14Spatrick 	/* wait until module is enabled */
308*8eda2d14Spatrick 	while (bus_space_read_4(sc->sc_iot, sc->sc_prcm, reg) & 0x30000)
309*8eda2d14Spatrick 		;
310*8eda2d14Spatrick }
311*8eda2d14Spatrick 
312*8eda2d14Spatrick void
313*8eda2d14Spatrick prcm_v3_enablemodule(struct prcm_softc *sc, int mod)
314*8eda2d14Spatrick {
315*8eda2d14Spatrick 	uint32_t bit;
316*8eda2d14Spatrick 	uint32_t fclk, iclk, fmask, imask, mbit;
317*8eda2d14Spatrick 	int freg, ireg, reg;
318*8eda2d14Spatrick 
319*8eda2d14Spatrick 	bit = prcm_v3_bit(mod);
320*8eda2d14Spatrick 	reg = bit >> 5;
321*8eda2d14Spatrick 
322*8eda2d14Spatrick 	freg = prcm_fmask_addr[reg];
323*8eda2d14Spatrick 	ireg = prcm_imask_addr[reg];
324*8eda2d14Spatrick 	fmask = prcm_fmask_mask[reg];
325*8eda2d14Spatrick 	imask = prcm_imask_mask[reg];
326*8eda2d14Spatrick 
327*8eda2d14Spatrick 	mbit = 1 << (bit & 0x1f);
328*8eda2d14Spatrick 	if (fmask & mbit) { /* dont access the register if bit isn't present */
329*8eda2d14Spatrick 		fclk = bus_space_read_4(sc->sc_iot, sc->sc_prcm, freg);
330*8eda2d14Spatrick 		bus_space_write_4(sc->sc_iot, sc->sc_prcm, freg, fclk | mbit);
331*8eda2d14Spatrick 	}
332*8eda2d14Spatrick 	if (imask & mbit) { /* dont access the register if bit isn't present */
333*8eda2d14Spatrick 		iclk = bus_space_read_4(sc->sc_iot, sc->sc_prcm, ireg);
334*8eda2d14Spatrick 		bus_space_write_4(sc->sc_iot, sc->sc_prcm, ireg, iclk | mbit);
335*8eda2d14Spatrick 	}
336*8eda2d14Spatrick 	printf("\n");
337*8eda2d14Spatrick }
338*8eda2d14Spatrick 
339*8eda2d14Spatrick void
340*8eda2d14Spatrick prcm_v4_enablemodule(struct prcm_softc *sc, int mod)
341*8eda2d14Spatrick {
342*8eda2d14Spatrick 	switch (mod) {
343*8eda2d14Spatrick 		case PRCM_USBP1_PHY:
344*8eda2d14Spatrick 		case PRCM_USBP2_PHY:
345*8eda2d14Spatrick 			prcm_v4_hsusbhost_set_source(mod, 0);
346*8eda2d14Spatrick 		case PRCM_USB:
347*8eda2d14Spatrick 		case PRCM_USBTLL:
348*8eda2d14Spatrick 		case PRCM_USBP1_UTMI:
349*8eda2d14Spatrick 		case PRCM_USBP1_HSIC:
350*8eda2d14Spatrick 		case PRCM_USBP2_UTMI:
351*8eda2d14Spatrick 		case PRCM_USBP2_HSIC:
352*8eda2d14Spatrick 			prcm_v4_hsusbhost_activate(mod);
353*8eda2d14Spatrick 			return;
354*8eda2d14Spatrick 	default:
355*8eda2d14Spatrick 		panic("%s: module not found\n", __func__);
356*8eda2d14Spatrick 	}
357*8eda2d14Spatrick }
358*8eda2d14Spatrick 
359*8eda2d14Spatrick int
360*8eda2d14Spatrick prcm_v4_hsusbhost_activate(int type)
361*8eda2d14Spatrick {
362*8eda2d14Spatrick 	struct prcm_softc *sc = prcm_cd.cd_devs[0];
363*8eda2d14Spatrick 	uint32_t i;
364*8eda2d14Spatrick 	uint32_t clksel_reg_off;
365*8eda2d14Spatrick 	uint32_t clksel, oclksel;
366*8eda2d14Spatrick 
367*8eda2d14Spatrick 	switch (type) {
368*8eda2d14Spatrick 		case PRCM_USB:
369*8eda2d14Spatrick 		case PRCM_USBP1_PHY:
370*8eda2d14Spatrick 		case PRCM_USBP2_PHY:
371*8eda2d14Spatrick 			/* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */
372*8eda2d14Spatrick 			clksel_reg_off = O4_L3INIT_CM2_OFFSET + 0x58;
373*8eda2d14Spatrick 			clksel = bus_space_read_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off);
374*8eda2d14Spatrick 			oclksel = clksel;
375*8eda2d14Spatrick 			/* Enable the module and also enable the optional func clocks */
376*8eda2d14Spatrick 			if (type == PRCM_USB) {
377*8eda2d14Spatrick 				clksel &= ~O4_CLKCTRL_MODULEMODE_MASK;
378*8eda2d14Spatrick 				clksel |=  /*O4_CLKCTRL_MODULEMODE_ENABLE*/2;
379*8eda2d14Spatrick 
380*8eda2d14Spatrick 				clksel |= (0x1 << 15); /* USB-HOST clock control: FUNC48MCLK */
381*8eda2d14Spatrick 			}
382*8eda2d14Spatrick 
383*8eda2d14Spatrick 			break;
384*8eda2d14Spatrick 
385*8eda2d14Spatrick 		default:
386*8eda2d14Spatrick 			panic("%s: invalid type %d", type);
387*8eda2d14Spatrick 			return (EINVAL);
388*8eda2d14Spatrick 	}
389*8eda2d14Spatrick 	bus_space_write_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off, clksel);
390*8eda2d14Spatrick 
391*8eda2d14Spatrick 	/* Try MAX_MODULE_ENABLE_WAIT number of times to check if enabled */
392*8eda2d14Spatrick 	for (i = 0; i < O4_MAX_MODULE_ENABLE_WAIT; i++) {
393*8eda2d14Spatrick 		clksel = bus_space_read_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off);
394*8eda2d14Spatrick 		if ((clksel & O4_CLKCTRL_IDLEST_MASK) == O4_CLKCTRL_IDLEST_ENABLED)
395*8eda2d14Spatrick 			break;
396*8eda2d14Spatrick 	}
397*8eda2d14Spatrick 
398*8eda2d14Spatrick 	/* Check the enabled state */
399*8eda2d14Spatrick 	if ((clksel & O4_CLKCTRL_IDLEST_MASK) != O4_CLKCTRL_IDLEST_ENABLED) {
400*8eda2d14Spatrick 		printf("Error: HERE failed to enable module with clock %d\n", type);
401*8eda2d14Spatrick 		printf("Error: 0x%08x => 0x%08x\n", clksel_reg_off, clksel);
402*8eda2d14Spatrick 		return (ETIMEDOUT);
403*8eda2d14Spatrick 	}
404*8eda2d14Spatrick 
405*8eda2d14Spatrick 	return (0);
406*8eda2d14Spatrick }
407*8eda2d14Spatrick 
408*8eda2d14Spatrick int
409*8eda2d14Spatrick prcm_v4_hsusbhost_set_source(int clk, int clksrc)
410*8eda2d14Spatrick {
411*8eda2d14Spatrick 	struct prcm_softc *sc = prcm_cd.cd_devs[0];
412*8eda2d14Spatrick 	uint32_t clksel_reg_off;
413*8eda2d14Spatrick 	uint32_t clksel;
414*8eda2d14Spatrick 	unsigned int bit;
415*8eda2d14Spatrick 
416*8eda2d14Spatrick 	if (clk == PRCM_USBP1_PHY)
417*8eda2d14Spatrick 		bit = 24;
418*8eda2d14Spatrick 	else if (clk != PRCM_USBP2_PHY)
419*8eda2d14Spatrick 		bit = 25;
420*8eda2d14Spatrick 	else
421*8eda2d14Spatrick 		return (-EINVAL);
422*8eda2d14Spatrick 
423*8eda2d14Spatrick 	/* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */
424*8eda2d14Spatrick 	clksel_reg_off = O4_L3INIT_CM2_OFFSET + 0x58;
425*8eda2d14Spatrick 	clksel = bus_space_read_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off);
426*8eda2d14Spatrick 
427*8eda2d14Spatrick 	/* XXX: Set the clock source to either external or internal */
428*8eda2d14Spatrick 	if (clksrc == 0)
429*8eda2d14Spatrick 		clksel |= (0x1 << bit);
430*8eda2d14Spatrick 	else
431*8eda2d14Spatrick 		clksel &= ~(0x1 << bit);
432*8eda2d14Spatrick 
433*8eda2d14Spatrick 	bus_space_write_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off, clksel);
434*8eda2d14Spatrick 
435*8eda2d14Spatrick 	return (0);
436*8eda2d14Spatrick }
437*8eda2d14Spatrick 
438*8eda2d14Spatrick /*
439*8eda2d14Spatrick  * OMAP35xx Power, Reset, and Clock Management Reference Guide
440*8eda2d14Spatrick  * (sprufa5.pdf) and AM/DM37x Multimedia Device Technical Reference
441*8eda2d14Spatrick  * Manual (sprugn4h.pdf) note that DPLL5 provides a 120MHz clock for
442*8eda2d14Spatrick  * peripheral domain modules (page 107 and page 302).
443*8eda2d14Spatrick  * The reference clock for DPLL5 is DPLL5_ALWON_FCLK which is
444*8eda2d14Spatrick  * SYS_CLK, running at 13MHz.
445*8eda2d14Spatrick  */
446*8eda2d14Spatrick int
447*8eda2d14Spatrick prcm_setup_dpll5(struct prcm_softc *sc)
448*8eda2d14Spatrick {
449*8eda2d14Spatrick 	uint32_t val;
450*8eda2d14Spatrick 
451*8eda2d14Spatrick 	/*
452*8eda2d14Spatrick 	 * We need to set the multiplier and divider values for PLL.
453*8eda2d14Spatrick 	 * To end up with 120MHz we take SYS_CLK, divide by it and multiply
454*8eda2d14Spatrick 	 * with 120 (sprugn4h.pdf, 13.4.11.4.1 SSC Configuration)
455*8eda2d14Spatrick 	 */
456*8eda2d14Spatrick 	val = ((120 & 0x7ff) << 8) | ((SYS_CLK - 1) & 0x7f);
457*8eda2d14Spatrick 	bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL4_PLL, val);
458*8eda2d14Spatrick 
459*8eda2d14Spatrick 	/* Clock divider from the PLL to the 120MHz clock. */
460*8eda2d14Spatrick 	bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL5_PLL, val);
461*8eda2d14Spatrick 
462*8eda2d14Spatrick 	/*
463*8eda2d14Spatrick 	 * spruf98o.pdf, page 2319:
464*8eda2d14Spatrick 	 * PERIPH2_DPLL_FREQSEL is 0x7 1.75MHz to 2.1MHz
465*8eda2d14Spatrick 	 * EN_PERIPH2_DPLL is 0x7
466*8eda2d14Spatrick 	 */
467*8eda2d14Spatrick 	val = (7 << 4) | (7 << 0);
468*8eda2d14Spatrick 	bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKEN2_PLL, val);
469*8eda2d14Spatrick 
470*8eda2d14Spatrick 	/* Disable the interconnect clock auto-idle. */
471*8eda2d14Spatrick 	bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_AUTOIDLE2_PLL, 0x0);
472*8eda2d14Spatrick 
473*8eda2d14Spatrick 	/* Wait until DPLL5 is locked and there's clock activity. */
474*8eda2d14Spatrick 	while ((val = bus_space_read_4(sc->sc_iot, sc->sc_prcm,
475*8eda2d14Spatrick 	    CM_IDLEST_CKGEN) & 0x01) == 0x00) {
476*8eda2d14Spatrick #ifdef DIAGNOSTIC
477*8eda2d14Spatrick 		printf("CM_IDLEST_PLL = 0x%08x\n", val);
478*8eda2d14Spatrick #endif
479*8eda2d14Spatrick 	}
480*8eda2d14Spatrick 
481*8eda2d14Spatrick 	return 0;
482*8eda2d14Spatrick }
483