Author: ganbold
Date: Tue Jan 20 09:07:28 2015
New Revision: 277413
URL: https://svnweb.freebsd.org/changeset/base/277413

Log:
  Enable Synopsys DesignWare Mobile Storage Host Controller
  driver on Rockchip boards. It currently supports PIO mode
  and dma mode needs external dma controller to be used.
  
  Submitted by:   jmcneill
  Approved by:    stas (mentor)

Modified:
  head/sys/arm/conf/RK3188
  head/sys/arm/rockchip/files.rk30xx
  head/sys/boot/fdt/dts/arm/rk3188-radxa-lite.dts
  head/sys/boot/fdt/dts/arm/rk3188-radxa.dts
  head/sys/boot/fdt/dts/arm/rk3188.dtsi
  head/sys/dev/mmc/host/dwmmc.c
  head/sys/dev/mmc/host/dwmmc.h

Modified: head/sys/arm/conf/RK3188
==============================================================================
--- head/sys/arm/conf/RK3188    Tue Jan 20 05:44:21 2015        (r277412)
+++ head/sys/arm/conf/RK3188    Tue Jan 20 09:07:28 2015        (r277413)
@@ -76,8 +76,9 @@ options       DIAGNOSTIC
 options        ROOTDEVNAME=\"ufs:/dev/da0s2\"
 
 # MMC/SD/SDIO Card slot support
-#device                mmc                     # mmc/sd bus
-#device                mmcsd                   # mmc/sd flash cards
+device         mmc                     # mmc/sd bus
+device         mmcsd                   # mmc/sd flash cards
+device         dwmmc
 
 # Console and misc
 device         uart

Modified: head/sys/arm/rockchip/files.rk30xx
==============================================================================
--- head/sys/arm/rockchip/files.rk30xx  Tue Jan 20 05:44:21 2015        
(r277412)
+++ head/sys/arm/rockchip/files.rk30xx  Tue Jan 20 09:07:28 2015        
(r277413)
@@ -19,3 +19,5 @@ arm/rockchip/rk30xx_grf.c             standard
 arm/rockchip/rk30xx_wdog.c             standard
 arm/rockchip/rk30xx_gpio.c             optional        gpio
 arm/rockchip/rk30xx_mp.c               optional        smp
+
+dev/mmc/host/dwmmc.c                   optional        dwmmc

Modified: head/sys/boot/fdt/dts/arm/rk3188-radxa-lite.dts
==============================================================================
--- head/sys/boot/fdt/dts/arm/rk3188-radxa-lite.dts     Tue Jan 20 05:44:21 
2015        (r277412)
+++ head/sys/boot/fdt/dts/arm/rk3188-radxa-lite.dts     Tue Jan 20 09:07:28 
2015        (r277413)
@@ -48,6 +48,10 @@
                        status = "okay";
                };
 
+               mmc@10214000 {
+                       status = "okay";
+               };
+
        };
 
        chosen {

Modified: head/sys/boot/fdt/dts/arm/rk3188-radxa.dts
==============================================================================
--- head/sys/boot/fdt/dts/arm/rk3188-radxa.dts  Tue Jan 20 05:44:21 2015        
(r277412)
+++ head/sys/boot/fdt/dts/arm/rk3188-radxa.dts  Tue Jan 20 09:07:28 2015        
(r277413)
@@ -48,6 +48,10 @@
                        status = "okay";
                };
 
+               mmc@10214000 {
+                       status = "okay";
+               };
+
        };
 
        chosen {

Modified: head/sys/boot/fdt/dts/arm/rk3188.dtsi
==============================================================================
--- head/sys/boot/fdt/dts/arm/rk3188.dtsi       Tue Jan 20 05:44:21 2015        
(r277412)
+++ head/sys/boot/fdt/dts/arm/rk3188.dtsi       Tue Jan 20 09:07:28 2015        
(r277413)
@@ -231,22 +231,26 @@
                };
 
                mmc@10214000 {
-                       compatible = "rockchip,rk30xx-mmc";
+                       compatible = "rockchip,rk2928-dw-mshc";
                        reg = <0x10214000 0x1000>;
                        interrupts = <55>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       clock-frequency = <24000000>;   /* TODO: verify freq */
+                       bus-frequency = <48000000>;     /* TODO: verify freq */
+                       fifo-depth = <0x40>;
+                       num-slots = <1>;
                        status = "disabled";
                };
 
                mmc@10218000 {
-                       compatible = "rockchip,rk30xx-mmc";
+                       compatible = "rockchip,rk2928-dw-mshc";
                        reg = <0x10218000 0x1000>;
                        interrupts = <56>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       clock-frequency = <24000000>;   /* TODO: verify freq */
+                       bus-frequency = <48000000>;     /* TODO: verify freq */
+                       fifo-depth = <0x40>;
+                       num-slots = <1>;
                        status = "disabled";
                };
        };

