Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 31 May 2018 15:39:39 +0000 (UTC)
From:      Emmanuel Vadot <manu@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r334434 - head/sys/arm/allwinner
Message-ID:  <201805311539.w4VFdd8w055797@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: manu
Date: Thu May 31 15:39:39 2018
New Revision: 334434
URL: https://svnweb.freebsd.org/changeset/base/334434

Log:
  aw_mmc: Rework DMA
  
   - Calculate the number of segments based on the page size
   - Add some comments on dma function so it's easier to read
   - Only enable interrupts on the last dma segment
   - If the segments size is the max transfer size, use the special size 0
   for the controller.
   - The max_data ivars is in block so calculate it properly.

Modified:
  head/sys/arm/allwinner/aw_mmc.c

Modified: head/sys/arm/allwinner/aw_mmc.c
==============================================================================
--- head/sys/arm/allwinner/aw_mmc.c	Thu May 31 15:36:26 2018	(r334433)
+++ head/sys/arm/allwinner/aw_mmc.c	Thu May 31 15:39:39 2018	(r334434)
@@ -58,8 +58,10 @@ __FBSDID("$FreeBSD$");
 #define	AW_MMC_MEMRES		0
 #define	AW_MMC_IRQRES		1
 #define	AW_MMC_RESSZ		2
-#define	AW_MMC_DMA_SEGS		((MAXPHYS / PAGE_SIZE) + 1)
+#define	AW_MMC_DMA_SEGS		(PAGE_SIZE / sizeof(struct aw_mmc_dma_desc))
+#define	AW_MMC_DMA_DESC_SIZE	(sizeof(struct aw_mmc_dma_desc) * AW_MMC_DMA_SEGS)
 #define	AW_MMC_DMA_FTRGLEVEL	0x20070008
+
 #define	AW_MMC_RESET_RETRY	1000
 
 #define	CARD_ID_FREQUENCY	400000
