atmegadci_atmelarm.c revision 190174
1#include <sys/cdefs.h> 2__FBSDID("$FreeBSD: head/sys/dev/usb/controller/atmegadci_atmelarm.c 190174 2009-03-20 19:04:31Z thompsa $"); 3 4/*- 5 * Copyright (c) 2009 Hans Petter Selasky. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <dev/usb/usb.h> 30 31#include <dev/usb/usb_core.h> 32#include <dev/usb/usb_busdma.h> 33#include <dev/usb/usb_process.h> 34#include <dev/usb/usb_sw_transfer.h> 35#include <dev/usb/usb_util.h> 36 37#include <dev/usb/usb_controller.h> 38#include <dev/usb/usb_bus.h> 39#include <dev/usb/controller/atmegadci.h> 40 41#include <sys/rman.h> 42 43static device_probe_t atmegadci_probe; 44static device_attach_t atmegadci_attach; 45static device_detach_t atmegadci_detach; 46static device_shutdown_t atmegadci_shutdown; 47 48struct atmegadci_super_softc { 49 struct atmegadci_softc sc_otg; /* must be first */ 50}; 51 52static void 53atmegadci_clocks_on(struct usb2_bus *bus) 54{ 55 /* TODO */ 56} 57 58static void 59atmegadci_clocks_off(struct usb2_bus *bus) 60{ 61 /* TODO */ 62} 63 64static int 65atmegadci_probe(device_t dev) 66{ 67 device_set_desc(dev, "ATMEL OTG integrated USB controller"); 68 return (0); 69} 70 71static int 72atmegadci_attach(device_t dev) 73{ 74 struct atmegadci_super_softc *sc = device_get_softc(dev); 75 int err; 76 int rid; 77 78 /* setup MUSB OTG USB controller interface softc */ 79 sc->sc_otg.sc_clocks_on = &atmegadci_clocks_on; 80 sc->sc_otg.sc_clocks_off = &atmegadci_clocks_off; 81 82 /* initialise some bus fields */ 83 sc->sc_otg.sc_bus.parent = dev; 84 sc->sc_otg.sc_bus.devices = sc->sc_otg.sc_devices; 85 sc->sc_otg.sc_bus.devices_max = ATMEGA_MAX_DEVICES; 86 87 /* get all DMA memory */ 88 if (usb2_bus_mem_alloc_all(&sc->sc_otg.sc_bus, 89 USB_GET_DMA_TAG(dev), NULL)) { 90 return (ENOMEM); 91 } 92 rid = 0; 93 sc->sc_otg.sc_io_res = 94 bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 95 96 if (!(sc->sc_otg.sc_io_res)) { 97 err = ENOMEM; 98 goto error; 99 } 100 sc->sc_otg.sc_io_tag = rman_get_bustag(sc->sc_otg.sc_io_res); 101 sc->sc_otg.sc_io_hdl = rman_get_bushandle(sc->sc_otg.sc_io_res); 102 103 rid = 0; 104 sc->sc_otg.sc_irq_res = 105 bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 106 if (!(sc->sc_otg.sc_irq_res)) { 107 goto error; 108 } 109 sc->sc_otg.sc_bus.bdev = device_add_child(dev, "usbus", -1); 110 if (!(sc->sc_otg.sc_bus.bdev)) { 111 goto error; 112 } 113 device_set_ivars(sc->sc_otg.sc_bus.bdev, &sc->sc_otg.sc_bus); 114 115 err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 116 NULL, (void *)atmegadci_interrupt, sc, &sc->sc_otg.sc_intr_hdl); 117 if (err) { 118 sc->sc_otg.sc_intr_hdl = NULL; 119 goto error; 120 } 121 err = atmegadci_init(&sc->sc_otg); 122 if (!err) { 123 err = device_probe_and_attach(sc->sc_otg.sc_bus.bdev); 124 } 125 if (err) { 126 goto error; 127 } 128 return (0); 129 130error: 131 atmegadci_detach(dev); 132 return (ENXIO); 133} 134 135static int 136atmegadci_detach(device_t dev) 137{ 138 struct atmegadci_super_softc *sc = device_get_softc(dev); 139 device_t bdev; 140 int err; 141 142 if (sc->sc_otg.sc_bus.bdev) { 143 bdev = sc->sc_otg.sc_bus.bdev; 144 device_detach(bdev); 145 device_delete_child(dev, bdev); 146 } 147 /* during module unload there are lots of children leftover */ 148 device_delete_all_children(dev); 149 150 if (sc->sc_otg.sc_irq_res && sc->sc_otg.sc_intr_hdl) { 151 /* 152 * only call atmegadci_uninit() after atmegadci_init() 153 */ 154 atmegadci_uninit(&sc->sc_otg); 155 156 err = bus_teardown_intr(dev, sc->sc_otg.sc_irq_res, 157 sc->sc_otg.sc_intr_hdl); 158 sc->sc_otg.sc_intr_hdl = NULL; 159 } 160 /* free IRQ channel, if any */ 161 if (sc->sc_otg.sc_irq_res) { 162 bus_release_resource(dev, SYS_RES_IRQ, 0, 163 sc->sc_otg.sc_irq_res); 164 sc->sc_otg.sc_irq_res = NULL; 165 } 166 /* free memory resource, if any */ 167 if (sc->sc_otg.sc_io_res) { 168 bus_release_resource(dev, SYS_RES_MEMORY, 0, 169 sc->sc_otg.sc_io_res); 170 sc->sc_otg.sc_io_res = NULL; 171 } 172 usb2_bus_mem_free_all(&sc->sc_otg.sc_bus, NULL); 173 174 return (0); 175} 176 177static int 178atmegadci_shutdown(device_t dev) 179{ 180 struct atmegadci_super_softc *sc = device_get_softc(dev); 181 int err; 182 183 err = bus_generic_shutdown(dev); 184 if (err) 185 return (err); 186 187 atmegadci_uninit(&sc->sc_otg); 188 189 return (0); 190} 191 192static device_method_t atmegadci_methods[] = { 193 /* Device interface */ 194 DEVMETHOD(device_probe, atmegadci_probe), 195 DEVMETHOD(device_attach, atmegadci_attach), 196 DEVMETHOD(device_detach, atmegadci_detach), 197 DEVMETHOD(device_shutdown, atmegadci_shutdown), 198 199 /* Bus interface */ 200 DEVMETHOD(bus_print_child, bus_generic_print_child), 201 202 {0, 0} 203}; 204 205static driver_t atmegadci_driver = { 206 "atmegadci", 207 atmegadci_methods, 208 sizeof(struct atmegadci_super_softc), 209}; 210 211static devclass_t atmegadci_devclass; 212 213DRIVER_MODULE(atmegadci, atmelarm, atmegadci_driver, atmegadci_devclass, 0, 0); 214MODULE_DEPEND(atmegadci, usb, 1, 1, 1); 215