Modified: head/sys/dev/mmc/host/dwmmc.c
==============================================================================
--- head/sys/dev/mmc/host/dwmmc.c       Tue Jan 20 05:44:21 2015        
(r277412)
+++ head/sys/dev/mmc/host/dwmmc.c       Tue Jan 20 09:07:28 2015        
(r277413)
@@ -129,6 +129,8 @@ struct dwmmc_softc {
        uint32_t                flags;
        uint32_t                hwtype;
        uint32_t                use_auto_stop;
+       uint32_t                use_pio;
+       uint32_t                pwren_inverted;
 
        bus_dma_tag_t           desc_tag;
        bus_dmamap_t            desc_map;
@@ -152,6 +154,8 @@ static void dwmmc_next_operation(struct 
 static int dwmmc_setup_bus(struct dwmmc_softc *, int);
 static int dma_done(struct dwmmc_softc *, struct mmc_command *);
 static int dma_stop(struct dwmmc_softc *);
+static void pio_read(struct dwmmc_softc *, struct mmc_command *);
+static void pio_write(struct dwmmc_softc *, struct mmc_command *);
 
 static struct resource_spec dwmmc_spec[] = {
        { SYS_RES_MEMORY,       0,      RF_ACTIVE },
@@ -163,6 +167,7 @@ enum {
        HWTYPE_NONE,
        HWTYPE_ALTERA,
        HWTYPE_EXYNOS,
+       HWTYPE_ROCKCHIP,
 };
 
 #define        HWTYPE_MASK             (0x0000ffff)
@@ -171,6 +176,7 @@ enum {
 static struct ofw_compat_data compat_data[] = {
        {"altr,socfpga-dw-mshc",        HWTYPE_ALTERA},
        {"samsung,exynos5420-dw-mshc",  HWTYPE_EXYNOS},
+       {"rockchip,rk2928-dw-mshc",     HWTYPE_ROCKCHIP},
        {NULL,                          HWTYPE_NONE},
 };
 
@@ -395,8 +401,10 @@ dwmmc_intr(void *arg)
                        dprintf("data err 0x%08x cmd 0x%08x\n",
                                reg, cmd->opcode);
                        cmd->error = MMC_ERR_FAILED;
-                       dma_done(sc, cmd);
-                       dma_stop(sc);
+                       if (!sc->use_pio) {
+                               dma_done(sc, cmd);
+                               dma_stop(sc);
+                       }
                }
 
                if (reg & SDMMC_INTMASK_CMD_DONE) {
@@ -421,15 +429,24 @@ dwmmc_intr(void *arg)
                }
        }
 
-       /* Now handle DMA interrupts */
-       reg = READ4(sc, SDMMC_IDSTS);
-       if (reg) {
-               dprintf("dma intr 0x%08x\n", reg);
-               if (reg & (SDMMC_IDINTEN_TI | SDMMC_IDINTEN_RI)) {
-                       WRITE4(sc, SDMMC_IDSTS, (SDMMC_IDINTEN_TI |
-                                                SDMMC_IDINTEN_RI));
-                       WRITE4(sc, SDMMC_IDSTS, SDMMC_IDINTEN_NI);
-                       dma_done(sc, cmd);
+       if (sc->use_pio) {
+               if (reg & (SDMMC_INTMASK_RXDR|SDMMC_INTMASK_DTO)) {
+                       pio_read(sc, cmd);
+               }
+               if (reg & (SDMMC_INTMASK_TXDR|SDMMC_INTMASK_DTO)) {
+                       pio_write(sc, cmd);
+               }
+       } else {
+               /* Now handle DMA interrupts */
+               reg = READ4(sc, SDMMC_IDSTS);
+               if (reg) {
+                       dprintf("dma intr 0x%08x\n", reg);
+                       if (reg & (SDMMC_IDINTEN_TI | SDMMC_IDINTEN_RI)) {
+                               WRITE4(sc, SDMMC_IDSTS, (SDMMC_IDINTEN_TI |
+                                                        SDMMC_IDINTEN_RI));
+                               WRITE4(sc, SDMMC_IDSTS, SDMMC_IDINTEN_NI);
+                               dma_done(sc, cmd);
+                       }
                }
        }
 
@@ -560,17 +577,29 @@ dwmmc_attach(device_t dev)
        device_printf(dev, "Hardware version ID is %04x\n",
                READ4(sc, SDMMC_VERID) & 0xffff);
 
-       WRITE4(sc, EMMCP_MPSBEGIN0, 0);
-       WRITE4(sc, EMMCP_SEND0, 0);
-       WRITE4(sc, EMMCP_CTRL0, (MPSCTRL_SECURE_READ_BIT |
-                                MPSCTRL_SECURE_WRITE_BIT |
-                                MPSCTRL_NON_SECURE_READ_BIT |
-                                MPSCTRL_NON_SECURE_WRITE_BIT |
-                                MPSCTRL_VALID));
+       sc->use_pio = 0;
+       sc->pwren_inverted = 0;
+
+       if ((sc->hwtype & HWTYPE_MASK) == HWTYPE_ROCKCHIP) {
+               sc->use_pio = 1;
+               sc->pwren_inverted = 1;
+       } else {
+               WRITE4(sc, EMMCP_MPSBEGIN0, 0);
+               WRITE4(sc, EMMCP_SEND0, 0);
+               WRITE4(sc, EMMCP_CTRL0, (MPSCTRL_SECURE_READ_BIT |
+                                        MPSCTRL_SECURE_WRITE_BIT |
+                                        MPSCTRL_NON_SECURE_READ_BIT |
+                                        MPSCTRL_NON_SECURE_WRITE_BIT |
+                                        MPSCTRL_VALID));
+       }
 
        /* XXX: we support operation for slot index 0 only */
        slot = 0;
-       WRITE4(sc, SDMMC_PWREN, (1 << slot));
+       if (sc->pwren_inverted) {
+               WRITE4(sc, SDMMC_PWREN, (0 << slot));
+       } else {
+               WRITE4(sc, SDMMC_PWREN, (1 << slot));
+       }
 
        /* Reset all */
        if (dwmmc_ctrl_reset(sc, (SDMMC_CTRL_RESET |
@@ -580,17 +609,19 @@ dwmmc_attach(device_t dev)
 
        dwmmc_setup_bus(sc, sc->host.f_min);
 
-       if (dma_setup(sc))
-               return (ENXIO);
-
-       /* Install desc base */
-       WRITE4(sc, SDMMC_DBADDR, sc->desc_ring_paddr);
-
-       /* Enable DMA interrupts */
-       WRITE4(sc, SDMMC_IDSTS, SDMMC_IDINTEN_MASK);
-       WRITE4(sc, SDMMC_IDINTEN, (SDMMC_IDINTEN_NI |
-                                  SDMMC_IDINTEN_RI |
-                                  SDMMC_IDINTEN_TI));
+       if (!sc->use_pio) {
+               if (dma_setup(sc))
+                       return (ENXIO);
+
+               /* Install desc base */
+               WRITE4(sc, SDMMC_DBADDR, sc->desc_ring_paddr);
+
+               /* Enable DMA interrupts */
+               WRITE4(sc, SDMMC_IDSTS, SDMMC_IDINTEN_MASK);
+               WRITE4(sc, SDMMC_IDINTEN, (SDMMC_IDINTEN_NI |
+                                          SDMMC_IDINTEN_RI |
+                                          SDMMC_IDINTEN_TI));
+       }
 
        /* Clear and disable interrups for a while */
        WRITE4(sc, SDMMC_RINTSTS, 0xffffffff);
@@ -797,6 +828,79 @@ dma_prepare(struct dwmmc_softc *sc, stru
        return (0);
 }
 
+static int
+pio_prepare(struct dwmmc_softc *sc, struct mmc_command *cmd)
+{
+       struct mmc_data *data;
+       int reg;
+
+       data = cmd->data;
+       data->xfer_len = 0;
+
+       reg = (DEF_MSIZE << SDMMC_FIFOTH_MSIZE_S);
+       reg |= ((sc->fifo_depth / 2) - 1) << SDMMC_FIFOTH_RXWMARK_S;
+       reg |= (sc->fifo_depth / 2) << SDMMC_FIFOTH_TXWMARK_S;
+
+       WRITE4(sc, SDMMC_FIFOTH, reg);
+       wmb();
+
+       return (0);
+}
+
+static void
+pio_read(struct dwmmc_softc *sc, struct mmc_command *cmd)
+{
+       struct mmc_data *data;
+       uint32_t *p, status;
+
+       if (cmd == NULL || cmd->data == NULL)
+               return;
+
+       data = cmd->data;
+       if ((data->flags & MMC_DATA_READ) == 0)
+               return;
+
+       KASSERT((data->xfer_len & 3) == 0, ("xfer_len not aligned"));
+       p = (uint32_t *)data->data + (data->xfer_len >> 2);
+
+       while (data->xfer_len < data->len) {
+               status = READ4(sc, SDMMC_STATUS);
+               if (status & SDMMC_STATUS_FIFO_EMPTY)
+                       break;
+               *p++ = READ4(sc, SDMMC_DATA);
+               data->xfer_len += 4;
+       }
+
+       WRITE4(sc, SDMMC_RINTSTS, SDMMC_INTMASK_RXDR);
+}
+
+static void
+pio_write(struct dwmmc_softc *sc, struct mmc_command *cmd)
+{
+       struct mmc_data *data;
+       uint32_t *p, status;
+
+       if (cmd == NULL || cmd->data == NULL)
+               return;
+
+       data = cmd->data;
+       if ((data->flags & MMC_DATA_WRITE) == 0)
+               return;
+
+       KASSERT((data->xfer_len & 3) == 0, ("xfer_len not aligned"));
+       p = (uint32_t *)data->data + (data->xfer_len >> 2);
+
+       while (data->xfer_len < data->len) {
+               status = READ4(sc, SDMMC_STATUS);
+               if (status & SDMMC_STATUS_FIFO_FULL)
+                       break;
+               WRITE4(sc, SDMMC_DATA, *p++);
+               data->xfer_len += 4;
+       }
+
+       WRITE4(sc, SDMMC_RINTSTS, SDMMC_INTMASK_TXDR);
+}
+
 static void
 dwmmc_start_cmd(struct dwmmc_softc *sc, struct mmc_command *cmd)
 {
@@ -807,6 +911,9 @@ dwmmc_start_cmd(struct dwmmc_softc *sc, 
        sc->curcmd = cmd;
        data = cmd->data;
 
+       if ((sc->hwtype & HWTYPE_MASK) == HWTYPE_ROCKCHIP)
+               dwmmc_setup_bus(sc, sc->host.ios.clock);
+
        /* XXX Upper layers don't always set this */
        cmd->mrq = sc->req;
 
@@ -861,7 +968,11 @@ dwmmc_start_cmd(struct dwmmc_softc *sc, 
                         data->len : MMC_SECTOR_SIZE;
                WRITE4(sc, SDMMC_BLKSIZ, blksz);
 
-               dma_prepare(sc, cmd);
+               if (sc->use_pio) {
+                       pio_prepare(sc, cmd);
+               } else {
+                       dma_prepare(sc, cmd);
+               }
                wmb();
        }
 

Modified: head/sys/dev/mmc/host/dwmmc.h
==============================================================================
--- head/sys/dev/mmc/host/dwmmc.h       Tue Jan 20 05:44:21 2015        
(r277412)
+++ head/sys/dev/mmc/host/dwmmc.h       Tue Jan 20 09:07:28 2015        
(r277413)
@@ -91,6 +91,8 @@
 #define        SDMMC_RINTSTS           0x44    /* Raw Interrupt Status 
Register */
 #define        SDMMC_STATUS            0x48    /* Status Register */
 #define         SDMMC_STATUS_DATA_BUSY (1 << 9) /* card_data[0] */
+#define         SDMMC_STATUS_FIFO_FULL (1 << 3) /* FIFO full */
+#define         SDMMC_STATUS_FIFO_EMPTY (1 << 2) /* FIFO empty */
 #define        SDMMC_FIFOTH            0x4C    /* FIFO Threshold Watermark 
Register */
 #define         SDMMC_FIFOTH_MSIZE_S   28      /* Burst size of multiple 
transaction */
 #define         SDMMC_FIFOTH_RXWMARK_S 16      /* FIFO threshold watermark 
level */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to