1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright 2011, Marvell Semiconductor Inc.
3*4882a593Smuzhiyun * Lei Wen <leiwen@marvell.com>
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Back ported to the 8xx platform (from the 8260 platform) by
8*4882a593Smuzhiyun * Murray.Jensen@cmst.csiro.au, 27-Jan-01.
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include <common.h>
12*4882a593Smuzhiyun #include <errno.h>
13*4882a593Smuzhiyun #include <malloc.h>
14*4882a593Smuzhiyun #include <mmc.h>
15*4882a593Smuzhiyun #include <sdhci.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #if defined(CONFIG_FIXED_SDHCI_ALIGNED_BUFFER)
18*4882a593Smuzhiyun void *aligned_buffer = (void *)CONFIG_FIXED_SDHCI_ALIGNED_BUFFER;
19*4882a593Smuzhiyun #else
20*4882a593Smuzhiyun void *aligned_buffer;
21*4882a593Smuzhiyun #endif
22*4882a593Smuzhiyun
sdhci_reset(struct sdhci_host * host,u8 mask)23*4882a593Smuzhiyun static void sdhci_reset(struct sdhci_host *host, u8 mask)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun unsigned long timeout;
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun /* Wait max 100 ms */
28*4882a593Smuzhiyun timeout = 100;
29*4882a593Smuzhiyun sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET);
30*4882a593Smuzhiyun while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) {
31*4882a593Smuzhiyun if (timeout == 0) {
32*4882a593Smuzhiyun printf("%s: Reset 0x%x never completed.\n",
33*4882a593Smuzhiyun __func__, (int)mask);
34*4882a593Smuzhiyun return;
35*4882a593Smuzhiyun }
36*4882a593Smuzhiyun timeout--;
37*4882a593Smuzhiyun udelay(1000);
38*4882a593Smuzhiyun }
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun
sdhci_cmd_done(struct sdhci_host * host,struct mmc_cmd * cmd)41*4882a593Smuzhiyun static void sdhci_cmd_done(struct sdhci_host *host, struct mmc_cmd *cmd)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun int i;
44*4882a593Smuzhiyun if (cmd->resp_type & MMC_RSP_136) {
45*4882a593Smuzhiyun /* CRC is stripped so we need to do some shifting. */
46*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
47*4882a593Smuzhiyun cmd->response[i] = sdhci_readl(host,
48*4882a593Smuzhiyun SDHCI_RESPONSE + (3-i)*4) << 8;
49*4882a593Smuzhiyun if (i != 3)
50*4882a593Smuzhiyun cmd->response[i] |= sdhci_readb(host,
51*4882a593Smuzhiyun SDHCI_RESPONSE + (3-i)*4-1);
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun } else {
54*4882a593Smuzhiyun cmd->response[0] = sdhci_readl(host, SDHCI_RESPONSE);
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun
sdhci_transfer_pio(struct sdhci_host * host,struct mmc_data * data)58*4882a593Smuzhiyun static void sdhci_transfer_pio(struct sdhci_host *host, struct mmc_data *data)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun int i;
61*4882a593Smuzhiyun char *offs;
62*4882a593Smuzhiyun for (i = 0; i < data->blocksize; i += 4) {
63*4882a593Smuzhiyun offs = data->dest + i;
64*4882a593Smuzhiyun if (data->flags == MMC_DATA_READ)
65*4882a593Smuzhiyun *(u32 *)offs = sdhci_readl(host, SDHCI_BUFFER);
66*4882a593Smuzhiyun else
67*4882a593Smuzhiyun sdhci_writel(host, *(u32 *)offs, SDHCI_BUFFER);
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun
sdhci_transfer_data(struct sdhci_host * host,struct mmc_data * data,unsigned int start_addr)71*4882a593Smuzhiyun static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
72*4882a593Smuzhiyun unsigned int start_addr)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun unsigned int stat, rdy, mask, timeout, block = 0;
75*4882a593Smuzhiyun bool transfer_done = false;
76*4882a593Smuzhiyun #ifdef CONFIG_MMC_SDHCI_SDMA
77*4882a593Smuzhiyun unsigned char ctrl;
78*4882a593Smuzhiyun ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
79*4882a593Smuzhiyun ctrl &= ~SDHCI_CTRL_DMA_MASK;
80*4882a593Smuzhiyun sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
81*4882a593Smuzhiyun #endif
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun timeout = 1000000;
84*4882a593Smuzhiyun rdy = SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_AVAIL;
85*4882a593Smuzhiyun mask = SDHCI_DATA_AVAILABLE | SDHCI_SPACE_AVAILABLE;
86*4882a593Smuzhiyun do {
87*4882a593Smuzhiyun stat = sdhci_readl(host, SDHCI_INT_STATUS);
88*4882a593Smuzhiyun if (stat & SDHCI_INT_ERROR) {
89*4882a593Smuzhiyun printf("%s: Error detected in status(0x%X)!\n",
90*4882a593Smuzhiyun __func__, stat);
91*4882a593Smuzhiyun return -EIO;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun if (!transfer_done && (stat & rdy)) {
94*4882a593Smuzhiyun if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & mask))
95*4882a593Smuzhiyun continue;
96*4882a593Smuzhiyun sdhci_writel(host, rdy, SDHCI_INT_STATUS);
97*4882a593Smuzhiyun sdhci_transfer_pio(host, data);
98*4882a593Smuzhiyun data->dest += data->blocksize;
99*4882a593Smuzhiyun if (++block >= data->blocks) {
100*4882a593Smuzhiyun /* Keep looping until the SDHCI_INT_DATA_END is
101*4882a593Smuzhiyun * cleared, even if we finished sending all the
102*4882a593Smuzhiyun * blocks.
103*4882a593Smuzhiyun */
104*4882a593Smuzhiyun transfer_done = true;
105*4882a593Smuzhiyun continue;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun #ifdef CONFIG_MMC_SDHCI_SDMA
109*4882a593Smuzhiyun if (!transfer_done && (stat & SDHCI_INT_DMA_END)) {
110*4882a593Smuzhiyun sdhci_writel(host, SDHCI_INT_DMA_END, SDHCI_INT_STATUS);
111*4882a593Smuzhiyun start_addr &= ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1);
112*4882a593Smuzhiyun start_addr += SDHCI_DEFAULT_BOUNDARY_SIZE;
113*4882a593Smuzhiyun sdhci_writel(host, start_addr, SDHCI_DMA_ADDRESS);
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun #endif
116*4882a593Smuzhiyun if (timeout-- > 0)
117*4882a593Smuzhiyun udelay(10);
118*4882a593Smuzhiyun else {
119*4882a593Smuzhiyun printf("%s: Transfer data timeout\n", __func__);
120*4882a593Smuzhiyun return -ETIMEDOUT;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun } while (!(stat & SDHCI_INT_DATA_END));
123*4882a593Smuzhiyun return 0;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun /*
127*4882a593Smuzhiyun * No command will be sent by driver if card is busy, so driver must wait
128*4882a593Smuzhiyun * for card ready state.
129*4882a593Smuzhiyun * Every time when card is busy after timeout then (last) timeout value will be
130*4882a593Smuzhiyun * increased twice but only if it doesn't exceed global defined maximum.
131*4882a593Smuzhiyun * Each function call will use last timeout value.
132*4882a593Smuzhiyun */
133*4882a593Smuzhiyun #define SDHCI_CMD_MAX_TIMEOUT 3200
134*4882a593Smuzhiyun #define SDHCI_CMD_DEFAULT_TIMEOUT 100
135*4882a593Smuzhiyun #define SDHCI_READ_STATUS_TIMEOUT 1000
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun #ifdef CONFIG_DM_MMC
sdhci_send_command(struct udevice * dev,struct mmc_cmd * cmd,struct mmc_data * data)138*4882a593Smuzhiyun static int sdhci_send_command(struct udevice *dev, struct mmc_cmd *cmd,
139*4882a593Smuzhiyun struct mmc_data *data)
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun struct mmc *mmc = mmc_get_mmc_dev(dev);
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun #else
144*4882a593Smuzhiyun static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
145*4882a593Smuzhiyun struct mmc_data *data)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun #endif
148*4882a593Smuzhiyun struct sdhci_host *host = mmc->priv;
149*4882a593Smuzhiyun unsigned int stat = 0;
150*4882a593Smuzhiyun int ret = 0;
151*4882a593Smuzhiyun int trans_bytes = 0, is_aligned = 1;
152*4882a593Smuzhiyun u32 mask, flags, mode;
153*4882a593Smuzhiyun unsigned int time = 0, start_addr = 0;
154*4882a593Smuzhiyun int mmc_dev = mmc_get_blk_desc(mmc)->devnum;
155*4882a593Smuzhiyun unsigned start = get_timer(0);
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun /* Timeout unit - ms */
158*4882a593Smuzhiyun static unsigned int cmd_timeout = SDHCI_CMD_DEFAULT_TIMEOUT;
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun mask = SDHCI_CMD_INHIBIT;
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun if (data)
163*4882a593Smuzhiyun mask |= SDHCI_DATA_INHIBIT;
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun /* We shouldn't wait for data inihibit for stop commands, even
166*4882a593Smuzhiyun though they might use busy signaling */
167*4882a593Smuzhiyun if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
168*4882a593Smuzhiyun mask &= ~SDHCI_DATA_INHIBIT;
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) {
171*4882a593Smuzhiyun if (time >= cmd_timeout) {
172*4882a593Smuzhiyun printf("%s: MMC: %d busy ", __func__, mmc_dev);
173*4882a593Smuzhiyun if (2 * cmd_timeout <= SDHCI_CMD_MAX_TIMEOUT) {
174*4882a593Smuzhiyun cmd_timeout += cmd_timeout;
175*4882a593Smuzhiyun printf("timeout increasing to: %u ms.\n",
176*4882a593Smuzhiyun cmd_timeout);
177*4882a593Smuzhiyun sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
178*4882a593Smuzhiyun } else {
179*4882a593Smuzhiyun puts("timeout.\n");
180*4882a593Smuzhiyun /* remove timeout return error and try to send command */
181*4882a593Smuzhiyun break;
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun time++;
185*4882a593Smuzhiyun udelay(1000);
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun mask = SDHCI_INT_RESPONSE;
191*4882a593Smuzhiyun if (!(cmd->resp_type & MMC_RSP_PRESENT))
192*4882a593Smuzhiyun flags = SDHCI_CMD_RESP_NONE;
193*4882a593Smuzhiyun else if (cmd->resp_type & MMC_RSP_136)
194*4882a593Smuzhiyun flags = SDHCI_CMD_RESP_LONG;
195*4882a593Smuzhiyun else if (cmd->resp_type & MMC_RSP_BUSY) {
196*4882a593Smuzhiyun flags = SDHCI_CMD_RESP_SHORT_BUSY;
197*4882a593Smuzhiyun if (data)
198*4882a593Smuzhiyun mask |= SDHCI_INT_DATA_END;
199*4882a593Smuzhiyun } else
200*4882a593Smuzhiyun flags = SDHCI_CMD_RESP_SHORT;
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun if (cmd->resp_type & MMC_RSP_CRC)
203*4882a593Smuzhiyun flags |= SDHCI_CMD_CRC;
204*4882a593Smuzhiyun if (cmd->resp_type & MMC_RSP_OPCODE)
205*4882a593Smuzhiyun flags |= SDHCI_CMD_INDEX;
206*4882a593Smuzhiyun if (data)
207*4882a593Smuzhiyun flags |= SDHCI_CMD_DATA;
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun if (cmd->cmdidx == MMC_SEND_TUNING_BLOCK ||
210*4882a593Smuzhiyun cmd->cmdidx == MMC_SEND_TUNING_BLOCK_HS200) {
211*4882a593Smuzhiyun mask &= ~SDHCI_INT_RESPONSE;
212*4882a593Smuzhiyun mask |= SDHCI_INT_DATA_AVAIL;
213*4882a593Smuzhiyun flags |= SDHCI_CMD_DATA;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun /* Set Transfer mode regarding to data flag */
217*4882a593Smuzhiyun if (data != 0) {
218*4882a593Smuzhiyun sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL);
219*4882a593Smuzhiyun mode = SDHCI_TRNS_BLK_CNT_EN;
220*4882a593Smuzhiyun trans_bytes = data->blocks * data->blocksize;
221*4882a593Smuzhiyun if (data->blocks > 1)
222*4882a593Smuzhiyun mode |= SDHCI_TRNS_MULTI;
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun if (data->flags == MMC_DATA_READ)
225*4882a593Smuzhiyun mode |= SDHCI_TRNS_READ;
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun #ifdef CONFIG_MMC_SDHCI_SDMA
228*4882a593Smuzhiyun if (data->flags == MMC_DATA_READ)
229*4882a593Smuzhiyun start_addr = (unsigned long)data->dest;
230*4882a593Smuzhiyun else
231*4882a593Smuzhiyun start_addr = (unsigned long)data->src;
232*4882a593Smuzhiyun if ((host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) &&
233*4882a593Smuzhiyun (start_addr & 0x7) != 0x0) {
234*4882a593Smuzhiyun is_aligned = 0;
235*4882a593Smuzhiyun start_addr = (unsigned long)aligned_buffer;
236*4882a593Smuzhiyun if (data->flags != MMC_DATA_READ)
237*4882a593Smuzhiyun memcpy(aligned_buffer, data->src, trans_bytes);
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun #if defined(CONFIG_FIXED_SDHCI_ALIGNED_BUFFER)
241*4882a593Smuzhiyun /*
242*4882a593Smuzhiyun * Always use this bounce-buffer when
243*4882a593Smuzhiyun * CONFIG_FIXED_SDHCI_ALIGNED_BUFFER is defined
244*4882a593Smuzhiyun */
245*4882a593Smuzhiyun is_aligned = 0;
246*4882a593Smuzhiyun start_addr = (unsigned long)aligned_buffer;
247*4882a593Smuzhiyun if (data->flags != MMC_DATA_READ)
248*4882a593Smuzhiyun memcpy(aligned_buffer, data->src, trans_bytes);
249*4882a593Smuzhiyun #endif
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun sdhci_writel(host, start_addr, SDHCI_DMA_ADDRESS);
252*4882a593Smuzhiyun mode |= SDHCI_TRNS_DMA;
253*4882a593Smuzhiyun #endif
254*4882a593Smuzhiyun sdhci_writew(host, SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG,
255*4882a593Smuzhiyun data->blocksize),
256*4882a593Smuzhiyun SDHCI_BLOCK_SIZE);
257*4882a593Smuzhiyun sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT);
258*4882a593Smuzhiyun sdhci_writew(host, mode, SDHCI_TRANSFER_MODE);
259*4882a593Smuzhiyun } else if (cmd->resp_type & MMC_RSP_BUSY) {
260*4882a593Smuzhiyun sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL);
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun sdhci_writel(host, cmd->cmdarg, SDHCI_ARGUMENT);
264*4882a593Smuzhiyun #ifdef CONFIG_MMC_SDHCI_SDMA
265*4882a593Smuzhiyun if (data != 0) {
266*4882a593Smuzhiyun trans_bytes = ALIGN(trans_bytes, CONFIG_SYS_CACHELINE_SIZE);
267*4882a593Smuzhiyun flush_cache(start_addr, trans_bytes);
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun #endif
270*4882a593Smuzhiyun sdhci_writew(host, SDHCI_MAKE_CMD(cmd->cmdidx, flags), SDHCI_COMMAND);
271*4882a593Smuzhiyun start = get_timer(0);
272*4882a593Smuzhiyun do {
273*4882a593Smuzhiyun stat = sdhci_readl(host, SDHCI_INT_STATUS);
274*4882a593Smuzhiyun if (stat & SDHCI_INT_ERROR)
275*4882a593Smuzhiyun break;
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun if (get_timer(start) >= SDHCI_READ_STATUS_TIMEOUT) {
278*4882a593Smuzhiyun if (host->quirks & SDHCI_QUIRK_BROKEN_R1B) {
279*4882a593Smuzhiyun return 0;
280*4882a593Smuzhiyun } else {
281*4882a593Smuzhiyun printf("%s: Timeout for status update!\n",
282*4882a593Smuzhiyun __func__);
283*4882a593Smuzhiyun return -ETIMEDOUT;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun } while ((stat & mask) != mask);
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun if ((stat & (SDHCI_INT_ERROR | mask)) == mask) {
289*4882a593Smuzhiyun sdhci_cmd_done(host, cmd);
290*4882a593Smuzhiyun sdhci_writel(host, mask, SDHCI_INT_STATUS);
291*4882a593Smuzhiyun } else
292*4882a593Smuzhiyun ret = -1;
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun if (!ret && data)
295*4882a593Smuzhiyun ret = sdhci_transfer_data(host, data, start_addr);
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun if (host->quirks & SDHCI_QUIRK_WAIT_SEND_CMD)
298*4882a593Smuzhiyun udelay(1000);
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun stat = sdhci_readl(host, SDHCI_INT_STATUS);
301*4882a593Smuzhiyun sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
302*4882a593Smuzhiyun if (!ret) {
303*4882a593Smuzhiyun if ((host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) &&
304*4882a593Smuzhiyun !is_aligned && (data->flags == MMC_DATA_READ))
305*4882a593Smuzhiyun memcpy(data->dest, aligned_buffer, trans_bytes);
306*4882a593Smuzhiyun return 0;
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun sdhci_reset(host, SDHCI_RESET_CMD);
310*4882a593Smuzhiyun sdhci_reset(host, SDHCI_RESET_DATA);
311*4882a593Smuzhiyun if (stat & SDHCI_INT_TIMEOUT)
312*4882a593Smuzhiyun return -ETIMEDOUT;
313*4882a593Smuzhiyun else
314*4882a593Smuzhiyun return -ECOMM;
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun void sdhci_enable_clk(struct sdhci_host *host, u16 clk)
318*4882a593Smuzhiyun {
319*4882a593Smuzhiyun unsigned int timeout;
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun clk |= SDHCI_CLOCK_INT_EN;
322*4882a593Smuzhiyun sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun /* Wait max 20 ms */
325*4882a593Smuzhiyun timeout = 20;
326*4882a593Smuzhiyun while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
327*4882a593Smuzhiyun & SDHCI_CLOCK_INT_STABLE)) {
328*4882a593Smuzhiyun if (timeout == 0) {
329*4882a593Smuzhiyun printf("%s: Internal clock never stabilised.\n",
330*4882a593Smuzhiyun __func__);
331*4882a593Smuzhiyun return;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun timeout--;
334*4882a593Smuzhiyun udelay(1000);
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun clk |= SDHCI_CLOCK_CARD_EN;
337*4882a593Smuzhiyun sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun int sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
341*4882a593Smuzhiyun {
342*4882a593Smuzhiyun unsigned int div, clk = 0, timeout;
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun /* Wait max 20 ms */
345*4882a593Smuzhiyun timeout = 200;
346*4882a593Smuzhiyun while (sdhci_readl(host, SDHCI_PRESENT_STATE) &
347*4882a593Smuzhiyun (SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT)) {
348*4882a593Smuzhiyun if (timeout == 0) {
349*4882a593Smuzhiyun printf("%s: Timeout to wait cmd & data inhibit\n",
350*4882a593Smuzhiyun __func__);
351*4882a593Smuzhiyun return -EBUSY;
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun timeout--;
355*4882a593Smuzhiyun udelay(100);
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun if (clock == 0)
360*4882a593Smuzhiyun return 0;
361*4882a593Smuzhiyun if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
362*4882a593Smuzhiyun /*
363*4882a593Smuzhiyun * Check if the Host Controller supports Programmable Clock
364*4882a593Smuzhiyun * Mode.
365*4882a593Smuzhiyun */
366*4882a593Smuzhiyun if (host->clk_mul) {
367*4882a593Smuzhiyun for (div = 1; div <= 1024; div++) {
368*4882a593Smuzhiyun if ((host->max_clk / div) <= clock)
369*4882a593Smuzhiyun break;
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun /*
373*4882a593Smuzhiyun * Set Programmable Clock Mode in the Clock
374*4882a593Smuzhiyun * Control register.
375*4882a593Smuzhiyun */
376*4882a593Smuzhiyun clk = SDHCI_PROG_CLOCK_MODE;
377*4882a593Smuzhiyun div--;
378*4882a593Smuzhiyun } else {
379*4882a593Smuzhiyun /* Version 3.00 divisors must be a multiple of 2. */
380*4882a593Smuzhiyun if (host->max_clk <= clock) {
381*4882a593Smuzhiyun div = 1;
382*4882a593Smuzhiyun } else {
383*4882a593Smuzhiyun for (div = 2;
384*4882a593Smuzhiyun div < SDHCI_MAX_DIV_SPEC_300;
385*4882a593Smuzhiyun div += 2) {
386*4882a593Smuzhiyun if ((host->max_clk / div) <= clock)
387*4882a593Smuzhiyun break;
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun div >>= 1;
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun } else {
393*4882a593Smuzhiyun /* Version 2.00 divisors must be a power of 2. */
394*4882a593Smuzhiyun for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) {
395*4882a593Smuzhiyun if ((host->max_clk / div) <= clock)
396*4882a593Smuzhiyun break;
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun div >>= 1;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun if (host->ops && host->ops->set_clock_ext)
401*4882a593Smuzhiyun host->ops->set_clock_ext(host, div);
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
404*4882a593Smuzhiyun clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
405*4882a593Smuzhiyun << SDHCI_DIVIDER_HI_SHIFT;
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun sdhci_enable_clk(host, clk);
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun host->clock = clock;
410*4882a593Smuzhiyun return 0;
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
414*4882a593Smuzhiyun {
415*4882a593Smuzhiyun u8 pwr = 0;
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun if (power != (unsigned short)-1) {
418*4882a593Smuzhiyun switch (1 << power) {
419*4882a593Smuzhiyun case MMC_VDD_165_195:
420*4882a593Smuzhiyun pwr = SDHCI_POWER_180;
421*4882a593Smuzhiyun break;
422*4882a593Smuzhiyun case MMC_VDD_29_30:
423*4882a593Smuzhiyun case MMC_VDD_30_31:
424*4882a593Smuzhiyun pwr = SDHCI_POWER_300;
425*4882a593Smuzhiyun break;
426*4882a593Smuzhiyun case MMC_VDD_32_33:
427*4882a593Smuzhiyun case MMC_VDD_33_34:
428*4882a593Smuzhiyun pwr = SDHCI_POWER_330;
429*4882a593Smuzhiyun break;
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun if (pwr == 0) {
434*4882a593Smuzhiyun sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
435*4882a593Smuzhiyun return;
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun pwr |= SDHCI_POWER_ON;
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun static void sdhci_set_uhs_signaling(struct sdhci_host *host)
444*4882a593Smuzhiyun {
445*4882a593Smuzhiyun u16 ctrl_2;
446*4882a593Smuzhiyun u32 timing = host->mmc->timing;
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
449*4882a593Smuzhiyun /* Select Bus Speed Mode for host */
450*4882a593Smuzhiyun ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun if ((timing != MMC_TIMING_LEGACY) &&
453*4882a593Smuzhiyun (timing != MMC_TIMING_MMC_HS) &&
454*4882a593Smuzhiyun (timing != MMC_TIMING_SD_HS))
455*4882a593Smuzhiyun ctrl_2 |= SDHCI_CTRL_VDD_180;
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun if ((timing == MMC_TIMING_MMC_HS200) ||
458*4882a593Smuzhiyun (timing == MMC_TIMING_UHS_SDR104))
459*4882a593Smuzhiyun ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_DRV_TYPE_A;
460*4882a593Smuzhiyun else if (timing == MMC_TIMING_UHS_SDR12)
461*4882a593Smuzhiyun ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
462*4882a593Smuzhiyun else if (timing == MMC_TIMING_UHS_SDR25)
463*4882a593Smuzhiyun ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
464*4882a593Smuzhiyun else if ((timing == MMC_TIMING_UHS_SDR50) ||
465*4882a593Smuzhiyun (timing == MMC_TIMING_MMC_HS))
466*4882a593Smuzhiyun ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
467*4882a593Smuzhiyun else if ((timing == MMC_TIMING_UHS_DDR50) ||
468*4882a593Smuzhiyun (timing == MMC_TIMING_MMC_DDR52))
469*4882a593Smuzhiyun ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
470*4882a593Smuzhiyun else if (timing == MMC_TIMING_MMC_HS400 ||
471*4882a593Smuzhiyun timing == MMC_TIMING_MMC_HS400ES)
472*4882a593Smuzhiyun ctrl_2 |= SDHCI_CTRL_HS400 | SDHCI_CTRL_DRV_TYPE_A;
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
475*4882a593Smuzhiyun }
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun #ifdef CONFIG_DM_MMC
478*4882a593Smuzhiyun static bool sdhci_card_busy(struct udevice *dev)
479*4882a593Smuzhiyun {
480*4882a593Smuzhiyun struct mmc *mmc = mmc_get_mmc_dev(dev);
481*4882a593Smuzhiyun #else
482*4882a593Smuzhiyun static bool sdhci_card_busy(struct mmc *mmc)
483*4882a593Smuzhiyun {
484*4882a593Smuzhiyun #endif
485*4882a593Smuzhiyun struct sdhci_host *host = mmc->priv;
486*4882a593Smuzhiyun u32 present_state;
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun /* Check whether DAT[0] is 0 */
489*4882a593Smuzhiyun present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun return !(present_state & SDHCI_DATA_0_LVL);
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun #ifdef CONFIG_DM_MMC
495*4882a593Smuzhiyun static int sdhci_set_ios(struct udevice *dev)
496*4882a593Smuzhiyun {
497*4882a593Smuzhiyun struct mmc *mmc = mmc_get_mmc_dev(dev);
498*4882a593Smuzhiyun #else
499*4882a593Smuzhiyun static int sdhci_set_ios(struct mmc *mmc)
500*4882a593Smuzhiyun {
501*4882a593Smuzhiyun #endif
502*4882a593Smuzhiyun u32 ctrl;
503*4882a593Smuzhiyun struct sdhci_host *host = mmc->priv;
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun if (host->ops && host->ops->set_control_reg)
506*4882a593Smuzhiyun host->ops->set_control_reg(host);
507*4882a593Smuzhiyun
508*4882a593Smuzhiyun if (mmc->clock != host->clock) {
509*4882a593Smuzhiyun if (host->ops && host->ops->set_clock)
510*4882a593Smuzhiyun host->ops->set_clock(host, mmc->clock);
511*4882a593Smuzhiyun else
512*4882a593Smuzhiyun sdhci_set_clock(host, mmc->clock);
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun /* Set bus width */
516*4882a593Smuzhiyun ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
517*4882a593Smuzhiyun if (mmc->bus_width == 8) {
518*4882a593Smuzhiyun ctrl &= ~SDHCI_CTRL_4BITBUS;
519*4882a593Smuzhiyun if ((SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) ||
520*4882a593Smuzhiyun (host->quirks & SDHCI_QUIRK_USE_WIDE8))
521*4882a593Smuzhiyun ctrl |= SDHCI_CTRL_8BITBUS;
522*4882a593Smuzhiyun } else {
523*4882a593Smuzhiyun if ((SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) ||
524*4882a593Smuzhiyun (host->quirks & SDHCI_QUIRK_USE_WIDE8))
525*4882a593Smuzhiyun ctrl &= ~SDHCI_CTRL_8BITBUS;
526*4882a593Smuzhiyun if (mmc->bus_width == 4)
527*4882a593Smuzhiyun ctrl |= SDHCI_CTRL_4BITBUS;
528*4882a593Smuzhiyun else
529*4882a593Smuzhiyun ctrl &= ~SDHCI_CTRL_4BITBUS;
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun
532*4882a593Smuzhiyun if (!(mmc->timing == MMC_TIMING_LEGACY) &&
533*4882a593Smuzhiyun !(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT))
534*4882a593Smuzhiyun ctrl |= SDHCI_CTRL_HISPD;
535*4882a593Smuzhiyun else
536*4882a593Smuzhiyun ctrl &= ~SDHCI_CTRL_HISPD;
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun if ((mmc->timing != MMC_TIMING_LEGACY) &&
541*4882a593Smuzhiyun (mmc->timing != MMC_TIMING_MMC_HS) &&
542*4882a593Smuzhiyun (mmc->timing != MMC_TIMING_SD_HS))
543*4882a593Smuzhiyun sdhci_set_power(host, MMC_VDD_165_195_SHIFT);
544*4882a593Smuzhiyun
545*4882a593Smuzhiyun sdhci_set_uhs_signaling(host);
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun /* If available, call the driver specific "post" set_ios() function */
548*4882a593Smuzhiyun if (host->ops && host->ops->set_ios_post)
549*4882a593Smuzhiyun host->ops->set_ios_post(host);
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun return 0;
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun static int sdhci_init(struct mmc *mmc)
555*4882a593Smuzhiyun {
556*4882a593Smuzhiyun struct sdhci_host *host = mmc->priv;
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun sdhci_reset(host, SDHCI_RESET_ALL);
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun if ((host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) && !aligned_buffer) {
561*4882a593Smuzhiyun aligned_buffer = memalign(8, 512*1024);
562*4882a593Smuzhiyun if (!aligned_buffer) {
563*4882a593Smuzhiyun printf("%s: Aligned buffer alloc failed!!!\n",
564*4882a593Smuzhiyun __func__);
565*4882a593Smuzhiyun return -ENOMEM;
566*4882a593Smuzhiyun }
567*4882a593Smuzhiyun }
568*4882a593Smuzhiyun
569*4882a593Smuzhiyun sdhci_set_power(host, fls(mmc->cfg->voltages) - 1);
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun if (host->ops && host->ops->get_cd)
572*4882a593Smuzhiyun host->ops->get_cd(host);
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun /* Enable only interrupts served by the SD controller */
575*4882a593Smuzhiyun sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK,
576*4882a593Smuzhiyun SDHCI_INT_ENABLE);
577*4882a593Smuzhiyun /* Mask all sdhci interrupt sources */
578*4882a593Smuzhiyun sdhci_writel(host, 0x0, SDHCI_SIGNAL_ENABLE);
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun return 0;
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun static int sdhci_send_tuning(struct sdhci_host *host, u32 opcode)
584*4882a593Smuzhiyun {
585*4882a593Smuzhiyun struct mmc_cmd cmd;
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun cmd.cmdidx = opcode;
588*4882a593Smuzhiyun cmd.resp_type = MMC_RSP_R1;
589*4882a593Smuzhiyun cmd.cmdarg = 0;
590*4882a593Smuzhiyun /*
591*4882a593Smuzhiyun * In response to CMD19, the card sends 64 bytes of tuning
592*4882a593Smuzhiyun * block to the Host Controller. So we set the block size
593*4882a593Smuzhiyun * to 64 here.
594*4882a593Smuzhiyun */
595*4882a593Smuzhiyun if (opcode == MMC_SEND_TUNING_BLOCK_HS200 &&
596*4882a593Smuzhiyun host->mmc->bus_width == MMC_BUS_WIDTH_8BIT)
597*4882a593Smuzhiyun sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 128), SDHCI_BLOCK_SIZE);
598*4882a593Smuzhiyun else
599*4882a593Smuzhiyun sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), SDHCI_BLOCK_SIZE);
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun /*
602*4882a593Smuzhiyun * The tuning block is sent by the card to the host controller.
603*4882a593Smuzhiyun * So we set the TRNS_READ bit in the Transfer Mode register.
604*4882a593Smuzhiyun * This also takes care of setting DMA Enable and Multi Block
605*4882a593Smuzhiyun * Select in the same register to 0.
606*4882a593Smuzhiyun */
607*4882a593Smuzhiyun sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
608*4882a593Smuzhiyun
609*4882a593Smuzhiyun #ifdef CONFIG_DM_MMC
610*4882a593Smuzhiyun return sdhci_send_command(host->mmc->dev, &cmd, NULL);
611*4882a593Smuzhiyun #else
612*4882a593Smuzhiyun return sdhci_send_command(host->mmc, &cmd, NULL);
613*4882a593Smuzhiyun #endif
614*4882a593Smuzhiyun }
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun #define MAX_TUNING_LOOP 40
617*4882a593Smuzhiyun static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
618*4882a593Smuzhiyun {
619*4882a593Smuzhiyun int i;
620*4882a593Smuzhiyun int ret;
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun /*
623*4882a593Smuzhiyun * Issue opcode repeatedly till Execute Tuning is set to 0 or the number
624*4882a593Smuzhiyun * of loops reaches 40 times.
625*4882a593Smuzhiyun */
626*4882a593Smuzhiyun for (i = 0; i < MAX_TUNING_LOOP; i++) {
627*4882a593Smuzhiyun u16 ctrl;
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun ret = sdhci_send_tuning(host, opcode);
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun if (ret)
632*4882a593Smuzhiyun return ret;
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
635*4882a593Smuzhiyun if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) {
636*4882a593Smuzhiyun if (ctrl & SDHCI_CTRL_TUNED_CLK)
637*4882a593Smuzhiyun /* Tuning successfully */
638*4882a593Smuzhiyun return 0;
639*4882a593Smuzhiyun break;
640*4882a593Smuzhiyun }
641*4882a593Smuzhiyun }
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun return -ETIMEDOUT;
644*4882a593Smuzhiyun }
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun #ifdef CONFIG_DM_MMC
647*4882a593Smuzhiyun static int sdhci_execute_tuning(struct udevice *dev, u32 opcode)
648*4882a593Smuzhiyun {
649*4882a593Smuzhiyun struct mmc *mmc = mmc_get_mmc_dev(dev);
650*4882a593Smuzhiyun #else
651*4882a593Smuzhiyun static int sdhci_execute_tuning(struct mmc *mmc, u32 opcode)
652*4882a593Smuzhiyun {
653*4882a593Smuzhiyun #endif
654*4882a593Smuzhiyun struct sdhci_host *host = mmc->priv;
655*4882a593Smuzhiyun u16 ctrl;
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun /*
658*4882a593Smuzhiyun * The Host Controller needs tuning in case of SDR104 and DDR50
659*4882a593Smuzhiyun * mode, and for SDR50 mode when Use Tuning for SDR50 is set in
660*4882a593Smuzhiyun * the Capabilities register.
661*4882a593Smuzhiyun * If the Host Controller supports the HS200 mode then the
662*4882a593Smuzhiyun * tuning function has to be executed.
663*4882a593Smuzhiyun */
664*4882a593Smuzhiyun switch (mmc->timing) {
665*4882a593Smuzhiyun /* HS400 tuning is done in HS200 mode */
666*4882a593Smuzhiyun case MMC_TIMING_MMC_HS400:
667*4882a593Smuzhiyun return -EINVAL;
668*4882a593Smuzhiyun case MMC_TIMING_MMC_HS200:
669*4882a593Smuzhiyun /*
670*4882a593Smuzhiyun * Periodic re-tuning for HS400 is not expected to be needed, so
671*4882a593Smuzhiyun * disable it here.
672*4882a593Smuzhiyun */
673*4882a593Smuzhiyun break;
674*4882a593Smuzhiyun default:
675*4882a593Smuzhiyun return -EINVAL;
676*4882a593Smuzhiyun }
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
679*4882a593Smuzhiyun ctrl |= SDHCI_CTRL_EXEC_TUNING;
680*4882a593Smuzhiyun sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
681*4882a593Smuzhiyun
682*4882a593Smuzhiyun return __sdhci_execute_tuning(host, opcode);
683*4882a593Smuzhiyun }
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun #ifdef CONFIG_DM_MMC
686*4882a593Smuzhiyun int sdhci_probe(struct udevice *dev)
687*4882a593Smuzhiyun {
688*4882a593Smuzhiyun struct mmc *mmc = mmc_get_mmc_dev(dev);
689*4882a593Smuzhiyun
690*4882a593Smuzhiyun return sdhci_init(mmc);
691*4882a593Smuzhiyun }
692*4882a593Smuzhiyun
693*4882a593Smuzhiyun static int sdhci_set_enhanced_strobe(struct udevice *dev)
694*4882a593Smuzhiyun {
695*4882a593Smuzhiyun struct mmc *mmc = mmc_get_mmc_dev(dev);
696*4882a593Smuzhiyun struct sdhci_host *host = mmc->priv;
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun if (host->ops && host->ops->set_enhanced_strobe)
699*4882a593Smuzhiyun return host->ops->set_enhanced_strobe(host);
700*4882a593Smuzhiyun
701*4882a593Smuzhiyun return -ENOTSUPP;
702*4882a593Smuzhiyun }
703*4882a593Smuzhiyun
704*4882a593Smuzhiyun const struct dm_mmc_ops sdhci_ops = {
705*4882a593Smuzhiyun .card_busy = sdhci_card_busy,
706*4882a593Smuzhiyun .send_cmd = sdhci_send_command,
707*4882a593Smuzhiyun .set_ios = sdhci_set_ios,
708*4882a593Smuzhiyun .execute_tuning = sdhci_execute_tuning,
709*4882a593Smuzhiyun .set_enhanced_strobe = sdhci_set_enhanced_strobe,
710*4882a593Smuzhiyun };
711*4882a593Smuzhiyun #else
712*4882a593Smuzhiyun static const struct mmc_ops sdhci_ops = {
713*4882a593Smuzhiyun .card_busy = sdhci_card_busy,
714*4882a593Smuzhiyun .send_cmd = sdhci_send_command,
715*4882a593Smuzhiyun .set_ios = sdhci_set_ios,
716*4882a593Smuzhiyun .init = sdhci_init,
717*4882a593Smuzhiyun .execute_tuning = sdhci_execute_tuning,
718*4882a593Smuzhiyun };
719*4882a593Smuzhiyun #endif
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
722*4882a593Smuzhiyun u32 f_max, u32 f_min)
723*4882a593Smuzhiyun {
724*4882a593Smuzhiyun u32 caps, caps_1;
725*4882a593Smuzhiyun
726*4882a593Smuzhiyun caps = sdhci_readl(host, SDHCI_CAPABILITIES);
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun #ifdef CONFIG_MMC_SDHCI_SDMA
729*4882a593Smuzhiyun if (!(caps & SDHCI_CAN_DO_SDMA)) {
730*4882a593Smuzhiyun printf("%s: Your controller doesn't support SDMA!!\n",
731*4882a593Smuzhiyun __func__);
732*4882a593Smuzhiyun return -EINVAL;
733*4882a593Smuzhiyun }
734*4882a593Smuzhiyun #endif
735*4882a593Smuzhiyun if (host->quirks & SDHCI_QUIRK_REG32_RW)
736*4882a593Smuzhiyun host->version =
737*4882a593Smuzhiyun sdhci_readl(host, SDHCI_HOST_VERSION - 2) >> 16;
738*4882a593Smuzhiyun else
739*4882a593Smuzhiyun host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun cfg->name = host->name;
742*4882a593Smuzhiyun #ifndef CONFIG_DM_MMC
743*4882a593Smuzhiyun cfg->ops = &sdhci_ops;
744*4882a593Smuzhiyun #endif
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun /* Check whether the clock multiplier is supported or not */
747*4882a593Smuzhiyun if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
748*4882a593Smuzhiyun caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
749*4882a593Smuzhiyun host->clk_mul = (caps_1 & SDHCI_CLOCK_MUL_MASK) >>
750*4882a593Smuzhiyun SDHCI_CLOCK_MUL_SHIFT;
751*4882a593Smuzhiyun }
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun if (host->max_clk == 0) {
754*4882a593Smuzhiyun if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
755*4882a593Smuzhiyun host->max_clk = (caps & SDHCI_CLOCK_V3_BASE_MASK) >>
756*4882a593Smuzhiyun SDHCI_CLOCK_BASE_SHIFT;
757*4882a593Smuzhiyun else
758*4882a593Smuzhiyun host->max_clk = (caps & SDHCI_CLOCK_BASE_MASK) >>
759*4882a593Smuzhiyun SDHCI_CLOCK_BASE_SHIFT;
760*4882a593Smuzhiyun host->max_clk *= 1000000;
761*4882a593Smuzhiyun if (host->clk_mul)
762*4882a593Smuzhiyun host->max_clk *= host->clk_mul;
763*4882a593Smuzhiyun }
764*4882a593Smuzhiyun if (host->max_clk == 0) {
765*4882a593Smuzhiyun printf("%s: Hardware doesn't specify base clock frequency\n",
766*4882a593Smuzhiyun __func__);
767*4882a593Smuzhiyun return -EINVAL;
768*4882a593Smuzhiyun }
769*4882a593Smuzhiyun if (f_max && (f_max < host->max_clk))
770*4882a593Smuzhiyun cfg->f_max = f_max;
771*4882a593Smuzhiyun else
772*4882a593Smuzhiyun cfg->f_max = host->max_clk;
773*4882a593Smuzhiyun if (f_min)
774*4882a593Smuzhiyun cfg->f_min = f_min;
775*4882a593Smuzhiyun else {
776*4882a593Smuzhiyun if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
777*4882a593Smuzhiyun cfg->f_min = cfg->f_max / SDHCI_MAX_DIV_SPEC_300;
778*4882a593Smuzhiyun else
779*4882a593Smuzhiyun cfg->f_min = cfg->f_max / SDHCI_MAX_DIV_SPEC_200;
780*4882a593Smuzhiyun }
781*4882a593Smuzhiyun cfg->voltages = 0;
782*4882a593Smuzhiyun if (caps & SDHCI_CAN_VDD_330)
783*4882a593Smuzhiyun cfg->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
784*4882a593Smuzhiyun if (caps & SDHCI_CAN_VDD_300)
785*4882a593Smuzhiyun cfg->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
786*4882a593Smuzhiyun if (caps & SDHCI_CAN_VDD_180)
787*4882a593Smuzhiyun cfg->voltages |= MMC_VDD_165_195;
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE)
790*4882a593Smuzhiyun cfg->voltages |= host->voltages;
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun cfg->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;
793*4882a593Smuzhiyun
794*4882a593Smuzhiyun /* Since Host Controller Version3.0 */
795*4882a593Smuzhiyun if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
796*4882a593Smuzhiyun if (!(caps & SDHCI_CAN_DO_8BIT))
797*4882a593Smuzhiyun cfg->host_caps &= ~MMC_MODE_8BIT;
798*4882a593Smuzhiyun }
799*4882a593Smuzhiyun
800*4882a593Smuzhiyun if (host->host_caps)
801*4882a593Smuzhiyun cfg->host_caps |= host->host_caps;
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun return 0;
806*4882a593Smuzhiyun }
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun #ifdef CONFIG_BLK
809*4882a593Smuzhiyun int sdhci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg)
810*4882a593Smuzhiyun {
811*4882a593Smuzhiyun return mmc_bind(dev, mmc, cfg);
812*4882a593Smuzhiyun }
813*4882a593Smuzhiyun #else
814*4882a593Smuzhiyun int add_sdhci(struct sdhci_host *host, u32 f_max, u32 f_min)
815*4882a593Smuzhiyun {
816*4882a593Smuzhiyun int ret;
817*4882a593Smuzhiyun
818*4882a593Smuzhiyun ret = sdhci_setup_cfg(&host->cfg, host, f_max, f_min);
819*4882a593Smuzhiyun if (ret)
820*4882a593Smuzhiyun return ret;
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun host->mmc = mmc_create(&host->cfg, host);
823*4882a593Smuzhiyun if (host->mmc == NULL) {
824*4882a593Smuzhiyun printf("%s: mmc create fail!\n", __func__);
825*4882a593Smuzhiyun return -ENOMEM;
826*4882a593Smuzhiyun }
827*4882a593Smuzhiyun
828*4882a593Smuzhiyun return 0;
829*4882a593Smuzhiyun }
830*4882a593Smuzhiyun #endif
831