All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2 0/3] UniPhier SD/eMMC controller driver
@ 2016-02-10 13:28 Masahiro Yamada
  2016-02-10 13:28 ` [U-Boot] [PATCH v2 1/3] mmc: uniphier: add driver for UniPhier SD/MMC host controller Masahiro Yamada
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Masahiro Yamada @ 2016-02-10 13:28 UTC (permalink / raw)
  To: u-boot

Masahiro Yamada (3):
  mmc: uniphier: add driver for UniPhier SD/MMC host controller
  ARM: uniphier: enable UniPhier SD/MMC host driver
  ARM: dts: uniphier: add SD/MMC host controller nodes

 arch/arm/Kconfig                             |   1 +
 arch/arm/dts/uniphier-ph1-ld4-ref.dts        |   4 +
 arch/arm/dts/uniphier-ph1-ld4.dtsi           |  25 +
 arch/arm/dts/uniphier-ph1-ld6b-ref.dts       |   4 +
 arch/arm/dts/uniphier-ph1-pro4-ref.dts       |   8 +
 arch/arm/dts/uniphier-ph1-pro4.dtsi          |  37 ++
 arch/arm/dts/uniphier-ph1-pro5-4kbox.dts     |   8 +
 arch/arm/dts/uniphier-ph1-pro5.dtsi          |  24 +
 arch/arm/dts/uniphier-ph1-sld3-ref.dts       |   4 +
 arch/arm/dts/uniphier-ph1-sld3.dtsi          |  19 +
 arch/arm/dts/uniphier-ph1-sld8-ref.dts       |   4 +
 arch/arm/dts/uniphier-ph1-sld8.dtsi          |  25 +
 arch/arm/dts/uniphier-pinctrl.dtsi           |  15 +
 arch/arm/dts/uniphier-proxstream2-gentil.dts |   4 +
 arch/arm/dts/uniphier-proxstream2-vodka.dts  |   4 +
 arch/arm/dts/uniphier-proxstream2.dtsi       |  24 +
 configs/uniphier_ld4_sld8_defconfig          |   1 +
 configs/uniphier_pro4_defconfig              |   1 +
 configs/uniphier_pro5_defconfig              |   1 +
 configs/uniphier_pxs2_ld6b_defconfig         |   1 +
 configs/uniphier_sld3_defconfig              |   1 +
 doc/README.uniphier                          |   1 +
 drivers/mmc/Kconfig                          |   6 +
 drivers/mmc/Makefile                         |   1 +
 drivers/mmc/uniphier-sd.c                    | 721 +++++++++++++++++++++++++++
 include/configs/uniphier.h                   |   4 +
 26 files changed, 948 insertions(+)
 create mode 100644 drivers/mmc/uniphier-sd.c

-- 
1.9.1

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [U-Boot] [PATCH v2 1/3] mmc: uniphier: add driver for UniPhier SD/MMC host controller
  2016-02-10 13:28 [U-Boot] [PATCH v2 0/3] UniPhier SD/eMMC controller driver Masahiro Yamada
@ 2016-02-10 13:28 ` Masahiro Yamada
  2016-02-10 13:45   ` Marek Vasut
  2016-02-10 13:28 ` [U-Boot] [PATCH v2 2/3] ARM: uniphier: enable UniPhier SD/MMC host driver Masahiro Yamada
  2016-02-10 13:28 ` [U-Boot] [PATCH v2 3/3] ARM: dts: uniphier: add SD/MMC host controller nodes Masahiro Yamada
  2 siblings, 1 reply; 7+ messages in thread
From: Masahiro Yamada @ 2016-02-10 13:28 UTC (permalink / raw)
  To: u-boot

Add a driver for the on-chip SD/eMMC host controller used by
UniPhier SoC family.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---

Changes in v2:
  - Fix the divisor bug on the older IP (on PH1-LD4, PH1-sLD8, PH1-Pro4)
  - Increase time out because "mmc erase" can sometimes take long
  - Move HOST_MODE register setting to uniphier_sd_init()
    because this register does not need setting multipule times.

 doc/README.uniphier       |   1 +
 drivers/mmc/Kconfig       |   6 +
 drivers/mmc/Makefile      |   1 +
 drivers/mmc/uniphier-sd.c | 721 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 729 insertions(+)
 create mode 100644 drivers/mmc/uniphier-sd.c

diff --git a/doc/README.uniphier b/doc/README.uniphier
index bcf0ac3..7cfff97 100644
--- a/doc/README.uniphier
+++ b/doc/README.uniphier
@@ -93,6 +93,7 @@ Supported devices
 
  - UART (on-chip)
  - NAND
+ - SD/eMMC
  - USB 2.0 (EHCI)
  - USB 3.0 (xHCI)
  - LAN (on-board SMSC9118)
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 9f4b766..faffefd 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -37,4 +37,10 @@ config PIC32_SDHCI
 	help
 	  Support for Microchip PIC32 SDHCI controller.
 
+config MMC_UNIPHIER
+	bool "UniPhier SD/MMC Host Controller support"
+	depends on ARCH_UNIPHIER
+	help
+	  This selects support for the SD/MMC Host Controller on UniPhier SoCs.
+
 endmenu
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index c9c3e3e..b85e4bf 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_SH_SDHI) += sh_sdhi.o
 obj-$(CONFIG_SOCFPGA_DWMMC) += socfpga_dw_mmc.o
 obj-$(CONFIG_SPEAR_SDHCI) += spear_sdhci.o
 obj-$(CONFIG_TEGRA_MMC) += tegra_mmc.o
+obj-$(CONFIG_MMC_UNIPHIER) += uniphier-sd.o
 obj-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o
 
 ifdef CONFIG_SPL_BUILD
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c
new file mode 100644
index 0000000..2974c68
--- /dev/null
+++ b/drivers/mmc/uniphier-sd.c
@@ -0,0 +1,721 @@
+/*
+ * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <fdtdec.h>
+#include <mapmem.h>
+#include <mmc.h>
+#include <dm/device.h>
+#include <linux/compat.h>
+#include <linux/io.h>
+#include <asm/unaligned.h>
+#include <asm/dma-mapping.h>
+
+#define pr_err   printf
+#define pr_warn  printf
+#ifdef DEBUG
+#define pr_debug printf
+#else
+#define pr_debug(...)
+#endif
+DECLARE_GLOBAL_DATA_PTR;
+
+#define UNIPHIER_SD_CMD			0x000	/* command */
+#define   UNIPHIER_SD_CMD_NOSTOP	BIT(14)	/* No automatic CMD12 issue */
+#define   UNIPHIER_SD_CMD_MULTI		BIT(13)	/* multiple block transfer */
+#define   UNIPHIER_SD_CMD_RD		BIT(12)	/* 1: read, 0: write */
+#define   UNIPHIER_SD_CMD_DATA		BIT(11)	/* data transfer */
+#define   UNIPHIER_SD_CMD_APP		BIT(6)	/* ACMD preceded by CMD55 */
+#define   UNIPHIER_SD_CMD_NORMAL	(0 << 8)/* auto-detect of resp-type */
+#define   UNIPHIER_SD_CMD_RSP_NONE	(3 << 8)/* response: none */
+#define   UNIPHIER_SD_CMD_RSP_R1	(4 << 8)/* response: R1, R5, R6, R7 */
+#define   UNIPHIER_SD_CMD_RSP_R1B	(5 << 8)/* response: R1b, R5b */
+#define   UNIPHIER_SD_CMD_RSP_R2	(6 << 8)/* response: R2 */
+#define   UNIPHIER_SD_CMD_RSP_R3	(7 << 8)/* response: R3, R4 */
+#define UNIPHIER_SD_ARG			0x008	/* command argument */
+#define UNIPHIER_SD_STOP		0x010	/* stop action control */
+#define   UNIPHIER_SD_STOP_SEC		BIT(8)	/* use sector count */
+#define   UNIPHIER_SD_STOP_STP		BIT(0)	/* issue CMD12 */
+#define UNIPHIER_SD_SECCNT		0x014	/* sector counter */
+#define UNIPHIER_SD_RSP10		0x018	/* response[39:8] */
+#define UNIPHIER_SD_RSP32		0x020	/* response[71:40] */
+#define UNIPHIER_SD_RSP54		0x028	/* response[103:72] */
+#define UNIPHIER_SD_RSP76		0x030	/* response[127:104] */
+#define UNIPHIER_SD_INFO1		0x038	/* IRQ status 1 */
+#define   UNIPHIER_SD_INFO1_CD		BIT(5)	/* state of card detect */
+#define   UNIPHIER_SD_INFO1_INSERT	BIT(4)	/* card inserted */
+#define   UNIPHIER_SD_INFO1_REMOVE	BIT(3)	/* card removed */
+#define   UNIPHIER_SD_INFO1_CMP		BIT(2)	/* data complete */
+#define   UNIPHIER_SD_INFO1_RSP		BIT(0)	/* response complete */
+#define UNIPHIER_SD_INFO2		0x03c	/* IRQ status 2 */
+#define   UNIPHIER_SD_INFO2_ERR_ILA	BIT(15)	/* illegal access err */
+#define   UNIPHIER_SD_INFO2_CBSY	BIT(14)	/* command busy */
+#define   UNIPHIER_SD_INFO2_BWE		BIT(9)	/* write buffer ready */
+#define   UNIPHIER_SD_INFO2_BRE		BIT(8)	/* read buffer ready */
+#define   UNIPHIER_SD_INFO2_DAT0	BIT(7)	/* SDDAT0 */
+#define   UNIPHIER_SD_INFO2_ERR_RTO	BIT(6)	/* response time out */
+#define   UNIPHIER_SD_INFO2_ERR_ILR	BIT(5)	/* illegal read err */
+#define   UNIPHIER_SD_INFO2_ERR_ILW	BIT(4)	/* illegal write err */
+#define   UNIPHIER_SD_INFO2_ERR_TO	BIT(3)	/* time out error */
+#define   UNIPHIER_SD_INFO2_ERR_END	BIT(2)	/* END bit error */
+#define   UNIPHIER_SD_INFO2_ERR_CRC	BIT(1)	/* CRC error */
+#define   UNIPHIER_SD_INFO2_ERR_IDX	BIT(0)	/* cmd index error */
+#define UNIPHIER_SD_INFO1_MASK		0x040
+#define UNIPHIER_SD_INFO2_MASK		0x044
+#define UNIPHIER_SD_CLKCTL		0x048	/* clock divisor */
+#define   UNIPHIER_SD_CLKCTL_DIV_MASK	0x104ff
+#define   UNIPHIER_SD_CLKCTL_DIV1024	BIT(16)	/* SDCLK = CLK / 1024 */
+#define   UNIPHIER_SD_CLKCTL_DIV512	BIT(7)	/* SDCLK = CLK / 512 */
+#define   UNIPHIER_SD_CLKCTL_DIV256	BIT(6)	/* SDCLK = CLK / 256 */
+#define   UNIPHIER_SD_CLKCTL_DIV128	BIT(5)	/* SDCLK = CLK / 128 */
+#define   UNIPHIER_SD_CLKCTL_DIV64	BIT(4)	/* SDCLK = CLK / 64 */
+#define   UNIPHIER_SD_CLKCTL_DIV32	BIT(3)	/* SDCLK = CLK / 32 */
+#define   UNIPHIER_SD_CLKCTL_DIV16	BIT(2)	/* SDCLK = CLK / 16 */
+#define   UNIPHIER_SD_CLKCTL_DIV8	BIT(1)	/* SDCLK = CLK / 8 */
+#define   UNIPHIER_SD_CLKCTL_DIV4	BIT(0)	/* SDCLK = CLK / 4 */
+#define   UNIPHIER_SD_CLKCTL_DIV2	0	/* SDCLK = CLK / 2 */
+#define   UNIPHIER_SD_CLKCTL_DIV1	BIT(10)	/* SDCLK = CLK */
+#define   UNIPHIER_SD_CLKCTL_OFFEN	BIT(9)	/* stop SDCLK when unused */
+#define   UNIPHIER_SD_CLKCTL_SCLKEN	BIT(8)	/* SDCLK output enable */
+#define UNIPHIER_SD_SIZE		0x04c	/* block size */
+#define UNIPHIER_SD_OPTION		0x050
+#define   UNIPHIER_SD_OPTION_WIDTH_MASK	(5 << 13)
+#define   UNIPHIER_SD_OPTION_WIDTH_1	(4 << 13)
+#define   UNIPHIER_SD_OPTION_WIDTH_4	(0 << 13)
+#define   UNIPHIER_SD_OPTION_WIDTH_8	(1 << 13)
+#define UNIPHIER_SD_BUF			0x060	/* read/write buffer */
+#define UNIPHIER_SD_EXTMODE		0x1b0
+#define   UNIPHIER_SD_EXTMODE_DMA_EN	BIT(1)	/* transfer 1: DMA, 0: pio */
+#define UNIPHIER_SD_SOFT_RST		0x1c0
+#define UNIPHIER_SD_SOFT_RST_RSTX	BIT(0)	/* reset deassert */
+#define UNIPHIER_SD_VERSION		0x1c4	/* version register */
+#define UNIPHIER_SD_VERSION_IP		0xff	/* IP version */
+#define UNIPHIER_SD_HOST_MODE		0x1c8
+#define UNIPHIER_SD_IF_MODE		0x1cc
+#define   UNIPHIER_SD_IF_MODE_DDR	BIT(0)	/* DDR mode */
+#define UNIPHIER_SD_VOLT		0x1e4	/* voltage switch */
+#define   UNIPHIER_SD_VOLT_MASK		(3 << 0)
+#define   UNIPHIER_SD_VOLT_OFF		(0 << 0)
+#define   UNIPHIER_SD_VOLT_330		(1 << 0)/* 3.3V signal */
+#define   UNIPHIER_SD_VOLT_180		(2 << 0)/* 1.8V signal */
+#define UNIPHIER_SD_DMA_MODE		0x410
+#define   UNIPHIER_SD_DMA_MODE_DIR_RD	BIT(16)	/* 1: from device, 0: to dev */
+#define   UNIPHIER_SD_DMA_MODE_ADDR_INC	BIT(0)	/* 1: address inc, 0: fixed */
+#define UNIPHIER_SD_DMA_CTL		0x414
+#define   UNIPHIER_SD_DMA_CTL_START	BIT(0)	/* start DMA (auto cleared) */
+#define UNIPHIER_SD_DMA_RST		0x418
+#define   UNIPHIER_SD_DMA_RST_RD	BIT(9)
+#define   UNIPHIER_SD_DMA_RST_WR	BIT(8)
+#define UNIPHIER_SD_DMA_INFO1		0x420
+#define   UNIPHIER_SD_DMA_INFO1_END_RD2	BIT(20)	/* DMA from device is complete*/
+#define   UNIPHIER_SD_DMA_INFO1_END_RD	BIT(17)	/* Don't use!  Hardware bug */
+#define   UNIPHIER_SD_DMA_INFO1_END_WR	BIT(16)	/* DMA to device is complete */
+#define UNIPHIER_SD_DMA_INFO1_MASK	0x424
+#define UNIPHIER_SD_DMA_INFO2		0x428
+#define   UNIPHIER_SD_DMA_INFO2_ERR_RD	BIT(17)
+#define   UNIPHIER_SD_DMA_INFO2_ERR_WR	BIT(16)
+#define UNIPHIER_SD_DMA_INFO2_MASK	0x42c
+#define UNIPHIER_SD_DMA_ADDR_L		0x440
+#define UNIPHIER_SD_DMA_ADDR_H		0x444
+
+/* alignment required by the DMA engine of this controller */
+#define UNIPHIER_SD_DMA_MINALIGN	0x10
+
+struct uniphier_sd_priv {
+	struct mmc_config cfg;
+	struct mmc *mmc;
+	void __iomem *regbase;
+	unsigned long mclk;
+	unsigned int version;
+	u32 caps;
+#define UNIPHIER_SD_CAP_NONREMOVABLE	BIT(0)	/* Nonremovable e.g. eMMC */
+#define UNIPHIER_SD_CAP_DMA_INTERNAL	BIT(1)	/* have internal DMA engine */
+#define UNIPHIER_SD_CAP_DIV1024		BIT(2)	/* divisor 1024 is available */
+};
+
+static dma_addr_t __dma_map_single(void *ptr, size_t size,
+				   enum dma_data_direction dir)
+{
+	unsigned long addr = (unsigned long)ptr;
+
+	if (dir == DMA_FROM_DEVICE)
+		invalidate_dcache_range(addr, addr + size);
+	else
+		flush_dcache_range(addr, addr + size);
+
+	return addr;
+}
+
+static void __dma_unmap_single(dma_addr_t addr, size_t size,
+			       enum dma_data_direction dir)
+{
+	if (dir != DMA_TO_DEVICE)
+		invalidate_dcache_range(addr, addr + size);
+}
+
+static int uniphier_sd_check_error(struct uniphier_sd_priv *priv)
+{
+	u32 info2 = readl(priv->regbase + UNIPHIER_SD_INFO2);
+
+	if (info2 & UNIPHIER_SD_INFO2_ERR_RTO) {
+		/*
+		 * TIMEOUT must be returned for unsupported command.  Do not
+		 * display error log since this might be a part of sequence to
+		 * distinguish between SD and MMC.
+		 */
+		return TIMEOUT;
+	}
+
+	if (info2 & UNIPHIER_SD_INFO2_ERR_TO) {
+		pr_err("timeout error\n");
+		return -ETIMEDOUT;
+	}
+
+	if (info2 & (UNIPHIER_SD_INFO2_ERR_END | UNIPHIER_SD_INFO2_ERR_CRC |
+		     UNIPHIER_SD_INFO2_ERR_IDX)) {
+		pr_err("communication out of sync\n");
+		return -EILSEQ;
+	}
+
+	if (info2 & (UNIPHIER_SD_INFO2_ERR_ILA | UNIPHIER_SD_INFO2_ERR_ILR |
+		     UNIPHIER_SD_INFO2_ERR_ILW)) {
+		pr_err("illegal access\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int uniphier_sd_wait_irq(struct uniphier_sd_priv *priv,
+				unsigned int reg, u32 flag)
+{
+	long wait = 1000000;
+	int ret;
+
+	while (!(readl(priv->regbase + reg) & flag)) {
+		if (wait-- < 0) {
+			pr_err("timeout\n");
+			return -ETIMEDOUT;
+		}
+
+		ret = uniphier_sd_check_error(priv);
+		if (ret)
+			return ret;
+
+		udelay(1);
+	}
+
+	return 0;
+}
+
+static int uniphier_sd_pio_read_one_block(struct mmc *mmc, u32 **pbuf,
+					  uint blocksize)
+{
+	struct uniphier_sd_priv *priv = mmc->priv;
+	int i, ret;
+
+	/* wait until the buffer is filled with data */
+	ret = uniphier_sd_wait_irq(priv, UNIPHIER_SD_INFO2,
+				   UNIPHIER_SD_INFO2_BRE);
+	if (ret)
+		return ret;
+
+	/*
+	 * Clear the status flag _before_ read the buffer out because
+	 * UNIPHIER_SD_INFO2_BRE is edge-triggered, not level-triggered.
+	 */
+	writel(0, priv->regbase + UNIPHIER_SD_INFO2);
+
+	if (likely(IS_ALIGNED((unsigned long)*pbuf, 4))) {
+		for (i = 0; i < blocksize / 4; i++)
+			*(*pbuf)++ = readl(priv->regbase + UNIPHIER_SD_BUF);
+	} else {
+		for (i = 0; i < blocksize / 4; i++)
+			put_unaligned(readl(priv->regbase + UNIPHIER_SD_BUF),
+				      (*pbuf)++);
+	}
+
+	return 0;
+}
+
+static int uniphier_sd_pio_write_one_block(struct mmc *mmc, const u32 **pbuf,
+					   uint blocksize)
+{
+	struct uniphier_sd_priv *priv = mmc->priv;
+	int i, ret;
+
+	/* wait until the buffer becomes empty */
+	ret = uniphier_sd_wait_irq(priv, UNIPHIER_SD_INFO2,
+				   UNIPHIER_SD_INFO2_BWE);
+	if (ret)
+		return ret;
+
+	writel(0, priv->regbase + UNIPHIER_SD_INFO2);
+
+	if (likely(IS_ALIGNED((unsigned long)*pbuf, 4))) {
+		for (i = 0; i < blocksize / 4; i++)
+			writel(*(*pbuf)++, priv->regbase + UNIPHIER_SD_BUF);
+	} else {
+		for (i = 0; i < blocksize / 4; i++)
+			writel(get_unaligned((*pbuf)++),
+			       priv->regbase + UNIPHIER_SD_BUF);
+	}
+
+	return 0;
+}
+
+static int uniphier_sd_pio_xfer(struct mmc *mmc, struct mmc_data *data)
+{
+	u32 *dest = (u32 *)data->dest;
+	const u32 *src = (const u32 *)data->src;
+	int i, ret;
+
+	for (i = 0; i < data->blocks; i++) {
+		if (data->flags & MMC_DATA_READ)
+			ret = uniphier_sd_pio_read_one_block(mmc, &dest,
+							     data->blocksize);
+		else
+			ret = uniphier_sd_pio_write_one_block(mmc, &src,
+							      data->blocksize);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void uniphier_sd_dma_start(struct uniphier_sd_priv *priv,
+				  dma_addr_t dma_addr)
+{
+	u32 tmp;
+
+	writel(0, priv->regbase + UNIPHIER_SD_DMA_INFO1);
+	writel(0, priv->regbase + UNIPHIER_SD_DMA_INFO2);
+
+	/* enable DMA */
+	tmp = readl(priv->regbase + UNIPHIER_SD_EXTMODE);
+	tmp |= UNIPHIER_SD_EXTMODE_DMA_EN;
+	writel(tmp, priv->regbase + UNIPHIER_SD_EXTMODE);
+
+	writel(dma_addr & U32_MAX, priv->regbase + UNIPHIER_SD_DMA_ADDR_L);
+
+	/* suppress the warning "right shift count >= width of type" */
+	dma_addr >>= min_t(int, 32, 8 * sizeof(dma_addr));
+
+	writel(dma_addr & U32_MAX, priv->regbase + UNIPHIER_SD_DMA_ADDR_H);
+
+	writel(UNIPHIER_SD_DMA_CTL_START, priv->regbase + UNIPHIER_SD_DMA_CTL);
+}
+
+static int uniphier_sd_dma_wait_irq(struct uniphier_sd_priv *priv, u32 flag,
+				    unsigned int blocks)
+{
+	long wait = 1000000 + 10 * blocks;
+
+	while (!(readl(priv->regbase + UNIPHIER_SD_DMA_INFO1) & flag)) {
+		if (wait-- < 0) {
+			pr_err("timeout during DMA\n");
+			return -ETIMEDOUT;
+		}
+
+		udelay(10);
+	}
+
+	if (readl(priv->regbase + UNIPHIER_SD_DMA_INFO2)) {
+		pr_err("error during DMA\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int uniphier_sd_dma_xfer(struct mmc *mmc, struct mmc_data *data)
+{
+	struct uniphier_sd_priv *priv = mmc->priv;
+	size_t len = data->blocks * data->blocksize;
+	void *buf;
+	enum dma_data_direction dir;
+	dma_addr_t dma_addr;
+	u32 poll_flag, tmp;
+	int ret;
+
+	tmp = readl(priv->regbase + UNIPHIER_SD_DMA_MODE);
+
+	if (data->flags & MMC_DATA_READ) {
+		buf = data->dest;
+		dir = DMA_FROM_DEVICE;
+		poll_flag = UNIPHIER_SD_DMA_INFO1_END_RD2;
+		tmp |= UNIPHIER_SD_DMA_MODE_DIR_RD;
+	} else {
+		buf = (void *)data->src;
+		dir = DMA_TO_DEVICE;
+		poll_flag = UNIPHIER_SD_DMA_INFO1_END_WR;
+		tmp &= ~UNIPHIER_SD_DMA_MODE_DIR_RD;
+	}
+
+	writel(tmp, priv->regbase + UNIPHIER_SD_DMA_MODE);
+
+	dma_addr = __dma_map_single(buf, len, dir);
+
+	uniphier_sd_dma_start(priv, dma_addr);
+
+	ret = uniphier_sd_dma_wait_irq(priv, poll_flag, data->blocks);
+
+	__dma_unmap_single(dma_addr, len, dir);
+
+	return ret;
+}
+
+static int uniphier_sd_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+				struct mmc_data *data)
+{
+	struct uniphier_sd_priv *priv = mmc->priv;
+	int ret;
+	u32 tmp;
+
+	if (readl(priv->regbase + UNIPHIER_SD_INFO2) & UNIPHIER_SD_INFO2_CBSY) {
+		pr_err("command busy\n");
+		return -EBUSY;
+	}
+
+	/* clear all status flags */
+	writel(0, priv->regbase + UNIPHIER_SD_INFO1);
+	writel(0, priv->regbase + UNIPHIER_SD_INFO2);
+
+	/* disable DMA once */
+	tmp = readl(priv->regbase + UNIPHIER_SD_EXTMODE);
+	tmp &= ~UNIPHIER_SD_EXTMODE_DMA_EN;
+	writel(tmp, priv->regbase + UNIPHIER_SD_EXTMODE);
+
+	writel(cmd->cmdarg, priv->regbase + UNIPHIER_SD_ARG);
+
+	tmp = cmd->cmdidx;
+
+	if (data) {
+		writel(data->blocksize, priv->regbase + UNIPHIER_SD_SIZE);
+		writel(data->blocks, priv->regbase + UNIPHIER_SD_SECCNT);
+
+		/* Do not send CMD12 automatically */
+		tmp |= UNIPHIER_SD_CMD_NOSTOP | UNIPHIER_SD_CMD_DATA;
+
+		if (data->blocks > 1)
+			tmp |= UNIPHIER_SD_CMD_MULTI;
+
+		if (data->flags & MMC_DATA_READ)
+			tmp |= UNIPHIER_SD_CMD_RD;
+	}
+
+	/*
+	 * Do not use the response type auto-detection on this hardware.
+	 * CMD8, for example, has different response types on SD and eMMC,
+	 * while this controller always assumes the response type for SD.
+	 * Set the response type manually.
+	 */
+	switch (cmd->resp_type) {
+	case MMC_RSP_NONE:
+		tmp |= UNIPHIER_SD_CMD_RSP_NONE;
+		break;
+	case MMC_RSP_R1:
+		tmp |= UNIPHIER_SD_CMD_RSP_R1;
+		break;
+	case MMC_RSP_R1b:
+		tmp |= UNIPHIER_SD_CMD_RSP_R1B;
+		break;
+	case MMC_RSP_R2:
+		tmp |= UNIPHIER_SD_CMD_RSP_R2;
+		break;
+	case MMC_RSP_R3:
+		tmp |= UNIPHIER_SD_CMD_RSP_R3;
+		break;
+	default:
+		pr_err("unknown response type\n");
+		return -EINVAL;
+	}
+
+	pr_debug("sending CMD%d (SD_CMD=%08x, SD_ARG=%08x)\n",
+		 cmd->cmdidx, tmp, cmd->cmdarg);
+	writel(tmp, priv->regbase + UNIPHIER_SD_CMD);
+
+	ret = uniphier_sd_wait_irq(priv, UNIPHIER_SD_INFO1,
+				   UNIPHIER_SD_INFO1_RSP);
+	if (ret)
+		return ret;
+
+	if (cmd->resp_type & MMC_RSP_136) {
+		u32 rsp_127_104 = readl(priv->regbase + UNIPHIER_SD_RSP76);
+		u32 rsp_103_72 = readl(priv->regbase + UNIPHIER_SD_RSP54);
+		u32 rsp_71_40 = readl(priv->regbase + UNIPHIER_SD_RSP32);
+		u32 rsp_39_8 = readl(priv->regbase + UNIPHIER_SD_RSP10);
+
+		cmd->response[0] = (rsp_127_104 & 0xffffff) << 8 |
+							(rsp_103_72 & 0xff);
+		cmd->response[1] = (rsp_103_72  & 0xffffff) << 8 |
+							(rsp_71_40 & 0xff);
+		cmd->response[2] = (rsp_71_40   & 0xffffff) << 8 |
+							(rsp_39_8 & 0xff);
+		cmd->response[3] = (rsp_39_8    & 0xffffff) << 8;
+	} else {
+		/* bit 39-8 */
+		cmd->response[0] = readl(priv->regbase + UNIPHIER_SD_RSP10);
+	}
+
+	if (data) {
+		/* use DMA if the HW supports it and the buffer is aligned */
+		if ((priv->caps & UNIPHIER_SD_CAP_DMA_INTERNAL) &&
+		    IS_ALIGNED((long)data->src, UNIPHIER_SD_DMA_MINALIGN))
+			ret = uniphier_sd_dma_xfer(mmc, data);
+		else
+			ret = uniphier_sd_pio_xfer(mmc, data);
+
+		ret = uniphier_sd_wait_irq(priv, UNIPHIER_SD_INFO1,
+					   UNIPHIER_SD_INFO1_CMP);
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+
+static void uniphier_sd_set_bus_width(struct mmc *mmc)
+{
+	struct uniphier_sd_priv *priv = mmc->priv;
+	u32 val, tmp;
+
+	pr_debug("uniphier_sd: setting bus to %u bit\n", mmc->bus_width);
+
+	switch (mmc->bus_width) {
+	case 1:
+		val = UNIPHIER_SD_OPTION_WIDTH_1;
+		break;
+	case 4:
+		val = UNIPHIER_SD_OPTION_WIDTH_4;
+		break;
+	case 8:
+		val = UNIPHIER_SD_OPTION_WIDTH_8;
+		break;
+	default:
+		BUG();
+		break;
+	}
+
+	tmp = readl(priv->regbase + UNIPHIER_SD_OPTION);
+	tmp &= ~UNIPHIER_SD_OPTION_WIDTH_MASK;
+	tmp |= val;
+	writel(tmp, priv->regbase + UNIPHIER_SD_OPTION);
+}
+
+static void uniphier_sd_set_clk(struct mmc *mmc)
+{
+	struct uniphier_sd_priv *priv = mmc->priv;
+	unsigned int divisor;
+	u32 val, tmp;
+
+	if (!mmc->clock)
+		return;
+
+	pr_debug("uniphier_sd: setting clock to %u, DDR=%s\n",
+		 mmc->clock, mmc->ddr_mode ? "on" : "off");
+
+	divisor = DIV_ROUND_UP(priv->mclk, mmc->clock);
+
+	if (divisor <= 1)
+		val = UNIPHIER_SD_CLKCTL_DIV1;
+	else if (divisor <= 2)
+		val = UNIPHIER_SD_CLKCTL_DIV2;
+	else if (divisor <= 4)
+		val = UNIPHIER_SD_CLKCTL_DIV4;
+	else if (divisor <= 8)
+		val = UNIPHIER_SD_CLKCTL_DIV8;
+	else if (divisor <= 16)
+		val = UNIPHIER_SD_CLKCTL_DIV16;
+	else if (divisor <= 32)
+		val = UNIPHIER_SD_CLKCTL_DIV32;
+	else if (divisor <= 64)
+		val = UNIPHIER_SD_CLKCTL_DIV64;
+	else if (divisor <= 128)
+		val = UNIPHIER_SD_CLKCTL_DIV128;
+	else if (divisor <= 256)
+		val = UNIPHIER_SD_CLKCTL_DIV256;
+	else if (divisor <= 512 || !(priv->caps & UNIPHIER_SD_CAP_DIV1024))
+		val = UNIPHIER_SD_CLKCTL_DIV512;
+	else
+		val = UNIPHIER_SD_CLKCTL_DIV1024;
+
+	tmp = readl(priv->regbase + UNIPHIER_SD_CLKCTL);
+	tmp &= ~UNIPHIER_SD_CLKCTL_DIV_MASK;
+	tmp |= val | UNIPHIER_SD_CLKCTL_OFFEN | UNIPHIER_SD_CLKCTL_SCLKEN;
+	writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL);
+
+	tmp = readl(priv->regbase + UNIPHIER_SD_IF_MODE);
+	if (mmc->ddr_mode)
+		tmp |= UNIPHIER_SD_IF_MODE_DDR;
+	else
+		tmp &= ~UNIPHIER_SD_IF_MODE_DDR;
+	writel(tmp, priv->regbase + UNIPHIER_SD_IF_MODE);
+
+	udelay(1000);
+}
+
+static void uniphier_sd_set_ios(struct mmc *mmc)
+{
+	uniphier_sd_set_clk(mmc);
+	uniphier_sd_set_bus_width(mmc);
+}
+
+static int uniphier_sd_init(struct mmc *mmc)
+{
+	struct uniphier_sd_priv *priv = mmc->priv;
+	u32 tmp;
+
+	/* soft reset of the host */
+	tmp = readl(priv->regbase + UNIPHIER_SD_SOFT_RST);
+	tmp &= ~UNIPHIER_SD_SOFT_RST_RSTX;
+	writel(tmp, priv->regbase + UNIPHIER_SD_SOFT_RST);
+	tmp |= UNIPHIER_SD_SOFT_RST_RSTX;
+	writel(tmp, priv->regbase + UNIPHIER_SD_SOFT_RST);
+
+	/* FIXME: implement eMMC hw_reset */
+
+	writel(UNIPHIER_SD_STOP_SEC, priv->regbase + UNIPHIER_SD_STOP);
+
+	writel(priv->version >= 0x10 ? 0x00000101 : 0x00000000,
+	       priv->regbase + UNIPHIER_SD_HOST_MODE);
+
+	if (priv->caps & UNIPHIER_SD_CAP_DMA_INTERNAL) {
+		tmp = readl(priv->regbase + UNIPHIER_SD_DMA_MODE);
+		tmp |= UNIPHIER_SD_DMA_MODE_ADDR_INC;
+		writel(tmp, priv->regbase + UNIPHIER_SD_DMA_MODE);
+	}
+
+	return 0;
+}
+
+static int uniphier_sd_getcd(struct mmc *mmc)
+{
+	struct uniphier_sd_priv *priv = mmc->priv;
+
+	if (priv->caps & UNIPHIER_SD_CAP_NONREMOVABLE)
+		return 1;
+
+	return !!(readl(priv->regbase + UNIPHIER_SD_INFO1) &
+		  UNIPHIER_SD_INFO1_CD);
+}
+
+static const struct mmc_ops uniphier_sd_ops = {
+	.send_cmd = uniphier_sd_send_cmd,
+	.set_ios = uniphier_sd_set_ios,
+	.init = uniphier_sd_init,
+	.getcd = uniphier_sd_getcd,
+};
+
+int uniphier_sd_probe(struct udevice *dev)
+{
+	struct uniphier_sd_priv *priv = dev_get_priv(dev);
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	fdt_addr_t base;
+	fdt_size_t size;
+	struct udevice *clk_dev;
+	int clk_id;
+	int ret;
+
+	base = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg", &size);
+	priv->regbase = map_sysmem(base, size);
+	if (!priv->regbase)
+		return -ENOMEM;
+
+	clk_id = clk_get_by_index(dev, 0, &clk_dev);
+	if (clk_id < 0) {
+		pr_err("failed to get host clock\n");
+		return clk_id;
+	}
+
+	/* set to max rate */
+	priv->mclk = clk_set_periph_rate(clk_dev, clk_id, ULONG_MAX);
+	if (IS_ERR_VALUE(priv->mclk)) {
+		pr_err("failed to set rate for host clock\n");
+		return priv->mclk;
+	}
+
+	ret = clk_enable(clk_dev, clk_id);
+	if (ret) {
+		pr_err("failed to enable host clock\n");
+		return ret;
+	}
+
+	priv->cfg.name = dev->name;
+	priv->cfg.ops = &uniphier_sd_ops;
+	priv->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
+
+	switch (fdtdec_get_int(gd->fdt_blob, dev->of_offset, "bus-width", 1)) {
+	case 8:
+		priv->cfg.host_caps |= MMC_MODE_8BIT;
+		break;
+	case 4:
+		priv->cfg.host_caps |= MMC_MODE_4BIT;
+		break;
+	case 1:
+		break;
+	default:
+		pr_err("Invalid \"bus-width\" value\n");
+		return -EINVAL;
+	}
+
+	if (fdt_get_property(gd->fdt_blob, dev->of_offset, "non-removable",
+			     NULL))
+		priv->caps |= UNIPHIER_SD_CAP_NONREMOVABLE;
+
+	priv->version = readl(priv->regbase + UNIPHIER_SD_VERSION) &
+							UNIPHIER_SD_VERSION_IP;
+	pr_debug("version %x\n", priv->version);
+	if (priv->version >= 0x10) {
+		/*
+		 * For UniPhier ARMv7 SoCs, RAM is not available in SPL,
+		 * so DMA is not available either.
+		 */
+		if (!IS_ENABLED(CONFIG_SPL_BUILD))
+			priv->caps |= UNIPHIER_SD_CAP_DMA_INTERNAL;
+		priv->caps |= UNIPHIER_SD_CAP_DIV1024;
+	}
+
+	priv->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
+	priv->cfg.f_min = priv->mclk /
+			(priv->caps & UNIPHIER_SD_CAP_DIV1024 ? 1024 : 512);
+	priv->cfg.f_max = priv->mclk;
+	priv->cfg.b_max = U32_MAX; /* max value of UNIPHIER_SD_SECCNT */
+
+	priv->mmc = mmc_create(&priv->cfg, priv);
+	if (!priv->mmc)
+		return -EIO;
+
+	upriv->mmc = priv->mmc;
+
+	return 0;
+}
+
+int uniphier_sd_remove(struct udevice *dev)
+{
+	struct uniphier_sd_priv *priv = dev_get_priv(dev);
+
+	unmap_sysmem(priv->regbase);
+	mmc_destroy(priv->mmc);
+
+	return 0;
+}
+
+static const struct udevice_id uniphier_sd_match[] = {
+	{ .compatible = "socionext,uniphier-sdhc" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(uniphier_mmc) = {
+	.name = "uniphier-mmc",
+	.id = UCLASS_MMC,
+	.of_match = uniphier_sd_match,
+	.probe = uniphier_sd_probe,
+	.remove = uniphier_sd_remove,
+	.priv_auto_alloc_size = sizeof(struct uniphier_sd_priv),
+};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [U-Boot] [PATCH v2 2/3] ARM: uniphier: enable UniPhier SD/MMC host driver
  2016-02-10 13:28 [U-Boot] [PATCH v2 0/3] UniPhier SD/eMMC controller driver Masahiro Yamada
  2016-02-10 13:28 ` [U-Boot] [PATCH v2 1/3] mmc: uniphier: add driver for UniPhier SD/MMC host controller Masahiro Yamada
