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