svn commit: r358635 - head/sys/dev/mmc/host

Emmanuel Vadot manu at FreeBSD.org
Wed Mar 4 20:01:04 UTC 2020


Author: manu
Date: Wed Mar  4 20:01:03 2020
New Revision: 358635
URL: https://svnweb.freebsd.org/changeset/base/358635

Log:
  dwmmc: Rework the DMA engine
  
  Each segment can be up to 4096 bytes in chain structure according to the
  RK3399 TRM Part 2.
  Set the buffers in full ring where the last one point to the first one.
  Correctly reports the MMC_IVAR_MAX_DATA.
  Use CACHE_LINE_SIZE for bus_dma alignment.
  
  MFC after:	1 month
  Differential Revision:	https://reviews.freebsd.org/D23894

Modified:
  head/sys/dev/mmc/host/dwmmc.c
  head/sys/dev/mmc/host/dwmmc_hisi.c
  head/sys/dev/mmc/host/dwmmc_var.h

Modified: head/sys/dev/mmc/host/dwmmc.c
==============================================================================
--- head/sys/dev/mmc/host/dwmmc.c	Wed Mar  4 19:52:34 2020	(r358634)
+++ head/sys/dev/mmc/host/dwmmc.c	Wed Mar  4 20:01:03 2020	(r358635)
@@ -99,16 +99,15 @@ __FBSDID("$FreeBSD$");
 #define	DWMMC_ERR_FLAGS		(DWMMC_DATA_ERR_FLAGS | DWMMC_CMD_ERR_FLAGS \
 				|SDMMC_INTMASK_HLE)
 
-#define	DES0_DIC	(1 << 1)
-#define	DES0_LD		(1 << 2)
-#define	DES0_FS		(1 << 3)
-#define	DES0_CH		(1 << 4)
-#define	DES0_ER		(1 << 5)
-#define	DES0_CES	(1 << 30)
-#define	DES0_OWN	(1 << 31)
+#define	DES0_DIC	(1 << 1)	/* Disable Interrupt on Completion */
+#define	DES0_LD		(1 << 2)	/* Last Descriptor */
+#define	DES0_FS		(1 << 3)	/* First Descriptor */
+#define	DES0_CH		(1 << 4)	/* second address CHained */
+#define	DES0_ER		(1 << 5)	/* End of Ring */
+#define	DES0_CES	(1 << 30)	/* Card Error Summary */
+#define	DES0_OWN	(1 << 31)	/* OWN */
 
