xref: /openbmc/u-boot/drivers/mmc/uniphier-sd.c (revision 4b26d5e3aebbcabb427d80be808074308ed02ba1)
1a111bfbfSMasahiro Yamada /*
24e3d8406SMasahiro Yamada  * Copyright (C) 2016 Socionext Inc.
34e3d8406SMasahiro Yamada  *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
4a111bfbfSMasahiro Yamada  *
5a111bfbfSMasahiro Yamada  * SPDX-License-Identifier:	GPL-2.0+
6a111bfbfSMasahiro Yamada  */
7a111bfbfSMasahiro Yamada 
8a111bfbfSMasahiro Yamada #include <common.h>
9a111bfbfSMasahiro Yamada #include <clk.h>
10a111bfbfSMasahiro Yamada #include <fdtdec.h>
11a111bfbfSMasahiro Yamada #include <mmc.h>
129d922450SSimon Glass #include <dm.h>
13a111bfbfSMasahiro Yamada #include <linux/compat.h>
14b27af399SMasahiro Yamada #include <linux/dma-direction.h>
15a111bfbfSMasahiro Yamada #include <linux/io.h>
164f80501bSMasahiro Yamada #include <linux/sizes.h>
17a111bfbfSMasahiro Yamada #include <asm/unaligned.h>
18a111bfbfSMasahiro Yamada 
19a111bfbfSMasahiro Yamada DECLARE_GLOBAL_DATA_PTR;
20a111bfbfSMasahiro Yamada 
21a111bfbfSMasahiro Yamada #define UNIPHIER_SD_CMD			0x000	/* command */
22a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CMD_NOSTOP	BIT(14)	/* No automatic CMD12 issue */
23a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CMD_MULTI		BIT(13)	/* multiple block transfer */
24a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CMD_RD		BIT(12)	/* 1: read, 0: write */
25a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CMD_DATA		BIT(11)	/* data transfer */
26a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CMD_APP		BIT(6)	/* ACMD preceded by CMD55 */
27a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CMD_NORMAL	(0 << 8)/* auto-detect of resp-type */
28a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CMD_RSP_NONE	(3 << 8)/* response: none */
29a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CMD_RSP_R1	(4 << 8)/* response: R1, R5, R6, R7 */
30a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CMD_RSP_R1B	(5 << 8)/* response: R1b, R5b */
31a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CMD_RSP_R2	(6 << 8)/* response: R2 */
32a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CMD_RSP_R3	(7 << 8)/* response: R3, R4 */
33a111bfbfSMasahiro Yamada #define UNIPHIER_SD_ARG			0x008	/* command argument */
34a111bfbfSMasahiro Yamada #define UNIPHIER_SD_STOP		0x010	/* stop action control */
35a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_STOP_SEC		BIT(8)	/* use sector count */
36a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_STOP_STP		BIT(0)	/* issue CMD12 */
37a111bfbfSMasahiro Yamada #define UNIPHIER_SD_SECCNT		0x014	/* sector counter */
38a111bfbfSMasahiro Yamada #define UNIPHIER_SD_RSP10		0x018	/* response[39:8] */
39a111bfbfSMasahiro Yamada #define UNIPHIER_SD_RSP32		0x020	/* response[71:40] */
40a111bfbfSMasahiro Yamada #define UNIPHIER_SD_RSP54		0x028	/* response[103:72] */
41a111bfbfSMasahiro Yamada #define UNIPHIER_SD_RSP76		0x030	/* response[127:104] */
42a111bfbfSMasahiro Yamada #define UNIPHIER_SD_INFO1		0x038	/* IRQ status 1 */
43a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_INFO1_CD		BIT(5)	/* state of card detect */
44a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_INFO1_INSERT	BIT(4)	/* card inserted */
45a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_INFO1_REMOVE	BIT(3)	/* card removed */
46a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_INFO1_CMP		BIT(2)	/* data complete */
47a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_INFO1_RSP		BIT(0)	/* response complete */
48a111bfbfSMasahiro Yamada #define UNIPHIER_SD_INFO2		0x03c	/* IRQ status 2 */
49a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_INFO2_ERR_ILA	BIT(15)	/* illegal access err */
50a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_INFO2_CBSY	BIT(14)	/* command busy */
51a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_INFO2_BWE		BIT(9)	/* write buffer ready */
52a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_INFO2_BRE		BIT(8)	/* read buffer ready */
53a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_INFO2_DAT0	BIT(7)	/* SDDAT0 */
54a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_INFO2_ERR_RTO	BIT(6)	/* response time out */
55a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_INFO2_ERR_ILR	BIT(5)	/* illegal read err */
56a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_INFO2_ERR_ILW	BIT(4)	/* illegal write err */
57a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_INFO2_ERR_TO	BIT(3)	/* time out error */
58a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_INFO2_ERR_END	BIT(2)	/* END bit error */
59a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_INFO2_ERR_CRC	BIT(1)	/* CRC error */
60a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_INFO2_ERR_IDX	BIT(0)	/* cmd index error */
61a111bfbfSMasahiro Yamada #define UNIPHIER_SD_INFO1_MASK		0x040
62a111bfbfSMasahiro Yamada #define UNIPHIER_SD_INFO2_MASK		0x044
63a111bfbfSMasahiro Yamada #define UNIPHIER_SD_CLKCTL		0x048	/* clock divisor */
64a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CLKCTL_DIV_MASK	0x104ff
65a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CLKCTL_DIV1024	BIT(16)	/* SDCLK = CLK / 1024 */
66a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CLKCTL_DIV512	BIT(7)	/* SDCLK = CLK / 512 */
67a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CLKCTL_DIV256	BIT(6)	/* SDCLK = CLK / 256 */
68a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CLKCTL_DIV128	BIT(5)	/* SDCLK = CLK / 128 */
69a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CLKCTL_DIV64	BIT(4)	/* SDCLK = CLK / 64 */
70a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CLKCTL_DIV32	BIT(3)	/* SDCLK = CLK / 32 */
71a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CLKCTL_DIV16	BIT(2)	/* SDCLK = CLK / 16 */
72a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CLKCTL_DIV8	BIT(1)	/* SDCLK = CLK / 8 */
73a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CLKCTL_DIV4	BIT(0)	/* SDCLK = CLK / 4 */
74a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CLKCTL_DIV2	0	/* SDCLK = CLK / 2 */
75a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CLKCTL_DIV1	BIT(10)	/* SDCLK = CLK */
76a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CLKCTL_OFFEN	BIT(9)	/* stop SDCLK when unused */
77a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_CLKCTL_SCLKEN	BIT(8)	/* SDCLK output enable */
78a111bfbfSMasahiro Yamada #define UNIPHIER_SD_SIZE		0x04c	/* block size */
79a111bfbfSMasahiro Yamada #define UNIPHIER_SD_OPTION		0x050
80a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_OPTION_WIDTH_MASK	(5 << 13)
81a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_OPTION_WIDTH_1	(4 << 13)
82a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_OPTION_WIDTH_4	(0 << 13)
83a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_OPTION_WIDTH_8	(1 << 13)
84a111bfbfSMasahiro Yamada #define UNIPHIER_SD_BUF			0x060	/* read/write buffer */
85a111bfbfSMasahiro Yamada #define UNIPHIER_SD_EXTMODE		0x1b0
86a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_EXTMODE_DMA_EN	BIT(1)	/* transfer 1: DMA, 0: pio */
87a111bfbfSMasahiro Yamada #define UNIPHIER_SD_SOFT_RST		0x1c0
88a111bfbfSMasahiro Yamada #define UNIPHIER_SD_SOFT_RST_RSTX	BIT(0)	/* reset deassert */
89a111bfbfSMasahiro Yamada #define UNIPHIER_SD_VERSION		0x1c4	/* version register */
90a111bfbfSMasahiro Yamada #define UNIPHIER_SD_VERSION_IP		0xff	/* IP version */
91a111bfbfSMasahiro Yamada #define UNIPHIER_SD_HOST_MODE		0x1c8
92a111bfbfSMasahiro Yamada #define UNIPHIER_SD_IF_MODE		0x1cc
93a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_IF_MODE_DDR	BIT(0)	/* DDR mode */
94a111bfbfSMasahiro Yamada #define UNIPHIER_SD_VOLT		0x1e4	/* voltage switch */
95a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_VOLT_MASK		(3 << 0)
96a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_VOLT_OFF		(0 << 0)
97a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_VOLT_330		(1 << 0)/* 3.3V signal */
98a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_VOLT_180		(2 << 0)/* 1.8V signal */
99a111bfbfSMasahiro Yamada #define UNIPHIER_SD_DMA_MODE		0x410
100a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_DMA_MODE_DIR_RD	BIT(16)	/* 1: from device, 0: to dev */
101a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_DMA_MODE_ADDR_INC	BIT(0)	/* 1: address inc, 0: fixed */
102a111bfbfSMasahiro Yamada #define UNIPHIER_SD_DMA_CTL		0x414
103a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_DMA_CTL_START	BIT(0)	/* start DMA (auto cleared) */
104a111bfbfSMasahiro Yamada #define UNIPHIER_SD_DMA_RST		0x418
105a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_DMA_RST_RD	BIT(9)
106a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_DMA_RST_WR	BIT(8)
107a111bfbfSMasahiro Yamada #define UNIPHIER_SD_DMA_INFO1		0x420
108a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_DMA_INFO1_END_RD2	BIT(20)	/* DMA from device is complete*/
109a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_DMA_INFO1_END_RD	BIT(17)	/* Don't use!  Hardware bug */
110a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_DMA_INFO1_END_WR	BIT(16)	/* DMA to device is complete */
111a111bfbfSMasahiro Yamada #define UNIPHIER_SD_DMA_INFO1_MASK	0x424
112a111bfbfSMasahiro Yamada #define UNIPHIER_SD_DMA_INFO2		0x428
113a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_DMA_INFO2_ERR_RD	BIT(17)
114a111bfbfSMasahiro Yamada #define   UNIPHIER_SD_DMA_INFO2_ERR_WR	BIT(16)
115a111bfbfSMasahiro Yamada #define UNIPHIER_SD_DMA_INFO2_MASK	0x42c
116a111bfbfSMasahiro Yamada #define UNIPHIER_SD_DMA_ADDR_L		0x440
117a111bfbfSMasahiro Yamada #define UNIPHIER_SD_DMA_ADDR_H		0x444
118a111bfbfSMasahiro Yamada 
119a111bfbfSMasahiro Yamada /* alignment required by the DMA engine of this controller */
120a111bfbfSMasahiro Yamada #define UNIPHIER_SD_DMA_MINALIGN	0x10
121a111bfbfSMasahiro Yamada 
12214f47234SMasahiro Yamada struct uniphier_sd_plat {
123a111bfbfSMasahiro Yamada 	struct mmc_config cfg;
12414f47234SMasahiro Yamada 	struct mmc mmc;
12514f47234SMasahiro Yamada };
12614f47234SMasahiro Yamada 
12714f47234SMasahiro Yamada struct uniphier_sd_priv {
128a111bfbfSMasahiro Yamada 	void __iomem *regbase;
129a111bfbfSMasahiro Yamada 	unsigned long mclk;
130a111bfbfSMasahiro Yamada 	unsigned int version;
131a111bfbfSMasahiro Yamada 	u32 caps;
132a111bfbfSMasahiro Yamada #define UNIPHIER_SD_CAP_NONREMOVABLE	BIT(0)	/* Nonremovable e.g. eMMC */
133a111bfbfSMasahiro Yamada #define UNIPHIER_SD_CAP_DMA_INTERNAL	BIT(1)	/* have internal DMA engine */
134a111bfbfSMasahiro Yamada #define UNIPHIER_SD_CAP_DIV1024		BIT(2)	/* divisor 1024 is available */
1351c99f68eSMarek Vasut #define UNIPHIER_SD_CAP_64BIT		BIT(3)	/* Controller is 64bit */
136a111bfbfSMasahiro Yamada };
137a111bfbfSMasahiro Yamada 
138484d9db4SMarek Vasut static u64 uniphier_sd_readq(struct uniphier_sd_priv *priv, const u32 reg)
139484d9db4SMarek Vasut {
140484d9db4SMarek Vasut 	if (priv->caps & UNIPHIER_SD_CAP_64BIT)
141484d9db4SMarek Vasut 		return readq(priv->regbase + (reg << 1));
142484d9db4SMarek Vasut 	else
143484d9db4SMarek Vasut 		return readq(priv->regbase + reg);
144484d9db4SMarek Vasut }
145484d9db4SMarek Vasut 
146484d9db4SMarek Vasut static void uniphier_sd_writeq(struct uniphier_sd_priv *priv,
147484d9db4SMarek Vasut 			       const u64 val, const u32 reg)
148484d9db4SMarek Vasut {
149484d9db4SMarek Vasut 	if (priv->caps & UNIPHIER_SD_CAP_64BIT)
150484d9db4SMarek Vasut 		writeq(val, priv->regbase + (reg << 1));
151484d9db4SMarek Vasut 	else
152484d9db4SMarek Vasut 		writeq(val, priv->regbase + reg);
153484d9db4SMarek Vasut }
154484d9db4SMarek Vasut 
1553d7b1d1bSMarek Vasut static u32 uniphier_sd_readl(struct uniphier_sd_priv *priv, const u32 reg)
1563d7b1d1bSMarek Vasut {
1571c99f68eSMarek Vasut 	if (priv->caps & UNIPHIER_SD_CAP_64BIT)
1581c99f68eSMarek Vasut 		return readl(priv->regbase + (reg << 1));
1591c99f68eSMarek Vasut 	else
1603d7b1d1bSMarek Vasut 		return readl(priv->regbase + reg);
1613d7b1d1bSMarek Vasut }
1623d7b1d1bSMarek Vasut 
1633d7b1d1bSMarek Vasut static void uniphier_sd_writel(struct uniphier_sd_priv *priv,
1643d7b1d1bSMarek Vasut 			       const u32 val, const u32 reg)
1653d7b1d1bSMarek Vasut {
1661c99f68eSMarek Vasut 	if (priv->caps & UNIPHIER_SD_CAP_64BIT)
1671c99f68eSMarek Vasut 		writel(val, priv->regbase + (reg << 1));
1681c99f68eSMarek Vasut 	else
1693d7b1d1bSMarek Vasut 		writel(val, priv->regbase + reg);
1703d7b1d1bSMarek Vasut }
1713d7b1d1bSMarek Vasut 
172a111bfbfSMasahiro Yamada static dma_addr_t __dma_map_single(void *ptr, size_t size,
173a111bfbfSMasahiro Yamada 				   enum dma_data_direction dir)
174a111bfbfSMasahiro Yamada {
175a111bfbfSMasahiro Yamada 	unsigned long addr = (unsigned long)ptr;
176a111bfbfSMasahiro Yamada 
177a111bfbfSMasahiro Yamada 	if (dir == DMA_FROM_DEVICE)
178a111bfbfSMasahiro Yamada 		invalidate_dcache_range(addr, addr + size);
179a111bfbfSMasahiro Yamada 	else
180a111bfbfSMasahiro Yamada 		flush_dcache_range(addr, addr + size);
181a111bfbfSMasahiro Yamada 
182a111bfbfSMasahiro Yamada 	return addr;
183a111bfbfSMasahiro Yamada }
184a111bfbfSMasahiro Yamada 
185a111bfbfSMasahiro Yamada static void __dma_unmap_single(dma_addr_t addr, size_t size,
186a111bfbfSMasahiro Yamada 			       enum dma_data_direction dir)
187a111bfbfSMasahiro Yamada {
188a111bfbfSMasahiro Yamada 	if (dir != DMA_TO_DEVICE)
189a111bfbfSMasahiro Yamada 		invalidate_dcache_range(addr, addr + size);
190a111bfbfSMasahiro Yamada }
191a111bfbfSMasahiro Yamada 
1923937404fSMasahiro Yamada static int uniphier_sd_check_error(struct udevice *dev)
193a111bfbfSMasahiro Yamada {
1943937404fSMasahiro Yamada 	struct uniphier_sd_priv *priv = dev_get_priv(dev);
1953d7b1d1bSMarek Vasut 	u32 info2 = uniphier_sd_readl(priv, UNIPHIER_SD_INFO2);
196a111bfbfSMasahiro Yamada 
197a111bfbfSMasahiro Yamada 	if (info2 & UNIPHIER_SD_INFO2_ERR_RTO) {
198a111bfbfSMasahiro Yamada 		/*
199a111bfbfSMasahiro Yamada 		 * TIMEOUT must be returned for unsupported command.  Do not
200a111bfbfSMasahiro Yamada 		 * display error log since this might be a part of sequence to
201a111bfbfSMasahiro Yamada 		 * distinguish between SD and MMC.
202a111bfbfSMasahiro Yamada 		 */
203915ffa52SJaehoon Chung 		return -ETIMEDOUT;
204a111bfbfSMasahiro Yamada 	}
205a111bfbfSMasahiro Yamada 
206a111bfbfSMasahiro Yamada 	if (info2 & UNIPHIER_SD_INFO2_ERR_TO) {
2073937404fSMasahiro Yamada 		dev_err(dev, "timeout error\n");
208a111bfbfSMasahiro Yamada 		return -ETIMEDOUT;
209a111bfbfSMasahiro Yamada 	}
210a111bfbfSMasahiro Yamada 
211a111bfbfSMasahiro Yamada 	if (info2 & (UNIPHIER_SD_INFO2_ERR_END | UNIPHIER_SD_INFO2_ERR_CRC |
212a111bfbfSMasahiro Yamada 		     UNIPHIER_SD_INFO2_ERR_IDX)) {
2133937404fSMasahiro Yamada 		dev_err(dev, "communication out of sync\n");
214a111bfbfSMasahiro Yamada 		return -EILSEQ;
215a111bfbfSMasahiro Yamada 	}
216a111bfbfSMasahiro Yamada 
217a111bfbfSMasahiro Yamada 	if (info2 & (UNIPHIER_SD_INFO2_ERR_ILA | UNIPHIER_SD_INFO2_ERR_ILR |
218a111bfbfSMasahiro Yamada 		     UNIPHIER_SD_INFO2_ERR_ILW)) {
2193937404fSMasahiro Yamada 		dev_err(dev, "illegal access\n");
220a111bfbfSMasahiro Yamada 		return -EIO;
221a111bfbfSMasahiro Yamada 	}
222a111bfbfSMasahiro Yamada 
223a111bfbfSMasahiro Yamada 	return 0;
224a111bfbfSMasahiro Yamada }
225a111bfbfSMasahiro Yamada 
2263937404fSMasahiro Yamada static int uniphier_sd_wait_for_irq(struct udevice *dev, unsigned int reg,
2273937404fSMasahiro Yamada 				    u32 flag)
228a111bfbfSMasahiro Yamada {
2293937404fSMasahiro Yamada 	struct uniphier_sd_priv *priv = dev_get_priv(dev);
230a111bfbfSMasahiro Yamada 	long wait = 1000000;
231a111bfbfSMasahiro Yamada 	int ret;
232a111bfbfSMasahiro Yamada 
2333d7b1d1bSMarek Vasut 	while (!(uniphier_sd_readl(priv, reg) & flag)) {
234a111bfbfSMasahiro Yamada 		if (wait-- < 0) {
2353937404fSMasahiro Yamada 			dev_err(dev, "timeout\n");
236a111bfbfSMasahiro Yamada 			return -ETIMEDOUT;
237a111bfbfSMasahiro Yamada 		}
238a111bfbfSMasahiro Yamada 
2393937404fSMasahiro Yamada 		ret = uniphier_sd_check_error(dev);
240a111bfbfSMasahiro Yamada 		if (ret)
241a111bfbfSMasahiro Yamada 			return ret;
242a111bfbfSMasahiro Yamada 
243a111bfbfSMasahiro Yamada 		udelay(1);
244a111bfbfSMasahiro Yamada 	}
245a111bfbfSMasahiro Yamada 
246a111bfbfSMasahiro Yamada 	return 0;
247a111bfbfSMasahiro Yamada }
248a111bfbfSMasahiro Yamada 
2493937404fSMasahiro Yamada static int uniphier_sd_pio_read_one_block(struct udevice *dev, u32 **pbuf,
250a111bfbfSMasahiro Yamada 					  uint blocksize)
251a111bfbfSMasahiro Yamada {
2523937404fSMasahiro Yamada 	struct uniphier_sd_priv *priv = dev_get_priv(dev);
253a111bfbfSMasahiro Yamada 	int i, ret;
254a111bfbfSMasahiro Yamada 
255a111bfbfSMasahiro Yamada 	/* wait until the buffer is filled with data */
2563937404fSMasahiro Yamada 	ret = uniphier_sd_wait_for_irq(dev, UNIPHIER_SD_INFO2,
257a111bfbfSMasahiro Yamada 				       UNIPHIER_SD_INFO2_BRE);
258a111bfbfSMasahiro Yamada 	if (ret)
259a111bfbfSMasahiro Yamada 		return ret;
260a111bfbfSMasahiro Yamada 
261a111bfbfSMasahiro Yamada 	/*
262a111bfbfSMasahiro Yamada 	 * Clear the status flag _before_ read the buffer out because
263a111bfbfSMasahiro Yamada 	 * UNIPHIER_SD_INFO2_BRE is edge-triggered, not level-triggered.
264a111bfbfSMasahiro Yamada 	 */
2653d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO2);
266a111bfbfSMasahiro Yamada 
267a111bfbfSMasahiro Yamada 	if (likely(IS_ALIGNED((unsigned long)*pbuf, 4))) {
268484d9db4SMarek Vasut 		if (priv->caps & UNIPHIER_SD_CAP_64BIT) {
269484d9db4SMarek Vasut 			for (i = 0; i < blocksize / 8; i++) {
270484d9db4SMarek Vasut 				u64 data;
271484d9db4SMarek Vasut 				data = uniphier_sd_readq(priv,
272484d9db4SMarek Vasut 							 UNIPHIER_SD_BUF);
273484d9db4SMarek Vasut 				*(*pbuf)++ = data;
274484d9db4SMarek Vasut 				*(*pbuf)++ = data >> 32;
275484d9db4SMarek Vasut 			}
276a111bfbfSMasahiro Yamada 		} else {
277484d9db4SMarek Vasut 			for (i = 0; i < blocksize / 4; i++) {
278484d9db4SMarek Vasut 				u32 data;
279484d9db4SMarek Vasut 				data = uniphier_sd_readl(priv, UNIPHIER_SD_BUF);
280484d9db4SMarek Vasut 				*(*pbuf)++ = data;
281484d9db4SMarek Vasut 			}
282484d9db4SMarek Vasut 		}
283484d9db4SMarek Vasut 	} else {
284484d9db4SMarek Vasut 		if (priv->caps & UNIPHIER_SD_CAP_64BIT) {
285484d9db4SMarek Vasut 			for (i = 0; i < blocksize / 8; i++) {
286484d9db4SMarek Vasut 				u64 data;
287484d9db4SMarek Vasut 				data = uniphier_sd_readq(priv,
288484d9db4SMarek Vasut 							 UNIPHIER_SD_BUF);
289484d9db4SMarek Vasut 				put_unaligned(data, (*pbuf)++);
290484d9db4SMarek Vasut 				put_unaligned(data >> 32, (*pbuf)++);
291484d9db4SMarek Vasut 			}
292484d9db4SMarek Vasut 		} else {
293484d9db4SMarek Vasut 			for (i = 0; i < blocksize / 4; i++) {
294484d9db4SMarek Vasut 				u32 data;
295484d9db4SMarek Vasut 				data = uniphier_sd_readl(priv, UNIPHIER_SD_BUF);
296484d9db4SMarek Vasut 				put_unaligned(data, (*pbuf)++);
297484d9db4SMarek Vasut 			}
298484d9db4SMarek Vasut 		}
299a111bfbfSMasahiro Yamada 	}
300a111bfbfSMasahiro Yamada 
301a111bfbfSMasahiro Yamada 	return 0;
302a111bfbfSMasahiro Yamada }
303a111bfbfSMasahiro Yamada 
3043937404fSMasahiro Yamada static int uniphier_sd_pio_write_one_block(struct udevice *dev,
3053937404fSMasahiro Yamada 					   const u32 **pbuf, uint blocksize)
306a111bfbfSMasahiro Yamada {
3073937404fSMasahiro Yamada 	struct uniphier_sd_priv *priv = dev_get_priv(dev);
308a111bfbfSMasahiro Yamada 	int i, ret;
309a111bfbfSMasahiro Yamada 
310a111bfbfSMasahiro Yamada 	/* wait until the buffer becomes empty */
3113937404fSMasahiro Yamada 	ret = uniphier_sd_wait_for_irq(dev, UNIPHIER_SD_INFO2,
312a111bfbfSMasahiro Yamada 				       UNIPHIER_SD_INFO2_BWE);
313a111bfbfSMasahiro Yamada 	if (ret)
314a111bfbfSMasahiro Yamada 		return ret;
315a111bfbfSMasahiro Yamada 
3163d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO2);
317a111bfbfSMasahiro Yamada 
318a111bfbfSMasahiro Yamada 	if (likely(IS_ALIGNED((unsigned long)*pbuf, 4))) {
319484d9db4SMarek Vasut 		if (priv->caps & UNIPHIER_SD_CAP_64BIT) {
320484d9db4SMarek Vasut 			for (i = 0; i < blocksize / 8; i++) {
321484d9db4SMarek Vasut 				u64 data = *(*pbuf)++;
322484d9db4SMarek Vasut 				data |= (u64)*(*pbuf)++ << 32;
323484d9db4SMarek Vasut 				uniphier_sd_writeq(priv, data,
3243d7b1d1bSMarek Vasut 						   UNIPHIER_SD_BUF);
325a111bfbfSMasahiro Yamada 			}
326484d9db4SMarek Vasut 		} else {
327484d9db4SMarek Vasut 			for (i = 0; i < blocksize / 4; i++) {
328484d9db4SMarek Vasut 				uniphier_sd_writel(priv, *(*pbuf)++,
329484d9db4SMarek Vasut 						   UNIPHIER_SD_BUF);
330484d9db4SMarek Vasut 			}
331484d9db4SMarek Vasut 		}
332484d9db4SMarek Vasut 	} else {
333484d9db4SMarek Vasut 		if (priv->caps & UNIPHIER_SD_CAP_64BIT) {
334484d9db4SMarek Vasut 			for (i = 0; i < blocksize / 8; i++) {
335484d9db4SMarek Vasut 				u64 data = get_unaligned((*pbuf)++);
336484d9db4SMarek Vasut 				data |= (u64)get_unaligned((*pbuf)++) << 32;
337484d9db4SMarek Vasut 				uniphier_sd_writeq(priv, data,
338484d9db4SMarek Vasut 						   UNIPHIER_SD_BUF);
339484d9db4SMarek Vasut 			}
340484d9db4SMarek Vasut 		} else {
341484d9db4SMarek Vasut 			for (i = 0; i < blocksize / 4; i++) {
342484d9db4SMarek Vasut 				u32 data = get_unaligned((*pbuf)++);
343484d9db4SMarek Vasut 				uniphier_sd_writel(priv, data,
344484d9db4SMarek Vasut 						   UNIPHIER_SD_BUF);
345484d9db4SMarek Vasut 			}
346484d9db4SMarek Vasut 		}
347484d9db4SMarek Vasut 	}
348a111bfbfSMasahiro Yamada 
349a111bfbfSMasahiro Yamada 	return 0;
350a111bfbfSMasahiro Yamada }
351a111bfbfSMasahiro Yamada 
3523937404fSMasahiro Yamada static int uniphier_sd_pio_xfer(struct udevice *dev, struct mmc_data *data)
353a111bfbfSMasahiro Yamada {
354a111bfbfSMasahiro Yamada 	u32 *dest = (u32 *)data->dest;
355a111bfbfSMasahiro Yamada 	const u32 *src = (const u32 *)data->src;
356a111bfbfSMasahiro Yamada 	int i, ret;
357a111bfbfSMasahiro Yamada 
358a111bfbfSMasahiro Yamada 	for (i = 0; i < data->blocks; i++) {
359a111bfbfSMasahiro Yamada 		if (data->flags & MMC_DATA_READ)
3603937404fSMasahiro Yamada 			ret = uniphier_sd_pio_read_one_block(dev, &dest,
361a111bfbfSMasahiro Yamada 							     data->blocksize);
362a111bfbfSMasahiro Yamada 		else
3633937404fSMasahiro Yamada 			ret = uniphier_sd_pio_write_one_block(dev, &src,
364a111bfbfSMasahiro Yamada 							      data->blocksize);
365a111bfbfSMasahiro Yamada 		if (ret)
366a111bfbfSMasahiro Yamada 			return ret;
367a111bfbfSMasahiro Yamada 	}
368a111bfbfSMasahiro Yamada 
369a111bfbfSMasahiro Yamada 	return 0;
370a111bfbfSMasahiro Yamada }
371a111bfbfSMasahiro Yamada 
372a111bfbfSMasahiro Yamada static void uniphier_sd_dma_start(struct uniphier_sd_priv *priv,
373a111bfbfSMasahiro Yamada 				  dma_addr_t dma_addr)
374a111bfbfSMasahiro Yamada {
375a111bfbfSMasahiro Yamada 	u32 tmp;
376a111bfbfSMasahiro Yamada 
3773d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, 0, UNIPHIER_SD_DMA_INFO1);
3783d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, 0, UNIPHIER_SD_DMA_INFO2);
379a111bfbfSMasahiro Yamada 
380a111bfbfSMasahiro Yamada 	/* enable DMA */
3813d7b1d1bSMarek Vasut 	tmp = uniphier_sd_readl(priv, UNIPHIER_SD_EXTMODE);
382a111bfbfSMasahiro Yamada 	tmp |= UNIPHIER_SD_EXTMODE_DMA_EN;
3833d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_EXTMODE);
384a111bfbfSMasahiro Yamada 
3853d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, dma_addr & U32_MAX, UNIPHIER_SD_DMA_ADDR_L);
386a111bfbfSMasahiro Yamada 
387a111bfbfSMasahiro Yamada 	/* suppress the warning "right shift count >= width of type" */
388a111bfbfSMasahiro Yamada 	dma_addr >>= min_t(int, 32, 8 * sizeof(dma_addr));
389a111bfbfSMasahiro Yamada 
3903d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, dma_addr & U32_MAX, UNIPHIER_SD_DMA_ADDR_H);
391a111bfbfSMasahiro Yamada 
3923d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, UNIPHIER_SD_DMA_CTL_START, UNIPHIER_SD_DMA_CTL);
393a111bfbfSMasahiro Yamada }
394a111bfbfSMasahiro Yamada 
3953937404fSMasahiro Yamada static int uniphier_sd_dma_wait_for_irq(struct udevice *dev, u32 flag,
396a111bfbfSMasahiro Yamada 					unsigned int blocks)
397a111bfbfSMasahiro Yamada {
3983937404fSMasahiro Yamada 	struct uniphier_sd_priv *priv = dev_get_priv(dev);
399a111bfbfSMasahiro Yamada 	long wait = 1000000 + 10 * blocks;
400a111bfbfSMasahiro Yamada 
4013d7b1d1bSMarek Vasut 	while (!(uniphier_sd_readl(priv, UNIPHIER_SD_DMA_INFO1) & flag)) {
402a111bfbfSMasahiro Yamada 		if (wait-- < 0) {
4033937404fSMasahiro Yamada 			dev_err(dev, "timeout during DMA\n");
404a111bfbfSMasahiro Yamada 			return -ETIMEDOUT;
405a111bfbfSMasahiro Yamada 		}
406a111bfbfSMasahiro Yamada 
407a111bfbfSMasahiro Yamada 		udelay(10);
408a111bfbfSMasahiro Yamada 	}
409a111bfbfSMasahiro Yamada 
4103d7b1d1bSMarek Vasut 	if (uniphier_sd_readl(priv, UNIPHIER_SD_DMA_INFO2)) {
4113937404fSMasahiro Yamada 		dev_err(dev, "error during DMA\n");
412a111bfbfSMasahiro Yamada 		return -EIO;
413a111bfbfSMasahiro Yamada 	}
414a111bfbfSMasahiro Yamada 
415a111bfbfSMasahiro Yamada 	return 0;
416a111bfbfSMasahiro Yamada }
417a111bfbfSMasahiro Yamada 
4183937404fSMasahiro Yamada static int uniphier_sd_dma_xfer(struct udevice *dev, struct mmc_data *data)
419a111bfbfSMasahiro Yamada {
4203937404fSMasahiro Yamada 	struct uniphier_sd_priv *priv = dev_get_priv(dev);
421a111bfbfSMasahiro Yamada 	size_t len = data->blocks * data->blocksize;
422a111bfbfSMasahiro Yamada 	void *buf;
423a111bfbfSMasahiro Yamada 	enum dma_data_direction dir;
424a111bfbfSMasahiro Yamada 	dma_addr_t dma_addr;
425a111bfbfSMasahiro Yamada 	u32 poll_flag, tmp;
426a111bfbfSMasahiro Yamada 	int ret;
427a111bfbfSMasahiro Yamada 
4283d7b1d1bSMarek Vasut 	tmp = uniphier_sd_readl(priv, UNIPHIER_SD_DMA_MODE);
429a111bfbfSMasahiro Yamada 
430a111bfbfSMasahiro Yamada 	if (data->flags & MMC_DATA_READ) {
431a111bfbfSMasahiro Yamada 		buf = data->dest;
432a111bfbfSMasahiro Yamada 		dir = DMA_FROM_DEVICE;
433a111bfbfSMasahiro Yamada 		poll_flag = UNIPHIER_SD_DMA_INFO1_END_RD2;
434a111bfbfSMasahiro Yamada 		tmp |= UNIPHIER_SD_DMA_MODE_DIR_RD;
435a111bfbfSMasahiro Yamada 	} else {
436a111bfbfSMasahiro Yamada 		buf = (void *)data->src;
437a111bfbfSMasahiro Yamada 		dir = DMA_TO_DEVICE;
438a111bfbfSMasahiro Yamada 		poll_flag = UNIPHIER_SD_DMA_INFO1_END_WR;
439a111bfbfSMasahiro Yamada 		tmp &= ~UNIPHIER_SD_DMA_MODE_DIR_RD;
440a111bfbfSMasahiro Yamada 	}
441a111bfbfSMasahiro Yamada 
4423d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_DMA_MODE);
443a111bfbfSMasahiro Yamada 
444a111bfbfSMasahiro Yamada 	dma_addr = __dma_map_single(buf, len, dir);
445a111bfbfSMasahiro Yamada 
446a111bfbfSMasahiro Yamada 	uniphier_sd_dma_start(priv, dma_addr);
447a111bfbfSMasahiro Yamada 
4483937404fSMasahiro Yamada 	ret = uniphier_sd_dma_wait_for_irq(dev, poll_flag, data->blocks);
449a111bfbfSMasahiro Yamada 
450a111bfbfSMasahiro Yamada 	__dma_unmap_single(dma_addr, len, dir);
451a111bfbfSMasahiro Yamada 
452a111bfbfSMasahiro Yamada 	return ret;
453a111bfbfSMasahiro Yamada }
454a111bfbfSMasahiro Yamada 
455a111bfbfSMasahiro Yamada /* check if the address is DMA'able */
456a111bfbfSMasahiro Yamada static bool uniphier_sd_addr_is_dmaable(unsigned long addr)
457a111bfbfSMasahiro Yamada {
458a111bfbfSMasahiro Yamada 	if (!IS_ALIGNED(addr, UNIPHIER_SD_DMA_MINALIGN))
459a111bfbfSMasahiro Yamada 		return false;
460a111bfbfSMasahiro Yamada 
461a111bfbfSMasahiro Yamada #if defined(CONFIG_ARCH_UNIPHIER) && !defined(CONFIG_ARM64) && \
462a111bfbfSMasahiro Yamada 	defined(CONFIG_SPL_BUILD)
463a111bfbfSMasahiro Yamada 	/*
464a111bfbfSMasahiro Yamada 	 * For UniPhier ARMv7 SoCs, the stack is allocated in the locked ways
465a111bfbfSMasahiro Yamada 	 * of L2, which is unreachable from the DMA engine.
466a111bfbfSMasahiro Yamada 	 */
467a111bfbfSMasahiro Yamada 	if (addr < CONFIG_SPL_STACK)
468a111bfbfSMasahiro Yamada 		return false;
469a111bfbfSMasahiro Yamada #endif
470a111bfbfSMasahiro Yamada 
471a111bfbfSMasahiro Yamada 	return true;
472a111bfbfSMasahiro Yamada }
473a111bfbfSMasahiro Yamada 
4743937404fSMasahiro Yamada static int uniphier_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
475a111bfbfSMasahiro Yamada 				struct mmc_data *data)
476a111bfbfSMasahiro Yamada {
4773937404fSMasahiro Yamada 	struct uniphier_sd_priv *priv = dev_get_priv(dev);
478a111bfbfSMasahiro Yamada 	int ret;
479a111bfbfSMasahiro Yamada 	u32 tmp;
480a111bfbfSMasahiro Yamada 
4813d7b1d1bSMarek Vasut 	if (uniphier_sd_readl(priv, UNIPHIER_SD_INFO2) & UNIPHIER_SD_INFO2_CBSY) {
4823937404fSMasahiro Yamada 		dev_err(dev, "command busy\n");
483a111bfbfSMasahiro Yamada 		return -EBUSY;
484a111bfbfSMasahiro Yamada 	}
485a111bfbfSMasahiro Yamada 
486a111bfbfSMasahiro Yamada 	/* clear all status flags */
4873d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO1);
4883d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO2);
489a111bfbfSMasahiro Yamada 
490a111bfbfSMasahiro Yamada 	/* disable DMA once */
4913d7b1d1bSMarek Vasut 	tmp = uniphier_sd_readl(priv, UNIPHIER_SD_EXTMODE);
492a111bfbfSMasahiro Yamada 	tmp &= ~UNIPHIER_SD_EXTMODE_DMA_EN;
4933d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_EXTMODE);
494a111bfbfSMasahiro Yamada 
4953d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, cmd->cmdarg, UNIPHIER_SD_ARG);
496a111bfbfSMasahiro Yamada 
497a111bfbfSMasahiro Yamada 	tmp = cmd->cmdidx;
498a111bfbfSMasahiro Yamada 
499a111bfbfSMasahiro Yamada 	if (data) {
5003d7b1d1bSMarek Vasut 		uniphier_sd_writel(priv, data->blocksize, UNIPHIER_SD_SIZE);
5013d7b1d1bSMarek Vasut 		uniphier_sd_writel(priv, data->blocks, UNIPHIER_SD_SECCNT);
502a111bfbfSMasahiro Yamada 
503a111bfbfSMasahiro Yamada 		/* Do not send CMD12 automatically */
504a111bfbfSMasahiro Yamada 		tmp |= UNIPHIER_SD_CMD_NOSTOP | UNIPHIER_SD_CMD_DATA;
505a111bfbfSMasahiro Yamada 
506a111bfbfSMasahiro Yamada 		if (data->blocks > 1)
507a111bfbfSMasahiro Yamada 			tmp |= UNIPHIER_SD_CMD_MULTI;
508a111bfbfSMasahiro Yamada 
509a111bfbfSMasahiro Yamada 		if (data->flags & MMC_DATA_READ)
510a111bfbfSMasahiro Yamada 			tmp |= UNIPHIER_SD_CMD_RD;
511a111bfbfSMasahiro Yamada 	}
512a111bfbfSMasahiro Yamada 
513a111bfbfSMasahiro Yamada 	/*
514a111bfbfSMasahiro Yamada 	 * Do not use the response type auto-detection on this hardware.
515a111bfbfSMasahiro Yamada 	 * CMD8, for example, has different response types on SD and eMMC,
516a111bfbfSMasahiro Yamada 	 * while this controller always assumes the response type for SD.
517a111bfbfSMasahiro Yamada 	 * Set the response type manually.
518a111bfbfSMasahiro Yamada 	 */
519a111bfbfSMasahiro Yamada 	switch (cmd->resp_type) {
520a111bfbfSMasahiro Yamada 	case MMC_RSP_NONE:
521a111bfbfSMasahiro Yamada 		tmp |= UNIPHIER_SD_CMD_RSP_NONE;
522a111bfbfSMasahiro Yamada 		break;
523a111bfbfSMasahiro Yamada 	case MMC_RSP_R1:
524a111bfbfSMasahiro Yamada 		tmp |= UNIPHIER_SD_CMD_RSP_R1;
525a111bfbfSMasahiro Yamada 		break;
526a111bfbfSMasahiro Yamada 	case MMC_RSP_R1b:
527a111bfbfSMasahiro Yamada 		tmp |= UNIPHIER_SD_CMD_RSP_R1B;
528a111bfbfSMasahiro Yamada 		break;
529a111bfbfSMasahiro Yamada 	case MMC_RSP_R2:
530a111bfbfSMasahiro Yamada 		tmp |= UNIPHIER_SD_CMD_RSP_R2;
531a111bfbfSMasahiro Yamada 		break;
532a111bfbfSMasahiro Yamada 	case MMC_RSP_R3:
533a111bfbfSMasahiro Yamada 		tmp |= UNIPHIER_SD_CMD_RSP_R3;
534a111bfbfSMasahiro Yamada 		break;
535a111bfbfSMasahiro Yamada 	default:
5363937404fSMasahiro Yamada 		dev_err(dev, "unknown response type\n");
537a111bfbfSMasahiro Yamada 		return -EINVAL;
538a111bfbfSMasahiro Yamada 	}
539a111bfbfSMasahiro Yamada 
5403937404fSMasahiro Yamada 	dev_dbg(dev, "sending CMD%d (SD_CMD=%08x, SD_ARG=%08x)\n",
541a111bfbfSMasahiro Yamada 		cmd->cmdidx, tmp, cmd->cmdarg);
5423d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_CMD);
543a111bfbfSMasahiro Yamada 
5443937404fSMasahiro Yamada 	ret = uniphier_sd_wait_for_irq(dev, UNIPHIER_SD_INFO1,
545a111bfbfSMasahiro Yamada 				       UNIPHIER_SD_INFO1_RSP);
546a111bfbfSMasahiro Yamada 	if (ret)
547a111bfbfSMasahiro Yamada 		return ret;
548a111bfbfSMasahiro Yamada 
549a111bfbfSMasahiro Yamada 	if (cmd->resp_type & MMC_RSP_136) {
5503d7b1d1bSMarek Vasut 		u32 rsp_127_104 = uniphier_sd_readl(priv, UNIPHIER_SD_RSP76);
5513d7b1d1bSMarek Vasut 		u32 rsp_103_72 = uniphier_sd_readl(priv, UNIPHIER_SD_RSP54);
5523d7b1d1bSMarek Vasut 		u32 rsp_71_40 = uniphier_sd_readl(priv, UNIPHIER_SD_RSP32);
5533d7b1d1bSMarek Vasut 		u32 rsp_39_8 = uniphier_sd_readl(priv, UNIPHIER_SD_RSP10);
554a111bfbfSMasahiro Yamada 
555ac5efc35SMarek Vasut 		cmd->response[0] = ((rsp_127_104 & 0x00ffffff) << 8) |
556ac5efc35SMarek Vasut 				   ((rsp_103_72  & 0xff000000) >> 24);
557ac5efc35SMarek Vasut 		cmd->response[1] = ((rsp_103_72  & 0x00ffffff) << 8) |
558ac5efc35SMarek Vasut 				   ((rsp_71_40   & 0xff000000) >> 24);
559ac5efc35SMarek Vasut 		cmd->response[2] = ((rsp_71_40   & 0x00ffffff) << 8) |
560ac5efc35SMarek Vasut 				   ((rsp_39_8    & 0xff000000) >> 24);
561a111bfbfSMasahiro Yamada 		cmd->response[3] = (rsp_39_8     & 0xffffff)   << 8;
562a111bfbfSMasahiro Yamada 	} else {
563a111bfbfSMasahiro Yamada 		/* bit 39-8 */
5643d7b1d1bSMarek Vasut 		cmd->response[0] = uniphier_sd_readl(priv, UNIPHIER_SD_RSP10);
565a111bfbfSMasahiro Yamada 	}
566a111bfbfSMasahiro Yamada 
567a111bfbfSMasahiro Yamada 	if (data) {
568a111bfbfSMasahiro Yamada 		/* use DMA if the HW supports it and the buffer is aligned */
569a111bfbfSMasahiro Yamada 		if (priv->caps & UNIPHIER_SD_CAP_DMA_INTERNAL &&
570a111bfbfSMasahiro Yamada 		    uniphier_sd_addr_is_dmaable((long)data->src))
5713937404fSMasahiro Yamada 			ret = uniphier_sd_dma_xfer(dev, data);
572a111bfbfSMasahiro Yamada 		else
5733937404fSMasahiro Yamada 			ret = uniphier_sd_pio_xfer(dev, data);
574a111bfbfSMasahiro Yamada 
5753937404fSMasahiro Yamada 		ret = uniphier_sd_wait_for_irq(dev, UNIPHIER_SD_INFO1,
576a111bfbfSMasahiro Yamada 					       UNIPHIER_SD_INFO1_CMP);
577a111bfbfSMasahiro Yamada 		if (ret)
578a111bfbfSMasahiro Yamada 			return ret;
579a111bfbfSMasahiro Yamada 	}
580a111bfbfSMasahiro Yamada 
581a111bfbfSMasahiro Yamada 	return ret;
582a111bfbfSMasahiro Yamada }
583a111bfbfSMasahiro Yamada 
5848be12e28SMasahiro Yamada static int uniphier_sd_set_bus_width(struct uniphier_sd_priv *priv,
585a111bfbfSMasahiro Yamada 				     struct mmc *mmc)
586a111bfbfSMasahiro Yamada {
587a111bfbfSMasahiro Yamada 	u32 val, tmp;
588a111bfbfSMasahiro Yamada 
589a111bfbfSMasahiro Yamada 	switch (mmc->bus_width) {
590a111bfbfSMasahiro Yamada 	case 1:
591a111bfbfSMasahiro Yamada 		val = UNIPHIER_SD_OPTION_WIDTH_1;
592a111bfbfSMasahiro Yamada 		break;
593a111bfbfSMasahiro Yamada 	case 4:
594a111bfbfSMasahiro Yamada 		val = UNIPHIER_SD_OPTION_WIDTH_4;
595a111bfbfSMasahiro Yamada 		break;
596a111bfbfSMasahiro Yamada 	case 8:
597a111bfbfSMasahiro Yamada 		val = UNIPHIER_SD_OPTION_WIDTH_8;
598a111bfbfSMasahiro Yamada 		break;
599a111bfbfSMasahiro Yamada 	default:
6008be12e28SMasahiro Yamada 		return -EINVAL;
601a111bfbfSMasahiro Yamada 	}
602a111bfbfSMasahiro Yamada 
6033d7b1d1bSMarek Vasut 	tmp = uniphier_sd_readl(priv, UNIPHIER_SD_OPTION);
604a111bfbfSMasahiro Yamada 	tmp &= ~UNIPHIER_SD_OPTION_WIDTH_MASK;
605a111bfbfSMasahiro Yamada 	tmp |= val;
6063d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_OPTION);
6078be12e28SMasahiro Yamada 
6088be12e28SMasahiro Yamada 	return 0;
609a111bfbfSMasahiro Yamada }
610a111bfbfSMasahiro Yamada 
611a111bfbfSMasahiro Yamada static void uniphier_sd_set_ddr_mode(struct uniphier_sd_priv *priv,
612a111bfbfSMasahiro Yamada 				     struct mmc *mmc)
613a111bfbfSMasahiro Yamada {
614a111bfbfSMasahiro Yamada 	u32 tmp;
615a111bfbfSMasahiro Yamada 
6163d7b1d1bSMarek Vasut 	tmp = uniphier_sd_readl(priv, UNIPHIER_SD_IF_MODE);
617a111bfbfSMasahiro Yamada 	if (mmc->ddr_mode)
618a111bfbfSMasahiro Yamada 		tmp |= UNIPHIER_SD_IF_MODE_DDR;
619a111bfbfSMasahiro Yamada 	else
620a111bfbfSMasahiro Yamada 		tmp &= ~UNIPHIER_SD_IF_MODE_DDR;
6213d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_IF_MODE);
622a111bfbfSMasahiro Yamada }
623a111bfbfSMasahiro Yamada 
624a111bfbfSMasahiro Yamada static void uniphier_sd_set_clk_rate(struct uniphier_sd_priv *priv,
625a111bfbfSMasahiro Yamada 				     struct mmc *mmc)
626a111bfbfSMasahiro Yamada {
627a111bfbfSMasahiro Yamada 	unsigned int divisor;
628a111bfbfSMasahiro Yamada 	u32 val, tmp;
629a111bfbfSMasahiro Yamada 
630a111bfbfSMasahiro Yamada 	if (!mmc->clock)
631a111bfbfSMasahiro Yamada 		return;
632a111bfbfSMasahiro Yamada 
633a111bfbfSMasahiro Yamada 	divisor = DIV_ROUND_UP(priv->mclk, mmc->clock);
634a111bfbfSMasahiro Yamada 
635a111bfbfSMasahiro Yamada 	if (divisor <= 1)
636a111bfbfSMasahiro Yamada 		val = UNIPHIER_SD_CLKCTL_DIV1;
637a111bfbfSMasahiro Yamada 	else if (divisor <= 2)
638a111bfbfSMasahiro Yamada 		val = UNIPHIER_SD_CLKCTL_DIV2;
639a111bfbfSMasahiro Yamada 	else if (divisor <= 4)
640a111bfbfSMasahiro Yamada 		val = UNIPHIER_SD_CLKCTL_DIV4;
641a111bfbfSMasahiro Yamada 	else if (divisor <= 8)
642a111bfbfSMasahiro Yamada 		val = UNIPHIER_SD_CLKCTL_DIV8;
643a111bfbfSMasahiro Yamada 	else if (divisor <= 16)
644a111bfbfSMasahiro Yamada 		val = UNIPHIER_SD_CLKCTL_DIV16;
645a111bfbfSMasahiro Yamada 	else if (divisor <= 32)
646a111bfbfSMasahiro Yamada 		val = UNIPHIER_SD_CLKCTL_DIV32;
647a111bfbfSMasahiro Yamada 	else if (divisor <= 64)
648a111bfbfSMasahiro Yamada 		val = UNIPHIER_SD_CLKCTL_DIV64;
649a111bfbfSMasahiro Yamada 	else if (divisor <= 128)
650a111bfbfSMasahiro Yamada 		val = UNIPHIER_SD_CLKCTL_DIV128;
651a111bfbfSMasahiro Yamada 	else if (divisor <= 256)
652a111bfbfSMasahiro Yamada 		val = UNIPHIER_SD_CLKCTL_DIV256;
653a111bfbfSMasahiro Yamada 	else if (divisor <= 512 || !(priv->caps & UNIPHIER_SD_CAP_DIV1024))
654a111bfbfSMasahiro Yamada 		val = UNIPHIER_SD_CLKCTL_DIV512;
655a111bfbfSMasahiro Yamada 	else
656a111bfbfSMasahiro Yamada 		val = UNIPHIER_SD_CLKCTL_DIV1024;
657a111bfbfSMasahiro Yamada 
6583d7b1d1bSMarek Vasut 	tmp = uniphier_sd_readl(priv, UNIPHIER_SD_CLKCTL);
6594a89a24eSMasahiro Yamada 	if (tmp & UNIPHIER_SD_CLKCTL_SCLKEN &&
6604a89a24eSMasahiro Yamada 	    (tmp & UNIPHIER_SD_CLKCTL_DIV_MASK) == val)
6614a89a24eSMasahiro Yamada 		return;
662a111bfbfSMasahiro Yamada 
663a111bfbfSMasahiro Yamada 	/* stop the clock before changing its rate to avoid a glitch signal */
664a111bfbfSMasahiro Yamada 	tmp &= ~UNIPHIER_SD_CLKCTL_SCLKEN;
6653d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_CLKCTL);
666a111bfbfSMasahiro Yamada 
667a111bfbfSMasahiro Yamada 	tmp &= ~UNIPHIER_SD_CLKCTL_DIV_MASK;
668a111bfbfSMasahiro Yamada 	tmp |= val | UNIPHIER_SD_CLKCTL_OFFEN;
6693d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_CLKCTL);
670a111bfbfSMasahiro Yamada 
671a111bfbfSMasahiro Yamada 	tmp |= UNIPHIER_SD_CLKCTL_SCLKEN;
6723d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_CLKCTL);
6734a89a24eSMasahiro Yamada 
6744a89a24eSMasahiro Yamada 	udelay(1000);
675a111bfbfSMasahiro Yamada }
676a111bfbfSMasahiro Yamada 
6773937404fSMasahiro Yamada static int uniphier_sd_set_ios(struct udevice *dev)
678a111bfbfSMasahiro Yamada {
6793937404fSMasahiro Yamada 	struct uniphier_sd_priv *priv = dev_get_priv(dev);
6803937404fSMasahiro Yamada 	struct mmc *mmc = mmc_get_mmc_dev(dev);
6818be12e28SMasahiro Yamada 	int ret;
682a111bfbfSMasahiro Yamada 
6833937404fSMasahiro Yamada 	dev_dbg(dev, "clock %uHz, DDRmode %d, width %u\n",
684a111bfbfSMasahiro Yamada 		mmc->clock, mmc->ddr_mode, mmc->bus_width);
685a111bfbfSMasahiro Yamada 
6868be12e28SMasahiro Yamada 	ret = uniphier_sd_set_bus_width(priv, mmc);
6878be12e28SMasahiro Yamada 	if (ret)
6888be12e28SMasahiro Yamada 		return ret;
689a111bfbfSMasahiro Yamada 	uniphier_sd_set_ddr_mode(priv, mmc);
690a111bfbfSMasahiro Yamada 	uniphier_sd_set_clk_rate(priv, mmc);
691a111bfbfSMasahiro Yamada 
6923937404fSMasahiro Yamada 	return 0;
693a111bfbfSMasahiro Yamada }
694a111bfbfSMasahiro Yamada 
6954eb00846SMasahiro Yamada static int uniphier_sd_get_cd(struct udevice *dev)
6964eb00846SMasahiro Yamada {
6974eb00846SMasahiro Yamada 	struct uniphier_sd_priv *priv = dev_get_priv(dev);
6984eb00846SMasahiro Yamada 
6994eb00846SMasahiro Yamada 	if (priv->caps & UNIPHIER_SD_CAP_NONREMOVABLE)
7004eb00846SMasahiro Yamada 		return 1;
7014eb00846SMasahiro Yamada 
7023d7b1d1bSMarek Vasut 	return !!(uniphier_sd_readl(priv, UNIPHIER_SD_INFO1) &
7034eb00846SMasahiro Yamada 		  UNIPHIER_SD_INFO1_CD);
7044eb00846SMasahiro Yamada }
7054eb00846SMasahiro Yamada 
7064eb00846SMasahiro Yamada static const struct dm_mmc_ops uniphier_sd_ops = {
7074eb00846SMasahiro Yamada 	.send_cmd = uniphier_sd_send_cmd,
7084eb00846SMasahiro Yamada 	.set_ios = uniphier_sd_set_ios,
7094eb00846SMasahiro Yamada 	.get_cd = uniphier_sd_get_cd,
7104eb00846SMasahiro Yamada };
7114eb00846SMasahiro Yamada 
7124eb00846SMasahiro Yamada static void uniphier_sd_host_init(struct uniphier_sd_priv *priv)
713a111bfbfSMasahiro Yamada {
714a111bfbfSMasahiro Yamada 	u32 tmp;
715a111bfbfSMasahiro Yamada 
716a111bfbfSMasahiro Yamada 	/* soft reset of the host */
7173d7b1d1bSMarek Vasut 	tmp = uniphier_sd_readl(priv, UNIPHIER_SD_SOFT_RST);
718a111bfbfSMasahiro Yamada 	tmp &= ~UNIPHIER_SD_SOFT_RST_RSTX;
7193d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_SOFT_RST);
720a111bfbfSMasahiro Yamada 	tmp |= UNIPHIER_SD_SOFT_RST_RSTX;
7213d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_SOFT_RST);
722a111bfbfSMasahiro Yamada 
723a111bfbfSMasahiro Yamada 	/* FIXME: implement eMMC hw_reset */
724a111bfbfSMasahiro Yamada 
7253d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, UNIPHIER_SD_STOP_SEC, UNIPHIER_SD_STOP);
726a111bfbfSMasahiro Yamada 
727a111bfbfSMasahiro Yamada 	/*
728a111bfbfSMasahiro Yamada 	 * Connected to 32bit AXI.
729a111bfbfSMasahiro Yamada 	 * This register dropped backward compatibility at version 0x10.
730a111bfbfSMasahiro Yamada 	 * Write an appropriate value depending on the IP version.
731a111bfbfSMasahiro Yamada 	 */
7323d7b1d1bSMarek Vasut 	uniphier_sd_writel(priv, priv->version >= 0x10 ? 0x00000101 : 0x00000000,
7333d7b1d1bSMarek Vasut 			   UNIPHIER_SD_HOST_MODE);
734a111bfbfSMasahiro Yamada 
735a111bfbfSMasahiro Yamada 	if (priv->caps & UNIPHIER_SD_CAP_DMA_INTERNAL) {
7363d7b1d1bSMarek Vasut 		tmp = uniphier_sd_readl(priv, UNIPHIER_SD_DMA_MODE);
737a111bfbfSMasahiro Yamada 		tmp |= UNIPHIER_SD_DMA_MODE_ADDR_INC;
7383d7b1d1bSMarek Vasut 		uniphier_sd_writel(priv, tmp, UNIPHIER_SD_DMA_MODE);
739a111bfbfSMasahiro Yamada 	}
740a111bfbfSMasahiro Yamada }
741a111bfbfSMasahiro Yamada 
74214f47234SMasahiro Yamada static int uniphier_sd_bind(struct udevice *dev)
74314f47234SMasahiro Yamada {
74414f47234SMasahiro Yamada 	struct uniphier_sd_plat *plat = dev_get_platdata(dev);
74514f47234SMasahiro Yamada 
74614f47234SMasahiro Yamada 	return mmc_bind(dev, &plat->mmc, &plat->cfg);
74714f47234SMasahiro Yamada }
74814f47234SMasahiro Yamada 
7494a70d262SMasahiro Yamada static int uniphier_sd_probe(struct udevice *dev)
750a111bfbfSMasahiro Yamada {
75114f47234SMasahiro Yamada 	struct uniphier_sd_plat *plat = dev_get_platdata(dev);
752a111bfbfSMasahiro Yamada 	struct uniphier_sd_priv *priv = dev_get_priv(dev);
753a111bfbfSMasahiro Yamada 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
754*4b26d5e3SMarek Vasut 	const u32 quirks = dev_get_driver_data(dev);
755a111bfbfSMasahiro Yamada 	fdt_addr_t base;
756135aa950SStephen Warren 	struct clk clk;
757a111bfbfSMasahiro Yamada 	int ret;
758a111bfbfSMasahiro Yamada 
759a821c4afSSimon Glass 	base = devfdt_get_addr(dev);
7604f80501bSMasahiro Yamada 	if (base == FDT_ADDR_T_NONE)
7614f80501bSMasahiro Yamada 		return -EINVAL;
7624f80501bSMasahiro Yamada 
7634e3d8406SMasahiro Yamada 	priv->regbase = devm_ioremap(dev, base, SZ_2K);
764a111bfbfSMasahiro Yamada 	if (!priv->regbase)
765a111bfbfSMasahiro Yamada 		return -ENOMEM;
766a111bfbfSMasahiro Yamada 
767135aa950SStephen Warren 	ret = clk_get_by_index(dev, 0, &clk);
768135aa950SStephen Warren 	if (ret < 0) {
769a111bfbfSMasahiro Yamada 		dev_err(dev, "failed to get host clock\n");
770135aa950SStephen Warren 		return ret;
771a111bfbfSMasahiro Yamada 	}
772a111bfbfSMasahiro Yamada 
773a111bfbfSMasahiro Yamada 	/* set to max rate */
774135aa950SStephen Warren 	priv->mclk = clk_set_rate(&clk, ULONG_MAX);
775a111bfbfSMasahiro Yamada 	if (IS_ERR_VALUE(priv->mclk)) {
776a111bfbfSMasahiro Yamada 		dev_err(dev, "failed to set rate for host clock\n");
777135aa950SStephen Warren 		clk_free(&clk);
778a111bfbfSMasahiro Yamada 		return priv->mclk;
779a111bfbfSMasahiro Yamada 	}
780a111bfbfSMasahiro Yamada 
781135aa950SStephen Warren 	ret = clk_enable(&clk);
782135aa950SStephen Warren 	clk_free(&clk);
783a111bfbfSMasahiro Yamada 	if (ret) {
784a111bfbfSMasahiro Yamada 		dev_err(dev, "failed to enable host clock\n");
785a111bfbfSMasahiro Yamada 		return ret;
786a111bfbfSMasahiro Yamada 	}
787a111bfbfSMasahiro Yamada 
78814f47234SMasahiro Yamada 	plat->cfg.name = dev->name;
78914f47234SMasahiro Yamada 	plat->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
790a111bfbfSMasahiro Yamada 
791e160f7d4SSimon Glass 	switch (fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "bus-width",
792e160f7d4SSimon Glass 			       1)) {
793a111bfbfSMasahiro Yamada 	case 8:
79414f47234SMasahiro Yamada 		plat->cfg.host_caps |= MMC_MODE_8BIT;
795a111bfbfSMasahiro Yamada 		break;
796a111bfbfSMasahiro Yamada 	case 4:
79714f47234SMasahiro Yamada 		plat->cfg.host_caps |= MMC_MODE_4BIT;
798a111bfbfSMasahiro Yamada 		break;
799a111bfbfSMasahiro Yamada 	case 1:
800a111bfbfSMasahiro Yamada 		break;
801a111bfbfSMasahiro Yamada 	default:
802a111bfbfSMasahiro Yamada 		dev_err(dev, "Invalid \"bus-width\" value\n");
803a111bfbfSMasahiro Yamada 		return -EINVAL;
804a111bfbfSMasahiro Yamada 	}
805a111bfbfSMasahiro Yamada 
806*4b26d5e3SMarek Vasut 	if (quirks) {
807*4b26d5e3SMarek Vasut 		priv->caps = quirks;
808*4b26d5e3SMarek Vasut 	} else {
8093d7b1d1bSMarek Vasut 		priv->version = uniphier_sd_readl(priv, UNIPHIER_SD_VERSION) &
810a111bfbfSMasahiro Yamada 							UNIPHIER_SD_VERSION_IP;
811a111bfbfSMasahiro Yamada 		dev_dbg(dev, "version %x\n", priv->version);
812a111bfbfSMasahiro Yamada 		if (priv->version >= 0x10) {
813a111bfbfSMasahiro Yamada 			priv->caps |= UNIPHIER_SD_CAP_DMA_INTERNAL;
814a111bfbfSMasahiro Yamada 			priv->caps |= UNIPHIER_SD_CAP_DIV1024;
815a111bfbfSMasahiro Yamada 		}
816*4b26d5e3SMarek Vasut 	}
817*4b26d5e3SMarek Vasut 
818*4b26d5e3SMarek Vasut 	if (fdt_get_property(gd->fdt_blob, dev_of_offset(dev), "non-removable",
819*4b26d5e3SMarek Vasut 			     NULL))
820*4b26d5e3SMarek Vasut 		priv->caps |= UNIPHIER_SD_CAP_NONREMOVABLE;
821a111bfbfSMasahiro Yamada 
8224eb00846SMasahiro Yamada 	uniphier_sd_host_init(priv);
8233937404fSMasahiro Yamada 
82414f47234SMasahiro Yamada 	plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
82514f47234SMasahiro Yamada 	plat->cfg.f_min = priv->mclk /
826a111bfbfSMasahiro Yamada 			(priv->caps & UNIPHIER_SD_CAP_DIV1024 ? 1024 : 512);
82714f47234SMasahiro Yamada 	plat->cfg.f_max = priv->mclk;
82814f47234SMasahiro Yamada 	plat->cfg.b_max = U32_MAX; /* max value of UNIPHIER_SD_SECCNT */
829a111bfbfSMasahiro Yamada 
83014f47234SMasahiro Yamada 	upriv->mmc = &plat->mmc;
831a111bfbfSMasahiro Yamada 
832a111bfbfSMasahiro Yamada 	return 0;
833a111bfbfSMasahiro Yamada }
834a111bfbfSMasahiro Yamada 
835a111bfbfSMasahiro Yamada static const struct udevice_id uniphier_sd_match[] = {
836*4b26d5e3SMarek Vasut 	{ .compatible = "socionext,uniphier-sdhc", .data = 0 },
837a111bfbfSMasahiro Yamada 	{ /* sentinel */ }
838a111bfbfSMasahiro Yamada };
839a111bfbfSMasahiro Yamada 
840a111bfbfSMasahiro Yamada U_BOOT_DRIVER(uniphier_mmc) = {
841a111bfbfSMasahiro Yamada 	.name = "uniphier-mmc",
842a111bfbfSMasahiro Yamada 	.id = UCLASS_MMC,
843a111bfbfSMasahiro Yamada 	.of_match = uniphier_sd_match,
84414f47234SMasahiro Yamada 	.bind = uniphier_sd_bind,
845a111bfbfSMasahiro Yamada 	.probe = uniphier_sd_probe,
846a111bfbfSMasahiro Yamada 	.priv_auto_alloc_size = sizeof(struct uniphier_sd_priv),
84714f47234SMasahiro Yamada 	.platdata_auto_alloc_size = sizeof(struct uniphier_sd_plat),
8483937404fSMasahiro Yamada 	.ops = &uniphier_sd_ops,
849a111bfbfSMasahiro Yamada };
850