From: Christian Mauderer <christian.maude...@embedded-brains.de>

---
 freebsd/sys/arm/at91/at91_mci.c                | 272 ++++++++++++++++++++++++-
 freebsd/sys/arm/at91/at91_mcireg.h             |  25 +++
 libbsd.py                                      |   6 +
 libbsd_waf.py                                  |   3 +-
 rtemsbsd/include/machine/rtems-bsd-nexus-bus.h |  21 ++
 rtemsbsd/include/rtems/bsd/local/opt_at91.h    |   0
 6 files changed, 317 insertions(+), 10 deletions(-)
 create mode 100644 rtemsbsd/include/rtems/bsd/local/opt_at91.h

diff --git a/freebsd/sys/arm/at91/at91_mci.c b/freebsd/sys/arm/at91/at91_mci.c
index 1fe0f4e36a9..5d448d1cc5c 100644
--- a/freebsd/sys/arm/at91/at91_mci.c
+++ b/freebsd/sys/arm/at91/at91_mci.c
@@ -32,7 +32,7 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
-#include <rtems/bsd/sys/param.h>
+#include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/bio.h>
 #include <sys/bus.h>
@@ -40,7 +40,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/endian.h>
 #include <sys/kernel.h>
 #include <sys/kthread.h>
-#include <rtems/bsd/sys/lock.h>
+#include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/module.h>
 #include <sys/mutex.h>
@@ -76,6 +76,10 @@ __FBSDID("$FreeBSD$");
 
 #include <rtems/bsd/local/opt_at91.h>
 