@ 2016-02-10 13:28 ` Masahiro Yamada
  2016-02-10 13:28 ` [U-Boot] [PATCH v2 3/3] ARM: dts: uniphier: add SD/MMC host controller nodes Masahiro Yamada
  2 siblings, 0 replies; 7+ messages in thread
From: Masahiro Yamada @ 2016-02-10 13:28 UTC (permalink / raw)
  To: u-boot

Enable the driver in all UniPhier defconfig files and add some
needed defines to the common files.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---

Changes in v2: None

 arch/arm/Kconfig                     | 1 +
 configs/uniphier_ld4_sld8_defconfig  | 1 +
 configs/uniphier_pro4_defconfig      | 1 +
 configs/uniphier_pro5_defconfig      | 1 +
 configs/uniphier_pxs2_ld6b_defconfig | 1 +
 configs/uniphier_sld3_defconfig      | 1 +
 include/configs/uniphier.h           | 4 ++++
 7 files changed, 10 insertions(+)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d8b63e9..6a8c9ae 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -699,6 +699,7 @@ config ARCH_UNIPHIER
 	select SPL_DM
 	select DM_SERIAL
 	select DM_I2C
+	select DM_MMC
 	help
 	  Support for UniPhier SoC family developed by Socionext Inc.
 	  (formerly, System LSI Business Division of Panasonic Corporation)
