]> git.sur5r.net Git - u-boot/blob - drivers/mmc/ftsdc010_mci.c
5506ef4460505ff892ad11c4e894cfa300a0f07a
[u-boot] / 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  * SPDX-License-Identifier:     GPL-2.0+
8  */
9
10 #include <common.h>
11 #include <malloc.h>
12 #include <part.h>
13 #include <mmc.h>
14
15 #include <linux/io.h>
16 #include <linux/errno.h>
17 #include <asm/byteorder.h>
18 #include <faraday/ftsdc010.h>
19 #include "ftsdc010_mci.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 static inline int ftsdc010_send_cmd(struct mmc *mmc, struct mmc_cmd *mmc_cmd)
25 {
26         struct ftsdc010_chip *chip = mmc->priv;
27         struct ftsdc010_mmc __iomem *regs = chip->regs;
28         int ret = -ETIMEDOUT;
29         uint32_t ts, st;
30         uint32_t cmd   = FTSDC010_CMD_IDX(mmc_cmd->cmdidx);
31         uint32_t arg   = mmc_cmd->cmdarg;
32         uint32_t flags = mmc_cmd->resp_type;
33
34         cmd |= FTSDC010_CMD_CMD_EN;
35
36         if (chip->acmd) {
37                 cmd |= FTSDC010_CMD_APP_CMD;
38                 chip->acmd = 0;
39         }
40
41         if (flags & MMC_RSP_PRESENT)
42                 cmd |= FTSDC010_CMD_NEED_RSP;
43
44         if (flags & MMC_RSP_136)
45                 cmd |= FTSDC010_CMD_LONG_RSP;
46
47         writel(FTSDC010_STATUS_RSP_MASK | FTSDC010_STATUS_CMD_SEND,
48                 &regs->clr);
49         writel(arg, &regs->argu);
50         writel(cmd, &regs->cmd);
51
52         if (!(flags & (MMC_RSP_PRESENT | MMC_RSP_136))) {
53                 for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) {
54                         if (readl(&regs->status) & FTSDC010_STATUS_CMD_SEND) {
55                                 writel(FTSDC010_STATUS_CMD_SEND, &regs->clr);
56                                 ret = 0;
57                                 break;
58                         }
59                 }
60         } else {
61                 st = 0;
62                 for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) {
63                         st = readl(&regs->status);
64                         writel(st & FTSDC010_STATUS_RSP_MASK, &regs->clr);
65                         if (st & FTSDC010_STATUS_RSP_MASK)
66                                 break;
67                 }
68                 if (st & FTSDC010_STATUS_RSP_CRC_OK) {
69                         if (flags & MMC_RSP_136) {
70                                 mmc_cmd->response[0] = readl(&regs->rsp3);
71                                 mmc_cmd->response[1] = readl(&regs->rsp2);
72                                 mmc_cmd->response[2] = readl(&regs->rsp1);
73                                 mmc_cmd->response[3] = readl(&regs->rsp0);
74                         } else {
75                                 mmc_cmd->response[0] = readl(&regs->rsp0);
76                         }
77                         ret = 0;
78                 } else {
79                         debug("ftsdc010: rsp err (cmd=%d, st=0x%x)\n",
80                                 mmc_cmd->cmdidx, st);
81                 }
82         }
83
84         if (ret) {
85                 debug("ftsdc010: cmd timeout (op code=%d)\n",
86                         mmc_cmd->cmdidx);
87         } else if (mmc_cmd->cmdidx == MMC_CMD_APP_CMD) {
88                 chip->acmd = 1;
89         }
90
91         return ret;
92 }
93
94 static void ftsdc010_clkset(struct mmc *mmc, uint32_t rate)
95 {
96         struct ftsdc010_chip *chip = mmc->priv;
97         struct ftsdc010_mmc __iomem *regs = chip->regs;
98         uint32_t div;
99
100         for (div = 0; div < 0x7f; ++div) {
101                 if (rate >= chip->sclk / (2 * (div + 1)))
102                         break;
103         }
104         chip->rate = chip->sclk / (2 * (div + 1));
105
106         writel(FTSDC010_CCR_CLK_DIV(div), &regs->ccr);
107
108         if (IS_SD(mmc)) {
109                 setbits_le32(&regs->ccr, FTSDC010_CCR_CLK_SD);
110
111                 if (chip->rate > 25000000)
112                         setbits_le32(&regs->ccr, FTSDC010_CCR_CLK_HISPD);
113                 else
114                         clrbits_le32(&regs->ccr, FTSDC010_CCR_CLK_HISPD);
115         }
116 }
117
118 static int ftsdc010_wait(struct ftsdc010_mmc __iomem *regs, uint32_t mask)
119 {
120         int ret = -ETIMEDOUT;
121         uint32_t st, timeout = 10000000;
122         while (timeout--) {
123                 st = readl(&regs->status);
124                 if (!(st & mask))
125                         continue;
126                 writel(st & mask, &regs->clr);
127                 ret = 0;
128                 break;
129         }
130
131         if (ret){
132                 debug("ftsdc010: wait st(0x%x) timeout\n", mask);
133         }
134
135         return ret;
136 }
137
138 /*
139  * u-boot mmc api
140  */
141 static int ftsdc010_request(struct udevice *dev, struct mmc_cmd *cmd,
142         struct mmc_data *data)
143 {
144         struct mmc *mmc = mmc_get_mmc_dev(dev);
145         int ret = -EOPNOTSUPP;
146         uint32_t len = 0;
147         struct ftsdc010_chip *chip = mmc->priv;
148         struct ftsdc010_mmc __iomem *regs = chip->regs;
149
150         if (data && (data->flags & MMC_DATA_WRITE) && chip->wprot) {
151                 printf("ftsdc010: the card is write protected!\n");
152                 return ret;
153         }
154
155         if (data) {
156                 uint32_t dcr;
157
158                 len = data->blocksize * data->blocks;
159
160                 /* 1. data disable + fifo reset */
161                 dcr = 0;
162 #ifdef CONFIG_FTSDC010_SDIO
163                 dcr |= FTSDC010_DCR_FIFO_RST;
164 #endif
165                 writel(dcr, &regs->dcr);
166
167                 /* 2. clear status register */
168                 writel(FTSDC010_STATUS_DATA_MASK | FTSDC010_STATUS_FIFO_URUN
169                         | FTSDC010_STATUS_FIFO_ORUN, &regs->clr);
170
171                 /* 3. data timeout (1 sec) */
172                 writel(chip->rate, &regs->dtr);
173
174                 /* 4. data length (bytes) */
175                 writel(len, &regs->dlr);
176
177                 /* 5. data enable */
178                 dcr = (ffs(data->blocksize) - 1) | FTSDC010_DCR_DATA_EN;
179                 if (data->flags & MMC_DATA_WRITE)
180                         dcr |= FTSDC010_DCR_DATA_WRITE;
181                 writel(dcr, &regs->dcr);
182         }
183
184         ret = ftsdc010_send_cmd(mmc, cmd);
185         if (ret) {
186                 printf("ftsdc010: CMD%d failed\n", cmd->cmdidx);
187                 return ret;
188         }
189
190         if (!data)
191                 return ret;
192
193         if (data->flags & MMC_DATA_WRITE) {
194                 const uint8_t *buf = (const uint8_t *)data->src;
195
196                 while (len > 0) {
197                         int wlen;
198
199                         /* wait for tx ready */
200                         ret = ftsdc010_wait(regs, FTSDC010_STATUS_FIFO_URUN);
201                         if (ret)
202                                 break;
203
204                         /* write bytes to ftsdc010 */
205                         for (wlen = 0; wlen < len && wlen < chip->fifo; ) {
206                                 writel(*(uint32_t *)buf, &regs->dwr);
207                                 buf  += 4;
208                                 wlen += 4;
209                         }
210
211                         len -= wlen;
212                 }
213
214         } else {
215                 uint8_t *buf = (uint8_t *)data->dest;
216
217                 while (len > 0) {
218                         int rlen;
219
220                         /* wait for rx ready */
221                         ret = ftsdc010_wait(regs, FTSDC010_STATUS_FIFO_ORUN);
222                         if (ret)
223                                 break;
224
225                         /* fetch bytes from ftsdc010 */
226                         for (rlen = 0; rlen < len && rlen < chip->fifo; ) {
227                                 *(uint32_t *)buf = readl(&regs->dwr);
228                                 buf  += 4;
229                                 rlen += 4;
230                         }
231
232                         len -= rlen;
233                 }
234
235         }
236
237         if (!ret) {
238                 ret = ftsdc010_wait(regs,
239                         FTSDC010_STATUS_DATA_END | FTSDC010_STATUS_DATA_CRC_OK);
240         }
241
242         return ret;
243 }
244
245 static int ftsdc010_set_ios(struct udevice *dev)
246 {
247         struct mmc *mmc = mmc_get_mmc_dev(dev);
248         struct ftsdc010_chip *chip = mmc->priv;
249         struct ftsdc010_mmc __iomem *regs = chip->regs;
250
251         ftsdc010_clkset(mmc, mmc->clock);
252
253         clrbits_le32(&regs->bwr, FTSDC010_BWR_MODE_MASK);
254         switch (mmc->bus_width) {
255         case 4:
256                 setbits_le32(&regs->bwr, FTSDC010_BWR_MODE_4BIT);
257                 break;
258         case 8:
259                 setbits_le32(&regs->bwr, FTSDC010_BWR_MODE_8BIT);
260                 break;
261         default:
262                 setbits_le32(&regs->bwr, FTSDC010_BWR_MODE_1BIT);
263                 break;
264         }
265
266         return 0;
267 }
268
269 static int ftsdc010_get_cd(struct udevice *dev)
270 {
271         struct mmc *mmc = mmc_get_mmc_dev(dev);
272         struct ftsdc010_chip *chip = mmc->priv;
273         struct ftsdc010_mmc __iomem *regs = chip->regs;
274         return !(readl(&regs->status) & FTSDC010_STATUS_CARD_DETECT);
275 }
276
277 static int ftsdc010_get_wp(struct udevice *dev)
278 {
279         struct mmc *mmc = mmc_get_mmc_dev(dev);
280         struct ftsdc010_chip *chip = mmc->priv;
281         struct ftsdc010_mmc __iomem *regs = chip->regs;
282         if (readl(&regs->status) & FTSDC010_STATUS_WRITE_PROT) {
283                 printf("ftsdc010: write protected\n");
284                 chip->wprot = 1;
285         }
286
287         return 0;
288 }
289
290 static int ftsdc010_init(struct mmc *mmc)
291 {
292         struct ftsdc010_chip *chip = mmc->priv;
293         struct ftsdc010_mmc __iomem *regs = chip->regs;
294         uint32_t ts;
295
296         chip->fifo = (readl(&regs->feature) & 0xff) << 2;
297
298         /* 1. chip reset */
299         writel(FTSDC010_CMD_SDC_RST, &regs->cmd);
300         for (ts = get_timer(0); get_timer(ts) < CFG_RST_TIMEOUT; ) {
301                 if (readl(&regs->cmd) & FTSDC010_CMD_SDC_RST)
302                         continue;
303                 break;
304         }
305         if (readl(&regs->cmd) & FTSDC010_CMD_SDC_RST) {
306                 printf("ftsdc010: reset failed\n");
307                 return -EOPNOTSUPP;
308         }
309
310         /* 2. enter low speed mode (400k card detection) */
311         ftsdc010_clkset(mmc, 400000);
312
313         /* 3. interrupt disabled */
314         writel(0, &regs->int_mask);
315
316         return 0;
317 }
318
319 int ftsdc010_probe(struct udevice *dev)
320 {
321         struct mmc *mmc = mmc_get_mmc_dev(dev);
322         return ftsdc010_init(mmc);
323 }
324
325 const struct dm_mmc_ops dm_ftsdc010_ops = {
326         .send_cmd       = ftsdc010_request,
327         .set_ios        = ftsdc010_set_ios,
328         .get_cd         = ftsdc010_get_cd,
329         .get_wp         = ftsdc010_get_wp,
330 };
331
332 void ftsdc_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth,
333                      uint caps, u32 max_clk, u32 min_clk)
334 {
335         cfg->name = name;
336         cfg->f_min = min_clk;
337         cfg->f_max = max_clk;
338         cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
339         cfg->host_caps = caps;
340         if (buswidth == 8) {
341                 cfg->host_caps |= MMC_MODE_8BIT;
342                 cfg->host_caps &= ~MMC_MODE_4BIT;
343         } else {
344                 cfg->host_caps |= MMC_MODE_4BIT;
345                 cfg->host_caps &= ~MMC_MODE_8BIT;
346         }
347         cfg->part_type = PART_TYPE_DOS;
348         cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
349 }
350
351 int ftsdc010_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg)
352 {
353         return mmc_bind(dev, mmc, cfg);
354 }