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