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