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