]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/mmc/dw_mmc.c
Merge branch 'master' of git://git.denx.de/u-boot-blackfin
[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 #include <asm/arch/dwmmc.h>
15
16 #define PAGE_SIZE 4096
17
18 static int dwmci_wait_reset(struct dwmci_host *host, u32 value)
19 {
20         unsigned long timeout = 1000;
21         u32 ctrl;
22
23         dwmci_writel(host, DWMCI_CTRL, value);
24
25         while (timeout--) {
26                 ctrl = dwmci_readl(host, DWMCI_CTRL);
27                 if (!(ctrl & DWMCI_RESET_ALL))
28                         return 1;
29         }
30         return 0;
31 }
32
33 static void dwmci_set_idma_desc(struct dwmci_idmac *idmac,
34                 u32 desc0, u32 desc1, u32 desc2)
35 {
36         struct dwmci_idmac *desc = idmac;
37
38         desc->flags = desc0;
39         desc->cnt = desc1;
40         desc->addr = desc2;
41         desc->next_addr = (unsigned int)desc + sizeof(struct dwmci_idmac);
42 }
43
44 static void dwmci_prepare_data(struct dwmci_host *host,
45                 struct mmc_data *data, struct dwmci_idmac *cur_idmac)
46 {
47         unsigned long ctrl;
48         unsigned int i = 0, flags, cnt, blk_cnt;
49         ulong data_start, data_end, start_addr;
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         ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac,
115                                  data ? DIV_ROUND_UP(data->blocks, 8) : 0);
116         int flags = 0, i;
117         unsigned int timeout = 100000;
118         u32 retry = 10000;
119         u32 mask, ctrl;
120         ulong start = get_timer(0);
121
122         while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) {
123                 if (get_timer(start) > timeout) {
124                         printf("Timeout on data busy\n");
125                         return TIMEOUT;
126                 }
127         }
128
129         dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL);
130
131         if (data)
132                 dwmci_prepare_data(host, data, cur_idmac);
133
134         dwmci_writel(host, DWMCI_CMDARG, cmd->cmdarg);
135
136         if (data)
137                 flags = dwmci_set_transfer_mode(host, data);
138
139         if ((cmd->resp_type & MMC_RSP_136) && (cmd->resp_type & MMC_RSP_BUSY))
140                 return -1;
141
142         if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
143                 flags |= DWMCI_CMD_ABORT_STOP;
144         else
145                 flags |= DWMCI_CMD_PRV_DAT_WAIT;
146
147         if (cmd->resp_type & MMC_RSP_PRESENT) {
148                 flags |= DWMCI_CMD_RESP_EXP;
149                 if (cmd->resp_type & MMC_RSP_136)
150                         flags |= DWMCI_CMD_RESP_LENGTH;
151         }
152
153         if (cmd->resp_type & MMC_RSP_CRC)
154                 flags |= DWMCI_CMD_CHECK_CRC;
155
156         flags |= (cmd->cmdidx | DWMCI_CMD_START | DWMCI_CMD_USE_HOLD_REG);
157
158         debug("Sending CMD%d\n",cmd->cmdidx);
159
160         dwmci_writel(host, DWMCI_CMD, flags);
161
162         for (i = 0; i < retry; i++) {
163                 mask = dwmci_readl(host, DWMCI_RINTSTS);
164                 if (mask & DWMCI_INTMSK_CDONE) {
165                         if (!data)
166                                 dwmci_writel(host, DWMCI_RINTSTS, mask);
167                         break;
168                 }
169         }
170
171         if (i == retry)
172                 return TIMEOUT;
173
174         if (mask & DWMCI_INTMSK_RTO) {
175                 debug("Response Timeout..\n");
176                 return TIMEOUT;
177         } else if (mask & DWMCI_INTMSK_RE) {
178                 debug("Response Error..\n");
179                 return -1;
180         }
181
182
183         if (cmd->resp_type & MMC_RSP_PRESENT) {
184                 if (cmd->resp_type & MMC_RSP_136) {
185                         cmd->response[0] = dwmci_readl(host, DWMCI_RESP3);
186                         cmd->response[1] = dwmci_readl(host, DWMCI_RESP2);
187                         cmd->response[2] = dwmci_readl(host, DWMCI_RESP1);
188                         cmd->response[3] = dwmci_readl(host, DWMCI_RESP0);
189                 } else {
190                         cmd->response[0] = dwmci_readl(host, DWMCI_RESP0);
191                 }
192         }
193
194         if (data) {
195                 do {
196                         mask = dwmci_readl(host, DWMCI_RINTSTS);
197                         if (mask & (DWMCI_DATA_ERR | DWMCI_DATA_TOUT)) {
198                                 debug("DATA ERROR!\n");
199                                 return -1;
200                         }
201                 } while (!(mask & DWMCI_INTMSK_DTO));
202
203                 dwmci_writel(host, DWMCI_RINTSTS, mask);
204
205                 ctrl = dwmci_readl(host, DWMCI_CTRL);
206                 ctrl &= ~(DWMCI_DMA_EN);
207                 dwmci_writel(host, DWMCI_CTRL, ctrl);
208         }
209
210         udelay(100);
211
212         return 0;
213 }
214
215 static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
216 {
217         u32 div, status;
218         int timeout = 10000;
219         unsigned long sclk;
220
221         if ((freq == host->clock) || (freq == 0))
222                 return 0;
223         /*
224          * If host->get_mmc_clk didn't define,
225          * then assume that host->bus_hz is source clock value.
226          * host->bus_hz should be set from user.
227          */
228         if (host->get_mmc_clk)
229                 sclk = host->get_mmc_clk(host->dev_index);
230         else if (host->bus_hz)
231                 sclk = host->bus_hz;
232         else {
233                 printf("Didn't get source clock value..\n");
234                 return -EINVAL;
235         }
236
237         div = DIV_ROUND_UP(sclk, 2 * freq);
238
239         dwmci_writel(host, DWMCI_CLKENA, 0);
240         dwmci_writel(host, DWMCI_CLKSRC, 0);
241
242         dwmci_writel(host, DWMCI_CLKDIV, div);
243         dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_PRV_DAT_WAIT |
244                         DWMCI_CMD_UPD_CLK | DWMCI_CMD_START);
245
246         do {
247                 status = dwmci_readl(host, DWMCI_CMD);
248                 if (timeout-- < 0) {
249                         printf("TIMEOUT error!!\n");
250                         return -ETIMEDOUT;
251                 }
252         } while (status & DWMCI_CMD_START);
253
254         dwmci_writel(host, DWMCI_CLKENA, DWMCI_CLKEN_ENABLE |
255                         DWMCI_CLKEN_LOW_PWR);
256
257         dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_PRV_DAT_WAIT |
258                         DWMCI_CMD_UPD_CLK | DWMCI_CMD_START);
259
260         timeout = 10000;
261         do {
262                 status = dwmci_readl(host, DWMCI_CMD);
263                 if (timeout-- < 0) {
264                         printf("TIMEOUT error!!\n");
265                         return -ETIMEDOUT;
266                 }
267         } while (status & DWMCI_CMD_START);
268
269         host->clock = freq;
270
271         return 0;
272 }
273
274 static void dwmci_set_ios(struct mmc *mmc)
275 {
276         struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
277         u32 ctype;
278
279         debug("Buswidth = %d, clock: %d\n",mmc->bus_width, mmc->clock);
280
281         dwmci_setup_bus(host, mmc->clock);
282         switch (mmc->bus_width) {
283         case 8:
284                 ctype = DWMCI_CTYPE_8BIT;
285                 break;
286         case 4:
287                 ctype = DWMCI_CTYPE_4BIT;
288                 break;
289         default:
290                 ctype = DWMCI_CTYPE_1BIT;
291                 break;
292         }
293
294         dwmci_writel(host, DWMCI_CTYPE, ctype);
295
296         if (host->clksel)
297                 host->clksel(host);
298 }
299
300 static int dwmci_init(struct mmc *mmc)
301 {
302         struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
303         u32 fifo_size;
304
305         if (host->quirks & DWMCI_QUIRK_DISABLE_SMU) {
306                 dwmci_writel(host, EMMCP_MPSBEGIN0, 0);
307                 dwmci_writel(host, EMMCP_SEND0, 0);
308                 dwmci_writel(host, EMMCP_CTRL0,
309                              MPSCTRL_SECURE_READ_BIT |
310                              MPSCTRL_SECURE_WRITE_BIT |
311                              MPSCTRL_NON_SECURE_READ_BIT |
312                              MPSCTRL_NON_SECURE_WRITE_BIT | MPSCTRL_VALID);
313         }
314
315         dwmci_writel(host, DWMCI_PWREN, 1);
316
317         if (!dwmci_wait_reset(host, DWMCI_RESET_ALL)) {
318                 debug("%s[%d] Fail-reset!!\n",__func__,__LINE__);
319                 return -1;
320         }
321
322         /* Enumerate at 400KHz */
323         dwmci_setup_bus(host, mmc->f_min);
324
325         dwmci_writel(host, DWMCI_RINTSTS, 0xFFFFFFFF);
326         dwmci_writel(host, DWMCI_INTMASK, 0);
327
328         dwmci_writel(host, DWMCI_TMOUT, 0xFFFFFFFF);
329
330         dwmci_writel(host, DWMCI_IDINTEN, 0);
331         dwmci_writel(host, DWMCI_BMOD, 1);
332
333         if (!host->fifoth_val) {
334                 fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
335                 fifo_size = ((fifo_size & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1;
336                 host->fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size / 2 - 1) |
337                         TX_WMARK(fifo_size / 2);
338         }
339         dwmci_writel(host, DWMCI_FIFOTH, host->fifoth_val);
340
341         dwmci_writel(host, DWMCI_CLKENA, 0);
342         dwmci_writel(host, DWMCI_CLKSRC, 0);
343
344         return 0;
345 }
346
347 int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk)
348 {
349         struct mmc *mmc;
350         int err = 0;
351
352         mmc = malloc(sizeof(struct mmc));
353         if (!mmc) {
354                 printf("mmc malloc fail!\n");
355                 return -1;
356         }
357
358         mmc->priv = host;
359         host->mmc = mmc;
360
361         sprintf(mmc->name, "%s", host->name);
362         mmc->send_cmd = dwmci_send_cmd;
363         mmc->set_ios = dwmci_set_ios;
364         mmc->init = dwmci_init;
365         mmc->f_min = min_clk;
366         mmc->f_max = max_clk;
367
368         mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
369
370         mmc->host_caps = host->caps;
371
372         if (host->buswidth == 8) {
373                 mmc->host_caps |= MMC_MODE_8BIT;
374                 mmc->host_caps &= ~MMC_MODE_4BIT;
375         } else {
376                 mmc->host_caps |= MMC_MODE_4BIT;
377                 mmc->host_caps &= ~MMC_MODE_8BIT;
378         }
379         mmc->host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_HC;
380
381         err = mmc_register(mmc);
382
383         return err;
384 }