+#ifdef __rtems__
+#include <libchip/chip.h>
+static sXdmad *pXdmad = &XDMAD_Instance;
+#endif /* __rtems__ */
 /*
  * About running the MCI bus above 25MHz
  *
@@ -141,6 +145,18 @@ __FBSDID("$FreeBSD$");
 #define BBSIZE      (16*1024)
 #define MAX_BLOCKS  ((BBSIZE*BBCOUNT)/512)
 
+#ifdef __rtems__
+#ifdef BOARD_MCK
+uint32_t at91_master_clock = BOARD_MCK;
+#else
+uint32_t at91_master_clock;
+#endif
+#ifdef LIBBSP_ARM_ATSAM_BSP_H
+#define AT91_MCI_HAS_4WIRE 1
+#else
+#error This driver has been adapted to work with ATSAM v7 or e7. If you have 
some other board, please check whether the adaption fits your use case too.
+#endif /* LIBBSP_ARM_ATSAM_BSP_H */
+#endif /* __rtems__ */
 static int mci_debug;
 
 struct at91_mci_softc {
@@ -170,6 +186,14 @@ struct at91_mci_softc {
        uint32_t     bbuf_len[BBCOUNT];   /* len currently queued for bounce 
buf */
        uint32_t     bbuf_curidx;         /* which bbuf is the active DMA 
buffer */
        uint32_t     xfer_offset;         /* offset so far into caller's buf */
+#ifdef __rtems__
+       uint32_t xdma_tx_channel;
+       uint32_t xdma_rx_channel;
+       uint8_t xdma_tx_perid;
+       uint8_t xdma_rx_perid;
+       sXdmadCfg xdma_tx_cfg;
+       sXdmadCfg xdma_rx_cfg;
+#endif /* __rtems__ */
 };
 
 /* bus entry points */
@@ -182,6 +206,10 @@ static void at91_mci_intr(void *);
 static int at91_mci_activate(device_t dev);
 static void at91_mci_deactivate(device_t dev);
 static int at91_mci_is_mci1rev2xx(void);
+#ifdef __rtems__
+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__ */
 
 #define AT91_MCI_LOCK(_sc)             mtx_lock(&(_sc)->sc_mtx)
 #define        AT91_MCI_UNLOCK(_sc)            mtx_unlock(&(_sc)->sc_mtx)
@@ -252,6 +280,7 @@ at91_mci_getaddr(void *arg, bus_dma_segment_t *segs, int 
nsegs, int error)
 static void
 at91_mci_pdc_disable(struct at91_mci_softc *sc)
 {
+#ifndef __rtems__
        WR4(sc, PDC_PTCR, PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS);
        WR4(sc, PDC_RPR, 0);
        WR4(sc, PDC_RCR, 0);
@@ -261,6 +290,12 @@ at91_mci_pdc_disable(struct at91_mci_softc *sc)
        WR4(sc, PDC_TCR, 0);
        WR4(sc, PDC_TNPR, 0);
        WR4(sc, PDC_TNCR, 0);
+#else /* __rtems__ */
+       /* On SAMV71 there is no PDC but a DMAC */
+       XDMAD_StopTransfer(pXdmad, sc->xdma_rx_channel);
+       XDMAD_StopTransfer(pXdmad, sc->xdma_tx_channel);
+       WR4(sc, MCI_DMA, 0);
+#endif /* __rtems__ */
 }
 
 /*
@@ -282,7 +317,11 @@ static void at91_mci_reset(struct at91_mci_softc *sc)
        /* save current state */
 
        imr  = RD4(sc, MCI_IMR);
+#ifndef __rtems__
        mr   = RD4(sc, MCI_MR) & 0x7fff;
+#else /* __rtems__ */
+       mr   = RD4(sc, MCI_MR);
+#endif /* __rtems__ */
        sdcr = RD4(sc, MCI_SDCR);
        dtor = RD4(sc, MCI_DTOR);
 
@@ -316,7 +355,12 @@ at91_mci_init(device_t dev)
        WR4(sc, MCI_CR, MCI_CR_MCIDIS | MCI_CR_SWRST); /* device into reset */
        WR4(sc, MCI_IDR, 0xffffffff);           /* Turn off interrupts */
        WR4(sc, MCI_DTOR, MCI_DTOR_DTOMUL_1M | 1);
+#ifndef __rtems__
        val = MCI_MR_PDCMODE;
+#else /* __rtems__ */
+       val = 0;
+       val |= MCI_MR_RDPROOF | MCI_MR_WRPROOF;
+#endif /* __rtems__ */
        val |= 0x34a;                           /* PWSDIV = 3; CLKDIV = 74 */
 //     if (sc->sc_cap & CAP_MCI1_REV2XX)
 //             val |= MCI_MR_RDPROOF | MCI_MR_WRPROOF;
@@ -369,13 +413,22 @@ at91_mci_attach(device_t dev)
        device_t child;
        int err, i;
 
+#ifdef __rtems__
+#ifdef LIBBSP_ARM_ATSAM_BSP_H
+       PMC_EnablePeripheral(ID_HSMCI);
+       sc->xdma_tx_channel = XDMAD_ALLOC_FAILED;
+       sc->xdma_rx_channel = XDMAD_ALLOC_FAILED;
+#endif /* LIBBSP_ARM_ATSAM_BSP_H */
+#endif /* __rtems__ */
        sctx = device_get_sysctl_ctx(dev);
        soid = device_get_sysctl_tree(dev);
 
        sc->dev = dev;
        sc->sc_cap = 0;
+#ifndef __rtems__
        if (at91_is_rm92())
                sc->sc_cap |= CAP_NEEDS_BYTESWAP;
+#endif /* __rtems__ */
        /*
         * MCI1 Rev 2 controllers need some workarounds, flag if so.
         */
@@ -386,6 +439,57 @@ at91_mci_attach(device_t dev)
        if (err)
                goto out;
 
+#ifdef __rtems__
+       eXdmadRC rc;
+
+       /* Prepare some configurations so they don't have to be fetched on every
+        * setup */
+       sc->xdma_rx_perid = XDMAIF_Get_ChannelNumber(ID_HSMCI,
+           XDMAD_TRANSFER_RX);
+       sc->xdma_tx_perid = XDMAIF_Get_ChannelNumber(ID_HSMCI,
+           XDMAD_TRANSFER_TX);
+       memset(&sc->xdma_rx_cfg, 0, sizeof(sc->xdma_rx_cfg));
+       sc->xdma_rx_cfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
+           XDMAC_CC_MBSIZE_SINGLE | XDMAC_CC_DSYNC_PER2MEM |
+           XDMAC_CC_SWREQ_HWR_CONNECTED | XDMAC_CC_MEMSET_NORMAL_MODE |
+           XDMAC_CC_CSIZE_CHK_1 | XDMAC_CC_DWIDTH_WORD |
+           XDMAC_CC_SIF_AHB_IF1 | XDMAC_CC_DIF_AHB_IF1 |
+           XDMAC_CC_SAM_FIXED_AM | XDMAC_CC_DAM_INCREMENTED_AM |
+           XDMAC_CC_PERID(
+               XDMAIF_Get_ChannelNumber(ID_HSMCI,XDMAD_TRANSFER_RX));
+       memset(&sc->xdma_tx_cfg, 0, sizeof(sc->xdma_tx_cfg));
+       sc->xdma_tx_cfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
+           XDMAC_CC_MBSIZE_SINGLE | XDMAC_CC_DSYNC_MEM2PER |
+           XDMAC_CC_SWREQ_HWR_CONNECTED | XDMAC_CC_MEMSET_NORMAL_MODE |
+           XDMAC_CC_CSIZE_CHK_1 | XDMAC_CC_DWIDTH_WORD |
+           XDMAC_CC_SIF_AHB_IF1 | XDMAC_CC_DIF_AHB_IF1 |
+           XDMAC_CC_SAM_INCREMENTED_AM | XDMAC_CC_DAM_FIXED_AM |
+           XDMAC_CC_PERID(
+               XDMAIF_Get_ChannelNumber(ID_HSMCI,XDMAD_TRANSFER_TX));
+
+       sc->xdma_tx_channel = XDMAD_AllocateChannel(pXdmad,
+           XDMAD_TRANSFER_MEMORY, ID_HSMCI);
+       if (sc->xdma_tx_channel == XDMAD_ALLOC_FAILED)
+               goto out;
+
+       /* FIXME: The two DMA channels are not really necessary for the driver.
+        * But the XDMAD interface does not allow to allocate one and use it
+        * into two directions. The current (2017-07-11) implementation of
+        * the XDMAD interface should work with it. So we might could try it. */
+       sc->xdma_rx_channel = XDMAD_AllocateChannel(pXdmad, ID_HSMCI,
+           XDMAD_TRANSFER_MEMORY);
+       if (sc->xdma_rx_channel == XDMAD_ALLOC_FAILED)
+               goto out;
+
+       rc = XDMAD_PrepareChannel(pXdmad, sc->xdma_rx_channel);
+       if (rc != XDMAD_OK)
+               goto out;
+
+       rc = XDMAD_PrepareChannel(pXdmad, sc->xdma_tx_channel);
+       if (rc != XDMAD_OK)
+               goto out;
+
+#endif /* __rtems__ */
        AT91_MCI_LOCK_INIT(sc);
 
        at91_mci_fini(dev);
@@ -538,13 +642,21 @@ at91_mci_deactivate(device_t dev)
                bus_release_resource(dev, SYS_RES_IRQ,
                    rman_get_rid(sc->irq_res), sc->irq_res);
        sc->irq_res = NULL;
+#ifdef __rtems__
+       if (sc->xdma_rx_channel != XDMAD_ALLOC_FAILED) {
+               XDMAD_FreeChannel(pXdmad, sc->xdma_rx_channel);
+       }
+       if (sc->xdma_tx_channel != XDMAD_ALLOC_FAILED) {
+               XDMAD_FreeChannel(pXdmad, sc->xdma_tx_channel);
+       }
+#endif /* __rtems__ */
        return;
 }
 
 static int
 at91_mci_is_mci1rev2xx(void)
 {
-
+#ifndef __rtems__
        switch (soc_info.type) {
        case AT91_T_SAM9260:
        case AT91_T_SAM9263:
@@ -556,6 +668,10 @@ at91_mci_is_mci1rev2xx(void)
        default:
                return (0);
        }
+#else /* __rtems__ */
+       /* Currently only supports the SAM V71 */
+       return 1;
+#endif /* __rtems__ */
 }
 
 static int
