atmegadci_atmelarm.c revision 217265
155682Smarkm#include <sys/cdefs.h> 2233294Sstas__FBSDID("$FreeBSD: head/sys/dev/usb/controller/atmegadci_atmelarm.c 217265 2011-01-11 13:59:06Z jhb $"); 3233294Sstas 4233294Sstas/*- 555682Smarkm * Copyright (c) 2009 Hans Petter Selasky. All rights reserved. 6233294Sstas * 7233294Sstas * Redistribution and use in source and binary forms, with or without 8233294Sstas * modification, are permitted provided that the following conditions 955682Smarkm * are met: 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 2. Redistributions in binary form must reproduce the above copyright 13233294Sstas * notice, this list of conditions and the following disclaimer in the 14233294Sstas * documentation and/or other materials provided with the distribution. 15233294Sstas * 1655682Smarkm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2055682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26233294Sstas * SUCH DAMAGE. 27233294Sstas */ 28233294Sstas 29233294Sstas#include <sys/stdint.h> 30233294Sstas#include <sys/stddef.h> 31233294Sstas#include <sys/param.h> 3255682Smarkm#include <sys/queue.h> 3355682Smarkm#include <sys/types.h> 3455682Smarkm#include <sys/systm.h> 3555682Smarkm#include <sys/kernel.h> 3655682Smarkm#include <sys/bus.h> 3755682Smarkm#include <sys/module.h> 3855682Smarkm#include <sys/lock.h> 3955682Smarkm#include <sys/mutex.h> 4078527Sassar#include <sys/condvar.h> 4155682Smarkm#include <sys/sysctl.h> 4255682Smarkm#include <sys/sx.h> 4355682Smarkm#include <sys/unistd.h> 4455682Smarkm#include <sys/callout.h> 4555682Smarkm#include <sys/malloc.h> 4655682Smarkm#include <sys/priv.h> 4755682Smarkm 4855682Smarkm#include <dev/usb/usb.h> 4955682Smarkm#include <dev/usb/usbdi.h> 5055682Smarkm 5155682Smarkm#include <dev/usb/usb_core.h> 5278527Sassar#include <dev/usb/usb_busdma.h> 5378527Sassar#include <dev/usb/usb_process.h> 5455682Smarkm#include <dev/usb/usb_util.h> 5555682Smarkm 5655682Smarkm#include <dev/usb/usb_controller.h> 5755682Smarkm#include <dev/usb/usb_bus.h> 5855682Smarkm#include <dev/usb/controller/atmegadci.h> 5955682Smarkm 6055682Smarkm#include <sys/rman.h> 6178527Sassar 6255682Smarkmstatic device_probe_t atmegadci_probe; 6355682Smarkmstatic device_attach_t atmegadci_attach; 6455682Smarkmstatic device_detach_t atmegadci_detach; 6578527Sassarstatic device_shutdown_t atmegadci_shutdown; 6678527Sassar 6755682Smarkmstruct atmegadci_super_softc { 6855682Smarkm struct atmegadci_softc sc_otg; /* must be first */ 6955682Smarkm}; 7055682Smarkm 7155682Smarkmstatic void 7255682Smarkmatmegadci_clocks_on(struct usb_bus *bus) 7355682Smarkm{ 7455682Smarkm /* TODO */ 7555682Smarkm} 7655682Smarkm 7755682Smarkmstatic void 7855682Smarkmatmegadci_clocks_off(struct usb_bus *bus) 79178825Sdfr{ 8055682Smarkm /* TODO */ 8155682Smarkm} 8255682Smarkm 8355682Smarkmstatic int 8455682Smarkmatmegadci_probe(device_t dev) 8555682Smarkm{ 8655682Smarkm device_set_desc(dev, "ATMEL OTG integrated USB controller"); 8755682Smarkm return (0); 8855682Smarkm} 8955682Smarkm 9055682Smarkmstatic int 91233294Sstasatmegadci_attach(device_t dev) 9278527Sassar{ 9355682Smarkm struct atmegadci_super_softc *sc = device_get_softc(dev); 9478527Sassar int err; 9578527Sassar int rid; 9678527Sassar 9778527Sassar /* setup MUSB OTG USB controller interface softc */ 9855682Smarkm sc->sc_otg.sc_clocks_on = &atmegadci_clocks_on; 99233294Sstas sc->sc_otg.sc_clocks_off = &atmegadci_clocks_off; 100178825Sdfr 101178825Sdfr /* initialise some bus fields */ 102178825Sdfr sc->sc_otg.sc_bus.parent = dev; 103178825Sdfr sc->sc_otg.sc_bus.devices = sc->sc_otg.sc_devices; 104233294Sstas sc->sc_otg.sc_bus.devices_max = ATMEGA_MAX_DEVICES; 105233294Sstas 106178825Sdfr /* get all DMA memory */ 107178825Sdfr if (usb_bus_mem_alloc_all(&sc->sc_otg.sc_bus, 108178825Sdfr USB_GET_DMA_TAG(dev), NULL)) { 109178825Sdfr return (ENOMEM); 110178825Sdfr } 111178825Sdfr rid = 0; 112233294Sstas sc->sc_otg.sc_io_res = 113178825Sdfr bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 114178825Sdfr 115178825Sdfr if (!(sc->sc_otg.sc_io_res)) { 116178825Sdfr err = ENOMEM; 117178825Sdfr goto error; 118233294Sstas } 11978527Sassar sc->sc_otg.sc_io_tag = rman_get_bustag(sc->sc_otg.sc_io_res); 12078527Sassar sc->sc_otg.sc_io_hdl = rman_get_bushandle(sc->sc_otg.sc_io_res); 12178527Sassar 12278527Sassar rid = 0; 12378527Sassar sc->sc_otg.sc_irq_res = 124233294Sstas bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 12578527Sassar if (!(sc->sc_otg.sc_irq_res)) { 12678527Sassar goto error; 12778527Sassar } 12878527Sassar sc->sc_otg.sc_bus.bdev = device_add_child(dev, "usbus", -1); 12978527Sassar if (!(sc->sc_otg.sc_bus.bdev)) { 130233294Sstas goto error; 13178527Sassar } 13278527Sassar device_set_ivars(sc->sc_otg.sc_bus.bdev, &sc->sc_otg.sc_bus); 13378527Sassar 13478527Sassar err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 13578527Sassar NULL, (driver_intr_t *)atmegadci_interrupt, sc, &sc->sc_otg.sc_intr_hdl); 136233294Sstas if (err) { 13778527Sassar sc->sc_otg.sc_intr_hdl = NULL; 13878527Sassar goto error; 13978527Sassar } 14078527Sassar err = atmegadci_init(&sc->sc_otg); 14178527Sassar if (!err) { 142233294Sstas err = device_probe_and_attach(sc->sc_otg.sc_bus.bdev); 14378527Sassar } 14478527Sassar if (err) { 14578527Sassar goto error; 14678527Sassar } 14778527Sassar return (0); 14878527Sassar 14978527Sassarerror: 15078527Sassar atmegadci_detach(dev); 15178527Sassar return (ENXIO); 15278527Sassar} 15378527Sassar 15478527Sassarstatic int 15555682Smarkmatmegadci_detach(device_t dev) 156178825Sdfr{ 15755682Smarkm struct atmegadci_super_softc *sc = device_get_softc(dev); 15878527Sassar device_t bdev; 159178825Sdfr int err; 160178825Sdfr 161178825Sdfr if (sc->sc_otg.sc_bus.bdev) { 162233294Sstas bdev = sc->sc_otg.sc_bus.bdev; 163233294Sstas device_detach(bdev); 164178825Sdfr device_delete_child(dev, bdev); 16555682Smarkm } 16655682Smarkm /* during module unload there are lots of children leftover */ 16755682Smarkm device_delete_all_children(dev); 168102644Snectar 16955682Smarkm if (sc->sc_otg.sc_irq_res && sc->sc_otg.sc_intr_hdl) { 17055682Smarkm /* 17155682Smarkm * only call atmegadci_uninit() after atmegadci_init() 17255682Smarkm */ 173178825Sdfr atmegadci_uninit(&sc->sc_otg); 174178825Sdfr 17555682Smarkm err = bus_teardown_intr(dev, sc->sc_otg.sc_irq_res, 17655682Smarkm sc->sc_otg.sc_intr_hdl); 17778527Sassar sc->sc_otg.sc_intr_hdl = NULL; 178233294Sstas } 179233294Sstas /* free IRQ channel, if any */ 18078527Sassar if (sc->sc_otg.sc_irq_res) { 18178527Sassar bus_release_resource(dev, SYS_RES_IRQ, 0, 18255682Smarkm sc->sc_otg.sc_irq_res); 18355682Smarkm sc->sc_otg.sc_irq_res = NULL; 184233294Sstas } 18578527Sassar /* free memory resource, if any */ 18678527Sassar if (sc->sc_otg.sc_io_res) { 18778527Sassar bus_release_resource(dev, SYS_RES_MEMORY, 0, 18878527Sassar sc->sc_otg.sc_io_res); 18978527Sassar sc->sc_otg.sc_io_res = NULL; 19078527Sassar } 19178527Sassar usb_bus_mem_free_all(&sc->sc_otg.sc_bus, NULL); 19278527Sassar 19378527Sassar return (0); 19478527Sassar} 19578527Sassar 19678527Sassarstatic int 19778527Sassaratmegadci_shutdown(device_t dev) 198233294Sstas{ 19978527Sassar struct atmegadci_super_softc *sc = device_get_softc(dev); 200233294Sstas int err; 201233294Sstas 20278527Sassar err = bus_generic_shutdown(dev); 203233294Sstas if (err) 20478527Sassar return (err); 205233294Sstas 20678527Sassar atmegadci_uninit(&sc->sc_otg); 20778527Sassar 20878527Sassar return (0); 20978527Sassar} 21078527Sassar 21178527Sassarstatic device_method_t atmegadci_methods[] = { 21278527Sassar /* Device interface */ 21378527Sassar DEVMETHOD(device_probe, atmegadci_probe), 21478527Sassar DEVMETHOD(device_attach, atmegadci_attach), 21578527Sassar DEVMETHOD(device_detach, atmegadci_detach), 21678527Sassar DEVMETHOD(device_shutdown, atmegadci_shutdown), 21778527Sassar 218233294Sstas /* Bus interface */ 219233294Sstas DEVMETHOD(bus_print_child, bus_generic_print_child), 22078527Sassar 22178527Sassar {0, 0} 22278527Sassar}; 22378527Sassar 22478527Sassarstatic driver_t atmegadci_driver = { 22578527Sassar "atmegadci", 22678527Sassar atmegadci_methods, 227233294Sstas sizeof(struct atmegadci_super_softc), 22878527Sassar}; 229233294Sstas 23078527Sassarstatic devclass_t atmegadci_devclass; 23178527Sassar 23278527SassarDRIVER_MODULE(atmegadci, atmelarm, atmegadci_driver, atmegadci_devclass, 0, 0); 233233294SstasMODULE_DEPEND(atmegadci, usb, 1, 1, 1); 23478527Sassar