* [U-Boot] [PATCH v4 0/3] UniPhier SD/eMMC controller driver
@ 2016-02-18 10:52 Masahiro Yamada
2016-02-18 10:52 ` [U-Boot] [PATCH v4 1/3] mmc: uniphier: add driver for UniPhier SD/MMC host controller Masahiro Yamada
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Masahiro Yamada @ 2016-02-18 10:52 UTC (permalink / raw)
To: u-boot
Changes in v4:
- Add some comments about HOST_MODE register
- Rename uniphier_sd_wait_irq() to uniphier_sd_wait_for_irq()
Changes in v3:
- Use dev_err/dev_dbg instead of pr_err/pr_debug
- Tidy up uniphier_sd_set_ios()
- Allow to use DMA even in SPL if the target address is DMA'able
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.
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-ace.dts | 4 +
arch/arm/dts/uniphier-ph1-pro4-ref.dts | 8 +
arch/arm/dts/uniphier-ph1-pro4-sanji.dts | 4 +
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 | 751 +++++++++++++++++++++++++++
include/configs/uniphier.h | 4 +
28 files changed, 986 insertions(+)
create mode 100644 drivers/mmc/uniphier-sd.c
--
1.9.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [U-Boot] [PATCH v4 1/3] mmc: uniphier: add driver for UniPhier SD/MMC host controller
2016-02-18 10:52 [U-Boot] [PATCH v4 0/3] UniPhier SD/eMMC controller driver Masahiro Yamada
@ 2016-02-18 10:52 ` Masahiro Yamada
2016-02-18 10:52 ` [U-Boot] [PATCH v4 2/3] ARM: uniphier: enable UniPhier SD/MMC host driver Masahiro Yamada
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Masahiro Yamada @ 2016-02-18 10:52 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 v4:
- Add some comments about HOST_MODE register
- Rename uniphier_sd_wait_irq() to uniphier_sd_wait_for_irq()
Changes in v3:
- Use dev_err/dev_dbg instead of pr_err/pr_debug
- Tidy up uniphier_sd_set_ios()
- Allow to use DMA even in SPL if the target address is DMA'able
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 | 751 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 759 insertions(+)
create mode 100644 drivers/mmc/uniphier-sd.c
diff --git a/doc/README.uniphier b/doc/README.uniphier
index f03c207..c270ecb 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)
- GPIO
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..3bc4d94
--- /dev/null
+++ b/drivers/mmc/uniphier-sd.c
@@ -0,0 +1,751 @@
+/*
+ * 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>
+
+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;
+ struct udevice *dev;
+ 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) {
+ dev_err(priv->dev, "timeout error\n");
+ return -ETIMEDOUT;
+ }
+
+ if (info2 & (UNIPHIER_SD_INFO2_ERR_END | UNIPHIER_SD_INFO2_ERR_CRC |
+ UNIPHIER_SD_INFO2_ERR_IDX)) {
+ dev_err(priv->dev, "communication out of sync\n");
+ return -EILSEQ;
+ }
+
+ if (info2 & (UNIPHIER_SD_INFO2_ERR_ILA | UNIPHIER_SD_INFO2_ERR_ILR |
+ UNIPHIER_SD_INFO2_ERR_ILW)) {
+ dev_err(priv->dev, "illegal access\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int uniphier_sd_wait_for_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) {
+ dev_err(priv->dev, "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_for_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_for_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_for_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) {
+ dev_err(priv->dev, "timeout during DMA\n");
+ return -ETIMEDOUT;
+ }
+
+ udelay(10);
+ }
+
+ if (readl(priv->regbase + UNIPHIER_SD_DMA_INFO2)) {
+ dev_err(priv->dev, "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_for_irq(priv, poll_flag, data->blocks);
+
+ __dma_unmap_single(dma_addr, len, dir);
+
+ return ret;
+}
+
+/* check if the address is DMA'able */
+static bool uniphier_sd_addr_is_dmaable(unsigned long addr)
+{
+ if (!IS_ALIGNED(addr, UNIPHIER_SD_DMA_MINALIGN))
+ return false;
+
+#if defined(CONFIG_ARCH_UNIPHIER) && !defined(CONFIG_ARM64) && \
+ defined(CONFIG_SPL_BUILD)
+ /*
+ * For UniPhier ARMv7 SoCs, the stack is allocated in the locked ways
+ * of L2, which is unreachable from the DMA engine.
+ */
+ if (addr < CONFIG_SPL_STACK)
+ return false;
+#endif
+
+ return true;
+}
+
+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) {
+ dev_err(priv->dev, "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:
+ dev_err(priv->dev, "unknown response type\n");
+ return -EINVAL;
+ }
+
+ dev_dbg(priv->dev, "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_for_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 &&
+ uniphier_sd_addr_is_dmaable((long)data->src))
+ ret = uniphier_sd_dma_xfer(mmc, data);
+ else
+ ret = uniphier_sd_pio_xfer(mmc, data);
+
+ ret = uniphier_sd_wait_for_irq(priv, UNIPHIER_SD_INFO1,
+ UNIPHIER_SD_INFO1_CMP);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+static void uniphier_sd_set_bus_width(struct uniphier_sd_priv *priv,
+ struct mmc *mmc)
+{
+ u32 val, tmp;
+
+ 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_ddr_mode(struct uniphier_sd_priv *priv,
+ struct mmc *mmc)
+{
+ u32 tmp;
+
+ 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);
+}
+
+static void uniphier_sd_set_clk_rate(struct uniphier_sd_priv *priv,
+ struct mmc *mmc)
+{
+ unsigned int divisor;
+ u32 val, tmp;
+
+ if (!mmc->clock)
+ return;
+
+ 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);
+
+ /* stop the clock before changing its rate to avoid a glitch signal */
+ tmp &= ~UNIPHIER_SD_CLKCTL_SCLKEN;
+ writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL);
+
+ tmp &= ~UNIPHIER_SD_CLKCTL_DIV_MASK;
+ tmp |= val | UNIPHIER_SD_CLKCTL_OFFEN;
+ writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL);
+
+ tmp |= UNIPHIER_SD_CLKCTL_SCLKEN;
+ writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL);
+}
+
+static void uniphier_sd_set_ios(struct mmc *mmc)
+{
+ struct uniphier_sd_priv *priv = mmc->priv;
+
+ dev_dbg(priv->dev, "clock %uHz, DDRmode %d, width %u\n",
+ mmc->clock, mmc->ddr_mode, mmc->bus_width);
+
+ uniphier_sd_set_bus_width(priv, mmc);
+ uniphier_sd_set_ddr_mode(priv, mmc);
+ uniphier_sd_set_clk_rate(priv, mmc);
+
+ udelay(1000);
+}
+
+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);
+
+ /*
+ * Connected to 32bit AXI.
+ * This register dropped backward compatibility at version 0x10.
+ * Write an appropriate value depending on the IP version.
+ */
+ 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;
+
+ priv->dev = dev;
+
+ 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) {
+ dev_err(dev, "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)) {
+ dev_err(dev, "failed to set rate for host clock\n");
+ return priv->mclk;
+ }
+
+ ret = clk_enable(clk_dev, clk_id);
+ if (ret) {
+ dev_err(dev, "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:
+ dev_err(dev, "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;
+ dev_dbg(dev, "version %x\n", priv->version);
+ if (priv->version >= 0x10) {
+ 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] 5+ messages in thread
* [U-Boot] [PATCH v4 2/3] ARM: uniphier: enable UniPhier SD/MMC host driver
2016-02-18 10:52 [U-Boot] [PATCH v4 0/3] UniPhier SD/eMMC controller driver Masahiro Yamada
2016-02-18 10:52 ` [U-Boot] [PATCH v4 1/3] mmc: uniphier: add driver for UniPhier SD/MMC host controller Masahiro Yamada
@ 2016-02-18 10:52 ` Masahiro Yamada
2016-02-18 10:52 ` [U-Boot] [PATCH v4 3/3] ARM: dts: uniphier: add SD/MMC host controller nodes Masahiro Yamada
2016-02-26 15:41 ` [U-Boot] [PATCH v4 0/3] UniPhier SD/eMMC controller driver Masahiro Yamada
3 siblings, 0 replies; 5+ messages in thread
From: Masahiro Yamada @ 2016-02-18 10:52 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 v4: None
Changes in v3: None
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 94bd7ec..37b20ff 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -700,6 +700,7 @@ config ARCH_UNIPHIER
select DM_GPIO
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 dbee08e..892bccc 100644
--- a/configs/uniphier_ld4_sld8_defconfig
+++ b/configs/uniphier_ld4_sld8_defconfig
@@ -21,6 +21,7 @@ CONFIG_CMD_TIME=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_SIMPLE_BUS=y
CONFIG_GPIO_UNIPHIER=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 3c2f7b0..45ef883 100644
--- a/configs/uniphier_pro4_defconfig
+++ b/configs/uniphier_pro4_defconfig
@@ -20,6 +20,7 @@ CONFIG_CMD_TIME=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_SIMPLE_BUS=y
CONFIG_GPIO_UNIPHIER=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 cf5f1ce..0029cd3 100644
--- a/configs/uniphier_pro5_defconfig
+++ b/configs/uniphier_pro5_defconfig
@@ -20,6 +20,7 @@ CONFIG_CMD_TIME=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_SIMPLE_BUS=y
CONFIG_GPIO_UNIPHIER=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 00a2900..0115c21 100644
--- a/configs/uniphier_pxs2_ld6b_defconfig
+++ b/configs/uniphier_pxs2_ld6b_defconfig
@@ -21,6 +21,7 @@ CONFIG_CMD_TIME=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_SIMPLE_BUS=y
CONFIG_GPIO_UNIPHIER=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 013fc8a..5f0d678 100644
--- a/configs/uniphier_sld3_defconfig
+++ b/configs/uniphier_sld3_defconfig
@@ -18,6 +18,7 @@ CONFIG_CMD_TIME=y
# CONFIG_CMD_MISC is not set
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_GPIO_UNIPHIER=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 fcec0c0..9d14155 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] 5+ messages in thread
* [U-Boot] [PATCH v4 3/3] ARM: dts: uniphier: add SD/MMC host controller nodes
2016-02-18 10:52 [U-Boot] [PATCH v4 0/3] UniPhier SD/eMMC controller driver Masahiro Yamada
2016-02-18 10:52 ` [U-Boot] [PATCH v4 1/3] mmc: uniphier: add driver for UniPhier SD/MMC host controller Masahiro Yamada
2016-02-18 10:52 ` [U-Boot] [PATCH v4 2/3] ARM: uniphier: enable UniPhier SD/MMC host driver Masahiro Yamada
@ 2016-02-18 10:52 ` Masahiro Yamada
2016-02-26 15:41 ` [U-Boot] [PATCH v4 0/3] UniPhier SD/eMMC controller driver Masahiro Yamada
3 siblings, 0 replies; 5+ messages in thread
From: Masahiro Yamada @ 2016-02-18 10:52 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 v4: None
Changes in v3: None
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-ace.dts | 4 +++
arch/arm/dts/uniphier-ph1-pro4-ref.dts | 8 ++++++
arch/arm/dts/uniphier-ph1-pro4-sanji.dts | 4 +++
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 ++++++++++++++++++
17 files changed, 217 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 f13c6db..5ae029e 100644
--- a/arch/arm/dts/uniphier-ph1-ld4.dtsi
+++ b/arch/arm/dts/uniphier-ph1-ld4.dtsi
@@ -220,6 +220,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-ace.dts b/arch/arm/dts/uniphier-ph1-pro4-ace.dts
index 6e741ea..37e0853 100644
--- a/arch/arm/dts/uniphier-ph1-pro4-ace.dts
+++ b/arch/arm/dts/uniphier-ph1-pro4-ace.dts
@@ -69,6 +69,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-sanji.dts b/arch/arm/dts/uniphier-ph1-pro4-sanji.dts
index 91a71ef..1ca1042 100644
--- a/arch/arm/dts/uniphier-ph1-pro4-sanji.dts
+++ b/arch/arm/dts/uniphier-ph1-pro4-sanji.dts
@@ -64,6 +64,10 @@
status = "okay";
};
+&emmc {
+ status = "okay";
+};
+
&usb0 {
status = "okay";
};
diff --git a/arch/arm/dts/uniphier-ph1-pro4.dtsi b/arch/arm/dts/uniphier-ph1-pro4.dtsi
index 6637aea..d5767b6 100644
--- a/arch/arm/dts/uniphier-ph1-pro4.dtsi
+++ b/arch/arm/dts/uniphier-ph1-pro4.dtsi
@@ -343,6 +343,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 67a435e..bd1b4b1 100644
--- a/arch/arm/dts/uniphier-ph1-pro5.dtsi
+++ b/arch/arm/dts/uniphier-ph1-pro5.dtsi
@@ -355,6 +355,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 9a6ca57..789713d 100644
--- a/arch/arm/dts/uniphier-ph1-sld3.dtsi
+++ b/arch/arm/dts/uniphier-ph1-sld3.dtsi
@@ -298,6 +298,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 985848a..61e0b45 100644
--- a/arch/arm/dts/uniphier-ph1-sld8.dtsi
+++ b/arch/arm/dts/uniphier-ph1-sld8.dtsi
@@ -220,6 +220,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 dc0def3..c3551fe 100644
--- a/arch/arm/dts/uniphier-proxstream2-gentil.dts
+++ b/arch/arm/dts/uniphier-proxstream2-gentil.dts
@@ -52,6 +52,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 21fad0c..12968bd 100644
--- a/arch/arm/dts/uniphier-proxstream2.dtsi
+++ b/arch/arm/dts/uniphier-proxstream2.dtsi
@@ -359,6 +359,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] 5+ messages in thread
* [U-Boot] [PATCH v4 0/3] UniPhier SD/eMMC controller driver
2016-02-18 10:52 [U-Boot] [PATCH v4 0/3] UniPhier SD/eMMC controller driver Masahiro Yamada
` (2 preceding siblings ...)
2016-02-18 10:52 ` [U-Boot] [PATCH v4 3/3] ARM: dts: uniphier: add SD/MMC host controller nodes Masahiro Yamada
@ 2016-02-26 15:41 ` Masahiro Yamada
3 siblings, 0 replies; 5+ messages in thread
From: Masahiro Yamada @ 2016-02-26 15:41 UTC (permalink / raw)
To: u-boot
2016-02-18 19:52 GMT+09:00 Masahiro Yamada <yamada.masahiro@socionext.com>:
>
>
> Changes in v4:
> - Add some comments about HOST_MODE register
> - Rename uniphier_sd_wait_irq() to uniphier_sd_wait_for_irq()
>
> Changes in v3:
> - Use dev_err/dev_dbg instead of pr_err/pr_debug
> - Tidy up uniphier_sd_set_ios()
> - Allow to use DMA even in SPL if the target address is DMA'able
>
> 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.
>
> 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
>
Series, applied to u-boot-uniphier.
--
Best Regards
Masahiro Yamada
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2016-02-26 15:41 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-18 10:52 [U-Boot] [PATCH v4 0/3] UniPhier SD/eMMC controller driver Masahiro Yamada
2016-02-18 10:52 ` [U-Boot] [PATCH v4 1/3] mmc: uniphier: add driver for UniPhier SD/MMC host controller Masahiro Yamada
2016-02-18 10:52 ` [U-Boot] [PATCH v4 2/3] ARM: uniphier: enable UniPhier SD/MMC host driver Masahiro Yamada
2016-02-18 10:52 ` [U-Boot] [PATCH v4 3/3] ARM: dts: uniphier: add SD/MMC host controller nodes Masahiro Yamada
2016-02-26 15:41 ` [U-Boot] [PATCH v4 0/3] UniPhier SD/eMMC controller driver 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.