@@ -609,10 +725,81 @@ at91_mci_update_ios(device_t brdev, device_t reqdev)
        return (0);
 }
 
+#ifdef __rtems__
+static LinkedListDescriporView1 dma_desc[MAX_BLOCKS];
+
+static void
+at91_mci_setup_xdma(struct at91_mci_softc *sc, bool read, uint32_t block_size,
+    uint32_t number_blocks, bus_addr_t paddr, uint32_t len)
+{
+       sXdmadCfg *xdma_cfg;
+       uint32_t xdma_channel;
+       const uint32_t xdma_cndc = XDMAC_CNDC_NDVIEW_NDV1 |
+           XDMAC_CNDC_NDE_DSCR_FETCH_EN |
+           XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED |
+           XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED;
+       const uint32_t sa_rdr = (uint32_t)(sc->mem_res->r_bushandle + MCI_RDR);
+       const uint32_t da_tdr = (uint32_t)(sc->mem_res->r_bushandle + MCI_TDR);
+       const uint32_t xdma_interrupt = XDMAC_CIE_BIE | XDMAC_CIE_DIE |
+           XDMAC_CIE_FIE | XDMAC_CIE_RBIE | XDMAC_CIE_WBIE | XDMAC_CIE_ROIE;
+       eXdmadRC rc;
+       size_t i;
+
+       if (read) {
+               xdma_cfg = &sc->xdma_rx_cfg;
+               xdma_channel = sc->xdma_rx_channel;
+       } else {
+               xdma_cfg = &sc->xdma_tx_cfg;
+               xdma_channel = sc->xdma_tx_channel;
+       }
+
+       for (i = 0; i < number_blocks; ++i) {
+               if (read) {
+                       dma_desc[i].mbr_sa = sa_rdr;
+                       dma_desc[i].mbr_da = ((uint32_t)paddr) + i * block_size;
+               } else {
+                       dma_desc[i].mbr_sa = ((uint32_t)paddr) + i * block_size;
+                       dma_desc[i].mbr_da = da_tdr;
+               }
+               dma_desc[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1 |
+                   XDMA_UBC_NDEN_UPDATED | (block_size/4);
+               if (i == number_blocks - 1) {
+                       dma_desc[i].mbr_ubc |= XDMA_UBC_NDE_FETCH_DIS;
+                       dma_desc[i].mbr_nda = 0;
+               } else {
+                       dma_desc[i].mbr_ubc |= XDMA_UBC_NDE_FETCH_EN;
+                       dma_desc[i].mbr_nda = (uint32_t) &dma_desc[i+1];
+               }
+       }
+
+       rc = XDMAD_ConfigureTransfer(pXdmad, xdma_channel, xdma_cfg, xdma_cndc,
+           (uint32_t)dma_desc, xdma_interrupt);
+       if (rc != XDMAD_OK)
+               panic("Could not configure XDMA: %d.", rc);
+
+       /* FIXME: Is that correct? */
+       if (read) {
+               rtems_cache_invalidate_multiple_data_lines(paddr, len);
+       } else {
+               rtems_cache_flush_multiple_data_lines(paddr, len);
+       }
+       rtems_cache_flush_multiple_data_lines(dma_desc, sizeof(dma_desc));
+
+       rc = XDMAD_StartTransfer(pXdmad, xdma_channel);
+       if (rc != XDMAD_OK)
+               panic("Could not start XDMA: %d.", rc);
+
+}
+
+#endif /* __rtems__ */
 static void
 at91_mci_start_cmd(struct at91_mci_softc *sc, struct mmc_command *cmd)
 {
        uint32_t cmdr, mr;
+#ifdef __rtems__
+       uint32_t number_blocks;
+       uint32_t block_size;
+#endif /* __rtems__ */
        struct mmc_data *data;
 
        sc->curcmd = cmd;
@@ -705,11 +892,22 @@ at91_mci_start_cmd(struct at91_mci_softc *sc, struct 
mmc_command *cmd)
         * smaller blocks are possible, but never larger.
         */
 
+#ifndef __rtems__
        WR4(sc, PDC_PTCR, PDC_PTCR_RXTDIS | PDC_PTCR_TXTDIS);
 
        mr = RD4(sc,MCI_MR) & ~MCI_MR_BLKLEN;
        mr |=  min(data->len, 512) << 16;
        WR4(sc, MCI_MR, mr | MCI_MR_PDCMODE|MCI_MR_PDCPADV);
+#else /* __rtems__ */
+       mr = RD4(sc,MCI_MR);
+       WR4(sc, MCI_MR, mr | MCI_MR_PDCPADV);
+
+       WR4(sc, MCI_DMA, MCI_DMA_DMAEN | MCI_DMA_CHKSIZE_1);
+
+       block_size = min(data->len, 512);
+       number_blocks = data->len / block_size;
+       WR4(sc, MCI_BLKR, block_size << 16 | number_blocks);
+#endif /* __rtems__ */
 
        /*
         * Set up DMA.
@@ -754,9 +952,14 @@ at91_mci_start_cmd(struct at91_mci_softc *sc, struct 
mmc_command *cmd)
                        panic("IO read size exceeds MAXDATA\n");
 
                if (data->flags & MMC_DATA_READ) {
+#ifndef __rtems__
                        if (remaining > 2048) // XXX
                                len = remaining / 2;
                        else
+#else
+                       /* FIXME: This reduces performance. Set up DMA in two
+                        * parts instead like done on AT91. */
+#endif /* __rtems__ */
                                len = remaining;
                        err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[0],
                            sc->bbuf_vaddr[0], len, at91_mci_getaddr,
@@ -765,6 +968,7 @@ at91_mci_start_cmd(struct at91_mci_softc *sc, struct 
mmc_command *cmd)
                                panic("IO read dmamap_load failed\n");
                        bus_dmamap_sync(sc->dmatag, sc->bbuf_map[0],
                            BUS_DMASYNC_PREREAD);
+#ifndef __rtems__
                        WR4(sc, PDC_RPR, paddr);
                        WR4(sc, PDC_RCR, len / 4);
                        sc->bbuf_len[0] = len;
@@ -786,6 +990,16 @@ at91_mci_start_cmd(struct at91_mci_softc *sc, struct 
mmc_command *cmd)
                                remaining -= len;
                        }
                        WR4(sc, PDC_PTCR, PDC_PTCR_RXTEN);
+#else /* __rtems__ */
+                       at91_mci_setup_xdma(sc, true, block_size,
+                           number_blocks, paddr, len);
+
+                       sc->bbuf_len[0] = len;
+                       remaining -= len;
+                       sc->bbuf_len[1] = 0;
+                       if (remaining != 0)
+                               panic("Still rx-data left. This should never 
happen.");
+#endif /* __rtems__ */
                } else {
                        len = min(BBSIZE, remaining);
                        at91_bswap_buf(sc, sc->bbuf_vaddr[0], data->data, len);
@@ -796,6 +1010,7 @@ at91_mci_start_cmd(struct at91_mci_softc *sc, struct 
mmc_command *cmd)
                                panic("IO write dmamap_load failed\n");
                        bus_dmamap_sync(sc->dmatag, sc->bbuf_map[0],
                            BUS_DMASYNC_PREWRITE);
+#ifndef __rtems__
                        /*
                         * Erratum workaround:  PDC transfer length on a write
                         * must not be smaller than 12 bytes (3 words); only
@@ -818,12 +1033,23 @@ at91_mci_start_cmd(struct at91_mci_softc *sc, struct 
mmc_command *cmd)
                                        panic("IO write dmamap_load failed\n");
                                bus_dmamap_sync(sc->dmatag, sc->bbuf_map[1],
                                    BUS_DMASYNC_PREWRITE);
-                               WR4(sc, PDC_TNPR, paddr);
-                               WR4(sc, PDC_TNCR, (len < 12) ? 3 : len / 4);
-                               sc->bbuf_len[1] = len;
-                               remaining -= len;
-                       }
-                       /* do not enable PDC xfer until CMDRDY asserted */
+                                       WR4(sc, PDC_TNPR, paddr);
+                                       WR4(sc, PDC_TNCR, (len < 12) ? 3 : len 
/ 4);
+                                       sc->bbuf_len[1] = len;
+                                       remaining -= len;
+                               }
+                               /* do not enable PDC xfer until CMDRDY asserted 
*/
+#else /* __rtems__ */
+                       at91_mci_setup_xdma(sc, false, block_size,
+                           number_blocks, paddr, len);
+
+                       sc->bbuf_len[0] = len;
+                       remaining -= len;
+                       sc->bbuf_len[1] = 0;
+                       if (remaining != 0)
+                               panic("Still tx-data left. This should never 
happen.");
+
+#endif /* __rtems__ */
                }
                data->xfer_len = 0; /* XXX what's this? appears to be unused. */
        }
