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 */
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to