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