@@ -932,8 +1158,10 @@ at91_mci_read_done(struct at91_mci_softc *sc, uint32_t sr)
         * operation, otherwise we wait for another ENDRX for the next bufer.
         */
 
+#ifndef __rtems__
        bus_dmamap_sync(sc->dmatag, sc->bbuf_map[curidx], BUS_DMASYNC_POSTREAD);
        bus_dmamap_unload(sc->dmatag, sc->bbuf_map[curidx]);
+#endif /* __rtems__ */
 
        at91_bswap_buf(sc, dataptr + sc->xfer_offset, sc->bbuf_vaddr[curidx], 
len);
 
@@ -958,7 +1186,11 @@ at91_mci_read_done(struct at91_mci_softc *sc, uint32_t sr)
                at91_mci_next_operation(sc);
        } else {
                WR4(sc, PDC_RNCR, 0);
+#ifndef __rtems__
                WR4(sc, MCI_IER, MCI_SR_ERROR | MCI_SR_ENDRX);
+#else /* __rtems__ */
+               WR4(sc, MCI_IER, MCI_SR_ERROR | MCI_SR_XFRDONE);
+#endif /* __rtems__ */
        }
 }
 
@@ -1153,12 +1385,16 @@ at91_mci_cmdrdy(struct at91_mci_softc *sc, uint32_t sr)
         */
        if (cmd->data) {
                uint32_t ier;
+#ifndef __rtems__
                if (cmd->data->flags & MMC_DATA_READ) {
                        ier = MCI_SR_ENDRX;
                } else {
                        ier = MCI_SR_TXBUFE;
                        WR4(sc, PDC_PTCR, PDC_PTCR_TXTEN);
                }
+#else /* __rtems__ */
+               ier = MCI_SR_XFRDONE;
+#endif /* __rtems__ */
                WR4(sc, MCI_IER, MCI_SR_ERROR | ier);
                return;
        }