diff --git a/configs/uniphier_ld4_sld8_defconfig b/configs/uniphier_ld4_sld8_defconfig
index 535f96f..9bae445 100644
--- a/configs/uniphier_ld4_sld8_defconfig
+++ b/configs/uniphier_ld4_sld8_defconfig
@@ -19,6 +19,7 @@ CONFIG_CMD_TIME=y
 # CONFIG_CMD_MISC is not set
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SPL_SIMPLE_BUS=y
+CONFIG_MMC_UNIPHIER=y
 CONFIG_NAND_DENALI=y
 CONFIG_SYS_NAND_DENALI_64BIT=y
 CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
diff --git a/configs/uniphier_pro4_defconfig b/configs/uniphier_pro4_defconfig
index 2361db6..b6e6ebf 100644
--- a/configs/uniphier_pro4_defconfig
+++ b/configs/uniphier_pro4_defconfig
@@ -18,6 +18,7 @@ CONFIG_CMD_TIME=y
 # CONFIG_CMD_MISC is not set
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SPL_SIMPLE_BUS=y
+CONFIG_MMC_UNIPHIER=y
 CONFIG_NAND_DENALI=y
 CONFIG_SYS_NAND_DENALI_64BIT=y
 CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
diff --git a/configs/uniphier_pro5_defconfig b/configs/uniphier_pro5_defconfig
index be0d7b5..5981c87 100644
--- a/configs/uniphier_pro5_defconfig
+++ b/configs/uniphier_pro5_defconfig
@@ -18,6 +18,7 @@ CONFIG_CMD_TIME=y
 # CONFIG_CMD_MISC is not set
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SPL_SIMPLE_BUS=y
+CONFIG_MMC_UNIPHIER=y
 CONFIG_NAND_DENALI=y
 CONFIG_SYS_NAND_DENALI_64BIT=y
 CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
