1 /* $NetBSD: pxa2x0_ohci.c,v 1.6 2009/08/09 06:12:34 kiyohara Exp $ */
2 /* $OpenBSD: pxa2x0_ohci.c,v 1.19 2005/04/08 02:32:54 dlg Exp $ */
5 * Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include <sys/param.h>
21 #include <sys/systm.h>
22 #include <sys/device.h>
23 #include <sys/kernel.h>
25 #include <machine/intr.h>
26 #include <machine/bus.h>
28 #include <dev/usb/usb.h>
29 #include <dev/usb/usbdi.h>
30 #include <dev/usb/usbdivar.h>
31 #include <dev/usb/usb_mem.h>
33 #include <dev/usb/ohcireg.h>
34 #include <dev/usb/ohcivar.h>
36 #include <arm/xscale/pxa2x0cpu.h>
37 #include <arm/xscale/pxa2x0reg.h>
38 #include <arm/xscale/pxa2x0var.h>
39 #include <arm/xscale/pxa2x0_gpio.h>
41 struct pxaohci_softc
{
48 static void pxaohci_power(int, void *);
50 static void pxaohci_enable(struct pxaohci_softc
*);
51 static void pxaohci_disable(struct pxaohci_softc
*);
53 #define HREAD4(sc,r) bus_space_read_4((sc)->sc.iot, (sc)->sc.ioh, (r))
54 #define HWRITE4(sc,r,v) bus_space_write_4((sc)->sc.iot, (sc)->sc.ioh, (r), (v))
57 pxaohci_match(device_t parent
, struct cfdata
*cf
, void *aux
)
59 struct pxaip_attach_args
*pxa
= aux
;
61 if (CPU_IS_PXA270
&& strcmp(pxa
->pxa_name
, cf
->cf_name
) == 0) {
62 pxa
->pxa_size
= PXA2X0_USBHC_SIZE
;
69 pxaohci_attach(device_t parent
, device_t self
, void *aux
)
71 struct pxaohci_softc
*sc
= device_private(self
);
72 struct pxaip_attach_args
*pxa
= aux
;
77 //extern int ohcidebug;
82 sc
->sc
.iot
= pxa
->pxa_iot
;
83 sc
->sc
.sc_bus
.dmatag
= pxa
->pxa_dmat
;
87 sc
->sc
.sc_bus
.hci_private
= sc
;
93 if (bus_space_map(sc
->sc
.iot
, pxa
->pxa_addr
, pxa
->pxa_size
, 0,
95 aprint_error_dev(sc
->sc
.sc_dev
, "couldn't map memory space\n");
98 sc
->sc
.sc_size
= pxa
->pxa_size
;
100 /* XXX copied from ohci_pci.c. needed? */
101 bus_space_barrier(sc
->sc
.iot
, sc
->sc
.ioh
, 0, sc
->sc
.sc_size
,
102 BUS_SPACE_BARRIER_READ
|BUS_SPACE_BARRIER_WRITE
);
104 /* start the usb clock */
105 pxa2x0_clkman_config(CKEN_USBHC
, 1);
108 /* Disable interrupts, so we don't get any spurious ones. */
109 bus_space_write_4(sc
->sc
.iot
, sc
->sc
.ioh
, OHCI_INTERRUPT_DISABLE
,
112 sc
->sc_ih
= pxa2x0_intr_establish(PXA2X0_INT_USBH1
, IPL_USB
,
114 if (sc
->sc_ih
== NULL
) {
115 aprint_error_dev(sc
->sc
.sc_dev
,
116 "unable to establish interrupt\n");
120 strlcpy(sc
->sc
.sc_vendor
, "PXA27x", sizeof(sc
->sc
.sc_vendor
));
121 r
= ohci_init(&sc
->sc
);
122 if (r
!= USBD_NORMAL_COMPLETION
) {
123 aprint_error_dev(sc
->sc
.sc_dev
, "init failed, error=%d\n", r
);
128 sc
->sc
.sc_powerhook
= powerhook_establish(sc
->sc
.sc_bus
.bdev
.dv_xname
,
130 if (sc
->sc
.sc_powerhook
== NULL
) {
131 aprint_error("%s: cannot establish powerhook\n",
132 sc
->sc
.sc_dev
->sc_bus
.bdev
.dv_xname
);
136 sc
->sc
.sc_child
= config_found(self
, &sc
->sc
.sc_bus
, usbctlprint
);
141 pxa2x0_intr_disestablish(sc
->sc_ih
);
145 pxa2x0_clkman_config(CKEN_USBHC
, 0);
146 bus_space_unmap(sc
->sc
.iot
, sc
->sc
.ioh
, sc
->sc
.sc_size
);
151 pxaohci_detach(device_t self
, int flags
)
153 struct pxaohci_softc
*sc
= device_private(self
);
156 error
= ohci_detach(&sc
->sc
, flags
);
161 if (sc
->sc
.sc_powerhook
) {
162 powerhook_disestablish(sc
->sc
.sc_powerhook
);
163 sc
->sc
.sc_powerhook
= NULL
;
168 pxa2x0_intr_disestablish(sc
->sc_ih
);
175 pxa2x0_clkman_config(CKEN_USBHC
, 0);
177 if (sc
->sc
.sc_size
) {
178 bus_space_unmap(sc
->sc
.iot
, sc
->sc
.ioh
, sc
->sc
.sc_size
);
187 pxaohci_power(int why
, void *arg
)
189 struct pxaohci_softc
*sc
= (struct pxaohci_softc
*)arg
;
193 sc
->sc
.sc_bus
.use_polling
++;
198 ohci_power(why
, &sc
->sc
);
200 pxa2x0_clkman_config(CKEN_USBHC
, 0);
204 pxa2x0_clkman_config(CKEN_USBHC
, 1);
207 ohci_power(why
, &sc
->sc
);
211 sc
->sc
.sc_bus
.use_polling
--;
217 pxaohci_enable(struct pxaohci_softc
*sc
)
221 /* Full host reset */
222 hr
= HREAD4(sc
, USBHC_HR
);
223 HWRITE4(sc
, USBHC_HR
, (hr
& USBHC_HR_MASK
) | USBHC_HR_FHR
);
225 DELAY(USBHC_RST_WAIT
);
227 hr
= HREAD4(sc
, USBHC_HR
);
228 HWRITE4(sc
, USBHC_HR
, (hr
& USBHC_HR_MASK
) & ~(USBHC_HR_FHR
));
230 /* Force system bus interface reset */
231 hr
= HREAD4(sc
, USBHC_HR
);
232 HWRITE4(sc
, USBHC_HR
, (hr
& USBHC_HR_MASK
) | USBHC_HR_FSBIR
);
234 while (HREAD4(sc
, USBHC_HR
) & USBHC_HR_FSBIR
)
237 /* Enable the ports (physically only one, only enable that one?) */
238 hr
= HREAD4(sc
, USBHC_HR
);
239 HWRITE4(sc
, USBHC_HR
, (hr
& USBHC_HR_MASK
) & ~(USBHC_HR_SSE
));
240 hr
= HREAD4(sc
, USBHC_HR
);
241 HWRITE4(sc
, USBHC_HR
, (hr
& USBHC_HR_MASK
) &
242 ~(USBHC_HR_SSEP1
| USBHC_HR_SSEP2
| USBHC_HR_SSEP3
));
243 HWRITE4(sc
, USBHC_HIE
, USBHC_HIE_RWIE
| USBHC_HIE_UPRIE
);
245 hr
= HREAD4(sc
, USBHC_UHCRHDA
);
249 pxaohci_disable(struct pxaohci_softc
*sc
)
253 /* Full host reset */
254 hr
= HREAD4(sc
, USBHC_HR
);
255 HWRITE4(sc
, USBHC_HR
, (hr
& USBHC_HR_MASK
) | USBHC_HR_FHR
);
257 DELAY(USBHC_RST_WAIT
);
259 hr
= HREAD4(sc
, USBHC_HR
);
260 HWRITE4(sc
, USBHC_HR
, (hr
& USBHC_HR_MASK
) & ~(USBHC_HR_FHR
));
264 CFATTACH_DECL2_NEW(pxaohci
, sizeof(struct pxaohci_softc
),
265 pxaohci_match
, pxaohci_attach
, pxaohci_detach
, ohci_activate
, NULL
,