summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2012-09-10 13:50:34 +0000
committerhselasky <hselasky@FreeBSD.org>2012-09-10 13:50:34 +0000
commitd6420ed47c240aed3849f8f82d7c8468fbb49622 (patch)
treeac16bd2b6eb408a501a3498bc10777b40dd6a361
parent3467c1af7a81e2a8c9aa8b461eeebc4fe5cf7b0d (diff)
downloadFreeBSD-src-d6420ed47c240aed3849f8f82d7c8468fbb49622.zip
FreeBSD-src-d6420ed47c240aed3849f8f82d7c8468fbb49622.tar.gz
Poll VBUS status every second, hence the AT91 GPIO library doesn't support
registering interrupt handlers yet for GPIO events.
-rw-r--r--sys/dev/usb/controller/at91dci.c2
-rw-r--r--sys/dev/usb/controller/at91dci_atmelarm.c64
2 files changed, 15 insertions, 51 deletions
diff --git a/sys/dev/usb/controller/at91dci.c b/sys/dev/usb/controller/at91dci.c
index 8468e6f..8d3c1cb 100644
--- a/sys/dev/usb/controller/at91dci.c
+++ b/sys/dev/usb/controller/at91dci.c
@@ -740,7 +740,6 @@ at91dci_vbus_interrupt(struct at91dci_softc *sc, uint8_t is_on)
{
DPRINTFN(5, "vbus = %u\n", is_on);
- USB_BUS_LOCK(&sc->sc_bus);
if (is_on) {
if (!sc->sc_flags.status_vbus) {
sc->sc_flags.status_vbus = 1;
@@ -760,7 +759,6 @@ at91dci_vbus_interrupt(struct at91dci_softc *sc, uint8_t is_on)
at91dci_root_intr(sc);
}
}
- USB_BUS_UNLOCK(&sc->sc_bus);
}
void
diff --git a/sys/dev/usb/controller/at91dci_atmelarm.c b/sys/dev/usb/controller/at91dci_atmelarm.c
index be3d7d8..678ad48 100644
--- a/sys/dev/usb/controller/at91dci_atmelarm.c
+++ b/sys/dev/usb/controller/at91dci_atmelarm.c
@@ -83,24 +83,18 @@ struct at91_udp_softc {
struct at91_pmc_clock *sc_mclk;
struct at91_pmc_clock *sc_iclk;
struct at91_pmc_clock *sc_fclk;
- struct resource *sc_vbus_irq_res;
- void *sc_vbus_intr_hdl;
+ struct callout sc_vbus;
};
static void
at91_vbus_poll(struct at91_udp_softc *sc)
{
- uint32_t temp;
uint8_t vbus_val;
- /* XXX temporary clear interrupts here */
-
- temp = at91_pio_gpio_clear_interrupt(VBUS_BASE);
-
- /* just forward it */
-
vbus_val = at91_pio_gpio_get(VBUS_BASE, VBUS_MASK);
at91dci_vbus_interrupt(&sc->sc_dci, vbus_val);
+
+ callout_reset(&sc->sc_vbus, hz, (void *)&at91_vbus_poll, sc);
}
static void
@@ -168,6 +162,8 @@ at91_udp_attach(device_t dev)
USB_GET_DMA_TAG(dev), NULL)) {
return (ENOMEM);
}
+ callout_init_mtx(&sc->sc_vbus, &sc->sc_dci.sc_bus.bus_mtx, 0);
+
/*
* configure VBUS input pin, enable deglitch and enable
* interrupt :
@@ -175,7 +171,7 @@ at91_udp_attach(device_t dev)
at91_pio_use_gpio(VBUS_BASE, VBUS_MASK);
at91_pio_gpio_input(VBUS_BASE, VBUS_MASK);
at91_pio_gpio_set_deglitch(VBUS_BASE, VBUS_MASK, 1);
- at91_pio_gpio_set_interrupt(VBUS_BASE, VBUS_MASK, 1);
+ at91_pio_gpio_set_interrupt(VBUS_BASE, VBUS_MASK, 0);
/*
* configure PULLUP output pin :
@@ -210,13 +206,6 @@ at91_udp_attach(device_t dev)
if (!(sc->sc_dci.sc_irq_res)) {
goto error;
}
- rid = 1;
- sc->sc_vbus_irq_res =
- bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
- if (sc->sc_vbus_irq_res == NULL) {
- at91_pio_gpio_set_interrupt(VBUS_BASE, VBUS_MASK, 0);
- device_printf(dev, "No VBUS IRQ!\n");
- }
sc->sc_dci.sc_bus.bdev = device_add_child(dev, "usbus", -1);
if (!(sc->sc_dci.sc_bus.bdev)) {
goto error;
@@ -234,25 +223,7 @@ at91_udp_attach(device_t dev)
sc->sc_dci.sc_intr_hdl = NULL;
goto error;
}
-#if (__FreeBSD_version >= 700031)
- if (sc->sc_vbus_irq_res != NULL) {
- err = bus_setup_intr(dev, sc->sc_vbus_irq_res,
- INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (driver_intr_t *)at91_vbus_poll, sc,
- &sc->sc_vbus_intr_hdl);
- }
-#else
- if (sc->sc_vbus_irq_res != NULL) {
- err = bus_setup_intr(dev, sc->sc_vbus_irq_res,
- INTR_TYPE_BIO | INTR_MPSAFE,
- (driver_intr_t *)at91_vbus_poll, sc,
- &sc->sc_vbus_intr_hdl);
- }
-#endif
- if (err) {
- sc->sc_vbus_intr_hdl = NULL;
- goto error;
- }
+
err = at91dci_init(&sc->sc_dci);
if (!err) {
err = device_probe_and_attach(sc->sc_dci.sc_bus.bdev);
@@ -261,7 +232,9 @@ at91_udp_attach(device_t dev)
goto error;
} else {
/* poll VBUS one time */
+ USB_BUS_LOCK(&sc->sc_dci.sc_bus);
at91_vbus_poll(sc);
+ USB_BUS_UNLOCK(&sc->sc_dci.sc_bus);
}
return (0);
@@ -285,6 +258,12 @@ at91_udp_detach(device_t dev)
/* during module unload there are lots of children leftover */
device_delete_children(dev);
+ USB_BUS_LOCK(&sc->sc_dci.sc_bus);
+ callout_stop(&sc->sc_vbus);
+ USB_BUS_UNLOCK(&sc->sc_dci.sc_bus);
+
+ callout_drain(&sc->sc_vbus);
+
/* disable Transceiver */
AT91_UDP_WRITE_4(&sc->sc_dci, AT91_UDP_TXVC, AT91_UDP_TXVC_DIS);
@@ -292,19 +271,6 @@ at91_udp_detach(device_t dev)
AT91_UDP_WRITE_4(&sc->sc_dci, AT91_UDP_IDR, 0xFFFFFFFF);
AT91_UDP_WRITE_4(&sc->sc_dci, AT91_UDP_ICR, 0xFFFFFFFF);
- /* disable VBUS interrupt */
- at91_pio_gpio_set_interrupt(VBUS_BASE, VBUS_MASK, 0);
-
- if (sc->sc_vbus_irq_res && sc->sc_vbus_intr_hdl) {
- err = bus_teardown_intr(dev, sc->sc_vbus_irq_res,
- sc->sc_vbus_intr_hdl);
- sc->sc_vbus_intr_hdl = NULL;
- }
- if (sc->sc_vbus_irq_res) {
- bus_release_resource(dev, SYS_RES_IRQ, 1,
- sc->sc_vbus_irq_res);
- sc->sc_vbus_irq_res = NULL;
- }
if (sc->sc_dci.sc_irq_res && sc->sc_dci.sc_intr_hdl) {
/*
* only call at91_udp_uninit() after at91_udp_init()
OpenPOWER on IntegriCloud