diff --git a/configs/uniphier_pxs2_ld6b_defconfig b/configs/uniphier_pxs2_ld6b_defconfig
index f8cb794..dae5a6e 100644
--- a/configs/uniphier_pxs2_ld6b_defconfig
+++ b/configs/uniphier_pxs2_ld6b_defconfig
@@ -19,6 +19,7 @@ CONFIG_CMD_TIME=y
 # CONFIG_CMD_MISC is not set
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SPL_SIMPLE_BUS=y
+CONFIG_MMC_UNIPHIER=y
 CONFIG_NAND_DENALI=y
 CONFIG_SYS_NAND_DENALI_64BIT=y
 CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
diff --git a/configs/uniphier_sld3_defconfig b/configs/uniphier_sld3_defconfig
index e369c45..0a4550e 100644
--- a/configs/uniphier_sld3_defconfig
+++ b/configs/uniphier_sld3_defconfig
@@ -16,6 +16,7 @@ CONFIG_CMD_PING=y
 CONFIG_CMD_TIME=y
 # CONFIG_CMD_MISC is not set
 CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_MMC_UNIPHIER=y
 CONFIG_NAND_DENALI=y
 CONFIG_SYS_NAND_DENALI_64BIT=y
 CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
diff --git a/include/configs/uniphier.h b/include/configs/uniphier.h
index 43fe946..bef92a1 100644
--- a/include/configs/uniphier.h
+++ b/include/configs/uniphier.h
@@ -146,6 +146,10 @@
 #define CONFIG_FAT_WRITE
 #define CONFIG_DOS_PARTITION
 
