1 /* $Id: at91ohci.c,v 1.3 2009/03/14 15:36:01 dsl Exp $ */ 2 /* $NetBSD: at91ohci.c,v 1.3 2009/03/14 15:36:01 dsl Exp $ */ 3 4 /*- 5 * Copyright (c) 2007 Embedtronics Oy. 6 * All rights reserved. 7 * 8 * Based on arch/arm/ep93xx/epohci.c, 9 * Copyright (c) 2004 Jesse Off 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 /* 35 * USB Open Host Controller driver. 36 * 37 * OHCI spec: ftp://ftp.compaq.com/pub/supportinformation/papers/hcir1_0a.exe 38 * USB spec: http://www.usb.org/developers/data/usb11.pdf 39 */ 40 41 #include <sys/cdefs.h> 42 __KERNEL_RCSID(0, "$NetBSD: at91ohci.c,v 1.3 2009/03/14 15:36:01 dsl Exp $"); 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/kernel.h> 47 #include <sys/device.h> 48 #include <sys/proc.h> 49 #include <sys/queue.h> 50 51 /* busdma */ 52 #include <sys/mbuf.h> 53 #include <uvm/uvm_extern.h> 54 55 #include <machine/bus.h> 56 57 #include <dev/usb/usb.h> 58 #include <dev/usb/usbdi.h> 59 #include <dev/usb/usbdivar.h> 60 #include <dev/usb/usb_mem.h> 61 62 #include <dev/usb/ohcireg.h> 63 #include <dev/usb/ohcivar.h> 64 65 #include <arm/at91/at91reg.h> 66 #include <arm/at91/at91var.h> 67 68 int at91ohci_match(device_t, cfdata_t, void *); 69 void at91ohci_attach(device_t, device_t, void *); 70 void at91ohci_callback(device_t ); 71 72 struct at91ohci_softc { 73 struct ohci_softc sc; 74 void *sc_ih; 75 int sc_pid; 76 }; 77 78 CFATTACH_DECL(at91ohci, sizeof(struct at91ohci_softc), 79 at91ohci_match, at91ohci_attach, NULL, NULL); 80 81 int 82 at91ohci_match(device_t parent, cfdata_t match, void *aux) 83 { 84 /* AT91X builtin OHCI module */ 85 if (strcmp(match->cf_name, "ohci") == 0 && strcmp(match->cf_atname, "at91ohci") == 0) 86 return (2); 87 return(0); 88 } 89 90 void 91 at91ohci_attach(device_t parent, device_t self, void *aux) 92 { 93 struct at91ohci_softc *sc = (struct at91ohci_softc *)self; 94 struct at91bus_attach_args *sa = aux; 95 96 sc->sc.iot = sa->sa_iot; 97 sc->sc.sc_bus.dmatag = sa->sa_dmat; 98 sc->sc_pid = sa->sa_pid; 99 100 /* Map I/O space */ 101 if (bus_space_map(sc->sc.iot, sa->sa_addr, sa->sa_size, 102 0, &sc->sc.ioh)) { 103 printf(": cannot map mem space\n"); 104 return; 105 } 106 107 /* enable peripheral clock */ 108 at91_peripheral_clock(sc->sc_pid, 1); 109 110 printf("\n"); 111 112 /* Defer the rest until later */ 113 config_defer(self, at91ohci_callback); 114 } 115 116 void 117 at91ohci_callback(device_t self) 118 { 119 struct at91ohci_softc *sc = (struct at91ohci_softc *)self; 120 usbd_status r; 121 122 /* Disable interrupts, so we don't get any spurious ones. */ 123 bus_space_write_4(sc->sc.iot, sc->sc.ioh, OHCI_INTERRUPT_DISABLE, 124 OHCI_ALL_INTRS); 125 126 strlcpy(sc->sc.sc_vendor, "Atmel", sizeof sc->sc.sc_vendor); 127 128 sc->sc_ih = at91_intr_establish(sc->sc_pid, IPL_USB, INTR_HIGH_LEVEL, ohci_intr, sc); 129 r = ohci_init(&sc->sc); 130 131 if (r != USBD_NORMAL_COMPLETION) { 132 printf("%s: init failed, error=%d\n", device_xname(self), r); 133 134 at91_intr_disestablish(sc->sc_ih); 135 return; 136 } 137 138 /* Attach usb device. */ 139 sc->sc.sc_child = config_found((void *) sc, &sc->sc.sc_bus, usbctlprint); 140 } 141