socsvn commit: r287080 - soc2015/pratiksinghal/cubie-head/sys/arm/allwinner
pratiksinghal at FreeBSD.org
pratiksinghal at FreeBSD.org
Sun Jun 14 09:57:48 UTC 2015
Author: pratiksinghal
Date: Sun Jun 14 09:57:47 2015
New Revision: 287080
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=287080
Log:
DMA transfer interrupt coming but 2 problems still remain :-
1) Interrupt storm
2) Timeout in raw interrupt register
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 Sun Jun 14 09:54:48 2015 (r287079)
+++ soc2015/pratiksinghal/cubie-head/sys/arm/allwinner/a10_mmc.c Sun Jun 14 09:57:47 2015 (r287080)
@@ -57,10 +57,11 @@
#define A10_MMC_IRQRES 1
#define A10_MMC_RESSZ 2
#define A10_MMC_NDESC 16
-#define A10_DMA_NSEGS 16
+#define A10_DMA_NSEGS 16
#define A10_DMA_BUFF_SIZE 512
#define A10_MMC_DMA_FTRGLEVEL_A20 0x20070008
#define A10_MMC_DMA_FTRGLEVEL_A10 0x00070208
+#define A10_MMC_DMA_MAXLEN 0x1000
struct a10_mmc_softc {
bus_space_handle_t a10_bsh;
@@ -92,8 +93,9 @@
int a10_dma_ndesc;
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 */
- bus_dma_tag_t a10_dma_buff_tag ;
- bus_dmamap_t a10_dma_buff_map ;
+ bus_dma_tag_t a10_dma_buff_tag ;
+ bus_dmamap_t a10_dma_buff_map ;
+ bus_addr_t a10_dma_buff_addr ;
};
@@ -107,7 +109,8 @@
static int a10_mmc_attach(device_t);
static int a10_mmc_setup_dma(struct a10_mmc_softc*, device_t) ;
static int a10_mmc_prepare_dma(struct a10_mmc_softc*) ;
-static int a10_mmc_can_do_dma(struct mmc_request*) ;
+static int a10_mmc_can_do_dma(struct mmc_request*) ;
+static void a10_dma_buff_cb(void*, bus_dma_segment_t*, int, int) ;
static int a10_mmc_detach(device_t);
static int a10_mmc_reset(struct a10_mmc_softc *);
static void a10_mmc_intr(void *);
@@ -225,9 +228,9 @@
sc->a10_use_dma = 0 ;
}
}
-#ifdef DEBUG
- device_printf(sc->a10_dev, "DMA status %d\n", sc->a10_use_dma) ;
-#endif
+#ifdef DEBUG
+ device_printf(sc->a10_dev, "DMA status %d\n", sc->a10_use_dma) ;
+#endif
return (0);
fail:
@@ -268,24 +271,25 @@
if((error != 0)&&(error != EINPROGRESS))
return (error) ;
-
- /* Now allocate tag and map for the buffer to be used with transfer. */
+
+ /* Now allocate tag and map for the buffer to be used with transfer. */
error = bus_dma_tag_create(bus_get_dma_tag(dev),1,
0,BUS_SPACE_MAXADDR_32BIT,BUS_SPACE_MAXADDR,
NULL,NULL,A10_DMA_BUFF_SIZE,
A10_DMA_NSEGS,A10_DMA_BUFF_SIZE,0,
- NULL,NULL,&sc->a10_dma_buff_tag) ;
+ NULL,NULL,&sc->a10_dma_buff_tag) ;
if(error)
- return (error) ;
-
- error = bus_dmamap_create(sc->a10_dma_buff_tag,0,&sc->a10_dma_buff_map) ;
+ return (error) ;
+
+ error = bus_dmamap_create(sc->a10_dma_buff_tag,0,&sc->a10_dma_buff_map) ;
if(error)
- return (error) ;
+ return (error) ;
return(0) ;
}
+/* Transfer at most 0x1000 (4K) of data (Experimental) */
static int
a10_mmc_prepare_dma(struct a10_mmc_softc* sc)
{
@@ -299,14 +303,21 @@
bus_size_t off = 0 ;
int desc, rem ;
uint32_t val;
-
desc = 0 ;
-
- /* Pick a segment and program all the descriptors in the segment. */
- 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 ;
+ bus_addr_t paddr = sc->a10_dma_buff_addr ;
+ //bus_size_t len = (sc->a10_dma_cb_arg).segs[0].ds_len ;
+ bus_size_t len = A10_MMC_DMA_MAXLEN ;
rem = min(len,cmd->data->len) ;
+ uint32_t error = bus_dmamap_load(sc->a10_dma_buff_tag, sc->a10_dma_buff_map,
+ cmd->data->data,rem,a10_dma_buff_cb,
+ &sc->a10_dma_buff_addr,BUS_DMA_NOWAIT) ;
+ if(error != 0) {
+ device_printf(sc->a10_dev, "DMA transaction failed due to insufficient resources\n") ;
+ return EIO ;
+ }
+
+ /* Program all the descriptors in this segment. */
while(rem > 0)
{
if(desc == sc->a10_dma_ndesc)
@@ -347,7 +358,7 @@
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) ;
@@ -383,11 +394,14 @@
}
-/* Not implemented yet. */
-static int
+/* Not implemented yet. */
+static int
a10_mmc_can_do_dma(struct mmc_request* req)
{
- return (1) ;
+ if(req->cmd->data->len > A10_MMC_DMA_MAXLEN)
+ return (0) ;
+ else
+ return (1) ;
}
static void
a10_dma_cb(void* arg, bus_dma_segment_t* segs, int nsegs, int error)
@@ -401,6 +415,16 @@
(*(struct a10_mmc_cb*)arg).segs = segs;
}
+static void
+a10_dma_buff_cb(void* arg, bus_dma_segment_t* segs, int nsegs, int error)
+{
+ if(error) {
+ printf("a10_mmc: Error in a10_dma_buff_callback function, code = %d\n", error) ;
+ return ;
+ }
+ *(bus_addr_t*)arg = segs[0].ds_addr ;
+}
+
static int
a10_mmc_detach(device_t dev)
{
@@ -421,8 +445,10 @@
break;
DELAY(100);
}
- if (timeout == 0)
+ if (timeout == 0) {
+ device_printf(sc->a10_dev, "Getting timedout in reset\n") ;
return (ETIMEDOUT);
+ }
/* Set the timeout. */
A10_MMC_WRITE_4(sc, A10_MMC_TIMEOUT, 0xffffffff);
@@ -438,7 +464,7 @@
A10_MMC_WRITE_4(sc, A10_MMC_GCTRL,
A10_MMC_READ_4(sc, A10_MMC_GCTRL) |
A10_MMC_INT_ENABLE | A10_MMC_ACCESS_BY_AHB);
-
+ device_printf(sc->a10_dev,"Reset succesfully in reset function\n") ;
return (0);
}
@@ -557,15 +583,15 @@
A10_MMC_UNLOCK(sc);
return;
}
-#ifdef DEBUG
- device_printf(sc->a10_dev, "imask: %#x, rint: %#x\n", imask, rint);
-#endif
+
+ A10_MMC_WRITE_4(sc, A10_MMC_RINTR, rint) ;
+ A10_MMC_WRITE_4(sc, A10_MMC_IDST, idst) ;
+ A10_MMC_WRITE_4(sc, A10_MMC_IMASK, imask) ;
+ device_printf(sc->a10_dev, "imask: %#x, rint: %#x, idst: %#x\n", imask, rint,idst);
if (sc->a10_req == NULL) {
device_printf(sc->a10_dev,
"Spurious interrupt - no active request, rint: 0x%08X\n",
rint);
- A10_MMC_WRITE_4(sc, A10_MMC_RINTR, rint);
- A10_MMC_WRITE_4(sc, A10_MMC_IDST, idst) ;
A10_MMC_UNLOCK(sc);
return;
}
@@ -578,8 +604,6 @@
}
else
sc->a10_req->cmd->error = MMC_ERR_FAILED;
- A10_MMC_WRITE_4(sc, A10_MMC_RINTR, rint);
- A10_MMC_WRITE_4(sc, A10_MMC_IDST, idst) ;
a10_mmc_req_done(sc);
A10_MMC_UNLOCK(sc);
return;
@@ -588,8 +612,6 @@
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_WRITE_4(sc, A10_MMC_RINTR, rint) ;
a10_mmc_req_done(sc) ;
A10_MMC_UNLOCK(sc) ;
return ;
@@ -603,8 +625,7 @@
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_WRITE_4(sc, A10_MMC_IDST, idst) ;
- A10_MMC_WRITE_4(sc, A10_MMC_RINTR, rint) ;
+ bus_dmamap_unload(sc->a10_dma_buff_tag, sc->a10_dma_buff_map) ;
a10_mmc_req_ok(sc) ;
A10_MMC_UNLOCK(sc) ;
return ;
@@ -626,8 +647,6 @@
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);
}
@@ -638,7 +657,7 @@
int blksz;
struct a10_mmc_softc *sc;
struct mmc_command *cmd;
- uint32_t cmdreg,imask;
+ uint32_t cmdreg ;
sc = device_get_softc(bus);
A10_MMC_LOCK(sc);
@@ -648,7 +667,6 @@
}
sc->a10_req = req;
- imask = 0 ;
cmd = req->cmd;
cmdreg = A10_MMC_START;
if (cmd->opcode == MMC_GO_IDLE_STATE)
@@ -668,15 +686,15 @@
if (cmd->data != NULL) {
sc->a10_intr_wait |= A10_MMC_DATA_OVER;
- sc->a10_dma_ops = 0 ;
+ sc->a10_dma_ops = 0 ;
cmdreg |= A10_MMC_DATA_EXP | A10_MMC_WAIT_PREOVER;
if (cmd->data->flags & MMC_DATA_MULTI) {
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;
- sc->a10_dma_ops = 1 ;
+ sc->a10_dma_ops = 1 ;
}
blksz = min(cmd->data->len, MMC_SECTOR_SIZE);
@@ -684,20 +702,15 @@
A10_MMC_WRITE_4(sc, A10_MMC_BCNTR, cmd->data->len);
if((sc->a10_use_dma == 1)&&(a10_mmc_can_do_dma(req))) {
- uint32_t error = a10_mmc_prepare_dma(sc) ;
- if(error == 0)
- imask |= (A10_MMC_TX_DATA_REQ|A10_MMC_RX_DATA_REQ) ;
+ uint32_t error = a10_mmc_prepare_dma(sc) ;
+ if(error == 0) {
+ A10_MMC_WRITE_4(sc, A10_MMC_IMASK, A10_MMC_READ_4(sc, A10_MMC_IMASK) | (A10_MMC_TX_DATA_REQ | A10_MMC_RX_DATA_REQ)) ;
+ }
else
- device_printf(sc->a10_dev, "Couldn't prepare DMA, using pio instead\n") ;
+ device_printf(sc->a10_dev, "Couldn't prepare DMA, using pio instead\n") ;
}
}
- 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,
More information about the svn-soc-all
mailing list