+/* SD/MMC */
+#define CONFIG_CMD_MMC
+#define CONFIG_GENERIC_MMC
+
 /* memtest works on */
 #define CONFIG_SYS_MEMTEST_START	CONFIG_SYS_SDRAM_BASE
 #define CONFIG_SYS_MEMTEST_END		(CONFIG_SYS_SDRAM_BASE + 0x01000000)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [U-Boot] [PATCH v2 3/3] ARM: dts: uniphier: add SD/MMC host controller nodes
  2016-02-10 13:28 [U-Boot] [PATCH v2 0/3] UniPhier SD/eMMC controller driver Masahiro Yamada
  2016-02-10 13:28 ` [U-Boot] [PATCH v2 1/3] mmc: uniphier: add driver for UniPhier SD/MMC host controller Masahiro Yamada
  2016-02-10 13:28 ` [U-Boot] [PATCH v2 2/3] ARM: uniphier: enable UniPhier SD/MMC host driver Masahiro Yamada
@ 2016-02-10 13:28 ` Masahiro Yamada
  2 siblings, 0 replies; 7+ messages in thread
From: Masahiro Yamada @ 2016-02-10 13:28 UTC (permalink / raw)
  To: u-boot

This host controller is available for all UniPhier SoCs.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---

Changes in v2: None

 arch/arm/dts/uniphier-ph1-ld4-ref.dts        |  4 +++
 arch/arm/dts/uniphier-ph1-ld4.dtsi           | 25 +++++++++++++++++++
 arch/arm/dts/uniphier-ph1-ld6b-ref.dts       |  4 +++
 arch/arm/dts/uniphier-ph1-pro4-ref.dts       |  8 ++++++
 arch/arm/dts/uniphier-ph1-pro4.dtsi          | 37 ++++++++++++++++++++++++++++
 arch/arm/dts/uniphier-ph1-pro5-4kbox.dts     |  8 ++++++
 arch/arm/dts/uniphier-ph1-pro5.dtsi          | 24 ++++++++++++++++++
 arch/arm/dts/uniphier-ph1-sld3-ref.dts       |  4 +++
 arch/arm/dts/uniphier-ph1-sld3.dtsi          | 19 ++++++++++++++
 arch/arm/dts/uniphier-ph1-sld8-ref.dts       |  4 +++
 arch/arm/dts/uniphier-ph1-sld8.dtsi          | 25 +++++++++++++++++++
 arch/arm/dts/uniphier-pinctrl.dtsi           | 15 +++++++++++
 arch/arm/dts/uniphier-proxstream2-gentil.dts |  4 +++
 arch/arm/dts/uniphier-proxstream2-vodka.dts  |  4 +++
 arch/arm/dts/uniphier-proxstream2.dtsi       | 24 ++++++++++++++++++
 15 files changed, 209 insertions(+)

diff --git a/arch/arm/dts/uniphier-ph1-ld4-ref.dts b/arch/arm/dts/uniphier-ph1-ld4-ref.dts
index f62916d..d7b0007 100644
--- a/arch/arm/dts/uniphier-ph1-ld4-ref.dts
+++ b/arch/arm/dts/uniphier-ph1-ld4-ref.dts
@@ -51,6 +51,10 @@
 	status = "okay";
 };
 
+&sd {
+	status = "okay";
+};
+
 &usb0 {
 	status = "okay";
 };
diff --git a/arch/arm/dts/uniphier-ph1-ld4.dtsi b/arch/arm/dts/uniphier-ph1-ld4.dtsi
index 7c8759f..b93a34f 100644
--- a/arch/arm/dts/uniphier-ph1-ld4.dtsi
+++ b/arch/arm/dts/uniphier-ph1-ld4.dtsi
@@ -108,6 +108,31 @@
 		clock-frequency = <100000>;
 	};
 
+	sd: sdhc at 5a400000 {
+		compatible = "socionext,uniphier-sdhc";
+		status = "disabled";
+		reg = <0x5a400000 0x200>;
+		interrupts = <0 76 4>;
+		pinctrl-names = "default", "1.8v";
+		pinctrl-0 = <&pinctrl_sd>;
+		pinctrl-1 = <&pinctrl_sd_1v8>;
+		clocks = <&mio 0>;
+		bus-width = <4>;
+	};
+
+	emmc: sdhc at 5a500000 {
+		compatible = "socionext,uniphier-sdhc";
+		status = "disabled";
+		reg = <0x5a500000 0x200>;
+		interrupts = <0 78 4>;
+		pinctrl-names = "default", "1.8v";
+		pinctrl-0 = <&pinctrl_emmc>;
+		pinctrl-1 = <&pinctrl_emmc_1v8>;
+		clocks = <&mio 1>;
+		bus-width = <8>;
+		non-removable;
+	};
+
 	usb0: usb at 5a800100 {
 		compatible = "socionext,uniphier-ehci", "generic-ehci";
 		status = "disabled";
diff --git a/arch/arm/dts/uniphier-ph1-ld6b-ref.dts b/arch/arm/dts/uniphier-ph1-ld6b-ref.dts
index dca408b..13a29fd 100644
--- a/arch/arm/dts/uniphier-ph1-ld6b-ref.dts
+++ b/arch/arm/dts/uniphier-ph1-ld6b-ref.dts
@@ -53,6 +53,10 @@
 	status = "okay";
 };
 
+&sd {
+	status = "okay";
+};
+
 &usb0 {
 	status = "okay";
 };
diff --git a/arch/arm/dts/uniphier-ph1-pro4-ref.dts b/arch/arm/dts/uniphier-ph1-pro4-ref.dts
index 202a642..07a9783 100644
--- a/arch/arm/dts/uniphier-ph1-pro4-ref.dts
+++ b/arch/arm/dts/uniphier-ph1-pro4-ref.dts
@@ -54,6 +54,14 @@
 	status = "okay";
 };
 
+&sd {
+	status = "okay";
+};
+
+&sd1 {
+	status = "okay";
+};
+
 &usb0 {
 	status = "okay";
 };
diff --git a/arch/arm/dts/uniphier-ph1-pro4.dtsi b/arch/arm/dts/uniphier-ph1-pro4.dtsi
index cb5b8f1..f413549 100644
--- a/arch/arm/dts/uniphier-ph1-pro4.dtsi
+++ b/arch/arm/dts/uniphier-ph1-pro4.dtsi
@@ -140,6 +140,43 @@
 		clock-frequency = <400000>;
 	};
 
+	sd: sdhc at 5a400000 {
+		compatible = "socionext,uniphier-sdhc";
+		status = "disabled";
+		reg = <0x5a400000 0x200>;
+		interrupts = <0 76 4>;
+		pinctrl-names = "default", "1.8v";
+		pinctrl-0 = <&pinctrl_sd>;
+		pinctrl-1 = <&pinctrl_sd_1v8>;
+		clocks = <&mio 0>;
+		bus-width = <4>;
+	};
+
+	emmc: sdhc at 5a500000 {
+		compatible = "socionext,uniphier-sdhc";
+		status = "disabled";
+		reg = <0x5a500000 0x200>;
+		interrupts = <0 78 4>;
+		pinctrl-names = "default", "1.8v";
+		pinctrl-0 = <&pinctrl_emmc>;
+		pinctrl-1 = <&pinctrl_emmc_1v8>;
+		clocks = <&mio 1>;
+		bus-width = <8>;
+		non-removable;
+	};
+
+	sd1: sdhc at 5a600000 {
+		compatible = "socionext,uniphier-sdhc";
+		status = "disabled";
+		reg = <0x5a600000 0x200>;
+		interrupts = <0 85 4>;
+		pinctrl-names = "default", "1.8v";
+		pinctrl-0 = <&pinctrl_sd1>;
+		pinctrl-1 = <&pinctrl_sd1_1v8>;
+		clocks = <&mio 2>;
+		bus-width = <4>;
+	};
+
 	usb2: usb at 5a800100 {
 		compatible = "socionext,uniphier-ehci", "generic-ehci";
 		status = "disabled";
diff --git a/arch/arm/dts/uniphier-ph1-pro5-4kbox.dts b/arch/arm/dts/uniphier-ph1-pro5-4kbox.dts
index 02a3362..cbdc3eb 100644
--- a/arch/arm/dts/uniphier-ph1-pro5-4kbox.dts
+++ b/arch/arm/dts/uniphier-ph1-pro5-4kbox.dts
@@ -47,6 +47,14 @@
 	status = "okay";
 };
 
+&emmc {
+	status = "okay";
+};
+
+&sd {
+	status = "okay";
+};
+
 /* for U-Boot only */
 / {
 	soc {
diff --git a/arch/arm/dts/uniphier-ph1-pro5.dtsi b/arch/arm/dts/uniphier-ph1-pro5.dtsi
index 087b25a..56b5f3d 100644
--- a/arch/arm/dts/uniphier-ph1-pro5.dtsi
+++ b/arch/arm/dts/uniphier-ph1-pro5.dtsi
@@ -152,6 +152,30 @@
 		clock-frequency = <400000>;
 	};
 
+	emmc: sdhc at 68400000 {
+		compatible = "socionext,uniphier-sdhc";
+		status = "disabled";
+		reg = <0x68400000 0x800>;
+		interrupts = <0 78 4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_emmc>;
+		clocks = <&mio 1>;
+		bus-width = <8>;
+		non-removable;
+	};
+
+	sd: sdhc at 68800000 {
+		compatible = "socionext,uniphier-sdhc";
+		status = "disabled";
+		reg = <0x68800000 0x800>;
+		interrupts = <0 76 4>;
+		pinctrl-names = "default", "1.8v";
+		pinctrl-0 = <&pinctrl_sd>;
+		pinctrl-1 = <&pinctrl_sd_1v8>;
+		clocks = <&mio 0>;
+		bus-width = <4>;
+	};
+
 	usb0: usb at 65a00000 {
 		compatible = "socionext,uniphier-xhci", "generic-xhci";
 		status = "disabled";
diff --git a/arch/arm/dts/uniphier-ph1-sld3-ref.dts b/arch/arm/dts/uniphier-ph1-sld3-ref.dts
index ff17945..c7213c9 100644
--- a/arch/arm/dts/uniphier-ph1-sld3-ref.dts
+++ b/arch/arm/dts/uniphier-ph1-sld3-ref.dts
@@ -52,6 +52,10 @@
 	status = "okay";
 };
 
+&sd {
+	status = "okay";
+};
+
 &usb0 {
 	status = "okay";
 };
diff --git a/arch/arm/dts/uniphier-ph1-sld3.dtsi b/arch/arm/dts/uniphier-ph1-sld3.dtsi
index 85dde66..d118e17 100644
--- a/arch/arm/dts/uniphier-ph1-sld3.dtsi
+++ b/arch/arm/dts/uniphier-ph1-sld3.dtsi
@@ -186,6 +186,25 @@
 			clocks = <&sysctrl 10>, <&sysctrl 18>;
 		};
 
+		emmc: sdhc at 5a400000 {
+			compatible = "socionext,uniphier-sdhc";
+			status = "disabled";
+			reg = <0x5a400000 0x200>;
+			interrupts = <0 78 4>;
+			clocks = <&mio 1>;
+			bus-width = <8>;
+			non-removable;
+		};
+
+		sd: sdhc at 5a500000 {
+			compatible = "socionext,uniphier-sdhc";
+			status = "disabled";
+			reg = <0x5a500000 0x200>;
+			interrupts = <0 76 4>;
+			clocks = <&mio 0>;
+			bus-width = <4>;
+		};
+
 		usb0: usb at 5a800100 {
 			compatible = "socionext,uniphier-ehci", "generic-ehci";
 			status = "disabled";
diff --git a/arch/arm/dts/uniphier-ph1-sld8-ref.dts b/arch/arm/dts/uniphier-ph1-sld8-ref.dts
index b5b6f65..ec5c5bd 100644
--- a/arch/arm/dts/uniphier-ph1-sld8-ref.dts
+++ b/arch/arm/dts/uniphier-ph1-sld8-ref.dts
@@ -51,6 +51,10 @@
 	status = "okay";
 };
 
+&sd {
+	status = "okay";
+};
+
 &usb0 {
 	status = "okay";
 };
diff --git a/arch/arm/dts/uniphier-ph1-sld8.dtsi b/arch/arm/dts/uniphier-ph1-sld8.dtsi
index f93db83..159354f 100644
--- a/arch/arm/dts/uniphier-ph1-sld8.dtsi
+++ b/arch/arm/dts/uniphier-ph1-sld8.dtsi
@@ -108,6 +108,31 @@
 		clock-frequency = <100000>;
 	};
 
+	sd: sdhc at 5a400000 {
+		compatible = "socionext,uniphier-sdhc";
+		status = "disabled";
+		reg = <0x5a400000 0x200>;
+		interrupts = <0 76 4>;
+		pinctrl-names = "default", "1.8v";
+		pinctrl-0 = <&pinctrl_sd>;
+		pinctrl-1 = <&pinctrl_sd_1v8>;
+		clocks = <&mio 0>;
+		bus-width = <4>;
+	};
+
+	emmc: sdhc at 5a500000 {
+		compatible = "socionext,uniphier-sdhc";
+		status = "disabled";
+		interrupts = <0 78 4>;
+		reg = <0x5a500000 0x200>;
+		pinctrl-names = "default", "1.8v";
+		pinctrl-0 = <&pinctrl_emmc>;
+		pinctrl-1 = <&pinctrl_emmc_1v8>;
+		clocks = <&mio 1>;
+		bus-width = <8>;
+		non-removable;
+	};
+
 	usb0: usb at 5a800100 {
 		compatible = "socionext,uniphier-ehci", "generic-ehci";
 		status = "disabled";
diff --git a/arch/arm/dts/uniphier-pinctrl.dtsi b/arch/arm/dts/uniphier-pinctrl.dtsi
index b1691d0..494139a 100644
--- a/arch/arm/dts/uniphier-pinctrl.dtsi
+++ b/arch/arm/dts/uniphier-pinctrl.dtsi
@@ -12,6 +12,11 @@
 		function = "emmc";
 	};
 
+	pinctrl_emmc_1v8: emmc_grp_1v8 {
+		groups = "emmc", "emmc_dat8";
+		function = "emmc";
+	};
+
 	pinctrl_i2c0: i2c0_grp {
 		groups = "i2c0";
 		function = "i2c0";
@@ -37,11 +42,21 @@
 		function = "sd";
 	};
 
+	pinctrl_sd_1v8: sd_grp_1v8 {
+		groups = "sd";
+		function = "sd";
+	};
+
 	pinctrl_sd1: sd1_grp {
 		groups = "sd1";
 		function = "sd1";
 	};
 
+	pinctrl_sd1_1v8: sd1_grp_1v8 {
+		groups = "sd1";
+		function = "sd1";
+	};
+
 	pinctrl_uart0: uart0_grp {
 		groups = "uart0";
 		function = "uart0";
diff --git a/arch/arm/dts/uniphier-proxstream2-gentil.dts b/arch/arm/dts/uniphier-proxstream2-gentil.dts
index c6c133a..b198d8e 100644
--- a/arch/arm/dts/uniphier-proxstream2-gentil.dts
+++ b/arch/arm/dts/uniphier-proxstream2-gentil.dts
@@ -41,6 +41,10 @@
 	status = "okay";
 };
 
+&emmc {
+	status = "okay";
+};
+
 &usb0 {
 	status = "okay";
 };
diff --git a/arch/arm/dts/uniphier-proxstream2-vodka.dts b/arch/arm/dts/uniphier-proxstream2-vodka.dts
index 3703ad3..d61e0b6 100644
--- a/arch/arm/dts/uniphier-proxstream2-vodka.dts
+++ b/arch/arm/dts/uniphier-proxstream2-vodka.dts
@@ -41,6 +41,10 @@
 	status = "okay";
 };
 
+&emmc {
+	status = "okay";
+};
+
 &usb0 {
 	status = "okay";
 };
diff --git a/arch/arm/dts/uniphier-proxstream2.dtsi b/arch/arm/dts/uniphier-proxstream2.dtsi
index a70b135..a01725f 100644
--- a/arch/arm/dts/uniphier-proxstream2.dtsi
+++ b/arch/arm/dts/uniphier-proxstream2.dtsi
@@ -163,6 +163,30 @@
 		clock-frequency = <400000>;
 	};
 
+	emmc: sdhc at 5a000000 {
+		compatible = "socionext,uniphier-sdhc";
+		status = "disabled";
+		reg = <0x5a000000 0x800>;
+		interrupts = <0 78 4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_emmc>;
+		clocks = <&mio 1>;
+		bus-width = <8>;
+		non-removable;
+	};
+
+	sd: sdhc at 5a400000 {
+		compatible = "socionext,uniphier-sdhc";
+		status = "disabled";
+		reg = <0x5a400000 0x800>;
+		interrupts = <0 76 4>;
+		pinctrl-names = "default", "1.8v";
+		pinctrl-0 = <&pinctrl_sd>;
+		pinctrl-1 = <&pinctrl_sd_1v8>;
+		clocks = <&mio 0>;
+		bus-width = <4>;
+	};
+
 	usb0: usb at 65a00000 {
 		compatible = "socionext,uniphier-xhci", "generic-xhci";
 		status = "disabled";
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [U-Boot] [PATCH v2 1/3] mmc: uniphier: add driver for UniPhier SD/MMC host controller
  2016-02-10 13:28 ` [U-Boot] [PATCH v2 1/3] mmc: uniphier: add driver for UniPhier SD/MMC host controller Masahiro Yamada
