| @@ -24,27 +24,27 @@ | | | @@ -24,27 +24,27 @@ |
24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
27 | * POSSIBILITY OF SUCH DAMAGE. | | 27 | * POSSIBILITY OF SUCH DAMAGE. |
28 | */ | | 28 | */ |
29 | #define USBH_PRIVATE | | 29 | #define USBH_PRIVATE |
30 | | | 30 | |
31 | #include "locators.h" | | 31 | #include "locators.h" |
32 | #include "ohci.h" | | 32 | #include "ohci.h" |
33 | #include "ehci.h" | | 33 | #include "ehci.h" |
34 | | | 34 | |
35 | #include <sys/cdefs.h> | | 35 | #include <sys/cdefs.h> |
36 | | | 36 | |
37 | __KERNEL_RCSID(1, "$NetBSD: awin_usb.c,v 1.7 2013/09/07 19:48:57 matt Exp $"); | | 37 | __KERNEL_RCSID(1, "$NetBSD: awin_usb.c,v 1.8 2013/09/07 22:51:41 matt Exp $"); |
38 | | | 38 | |
39 | #include <sys/bus.h> | | 39 | #include <sys/bus.h> |
40 | #include <sys/device.h> | | 40 | #include <sys/device.h> |
41 | #include <sys/intr.h> | | 41 | #include <sys/intr.h> |
42 | #include <sys/systm.h> | | 42 | #include <sys/systm.h> |
43 | | | 43 | |
44 | #include <arm/allwinner/awin_reg.h> | | 44 | #include <arm/allwinner/awin_reg.h> |
45 | #include <arm/allwinner/awin_var.h> | | 45 | #include <arm/allwinner/awin_var.h> |
46 | | | 46 | |
47 | #include <dev/usb/usb.h> | | 47 | #include <dev/usb/usb.h> |
48 | #include <dev/usb/usbdi.h> | | 48 | #include <dev/usb/usbdi.h> |
49 | #include <dev/usb/usbdivar.h> | | 49 | #include <dev/usb/usbdivar.h> |
50 | #include <dev/usb/usb_mem.h> | | 50 | #include <dev/usb/usb_mem.h> |
| @@ -79,34 +79,26 @@ struct awinusb_softc { | | | @@ -79,34 +79,26 @@ struct awinusb_softc { |
79 | | | 79 | |
80 | struct awinusb_attach_args { | | 80 | struct awinusb_attach_args { |
81 | const char *usbaa_name; | | 81 | const char *usbaa_name; |
82 | bus_dma_tag_t usbaa_dmat; | | 82 | bus_dma_tag_t usbaa_dmat; |
83 | bus_space_tag_t usbaa_bst; | | 83 | bus_space_tag_t usbaa_bst; |
84 | bus_space_handle_t usbaa_bsh; | | 84 | bus_space_handle_t usbaa_bsh; |
85 | bus_space_handle_t usbaa_ccm_bsh; | | 85 | bus_space_handle_t usbaa_ccm_bsh; |
86 | bus_size_t usbaa_size; | | 86 | bus_size_t usbaa_size; |
87 | int usbaa_port; | | 87 | int usbaa_port; |
88 | }; | | 88 | }; |
89 | | | 89 | |
90 | #if NOHCI > 0 | | 90 | #if NOHCI > 0 |
91 | static const int awinusb_ohci_irqs[2] = { AWIN_IRQ_USB3, AWIN_IRQ_USB4 }; | | 91 | static const int awinusb_ohci_irqs[2] = { AWIN_IRQ_USB3, AWIN_IRQ_USB4 }; |
92 | static const uint32_t awinusb_ohci_ahb_gating[2] = { | | | |
93 | AWIN_AHB_GATING0_USB_OHCI0, AWIN_AHB_GATING0_USB_OHCI1, | | | |
94 | }; | | | |
95 | static const uint32_t awinusb_ohci_usb_clk_set[2] = { | | | |
96 | AWIN_USB_CLK_OHCI0_ENABLE|AWIN_USB_CLK_USBPHY_ENABLE|AWIN_USB_CLK_PHY1_ENABLE, | | | |
97 | AWIN_USB_CLK_OHCI1_ENABLE|AWIN_USB_CLK_USBPHY_ENABLE|AWIN_USB_CLK_PHY2_ENABLE, | | | |
98 | }; | | | |
99 | | | | |
100 | | | 92 | |
101 | #ifdef OHCI_DEBUG | | 93 | #ifdef OHCI_DEBUG |
102 | #define OHCI_DPRINTF(x) if (ohcidebug) printf x | | 94 | #define OHCI_DPRINTF(x) if (ohcidebug) printf x |
103 | extern int ohcidebug; | | 95 | extern int ohcidebug; |
104 | #else | | 96 | #else |
105 | #define OHCI_DPRINTF(x) | | 97 | #define OHCI_DPRINTF(x) |
106 | #endif | | 98 | #endif |
107 | | | 99 | |
108 | static int ohci_awinusb_match(device_t, cfdata_t, void *); | | 100 | static int ohci_awinusb_match(device_t, cfdata_t, void *); |
109 | static void ohci_awinusb_attach(device_t, device_t, void *); | | 101 | static void ohci_awinusb_attach(device_t, device_t, void *); |
110 | | | 102 | |
111 | CFATTACH_DECL_NEW(ohci_awinusb, sizeof(struct ohci_softc), | | 103 | CFATTACH_DECL_NEW(ohci_awinusb, sizeof(struct ohci_softc), |
112 | ohci_awinusb_match, ohci_awinusb_attach, NULL, NULL); | | 104 | ohci_awinusb_match, ohci_awinusb_attach, NULL, NULL); |
| @@ -121,32 +113,26 @@ ohci_awinusb_match(device_t parent, cfda | | | @@ -121,32 +113,26 @@ ohci_awinusb_match(device_t parent, cfda |
121 | | | 113 | |
122 | return 1; | | 114 | return 1; |
123 | } | | 115 | } |
124 | | | 116 | |
125 | static void | | 117 | static void |
126 | ohci_awinusb_attach(device_t parent, device_t self, void *aux) | | 118 | ohci_awinusb_attach(device_t parent, device_t self, void *aux) |
127 | { | | 119 | { |
128 | struct awinusb_softc * const usbsc = device_private(parent); | | 120 | struct awinusb_softc * const usbsc = device_private(parent); |
129 | struct ohci_softc * const sc = device_private(self); | | 121 | struct ohci_softc * const sc = device_private(self); |
130 | struct awinusb_attach_args * const usbaa = aux; | | 122 | struct awinusb_attach_args * const usbaa = aux; |
131 | | | 123 | |
132 | sc->sc_dev = self; | | 124 | sc->sc_dev = self; |
133 | | | 125 | |
134 | awin_reg_set_clear(usbaa->usbaa_bst, usbaa->usbaa_ccm_bsh, | | | |
135 | AWIN_AHB_GATING0_REG, awinusb_ohci_ahb_gating[usbaa->usbaa_port], | | | |
136 | 0); | | | |
137 | awin_reg_set_clear(usbaa->usbaa_bst, usbaa->usbaa_ccm_bsh, | | | |
138 | AWIN_USB_CLK_REG, awinusb_ohci_usb_clk_set[usbaa->usbaa_port], 0); | | | |
139 | | | | |
140 | sc->iot = usbaa->usbaa_bst; | | 126 | sc->iot = usbaa->usbaa_bst; |
141 | sc->ioh = usbaa->usbaa_bsh; | | 127 | sc->ioh = usbaa->usbaa_bsh; |
142 | sc->sc_size = usbaa->usbaa_size; | | 128 | sc->sc_size = usbaa->usbaa_size; |
143 | sc->sc_bus.dmatag = usbaa->usbaa_dmat; | | 129 | sc->sc_bus.dmatag = usbaa->usbaa_dmat; |
144 | sc->sc_bus.hci_private = sc; | | 130 | sc->sc_bus.hci_private = sc; |
145 | | | 131 | |
146 | //sc->sc_id_vendor = PCI_VENDOR_ALLWINNER; | | 132 | //sc->sc_id_vendor = PCI_VENDOR_ALLWINNER; |
147 | strlcpy(sc->sc_vendor, "Allwinner", sizeof(sc->sc_vendor)); | | 133 | strlcpy(sc->sc_vendor, "Allwinner", sizeof(sc->sc_vendor)); |
148 | | | 134 | |
149 | aprint_naive(": OHCI USB controller\n"); | | 135 | aprint_naive(": OHCI USB controller\n"); |
150 | aprint_normal(": OHCI USB controller\n"); | | 136 | aprint_normal(": OHCI USB controller\n"); |
151 | | | 137 | |
152 | int error = ohci_init(sc); | | 138 | int error = ohci_init(sc); |
| @@ -171,57 +157,50 @@ ohci_awinusb_attach(device_t parent, dev | | | @@ -171,57 +157,50 @@ ohci_awinusb_attach(device_t parent, dev |
171 | | | 157 | |
172 | #if NEHCI > 0 | | 158 | #if NEHCI > 0 |
173 | #ifdef EHCI_DEBUG | | 159 | #ifdef EHCI_DEBUG |
174 | #define EHCI_DPRINTF(x) if (ehcidebug) printf x | | 160 | #define EHCI_DPRINTF(x) if (ehcidebug) printf x |
175 | extern int ehcidebug; | | 161 | extern int ehcidebug; |
176 | #else | | 162 | #else |
177 | #define EHCI_DPRINTF(x) | | 163 | #define EHCI_DPRINTF(x) |
178 | #endif | | 164 | #endif |
179 | | | 165 | |
180 | static int ehci_awinusb_match(device_t, cfdata_t, void *); | | 166 | static int ehci_awinusb_match(device_t, cfdata_t, void *); |
181 | static void ehci_awinusb_attach(device_t, device_t, void *); | | 167 | static void ehci_awinusb_attach(device_t, device_t, void *); |
182 | | | 168 | |
183 | static const int awinusb_ehci_irqs[2] = { AWIN_IRQ_USB1, AWIN_IRQ_USB2 }; | | 169 | static const int awinusb_ehci_irqs[2] = { AWIN_IRQ_USB1, AWIN_IRQ_USB2 }; |
184 | static const uint32_t awinusb_ehci_ahb_gating[2] = { | | | |
185 | AWIN_AHB_GATING0_USB_EHCI0, AWIN_AHB_GATING0_USB_EHCI1, | | | |
186 | }; | | | |
187 | | | 170 | |
188 | CFATTACH_DECL_NEW(ehci_awinusb, sizeof(struct ehci_softc), | | 171 | CFATTACH_DECL_NEW(ehci_awinusb, sizeof(struct ehci_softc), |
189 | ehci_awinusb_match, ehci_awinusb_attach, NULL, NULL); | | 172 | ehci_awinusb_match, ehci_awinusb_attach, NULL, NULL); |
190 | | | 173 | |
191 | static int | | 174 | static int |
192 | ehci_awinusb_match(device_t parent, cfdata_t cf, void *aux) | | 175 | ehci_awinusb_match(device_t parent, cfdata_t cf, void *aux) |
193 | { | | 176 | { |
194 | struct awinusb_attach_args * const usbaa = aux; | | 177 | struct awinusb_attach_args * const usbaa = aux; |
195 | | | 178 | |
196 | if (strcmp(cf->cf_name, usbaa->usbaa_name)) | | 179 | if (strcmp(cf->cf_name, usbaa->usbaa_name)) |
197 | return 0; | | 180 | return 0; |
198 | | | 181 | |
199 | return 1; | | 182 | return 1; |
200 | } | | 183 | } |
201 | | | 184 | |
202 | static void | | 185 | static void |
203 | ehci_awinusb_attach(device_t parent, device_t self, void *aux) | | 186 | ehci_awinusb_attach(device_t parent, device_t self, void *aux) |
204 | { | | 187 | { |
205 | struct awinusb_softc * const usbsc = device_private(parent); | | 188 | struct awinusb_softc * const usbsc = device_private(parent); |
206 | struct ehci_softc * const sc = device_private(self); | | 189 | struct ehci_softc * const sc = device_private(self); |
207 | struct awinusb_attach_args * const usbaa = aux; | | 190 | struct awinusb_attach_args * const usbaa = aux; |
208 | | | 191 | |
209 | sc->sc_dev = self; | | 192 | sc->sc_dev = self; |
210 | | | 193 | |
211 | awin_reg_set_clear(usbaa->usbaa_bst, usbaa->usbaa_ccm_bsh, | | | |
212 | AWIN_AHB_GATING0_REG, awinusb_ehci_ahb_gating[usbaa->usbaa_port], | | | |
213 | 0); | | | |
214 | | | | |
215 | sc->iot = usbaa->usbaa_bst; | | 194 | sc->iot = usbaa->usbaa_bst; |
216 | sc->ioh = usbaa->usbaa_bsh; | | 195 | sc->ioh = usbaa->usbaa_bsh; |
217 | sc->sc_size = usbaa->usbaa_size; | | 196 | sc->sc_size = usbaa->usbaa_size; |
218 | sc->sc_bus.dmatag = usbaa->usbaa_dmat; | | 197 | sc->sc_bus.dmatag = usbaa->usbaa_dmat; |
219 | sc->sc_bus.hci_private = sc; | | 198 | sc->sc_bus.hci_private = sc; |
220 | sc->sc_bus.usbrev = USBREV_2_0; | | 199 | sc->sc_bus.usbrev = USBREV_2_0; |
221 | sc->sc_ncomp = 0; | | 200 | sc->sc_ncomp = 0; |
222 | if (usbsc->usbsc_ohci_dev != NULL) { | | 201 | if (usbsc->usbsc_ohci_dev != NULL) { |
223 | sc->sc_comps[sc->sc_ncomp++] = usbsc->usbsc_ohci_dev; | | 202 | sc->sc_comps[sc->sc_ncomp++] = usbsc->usbsc_ohci_dev; |
224 | } | | 203 | } |
225 | | | 204 | |
226 | //sc->sc_id_vendor = PCI_VENDOR_ALLWINNER; | | 205 | //sc->sc_id_vendor = PCI_VENDOR_ALLWINNER; |
227 | strlcpy(sc->sc_vendor, "Allwinner", sizeof(sc->sc_vendor)); | | 206 | strlcpy(sc->sc_vendor, "Allwinner", sizeof(sc->sc_vendor)); |
| @@ -288,26 +267,46 @@ awin_usb_phy_write(struct awinusb_softc | | | @@ -288,26 +267,46 @@ awin_usb_phy_write(struct awinusb_softc |
288 | static int awinusb_match(device_t, cfdata_t, void *); | | 267 | static int awinusb_match(device_t, cfdata_t, void *); |
289 | static void awinusb_attach(device_t, device_t, void *); | | 268 | static void awinusb_attach(device_t, device_t, void *); |
290 | | | 269 | |
291 | CFATTACH_DECL_NEW(awin_usb, sizeof(struct awinusb_softc), | | 270 | CFATTACH_DECL_NEW(awin_usb, sizeof(struct awinusb_softc), |
292 | awinusb_match, awinusb_attach, NULL, NULL); | | 271 | awinusb_match, awinusb_attach, NULL, NULL); |
293 | | | 272 | |
294 | static int awinusb_ports; | | 273 | static int awinusb_ports; |
295 | | | 274 | |
296 | static const char awinusb_drvpin_names[2][8] = { "usb1drv", "usb2drv" }; | | 275 | static const char awinusb_drvpin_names[2][8] = { "usb1drv", "usb2drv" }; |
297 | static const bus_size_t awinusb_dram_hpcr_regs[2] = { | | 276 | static const bus_size_t awinusb_dram_hpcr_regs[2] = { |
298 | AWIN_DRAM_HPCR_USB1_REG, | | 277 | AWIN_DRAM_HPCR_USB1_REG, |
299 | AWIN_DRAM_HPCR_USB2_REG, | | 278 | AWIN_DRAM_HPCR_USB2_REG, |
300 | }; | | 279 | }; |
| | | 280 | static const uint32_t awinusb_ahb_gating[2] = { |
| | | 281 | #if NOHCI > 0 |
| | | 282 | AWIN_AHB_GATING0_USB_OHCI0 | |
| | | 283 | #endif |
| | | 284 | AWIN_AHB_GATING0_USB_EHCI0, |
| | | 285 | #if NOHCI > 0 |
| | | 286 | AWIN_AHB_GATING0_USB_OHCI1 | |
| | | 287 | #endif |
| | | 288 | AWIN_AHB_GATING0_USB_EHCI1, |
| | | 289 | }; |
| | | 290 | static const uint32_t awinusb_usb_clk_set[2] = { |
| | | 291 | #if NOHCI > 0 |
| | | 292 | AWIN_USB_CLK_OHCI0_ENABLE | |
| | | 293 | #endif |
| | | 294 | AWIN_USB_CLK_USBPHY_ENABLE|AWIN_USB_CLK_PHY1_ENABLE, |
| | | 295 | #if NOHCI > 0 |
| | | 296 | AWIN_USB_CLK_OHCI1_ENABLE | |
| | | 297 | #endif |
| | | 298 | AWIN_USB_CLK_USBPHY_ENABLE|AWIN_USB_CLK_PHY2_ENABLE, |
| | | 299 | }; |
301 | | | 300 | |
302 | int | | 301 | int |
303 | awinusb_match(device_t parent, cfdata_t cf, void *aux) | | 302 | awinusb_match(device_t parent, cfdata_t cf, void *aux) |
304 | { | | 303 | { |
305 | struct awinio_attach_args * const aio = aux; | | 304 | struct awinio_attach_args * const aio = aux; |
306 | const struct awin_locators * const loc = &aio->aio_loc; | | 305 | const struct awin_locators * const loc = &aio->aio_loc; |
307 | | | 306 | |
308 | KASSERT(loc->loc_port != AWINIOCF_PORT_DEFAULT); | | 307 | KASSERT(loc->loc_port != AWINIOCF_PORT_DEFAULT); |
309 | KASSERT(!strcmp(cf->cf_name, loc->loc_name)); | | 308 | KASSERT(!strcmp(cf->cf_name, loc->loc_name)); |
310 | KASSERT(cf->cf_loc[AWINIOCF_PORT] == AWINIOCF_PORT_DEFAULT | | 309 | KASSERT(cf->cf_loc[AWINIOCF_PORT] == AWINIOCF_PORT_DEFAULT |
311 | || cf->cf_loc[AWINIOCF_PORT] == loc->loc_port); | | 310 | || cf->cf_loc[AWINIOCF_PORT] == loc->loc_port); |
312 | KASSERT((awinusb_ports & __BIT(loc->loc_port)) == 0); | | 311 | KASSERT((awinusb_ports & __BIT(loc->loc_port)) == 0); |
313 | | | 312 | |
| @@ -334,37 +333,44 @@ awinusb_attach(device_t parent, device_t | | | @@ -334,37 +333,44 @@ awinusb_attach(device_t parent, device_t |
334 | loc->loc_offset + AWIN_OHCI_OFFSET, AWIN_OHCI_SIZE, | | 333 | loc->loc_offset + AWIN_OHCI_OFFSET, AWIN_OHCI_SIZE, |
335 | &usbsc->usbsc_ohci_bsh); | | 334 | &usbsc->usbsc_ohci_bsh); |
336 | bus_space_subregion(usbsc->usbsc_bst, aio->aio_core_bsh, | | 335 | bus_space_subregion(usbsc->usbsc_bst, aio->aio_core_bsh, |
337 | AWIN_USB0_OFFSET + AWIN_USB0_PHY_CSR_REG, 4, | | 336 | AWIN_USB0_OFFSET + AWIN_USB0_PHY_CSR_REG, 4, |
338 | &usbsc->usbsc_usb0_phy_csr_bsh); | | 337 | &usbsc->usbsc_usb0_phy_csr_bsh); |
339 | | | 338 | |
340 | aprint_naive("\n"); | | 339 | aprint_naive("\n"); |
341 | aprint_normal("\n"); | | 340 | aprint_normal("\n"); |
342 | | | 341 | |
343 | /* | | 342 | /* |
344 | * Access to the USB phy is off USB0 so make sure it's on. | | 343 | * Access to the USB phy is off USB0 so make sure it's on. |
345 | */ | | 344 | */ |
346 | awin_reg_set_clear(usbsc->usbsc_bst, aio->aio_ccm_bsh, | | 345 | awin_reg_set_clear(usbsc->usbsc_bst, aio->aio_ccm_bsh, |
347 | AWIN_AHB_GATING0_REG, AWIN_AHB_GATING0_USB0, 0); | | 346 | AWIN_AHB_GATING0_REG, |
| | | 347 | AWIN_AHB_GATING0_USB0 | awinusb_ahb_gating[loc->loc_port], 0); |
| | | 348 | |
| | | 349 | |
| | | 350 | /* |
| | | 351 | * Enable the USB phy for this port. |
| | | 352 | */ |
| | | 353 | awin_reg_set_clear(usbsc->usbsc_bst, aio->aio_ccm_bsh, |
| | | 354 | AWIN_USB_CLK_REG, awinusb_usb_clk_set[loc->loc_port], 0); |
348 | | | 355 | |
| | | 356 | /* |
| | | 357 | * Allow USB DMA engine access to the DRAM. |
| | | 358 | */ |
349 | awin_reg_set_clear(usbsc->usbsc_bst, aio->aio_core_bsh, | | 359 | awin_reg_set_clear(usbsc->usbsc_bst, aio->aio_core_bsh, |
350 | loc->loc_offset + AWIN_USB_PMU_IRQ_REG, | | 360 | loc->loc_offset + AWIN_USB_PMU_IRQ_REG, |
351 | AWIN_USB_PMU_IRQ_AHB_INCR8 | AWIN_USB_PMU_IRQ_AHB_INCR4 | | 361 | AWIN_USB_PMU_IRQ_AHB_INCR8 | AWIN_USB_PMU_IRQ_AHB_INCR4 |
352 | | AWIN_USB_PMU_IRQ_AHB_INCRX | AWIN_USB_PMU_IRQ_ULPI_BYPASS, | | 362 | | AWIN_USB_PMU_IRQ_AHB_INCRX | AWIN_USB_PMU_IRQ_ULPI_BYPASS, |
353 | 0); | | 363 | 0); |
354 | | | | |
355 | /* | | | |
356 | * Allow USB DMA engine access to the DRAM. | | | |
357 | */ | | | |
358 | awin_reg_set_clear(usbsc->usbsc_bst, aio->aio_core_bsh, | | 364 | awin_reg_set_clear(usbsc->usbsc_bst, aio->aio_core_bsh, |
359 | AWIN_DRAM_OFFSET + awinusb_dram_hpcr_regs[loc->loc_port], | | 365 | AWIN_DRAM_OFFSET + awinusb_dram_hpcr_regs[loc->loc_port], |
360 | AWIN_DRAM_HPCR_ACCESS_EN, 0); | | 366 | AWIN_DRAM_HPCR_ACCESS_EN, 0); |
361 | | | 367 | |
362 | /* initialize the USB phy */ | | 368 | /* initialize the USB phy */ |
363 | awin_usb_phy_write(usbsc, 0x20, 0x14, 5); | | 369 | awin_usb_phy_write(usbsc, 0x20, 0x14, 5); |
364 | awin_usb_phy_write(usbsc, 0x2a, 0x03, 2); | | 370 | awin_usb_phy_write(usbsc, 0x2a, 0x03, 2); |
365 | | | 371 | |
366 | /* | | 372 | /* |
367 | * Now get the GPIO that enables the power to the port and | | 373 | * Now get the GPIO that enables the power to the port and |
368 | * turn it on. | | 374 | * turn it on. |
369 | */ | | 375 | */ |
370 | if (awin_gpio_pin_reserve(awinusb_drvpin_names[loc->loc_port], | | 376 | if (awin_gpio_pin_reserve(awinusb_drvpin_names[loc->loc_port], |