@@ -1220,6 +1456,7 @@ at91_mci_intr(void *arg)
                }
                at91_mci_next_operation(sc);
        } else {
+#ifndef __rtems__
                if (isr & MCI_SR_TXBUFE) {
 //                     printf("TXBUFE\n");
                        /*
@@ -1244,6 +1481,19 @@ at91_mci_intr(void *arg)
 //                     printf("ENDRX\n");
                        at91_mci_read_done(sc, sr);
                }
+#else /* __rtems__ */
+               if (isr & MCI_SR_XFRDONE) {
+                       struct mmc_command *cmd = sc->curcmd;
+                       if (cmd->data->flags & MMC_DATA_READ) {
+                               at91_mci_read_done(sc, sr);
+                       } else {
+                               if (sr & MCI_SR_BLKE)
+                                       isr |= MCI_SR_BLKE;
+                               else
+                                       WR4(sc, MCI_IER, MCI_SR_BLKE);
+                       }
+               }
+#endif /* __rtems__ */
                if (isr & MCI_SR_NOTBUSY) {
 //                     printf("NOTBUSY\n");
                        at91_mci_notbusy(sc);
@@ -1406,6 +1656,7 @@ static driver_t at91_mci_driver = {
 
 static devclass_t at91_mci_devclass;
 
+#ifndef __rtems__
 #ifdef FDT
 DRIVER_MODULE(at91_mci, simplebus, at91_mci_driver, at91_mci_devclass, NULL,
     NULL);
@@ -1413,5 +1664,8 @@ DRIVER_MODULE(at91_mci, simplebus, at91_mci_driver, 
at91_mci_devclass, NULL,
 DRIVER_MODULE(at91_mci, atmelarm, at91_mci_driver, at91_mci_devclass, NULL,
     NULL);
 #endif
+#else /* __rtems__ */
+DRIVER_MODULE(at91_mci, nexus, at91_mci_driver, at91_mci_devclass, NULL, NULL);
+#endif /* __rtems__ */
 DRIVER_MODULE(mmc, at91_mci, mmc_driver, mmc_devclass, NULL, NULL);
 MODULE_DEPEND(at91_mci, mmc, 1, 1, 1);
diff --git a/freebsd/sys/arm/at91/at91_mcireg.h 
b/freebsd/sys/arm/at91/at91_mcireg.h
index 1831c0dbfc7..b79582bd39e 100644
--- a/freebsd/sys/arm/at91/at91_mcireg.h
+++ b/freebsd/sys/arm/at91/at91_mcireg.h
@@ -37,6 +37,9 @@
 #define MCI_SDCR       0x0c    /* MCI SD Card Register */
 #define MCI_ARGR       0x10    /* MCI Argument Register */
 #define MCI_CMDR       0x14    /* MCI Command Register */
+#ifdef __rtems__
+#define MCI_BLKR       0x18    /* MCI Block Register */
+#endif /* __rtems__ */
 #define MCI_RSPR       0x20    /* MCI Response Registers - 4 of them */
 #define MCI_RDR                0x30    /* MCI Receive Data Register */
 #define MCI_TDR                0x34    /* MCI Transmit Data Register */
@@ -44,6 +47,9 @@
 #define MCI_IER                0x44    /* MCI Interrupt Enable Register */
 #define MCI_IDR                0x48    /* MCI Interrupt Disable Register */
 #define MCI_IMR                0x4c    /* MCI Interrupt Mask Register */
+#ifdef __rtems__
+#define MCI_DMA                0x50    /* MCI DMA Control Register */
+#endif /* __rtems__ */
 
 /* -------- MCI_CR : (MCI Offset: 0x0) MCI Control Register --------  */
 #define        MCI_CR_MCIEN       (0x1u <<  0) /* (MCI) Multimedia Interface 
Enable */
@@ -59,6 +65,7 @@
 #define        MCI_MR_PDCFBYTE (0x1u << 13)    /* (MCI) PDC Force Byte 
Transfer */
 #define        MCI_MR_PDCPADV     (0x1u << 14) /* (MCI) PDC Padding Value */
 #define        MCI_MR_PDCMODE     (0x1u << 15) /* (MCI) PDC Oriented Mode */
+#define        MCI_MR_CLKODD      (0x1u << 16) /* (MCI) Clock Divider is Odd */
 #define        MCI_MR_BLKLEN      0x3fff0000ul /* (MCI) Data Block Length */
 /* -------- MCI_DTOR : (MCI Offset: 0x8) MCI Data Timeout Register --------  */
 #define        MCI_DTOR_DTOCYC      (0xfu <<  0) /* (MCI) Data Timeout Cycle 
Number */
@@ -97,6 +104,11 @@
 #define                MCI_CMDR_TRTYP_BLOCK                (0x0u << 19) /* 
(MCI) Block Transfer type */
 #define                MCI_CMDR_TRTYP_MULTIPLE             (0x1u << 19) /* 
(MCI) Multiple Block transfer type */
 #define                MCI_CMDR_TRTYP_STREAM               (0x2u << 19) /* 
(MCI) Stream transfer type */
+#ifdef __rtems__
+/* -------- MCI_BLKR : (MCI Offset: 0x18) MCI Block Register --------  */
+#define        MCI_BLKR_BCNT        (0xFFFFu << 0)
+#define        MCI_BLKR_BLKLEN      (0xFFFFu << 16)
+#endif /* __rtems__ */
 /* -------- MCI_SR : (MCI Offset: 0x40) MCI Status Register --------  */
 #define        MCI_SR_CMDRDY   (0x1u <<  0) /* (MCI) Command Ready flag */
 #define        MCI_SR_RXRDY    (0x1u <<  1) /* (MCI) RX Ready flag */
@@ -117,6 +129,19 @@
 #define        MCI_SR_DTOE     (0x1u << 22) /* (MCI) Data timeout Error flag */
 #define        MCI_SR_OVRE     (0x1u << 30) /* (MCI) Overrun flag */
 #define        MCI_SR_UNRE     (0x1u << 31) /* (MCI) Underrun flag */
+#ifdef __rtems__
+#define        MCI_SR_XFRDONE  (0x1u << 27) /* (MCI) Underrun flag */
+#endif /* __rtems__ */
+#ifdef __rtems__
+/* -------- MCI_DMA : (MCI Offset: 0x50) MCI DMA Control Register --------  */
+#define        MCI_DMA_DMAEN        (0x1u << 8)
+#define        MCI_DMA_CHKSIZE      (0x7u << 4)
+#define                MCI_DMA_CHKSIZE_1      (0x0u << 4)
+#define                MCI_DMA_CHKSIZE_2      (0x1u << 4)
+#define                MCI_DMA_CHKSIZE_4      (0x2u << 4)
+#define                MCI_DMA_CHKSIZE_8      (0x3u << 4)
+#define                MCI_DMA_CHKSIZE_16     (0x4u << 4)
+#endif /* __rtems__ */
 
 /*     TXRDY,DTIP,ENDTX,TXBUFE,RTOE */
 
diff --git a/libbsd.py b/libbsd.py
index 4c833fbcac3..188b1aec3a2 100644
--- a/libbsd.py
+++ b/libbsd.py
@@ -482,6 +482,10 @@ def mmc(mm):
     mod = builder.Module('mmc')
     mod.addKernelSpaceHeaderFiles(
         [
+            'sys/arm/at91/at91_mcireg.h',
+            'sys/arm/at91/at91_pdcreg.h',
+            'sys/arm/at91/at91reg.h',
+            'sys/arm/at91/at91var.h',
             'sys/dev/mmc/bridge.h',
             'sys/dev/mmc/mmcbrvar.h',
             'sys/dev/mmc/mmc_ioctl.h',
@@ -489,10 +493,12 @@ def mmc(mm):
             'sys/dev/mmc/mmcreg.h',
             'sys/dev/mmc/mmc_subr.h',
             'sys/dev/mmc/mmcvar.h',
+            'sys/sys/watchdog.h',
         ]
     )
     mod.addKernelSpaceSourceFiles(
         [
+            'sys/arm/at91/at91_mci.c',
             'sys/dev/mmc/mmc.c',
             'sys/dev/mmc/mmcsd.c',
             'sys/dev/mmc/mmc_subr.c',
diff --git a/libbsd_waf.py b/libbsd_waf.py
index 3365316f9ef..cbe3fdeabe5 100644
--- a/libbsd_waf.py
+++ b/libbsd_waf.py
@@ -1685,7 +1685,8 @@ def build(bld):
                 source = objs09_source)
     libbsd_use += ["objs09"]
 
-    source = ['freebsd/sys/arm/lpc/if_lpe.c',
+    source = ['freebsd/sys/arm/at91/at91_mci.c',
+              'freebsd/sys/arm/lpc/if_lpe.c',
               'freebsd/sys/arm/lpc/lpc_pwr.c',
               'freebsd/sys/arm/ti/am335x/am335x_musb.c',
               'freebsd/sys/arm/ti/am335x/am335x_prcm.c',
diff --git a/rtemsbsd/include/machine/rtems-bsd-nexus-bus.h 
b/rtemsbsd/include/machine/rtems-bsd-nexus-bus.h
index 251309ae6f5..c650918dee6 100644
--- a/rtemsbsd/include/machine/rtems-bsd-nexus-bus.h
+++ b/rtemsbsd/include/machine/rtems-bsd-nexus-bus.h
@@ -231,6 +231,27 @@ extern "C" {
 #endif /* RTEMS_BSD_DRIVER_DWC_MMC */
 
 /*
+ * Atmel Media Card Interface (MCI).
+ */
+#if !defined(RTEMS_BSD_DRIVER_AT91_MCI0)
+  #define RTEMS_BSD_DRIVER_AT91_MCI0(_base, _irq)                  \
+    static const rtems_bsd_device_resource at91_mci0_res[] = {     \
+      {                                                            \
+        .type = RTEMS_BSD_RES_MEMORY,                              \
+        .start_request = 0,                                        \
+        .start_actual = (_base)                                    \
+      }, {                                                         \
+        .type = RTEMS_BSD_RES_IRQ,                                 \
+        .start_request = 0,                                        \
+        .start_actual = (_irq)                                     \
+      }                                                            \
+    };                                                             \
+    RTEMS_BSD_DEFINE_NEXUS_DEVICE(at91_mci, 0,                     \
+                                  RTEMS_ARRAY_SIZE(at91_mci0_res), \
+                                  &at91_mci0_res[0])
+#endif /* RTEMS_BSD_DRIVER_DWC0 */
+
+/*
  * MMC Driver.
  */
 #if !defined(RTEMS_BSD_DRIVER_MMC)
diff --git a/rtemsbsd/include/rtems/bsd/local/opt_at91.h 
b/rtemsbsd/include/rtems/bsd/local/opt_at91.h
new file mode 100644
index 00000000000..e69de29bb2d
-- 
2.12.3

_______________________________________________
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

Reply via email to