-#define	DES1_BS1_MASK	0xfff
-#define	DES1_BS1_SHIFT	0
+#define	DES1_BS1_MASK	0x1fff
 
 struct idmac_desc {
 	uint32_t	des0;	/* control */
@@ -117,9 +116,10 @@ struct idmac_desc {
 	uint32_t	des3;	/* buf2 phys addr or next descr */
 };
 
-#define	DESC_MAX	256
-#define	DESC_SIZE	(sizeof(struct idmac_desc) * DESC_MAX)
+#define	IDMAC_DESC_SEGS	(PAGE_SIZE / (sizeof(struct idmac_desc)))
+#define	IDMAC_DESC_SIZE	(sizeof(struct idmac_desc) * IDMAC_DESC_SEGS)
 #define	DEF_MSIZE	0x2	/* Burst size of multiple transaction */
+#define	IDMAC_MAX_SIZE	4096
 
 static void dwmmc_next_operation(struct dwmmc_softc *);
 static int dwmmc_setup_bus(struct dwmmc_softc *, int);
@@ -162,7 +162,7 @@ dwmmc_ring_setup(void *arg, bus_dma_segment_t *segs, i
 
 	for (idx = 0; idx < nsegs; idx++) {
 		sc->desc_ring[idx].des0 = (DES0_OWN | DES0_DIC | DES0_CH);
-		sc->desc_ring[idx].des1 = segs[idx].ds_len;
+		sc->desc_ring[idx].des1 = segs[idx].ds_len & DES1_BS1_MASK;
 		sc->desc_ring[idx].des2 = segs[idx].ds_addr;
 
 		if (idx == 0)
@@ -213,8 +213,8 @@ dma_setup(struct dwmmc_softc *sc)
 	    BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
 	    BUS_SPACE_MAXADDR,		/* highaddr */
 	    NULL, NULL,			/* filter, filterarg */
-	    DESC_SIZE, 1, 		/* maxsize, nsegments */
-	    DESC_SIZE,			/* maxsegsize */
+	    IDMAC_DESC_SIZE, 1,		/* maxsize, nsegments */
+	    IDMAC_DESC_SIZE,		/* maxsegsize */
 	    0,				/* flags */
 	    NULL, NULL,			/* lockfunc, lockarg */
 	    &sc->desc_tag);
@@ -234,7 +234,7 @@ dma_setup(struct dwmmc_softc *sc)
 	}
 
 	error = bus_dmamap_load(sc->desc_tag, sc->desc_map,
-	    sc->desc_ring, DESC_SIZE, dwmmc_get1paddr,
+	    sc->desc_ring, IDMAC_DESC_SIZE, dwmmc_get1paddr,
 	    &sc->desc_ring_paddr, 0);
 	if (error != 0) {
 		device_printf(sc->dev,
@@ -242,23 +242,25 @@ dma_setup(struct dwmmc_softc *sc)
 		return (1);
 	}
 
-	for (idx = 0; idx < sc->desc_count; idx++) {
+	for (idx = 0; idx < IDMAC_DESC_SEGS; idx++) {
 		sc->desc_ring[idx].des0 = DES0_CH;
 		sc->desc_ring[idx].des1 = 0;
-		nidx = (idx + 1) % sc->desc_count;
+		nidx = (idx + 1) % IDMAC_DESC_SEGS;
 		sc->desc_ring[idx].des3 = sc->desc_ring_paddr + \
 		    (nidx * sizeof(struct idmac_desc));
 	}
+	sc->desc_ring[idx - 1].des3 = sc->desc_ring_paddr;
+	sc->desc_ring[idx - 1].des0 |= DES0_ER;
 
 	error = bus_dma_tag_create(
 	    bus_get_dma_tag(sc->dev),	/* Parent tag. */
-	    4096, 0,			/* alignment, boundary */
+	    CACHE_LINE_SIZE, 0,		/* alignment, boundary */
 	    BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
 	    BUS_SPACE_MAXADDR,		/* highaddr */
 	    NULL, NULL,			/* filter, filterarg */
-	    sc->desc_count * MMC_SECTOR_SIZE, /* maxsize */
-	    sc->desc_count,		/* nsegments */
-	    MMC_SECTOR_SIZE,		/* maxsegsize */
+	    IDMAC_MAX_SIZE * IDMAC_DESC_SEGS,	/* maxsize */
+	    IDMAC_DESC_SEGS,		/* nsegments */
+	    IDMAC_MAX_SIZE,		/* maxsegsize */
 	    0,				/* flags */
 	    NULL, NULL,			/* lockfunc, lockarg */
 	    &sc->buf_tag);
@@ -664,9 +666,6 @@ dwmmc_attach(device_t dev)
 	device_printf(dev, "Hardware version ID is %04x\n",
 		READ4(sc, SDMMC_VERID) & 0xffff);
 
-	if (sc->desc_count == 0)
-		sc->desc_count = DESC_MAX;
-
 	/* XXX: we support operation for slot index 0 only */
 	slot = 0;
 	if (sc->pwren_inverted) {
@@ -1278,7 +1277,7 @@ dwmmc_read_ivar(device_t bus, device_t child, int whic
 		*(int *)result = sc->host.caps;
 		break;
 	case MMCBR_IVAR_MAX_DATA:
-		*(int *)result = sc->desc_count - 1;
+		*(int *)result = (IDMAC_MAX_SIZE * IDMAC_DESC_SEGS) / MMC_SECTOR_SIZE;
 		break;
 	case MMCBR_IVAR_TIMING:
 		*(int *)result = sc->host.ios.timing;

Modified: head/sys/dev/mmc/host/dwmmc_hisi.c
==============================================================================
--- head/sys/dev/mmc/host/dwmmc_hisi.c	Wed Mar  4 19:52:34 2020	(r358634)
+++ head/sys/dev/mmc/host/dwmmc_hisi.c	Wed Mar  4 20:01:03 2020	(r358635)
@@ -79,7 +79,6 @@ hisi_dwmmc_attach(device_t dev)
 	 * DMA when the controller is not cache-coherent on arm64.
 	 */
 	sc->use_pio = 1;
-	sc->desc_count = 1;
 
 	return (dwmmc_attach(dev));
 }

Modified: head/sys/dev/mmc/host/dwmmc_var.h
==============================================================================
--- head/sys/dev/mmc/host/dwmmc_var.h	Wed Mar  4 19:52:34 2020	(r358634)
+++ head/sys/dev/mmc/host/dwmmc_var.h	Wed Mar  4 20:01:03 2020	(r358635)
@@ -60,7 +60,6 @@ struct dwmmc_softc {
 	uint32_t		use_auto_stop;
 	uint32_t		use_pio;
 	uint32_t		pwren_inverted;
-	u_int			desc_count;
 	device_t		child;
 	struct task		card_task;	/* Card presence check task */
 	struct timeout_task	card_delayed_task;/* Card insert delayed task */


More information about the svn-src-head mailing list