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