@ 2016-02-10 13:45   ` Marek Vasut
  2016-02-16  8:18     ` Masahiro Yamada
  0 siblings, 1 reply; 7+ messages in thread
From: Marek Vasut @ 2016-02-10 13:45 UTC (permalink / raw)
  To: u-boot

On 02/10/2016 02:28 PM, Masahiro Yamada wrote:
> Add a driver for the on-chip SD/eMMC host controller used by
> UniPhier SoC family.
> 
> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>

?? ????,

[...]

> +#include <common.h>
> +#include <clk.h>
> +#include <fdtdec.h>
> +#include <mapmem.h>
> +#include <mmc.h>
> +#include <dm/device.h>
> +#include <linux/compat.h>
> +#include <linux/io.h>
> +#include <asm/unaligned.h>
> +#include <asm/dma-mapping.h>
> +
> +#define pr_err   printf
> +#define pr_warn  printf
> +#ifdef DEBUG
> +#define pr_debug printf
> +#else
> +#define pr_debug(...)
> +#endif

This should go into include/ somewhere, your driver shouldn't be a
platform abstraction library.

> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define UNIPHIER_SD_CMD			0x000	/* command */

[...]

> +static int uniphier_sd_wait_irq(struct uniphier_sd_priv *priv,
> +				unsigned int reg, u32 flag)
> +{
> +	long wait = 1000000;
> +	int ret;

Replace this with wait_for_bit() please .

> +	while (!(readl(priv->regbase + reg) & flag)) {
> +		if (wait-- < 0) {
> +			pr_err("timeout\n");
> +			return -ETIMEDOUT;
> +		}
> +
> +		ret = uniphier_sd_check_error(priv);
> +		if (ret)
> +			return ret;
> +
> +		udelay(1);
> +	}
> +
> +	return 0;
> +}

