atmegadci_atmelarm.c revision 190749
175337Sru#include <sys/cdefs.h> 275337Sru__FBSDID("$FreeBSD: head/sys/dev/usb/controller/atmegadci_atmelarm.c 190749 2009-04-05 21:24:15Z piso $"); 318099Spst 418099Spst/*- 518099Spst * Copyright (c) 2009 Hans Petter Selasky. All rights reserved. 618099Spst * 718099Spst * Redistribution and use in source and binary forms, with or without 818099Spst * modification, are permitted provided that the following conditions 918099Spst * are met: 1018099Spst * 1. Redistributions of source code must retain the above copyright 1118099Spst * notice, this list of conditions and the following disclaimer. 12151502Sru * 2. Redistributions in binary form must reproduce the above copyright 13151502Sru * notice, this list of conditions and the following disclaimer in the 1418099Spst * documentation and/or other materials provided with the distribution. 1518099Spst * 1618099Spst * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1718099Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1818099Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1918099Spst * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2018099Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2118099Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2218099Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2318099Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2418099Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2518099Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2618099Spst * SUCH DAMAGE. 2718099Spst */ 2818099Spst 2918099Spst#include <dev/usb/usb.h> 3075337Sru 3118099Spst#include <dev/usb/usb_core.h> 3218099Spst#include <dev/usb/usb_busdma.h> 3375589Sru#include <dev/usb/usb_process.h> 3475589Sru#include <dev/usb/usb_sw_transfer.h> 3575589Sru#include <dev/usb/usb_util.h> 3675589Sru 3775589Sru#include <dev/usb/usb_controller.h> 3818099Spst#include <dev/usb/usb_bus.h> 3975589Sru#include <dev/usb/controller/atmegadci.h> 40262656Suqs 4175589Sru#include <sys/rman.h> 4289502Sru 4318099Spststatic device_probe_t atmegadci_probe; 4418099Spststatic device_attach_t atmegadci_attach; 4518099Spststatic device_detach_t atmegadci_detach; 4675589Srustatic device_shutdown_t atmegadci_shutdown; 4775589Sru 4818099Spststruct atmegadci_super_softc { 4918099Spst struct atmegadci_softc sc_otg; /* must be first */ 50202366Sru}; 5118099Spst 5275589Srustatic void 5318099Spstatmegadci_clocks_on(struct usb2_bus *bus) 5475589Sru{ 5518099Spst /* TODO */ 5618099Spst} 5718099Spst 5818099Spststatic void 5975589Sruatmegadci_clocks_off(struct usb2_bus *bus) 6018099Spst{ 6175589Sru /* TODO */ 6275589Sru} 6318099Spst 6418099Spststatic int 6518099Spstatmegadci_probe(device_t dev) 6675589Sru{ 6775589Sru device_set_desc(dev, "ATMEL OTG integrated USB controller"); 6875589Sru return (0); 6975589Sru} 7075589Sru 7175589Srustatic int 7218099Spstatmegadci_attach(device_t dev) 7318099Spst{ 7475589Sru struct atmegadci_super_softc *sc = device_get_softc(dev); 7518099Spst int err; 7675589Sru int rid; 7775589Sru 7875589Sru /* setup MUSB OTG USB controller interface softc */ 7918099Spst sc->sc_otg.sc_clocks_on = &atmegadci_clocks_on; 8075589Sru sc->sc_otg.sc_clocks_off = &atmegadci_clocks_off; 8118099Spst 82202366Sru /* initialise some bus fields */ 8318099Spst sc->sc_otg.sc_bus.parent = dev; 8475589Sru sc->sc_otg.sc_bus.devices = sc->sc_otg.sc_devices; 8575589Sru sc->sc_otg.sc_bus.devices_max = ATMEGA_MAX_DEVICES; 8618099Spst 8775589Sru /* get all DMA memory */ 8875589Sru if (usb2_bus_mem_alloc_all(&sc->sc_otg.sc_bus, 8918099Spst USB_GET_DMA_TAG(dev), NULL)) { 9018099Spst return (ENOMEM); 9159953Sphantom } 9275589Sru rid = 0; 9318099Spst sc->sc_otg.sc_io_res = 9481684Sru bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 9518099Spst 9675589Sru if (!(sc->sc_otg.sc_io_res)) { 9775589Sru err = ENOMEM; 9818099Spst goto error; 9975589Sru } 10018099Spst sc->sc_otg.sc_io_tag = rman_get_bustag(sc->sc_otg.sc_io_res); 10175589Sru sc->sc_otg.sc_io_hdl = rman_get_bushandle(sc->sc_otg.sc_io_res); 10275589Sru 10375589Sru rid = 0; 10418099Spst sc->sc_otg.sc_irq_res = 105117203Sru bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 10675589Sru if (!(sc->sc_otg.sc_irq_res)) { 10775589Sru goto error; 10818099Spst } 10975589Sru sc->sc_otg.sc_bus.bdev = device_add_child(dev, "usbus", -1); 11075589Sru if (!(sc->sc_otg.sc_bus.bdev)) { 11175589Sru goto error; 11218099Spst } 11375589Sru device_set_ivars(sc->sc_otg.sc_bus.bdev, &sc->sc_otg.sc_bus); 11475589Sru 11518099Spst err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 11618099Spst NULL, (driver_intr_t *)atmegadci_interrupt, sc, &sc->sc_otg.sc_intr_hdl); 11718099Spst if (err) { 11875589Sru sc->sc_otg.sc_intr_hdl = NULL; 11975589Sru goto error; 12018099Spst } 12118099Spst err = atmegadci_init(&sc->sc_otg); 12275589Sru if (!err) { 12375589Sru err = device_probe_and_attach(sc->sc_otg.sc_bus.bdev); 12418099Spst } 12575589Sru if (err) { 12618099Spst goto error; 12718099Spst } 12875589Sru return (0); 12918099Spst 13075589Sruerror: 13118099Spst atmegadci_detach(dev); 13218099Spst return (ENXIO); 13318099Spst} 13475589Sru 13518099Spststatic int 13675589Sruatmegadci_detach(device_t dev) 13775589Sru{ 13818099Spst struct atmegadci_super_softc *sc = device_get_softc(dev); 13918099Spst device_t bdev; 14075589Sru int err; 14175589Sru 14275589Sru if (sc->sc_otg.sc_bus.bdev) { 14318099Spst bdev = sc->sc_otg.sc_bus.bdev; 14475589Sru device_detach(bdev); 14518099Spst device_delete_child(dev, bdev); 14675589Sru } 14775589Sru /* during module unload there are lots of children leftover */ 14818099Spst device_delete_all_children(dev); 14975589Sru 15018099Spst if (sc->sc_otg.sc_irq_res && sc->sc_otg.sc_intr_hdl) { 15118099Spst /* 15218099Spst * only call atmegadci_uninit() after atmegadci_init() 15375589Sru */ 15475589Sru atmegadci_uninit(&sc->sc_otg); 155104867Sru 15675589Sru err = bus_teardown_intr(dev, sc->sc_otg.sc_irq_res, 15775589Sru sc->sc_otg.sc_intr_hdl); 15875589Sru sc->sc_otg.sc_intr_hdl = NULL; 15975589Sru } 16075589Sru /* free IRQ channel, if any */ 16175589Sru if (sc->sc_otg.sc_irq_res) { 16275589Sru bus_release_resource(dev, SYS_RES_IRQ, 0, 16375589Sru sc->sc_otg.sc_irq_res); 16475589Sru sc->sc_otg.sc_irq_res = NULL; 16575589Sru } 16675589Sru /* free memory resource, if any */ 16775589Sru if (sc->sc_otg.sc_io_res) { 16875589Sru bus_release_resource(dev, SYS_RES_MEMORY, 0, 16975589Sru sc->sc_otg.sc_io_res); 17075589Sru sc->sc_otg.sc_io_res = NULL; 17175589Sru } 17275589Sru usb2_bus_mem_free_all(&sc->sc_otg.sc_bus, NULL); 17375589Sru 17475589Sru return (0); 17575589Sru} 17675589Sru 17775589Srustatic int 17875589Sruatmegadci_shutdown(device_t dev) 17975589Sru{ 18075589Sru struct atmegadci_super_softc *sc = device_get_softc(dev); 18175589Sru int err; 18275589Sru 18375589Sru err = bus_generic_shutdown(dev); 184114409Sru if (err) 18575589Sru return (err); 18675589Sru 18775589Sru atmegadci_uninit(&sc->sc_otg); 18875589Sru 18975589Sru return (0); 19075589Sru} 19175589Sru 19275589Srustatic device_method_t atmegadci_methods[] = { 19375589Sru /* Device interface */ 19475589Sru DEVMETHOD(device_probe, atmegadci_probe), 19575589Sru DEVMETHOD(device_attach, atmegadci_attach), 19675589Sru DEVMETHOD(device_detach, atmegadci_detach), 19775589Sru DEVMETHOD(device_shutdown, atmegadci_shutdown), 19875589Sru 19975589Sru /* Bus interface */ 20075589Sru DEVMETHOD(bus_print_child, bus_generic_print_child), 20175589Sru 20275589Sru {0, 0} 20375589Sru}; 20475589Sru 20575589Srustatic driver_t atmegadci_driver = { 20675589Sru "atmegadci", 20775589Sru atmegadci_methods, 20875589Sru sizeof(struct atmegadci_super_softc), 20975589Sru}; 21075589Sru 21175589Srustatic devclass_t atmegadci_devclass; 21275589Sru 21375589SruDRIVER_MODULE(atmegadci, atmelarm, atmegadci_driver, atmegadci_devclass, 0, 0); 21475589SruMODULE_DEPEND(atmegadci, usb, 1, 1, 1); 21575589Sru