Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 13 Jun 2015 01:46:51 GMT
From:      pratiksinghal@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r287028 - soc2015/pratiksinghal/cubie-head/sys/arm/allwinner
Message-ID:  <201506130146.t5D1kpba022758@socsvn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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) ;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201506130146.t5D1kpba022758>