[...]

> +static void uniphier_sd_dma_start(struct uniphier_sd_priv *priv,
> +				  dma_addr_t dma_addr)
> +{
> +	u32 tmp;
> +
> +	writel(0, priv->regbase + UNIPHIER_SD_DMA_INFO1);
> +	writel(0, priv->regbase + UNIPHIER_SD_DMA_INFO2);
> +
> +	/* enable DMA */
> +	tmp = readl(priv->regbase + UNIPHIER_SD_EXTMODE);
> +	tmp |= UNIPHIER_SD_EXTMODE_DMA_EN;
> +	writel(tmp, priv->regbase + UNIPHIER_SD_EXTMODE);

I'd say, use setbits_le32(), but could it be that this driver is kept in
sync with Linux ?

> +	writel(dma_addr & U32_MAX, priv->regbase + UNIPHIER_SD_DMA_ADDR_L);
> +
> +	/* suppress the warning "right shift count >= width of type" */
> +	dma_addr >>= min_t(int, 32, 8 * sizeof(dma_addr));
> +
> +	writel(dma_addr & U32_MAX, priv->regbase + UNIPHIER_SD_DMA_ADDR_H);
> +
> +	writel(UNIPHIER_SD_DMA_CTL_START, priv->regbase + UNIPHIER_SD_DMA_CTL);
> +}
> +
> +static int uniphier_sd_dma_wait_irq(struct uniphier_sd_priv *priv, u32 flag,
> +				    unsigned int blocks)
> +{
> +	long wait = 1000000 + 10 * blocks;

wait_for_bit() again.

> +	while (!(readl(priv->regbase + UNIPHIER_SD_DMA_INFO1) & flag)) {
> +		if (wait-- < 0) {
> +			pr_err("timeout during DMA\n");
> +			return -ETIMEDOUT;
> +		}
> +
> +		udelay(10);
> +	}
> +
> +	if (readl(priv->regbase + UNIPHIER_SD_DMA_INFO2)) {
> +		pr_err("error during DMA\n");
> +		return -EIO;
> +	}
> +
> +	return 0;
> +}

