[PATCH 2/4] at91_mci: Port to RTEMS and adapt for atsam.

Christian Mauderer christian.mauderer at embedded-brains.de
Wed Nov 8 12:36:58 UTC 2017


From: Christian Mauderer <Christian.Mauderer at 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




More information about the devel mailing list