]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/mmc/sunxi_mmc.c
Merge branch 'master' of git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / drivers / mmc / sunxi_mmc.c
1 /*
2  * (C) Copyright 2007-2011
3  * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
4  * Aaron <leafy.myeh@allwinnertech.com>
5  *
6  * MMC driver for allwinner sunxi platform.
7  *
8  * SPDX-License-Identifier:     GPL-2.0+
9  */
10
11 #include <common.h>
12 #include <malloc.h>
13 #include <mmc.h>
14 #include <asm/io.h>
15 #include <asm/arch/clock.h>
16 #include <asm/arch/cpu.h>
17 #include <asm/arch/gpio.h>
18 #include <asm/arch/mmc.h>
19 #include <asm-generic/gpio.h>
20
21 struct sunxi_mmc_host {
22         unsigned mmc_no;
23         uint32_t *mclkreg;
24         unsigned fatal_err;
25         unsigned mod_clk;
26         struct sunxi_mmc *reg;
27         struct mmc_config cfg;
28 };
29
30 /* support 4 mmc hosts */
31 struct sunxi_mmc_host mmc_host[4];
32
33 static int sunxi_mmc_getcd_gpio(int sdc_no)
34 {
35         switch (sdc_no) {
36         case 0: return sunxi_name_to_gpio(CONFIG_MMC0_CD_PIN);
37         case 1: return sunxi_name_to_gpio(CONFIG_MMC1_CD_PIN);
38         case 2: return sunxi_name_to_gpio(CONFIG_MMC2_CD_PIN);
39         case 3: return sunxi_name_to_gpio(CONFIG_MMC3_CD_PIN);
40         }
41         return -1;
42 }
43
44 static int mmc_resource_init(int sdc_no)
45 {
46         struct sunxi_mmc_host *mmchost = &mmc_host[sdc_no];
47         struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
48         int cd_pin, ret = 0;
49
50         debug("init mmc %d resource\n", sdc_no);
51
52         switch (sdc_no) {
53         case 0:
54                 mmchost->reg = (struct sunxi_mmc *)SUNXI_MMC0_BASE;
55                 mmchost->mclkreg = &ccm->sd0_clk_cfg;
56                 break;
57         case 1:
58                 mmchost->reg = (struct sunxi_mmc *)SUNXI_MMC1_BASE;
59                 mmchost->mclkreg = &ccm->sd1_clk_cfg;
60                 break;
61         case 2:
62                 mmchost->reg = (struct sunxi_mmc *)SUNXI_MMC2_BASE;
63                 mmchost->mclkreg = &ccm->sd2_clk_cfg;
64                 break;
65         case 3:
66                 mmchost->reg = (struct sunxi_mmc *)SUNXI_MMC3_BASE;
67                 mmchost->mclkreg = &ccm->sd3_clk_cfg;
68                 break;
69         default:
70                 printf("Wrong mmc number %d\n", sdc_no);
71                 return -1;
72         }
73         mmchost->mmc_no = sdc_no;
74
75         cd_pin = sunxi_mmc_getcd_gpio(sdc_no);
76         if (cd_pin != -1)
77                 ret = gpio_request(cd_pin, "mmc_cd");
78
79         return ret;
80 }
81
82 static int mmc_clk_io_on(int sdc_no)
83 {
84         unsigned int pll_clk;
85         unsigned int divider;
86         struct sunxi_mmc_host *mmchost = &mmc_host[sdc_no];
87         struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
88
89         debug("init mmc %d clock and io\n", sdc_no);
90
91         /* config ahb clock */
92         setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MMC(sdc_no));
93
94 #if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I)
95         /* unassert reset */
96         setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MMC(sdc_no));
97 #endif
98
99         /* config mod clock */
100         pll_clk = clock_get_pll6();
101         /* should be close to 100 MHz but no more, so round up */
102         divider = ((pll_clk + 99999999) / 100000000) - 1;
103         writel(CCM_MMC_CTRL_ENABLE | CCM_MMC_CTRL_PLL6 | divider,
104                mmchost->mclkreg);
105         mmchost->mod_clk = pll_clk / (divider + 1);
106
107         return 0;
108 }
109
110 static int mmc_update_clk(struct mmc *mmc)
111 {
112         struct sunxi_mmc_host *mmchost = mmc->priv;
113         unsigned int cmd;
114         unsigned timeout_msecs = 2000;
115
116         cmd = SUNXI_MMC_CMD_START |
117               SUNXI_MMC_CMD_UPCLK_ONLY |
118               SUNXI_MMC_CMD_WAIT_PRE_OVER;
119         writel(cmd, &mmchost->reg->cmd);
120         while (readl(&mmchost->reg->cmd) & SUNXI_MMC_CMD_START) {
121                 if (!timeout_msecs--)
122                         return -1;
123                 udelay(1000);
124         }
125
126         /* clock update sets various irq status bits, clear these */
127         writel(readl(&mmchost->reg->rint), &mmchost->reg->rint);
128
129         return 0;
130 }
131
132 static int mmc_config_clock(struct mmc *mmc, unsigned div)
133 {
134         struct sunxi_mmc_host *mmchost = mmc->priv;
135         unsigned rval = readl(&mmchost->reg->clkcr);
136
137         /* Disable Clock */
138         rval &= ~SUNXI_MMC_CLK_ENABLE;
139         writel(rval, &mmchost->reg->clkcr);
140         if (mmc_update_clk(mmc))
141                 return -1;
142
143         /* Change Divider Factor */
144         rval &= ~SUNXI_MMC_CLK_DIVIDER_MASK;
145         rval |= div;
146         writel(rval, &mmchost->reg->clkcr);
147         if (mmc_update_clk(mmc))
148                 return -1;
149         /* Re-enable Clock */
150         rval |= SUNXI_MMC_CLK_ENABLE;
151         writel(rval, &mmchost->reg->clkcr);
152
153         if (mmc_update_clk(mmc))
154                 return -1;
155
156         return 0;
157 }
158
159 static void mmc_set_ios(struct mmc *mmc)
160 {
161         struct sunxi_mmc_host *mmchost = mmc->priv;
162         unsigned int clkdiv = 0;
163
164         debug("set ios: bus_width: %x, clock: %d, mod_clk: %d\n",
165               mmc->bus_width, mmc->clock, mmchost->mod_clk);
166
167         /* Change clock first */
168         clkdiv = (mmchost->mod_clk + (mmc->clock >> 1)) / mmc->clock / 2;
169         if (mmc->clock) {
170                 if (mmc_config_clock(mmc, clkdiv)) {
171                         mmchost->fatal_err = 1;
172                         return;
173                 }
174         }
175
176         /* Change bus width */
177         if (mmc->bus_width == 8)
178                 writel(0x2, &mmchost->reg->width);
179         else if (mmc->bus_width == 4)
180                 writel(0x1, &mmchost->reg->width);
181         else
182                 writel(0x0, &mmchost->reg->width);
183 }
184
185 static int mmc_core_init(struct mmc *mmc)
186 {
187         struct sunxi_mmc_host *mmchost = mmc->priv;
188
189         /* Reset controller */
190         writel(SUNXI_MMC_GCTRL_RESET, &mmchost->reg->gctrl);
191         udelay(1000);
192
193         return 0;
194 }
195
196 static int mmc_trans_data_by_cpu(struct mmc *mmc, struct mmc_data *data)
197 {
198         struct sunxi_mmc_host *mmchost = mmc->priv;
199         const int reading = !!(data->flags & MMC_DATA_READ);
200         const uint32_t status_bit = reading ? SUNXI_MMC_STATUS_FIFO_EMPTY :
201                                               SUNXI_MMC_STATUS_FIFO_FULL;
202         unsigned i;
203         unsigned byte_cnt = data->blocksize * data->blocks;
204         unsigned timeout_msecs = 2000;
205         unsigned *buff = (unsigned int *)(reading ? data->dest : data->src);
206
207         /* Always read / write data through the CPU */
208         setbits_le32(&mmchost->reg->gctrl, SUNXI_MMC_GCTRL_ACCESS_BY_AHB);
209
210         for (i = 0; i < (byte_cnt >> 2); i++) {
211                 while (readl(&mmchost->reg->status) & status_bit) {
212                         if (!timeout_msecs--)
213                                 return -1;
214                         udelay(1000);
215                 }
216
217                 if (reading)
218                         buff[i] = readl(&mmchost->reg->fifo);
219                 else
220                         writel(buff[i], &mmchost->reg->fifo);
221         }
222
223         return 0;
224 }
225
226 static int mmc_rint_wait(struct mmc *mmc, unsigned int timeout_msecs,
227                          unsigned int done_bit, const char *what)
228 {
229         struct sunxi_mmc_host *mmchost = mmc->priv;
230         unsigned int status;
231
232         do {
233                 status = readl(&mmchost->reg->rint);
234                 if (!timeout_msecs-- ||
235                     (status & SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT)) {
236                         debug("%s timeout %x\n", what,
237                               status & SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT);
238                         return TIMEOUT;
239                 }
240                 udelay(1000);
241         } while (!(status & done_bit));
242
243         return 0;
244 }
245
246 static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
247                         struct mmc_data *data)
248 {
249         struct sunxi_mmc_host *mmchost = mmc->priv;
250         unsigned int cmdval = SUNXI_MMC_CMD_START;
251         unsigned int timeout_msecs;
252         int error = 0;
253         unsigned int status = 0;
254         unsigned int bytecnt = 0;
255
256         if (mmchost->fatal_err)
257                 return -1;
258         if (cmd->resp_type & MMC_RSP_BUSY)
259                 debug("mmc cmd %d check rsp busy\n", cmd->cmdidx);
260         if (cmd->cmdidx == 12)
261                 return 0;
262
263         if (!cmd->cmdidx)
264                 cmdval |= SUNXI_MMC_CMD_SEND_INIT_SEQ;
265         if (cmd->resp_type & MMC_RSP_PRESENT)
266                 cmdval |= SUNXI_MMC_CMD_RESP_EXPIRE;
267         if (cmd->resp_type & MMC_RSP_136)
268                 cmdval |= SUNXI_MMC_CMD_LONG_RESPONSE;
269         if (cmd->resp_type & MMC_RSP_CRC)
270                 cmdval |= SUNXI_MMC_CMD_CHK_RESPONSE_CRC;
271
272         if (data) {
273                 if ((u32) data->dest & 0x3) {
274                         error = -1;
275                         goto out;
276                 }
277
278                 cmdval |= SUNXI_MMC_CMD_DATA_EXPIRE|SUNXI_MMC_CMD_WAIT_PRE_OVER;
279                 if (data->flags & MMC_DATA_WRITE)
280                         cmdval |= SUNXI_MMC_CMD_WRITE;
281                 if (data->blocks > 1)
282                         cmdval |= SUNXI_MMC_CMD_AUTO_STOP;
283                 writel(data->blocksize, &mmchost->reg->blksz);
284                 writel(data->blocks * data->blocksize, &mmchost->reg->bytecnt);
285         }
286
287         debug("mmc %d, cmd %d(0x%08x), arg 0x%08x\n", mmchost->mmc_no,
288               cmd->cmdidx, cmdval | cmd->cmdidx, cmd->cmdarg);
289         writel(cmd->cmdarg, &mmchost->reg->arg);
290
291         if (!data)
292                 writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd);
293
294         /*
295          * transfer data and check status
296          * STATREG[2] : FIFO empty
297          * STATREG[3] : FIFO full
298          */
299         if (data) {
300                 int ret = 0;
301
302                 bytecnt = data->blocksize * data->blocks;
303                 debug("trans data %d bytes\n", bytecnt);
304                 writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd);
305                 ret = mmc_trans_data_by_cpu(mmc, data);
306                 if (ret) {
307                         error = readl(&mmchost->reg->rint) & \
308                                 SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT;
309                         error = TIMEOUT;
310                         goto out;
311                 }
312         }
313
314         error = mmc_rint_wait(mmc, 0xfffff, SUNXI_MMC_RINT_COMMAND_DONE, "cmd");
315         if (error)
316                 goto out;
317
318         if (data) {
319                 timeout_msecs = 120;
320                 debug("cacl timeout %x msec\n", timeout_msecs);
321                 error = mmc_rint_wait(mmc, timeout_msecs,
322                                       data->blocks > 1 ?
323                                       SUNXI_MMC_RINT_AUTO_COMMAND_DONE :
324                                       SUNXI_MMC_RINT_DATA_OVER,
325                                       "data");
326                 if (error)
327                         goto out;
328         }
329
330         if (cmd->resp_type & MMC_RSP_BUSY) {
331                 timeout_msecs = 2000;
332                 do {
333                         status = readl(&mmchost->reg->status);
334                         if (!timeout_msecs--) {
335                                 debug("busy timeout\n");
336                                 error = TIMEOUT;
337                                 goto out;
338                         }
339                         udelay(1000);
340                 } while (status & SUNXI_MMC_STATUS_CARD_DATA_BUSY);
341         }
342
343         if (cmd->resp_type & MMC_RSP_136) {
344                 cmd->response[0] = readl(&mmchost->reg->resp3);
345                 cmd->response[1] = readl(&mmchost->reg->resp2);
346                 cmd->response[2] = readl(&mmchost->reg->resp1);
347                 cmd->response[3] = readl(&mmchost->reg->resp0);
348                 debug("mmc resp 0x%08x 0x%08x 0x%08x 0x%08x\n",
349                       cmd->response[3], cmd->response[2],
350                       cmd->response[1], cmd->response[0]);
351         } else {
352                 cmd->response[0] = readl(&mmchost->reg->resp0);
353                 debug("mmc resp 0x%08x\n", cmd->response[0]);
354         }
355 out:
356         if (error < 0) {
357                 writel(SUNXI_MMC_GCTRL_RESET, &mmchost->reg->gctrl);
358                 mmc_update_clk(mmc);
359         }
360         writel(0xffffffff, &mmchost->reg->rint);
361         writel(readl(&mmchost->reg->gctrl) | SUNXI_MMC_GCTRL_FIFO_RESET,
362                &mmchost->reg->gctrl);
363
364         return error;
365 }
366
367 static int sunxi_mmc_getcd(struct mmc *mmc)
368 {
369         struct sunxi_mmc_host *mmchost = mmc->priv;
370         int cd_pin;
371
372         cd_pin = sunxi_mmc_getcd_gpio(mmchost->mmc_no);
373         if (cd_pin == -1)
374                 return 1;
375
376         return !gpio_direction_input(cd_pin);
377 }
378
379 static const struct mmc_ops sunxi_mmc_ops = {
380         .send_cmd       = mmc_send_cmd,
381         .set_ios        = mmc_set_ios,
382         .init           = mmc_core_init,
383         .getcd          = sunxi_mmc_getcd,
384 };
385
386 struct mmc *sunxi_mmc_init(int sdc_no)
387 {
388         struct mmc_config *cfg = &mmc_host[sdc_no].cfg;
389
390         memset(&mmc_host[sdc_no], 0, sizeof(struct sunxi_mmc_host));
391
392         cfg->name = "SUNXI SD/MMC";
393         cfg->ops  = &sunxi_mmc_ops;
394
395         cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
396         cfg->host_caps = MMC_MODE_4BIT;
397         cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
398 #if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || defined(CONFIG_MACH_SUN8I)
399         cfg->host_caps |= MMC_MODE_HC;
400 #endif
401         cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
402
403         cfg->f_min = 400000;
404         cfg->f_max = 52000000;
405
406         if (mmc_resource_init(sdc_no) != 0)
407                 return NULL;
408
409         mmc_clk_io_on(sdc_no);
410
411         return mmc_create(cfg, &mmc_host[sdc_no]);
412 }