svn commit: r277413 - in head/sys: arm/conf arm/rockchip boot/fdt/dts/arm dev/mmc/host

Ganbold Tsagaankhuu ganbold at FreeBSD.org
Tue Jan 20 09:07:32 UTC 2015


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 at 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 at 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 at 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 at 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 */


More information about the svn-src-all mailing list