@@ -335,34 +337,50 @@ aw_dma_desc_cb(void *arg, bus_dma_segment_t *segs, int
 static int
 aw_mmc_setup_dma(struct aw_mmc_softc *sc)
 {
-	int dma_desc_size, error;
+	int error;
 
 	/* Allocate the DMA descriptor memory. */
-	dma_desc_size = sizeof(struct aw_mmc_dma_desc) * AW_MMC_DMA_SEGS;
-	error = bus_dma_tag_create(bus_get_dma_tag(sc->aw_dev),
-	    AW_MMC_DMA_ALIGN, 0,
-	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
-	    dma_desc_size, 1, dma_desc_size, 0, NULL, NULL, &sc->aw_dma_tag);
+	error = bus_dma_tag_create(
+	    bus_get_dma_tag(sc->aw_dev),	/* parent */
+	    AW_MMC_DMA_ALIGN, 0,		/* align, boundary */
+	    BUS_SPACE_MAXADDR_32BIT,		/* lowaddr */
+	    BUS_SPACE_MAXADDR,			/* highaddr */
+	    NULL, NULL,				/* filter, filterarg*/
+	    AW_MMC_DMA_DESC_SIZE, 1,		/* maxsize, nsegment */
+	    AW_MMC_DMA_DESC_SIZE,		/* maxsegsize */
+	    0,					/* flags */
+	    NULL, NULL,				/* lock, lockarg*/
+	    &sc->aw_dma_tag);
 	if (error)
 		return (error);
+
 	error = bus_dmamem_alloc(sc->aw_dma_tag, &sc->aw_dma_desc,
-	    BUS_DMA_WAITOK | BUS_DMA_ZERO, &sc->aw_dma_map);
+	    BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO,
+	    &sc->aw_dma_map);
 	if (error)
 		return (error);
 
-	error = bus_dmamap_load(sc->aw_dma_tag, sc->aw_dma_map,
-	    sc->aw_dma_desc, dma_desc_size, aw_dma_desc_cb, sc, 0);
+	error = bus_dmamap_load(sc->aw_dma_tag,
+	    sc->aw_dma_map,
+	    sc->aw_dma_desc, AW_MMC_DMA_DESC_SIZE,
+	    aw_dma_desc_cb, sc, 0);
 	if (error)
 		return (error);
 	if (sc->aw_dma_map_err)
 		return (sc->aw_dma_map_err);
 
 	/* Create the DMA map for data transfers. */
-	error = bus_dma_tag_create(bus_get_dma_tag(sc->aw_dev),
-	    AW_MMC_DMA_ALIGN, 0,
-	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
-	    sc->aw_mmc_conf->dma_xferlen * AW_MMC_DMA_SEGS, AW_MMC_DMA_SEGS,
-	    sc->aw_mmc_conf->dma_xferlen, BUS_DMA_ALLOCNOW, NULL, NULL,
+	error = bus_dma_tag_create(
+	    bus_get_dma_tag(sc->aw_dev),	/* parent */
+	    AW_MMC_DMA_ALIGN, 0,		/* align, boundary */
+	    BUS_SPACE_MAXADDR_32BIT,		/* lowaddr */
+	    BUS_SPACE_MAXADDR,			/* highaddr */
+	    NULL, NULL,				/* filter, filterarg*/
+	    sc->aw_mmc_conf->dma_xferlen *
+	    AW_MMC_DMA_SEGS, AW_MMC_DMA_SEGS,	/* maxsize, nsegments */
+	    sc->aw_mmc_conf->dma_xferlen,	/* maxsegsize */
+	    BUS_DMA_ALLOCNOW,			/* flags */
+	    NULL, NULL,				/* lock, lockarg*/
 	    &sc->aw_dma_buf_tag);
 	if (error)
 		return (error);
@@ -389,22 +407,23 @@ aw_dma_cb(void *arg, bus_dma_segment_t *segs, int nseg
 
 	dma_desc = sc->aw_dma_desc;
 	for (i = 0; i < nsegs; i++) {
-		dma_desc[i].buf_size = segs[i].ds_len;
+		if (segs[i].ds_len == sc->aw_mmc_conf->dma_xferlen)
+			dma_desc[i].buf_size = 0;		/* Size of 0 indicate max len */
+		else
+			dma_desc[i].buf_size = segs[i].ds_len;
 		dma_desc[i].buf_addr = segs[i].ds_addr;
 		dma_desc[i].config = AW_MMC_DMA_CONFIG_CH |
-		    AW_MMC_DMA_CONFIG_OWN;
-		if (i == 0)
-			dma_desc[i].config |= AW_MMC_DMA_CONFIG_FD;
-		if (i < (nsegs - 1)) {
-			dma_desc[i].config |= AW_MMC_DMA_CONFIG_DIC;
-			dma_desc[i].next = sc->aw_dma_desc_phys +
-			    ((i + 1) * sizeof(struct aw_mmc_dma_desc));
-		} else {
-			dma_desc[i].config |= AW_MMC_DMA_CONFIG_LD |
-			    AW_MMC_DMA_CONFIG_ER;
-			dma_desc[i].next = 0;
-		}
+			AW_MMC_DMA_CONFIG_OWN | AW_MMC_DMA_CONFIG_DIC;
+
+		dma_desc[i].next = sc->aw_dma_desc_phys +
+			((i + 1) * sizeof(struct aw_mmc_dma_desc));
 	}
+
+	dma_desc[0].config |= AW_MMC_DMA_CONFIG_FD;
+	dma_desc[nsegs - 1].config |= AW_MMC_DMA_CONFIG_LD |
+		AW_MMC_DMA_CONFIG_ER;
+	dma_desc[nsegs - 1].config &= ~AW_MMC_DMA_CONFIG_DIC;
+	dma_desc[nsegs - 1].next = 0;
 }
 
 static int
@@ -472,7 +491,7 @@ aw_mmc_reset(struct aw_mmc_softc *sc)
 	reg = AW_MMC_READ_4(sc, AW_MMC_GCTL);
 	reg |= AW_MMC_GCTL_RESET;
 	AW_MMC_WRITE_4(sc, AW_MMC_GCTL, reg);
-	timeout = 1000;
+	timeout = AW_MMC_RESET_RETRY;
 	while (--timeout > 0) {
 		if ((AW_MMC_READ_4(sc, AW_MMC_GCTL) & AW_MMC_GCTL_RESET) == 0)
 			break;
@@ -540,10 +559,10 @@ aw_mmc_req_done(struct aw_mmc_softc *sc)
 
 		retry = AW_MMC_RESET_RETRY;
 		while (--retry > 0) {
-			val = AW_MMC_READ_4(sc, AW_MMC_GCTL);
-			if ((val & mask) == 0)
+			if ((AW_MMC_READ_4(sc, AW_MMC_GCTL) &
+			    AW_MMC_GCTL_RESET) == 0)
 				break;
-			DELAY(10);
+			DELAY(100);
 		}
 		if (retry == 0)
 			device_printf(sc->aw_dev,
@@ -688,6 +707,7 @@ aw_mmc_request(device_t bus, device_t child, struct mm
 	int err;
 
 	sc = device_get_softc(bus);
+
 	AW_MMC_LOCK(sc);
 	if (sc->aw_req) {
 		AW_MMC_UNLOCK(sc);
@@ -819,7 +839,8 @@ aw_mmc_read_ivar(device_t bus, device_t child, int whi
 		*(int *)result = sc->aw_host.ios.timing;
 		break;
 	case MMCBR_IVAR_MAX_DATA:
-		*(int *)result = 65535;
+		*(int *)result = (sc->aw_mmc_conf->dma_xferlen *
+		    AW_MMC_DMA_SEGS) / MMC_SECTOR_SIZE;
 		break;
 	}
 



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