ohci_pci.c revision 184610
1/*- 2 * Copyright (c) 1998 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Lennart Augustsson (augustss@carlstedt.se) at 7 * Carlstedt Research & Technology. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 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. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the NetBSD 20 * Foundation, Inc. and its contributors. 21 * 4. Neither the name of The NetBSD Foundation nor the names of its 22 * contributors may be used to endorse or promote products derived 23 * from this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38#include <sys/cdefs.h> 39__FBSDID("$FreeBSD: head/sys/dev/usb2/controller/ohci2_pci.c 184610 2008-11-04 02:31:03Z alfred $"); 40 41/* 42 * USB Open Host Controller driver. 43 * 44 * OHCI spec: http://www.intel.com/design/usb/ohci11d.pdf 45 */ 46 47/* The low level controller code for OHCI has been split into 48 * PCI probes and OHCI specific code. This was done to facilitate the 49 * sharing of code between *BSD's 50 */ 51 52#include <dev/usb2/include/usb2_standard.h> 53#include <dev/usb2/include/usb2_mfunc.h> 54#include <dev/usb2/include/usb2_error.h> 55#include <dev/usb2/include/usb2_defs.h> 56 57#include <dev/usb2/core/usb2_core.h> 58#include <dev/usb2/core/usb2_busdma.h> 59#include <dev/usb2/core/usb2_process.h> 60#include <dev/usb2/core/usb2_config_td.h> 61#include <dev/usb2/core/usb2_sw_transfer.h> 62#include <dev/usb2/core/usb2_util.h> 63 64#include <dev/usb2/controller/usb2_controller.h> 65#include <dev/usb2/controller/usb2_bus.h> 66#include <dev/usb2/controller/usb2_pci.h> 67#include <dev/usb2/controller/ohci2.h> 68 69#define PCI_OHCI_VENDORID_ACERLABS 0x10b9 70#define PCI_OHCI_VENDORID_AMD 0x1022 71#define PCI_OHCI_VENDORID_APPLE 0x106b 72#define PCI_OHCI_VENDORID_ATI 0x1002 73#define PCI_OHCI_VENDORID_CMDTECH 0x1095 74#define PCI_OHCI_VENDORID_NEC 0x1033 75#define PCI_OHCI_VENDORID_NVIDIA 0x12D2 76#define PCI_OHCI_VENDORID_NVIDIA2 0x10DE 77#define PCI_OHCI_VENDORID_OPTI 0x1045 78#define PCI_OHCI_VENDORID_SIS 0x1039 79#define PCI_OHCI_VENDORID_SUN 0x108e 80 81#define PCI_OHCI_BASE_REG 0x10 82 83static device_probe_t ohci_pci_probe; 84static device_attach_t ohci_pci_attach; 85static device_detach_t ohci_pci_detach; 86static device_suspend_t ohci_pci_suspend; 87static device_resume_t ohci_pci_resume; 88 89static int 90ohci_pci_suspend(device_t self) 91{ 92 ohci_softc_t *sc = device_get_softc(self); 93 int err; 94 95 err = bus_generic_suspend(self); 96 if (err) { 97 return (err); 98 } 99 ohci_suspend(sc); 100 return (0); 101} 102 103static int 104ohci_pci_resume(device_t self) 105{ 106 ohci_softc_t *sc = device_get_softc(self); 107 uint32_t reg, int_line; 108 109 if (pci_get_powerstate(self) != PCI_POWERSTATE_D0) { 110 device_printf(self, "chip is in D%d mode " 111 "-- setting to D0\n", pci_get_powerstate(self)); 112 reg = pci_read_config(self, PCI_CBMEM, 4); 113 int_line = pci_read_config(self, PCIR_INTLINE, 4); 114 pci_set_powerstate(self, PCI_POWERSTATE_D0); 115 pci_write_config(self, PCI_CBMEM, reg, 4); 116 pci_write_config(self, PCIR_INTLINE, int_line, 4); 117 } 118 ohci_resume(sc); 119 120 bus_generic_resume(self); 121 return (0); 122} 123 124static const char * 125ohci_pci_match(device_t self) 126{ 127 uint32_t device_id = pci_get_devid(self); 128 129 switch (device_id) { 130 case 0x523710b9: 131 return ("AcerLabs M5237 (Aladdin-V) USB controller"); 132 133 case 0x740c1022: 134 return ("AMD-756 USB Controller"); 135 136 case 0x74141022: 137 return ("AMD-766 USB Controller"); 138 139 case 0x43741002: 140 return "ATI SB400 USB Controller"; 141 case 0x43751002: 142 return "ATI SB400 USB Controller"; 143 144 case 0x06701095: 145 return ("CMD Tech 670 (USB0670) USB controller"); 146 147 case 0x06731095: 148 return ("CMD Tech 673 (USB0673) USB controller"); 149 150 case 0xc8611045: 151 return ("OPTi 82C861 (FireLink) USB controller"); 152 153 case 0x00351033: 154 return ("NEC uPD 9210 USB controller"); 155 156 case 0x00d710de: 157 return ("nVidia nForce3 USB Controller"); 158 159 case 0x70011039: 160 return ("SiS 5571 USB controller"); 161 162 case 0x1103108e: 163 return "Sun PCIO-2 USB controller"; 164 165 case 0x0019106b: 166 return ("Apple KeyLargo USB controller"); 167 168 default: 169 break; 170 } 171 if ((pci_get_class(self) == PCIC_SERIALBUS) && 172 (pci_get_subclass(self) == PCIS_SERIALBUS_USB) && 173 (pci_get_progif(self) == PCI_INTERFACE_OHCI)) { 174 return ("OHCI (generic) USB controller"); 175 } 176 return (NULL); 177} 178 179static int 180ohci_pci_probe(device_t self) 181{ 182 const char *desc = ohci_pci_match(self); 183 184 if (desc) { 185 device_set_desc(self, desc); 186 return (0); 187 } else { 188 return (ENXIO); 189 } 190} 191 192static int 193ohci_pci_attach(device_t self) 194{ 195 ohci_softc_t *sc = device_get_softc(self); 196 int rid; 197 int err; 198 199 if (sc == NULL) { 200 device_printf(self, "Could not allocate sc\n"); 201 return (ENXIO); 202 } 203 /* get all DMA memory */ 204 205 if (usb2_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(self), 206 &ohci_iterate_hw_softc)) { 207 return ENOMEM; 208 } 209 sc->sc_dev = self; 210 211 pci_enable_busmaster(self); 212 213 rid = PCI_CBMEM; 214 sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, 215 RF_ACTIVE); 216 if (!sc->sc_io_res) { 217 device_printf(self, "Could not map memory\n"); 218 goto error; 219 } 220 sc->sc_io_tag = rman_get_bustag(sc->sc_io_res); 221 sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res); 222 sc->sc_io_size = rman_get_size(sc->sc_io_res); 223 224 rid = 0; 225 sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, 226 RF_SHAREABLE | RF_ACTIVE); 227 if (sc->sc_irq_res == NULL) { 228 device_printf(self, "Could not allocate irq\n"); 229 goto error; 230 } 231 sc->sc_bus.bdev = device_add_child(self, "usbus", -1); 232 if (!sc->sc_bus.bdev) { 233 device_printf(self, "Could not add USB device\n"); 234 goto error; 235 } 236 device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); 237 238 /* 239 * ohci_pci_match will never return NULL if ohci_pci_probe 240 * succeeded 241 */ 242 device_set_desc(sc->sc_bus.bdev, ohci_pci_match(self)); 243 switch (pci_get_vendor(self)) { 244 case PCI_OHCI_VENDORID_ACERLABS: 245 sprintf(sc->sc_vendor, "AcerLabs"); 246 break; 247 case PCI_OHCI_VENDORID_AMD: 248 sprintf(sc->sc_vendor, "AMD"); 249 break; 250 case PCI_OHCI_VENDORID_APPLE: 251 sprintf(sc->sc_vendor, "Apple"); 252 break; 253 case PCI_OHCI_VENDORID_ATI: 254 sprintf(sc->sc_vendor, "ATI"); 255 break; 256 case PCI_OHCI_VENDORID_CMDTECH: 257 sprintf(sc->sc_vendor, "CMDTECH"); 258 break; 259 case PCI_OHCI_VENDORID_NEC: 260 sprintf(sc->sc_vendor, "NEC"); 261 break; 262 case PCI_OHCI_VENDORID_NVIDIA: 263 case PCI_OHCI_VENDORID_NVIDIA2: 264 sprintf(sc->sc_vendor, "nVidia"); 265 break; 266 case PCI_OHCI_VENDORID_OPTI: 267 sprintf(sc->sc_vendor, "OPTi"); 268 break; 269 case PCI_OHCI_VENDORID_SIS: 270 sprintf(sc->sc_vendor, "SiS"); 271 break; 272 case PCI_OHCI_VENDORID_SUN: 273 sprintf(sc->sc_vendor, "SUN"); 274 break; 275 default: 276 if (bootverbose) { 277 device_printf(self, "(New OHCI DeviceId=0x%08x)\n", 278 pci_get_devid(self)); 279 } 280 sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self)); 281 } 282 283 err = usb2_config_td_setup(&sc->sc_config_td, sc, &sc->sc_bus.mtx, 284 NULL, 0, 4); 285 if (err) { 286 device_printf(self, "could not setup config thread!\n"); 287 goto error; 288 } 289 /* sc->sc_bus.usbrev; set by ohci_init() */ 290 291#if (__FreeBSD_version >= 700031) 292 err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 293 NULL, (void *)(void *)ohci_interrupt, sc, &sc->sc_intr_hdl); 294#else 295 err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 296 (void *)(void *)ohci_interrupt, sc, &sc->sc_intr_hdl); 297#endif 298 if (err) { 299 device_printf(self, "Could not setup irq, %d\n", err); 300 sc->sc_intr_hdl = NULL; 301 goto error; 302 } 303 err = ohci_init(sc); 304 if (!err) { 305 err = device_probe_and_attach(sc->sc_bus.bdev); 306 } 307 if (err) { 308 device_printf(self, "USB init failed\n"); 309 goto error; 310 } 311 return (0); 312 313error: 314 ohci_pci_detach(self); 315 return (ENXIO); 316} 317 318static int 319ohci_pci_detach(device_t self) 320{ 321 ohci_softc_t *sc = device_get_softc(self); 322 device_t bdev; 323 324 usb2_config_td_drain(&sc->sc_config_td); 325 326 if (sc->sc_bus.bdev) { 327 bdev = sc->sc_bus.bdev; 328 device_detach(bdev); 329 device_delete_child(self, bdev); 330 } 331 /* during module unload there are lots of children leftover */ 332 device_delete_all_children(self); 333 334 pci_disable_busmaster(self); 335 336 if (sc->sc_irq_res && sc->sc_intr_hdl) { 337 /* 338 * only call ohci_detach() after ohci_init() 339 */ 340 ohci_detach(sc); 341 342 int err = bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl); 343 344 if (err) { 345 /* XXX or should we panic? */ 346 device_printf(self, "Could not tear down irq, %d\n", 347 err); 348 } 349 sc->sc_intr_hdl = NULL; 350 } 351 if (sc->sc_irq_res) { 352 bus_release_resource(self, SYS_RES_IRQ, 0, sc->sc_irq_res); 353 sc->sc_irq_res = NULL; 354 } 355 if (sc->sc_io_res) { 356 bus_release_resource(self, SYS_RES_MEMORY, PCI_CBMEM, 357 sc->sc_io_res); 358 sc->sc_io_res = NULL; 359 } 360 usb2_config_td_unsetup(&sc->sc_config_td); 361 362 usb2_bus_mem_free_all(&sc->sc_bus, &ohci_iterate_hw_softc); 363 364 return (0); 365} 366 367static driver_t ohci_driver = 368{ 369 .name = "ohci", 370 .methods = (device_method_t[]){ 371 /* device interface */ 372 DEVMETHOD(device_probe, ohci_pci_probe), 373 DEVMETHOD(device_attach, ohci_pci_attach), 374 DEVMETHOD(device_detach, ohci_pci_detach), 375 DEVMETHOD(device_suspend, ohci_pci_suspend), 376 DEVMETHOD(device_resume, ohci_pci_resume), 377 DEVMETHOD(device_shutdown, bus_generic_shutdown), 378 379 /* bus interface */ 380 DEVMETHOD(bus_print_child, bus_generic_print_child), 381 382 {0, 0} 383 }, 384 .size = sizeof(struct ohci_softc), 385}; 386 387static devclass_t ohci_devclass; 388 389DRIVER_MODULE(ohci, pci, ohci_driver, ohci_devclass, 0, 0); 390DRIVER_MODULE(ohci, cardbus, ohci_driver, ohci_devclass, 0, 0); 391MODULE_DEPEND(ohci, usb2_controller, 1, 1, 1); 392MODULE_DEPEND(ohci, usb2_core, 1, 1, 1); 393