??

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [U-Boot] [PATCH v2 1/3] mmc: uniphier: add driver for UniPhier SD/MMC host controller
  2016-02-10 13:45   ` Marek Vasut
@ 2016-02-16  8:18     ` Masahiro Yamada
  2016-02-16 12:51       ` Marek Vasut
  0 siblings, 1 reply; 7+ messages in thread
From: Masahiro Yamada @ 2016-02-16  8:18 UTC (permalink / raw)
  To: u-boot

Hi Marek,


2016-02-10 22:45 GMT+09:00 Marek Vasut <marex@denx.de>:
> On 02/10/2016 02:28 PM, Masahiro Yamada wrote:
>> Add a driver for the on-chip SD/eMMC host controller used by
>> UniPhier SoC family.
>>
>> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
>
> ?? ????,
>
> [...]
>
>> +#include <common.h>
>> +#include <clk.h>
>> +#include <fdtdec.h>
>> +#include <mapmem.h>
>> +#include <mmc.h>
>> +#include <dm/device.h>
>> +#include <linux/compat.h>
>> +#include <linux/io.h>
>> +#include <asm/unaligned.h>
>> +#include <asm/dma-mapping.h>
>> +
>> +#define pr_err   printf
>> +#define pr_warn  printf
>> +#ifdef DEBUG
>> +#define pr_debug printf
>> +#else
>> +#define pr_debug(...)
>> +#endif
>
> This should go into include/ somewhere, your driver shouldn't be a
> platform abstraction library.

Fixed in v3.



>> +static int uniphier_sd_wait_irq(struct uniphier_sd_priv *priv,
>> +                             unsigned int reg, u32 flag)
>> +{
>> +     long wait = 1000000;
>> +     int ret;
>
> Replace this with wait_for_bit() please .


It cannot check error during the loop.

I want to check the error flags in the loop
because no reason to wait for the time-out
if some error happens.


>> +     while (!(readl(priv->regbase + reg) & flag)) {
>> +             if (wait-- < 0) {
>> +                     pr_err("timeout\n");
>> +                     return -ETIMEDOUT;
>> +             }
>> +
>> +             ret = uniphier_sd_check_error(priv);
>> +             if (ret)
>> +                     return ret;
>> +
>> +             udelay(1);
>> +     }
>> +
>> +     return 0;
>> +}
>
> [...]
>
>> +static void uniphier_sd_dma_start(struct uniphier_sd_priv *priv,
>> +                               dma_addr_t dma_addr)
>> +{
>> +     u32 tmp;
>> +
>> +     writel(0, priv->regbase + UNIPHIER_SD_DMA_INFO1);
>> +     writel(0, priv->regbase + UNIPHIER_SD_DMA_INFO2);
>> +
>> +     /* enable DMA */
>> +     tmp = readl(priv->regbase + UNIPHIER_SD_EXTMODE);
>> +     tmp |= UNIPHIER_SD_EXTMODE_DMA_EN;
>> +     writel(tmp, priv->regbase + UNIPHIER_SD_EXTMODE);
>
> I'd say, use setbits_le32(), but could it be that this driver is kept in
> sync with Linux ?

Yes, I am developing the MMC driver
for Linux as well as U-Boot at the same time.

This is the U-Boot counter-part,
although the Linux one has not been upstreamed yet.

It can save my time to copy-paste code snippets between the two.

I want to sync as much code as possible.




-- 
Best Regards
Masahiro Yamada

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [U-Boot] [PATCH v2 1/3] mmc: uniphier: add driver for UniPhier SD/MMC host controller
  2016-02-16  8:18     ` Masahiro Yamada
@ 2016-02-16 12:51       ` Marek Vasut
  0 siblings, 0 replies; 7+ messages in thread
From: Marek Vasut @ 2016-02-16 12:51 UTC (permalink / raw)
  To: u-boot

On 02/16/2016 09:18 AM, Masahiro Yamada wrote:
> Hi Marek,

Hi!

[...]

>>> +static int uniphier_sd_wait_irq(struct uniphier_sd_priv *priv,
>>> +                             unsigned int reg, u32 flag)
>>> +{
>>> +     long wait = 1000000;
>>> +     int ret;
>>
>> Replace this with wait_for_bit() please .
> 
> 
> It cannot check error during the loop.
> 
> I want to check the error flags in the loop
> because no reason to wait for the time-out
> if some error happens.

You have a point there.

I wonder if it'd make sense to extend the wait_for_bit with some
callback maybe ?

>>> +     while (!(readl(priv->regbase + reg) & flag)) {
>>> +             if (wait-- < 0) {
>>> +                     pr_err("timeout\n");
>>> +                     return -ETIMEDOUT;
>>> +             }
>>> +
>>> +             ret = uniphier_sd_check_error(priv);
>>> +             if (ret)
>>> +                     return ret;
>>> +
>>> +             udelay(1);
>>> +     }
>>> +
>>> +     return 0;
>>> +}
>>
>> [...]
>>
>>> +static void uniphier_sd_dma_start(struct uniphier_sd_priv *priv,
>>> +                               dma_addr_t dma_addr)
>>> +{
>>> +     u32 tmp;
>>> +
>>> +     writel(0, priv->regbase + UNIPHIER_SD_DMA_INFO1);
>>> +     writel(0, priv->regbase + UNIPHIER_SD_DMA_INFO2);
>>> +
>>> +     /* enable DMA */
>>> +     tmp = readl(priv->regbase + UNIPHIER_SD_EXTMODE);
>>> +     tmp |= UNIPHIER_SD_EXTMODE_DMA_EN;
>>> +     writel(tmp, priv->regbase + UNIPHIER_SD_EXTMODE);
>>
>> I'd say, use setbits_le32(), but could it be that this driver is kept in
>> sync with Linux ?
> 
> Yes, I am developing the MMC driver
> for Linux as well as U-Boot at the same time.
> 
> This is the U-Boot counter-part,
> although the Linux one has not been upstreamed yet.
> 
> It can save my time to copy-paste code snippets between the two.
> 
> I want to sync as much code as possible.

Understood, thanks!

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2016-02-16 12:51 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-10 13:28 [U-Boot] [PATCH v2 0/3] UniPhier SD/eMMC controller driver Masahiro Yamada
2016-02-10 13:28 ` [U-Boot] [PATCH v2 1/3] mmc: uniphier: add driver for UniPhier SD/MMC host controller Masahiro Yamada
2016-02-10 13:45   ` Marek Vasut
2016-02-16  8:18     ` Masahiro Yamada
2016-02-16 12:51       ` Marek Vasut
2016-02-10 13:28 ` [U-Boot] [PATCH v2 2/3] ARM: uniphier: enable UniPhier SD/MMC host driver Masahiro Yamada
2016-02-10 13:28 ` [U-Boot] [PATCH v2 3/3] ARM: dts: uniphier: add SD/MMC host controller nodes Masahiro Yamada

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.