socsvn commit: r287028 - soc2015/pratiksinghal/cubie-head/sys/arm/allwinner
pratiksinghal at FreeBSD.org
pratiksinghal at FreeBSD.org
Sat Jun 13 01:46:52 UTC 2015
Author: pratiksinghal
Date: Sat Jun 13 01:46:51 2015
New Revision: 287028
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=287028
Log:
1) Added the code for setting up data buffer
2) Cleaned up the code in a10_mmc_request.
Changes in a10_mmc_prepare_dma still to be done though.
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 22:05:04 2015 (r287027)
+++ soc2015/pratiksinghal/cubie-head/sys/arm/allwinner/a10_mmc.c Sat Jun 13 01:46:51 2015 (r287028)
@@ -57,6 +57,8 @@
#define A10_MMC_IRQRES 1
#define A10_MMC_RESSZ 2
#define A10_MMC_NDESC 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
@@ -103,6 +105,7 @@
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_detach(device_t);
static int a10_mmc_reset(struct a10_mmc_softc *);
static void a10_mmc_intr(void *);
@@ -220,8 +223,9 @@
sc->a10_use_dma = 0 ;
}
}
- //sc->a10_use_dma = 0 ; /* Remove this after testing */
- device_printf(sc->a10_dev, "Setting up dma finished %d\n", sc->a10_use_dma) ;
+#ifdef DEBUG
+ device_printf(sc->a10_dev, "DMA status %d\n", sc->a10_use_dma) ;
+#endif
return (0);
fail:
@@ -262,6 +266,19 @@
if((error != 0)&&(error != EINPROGRESS))
return (error) ;
+
+ /* 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_buf_tag) ;
+ if(error)
+ return (error) ;
+
+ error = bus_dma_map_create(sc->a10_dma_buf_tag,0,&sc->a10_dma_buf_map) ;
+ if(error)
+ return (error) ;
return(0) ;
@@ -270,9 +287,11 @@
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 ;
+ device_printf(sc->a10_dev,"sc->a10_req = %p, sc->a10_req->cmd = %p, sc->a10_req->cmd->data = %p, dma = %p\n", sc->a10_req,sc->a10_req->cmd,sc->a10_req->cmd->data,dma) ;
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 ;
@@ -280,11 +299,12 @@
uint32_t val;
desc = 0 ;
-
+ device_printf(sc->a10_dev,"Before loop\n") ;
/* 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 ;
rem = min(len,cmd->data->len) ;
+ device_printf(sc->a10_dev, "Before rem\n") ;
while(rem > 0)
{
if(desc == sc->a10_dma_ndesc)
@@ -313,12 +333,15 @@
desc++ ;
}
+ device_printf(sc->a10_dev, "After the completion of loop\n") ;
if(desc == sc->a10_dma_ndesc) {
device_printf(sc->a10_dev, "Couldn't find enough descriptors for DMA transfer! desc = %d,sc->a10_dma_ndesc = %d\n",desc, sc->a10_dma_ndesc) ;
return EIO ;
}
+ device_printf(sc->a10_dev, "Before syncing\n") ;
bus_dmamap_sync(sc->a10_dma_tag, sc->a10_dma_map, BUS_DMASYNC_PREWRITE) ;
+ device_printf(sc->a10_dev, "After syncing\n") ;
/* Enable DMA and interrupts*/
val = A10_MMC_READ_4(sc, A10_MMC_GCTRL) ;
@@ -356,11 +379,17 @@
/* Disable debounce*/
A10_MMC_WRITE_4(sc, A10_MMC_READ_4(sc, A10_MMC_GCTRL) & (~A10_MMC_DEBOUNCE_ENABLE), A10_MMC_GCTRL);
-
+ device_printf(sc->a10_dev, "Completed the prepare function\n") ;
return (0) ;
}
+/* Not implemented yet. */
+static int
+a10_mmc_can_do_dma(struct mmc_request* req)
+{
+ return (1) ;
+}
static void
a10_dma_cb(void* arg, bus_dma_segment_t* segs, int nsegs, int error)
{
@@ -369,7 +398,6 @@
return ;
}
- (*(struct a10_mmc_cb*)arg).nsegs = nsegs ;
(*(struct a10_mmc_cb*)arg).addr = segs[0].ds_addr ;
(*(struct a10_mmc_cb*)arg).segs = segs;
}
@@ -566,7 +594,7 @@
}
if(idst & A10_MMC_IDMAC_COMPLETE) {
- device_printf(sc->a10_dev, "DMA transfer complete!\n", idst) ;
+ device_printf(sc->a10_dev, "DMA transfer complete!\n") ;
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)
@@ -579,8 +607,8 @@
}
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 ;
+ device_printf(sc->a10_dev, "DMA timeout error!\n") ;
+ sc->a10_req->cmd->error = MMC_ERR_TIMEOUT ;
a10_mmc_req_done(sc) ;
A10_MMC_UNLOCK(sc) ;
}
@@ -591,8 +619,6 @@
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);
@@ -601,6 +627,7 @@
A10_MMC_UNLOCK(sc);
}
+/* Interrupt masking in linux kernel apart from RX/TX is still dubious. */
static int
a10_mmc_request(device_t bus, device_t child, struct mmc_request *req)
{
@@ -609,16 +636,15 @@
struct mmc_command *cmd;
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);
if (sc->a10_req) {
A10_MMC_UNLOCK(sc);
return (EBUSY);
}
+
sc->a10_req = req;
- device_printf(sc->a10_dev, "a10_req = %p\n", sc->a10_req) ;
+ imask = 0 ;
cmd = req->cmd;
cmdreg = A10_MMC_START;
if (cmd->opcode == MMC_GO_IDLE_STATE)
@@ -635,7 +661,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;
@@ -643,20 +669,20 @@
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);
- if(sc->a10_use_dma == 1)
- a10_mmc_prepare_dma(sc) ;
+
+ 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) ;
+ else
+ device_printf(sc->a10_dev, "Couldn't prepare DMA, using pio instead\n") ;
+ }
}
uint32_t newmask = A10_MMC_READ_4(sc, A10_MMC_IMASK) ;
More information about the svn-soc-all
mailing list