xref: /rk3399_rockchip-uboot/drivers/mmc/sunxi_mmc.c (revision e24ea55c04a8ee9c273dd879edda23bbde3d807a)
1*e24ea55cSIan Campbell /*
2*e24ea55cSIan Campbell  * (C) Copyright 2007-2011
3*e24ea55cSIan Campbell  * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
4*e24ea55cSIan Campbell  * Aaron <leafy.myeh@allwinnertech.com>
5*e24ea55cSIan Campbell  *
6*e24ea55cSIan Campbell  * MMC driver for allwinner sunxi platform.
7*e24ea55cSIan Campbell  *
8*e24ea55cSIan Campbell  * SPDX-License-Identifier:	GPL-2.0+
9*e24ea55cSIan Campbell  */
10*e24ea55cSIan Campbell 
11*e24ea55cSIan Campbell #include <common.h>
12*e24ea55cSIan Campbell #include <malloc.h>
13*e24ea55cSIan Campbell #include <mmc.h>
14*e24ea55cSIan Campbell #include <asm/io.h>
15*e24ea55cSIan Campbell #include <asm/arch/clock.h>
16*e24ea55cSIan Campbell #include <asm/arch/cpu.h>
17*e24ea55cSIan Campbell #include <asm/arch/mmc.h>
18*e24ea55cSIan Campbell 
19*e24ea55cSIan Campbell struct sunxi_mmc_des {
20*e24ea55cSIan Campbell 	u32 reserved1_1:1;
21*e24ea55cSIan Campbell 	u32 dic:1;		/* disable interrupt on completion */
22*e24ea55cSIan Campbell 	u32 last_des:1;		/* 1-this data buffer is the last buffer */
23*e24ea55cSIan Campbell 	u32 first_des:1;		/* 1-data buffer is the first buffer,
24*e24ea55cSIan Campbell 				   0-data buffer contained in the next
25*e24ea55cSIan Campbell 				   descriptor is 1st buffer */
26*e24ea55cSIan Campbell 	u32 des_chain:1;	/* 1-the 2nd address in the descriptor is the
27*e24ea55cSIan Campbell 				   next descriptor address */
28*e24ea55cSIan Campbell 	u32 end_of_ring:1;	/* 1-last descriptor flag when using dual
29*e24ea55cSIan Campbell 				   data buffer in descriptor */
30*e24ea55cSIan Campbell 	u32 reserved1_2:24;
31*e24ea55cSIan Campbell 	u32 card_err_sum:1;	/* transfer error flag */
32*e24ea55cSIan Campbell 	u32 own:1;		/* des owner:1-idma owns it, 0-host owns it */
33*e24ea55cSIan Campbell #define SDXC_DES_NUM_SHIFT 16
34*e24ea55cSIan Campbell #define SDXC_DES_BUFFER_MAX_LEN	(1 << SDXC_DES_NUM_SHIFT)
35*e24ea55cSIan Campbell 	u32 data_buf1_sz:16;
36*e24ea55cSIan Campbell 	u32 data_buf2_sz:16;
37*e24ea55cSIan Campbell 	u32 buf_addr_ptr1;
38*e24ea55cSIan Campbell 	u32 buf_addr_ptr2;
39*e24ea55cSIan Campbell };
40*e24ea55cSIan Campbell 
41*e24ea55cSIan Campbell struct sunxi_mmc_host {
42*e24ea55cSIan Campbell 	unsigned mmc_no;
43*e24ea55cSIan Campbell 	uint32_t *mclkreg;
44*e24ea55cSIan Campbell 	unsigned database;
45*e24ea55cSIan Campbell 	unsigned fatal_err;
46*e24ea55cSIan Campbell 	unsigned mod_clk;
47*e24ea55cSIan Campbell 	struct sunxi_mmc *reg;
48*e24ea55cSIan Campbell 	struct mmc_config cfg;
49*e24ea55cSIan Campbell };
50*e24ea55cSIan Campbell 
51*e24ea55cSIan Campbell /* support 4 mmc hosts */
52*e24ea55cSIan Campbell struct sunxi_mmc_host mmc_host[4];
53*e24ea55cSIan Campbell 
54*e24ea55cSIan Campbell static int mmc_resource_init(int sdc_no)
55*e24ea55cSIan Campbell {
56*e24ea55cSIan Campbell 	struct sunxi_mmc_host *mmchost = &mmc_host[sdc_no];
57*e24ea55cSIan Campbell 	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
58*e24ea55cSIan Campbell 
59*e24ea55cSIan Campbell 	debug("init mmc %d resource\n", sdc_no);
60*e24ea55cSIan Campbell 
61*e24ea55cSIan Campbell 	switch (sdc_no) {
62*e24ea55cSIan Campbell 	case 0:
63*e24ea55cSIan Campbell 		mmchost->reg = (struct sunxi_mmc *)SUNXI_MMC0_BASE;
64*e24ea55cSIan Campbell 		mmchost->mclkreg = &ccm->sd0_clk_cfg;
65*e24ea55cSIan Campbell 		break;
66*e24ea55cSIan Campbell 	case 1:
67*e24ea55cSIan Campbell 		mmchost->reg = (struct sunxi_mmc *)SUNXI_MMC1_BASE;
68*e24ea55cSIan Campbell 		mmchost->mclkreg = &ccm->sd1_clk_cfg;
69*e24ea55cSIan Campbell 		break;
70*e24ea55cSIan Campbell 	case 2:
71*e24ea55cSIan Campbell 		mmchost->reg = (struct sunxi_mmc *)SUNXI_MMC2_BASE;
72*e24ea55cSIan Campbell 		mmchost->mclkreg = &ccm->sd2_clk_cfg;
73*e24ea55cSIan Campbell 		break;
74*e24ea55cSIan Campbell 	case 3:
75*e24ea55cSIan Campbell 		mmchost->reg = (struct sunxi_mmc *)SUNXI_MMC3_BASE;
76*e24ea55cSIan Campbell 		mmchost->mclkreg = &ccm->sd3_clk_cfg;
77*e24ea55cSIan Campbell 		break;
78*e24ea55cSIan Campbell 	default:
79*e24ea55cSIan Campbell 		printf("Wrong mmc number %d\n", sdc_no);
80*e24ea55cSIan Campbell 		return -1;
81*e24ea55cSIan Campbell 	}
82*e24ea55cSIan Campbell 	mmchost->database = (unsigned int)mmchost->reg + 0x100;
83*e24ea55cSIan Campbell 	mmchost->mmc_no = sdc_no;
84*e24ea55cSIan Campbell 
85*e24ea55cSIan Campbell 	return 0;
86*e24ea55cSIan Campbell }
87*e24ea55cSIan Campbell 
88*e24ea55cSIan Campbell static int mmc_clk_io_on(int sdc_no)
89*e24ea55cSIan Campbell {
90*e24ea55cSIan Campbell 	unsigned int pll_clk;
91*e24ea55cSIan Campbell 	unsigned int divider;
92*e24ea55cSIan Campbell 	struct sunxi_mmc_host *mmchost = &mmc_host[sdc_no];
93*e24ea55cSIan Campbell 	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
94*e24ea55cSIan Campbell 
95*e24ea55cSIan Campbell 	debug("init mmc %d clock and io\n", sdc_no);
96*e24ea55cSIan Campbell 
97*e24ea55cSIan Campbell 	/* config ahb clock */
98*e24ea55cSIan Campbell 	setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MMC(sdc_no));
99*e24ea55cSIan Campbell 
100*e24ea55cSIan Campbell 	/* config mod clock */
101*e24ea55cSIan Campbell 	pll_clk = clock_get_pll6();
102*e24ea55cSIan Campbell 	/* should be close to 100 MHz but no more, so round up */
103*e24ea55cSIan Campbell 	divider = ((pll_clk + 99999999) / 100000000) - 1;
104*e24ea55cSIan Campbell 	writel(CCM_MMC_CTRL_ENABLE | CCM_MMC_CTRL_PLL6 | divider,
105*e24ea55cSIan Campbell 	       mmchost->mclkreg);
106*e24ea55cSIan Campbell 	mmchost->mod_clk = pll_clk / (divider + 1);
107*e24ea55cSIan Campbell 
108*e24ea55cSIan Campbell 	return 0;
109*e24ea55cSIan Campbell }
110*e24ea55cSIan Campbell 
111*e24ea55cSIan Campbell static int mmc_update_clk(struct mmc *mmc)
112*e24ea55cSIan Campbell {
113*e24ea55cSIan Campbell 	struct sunxi_mmc_host *mmchost = mmc->priv;
114*e24ea55cSIan Campbell 	unsigned int cmd;
115*e24ea55cSIan Campbell 	unsigned timeout_msecs = 2000;
116*e24ea55cSIan Campbell 
117*e24ea55cSIan Campbell 	cmd = SUNXI_MMC_CMD_START |
118*e24ea55cSIan Campbell 	      SUNXI_MMC_CMD_UPCLK_ONLY |
119*e24ea55cSIan Campbell 	      SUNXI_MMC_CMD_WAIT_PRE_OVER;
120*e24ea55cSIan Campbell 	writel(cmd, &mmchost->reg->cmd);
121*e24ea55cSIan Campbell 	while (readl(&mmchost->reg->cmd) & SUNXI_MMC_CMD_START) {
122*e24ea55cSIan Campbell 		if (!timeout_msecs--)
123*e24ea55cSIan Campbell 			return -1;
124*e24ea55cSIan Campbell 		udelay(1000);
125*e24ea55cSIan Campbell 	}
126*e24ea55cSIan Campbell 
127*e24ea55cSIan Campbell 	/* clock update sets various irq status bits, clear these */
128*e24ea55cSIan Campbell 	writel(readl(&mmchost->reg->rint), &mmchost->reg->rint);
129*e24ea55cSIan Campbell 
130*e24ea55cSIan Campbell 	return 0;
131*e24ea55cSIan Campbell }
132*e24ea55cSIan Campbell 
133*e24ea55cSIan Campbell static int mmc_config_clock(struct mmc *mmc, unsigned div)
134*e24ea55cSIan Campbell {
135*e24ea55cSIan Campbell 	struct sunxi_mmc_host *mmchost = mmc->priv;
136*e24ea55cSIan Campbell 	unsigned rval = readl(&mmchost->reg->clkcr);
137*e24ea55cSIan Campbell 
138*e24ea55cSIan Campbell 	/* Disable Clock */
139*e24ea55cSIan Campbell 	rval &= ~SUNXI_MMC_CLK_ENABLE;
140*e24ea55cSIan Campbell 	writel(rval, &mmchost->reg->clkcr);
141*e24ea55cSIan Campbell 	if (mmc_update_clk(mmc))
142*e24ea55cSIan Campbell 		return -1;
143*e24ea55cSIan Campbell 
144*e24ea55cSIan Campbell 	/* Change Divider Factor */
145*e24ea55cSIan Campbell 	rval &= ~SUNXI_MMC_CLK_DIVIDER_MASK;
146*e24ea55cSIan Campbell 	rval |= div;
147*e24ea55cSIan Campbell 	writel(rval, &mmchost->reg->clkcr);
148*e24ea55cSIan Campbell 	if (mmc_update_clk(mmc))
149*e24ea55cSIan Campbell 		return -1;
150*e24ea55cSIan Campbell 	/* Re-enable Clock */
151*e24ea55cSIan Campbell 	rval |= SUNXI_MMC_CLK_ENABLE;
152*e24ea55cSIan Campbell 	writel(rval, &mmchost->reg->clkcr);
153*e24ea55cSIan Campbell 
154*e24ea55cSIan Campbell 	if (mmc_update_clk(mmc))
155*e24ea55cSIan Campbell 		return -1;
156*e24ea55cSIan Campbell 
157*e24ea55cSIan Campbell 	return 0;
158*e24ea55cSIan Campbell }
159*e24ea55cSIan Campbell 
160*e24ea55cSIan Campbell static void mmc_set_ios(struct mmc *mmc)
161*e24ea55cSIan Campbell {
162*e24ea55cSIan Campbell 	struct sunxi_mmc_host *mmchost = mmc->priv;
163*e24ea55cSIan Campbell 	unsigned int clkdiv = 0;
164*e24ea55cSIan Campbell 
165*e24ea55cSIan Campbell 	debug("set ios: bus_width: %x, clock: %d, mod_clk: %d\n",
166*e24ea55cSIan Campbell 	      mmc->bus_width, mmc->clock, mmchost->mod_clk);
167*e24ea55cSIan Campbell 
168*e24ea55cSIan Campbell 	/* Change clock first */
169*e24ea55cSIan Campbell 	clkdiv = (mmchost->mod_clk + (mmc->clock >> 1)) / mmc->clock / 2;
170*e24ea55cSIan Campbell 	if (mmc->clock) {
171*e24ea55cSIan Campbell 		if (mmc_config_clock(mmc, clkdiv)) {
172*e24ea55cSIan Campbell 			mmchost->fatal_err = 1;
173*e24ea55cSIan Campbell 			return;
174*e24ea55cSIan Campbell 		}
175*e24ea55cSIan Campbell 	}
176*e24ea55cSIan Campbell 
177*e24ea55cSIan Campbell 	/* Change bus width */
178*e24ea55cSIan Campbell 	if (mmc->bus_width == 8)
179*e24ea55cSIan Campbell 		writel(0x2, &mmchost->reg->width);
180*e24ea55cSIan Campbell 	else if (mmc->bus_width == 4)
181*e24ea55cSIan Campbell 		writel(0x1, &mmchost->reg->width);
182*e24ea55cSIan Campbell 	else
183*e24ea55cSIan Campbell 		writel(0x0, &mmchost->reg->width);
184*e24ea55cSIan Campbell }
185*e24ea55cSIan Campbell 
186*e24ea55cSIan Campbell static int mmc_core_init(struct mmc *mmc)
187*e24ea55cSIan Campbell {
188*e24ea55cSIan Campbell 	struct sunxi_mmc_host *mmchost = mmc->priv;
189*e24ea55cSIan Campbell 
190*e24ea55cSIan Campbell 	/* Reset controller */
191*e24ea55cSIan Campbell 	writel(SUNXI_MMC_GCTRL_RESET, &mmchost->reg->gctrl);
192*e24ea55cSIan Campbell 
193*e24ea55cSIan Campbell 	return 0;
194*e24ea55cSIan Campbell }
195*e24ea55cSIan Campbell 
196*e24ea55cSIan Campbell static int mmc_trans_data_by_cpu(struct mmc *mmc, struct mmc_data *data)
197*e24ea55cSIan Campbell {
198*e24ea55cSIan Campbell 	struct sunxi_mmc_host *mmchost = mmc->priv;
199*e24ea55cSIan Campbell 	const int reading = !!(data->flags & MMC_DATA_READ);
200*e24ea55cSIan Campbell 	const uint32_t status_bit = reading ? SUNXI_MMC_STATUS_FIFO_EMPTY :
201*e24ea55cSIan Campbell 					      SUNXI_MMC_STATUS_FIFO_FULL;
202*e24ea55cSIan Campbell 	unsigned i;
203*e24ea55cSIan Campbell 	unsigned byte_cnt = data->blocksize * data->blocks;
204*e24ea55cSIan Campbell 	unsigned timeout_msecs = 2000;
205*e24ea55cSIan Campbell 	unsigned *buff = (unsigned int *)(reading ? data->dest : data->src);
206*e24ea55cSIan Campbell 
207*e24ea55cSIan Campbell 	for (i = 0; i < (byte_cnt >> 2); i++) {
208*e24ea55cSIan Campbell 		while (readl(&mmchost->reg->status) & status_bit) {
209*e24ea55cSIan Campbell 			if (!timeout_msecs--)
210*e24ea55cSIan Campbell 				return -1;
211*e24ea55cSIan Campbell 			udelay(1000);
212*e24ea55cSIan Campbell 		}
213*e24ea55cSIan Campbell 
214*e24ea55cSIan Campbell 		if (reading)
215*e24ea55cSIan Campbell 			buff[i] = readl(mmchost->database);
216*e24ea55cSIan Campbell 		else
217*e24ea55cSIan Campbell 			writel(buff[i], mmchost->database);
218*e24ea55cSIan Campbell 	}
219*e24ea55cSIan Campbell 
220*e24ea55cSIan Campbell 	return 0;
221*e24ea55cSIan Campbell }
222*e24ea55cSIan Campbell 
223*e24ea55cSIan Campbell static int mmc_trans_data_by_dma(struct mmc *mmc, struct mmc_data *data)
224*e24ea55cSIan Campbell {
225*e24ea55cSIan Campbell 	struct sunxi_mmc_host *mmchost = mmc->priv;
226*e24ea55cSIan Campbell 	unsigned byte_cnt = data->blocksize * data->blocks;
227*e24ea55cSIan Campbell 	unsigned char *buff;
228*e24ea55cSIan Campbell 	unsigned des_idx = 0;
229*e24ea55cSIan Campbell 	unsigned buff_frag_num =
230*e24ea55cSIan Campbell 		(byte_cnt + SDXC_DES_BUFFER_MAX_LEN - 1) >> SDXC_DES_NUM_SHIFT;
231*e24ea55cSIan Campbell 	unsigned remain;
232*e24ea55cSIan Campbell 	unsigned i, rval;
233*e24ea55cSIan Campbell 	ALLOC_CACHE_ALIGN_BUFFER(struct sunxi_mmc_des, pdes, buff_frag_num);
234*e24ea55cSIan Campbell 
235*e24ea55cSIan Campbell 	buff = data->flags & MMC_DATA_READ ?
236*e24ea55cSIan Campbell 	    (unsigned char *)data->dest : (unsigned char *)data->src;
237*e24ea55cSIan Campbell 	remain = byte_cnt & (SDXC_DES_BUFFER_MAX_LEN - 1);
238*e24ea55cSIan Campbell 
239*e24ea55cSIan Campbell 	flush_cache((unsigned long)buff, (unsigned long)byte_cnt);
240*e24ea55cSIan Campbell 	for (i = 0; i < buff_frag_num; i++, des_idx++) {
241*e24ea55cSIan Campbell 		memset((void *)&pdes[des_idx], 0, sizeof(struct sunxi_mmc_des));
242*e24ea55cSIan Campbell 		pdes[des_idx].des_chain = 1;
243*e24ea55cSIan Campbell 		pdes[des_idx].own = 1;
244*e24ea55cSIan Campbell 		pdes[des_idx].dic = 1;
245*e24ea55cSIan Campbell 		if (buff_frag_num > 1 && i != buff_frag_num - 1)
246*e24ea55cSIan Campbell 			pdes[des_idx].data_buf1_sz = 0; /* 0 == max_len */
247*e24ea55cSIan Campbell 		else
248*e24ea55cSIan Campbell 			pdes[des_idx].data_buf1_sz = remain;
249*e24ea55cSIan Campbell 
250*e24ea55cSIan Campbell 		pdes[des_idx].buf_addr_ptr1 =
251*e24ea55cSIan Campbell 		    (u32) buff + i * SDXC_DES_BUFFER_MAX_LEN;
252*e24ea55cSIan Campbell 		if (i == 0)
253*e24ea55cSIan Campbell 			pdes[des_idx].first_des = 1;
254*e24ea55cSIan Campbell 
255*e24ea55cSIan Campbell 		if (i == buff_frag_num - 1) {
256*e24ea55cSIan Campbell 			pdes[des_idx].dic = 0;
257*e24ea55cSIan Campbell 			pdes[des_idx].last_des = 1;
258*e24ea55cSIan Campbell 			pdes[des_idx].end_of_ring = 1;
259*e24ea55cSIan Campbell 			pdes[des_idx].buf_addr_ptr2 = 0;
260*e24ea55cSIan Campbell 		} else {
261*e24ea55cSIan Campbell 			pdes[des_idx].buf_addr_ptr2 = (u32)&pdes[des_idx + 1];
262*e24ea55cSIan Campbell 		}
263*e24ea55cSIan Campbell 	}
264*e24ea55cSIan Campbell 	flush_cache((unsigned long)pdes,
265*e24ea55cSIan Campbell 		    sizeof(struct sunxi_mmc_des) * (des_idx + 1));
266*e24ea55cSIan Campbell 
267*e24ea55cSIan Campbell 	rval = readl(&mmchost->reg->gctrl);
268*e24ea55cSIan Campbell 	/* Enable DMA */
269*e24ea55cSIan Campbell 	writel(rval | SUNXI_MMC_GCTRL_DMA_RESET | SUNXI_MMC_GCTRL_DMA_ENABLE,
270*e24ea55cSIan Campbell 	       &mmchost->reg->gctrl);
271*e24ea55cSIan Campbell 	/* Reset iDMA */
272*e24ea55cSIan Campbell 	writel(SUNXI_MMC_IDMAC_RESET, &mmchost->reg->dmac);
273*e24ea55cSIan Campbell 	/* Enable iDMA */
274*e24ea55cSIan Campbell 	writel(SUNXI_MMC_IDMAC_FIXBURST | SUNXI_MMC_IDMAC_ENABLE,
275*e24ea55cSIan Campbell 	       &mmchost->reg->dmac);
276*e24ea55cSIan Campbell 	rval = readl(&mmchost->reg->idie) &
277*e24ea55cSIan Campbell 		~(SUNXI_MMC_IDIE_TXIRQ|SUNXI_MMC_IDIE_RXIRQ);
278*e24ea55cSIan Campbell 	if (data->flags & MMC_DATA_WRITE)
279*e24ea55cSIan Campbell 		rval |= SUNXI_MMC_IDIE_TXIRQ;
280*e24ea55cSIan Campbell 	else
281*e24ea55cSIan Campbell 		rval |= SUNXI_MMC_IDIE_RXIRQ;
282*e24ea55cSIan Campbell 	writel(rval, &mmchost->reg->idie);
283*e24ea55cSIan Campbell 	writel((u32) pdes, &mmchost->reg->dlba);
284*e24ea55cSIan Campbell 	writel((0x2 << 28) | (0x7 << 16) | (0x01 << 3),
285*e24ea55cSIan Campbell 	       &mmchost->reg->ftrglevel);
286*e24ea55cSIan Campbell 
287*e24ea55cSIan Campbell 	return 0;
288*e24ea55cSIan Campbell }
289*e24ea55cSIan Campbell 
290*e24ea55cSIan Campbell static void mmc_enable_dma_accesses(struct mmc *mmc, int dma)
291*e24ea55cSIan Campbell {
292*e24ea55cSIan Campbell 	struct sunxi_mmc_host *mmchost = mmc->priv;
293*e24ea55cSIan Campbell 
294*e24ea55cSIan Campbell 	unsigned int gctrl = readl(&mmchost->reg->gctrl);
295*e24ea55cSIan Campbell 	if (dma)
296*e24ea55cSIan Campbell 		gctrl &= ~SUNXI_MMC_GCTRL_ACCESS_BY_AHB;
297*e24ea55cSIan Campbell 	else
298*e24ea55cSIan Campbell 		gctrl |= SUNXI_MMC_GCTRL_ACCESS_BY_AHB;
299*e24ea55cSIan Campbell 	writel(gctrl, &mmchost->reg->gctrl);
300*e24ea55cSIan Campbell }
301*e24ea55cSIan Campbell 
302*e24ea55cSIan Campbell static int mmc_rint_wait(struct mmc *mmc, unsigned int timeout_msecs,
303*e24ea55cSIan Campbell 			 unsigned int done_bit, const char *what)
304*e24ea55cSIan Campbell {
305*e24ea55cSIan Campbell 	struct sunxi_mmc_host *mmchost = mmc->priv;
306*e24ea55cSIan Campbell 	unsigned int status;
307*e24ea55cSIan Campbell 
308*e24ea55cSIan Campbell 	do {
309*e24ea55cSIan Campbell 		status = readl(&mmchost->reg->rint);
310*e24ea55cSIan Campbell 		if (!timeout_msecs-- ||
311*e24ea55cSIan Campbell 		    (status & SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT)) {
312*e24ea55cSIan Campbell 			debug("%s timeout %x\n", what,
313*e24ea55cSIan Campbell 			      status & SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT);
314*e24ea55cSIan Campbell 			return TIMEOUT;
315*e24ea55cSIan Campbell 		}
316*e24ea55cSIan Campbell 		udelay(1000);
317*e24ea55cSIan Campbell 	} while (!(status & done_bit));
318*e24ea55cSIan Campbell 
319*e24ea55cSIan Campbell 	return 0;
320*e24ea55cSIan Campbell }
321*e24ea55cSIan Campbell 
322*e24ea55cSIan Campbell static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
323*e24ea55cSIan Campbell 			struct mmc_data *data)
324*e24ea55cSIan Campbell {
325*e24ea55cSIan Campbell 	struct sunxi_mmc_host *mmchost = mmc->priv;
326*e24ea55cSIan Campbell 	unsigned int cmdval = SUNXI_MMC_CMD_START;
327*e24ea55cSIan Campbell 	unsigned int timeout_msecs;
328*e24ea55cSIan Campbell 	int error = 0;
329*e24ea55cSIan Campbell 	unsigned int status = 0;
330*e24ea55cSIan Campbell 	unsigned int usedma = 0;
331*e24ea55cSIan Campbell 	unsigned int bytecnt = 0;
332*e24ea55cSIan Campbell 
333*e24ea55cSIan Campbell 	if (mmchost->fatal_err)
334*e24ea55cSIan Campbell 		return -1;
335*e24ea55cSIan Campbell 	if (cmd->resp_type & MMC_RSP_BUSY)
336*e24ea55cSIan Campbell 		debug("mmc cmd %d check rsp busy\n", cmd->cmdidx);
337*e24ea55cSIan Campbell 	if (cmd->cmdidx == 12)
338*e24ea55cSIan Campbell 		return 0;
339*e24ea55cSIan Campbell 
340*e24ea55cSIan Campbell 	if (!cmd->cmdidx)
341*e24ea55cSIan Campbell 		cmdval |= SUNXI_MMC_CMD_SEND_INIT_SEQ;
342*e24ea55cSIan Campbell 	if (cmd->resp_type & MMC_RSP_PRESENT)
343*e24ea55cSIan Campbell 		cmdval |= SUNXI_MMC_CMD_RESP_EXPIRE;
344*e24ea55cSIan Campbell 	if (cmd->resp_type & MMC_RSP_136)
345*e24ea55cSIan Campbell 		cmdval |= SUNXI_MMC_CMD_LONG_RESPONSE;
346*e24ea55cSIan Campbell 	if (cmd->resp_type & MMC_RSP_CRC)
347*e24ea55cSIan Campbell 		cmdval |= SUNXI_MMC_CMD_CHK_RESPONSE_CRC;
348*e24ea55cSIan Campbell 
349*e24ea55cSIan Campbell 	if (data) {
350*e24ea55cSIan Campbell 		if ((u32) data->dest & 0x3) {
351*e24ea55cSIan Campbell 			error = -1;
352*e24ea55cSIan Campbell 			goto out;
353*e24ea55cSIan Campbell 		}
354*e24ea55cSIan Campbell 
355*e24ea55cSIan Campbell 		cmdval |= SUNXI_MMC_CMD_DATA_EXPIRE|SUNXI_MMC_CMD_WAIT_PRE_OVER;
356*e24ea55cSIan Campbell 		if (data->flags & MMC_DATA_WRITE)
357*e24ea55cSIan Campbell 			cmdval |= SUNXI_MMC_CMD_WRITE;
358*e24ea55cSIan Campbell 		if (data->blocks > 1)
359*e24ea55cSIan Campbell 			cmdval |= SUNXI_MMC_CMD_AUTO_STOP;
360*e24ea55cSIan Campbell 		writel(data->blocksize, &mmchost->reg->blksz);
361*e24ea55cSIan Campbell 		writel(data->blocks * data->blocksize, &mmchost->reg->bytecnt);
362*e24ea55cSIan Campbell 	}
363*e24ea55cSIan Campbell 
364*e24ea55cSIan Campbell 	debug("mmc %d, cmd %d(0x%08x), arg 0x%08x\n", mmchost->mmc_no,
365*e24ea55cSIan Campbell 	      cmd->cmdidx, cmdval | cmd->cmdidx, cmd->cmdarg);
366*e24ea55cSIan Campbell 	writel(cmd->cmdarg, &mmchost->reg->arg);
367*e24ea55cSIan Campbell 
368*e24ea55cSIan Campbell 	if (!data)
369*e24ea55cSIan Campbell 		writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd);
370*e24ea55cSIan Campbell 
371*e24ea55cSIan Campbell 	/*
372*e24ea55cSIan Campbell 	 * transfer data and check status
373*e24ea55cSIan Campbell 	 * STATREG[2] : FIFO empty
374*e24ea55cSIan Campbell 	 * STATREG[3] : FIFO full
375*e24ea55cSIan Campbell 	 */
376*e24ea55cSIan Campbell 	if (data) {
377*e24ea55cSIan Campbell 		int ret = 0;
378*e24ea55cSIan Campbell 
379*e24ea55cSIan Campbell 		bytecnt = data->blocksize * data->blocks;
380*e24ea55cSIan Campbell 		debug("trans data %d bytes\n", bytecnt);
381*e24ea55cSIan Campbell #if defined(CONFIG_MMC_SUNXI_USE_DMA) && !defined(CONFIG_SPL_BUILD)
382*e24ea55cSIan Campbell 		if (bytecnt > 64) {
383*e24ea55cSIan Campbell #else
384*e24ea55cSIan Campbell 		if (0) {
385*e24ea55cSIan Campbell #endif
386*e24ea55cSIan Campbell 			usedma = 1;
387*e24ea55cSIan Campbell 			mmc_enable_dma_accesses(mmc, 1);
388*e24ea55cSIan Campbell 			ret = mmc_trans_data_by_dma(mmc, data);
389*e24ea55cSIan Campbell 			writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd);
390*e24ea55cSIan Campbell 		} else {
391*e24ea55cSIan Campbell 			mmc_enable_dma_accesses(mmc, 0);
392*e24ea55cSIan Campbell 			writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd);
393*e24ea55cSIan Campbell 			ret = mmc_trans_data_by_cpu(mmc, data);
394*e24ea55cSIan Campbell 		}
395*e24ea55cSIan Campbell 		if (ret) {
396*e24ea55cSIan Campbell 			error = readl(&mmchost->reg->rint) & \
397*e24ea55cSIan Campbell 				SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT;
398*e24ea55cSIan Campbell 			error = TIMEOUT;
399*e24ea55cSIan Campbell 			goto out;
400*e24ea55cSIan Campbell 		}
401*e24ea55cSIan Campbell 	}
402*e24ea55cSIan Campbell 
403*e24ea55cSIan Campbell 	error = mmc_rint_wait(mmc, 0xfffff, SUNXI_MMC_RINT_COMMAND_DONE, "cmd");
404*e24ea55cSIan Campbell 	if (error)
405*e24ea55cSIan Campbell 		goto out;
406*e24ea55cSIan Campbell 
407*e24ea55cSIan Campbell 	if (data) {
408*e24ea55cSIan Campbell 		timeout_msecs = usedma ? 120 * bytecnt : 120;
409*e24ea55cSIan Campbell 		debug("cacl timeout %x msec\n", timeout_msecs);
410*e24ea55cSIan Campbell 		error = mmc_rint_wait(mmc, timeout_msecs,
411*e24ea55cSIan Campbell 				      data->blocks > 1 ?
412*e24ea55cSIan Campbell 				      SUNXI_MMC_RINT_AUTO_COMMAND_DONE :
413*e24ea55cSIan Campbell 				      SUNXI_MMC_RINT_DATA_OVER,
414*e24ea55cSIan Campbell 				      "data");
415*e24ea55cSIan Campbell 		if (error)
416*e24ea55cSIan Campbell 			goto out;
417*e24ea55cSIan Campbell 	}
418*e24ea55cSIan Campbell 
419*e24ea55cSIan Campbell 	if (cmd->resp_type & MMC_RSP_BUSY) {
420*e24ea55cSIan Campbell 		timeout_msecs = 2000;
421*e24ea55cSIan Campbell 		do {
422*e24ea55cSIan Campbell 			status = readl(&mmchost->reg->status);
423*e24ea55cSIan Campbell 			if (!timeout_msecs--) {
424*e24ea55cSIan Campbell 				debug("busy timeout\n");
425*e24ea55cSIan Campbell 				error = TIMEOUT;
426*e24ea55cSIan Campbell 				goto out;
427*e24ea55cSIan Campbell 			}
428*e24ea55cSIan Campbell 			udelay(1000);
429*e24ea55cSIan Campbell 		} while (status & SUNXI_MMC_STATUS_CARD_DATA_BUSY);
430*e24ea55cSIan Campbell 	}
431*e24ea55cSIan Campbell 
432*e24ea55cSIan Campbell 	if (cmd->resp_type & MMC_RSP_136) {
433*e24ea55cSIan Campbell 		cmd->response[0] = readl(&mmchost->reg->resp3);
434*e24ea55cSIan Campbell 		cmd->response[1] = readl(&mmchost->reg->resp2);
435*e24ea55cSIan Campbell 		cmd->response[2] = readl(&mmchost->reg->resp1);
436*e24ea55cSIan Campbell 		cmd->response[3] = readl(&mmchost->reg->resp0);
437*e24ea55cSIan Campbell 		debug("mmc resp 0x%08x 0x%08x 0x%08x 0x%08x\n",
438*e24ea55cSIan Campbell 		      cmd->response[3], cmd->response[2],
439*e24ea55cSIan Campbell 		      cmd->response[1], cmd->response[0]);
440*e24ea55cSIan Campbell 	} else {
441*e24ea55cSIan Campbell 		cmd->response[0] = readl(&mmchost->reg->resp0);
442*e24ea55cSIan Campbell 		debug("mmc resp 0x%08x\n", cmd->response[0]);
443*e24ea55cSIan Campbell 	}
444*e24ea55cSIan Campbell out:
445*e24ea55cSIan Campbell 	if (data && usedma) {
446*e24ea55cSIan Campbell 		/* IDMASTAREG
447*e24ea55cSIan Campbell 		 * IDST[0] : idma tx int
448*e24ea55cSIan Campbell 		 * IDST[1] : idma rx int
449*e24ea55cSIan Campbell 		 * IDST[2] : idma fatal bus error
450*e24ea55cSIan Campbell 		 * IDST[4] : idma descriptor invalid
451*e24ea55cSIan Campbell 		 * IDST[5] : idma error summary
452*e24ea55cSIan Campbell 		 * IDST[8] : idma normal interrupt sumary
453*e24ea55cSIan Campbell 		 * IDST[9] : idma abnormal interrupt sumary
454*e24ea55cSIan Campbell 		 */
455*e24ea55cSIan Campbell 		status = readl(&mmchost->reg->idst);
456*e24ea55cSIan Campbell 		writel(status, &mmchost->reg->idst);
457*e24ea55cSIan Campbell 		writel(0, &mmchost->reg->idie);
458*e24ea55cSIan Campbell 		writel(0, &mmchost->reg->dmac);
459*e24ea55cSIan Campbell 		writel(readl(&mmchost->reg->gctrl) & ~SUNXI_MMC_GCTRL_DMA_ENABLE,
460*e24ea55cSIan Campbell 		       &mmchost->reg->gctrl);
461*e24ea55cSIan Campbell 	}
462*e24ea55cSIan Campbell 	if (error < 0) {
463*e24ea55cSIan Campbell 		writel(SUNXI_MMC_GCTRL_RESET, &mmchost->reg->gctrl);
464*e24ea55cSIan Campbell 		mmc_update_clk(mmc);
465*e24ea55cSIan Campbell 	}
466*e24ea55cSIan Campbell 	writel(0xffffffff, &mmchost->reg->rint);
467*e24ea55cSIan Campbell 	writel(readl(&mmchost->reg->gctrl) | SUNXI_MMC_GCTRL_FIFO_RESET,
468*e24ea55cSIan Campbell 	       &mmchost->reg->gctrl);
469*e24ea55cSIan Campbell 
470*e24ea55cSIan Campbell 	return error;
471*e24ea55cSIan Campbell }
472*e24ea55cSIan Campbell 
473*e24ea55cSIan Campbell static const struct mmc_ops sunxi_mmc_ops = {
474*e24ea55cSIan Campbell 	.send_cmd	= mmc_send_cmd,
475*e24ea55cSIan Campbell 	.set_ios	= mmc_set_ios,
476*e24ea55cSIan Campbell 	.init		= mmc_core_init,
477*e24ea55cSIan Campbell };
478*e24ea55cSIan Campbell 
479*e24ea55cSIan Campbell int sunxi_mmc_init(int sdc_no)
480*e24ea55cSIan Campbell {
481*e24ea55cSIan Campbell 	struct mmc_config *cfg = &mmc_host[sdc_no].cfg;
482*e24ea55cSIan Campbell 
483*e24ea55cSIan Campbell 	memset(&mmc_host[sdc_no], 0, sizeof(struct sunxi_mmc_host));
484*e24ea55cSIan Campbell 
485*e24ea55cSIan Campbell 	cfg->name = "SUNXI SD/MMC";
486*e24ea55cSIan Campbell 	cfg->ops  = &sunxi_mmc_ops;
487*e24ea55cSIan Campbell 
488*e24ea55cSIan Campbell 	cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
489*e24ea55cSIan Campbell 	cfg->host_caps = MMC_MODE_4BIT;
490*e24ea55cSIan Campbell 	cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
491*e24ea55cSIan Campbell 	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
492*e24ea55cSIan Campbell 
493*e24ea55cSIan Campbell 	cfg->f_min = 400000;
494*e24ea55cSIan Campbell 	cfg->f_max = 52000000;
495*e24ea55cSIan Campbell 
496*e24ea55cSIan Campbell 	mmc_resource_init(sdc_no);
497*e24ea55cSIan Campbell 	mmc_clk_io_on(sdc_no);
498*e24ea55cSIan Campbell 
499*e24ea55cSIan Campbell 	if (mmc_create(cfg, &mmc_host[sdc_no]) == NULL)
500*e24ea55cSIan Campbell 		return -1;
501*e24ea55cSIan Campbell 
502*e24ea55cSIan Campbell 	return 0;
503*e24ea55cSIan Campbell }
504