mmc: ftsdc010_mci: fix build error if CONFIG_FTSDC010_SDIO is not defined
[platform/kernel/u-boot.git] / drivers / mmc / ftsdc010_mci.c
1 /*
2  * Faraday MMC/SD Host Controller
3  *
4  * (C) Copyright 2010 Faraday Technology
5  * Dante Su <dantesu@faraday-tech.com>
6  *
7  * This file is released under the terms of GPL v2 and any later version.
8  * See the file COPYING in the root directory of the source tree for details.
9  */
10
11 #include <common.h>
12 #include <malloc.h>
13 #include <part.h>
14 #include <mmc.h>
15
16 #include <asm/io.h>
17 #include <asm/errno.h>
18 #include <asm/byteorder.h>
19 #include <faraday/ftsdc010.h>
20
21 #define CFG_CMD_TIMEOUT (CONFIG_SYS_HZ >> 4) /* 250 ms */
22 #define CFG_RST_TIMEOUT CONFIG_SYS_HZ /* 1 sec reset timeout */
23
24 struct ftsdc010_chip {
25         void __iomem *regs;
26         uint32_t wprot;   /* write protected (locked) */
27         uint32_t rate;    /* actual SD clock in Hz */
28         uint32_t sclk;    /* FTSDC010 source clock in Hz */
29         uint32_t fifo;    /* fifo depth in bytes */
30         uint32_t acmd;
31 };
32
33 static inline int ftsdc010_send_cmd(struct mmc *mmc, struct mmc_cmd *mmc_cmd)
34 {
35         struct ftsdc010_chip *chip = mmc->priv;
36         struct ftsdc010_mmc __iomem *regs = chip->regs;
37         int ret = TIMEOUT;
38         uint32_t ts, st;
39         uint32_t cmd   = FTSDC010_CMD_IDX(mmc_cmd->cmdidx);
40         uint32_t arg   = mmc_cmd->cmdarg;
41         uint32_t flags = mmc_cmd->resp_type;
42
43         cmd |= FTSDC010_CMD_CMD_EN;
44
45         if (chip->acmd) {
46                 cmd |= FTSDC010_CMD_APP_CMD;
47                 chip->acmd = 0;
48         }
49
50         if (flags & MMC_RSP_PRESENT)
51                 cmd |= FTSDC010_CMD_NEED_RSP;
52
53         if (flags & MMC_RSP_136)
54                 cmd |= FTSDC010_CMD_LONG_RSP;
55
56         writel(FTSDC010_STATUS_RSP_MASK | FTSDC010_STATUS_CMD_SEND,
57                 &regs->clr);
58         writel(arg, &regs->argu);
59         writel(cmd, &regs->cmd);
60
61         if (!(flags & (MMC_RSP_PRESENT | MMC_RSP_136))) {
62                 for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) {
63                         if (readl(&regs->status) & FTSDC010_STATUS_CMD_SEND) {
64                                 writel(FTSDC010_STATUS_CMD_SEND, &regs->clr);
65                                 ret = 0;
66                                 break;
67                         }
68                 }
69         } else {
70                 st = 0;
71                 for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) {
72                         st = readl(&regs->status);
73                         writel(st & FTSDC010_STATUS_RSP_MASK, &regs->clr);
74                         if (st & FTSDC010_STATUS_RSP_MASK)
75                                 break;
76                 }
77                 if (st & FTSDC010_STATUS_RSP_CRC_OK) {
78                         if (flags & MMC_RSP_136) {
79                                 mmc_cmd->response[0] = readl(&regs->rsp3);
80                                 mmc_cmd->response[1] = readl(&regs->rsp2);
81                                 mmc_cmd->response[2] = readl(&regs->rsp1);
82                                 mmc_cmd->response[3] = readl(&regs->rsp0);
83                         } else {
84                                 mmc_cmd->response[0] = readl(&regs->rsp0);
85                         }
86                         ret = 0;
87                 } else {
88                         debug("ftsdc010: rsp err (cmd=%d, st=0x%x)\n",
89                                 mmc_cmd->cmdidx, st);
90                 }
91         }
92
93         if (ret) {
94                 debug("ftsdc010: cmd timeout (op code=%d)\n",
95                         mmc_cmd->cmdidx);
96         } else if (mmc_cmd->cmdidx == MMC_CMD_APP_CMD) {
97                 chip->acmd = 1;
98         }
99
100         return ret;
101 }
102
103 static void ftsdc010_clkset(struct mmc *mmc, uint32_t rate)
104 {
105         struct ftsdc010_chip *chip = mmc->priv;
106         struct ftsdc010_mmc __iomem *regs = chip->regs;
107         uint32_t div;
108
109         for (div = 0; div < 0x7f; ++div) {
110                 if (rate >= chip->sclk / (2 * (div + 1)))
111                         break;
112         }
113         chip->rate = chip->sclk / (2 * (div + 1));
114
115         writel(FTSDC010_CCR_CLK_DIV(div), &regs->ccr);
116
117         if (IS_SD(mmc)) {
118                 setbits_le32(&regs->ccr, FTSDC010_CCR_CLK_SD);
119
120                 if (chip->rate > 25000000)
121                         setbits_le32(&regs->ccr, FTSDC010_CCR_CLK_HISPD);
122                 else
123                         clrbits_le32(&regs->ccr, FTSDC010_CCR_CLK_HISPD);
124         }
125 }
126
127 static inline int ftsdc010_is_ro(struct mmc *mmc)
128 {
129         struct ftsdc010_chip *chip = mmc->priv;
130         const uint8_t *csd = (const uint8_t *)mmc->csd;
131
132         return chip->wprot || (csd[1] & 0x30);
133 }
134
135 static int ftsdc010_wait(struct ftsdc010_mmc __iomem *regs, uint32_t mask)
136 {
137         int ret = TIMEOUT;
138         uint32_t st, ts;
139
140         for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) {
141                 st = readl(&regs->status);
142                 if (!(st & mask))
143                         continue;
144                 writel(st & mask, &regs->clr);
145                 ret = 0;
146                 break;
147         }
148
149         if (ret)
150                 debug("ftsdc010: wait st(0x%x) timeout\n", mask);
151
152         return ret;
153 }
154
155 /*
156  * u-boot mmc api
157  */
158
159 static int ftsdc010_request(struct mmc *mmc, struct mmc_cmd *cmd,
160         struct mmc_data *data)
161 {
162         int ret = UNUSABLE_ERR;
163         uint32_t len = 0;
164         struct ftsdc010_chip *chip = mmc->priv;
165         struct ftsdc010_mmc __iomem *regs = chip->regs;
166
167         if (data && (data->flags & MMC_DATA_WRITE) && chip->wprot) {
168                 printf("ftsdc010: the card is write protected!\n");
169                 return ret;
170         }
171
172         if (data) {
173                 uint32_t dcr;
174
175                 len = data->blocksize * data->blocks;
176
177                 /* 1. data disable + fifo reset */
178                 dcr = 0;
179 #ifdef CONFIG_FTSDC010_SDIO
180                 dcr |= FTSDC010_DCR_FIFO_RST;
181 #endif
182                 writel(dcr, &regs->dcr);
183
184                 /* 2. clear status register */
185                 writel(FTSDC010_STATUS_DATA_MASK | FTSDC010_STATUS_FIFO_URUN
186                         | FTSDC010_STATUS_FIFO_ORUN, &regs->clr);
187
188                 /* 3. data timeout (1 sec) */
189                 writel(chip->rate, &regs->dtr);
190
191                 /* 4. data length (bytes) */
192                 writel(len, &regs->dlr);
193
194                 /* 5. data enable */
195                 dcr = (ffs(data->blocksize) - 1) | FTSDC010_DCR_DATA_EN;
196                 if (data->flags & MMC_DATA_WRITE)
197                         dcr |= FTSDC010_DCR_DATA_WRITE;
198                 writel(dcr, &regs->dcr);
199         }
200
201         ret = ftsdc010_send_cmd(mmc, cmd);
202         if (ret) {
203                 printf("ftsdc010: CMD%d failed\n", cmd->cmdidx);
204                 return ret;
205         }
206
207         if (!data)
208                 return ret;
209
210         if (data->flags & MMC_DATA_WRITE) {
211                 const uint8_t *buf = (const uint8_t *)data->src;
212
213                 while (len > 0) {
214                         int wlen;
215
216                         /* wait for tx ready */
217                         ret = ftsdc010_wait(regs, FTSDC010_STATUS_FIFO_URUN);
218                         if (ret)
219                                 break;
220
221                         /* write bytes to ftsdc010 */
222                         for (wlen = 0; wlen < len && wlen < chip->fifo; ) {
223                                 writel(*(uint32_t *)buf, &regs->dwr);
224                                 buf  += 4;
225                                 wlen += 4;
226                         }
227
228                         len -= wlen;
229                 }
230
231         } else {
232                 uint8_t *buf = (uint8_t *)data->dest;
233
234                 while (len > 0) {
235                         int rlen;
236
237                         /* wait for rx ready */
238                         ret = ftsdc010_wait(regs, FTSDC010_STATUS_FIFO_ORUN);
239                         if (ret)
240                                 break;
241
242                         /* fetch bytes from ftsdc010 */
243                         for (rlen = 0; rlen < len && rlen < chip->fifo; ) {
244                                 *(uint32_t *)buf = readl(&regs->dwr);
245                                 buf  += 4;
246                                 rlen += 4;
247                         }
248
249                         len -= rlen;
250                 }
251
252         }
253
254         if (!ret) {
255                 ret = ftsdc010_wait(regs,
256                         FTSDC010_STATUS_DATA_END | FTSDC010_STATUS_DATA_ERROR);
257         }
258
259         return ret;
260 }
261
262 static void ftsdc010_set_ios(struct mmc *mmc)
263 {
264         struct ftsdc010_chip *chip = mmc->priv;
265         struct ftsdc010_mmc __iomem *regs = chip->regs;
266
267         ftsdc010_clkset(mmc, mmc->clock);
268
269         clrbits_le32(&regs->bwr, FTSDC010_BWR_MODE_MASK);
270         switch (mmc->bus_width) {
271         case 4:
272                 setbits_le32(&regs->bwr, FTSDC010_BWR_MODE_4BIT);
273                 break;
274         case 8:
275                 setbits_le32(&regs->bwr, FTSDC010_BWR_MODE_8BIT);
276                 break;
277         default:
278                 setbits_le32(&regs->bwr, FTSDC010_BWR_MODE_1BIT);
279                 break;
280         }
281 }
282
283 static int ftsdc010_init(struct mmc *mmc)
284 {
285         struct ftsdc010_chip *chip = mmc->priv;
286         struct ftsdc010_mmc __iomem *regs = chip->regs;
287         uint32_t ts;
288
289         if (readl(&regs->status) & FTSDC010_STATUS_CARD_DETECT)
290                 return NO_CARD_ERR;
291
292         if (readl(&regs->status) & FTSDC010_STATUS_WRITE_PROT) {
293                 printf("ftsdc010: write protected\n");
294                 chip->wprot = 1;
295         }
296
297         chip->fifo = (readl(&regs->feature) & 0xff) << 2;
298
299         /* 1. chip reset */
300         writel(FTSDC010_CMD_SDC_RST, &regs->cmd);
301         for (ts = get_timer(0); get_timer(ts) < CFG_RST_TIMEOUT; ) {
302                 if (readl(&regs->cmd) & FTSDC010_CMD_SDC_RST)
303                         continue;
304                 break;
305         }
306         if (readl(&regs->cmd) & FTSDC010_CMD_SDC_RST) {
307                 printf("ftsdc010: reset failed\n");
308                 return UNUSABLE_ERR;
309         }
310
311         /* 2. enter low speed mode (400k card detection) */
312         ftsdc010_clkset(mmc, 400000);
313
314         /* 3. interrupt disabled */
315         writel(0, &regs->int_mask);
316
317         return 0;
318 }
319
320 int ftsdc010_mmc_init(int devid)
321 {
322         struct mmc *mmc;
323         struct ftsdc010_chip *chip;
324         struct ftsdc010_mmc __iomem *regs;
325 #ifdef CONFIG_FTSDC010_BASE_LIST
326         uint32_t base_list[] = CONFIG_FTSDC010_BASE_LIST;
327
328         if (devid < 0 || devid >= ARRAY_SIZE(base_list))
329                 return -1;
330         regs = (void __iomem *)base_list[devid];
331 #else
332         regs = (void __iomem *)(CONFIG_FTSDC010_BASE + (devid << 20));
333 #endif
334
335         mmc = malloc(sizeof(struct mmc));
336         if (!mmc)
337                 return -ENOMEM;
338         memset(mmc, 0, sizeof(struct mmc));
339
340         chip = malloc(sizeof(struct ftsdc010_chip));
341         if (!chip) {
342                 free(mmc);
343                 return -ENOMEM;
344         }
345         memset(chip, 0, sizeof(struct ftsdc010_chip));
346
347         chip->regs = regs;
348         mmc->priv  = chip;
349
350         sprintf(mmc->name, "ftsdc010");
351         mmc->send_cmd  = ftsdc010_request;
352         mmc->set_ios   = ftsdc010_set_ios;
353         mmc->init      = ftsdc010_init;
354
355         mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz;
356         switch (readl(&regs->bwr) & FTSDC010_BWR_CAPS_MASK) {
357         case FTSDC010_BWR_CAPS_4BIT:
358                 mmc->host_caps |= MMC_MODE_4BIT;
359                 break;
360         case FTSDC010_BWR_CAPS_8BIT:
361                 mmc->host_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
362                 break;
363         default:
364                 break;
365         }
366
367 #ifdef CONFIG_SYS_CLK_FREQ
368         chip->sclk = CONFIG_SYS_CLK_FREQ;
369 #else
370         chip->sclk = clk_get_rate("SDC");
371 #endif
372
373         mmc->voltages  = MMC_VDD_32_33 | MMC_VDD_33_34;
374         mmc->f_max     = chip->sclk / 2;
375         mmc->f_min     = chip->sclk / 0x100;
376         mmc->block_dev.part_type = PART_TYPE_DOS;
377
378         mmc_register(mmc);
379
380         return 0;
381 }