socsvn commit: r286989 - soc2015/pratiksinghal/cubie-head/sys/arm/allwinner
pratiksinghal at FreeBSD.org
pratiksinghal at FreeBSD.org
Fri Jun 12 09:51:34 UTC 2015
Author: pratiksinghal
Date: Fri Jun 12 09:51:32 2015
New Revision: 286989
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=286989
Log:
Cleaned up interrupt handling code.
Modified:
soc2015/pratiksinghal/cubie-head/sys/arm/allwinner/a10_mmc.c
Modified: soc2015/pratiksinghal/cubie-head/sys/arm/allwinner/a10_mmc.c
==============================================================================
--- soc2015/pratiksinghal/cubie-head/sys/arm/allwinner/a10_mmc.c Fri Jun 12 09:24:03 2015 (r286988)
+++ soc2015/pratiksinghal/cubie-head/sys/arm/allwinner/a10_mmc.c Fri Jun 12 09:51:32 2015 (r286989)
@@ -58,6 +58,7 @@
#define A10_MMC_RESSZ 2
#define A10_MMC_NDESC 16
#define A10_MMC_DMA_FTRGLEVEL_A20 0x20070008
+#define A10_MMC_DMA_FTRGLEVEL_A10 0x00070208
struct a10_mmc_softc {
bus_space_handle_t a10_bsh;
@@ -87,7 +88,8 @@
bus_dmamap_t a10_dma_map ;
bus_dma_tag_t a10_dma_tag ;
int a10_dma_ndesc;
- void* a10_dma_desc ;
+ void* a10_dma_desc ; /* Contains the kva of the descriptor which we will pass to DLBA */
+ int a10_dma_ops ; /* Which type of operation DMA is performing ? 0:read, 1:write, 2:other */
};
@@ -119,6 +121,12 @@
bus_space_read_4((_sc)->a10_bst, (_sc)->a10_bsh, _reg)
#define A10_MMC_WRITE_4(_sc, _reg, _value) \
bus_space_write_4((_sc)->a10_bst, (_sc)->a10_bsh, _reg, _value)
+#define A10_MMC_READ_2(_sc, _reg) \
+ bus_space_read_2((_sc)->a10_bst, (_sc)->a10_bsh, _reg)
+#define A10_MMC_WRITE_2(_sc, _reg, _value) \
+ bus_space_write_2((_sc)->a10_bst, (_sc)->a10_bsh, _reg, _value)
+
+
static int
a10_mmc_probe(device_t dev)
@@ -143,6 +151,7 @@
sc = device_get_softc(dev);
sc->a10_use_dma = 1 ;
+ sc->a10_dma_ops = 2 ;
sc->a10_dev = dev;
sc->a10_req = NULL;
sc->a10_id = device_get_unit(dev);
@@ -244,7 +253,7 @@
/* Allocate the memory and map at kva sc->a10_dma_desc*/
- error = bus_dmamem_alloc(sc->a10_dma_tag,&sc->a10_dma_desc,BUS_DMA_WAITOK,&sc->a10_dma_map) ;
+ error = bus_dmamem_alloc(sc->a10_dma_tag,&sc->a10_dma_desc,BUS_DMA_WAITOK|BUS_DMA_ZERO,&sc->a10_dma_map) ;
if(error)
return (error) ;
@@ -261,49 +270,47 @@
static int
a10_mmc_prepare_dma(struct a10_mmc_softc* sc)
{
+ device_printf(sc->a10_dev, "Call to prepare dma\n") ;
struct a10_mmc_dma_desc* dma = sc->a10_dma_desc ;
struct mmc_command* cmd = sc->a10_req->cmd ;
int read = (sc->a10_req->cmd->data->flags & MMC_DATA_WRITE) ? 0 : 1 ;
bus_addr_t desc_paddr = (sc->a10_dma_cb_arg).addr ;
bus_size_t off = 0 ;
- int desc, rem,seg ;
+ int desc, rem ;
uint32_t val;
desc = 0 ;
/* Pick a segment and program all the descriptors in the segment. */
- for(seg = 0; seg < sc->a10_dma_cb_arg.nsegs ; seg++)
+ bus_addr_t paddr = (sc->a10_dma_cb_arg).segs[0].ds_addr;
+ bus_size_t len = (sc->a10_dma_cb_arg).segs[0].ds_len ;
+ rem = min(len,cmd->data->len) ;
+ while(rem > 0)
{
- bus_addr_t paddr = (sc->a10_dma_cb_arg).segs[seg].ds_addr;
- bus_size_t len = (sc->a10_dma_cb_arg).segs[seg].ds_len ;
- rem = min(len,cmd->data->len) ;
- while(rem > 0)
- {
- if(desc == sc->a10_dma_ndesc)
- break ;
- len = min(sc->a10_dma_xfer_len, rem) ;
- dma[desc].buff_size = htole32(len) ;
- dma[desc].buff_addr = htole32(paddr + off) ;
- dma[desc].config = htole32(A10_MMC_DMA_CONFIG_CH|A10_MMC_DMA_CONFIG_OWN) ;
-
- cmd->data->len -= len ;
- rem -= len ;
- off += len ;
- if(desc == 0) {
- dma[desc].config |= htole32(A10_MMC_DMA_CONFIG_FD) ;
- }
-
- if(cmd->data->len == 0) {
- dma[desc].config |= htole32(A10_MMC_DMA_CONFIG_LD) ;
- dma[desc].config |= htole32(A10_MMC_DMA_CONFIG_ER) ;
- dma[desc].next = 0 ;
- }
- else {
- dma[desc].config |= htole32(A10_MMC_DMA_CONFIG_DIC) ;
- dma[desc].next = htole32(desc_paddr + ((desc+1)*sizeof(struct a10_mmc_dma_desc))) ;
- }
- desc++ ;
+ if(desc == sc->a10_dma_ndesc)
+ break ;
+ len = min(sc->a10_dma_xfer_len, rem) ;
+ dma[desc].buff_size = htole32(len) ;
+ dma[desc].buff_addr = htole32(paddr + off) ;
+ dma[desc].config = htole32(A10_MMC_DMA_CONFIG_CH|A10_MMC_DMA_CONFIG_OWN) ;
+
+ cmd->data->len -= len ;
+ rem -= len ;
+ off += len ;
+ if(desc == 0) {
+ dma[desc].config |= htole32(A10_MMC_DMA_CONFIG_FD) ;
+ }
+
+ if(cmd->data->len == 0) {
+ dma[desc].config |= htole32(A10_MMC_DMA_CONFIG_LD) ;
+ dma[desc].config |= htole32(A10_MMC_DMA_CONFIG_ER) ;
+ dma[desc].next = 0 ;
+ }
+ else {
+ dma[desc].config |= htole32(A10_MMC_DMA_CONFIG_DIC) ;
+ dma[desc].next = htole32(desc_paddr + ((desc+1)*sizeof(struct a10_mmc_dma_desc))) ;
}
+ desc++ ;
}
if(desc == sc->a10_dma_ndesc) {
@@ -313,27 +320,42 @@
bus_dmamap_sync(sc->a10_dma_tag, sc->a10_dma_map, BUS_DMASYNC_PREWRITE) ;
+ /* Enable DMA and interrupts*/
val = A10_MMC_READ_4(sc, A10_MMC_GCTRL) ;
val |= A10_MMC_DMA_ENABLE ;
val |= A10_MMC_INT_ENABLE ;
A10_MMC_WRITE_4(sc, A10_MMC_GCTRL,val) ;
+
+ /* Reset DMA */
val |= A10_MMC_DMA_RESET ;
A10_MMC_WRITE_4(sc, A10_MMC_GCTRL,val) ;
+
+ /* IDMA Soft reset */
A10_MMC_WRITE_4(sc, A10_MMC_DMAC,A10_MMC_IDMAC_SOFT_RST) ;
+
+ /* Enable IDMA with Fix burst */
A10_MMC_WRITE_4(sc, A10_MMC_DMAC,A10_MMC_IDMAC_IDMA_ON | A10_MMC_IDMAC_FIX_BURST) ;
+
+ /* Disable interrupts */
val = A10_MMC_READ_4(sc,A10_MMC_IDIE) ;
val &= ~(A10_MMC_IDMAC_RECEIVE_INT | A10_MMC_IDMAC_TRANSMIT_INT) ;
+ A10_MMC_WRITE_4(sc,A10_MMC_IDIE, val) ;
- if(read == 1) {
+ /* Enable required interrupts */
+ if(read == 1)
val |= A10_MMC_IDMAC_RECEIVE_INT ;
- }
- else {
+ else
val |= A10_MMC_IDMAC_TRANSMIT_INT ;
- }
-
A10_MMC_WRITE_4(sc, A10_MMC_IDIE,val) ;
+
+ /* Give the starting segment physical address */
A10_MMC_WRITE_4(sc, A10_MMC_DLBA,desc_paddr) ;
- A10_MMC_WRITE_4(sc, A10_MMC_FTRGL,A10_MMC_DMA_FTRGLEVEL_A20) ;
+
+ /* Configure the watermark level. */
+ A10_MMC_WRITE_4(sc, A10_MMC_FTRGL,A10_MMC_DMA_FTRGLEVEL_A10) ;
+
+ /* Disable debounce*/
+ A10_MMC_WRITE_4(sc, A10_MMC_READ_4(sc, A10_MMC_GCTRL) & (~A10_MMC_DEBOUNCE_ENABLE), A10_MMC_GCTRL);
return (0) ;
}
@@ -503,7 +525,8 @@
rint = A10_MMC_READ_4(sc, A10_MMC_RINTR);
imask = A10_MMC_READ_4(sc, A10_MMC_IMASK);
idst = A10_MMC_READ_4(sc, A10_MMC_IDST) ;
- if (imask == 0 && rint == 0 ) {
+
+ if (imask == 0 && rint == 0 && idst == 0 ) {
A10_MMC_UNLOCK(sc);
return;
}
@@ -521,8 +544,10 @@
if (rint & A10_MMC_INT_ERR_BIT) {
device_printf(sc->a10_dev, "error rint: 0x%08X\n", rint);
- if (rint & A10_MMC_RESP_TIMEOUT)
+ if (rint & A10_MMC_RESP_TIMEOUT) {
+ device_printf(sc->a10_dev,"Setting timeout in intr\n") ;
sc->a10_req->cmd->error = MMC_ERR_TIMEOUT;
+ }
else
sc->a10_req->cmd->error = MMC_ERR_FAILED;
A10_MMC_WRITE_4(sc, A10_MMC_RINTR, rint);
@@ -531,52 +556,48 @@
return;
}
- /* Do we have to return from here or continue afterwards ? */
- /* What is the DMA only, what is PIO only and what is common part ? */
- if(sc->a10_use_dma == 1) {
- uint32_t comp = 0 ;
- device_printf(sc->a10_dev, "IDST = %d\n", idst) ;
- sc->a10_idst = idst ;
- if(idst & A10_MMC_IDMAC_ERROR) {
- device_printf(sc->a10_dev, "I/O error with DMA\n") ;
- sc->a10_req->cmd->error = EIO ;
- }
- if(!(idst & A10_MMC_IDMAC_COMPLETE)) {
- device_printf(sc->a10_dev, "Timeout error with DMA\n") ;
- sc->a10_req->cmd->error = ETIMEDOUT ;
- }
- else
- comp = 1 ;
-
- if(sc->a10_req->cmd->data != NULL) {
- data = sc->a10_req->cmd->data ;
- if(data->flags&MMC_DATA_WRITE)
- bus_dmamap_sync(sc->a10_dma_tag,sc->a10_dma_map,BUS_DMASYNC_POSTWRITE) ;
- else
- bus_dmamap_sync(sc->a10_dma_tag,sc->a10_dma_map, BUS_DMASYNC_POSTREAD) ;
- }
+ if(idst & A10_MMC_IDMAC_ERROR) {
+ device_printf(sc->a10_dev, "error rint: 0x%08x\n", idst) ;
+ sc->a10_req->cmd->error = MMC_ERR_FAILED ;
+ A10_MMC_WRITE_4(sc, A10_MMC_IDST, idst) ;
+ a10_mmc_req_done(sc) ;
+ A10_MMC_UNLOCK(sc) ;
+ return ;
+ }
- if(comp == 0)
- a10_mmc_req_done(sc) ;
- else {
- device_printf(sc->a10_dev, "DMA transfer working!\n") ;
- a10_mmc_req_ok(sc) ;
- }
+ if(idst & A10_MMC_IDMAC_COMPLETE) {
+ device_printf(sc->a10_dev, "DMA transfer complete!\n", idst) ;
+ if(sc->a10_dma_ops == 0)
+ bus_dmamap_sync(sc->a10_dma_tag, sc->a10_dma_map, BUS_DMASYNC_POSTREAD) ;
+ else if(sc->a10_dma_ops == 1)
+ bus_dmamap_sync(sc->a10_dma_tag, sc->a10_dma_map, BUS_DMASYNC_POSTWRITE) ;
+ else
+ device_printf(sc->a10_dev, "Invalid operations request!\n") ;
+ a10_mmc_req_ok(sc) ;
+ A10_MMC_UNLOCK(sc) ;
+ return ;
+ }
+ if((idst)&&(!(idst & A10_MMC_IDMAC_COMPLETE))) {
+ device_printf(sc->a10_dev, "DMA timeout error!\n", idst) ;
+ sc->a10_req_cmd->error = MMC_ERR_TIMEOUT ;
+ a10_mmc_req_done(sc) ;
+ A10_MMC_UNLOCK(sc) ;
}
- A10_MMC_WRITE_4(sc, A10_MMC_IDST, idst) ;
sc->a10_intr |= rint;
- if(sc->a10_use_dma == 0) {
- data = sc->a10_req->cmd->data;
- if (data != NULL && (rint & (A10_MMC_DATA_OVER |
- A10_MMC_RX_DATA_REQ | A10_MMC_TX_DATA_REQ)) != 0)
- a10_mmc_pio_transfer(sc, data);
- if ((sc->a10_intr & sc->a10_intr_wait) == sc->a10_intr_wait)
- a10_mmc_req_ok(sc);
+ data = sc->a10_req->cmd->data;
+
+ if (data != NULL && (rint & (A10_MMC_DATA_OVER |
+ A10_MMC_RX_DATA_REQ | A10_MMC_TX_DATA_REQ)) != 0)
+ a10_mmc_pio_transfer(sc, data);
}
+ if ((sc->a10_intr & sc->a10_intr_wait) == sc->a10_intr_wait)
+ a10_mmc_req_ok(sc);
+
A10_MMC_WRITE_4(sc, A10_MMC_RINTR, rint);
+ A10_MMC_WRITE_4(sc, A10_MMC_IDST, idst) ;
A10_MMC_UNLOCK(sc);
}
@@ -586,7 +607,9 @@
int blksz;
struct a10_mmc_softc *sc;
struct mmc_command *cmd;
- uint32_t cmdreg;
+ uint32_t cmdreg,imask;
+
+ imask = A10_MMC_CMD_DONE | A10_MMC_INT_ERR_BIT | A10_MMC_WAIT_PREOVER | A10_MMC_DATA_OVER ;
sc = device_get_softc(bus);
A10_MMC_LOCK(sc);
@@ -612,6 +635,7 @@
sc->a10_idst = 0 ;
sc->a10_intr_wait = A10_MMC_CMD_DONE;
cmd->error = MMC_ERR_NONE;
+ /* Will data be NULL when reading data ? */
if (cmd->data != NULL) {
sc->a10_intr_wait |= A10_MMC_DATA_OVER;
cmdreg |= A10_MMC_DATA_EXP | A10_MMC_WAIT_PREOVER;
@@ -619,21 +643,29 @@
cmdreg |= A10_MMC_SEND_AUTOSTOP;
sc->a10_intr_wait |= A10_MMC_AUTOCMD_DONE;
}
- if (cmd->data->flags & MMC_DATA_WRITE)
+ if (cmd->data->flags & MMC_DATA_WRITE) {
cmdreg |= A10_MMC_WRITE;
+ if(sc->a10_use_dma == 1)
+ imask |= A10_MMC_TX_DATA_REQ ;
+ }
+ else {
+ if(sc->a10_use_dma == 1)
+ imask |= A10_MMC_RX_DATA_REQ ;
+ }
blksz = min(cmd->data->len, MMC_SECTOR_SIZE);
A10_MMC_WRITE_4(sc, A10_MMC_BLKSZ, blksz);
A10_MMC_WRITE_4(sc, A10_MMC_BCNTR, cmd->data->len);
- }
-
- A10_MMC_WRITE_4(sc, A10_MMC_CARG, cmd->arg);
-
- if(cmd->data != NULL ) {
- if(sc->a10_use_dma == 1) {
+ if(sc->a10_use_dma == 1)
a10_mmc_prepare_dma(sc) ;
- }
}
+ uint32_t newmask = A10_MMC_READ_4(sc, A10_MMC_IMASK) ;
+ if(!(imask & A10_MMC_SDIO_INT))
+ A10_MMC_WRITE_2(sc, A10_MMC_IMASK, newmask) ;
+ else
+ A10_MMC_WRITE_4(sc, A10_MMC_IMASK, newmask) ;
+
+ A10_MMC_WRITE_4(sc, A10_MMC_CARG, cmd->arg);
A10_MMC_WRITE_4(sc, A10_MMC_CMDR, cmdreg | cmd->opcode);
callout_reset(&sc->a10_timeoutc, sc->a10_timeout * hz,
a10_mmc_timeout, sc);
More information about the svn-soc-all
mailing list