5 * Copyright (c) 2015 Stanislav Galabov. All rights reserved.
6 * Copyright (c) 2010,2011 Aleksandr Rybalko. All rights reserved.
7 * Copyright (c) 2007-2008 Hans Petter Selasky. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include <sys/stdint.h>
32 #include <sys/stddef.h>
33 #include <sys/param.h>
34 #include <sys/queue.h>
35 #include <sys/types.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
39 #include <sys/module.h>
41 #include <sys/mutex.h>
42 #include <sys/condvar.h>
43 #include <sys/sysctl.h>
45 #include <sys/unistd.h>
46 #include <sys/callout.h>
47 #include <sys/malloc.h>
51 #include <dev/usb/usb.h>
52 #include <dev/usb/usbdi.h>
54 #include <dev/usb/usb_core.h>
55 #include <dev/usb/usb_busdma.h>
56 #include <dev/usb/usb_process.h>
57 #include <dev/usb/usb_util.h>
59 #include <dev/usb/usb_controller.h>
60 #include <dev/usb/usb_bus.h>
62 #include <dev/usb/controller/ehci.h>
64 #include <mips/rt305x/rt305xreg.h>
65 #include <mips/rt305x/rt305x_sysctlvar.h>
67 #define EHCI_HC_DEVSTR "Ralink integrated USB 2.0 controller"
69 static device_probe_t ehci_obio_probe
;
70 static device_attach_t ehci_obio_attach
;
71 static device_detach_t ehci_obio_detach
;
74 ehci_obio_probe(device_t self
)
76 device_set_desc(self
, EHCI_HC_DEVSTR
);
78 return (BUS_PROBE_DEFAULT
);
82 ehci_obio_attach(device_t self
)
84 ehci_softc_t
*sc
= device_get_softc(self
);
89 /* setup controller interface softc */
90 reg
= rt305x_sysctl_get(SYSCTL_SYSCFG1
);
91 reg
|= SYSCTL_SYSCFG1_USB0_HOST_MODE
;
92 rt305x_sysctl_set(SYSCTL_SYSCFG1
, reg
);
94 reg
= rt305x_sysctl_get(SYSCTL_CLKCFG1
);
95 reg
|= SYSCTL_CLKCFG1_UPHY0_CLK_EN
;
97 reg
|= SYSCTL_CLKCFG1_UPHY1_CLK_EN
;
99 rt305x_sysctl_set(SYSCTL_CLKCFG1
, reg
);
101 reg
= rt305x_sysctl_get(SYSCTL_RSTCTRL
);
102 reg
|= SYSCTL_RSTCTRL_UPHY0
| SYSCTL_RSTCTRL_UPHY1
;
103 rt305x_sysctl_set(SYSCTL_RSTCTRL
, reg
);
104 reg
&= ~(SYSCTL_RSTCTRL_UPHY0
| SYSCTL_RSTCTRL_UPHY1
);
106 rt305x_sysctl_set(SYSCTL_RSTCTRL
, reg
);
109 /* initialise some bus fields */
110 sc
->sc_bus
.parent
= self
;
111 sc
->sc_bus
.devices
= sc
->sc_devices
;
112 sc
->sc_bus
.devices_max
= EHCI_MAX_DEVICES
;
113 sc
->sc_bus
.dma_bits
= 32;
115 /* get all DMA memory */
116 if (usb_bus_mem_alloc_all(&sc
->sc_bus
,
117 USB_GET_DMA_TAG(self
), &ehci_iterate_hw_softc
)) {
123 sc
->sc_io_res
= bus_alloc_resource_any(self
, SYS_RES_MEMORY
, &rid
,
125 if (!sc
->sc_io_res
) {
126 device_printf(self
, "Could not map memory\n");
129 sc
->sc_io_tag
= rman_get_bustag(sc
->sc_io_res
);
130 sc
->sc_io_hdl
= rman_get_bushandle(sc
->sc_io_res
);
131 sc
->sc_io_size
= rman_get_size(sc
->sc_io_res
);
134 sc
->sc_irq_res
= bus_alloc_resource_any(self
, SYS_RES_IRQ
, &rid
,
135 RF_SHAREABLE
| RF_ACTIVE
);
136 if (sc
->sc_irq_res
== NULL
) {
137 device_printf(self
, "Could not allocate irq\n");
141 sc
->sc_bus
.bdev
= device_add_child(self
, "usbus", -1);
142 if (!(sc
->sc_bus
.bdev
)) {
143 device_printf(self
, "Could not add USB device\n");
146 device_set_ivars(sc
->sc_bus
.bdev
, &sc
->sc_bus
);
147 device_set_desc(sc
->sc_bus
.bdev
, EHCI_HC_DEVSTR
);
149 sprintf(sc
->sc_vendor
, "Ralink");
151 err
= bus_setup_intr(self
, sc
->sc_irq_res
, INTR_TYPE_BIO
| INTR_MPSAFE
,
152 NULL
, (driver_intr_t
*)ehci_interrupt
, sc
, &sc
->sc_intr_hdl
);
154 device_printf(self
, "Could not setup irq, %d\n", err
);
155 sc
->sc_intr_hdl
= NULL
;
161 err
= device_probe_and_attach(sc
->sc_bus
.bdev
);
164 device_printf(self
, "USB init failed err=%d\n", err
);
170 ehci_obio_detach(self
);
175 ehci_obio_detach(device_t self
)
177 ehci_softc_t
*sc
= device_get_softc(self
);
181 if (sc
->sc_bus
.bdev
) {
182 bdev
= sc
->sc_bus
.bdev
;
184 device_delete_child(self
, bdev
);
186 /* during module unload there are lots of children leftover */
187 device_delete_children(self
);
189 if (sc
->sc_irq_res
&& sc
->sc_intr_hdl
) {
191 * only call ehci_detach() after ehci_init()
195 /* Stop EHCI clock */
196 rt305x_sysctl_set(SYSCTL_CLKCFG1
,
197 rt305x_sysctl_get(SYSCTL_CLKCFG1
) &
198 ~(SYSCTL_CLKCFG1_UPHY0_CLK_EN
200 | SYSCTL_CLKCFG1_UPHY1_CLK_EN
204 err
= bus_teardown_intr(self
, sc
->sc_irq_res
, sc
->sc_intr_hdl
);
206 device_printf(self
, "Could not tear down irq, %d\n",
208 sc
->sc_intr_hdl
= NULL
;
210 if (sc
->sc_irq_res
) {
211 bus_release_resource(self
, SYS_RES_IRQ
, 0,
213 sc
->sc_irq_res
= NULL
;
216 bus_release_resource(self
, SYS_RES_MEMORY
, 0,
218 sc
->sc_io_res
= NULL
;
220 usb_bus_mem_free_all(&sc
->sc_bus
, &ehci_iterate_hw_softc
);
225 static device_method_t ehci_obio_methods
[] = {
226 /* Device interface */
227 DEVMETHOD(device_probe
, ehci_obio_probe
),
228 DEVMETHOD(device_attach
, ehci_obio_attach
),
229 DEVMETHOD(device_detach
, ehci_obio_detach
),
230 DEVMETHOD(device_suspend
, bus_generic_suspend
),
231 DEVMETHOD(device_resume
, bus_generic_resume
),
232 DEVMETHOD(device_shutdown
, bus_generic_shutdown
),
237 static driver_t ehci_obio_driver
= {
239 .methods
= ehci_obio_methods
,
240 .size
= sizeof(ehci_softc_t
),
243 static devclass_t ehci_obio_devclass
;
245 DRIVER_MODULE(ehci
, obio
, ehci_obio_driver
, ehci_obio_devclass
, 0, 0);