summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-26 15:23:08 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-26 15:23:08 +0200
commit3fac9e9cd46b0926f9d90b593f164eb4c718a2a3 (patch)
treea74f4bd51eac5edc701c3724712e13fdfe28ba95
parentmmc: Optimize mmc_wait_for_req() (diff)
downloadrtems-libbsd-3fac9e9cd46b0926f9d90b593f164eb4c718a2a3.tar.bz2
at91_mci: Use real interrupt
Execute at91_mci_intr() in interrupt context. Synchronize MMC requests via RTEMS interrupt lock.
-rw-r--r--freebsd/sys/arm/at91/at91_mci.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/freebsd/sys/arm/at91/at91_mci.c b/freebsd/sys/arm/at91/at91_mci.c
index 44499bfe..82041da1 100644
--- a/freebsd/sys/arm/at91/at91_mci.c
+++ b/freebsd/sys/arm/at91/at91_mci.c
@@ -70,6 +70,7 @@ __FBSDID("$FreeBSD$");
#endif /* __rtems__ */
#if defined(__rtems__) && defined(LIBBSP_ARM_ATSAM_BSP_H)
#ifdef __rtems__
+#include <rtems/irq-extension.h>
#include <libchip/chip.h>
#define AT91_MCI_HAS_4WIRE 1
@@ -150,7 +151,11 @@ static sXdmad *pXdmad = &XDMAD_Instance;
* original driver. But that would need some rework. */
#endif /* __rtems__ */
+#ifndef __rtems__
static int mci_debug;
+#else /* __rtems__ */
+#define mci_debug 0
+#endif /* __rtems__ */
struct at91_mci_softc {
void *intrhand; /* Interrupt handle */
@@ -169,6 +174,9 @@ struct at91_mci_softc {
struct resource *irq_res; /* IRQ resource */
struct resource *mem_res; /* Memory resource */
struct mtx sc_mtx;
+#ifdef __rtems__
+ RTEMS_INTERRUPT_LOCK_MEMBER(sc_lock)
+#endif /* __rtems__ */
bus_dma_tag_t dmatag;
struct mmc_host host;
int bus_busy;
@@ -204,6 +212,7 @@ static void at91_mci_read_done(struct at91_mci_softc *sc, uint32_t sr);
static void at91_mci_write_done(struct at91_mci_softc *sc, uint32_t sr);
#endif /* __rtems__ */
+#ifndef __rtems__
#define AT91_MCI_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
#define AT91_MCI_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
#define AT91_MCI_LOCK_INIT(_sc) \
@@ -212,6 +221,23 @@ static void at91_mci_write_done(struct at91_mci_softc *sc, uint32_t sr);
#define AT91_MCI_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
#define AT91_MCI_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
#define AT91_MCI_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
+#else /* __rtems__ */
+#define AT91_MCI_LOCK(_sc) \
+ rtems_interrupt_lock_context at91_mci_lock_context; \
+ rtems_interrupt_lock_acquire(&(_sc)->sc_lock, &at91_mci_lock_context)
+#define AT91_MCI_UNLOCK(_sc) \
+ rtems_interrupt_lock_release(&(_sc)->sc_lock, &at91_mci_lock_context)
+#define AT91_MCI_LOCK_INIT(_sc) \
+ rtems_interrupt_lock_initialize(&(_sc)->sc_lock, \
+ device_get_nameunit((_sc)->dev))
+#define AT91_MCI_LOCK_DESTROY(_sc) \
+ rtems_interrupt_lock_destroy(&(_sc)->sc_mtx)
+#define AT91_MCI_BUS_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define AT91_MCI_BUS_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define AT91_MCI_BUS_LOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx, device_get_nameunit((_sc)->dev), \
+ "mci", MTX_DEF)
+#endif /* __rtems__ */
static inline uint32_t
RD4(struct at91_mci_softc *sc, bus_size_t off)
@@ -482,6 +508,7 @@ at91_mci_attach(device_t dev)
if (rc != XDMAD_OK)
goto out;
+ AT91_MCI_BUS_LOCK_INIT(sc);
#endif /* __rtems__ */
AT91_MCI_LOCK_INIT(sc);
@@ -516,8 +543,14 @@ at91_mci_attach(device_t dev)
/*
* Activate the interrupt
*/
+#ifndef __rtems__
err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
NULL, at91_mci_intr, sc, &sc->intrhand);
+#else /* __rtems__ */
+ err = rtems_interrupt_handler_install(rman_get_start(sc->irq_res),
+ device_get_nameunit(dev), RTEMS_INTERRUPT_SHARED, at91_mci_intr,
+ sc);
+#endif /* __rtems__ */
if (err) {
AT91_MCI_LOCK_DESTROY(sc);
goto out;
@@ -545,8 +578,10 @@ at91_mci_attach(device_t dev)
CTLFLAG_RW, &sc->allow_overclock, 0,
"Allow up to 30MHz clock for 25MHz request when next highest speed 15MHz or less.");
+#ifndef __rtems__
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "debug",
CTLFLAG_RWTUN, &mci_debug, 0, "enable debug output");
+#endif /* __rtems__ */
/*
* Our real min freq is master_clock/512, but upper driver layers are
@@ -1119,11 +1154,19 @@ at91_mci_acquire_host(device_t brdev, device_t reqdev)
struct at91_mci_softc *sc = device_get_softc(brdev);
int err = 0;
+#ifndef __rtems__
AT91_MCI_LOCK(sc);
+#else /* __rtems__ */
+ AT91_MCI_BUS_LOCK(sc);
+#endif /* __rtems__ */
while (sc->bus_busy)
msleep(sc, &sc->sc_mtx, PZERO, "mciah", hz / 5);
sc->bus_busy++;
+#ifndef __rtems__
AT91_MCI_UNLOCK(sc);
+#else /* __rtems__ */
+ AT91_MCI_BUS_UNLOCK(sc);
+#endif /* __rtems__ */
return (err);
}
@@ -1132,10 +1175,18 @@ at91_mci_release_host(device_t brdev, device_t reqdev)
{
struct at91_mci_softc *sc = device_get_softc(brdev);
+#ifndef __rtems__
AT91_MCI_LOCK(sc);
+#else /* __rtems__ */
+ AT91_MCI_BUS_LOCK(sc);
+#endif /* __rtems__ */
sc->bus_busy--;
wakeup(sc);
+#ifndef __rtems__
AT91_MCI_UNLOCK(sc);
+#else /* __rtems__ */
+ AT91_MCI_BUS_UNLOCK(sc);
+#endif /* __rtems__ */
return (0);
}