]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/mmc/dw_mmc.c
upgrade to upstream version 2013.07
[karo-tx-uboot.git] / drivers / mmc / dw_mmc.c
1 /*
2  * (C) Copyright 2012 SAMSUNG Electronics
3  * Jaehoon Chung <jh80.chung@samsung.com>
4  * Rajeshawari Shinde <rajeshwari.s@samsung.com>
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #include <common.h>
10 #include <malloc.h>
11 #include <mmc.h>
12 #include <dwmmc.h>
13 #include <asm-generic/errno.h>
14
15 #define PAGE_SIZE 4096
16
17 static int dwmci_wait_reset(struct dwmci_host *host, u32 value)
18 {
19         unsigned long timeout = 1000;
20         u32 ctrl;
21
22         dwmci_writel(host, DWMCI_CTRL, value);
23
24         while (timeout--) {
25                 ctrl = dwmci_readl(host, DWMCI_CTRL);
26                 if (!(ctrl & DWMCI_RESET_ALL))
27                         return 1;
28         }
29         return 0;
30 }
31
32 static void dwmci_set_idma_desc(struct dwmci_idmac *idmac,
33                 u32 desc0, u32 desc1, u32 desc2)
34 {
35         struct dwmci_idmac *desc = idmac;
36
37         desc->flags = desc0;
38         desc->cnt = desc1;
39         desc->addr = desc2;
40         desc->next_addr = (unsigned int)desc + sizeof(struct dwmci_idmac);
41 }
42
43 static void dwmci_prepare_data(struct dwmci_host *host,
44                 struct mmc_data *data)
45 {
46         unsigned long ctrl;
47         unsigned int i = 0, flags, cnt, blk_cnt;
48         ulong data_start, data_end, start_addr;
49         ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac, data->blocks);
50
51
52         blk_cnt = data->blocks;
53
54         dwmci_wait_reset(host, DWMCI_CTRL_FIFO_RESET);
55
56         data_start = (ulong)cur_idmac;
57         dwmci_writel(host, DWMCI_DBADDR, (unsigned int)cur_idmac);
58
59         if (data->flags == MMC_DATA_READ)
60                 start_addr = (unsigned int)data->dest;
61         else
62                 start_addr = (unsigned int)data->src;
63
64         do {
65                 flags = DWMCI_IDMAC_OWN | DWMCI_IDMAC_CH ;
66                 flags |= (i == 0) ? DWMCI_IDMAC_FS : 0;
67                 if (blk_cnt <= 8) {
68                         flags |= DWMCI_IDMAC_LD;
69                         cnt = data->blocksize * blk_cnt;
70                 } else
71                         cnt = data->blocksize * 8;
72
73                 dwmci_set_idma_desc(cur_idmac, flags, cnt,
74                                 start_addr + (i * PAGE_SIZE));
75
76                 if(blk_cnt < 8)
77                         break;
78                 blk_cnt -= 8;
79                 cur_idmac++;
80                 i++;
81         } while(1);
82
83         data_end = (ulong)cur_idmac;
84         flush_dcache_range(data_start, data_end + ARCH_DMA_MINALIGN);
85
86         ctrl = dwmci_readl(host, DWMCI_CTRL);
87         ctrl |= DWMCI_IDMAC_EN | DWMCI_DMA_EN;
88         dwmci_writel(host, DWMCI_CTRL, ctrl);
89
90         ctrl = dwmci_readl(host, DWMCI_BMOD);
91         ctrl |= DWMCI_BMOD_IDMAC_FB | DWMCI_BMOD_IDMAC_EN;
92         dwmci_writel(host, DWMCI_BMOD, ctrl);
93
94         dwmci_writel(host, DWMCI_BLKSIZ, data->blocksize);
95         dwmci_writel(host, DWMCI_BYTCNT, data->blocksize * data->blocks);
96 }
97
98 static int dwmci_set_transfer_mode(struct dwmci_host *host,
99                 struct mmc_data *data)
100 {
101         unsigned long mode;
102
103         mode = DWMCI_CMD_DATA_EXP;
104         if (data->flags & MMC_DATA_WRITE)
105                 mode |= DWMCI_CMD_RW;
106
107         return mode;
108 }
109
110 static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
111                 struct mmc_data *data)
112 {
113         struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
114         int flags = 0, i;
115         unsigned int timeout = 100000;
116         u32 retry = 10000;
117         u32 mask, ctrl;
118         ulong start = get_timer(0);
119
120         while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) {
121                 if (get_timer(start) > timeout) {
122                         printf("Timeout on data busy\n");
123                         return TIMEOUT;
124                 }
125         }
126
127         dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL);
128
129         if (data)
130                 dwmci_prepare_data(host, data);
131
132         dwmci_writel(host, DWMCI_CMDARG, cmd->cmdarg);
133
134         if (data)
135                 flags = dwmci_set_transfer_mode(host, data);
136
137         if ((cmd->resp_type & MMC_RSP_136) && (cmd->resp_type & MMC_RSP_BUSY))
138                 return -1;
139
140         if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
141                 flags |= DWMCI_CMD_ABORT_STOP;
142         else
143                 flags |= DWMCI_CMD_PRV_DAT_WAIT;
144
145         if (cmd->resp_type & MMC_RSP_PRESENT) {
146                 flags |= DWMCI_CMD_RESP_EXP;
147                 if (cmd->resp_type & MMC_RSP_136)
148                         flags |= DWMCI_CMD_RESP_LENGTH;
149         }
150
151         if (cmd->resp_type & MMC_RSP_CRC)
152                 flags |= DWMCI_CMD_CHECK_CRC;
153
154         flags |= (cmd->cmdidx | DWMCI_CMD_START | DWMCI_CMD_USE_HOLD_REG);
155
156         debug("Sending CMD%d\n",cmd->cmdidx);
157
158         dwmci_writel(host, DWMCI_CMD, flags);
159
160         for (i = 0; i < retry; i++) {
161                 mask = dwmci_readl(host, DWMCI_RINTSTS);
162                 if (mask & DWMCI_INTMSK_CDONE) {
163                         if (!data)
164                                 dwmci_writel(host, DWMCI_RINTSTS, mask);
165                         break;
166                 }
167         }
168
169         if (i == retry)
170                 return TIMEOUT;
171
172         if (mask & DWMCI_INTMSK_RTO) {
173                 debug("Response Timeout..\n");
174                 return TIMEOUT;
175         } else if (mask & DWMCI_INTMSK_RE) {
176                 debug("Response Error..\n");
177                 return -1;
178         }
179
180
181         if (cmd->resp_type & MMC_RSP_PRESENT) {
182                 if (cmd->resp_type & MMC_RSP_136) {
183                         cmd->response[0] = dwmci_readl(host, DWMCI_RESP3);
184                         cmd->response[1] = dwmci_readl(host, DWMCI_RESP2);
185                         cmd->response[2] = dwmci_readl(host, DWMCI_RESP1);
186                         cmd->response[3] = dwmci_readl(host, DWMCI_RESP0);
187                 } else {
188                         cmd->response[0] = dwmci_readl(host, DWMCI_RESP0);
189                 }
190         }
191
192         if (data) {
193                 do {
194                         mask = dwmci_readl(host, DWMCI_RINTSTS);
195                         if (mask & (DWMCI_DATA_ERR | DWMCI_DATA_TOUT)) {
196                                 debug("DATA ERROR!\n");
197                                 return -1;
198                         }
199                 } while (!(mask & DWMCI_INTMSK_DTO));
200
201                 dwmci_writel(host, DWMCI_RINTSTS, mask);
202
203                 ctrl = dwmci_readl(host, DWMCI_CTRL);
204                 ctrl &= ~(DWMCI_DMA_EN);
205                 dwmci_writel(host, DWMCI_CTRL, ctrl);
206         }
207
208         udelay(100);
209
210         return 0;
211 }
212
213 static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
214 {
215         u32 div, status;
216         int timeout = 10000;
217         unsigned long sclk;
218
219         if ((freq == host->clock) || (freq == 0))
220                 return 0;
221         /*
222          * If host->mmc_clk didn't define,
223          * then assume that host->bus_hz is source clock value.
224          * host->bus_hz should be set from user.
225          */
226         if (host->mmc_clk)
227                 sclk = host->mmc_clk(host->dev_index);
228         else if (host->bus_hz)
229                 sclk = host->bus_hz;
230         else {
231                 printf("Didn't get source clock value..\n");
232                 return -EINVAL;
233         }
234
235         div = DIV_ROUND_UP(sclk, 2 * freq);
236
237         dwmci_writel(host, DWMCI_CLKENA, 0);
238         dwmci_writel(host, DWMCI_CLKSRC, 0);
239
240         dwmci_writel(host, DWMCI_CLKDIV, div);
241         dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_PRV_DAT_WAIT |
242                         DWMCI_CMD_UPD_CLK | DWMCI_CMD_START);
243
244         do {
245                 status = dwmci_readl(host, DWMCI_CMD);
246                 if (timeout-- < 0) {
247                         printf("TIMEOUT error!!\n");
248                         return -ETIMEDOUT;
249                 }
250         } while (status & DWMCI_CMD_START);
251
252         dwmci_writel(host, DWMCI_CLKENA, DWMCI_CLKEN_ENABLE |
253                         DWMCI_CLKEN_LOW_PWR);
254
255         dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_PRV_DAT_WAIT |
256                         DWMCI_CMD_UPD_CLK | DWMCI_CMD_START);
257
258         timeout = 10000;
259         do {
260                 status = dwmci_readl(host, DWMCI_CMD);
261                 if (timeout-- < 0) {
262                         printf("TIMEOUT error!!\n");
263                         return -ETIMEDOUT;
264                 }
265         } while (status & DWMCI_CMD_START);
266
267         host->clock = freq;
268
269         return 0;
270 }
271
272 static void dwmci_set_ios(struct mmc *mmc)
273 {
274         struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
275         u32 ctype;
276
277         debug("Buswidth = %d, clock: %d\n",mmc->bus_width, mmc->clock);
278
279         dwmci_setup_bus(host, mmc->clock);
280         switch (mmc->bus_width) {
281         case 8:
282                 ctype = DWMCI_CTYPE_8BIT;
283                 break;
284         case 4:
285                 ctype = DWMCI_CTYPE_4BIT;
286                 break;
287         default:
288                 ctype = DWMCI_CTYPE_1BIT;
289                 break;
290         }
291
292         dwmci_writel(host, DWMCI_CTYPE, ctype);
293
294         if (host->clksel)
295                 host->clksel(host);
296 }
297
298 static int dwmci_init(struct mmc *mmc)
299 {
300         struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
301         u32 fifo_size;
302
303         dwmci_writel(host, DWMCI_PWREN, 1);
304
305         if (!dwmci_wait_reset(host, DWMCI_RESET_ALL)) {
306                 debug("%s[%d] Fail-reset!!\n",__func__,__LINE__);
307                 return -1;
308         }
309
310         /* Enumerate at 400KHz */
311         dwmci_setup_bus(host, mmc->f_min);
312
313         dwmci_writel(host, DWMCI_RINTSTS, 0xFFFFFFFF);
314         dwmci_writel(host, DWMCI_INTMASK, 0);
315
316         dwmci_writel(host, DWMCI_TMOUT, 0xFFFFFFFF);
317
318         dwmci_writel(host, DWMCI_IDINTEN, 0);
319         dwmci_writel(host, DWMCI_BMOD, 1);
320
321         if (!host->fifoth_val) {
322                 fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
323                 fifo_size = ((fifo_size & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1;
324                 host->fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size / 2 - 1) |
325                         TX_WMARK(fifo_size / 2);
326         }
327         dwmci_writel(host, DWMCI_FIFOTH, host->fifoth_val);
328
329         dwmci_writel(host, DWMCI_CLKENA, 0);
330         dwmci_writel(host, DWMCI_CLKSRC, 0);
331
332         return 0;
333 }
334
335 int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk)
336 {
337         struct mmc *mmc;
338         int err = 0;
339
340         mmc = malloc(sizeof(struct mmc));
341         if (!mmc) {
342                 printf("mmc malloc fail!\n");
343                 return -1;
344         }
345
346         mmc->priv = host;
347         host->mmc = mmc;
348
349         sprintf(mmc->name, "%s", host->name);
350         mmc->send_cmd = dwmci_send_cmd;
351         mmc->set_ios = dwmci_set_ios;
352         mmc->init = dwmci_init;
353         mmc->f_min = min_clk;
354         mmc->f_max = max_clk;
355
356         mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
357
358         mmc->host_caps = host->caps;
359
360         if (host->buswidth == 8) {
361                 mmc->host_caps |= MMC_MODE_8BIT;
362                 mmc->host_caps &= ~MMC_MODE_4BIT;
363         } else {
364                 mmc->host_caps |= MMC_MODE_4BIT;
365                 mmc->host_caps &= ~MMC_MODE_8BIT;
366         }
367         mmc->host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_HC;
368
369         err = mmc_register(mmc);
370
371         return err;
372 }