2 * (C) Copyright 2008-2010 Freescale Semiconductor, Inc.
5 * Copyright 2007, Freescale Semiconductor, Inc
8 * Based vaguely on the pxa mmc code:
10 * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
12 * See file CREDITS for list of people who contributed to this
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation; either version 2 of
18 * the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
39 #include <fsl_esdhc.h>
40 #include <fdt_support.h>
44 DECLARE_GLOBAL_DATA_PTR;
46 #define SDHCI_IRQ_EN_BITS (IRQSTATEN_CC | IRQSTATEN_TC | \
47 IRQSTATEN_BWR | IRQSTATEN_BRR | IRQSTATEN_CINT | \
48 IRQSTATEN_CTOE | IRQSTATEN_CCE | IRQSTATEN_CEBE | \
49 IRQSTATEN_CIE | IRQSTATEN_DTOE | IRQSTATEN_DCE | IRQSTATEN_DEBE)
79 /* Return the XFERTYP flags for a given command and data packet */
80 uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data)
85 xfertyp |= XFERTYP_DPSEL;
87 if (data->blocks > 1) {
88 xfertyp |= XFERTYP_MSBSEL;
89 xfertyp |= XFERTYP_BCEN;
92 if (data->flags & MMC_DATA_READ)
93 xfertyp |= XFERTYP_DTDSEL;
96 if (cmd->resp_type & MMC_RSP_CRC)
97 xfertyp |= XFERTYP_CCCEN;
98 if (cmd->resp_type & MMC_RSP_OPCODE)
99 xfertyp |= XFERTYP_CICEN;
100 if (cmd->resp_type & MMC_RSP_136)
101 xfertyp |= XFERTYP_RSPTYP_136;
102 else if (cmd->resp_type & MMC_RSP_BUSY)
103 xfertyp |= XFERTYP_RSPTYP_48_BUSY;
104 else if (cmd->resp_type & MMC_RSP_PRESENT)
105 xfertyp |= XFERTYP_RSPTYP_48;
107 return XFERTYP_CMD(cmd->cmdidx) | xfertyp;
110 static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
115 struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
116 struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
118 wml_value = data->blocksize / 4;
120 if (wml_value > 0x80)
123 if (!(data->flags & MMC_DATA_READ)) {
124 if ((readl(®s->prsstat) & PRSSTAT_WPSPL) == 0) {
125 printf("\nThe SD card is locked. Can not write to a locked card.\n\n");
128 wml_value = wml_value << 16;
131 writel(wml_value, ®s->wml);
133 writel(data->blocks << 16 | data->blocksize, ®s->blkattr);
135 /* Calculate the timeout period for data transactions */
137 timeout = fls(mmc->tran_speed / 10) - 1;
148 tmp = (readl(®s->sysctl) & (~SYSCTL_TIMEOUT_MASK)) | (timeout << 16);
149 writel(tmp, ®s->sysctl);
156 * Sends a command out on the bus. Takes the mmc pointer,
157 * a command pointer, and an optional data pointer.
160 esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
165 struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
166 volatile struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
168 writel(-1, ®s->irqstat);
172 tmp = readl(®s->irqstaten) | SDHCI_IRQ_EN_BITS;
173 writel(tmp, ®s->irqstaten);
175 /* Wait for the bus to be idle */
176 while ((readl(®s->prsstat) & PRSSTAT_CICHB) ||
177 (readl(®s->prsstat) & PRSSTAT_CIDHB))
180 while (readl(®s->prsstat) & PRSSTAT_DLA);
182 /* Wait at least 8 SD clock cycles before the next command */
184 * Note: This is way more than 8 cycles, but 1ms seems to
185 * resolve timing issues with some cards
189 /* Set up for a data transfer if we have one */
193 err = esdhc_setup_data(mmc, data);
198 /* Figure out the transfer arguments */
199 xfertyp = esdhc_xfertyp(cmd, data);
201 if (mmc->bus_width == EMMC_MODE_4BIT_DDR ||
202 mmc->bus_width == EMMC_MODE_8BIT_DDR)
203 xfertyp |= XFERTYP_DDR_EN;
205 /* Send the command */
206 writel(cmd->cmdarg, ®s->cmdarg);
207 writel(xfertyp, ®s->xfertyp);
210 writel(0, ®s->irqsigen);
212 /* Wait for the command to complete */
213 while (!(readl(®s->irqstat) & IRQSTAT_CC));
215 irqstat = readl(®s->irqstat);
216 writel(irqstat, ®s->irqstat);
218 if (irqstat & CMD_ERR)
221 if (irqstat & IRQSTAT_CTOE)
224 /* Copy the response to the response buffer */
225 if (cmd->resp_type & MMC_RSP_136) {
226 u32 cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0;
228 cmdrsp3 = readl(®s->cmdrsp3);
229 cmdrsp2 = readl(®s->cmdrsp2);
230 cmdrsp1 = readl(®s->cmdrsp1);
231 cmdrsp0 = readl(®s->cmdrsp0);
232 cmd->response[0] = (cmdrsp3 << 8) | (cmdrsp2 >> 24);
233 cmd->response[1] = (cmdrsp2 << 8) | (cmdrsp1 >> 24);
234 cmd->response[2] = (cmdrsp1 << 8) | (cmdrsp0 >> 24);
235 cmd->response[3] = (cmdrsp0 << 8);
237 cmd->response[0] = readl(®s->cmdrsp0);
239 /* Wait until all of the blocks are transferred */
243 uint block_size = data->blocksize;
244 uint block_cnt = data->blocks;
246 tmp = readl(®s->irqstaten) | SDHCI_IRQ_EN_BITS;
247 writel(tmp, ®s->irqstaten);
249 if (data->flags & MMC_DATA_READ) {
250 tmp_ptr = (u32 *)data->dest;
252 for (i = 0; i < (block_cnt); ++i) {
253 while (!(readl(®s->irqstat) & IRQSTAT_BRR))
256 for (j = 0; j < (block_size >> 2); ++j, ++tmp_ptr) {
257 *tmp_ptr = readl(®s->datport);
260 tmp = readl(®s->irqstat) & (IRQSTAT_BRR);
261 writel(tmp, ®s->irqstat);
264 tmp_ptr = (u32 *)data->src;
266 for (i = 0; i < (block_cnt); ++i) {
267 while (!(readl(®s->irqstat) & IRQSTAT_BWR))
270 for (j = 0; j < (block_size >> 2); ++j, ++tmp_ptr) {
271 writel(*tmp_ptr, ®s->datport);
274 tmp = readl(®s->irqstat) & (IRQSTAT_BWR);
275 writel(tmp, ®s->irqstat);
279 while (!(readl(®s->irqstat) & IRQSTAT_TC)) ;
282 if (readl(®s->irqstat) & 0xFFFF0000)
285 writel(-1, ®s->irqstat);
290 void set_sysctl(struct mmc *mmc, uint clock)
292 int sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
294 struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
295 volatile struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
299 if (sdhc_clk / 16 > clock) {
300 for (pre_div = 2; pre_div < 256; pre_div *= 2)
301 if ((sdhc_clk / pre_div) <= (clock * 16))
306 for (div = 1; div <= 16; div++)
307 if ((sdhc_clk / (div * pre_div)) <= clock)
313 clk = (pre_div << 8) | (div << 4);
315 #ifndef CONFIG_IMX_ESDHC_V1
316 tmp = readl(®s->sysctl) & (~SYSCTL_SDCLKEN);
317 writel(tmp, ®s->sysctl);
320 tmp = (readl(®s->sysctl) & (~SYSCTL_CLOCK_MASK)) | clk;
321 writel(tmp, ®s->sysctl);
325 #ifdef CONFIG_IMX_ESDHC_V1
326 tmp = readl(®s->sysctl) | SYSCTL_PEREN;
327 writel(tmp, ®s->sysctl);
329 while (!(readl(®s->prsstat) & PRSSTAT_SDSTB)) ;
331 tmp = readl(®s->sysctl) | (SYSCTL_SDCLKEN);
332 writel(tmp, ®s->sysctl);
336 static void esdhc_dll_setup(struct mmc *mmc)
338 struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
339 struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
341 uint dll_control = readl(®s->dllctrl);
342 dll_control &= ~(ESDHC_DLLCTRL_SLV_OVERRIDE_VAL_MASK |
343 ESDHC_DLLCTRL_SLV_OVERRIDE);
344 dll_control |= ((ESDHC_DLLCTRL_SLV_OVERRIDE_VAL <<
345 ESDHC_DLLCTRL_SLV_OVERRIDE_VAL_SHIFT) |
346 ESDHC_DLLCTRL_SLV_OVERRIDE);
348 writel(dll_control, ®s->dllctrl);
352 static void esdhc_set_ios(struct mmc *mmc)
354 struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
355 struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
358 /* Set the clock speed */
359 set_sysctl(mmc, mmc->clock);
361 /* Set the bus width */
362 tmp = readl(®s->proctl) & (~(PROCTL_DTW_4 | PROCTL_DTW_8));
363 writel(tmp, ®s->proctl);
365 if (mmc->bus_width == 4) {
366 tmp = readl(®s->proctl) | PROCTL_DTW_4;
367 writel(tmp, ®s->proctl);
368 } else if (mmc->bus_width == 8) {
369 tmp = readl(®s->proctl) | PROCTL_DTW_8;
370 writel(tmp, ®s->proctl);
371 } else if (mmc->bus_width == EMMC_MODE_4BIT_DDR) {
372 tmp = readl(®s->proctl) | PROCTL_DTW_4;
373 writel(tmp, ®s->proctl);
374 esdhc_dll_setup(mmc);
375 } else if (mmc->bus_width == EMMC_MODE_8BIT_DDR) {
376 tmp = readl(®s->proctl) | PROCTL_DTW_8;
377 writel(tmp, ®s->proctl);
378 esdhc_dll_setup(mmc);
382 static int esdhc_init(struct mmc *mmc)
384 struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
385 struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
388 /* Reset the eSDHC by writing 1 to RSTA bit of SYSCTRL Register */
389 tmp = readl(®s->sysctl) | SYSCTL_RSTA;
390 writel(tmp, ®s->sysctl);
392 while (readl(®s->sysctl) & SYSCTL_RSTA)
395 #ifdef CONFIG_IMX_ESDHC_V1
396 tmp = readl(®s->sysctl) | (SYSCTL_HCKEN | SYSCTL_IPGEN);
397 writel(tmp, ®s->sysctl);
400 /* Set the initial clock speed */
401 set_sysctl(mmc, 400000);
403 /* Put the PROCTL reg back to the default */
404 writel(PROCTL_INIT, ®s->proctl);
406 /* FIXME: For our CINS bit doesn't work. So this section is disabled. */
408 while (!(readl(®s->prsstat) & PRSSTAT_CINS) && --timeout)
412 printf("No MMC card detected!\n");
417 #ifndef CONFIG_IMX_ESDHC_V1
418 tmp = readl(®s->sysctl) | SYSCTL_INITA;
419 writel(tmp, ®s->sysctl);
421 while (readl(®s->sysctl) & SYSCTL_INITA)
428 int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
430 struct fsl_esdhc *regs;
437 mmc = malloc(sizeof(struct mmc));
439 sprintf(mmc->name, "FSL_ESDHC");
440 regs = (struct fsl_esdhc *)cfg->esdhc_base;
442 mmc->send_cmd = esdhc_send_cmd;
443 mmc->set_ios = esdhc_set_ios;
444 mmc->init = esdhc_init;
446 caps = readl(®s->hostcapblt);
447 if (caps & ESDHC_HOSTCAPBLT_VS30)
448 mmc->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
449 if (caps & ESDHC_HOSTCAPBLT_VS33)
450 mmc->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
452 mmc->host_caps = MMC_MODE_4BIT;
454 if (caps & ESDHC_HOSTCAPBLT_HSS)
455 mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
457 if (((readl(®s->hostver) & ESDHC_HOSTVER_VVN_MASK)
458 >> ESDHC_HOSTVER_VVN_SHIFT) >= ESDHC_HOSTVER_DDR_SUPPORT)
459 mmc->host_caps |= EMMC_MODE_4BIT_DDR;
462 mmc->f_max = MIN(mxc_get_clock(MXC_ESDHC_CLK), 50000000);
466 #ifdef CONFIG_MMC_8BIT_PORTS
467 if ((1 << mmc->block_dev.dev) & CONFIG_MMC_8BIT_PORTS) {
468 mmc->host_caps |= MMC_MODE_8BIT;
470 if (mmc->host_caps & EMMC_MODE_4BIT_DDR)
471 mmc->host_caps |= EMMC_MODE_8BIT_DDR;
478 int fsl_esdhc_mmc_init(bd_t *bis)
480 struct fsl_esdhc_cfg *cfg;
482 cfg = malloc(sizeof(struct fsl_esdhc_cfg));
483 memset(cfg, 0, sizeof(struct fsl_esdhc_cfg));
484 cfg->esdhc_base = CONFIG_SYS_FSL_ESDHC_ADDR;
485 return fsl_esdhc_initialize(bis, cfg);
488 #ifdef CONFIG_OF_LIBFDT
489 void fdt_fixup_esdhc(void *blob, bd_t *bd)
491 const char *compat = "fsl,esdhc";
492 const char *status = "okay";
494 if (!hwconfig("esdhc")) {
499 do_fixup_by_compat_u32(blob, compat, "clock-frequency",
502 do_fixup_by_compat(blob, compat, "status", status,
503 strlen(status) + 1, 1);