blob: bfbef66d86f27f0c33db634953dfeca5c883667c [file] [log] [blame]
Andy Fleming50586ef2008-10-30 16:47:16 -05001/*
Jerry Huangd621da02011-01-06 23:42:19 -06002 * Copyright 2007, 2010-2011 Freescale Semiconductor, Inc
Andy Fleming50586ef2008-10-30 16:47:16 -05003 * Andy Fleming
4 *
5 * Based vaguely on the pxa mmc code:
6 * (C) Copyright 2003
7 * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
8 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02009 * SPDX-License-Identifier: GPL-2.0+
Andy Fleming50586ef2008-10-30 16:47:16 -050010 */
11
12#include <config.h>
13#include <common.h>
14#include <command.h>
Anton Vorontsovb33433a2009-06-10 00:25:29 +040015#include <hwconfig.h>
Andy Fleming50586ef2008-10-30 16:47:16 -050016#include <mmc.h>
17#include <part.h>
18#include <malloc.h>
19#include <mmc.h>
20#include <fsl_esdhc.h>
Anton Vorontsovb33433a2009-06-10 00:25:29 +040021#include <fdt_support.h>
Andy Fleming50586ef2008-10-30 16:47:16 -050022#include <asm/io.h>
Peng Fan96f04072016-03-25 14:16:56 +080023#include <dm.h>
24#include <asm-generic/gpio.h>
Andy Fleming50586ef2008-10-30 16:47:16 -050025
Andy Fleming50586ef2008-10-30 16:47:16 -050026DECLARE_GLOBAL_DATA_PTR;
27
Ye.Lia3d6e382014-11-04 15:35:49 +080028#define SDHCI_IRQ_EN_BITS (IRQSTATEN_CC | IRQSTATEN_TC | \
29 IRQSTATEN_CINT | \
30 IRQSTATEN_CTOE | IRQSTATEN_CCE | IRQSTATEN_CEBE | \
31 IRQSTATEN_CIE | IRQSTATEN_DTOE | IRQSTATEN_DCE | \
32 IRQSTATEN_DEBE | IRQSTATEN_BRR | IRQSTATEN_BWR | \
33 IRQSTATEN_DINT)
34
Andy Fleming50586ef2008-10-30 16:47:16 -050035struct fsl_esdhc {
Haijun.Zhang511948b2013-10-30 11:37:55 +080036 uint dsaddr; /* SDMA system address register */
37 uint blkattr; /* Block attributes register */
38 uint cmdarg; /* Command argument register */
39 uint xfertyp; /* Transfer type register */
40 uint cmdrsp0; /* Command response 0 register */
41 uint cmdrsp1; /* Command response 1 register */
42 uint cmdrsp2; /* Command response 2 register */
43 uint cmdrsp3; /* Command response 3 register */
44 uint datport; /* Buffer data port register */
45 uint prsstat; /* Present state register */
46 uint proctl; /* Protocol control register */
47 uint sysctl; /* System Control Register */
48 uint irqstat; /* Interrupt status register */
49 uint irqstaten; /* Interrupt status enable register */
50 uint irqsigen; /* Interrupt signal enable register */
51 uint autoc12err; /* Auto CMD error status register */
52 uint hostcapblt; /* Host controller capabilities register */
53 uint wml; /* Watermark level register */
54 uint mixctrl; /* For USDHC */
55 char reserved1[4]; /* reserved */
56 uint fevt; /* Force event register */
57 uint admaes; /* ADMA error status register */
58 uint adsaddr; /* ADMA system address register */
Peng Fanf53225c2016-06-15 10:53:00 +080059 char reserved2[4];
60 uint dllctrl;
61 uint dllstat;
62 uint clktunectrlstatus;
63 char reserved3[84];
64 uint vendorspec;
65 uint mmcboot;
66 uint vendorspec2;
67 char reserved4[48];
Haijun.Zhang511948b2013-10-30 11:37:55 +080068 uint hostver; /* Host controller version register */
Haijun.Zhang511948b2013-10-30 11:37:55 +080069 char reserved5[4]; /* reserved */
Peng Fanf53225c2016-06-15 10:53:00 +080070 uint dmaerraddr; /* DMA error address register */
Otavio Salvadorf022d362015-02-17 10:42:43 -020071 char reserved6[4]; /* reserved */
Peng Fanf53225c2016-06-15 10:53:00 +080072 uint dmaerrattr; /* DMA error attribute register */
73 char reserved7[4]; /* reserved */
Haijun.Zhang511948b2013-10-30 11:37:55 +080074 uint hostcapblt2; /* Host controller capabilities register 2 */
Peng Fanf53225c2016-06-15 10:53:00 +080075 char reserved8[8]; /* reserved */
Haijun.Zhang511948b2013-10-30 11:37:55 +080076 uint tcr; /* Tuning control register */
Peng Fanf53225c2016-06-15 10:53:00 +080077 char reserved9[28]; /* reserved */
Haijun.Zhang511948b2013-10-30 11:37:55 +080078 uint sddirctl; /* SD direction control register */
Peng Fanf53225c2016-06-15 10:53:00 +080079 char reserved10[712];/* reserved */
Haijun.Zhang511948b2013-10-30 11:37:55 +080080 uint scr; /* eSDHC control register */
Andy Fleming50586ef2008-10-30 16:47:16 -050081};
82
Peng Fan96f04072016-03-25 14:16:56 +080083/**
84 * struct fsl_esdhc_priv
85 *
86 * @esdhc_regs: registers of the sdhc controller
87 * @sdhc_clk: Current clk of the sdhc controller
88 * @bus_width: bus width, 1bit, 4bit or 8bit
89 * @cfg: mmc config
90 * @mmc: mmc
91 * Following is used when Driver Model is enabled for MMC
92 * @dev: pointer for the device
93 * @non_removable: 0: removable; 1: non-removable
94 * @cd_gpio: gpio for card detection
95 */
96struct fsl_esdhc_priv {
97 struct fsl_esdhc *esdhc_regs;
98 unsigned int sdhc_clk;
99 unsigned int bus_width;
100 struct mmc_config cfg;
101 struct mmc *mmc;
102 struct udevice *dev;
103 int non_removable;
104 struct gpio_desc cd_gpio;
105};
106
Andy Fleming50586ef2008-10-30 16:47:16 -0500107/* Return the XFERTYP flags for a given command and data packet */
Kim Phillipseafa90a2012-10-29 13:34:44 +0000108static uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data)
Andy Fleming50586ef2008-10-30 16:47:16 -0500109{
110 uint xfertyp = 0;
111
112 if (data) {
Dipen Dudhat77c14582009-10-05 15:41:58 +0530113 xfertyp |= XFERTYP_DPSEL;
114#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
115 xfertyp |= XFERTYP_DMAEN;
116#endif
Andy Fleming50586ef2008-10-30 16:47:16 -0500117 if (data->blocks > 1) {
118 xfertyp |= XFERTYP_MSBSEL;
119 xfertyp |= XFERTYP_BCEN;
Jerry Huangd621da02011-01-06 23:42:19 -0600120#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
121 xfertyp |= XFERTYP_AC12EN;
122#endif
Andy Fleming50586ef2008-10-30 16:47:16 -0500123 }
124
125 if (data->flags & MMC_DATA_READ)
126 xfertyp |= XFERTYP_DTDSEL;
127 }
128
129 if (cmd->resp_type & MMC_RSP_CRC)
130 xfertyp |= XFERTYP_CCCEN;
131 if (cmd->resp_type & MMC_RSP_OPCODE)
132 xfertyp |= XFERTYP_CICEN;
133 if (cmd->resp_type & MMC_RSP_136)
134 xfertyp |= XFERTYP_RSPTYP_136;
135 else if (cmd->resp_type & MMC_RSP_BUSY)
136 xfertyp |= XFERTYP_RSPTYP_48_BUSY;
137 else if (cmd->resp_type & MMC_RSP_PRESENT)
138 xfertyp |= XFERTYP_RSPTYP_48;
139
Jason Liu4571de32011-03-22 01:32:31 +0000140 if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
141 xfertyp |= XFERTYP_CMDTYP_ABORT;
Yangbo Lu25503442016-01-21 17:33:19 +0800142
Andy Fleming50586ef2008-10-30 16:47:16 -0500143 return XFERTYP_CMD(cmd->cmdidx) | xfertyp;
144}
145
Dipen Dudhat77c14582009-10-05 15:41:58 +0530146#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
147/*
148 * PIO Read/Write Mode reduce the performace as DMA is not used in this mode.
149 */
Wolfgang Denk7b43db92010-05-09 23:52:59 +0200150static void
Dipen Dudhat77c14582009-10-05 15:41:58 +0530151esdhc_pio_read_write(struct mmc *mmc, struct mmc_data *data)
152{
Peng Fan96f04072016-03-25 14:16:56 +0800153 struct fsl_esdhc_priv *priv = mmc->priv;
154 struct fsl_esdhc *regs = priv->esdhc_regs;
Dipen Dudhat77c14582009-10-05 15:41:58 +0530155 uint blocks;
156 char *buffer;
157 uint databuf;
158 uint size;
159 uint irqstat;
160 uint timeout;
161
162 if (data->flags & MMC_DATA_READ) {
163 blocks = data->blocks;
164 buffer = data->dest;
165 while (blocks) {
166 timeout = PIO_TIMEOUT;
167 size = data->blocksize;
168 irqstat = esdhc_read32(&regs->irqstat);
169 while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_BREN)
170 && --timeout);
171 if (timeout <= 0) {
172 printf("\nData Read Failed in PIO Mode.");
Wolfgang Denk7b43db92010-05-09 23:52:59 +0200173 return;
Dipen Dudhat77c14582009-10-05 15:41:58 +0530174 }
175 while (size && (!(irqstat & IRQSTAT_TC))) {
176 udelay(100); /* Wait before last byte transfer complete */
177 irqstat = esdhc_read32(&regs->irqstat);
178 databuf = in_le32(&regs->datport);
179 *((uint *)buffer) = databuf;
180 buffer += 4;
181 size -= 4;
182 }
183 blocks--;
184 }
185 } else {
186 blocks = data->blocks;
Wolfgang Denk7b43db92010-05-09 23:52:59 +0200187 buffer = (char *)data->src;
Dipen Dudhat77c14582009-10-05 15:41:58 +0530188 while (blocks) {
189 timeout = PIO_TIMEOUT;
190 size = data->blocksize;
191 irqstat = esdhc_read32(&regs->irqstat);
192 while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_BWEN)
193 && --timeout);
194 if (timeout <= 0) {
195 printf("\nData Write Failed in PIO Mode.");
Wolfgang Denk7b43db92010-05-09 23:52:59 +0200196 return;
Dipen Dudhat77c14582009-10-05 15:41:58 +0530197 }
198 while (size && (!(irqstat & IRQSTAT_TC))) {
199 udelay(100); /* Wait before last byte transfer complete */
200 databuf = *((uint *)buffer);
201 buffer += 4;
202 size -= 4;
203 irqstat = esdhc_read32(&regs->irqstat);
204 out_le32(&regs->datport, databuf);
205 }
206 blocks--;
207 }
208 }
209}
210#endif
211
Andy Fleming50586ef2008-10-30 16:47:16 -0500212static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
213{
Andy Fleming50586ef2008-10-30 16:47:16 -0500214 int timeout;
Peng Fan96f04072016-03-25 14:16:56 +0800215 struct fsl_esdhc_priv *priv = mmc->priv;
216 struct fsl_esdhc *regs = priv->esdhc_regs;
Eddy Petrișor9702ec02016-06-05 03:43:00 +0300217#if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234)
Yangbo Lu8b064602015-03-20 19:28:31 -0700218 dma_addr_t addr;
219#endif
Wolfgang Denk7b43db92010-05-09 23:52:59 +0200220 uint wml_value;
Andy Fleming50586ef2008-10-30 16:47:16 -0500221
222 wml_value = data->blocksize/4;
223
224 if (data->flags & MMC_DATA_READ) {
Priyanka Jain32c8cfb2011-02-09 09:24:10 +0530225 if (wml_value > WML_RD_WML_MAX)
226 wml_value = WML_RD_WML_MAX_VAL;
Andy Fleming50586ef2008-10-30 16:47:16 -0500227
Roy Zangab467c52010-02-09 18:23:33 +0800228 esdhc_clrsetbits32(&regs->wml, WML_RD_WML_MASK, wml_value);
Ye.Li71689772014-02-20 18:00:57 +0800229#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
Eddy Petrișor9702ec02016-06-05 03:43:00 +0300230#if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234)
Yangbo Lu8b064602015-03-20 19:28:31 -0700231 addr = virt_to_phys((void *)(data->dest));
232 if (upper_32_bits(addr))
233 printf("Error found for upper 32 bits\n");
234 else
235 esdhc_write32(&regs->dsaddr, lower_32_bits(addr));
236#else
Stefano Babicc67bee12010-02-05 15:11:27 +0100237 esdhc_write32(&regs->dsaddr, (u32)data->dest);
Ye.Li71689772014-02-20 18:00:57 +0800238#endif
Yangbo Lu8b064602015-03-20 19:28:31 -0700239#endif
Andy Fleming50586ef2008-10-30 16:47:16 -0500240 } else {
Ye.Li71689772014-02-20 18:00:57 +0800241#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
Eric Nelsone576bd92012-04-25 14:28:48 +0000242 flush_dcache_range((ulong)data->src,
243 (ulong)data->src+data->blocks
244 *data->blocksize);
Ye.Li71689772014-02-20 18:00:57 +0800245#endif
Priyanka Jain32c8cfb2011-02-09 09:24:10 +0530246 if (wml_value > WML_WR_WML_MAX)
247 wml_value = WML_WR_WML_MAX_VAL;
Stefano Babicc67bee12010-02-05 15:11:27 +0100248 if ((esdhc_read32(&regs->prsstat) & PRSSTAT_WPSPL) == 0) {
Andy Fleming50586ef2008-10-30 16:47:16 -0500249 printf("\nThe SD card is locked. Can not write to a locked card.\n\n");
250 return TIMEOUT;
251 }
Roy Zangab467c52010-02-09 18:23:33 +0800252
253 esdhc_clrsetbits32(&regs->wml, WML_WR_WML_MASK,
254 wml_value << 16);
Ye.Li71689772014-02-20 18:00:57 +0800255#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
Eddy Petrișor9702ec02016-06-05 03:43:00 +0300256#if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234)
Yangbo Lu8b064602015-03-20 19:28:31 -0700257 addr = virt_to_phys((void *)(data->src));
258 if (upper_32_bits(addr))
259 printf("Error found for upper 32 bits\n");
260 else
261 esdhc_write32(&regs->dsaddr, lower_32_bits(addr));
262#else
Stefano Babicc67bee12010-02-05 15:11:27 +0100263 esdhc_write32(&regs->dsaddr, (u32)data->src);
Ye.Li71689772014-02-20 18:00:57 +0800264#endif
Yangbo Lu8b064602015-03-20 19:28:31 -0700265#endif
Andy Fleming50586ef2008-10-30 16:47:16 -0500266 }
267
Stefano Babicc67bee12010-02-05 15:11:27 +0100268 esdhc_write32(&regs->blkattr, data->blocks << 16 | data->blocksize);
Andy Fleming50586ef2008-10-30 16:47:16 -0500269
270 /* Calculate the timeout period for data transactions */
Priyanka Jainb71ea332011-03-03 09:18:56 +0530271 /*
272 * 1)Timeout period = (2^(timeout+13)) SD Clock cycles
273 * 2)Timeout period should be minimum 0.250sec as per SD Card spec
274 * So, Number of SD Clock cycles for 0.25sec should be minimum
275 * (SD Clock/sec * 0.25 sec) SD Clock cycles
Andrew Gabbasovfb823982014-03-24 02:40:41 -0500276 * = (mmc->clock * 1/4) SD Clock cycles
Priyanka Jainb71ea332011-03-03 09:18:56 +0530277 * As 1) >= 2)
Andrew Gabbasovfb823982014-03-24 02:40:41 -0500278 * => (2^(timeout+13)) >= mmc->clock * 1/4
Priyanka Jainb71ea332011-03-03 09:18:56 +0530279 * Taking log2 both the sides
Andrew Gabbasovfb823982014-03-24 02:40:41 -0500280 * => timeout + 13 >= log2(mmc->clock/4)
Priyanka Jainb71ea332011-03-03 09:18:56 +0530281 * Rounding up to next power of 2
Andrew Gabbasovfb823982014-03-24 02:40:41 -0500282 * => timeout + 13 = log2(mmc->clock/4) + 1
283 * => timeout + 13 = fls(mmc->clock/4)
Yangbo Lue978a312015-12-30 14:19:30 +0800284 *
285 * However, the MMC spec "It is strongly recommended for hosts to
286 * implement more than 500ms timeout value even if the card
287 * indicates the 250ms maximum busy length." Even the previous
288 * value of 300ms is known to be insufficient for some cards.
289 * So, we use
290 * => timeout + 13 = fls(mmc->clock/2)
Priyanka Jainb71ea332011-03-03 09:18:56 +0530291 */
Yangbo Lue978a312015-12-30 14:19:30 +0800292 timeout = fls(mmc->clock/2);
Andy Fleming50586ef2008-10-30 16:47:16 -0500293 timeout -= 13;
294
295 if (timeout > 14)
296 timeout = 14;
297
298 if (timeout < 0)
299 timeout = 0;
300
Kumar Gala5103a032011-01-29 15:36:10 -0600301#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC_A001
302 if ((timeout == 4) || (timeout == 8) || (timeout == 12))
303 timeout++;
304#endif
305
Haijun.Zhang1336e2d2014-03-18 17:04:23 +0800306#ifdef ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE
307 timeout = 0xE;
308#endif
Stefano Babicc67bee12010-02-05 15:11:27 +0100309 esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, timeout << 16);
Andy Fleming50586ef2008-10-30 16:47:16 -0500310
311 return 0;
312}
313
Eric Nelsone576bd92012-04-25 14:28:48 +0000314static void check_and_invalidate_dcache_range
315 (struct mmc_cmd *cmd,
316 struct mmc_data *data) {
Yangbo Lu8b064602015-03-20 19:28:31 -0700317 unsigned start = 0;
Yangbo Lucc634e22016-05-12 19:12:58 +0800318 unsigned end = 0;
Eric Nelsone576bd92012-04-25 14:28:48 +0000319 unsigned size = roundup(ARCH_DMA_MINALIGN,
320 data->blocks*data->blocksize);
Eddy Petrișor9702ec02016-06-05 03:43:00 +0300321#if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234)
Yangbo Lu8b064602015-03-20 19:28:31 -0700322 dma_addr_t addr;
323
324 addr = virt_to_phys((void *)(data->dest));
325 if (upper_32_bits(addr))
326 printf("Error found for upper 32 bits\n");
327 else
328 start = lower_32_bits(addr);
Yangbo Lucc634e22016-05-12 19:12:58 +0800329#else
330 start = (unsigned)data->dest;
Yangbo Lu8b064602015-03-20 19:28:31 -0700331#endif
Yangbo Lucc634e22016-05-12 19:12:58 +0800332 end = start + size;
Eric Nelsone576bd92012-04-25 14:28:48 +0000333 invalidate_dcache_range(start, end);
334}
Tom Rini10dc7772014-05-23 09:19:05 -0400335
Andy Fleming50586ef2008-10-30 16:47:16 -0500336/*
337 * Sends a command out on the bus. Takes the mmc pointer,
338 * a command pointer, and an optional data pointer.
339 */
340static int
341esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
342{
Andrew Gabbasov8a573022014-03-24 02:41:06 -0500343 int err = 0;
Andy Fleming50586ef2008-10-30 16:47:16 -0500344 uint xfertyp;
345 uint irqstat;
Peng Fan96f04072016-03-25 14:16:56 +0800346 struct fsl_esdhc_priv *priv = mmc->priv;
347 struct fsl_esdhc *regs = priv->esdhc_regs;
Andy Fleming50586ef2008-10-30 16:47:16 -0500348
Jerry Huangd621da02011-01-06 23:42:19 -0600349#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
350 if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
351 return 0;
352#endif
353
Stefano Babicc67bee12010-02-05 15:11:27 +0100354 esdhc_write32(&regs->irqstat, -1);
Andy Fleming50586ef2008-10-30 16:47:16 -0500355
356 sync();
357
358 /* Wait for the bus to be idle */
Stefano Babicc67bee12010-02-05 15:11:27 +0100359 while ((esdhc_read32(&regs->prsstat) & PRSSTAT_CICHB) ||
360 (esdhc_read32(&regs->prsstat) & PRSSTAT_CIDHB))
361 ;
Andy Fleming50586ef2008-10-30 16:47:16 -0500362
Stefano Babicc67bee12010-02-05 15:11:27 +0100363 while (esdhc_read32(&regs->prsstat) & PRSSTAT_DLA)
364 ;
Andy Fleming50586ef2008-10-30 16:47:16 -0500365
366 /* Wait at least 8 SD clock cycles before the next command */
367 /*
368 * Note: This is way more than 8 cycles, but 1ms seems to
369 * resolve timing issues with some cards
370 */
371 udelay(1000);
372
373 /* Set up for a data transfer if we have one */
374 if (data) {
Andy Fleming50586ef2008-10-30 16:47:16 -0500375 err = esdhc_setup_data(mmc, data);
376 if(err)
377 return err;
Peng Fan4683b222015-06-25 10:32:26 +0800378
379 if (data->flags & MMC_DATA_READ)
380 check_and_invalidate_dcache_range(cmd, data);
Andy Fleming50586ef2008-10-30 16:47:16 -0500381 }
382
383 /* Figure out the transfer arguments */
384 xfertyp = esdhc_xfertyp(cmd, data);
385
Andrew Gabbasov01b77352013-06-11 10:34:22 -0500386 /* Mask all irqs */
387 esdhc_write32(&regs->irqsigen, 0);
388
Andy Fleming50586ef2008-10-30 16:47:16 -0500389 /* Send the command */
Stefano Babicc67bee12010-02-05 15:11:27 +0100390 esdhc_write32(&regs->cmdarg, cmd->cmdarg);
Jason Liu46927082011-11-25 00:18:04 +0000391#if defined(CONFIG_FSL_USDHC)
392 esdhc_write32(&regs->mixctrl,
Volodymyr Riazantsev0e1bf612015-01-20 10:16:44 -0500393 (esdhc_read32(&regs->mixctrl) & 0xFFFFFF80) | (xfertyp & 0x7F)
394 | (mmc->ddr_mode ? XFERTYP_DDREN : 0));
Jason Liu46927082011-11-25 00:18:04 +0000395 esdhc_write32(&regs->xfertyp, xfertyp & 0xFFFF0000);
396#else
Stefano Babicc67bee12010-02-05 15:11:27 +0100397 esdhc_write32(&regs->xfertyp, xfertyp);
Jason Liu46927082011-11-25 00:18:04 +0000398#endif
Dirk Behme7a5b8022012-03-26 03:13:05 +0000399
Andy Fleming50586ef2008-10-30 16:47:16 -0500400 /* Wait for the command to complete */
Dirk Behme7a5b8022012-03-26 03:13:05 +0000401 while (!(esdhc_read32(&regs->irqstat) & (IRQSTAT_CC | IRQSTAT_CTOE)))
Stefano Babicc67bee12010-02-05 15:11:27 +0100402 ;
Andy Fleming50586ef2008-10-30 16:47:16 -0500403
Stefano Babicc67bee12010-02-05 15:11:27 +0100404 irqstat = esdhc_read32(&regs->irqstat);
Andy Fleming50586ef2008-10-30 16:47:16 -0500405
Andrew Gabbasov8a573022014-03-24 02:41:06 -0500406 if (irqstat & CMD_ERR) {
407 err = COMM_ERR;
408 goto out;
Dirk Behme7a5b8022012-03-26 03:13:05 +0000409 }
410
Andrew Gabbasov8a573022014-03-24 02:41:06 -0500411 if (irqstat & IRQSTAT_CTOE) {
412 err = TIMEOUT;
413 goto out;
414 }
Andy Fleming50586ef2008-10-30 16:47:16 -0500415
Otavio Salvadorf022d362015-02-17 10:42:43 -0200416 /* Switch voltage to 1.8V if CMD11 succeeded */
417 if (cmd->cmdidx == SD_CMD_SWITCH_UHS18V) {
418 esdhc_setbits32(&regs->vendorspec, ESDHC_VENDORSPEC_VSELECT);
419
420 printf("Run CMD11 1.8V switch\n");
421 /* Sleep for 5 ms - max time for card to switch to 1.8V */
422 udelay(5000);
423 }
424
Dirk Behme7a5b8022012-03-26 03:13:05 +0000425 /* Workaround for ESDHC errata ENGcm03648 */
426 if (!data && (cmd->resp_type & MMC_RSP_BUSY)) {
Yangbo Lu253d5bd2015-04-15 10:13:12 +0800427 int timeout = 6000;
Dirk Behme7a5b8022012-03-26 03:13:05 +0000428
Yangbo Lu253d5bd2015-04-15 10:13:12 +0800429 /* Poll on DATA0 line for cmd with busy signal for 600 ms */
Dirk Behme7a5b8022012-03-26 03:13:05 +0000430 while (timeout > 0 && !(esdhc_read32(&regs->prsstat) &
431 PRSSTAT_DAT0)) {
432 udelay(100);
433 timeout--;
434 }
435
436 if (timeout <= 0) {
437 printf("Timeout waiting for DAT0 to go high!\n");
Andrew Gabbasov8a573022014-03-24 02:41:06 -0500438 err = TIMEOUT;
439 goto out;
Dirk Behme7a5b8022012-03-26 03:13:05 +0000440 }
441 }
442
Andy Fleming50586ef2008-10-30 16:47:16 -0500443 /* Copy the response to the response buffer */
444 if (cmd->resp_type & MMC_RSP_136) {
445 u32 cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0;
446
Stefano Babicc67bee12010-02-05 15:11:27 +0100447 cmdrsp3 = esdhc_read32(&regs->cmdrsp3);
448 cmdrsp2 = esdhc_read32(&regs->cmdrsp2);
449 cmdrsp1 = esdhc_read32(&regs->cmdrsp1);
450 cmdrsp0 = esdhc_read32(&regs->cmdrsp0);
Rabin Vincent998be3d2009-04-05 13:30:56 +0530451 cmd->response[0] = (cmdrsp3 << 8) | (cmdrsp2 >> 24);
452 cmd->response[1] = (cmdrsp2 << 8) | (cmdrsp1 >> 24);
453 cmd->response[2] = (cmdrsp1 << 8) | (cmdrsp0 >> 24);
454 cmd->response[3] = (cmdrsp0 << 8);
Andy Fleming50586ef2008-10-30 16:47:16 -0500455 } else
Stefano Babicc67bee12010-02-05 15:11:27 +0100456 cmd->response[0] = esdhc_read32(&regs->cmdrsp0);
Andy Fleming50586ef2008-10-30 16:47:16 -0500457
458 /* Wait until all of the blocks are transferred */
459 if (data) {
Dipen Dudhat77c14582009-10-05 15:41:58 +0530460#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
461 esdhc_pio_read_write(mmc, data);
462#else
Andy Fleming50586ef2008-10-30 16:47:16 -0500463 do {
Stefano Babicc67bee12010-02-05 15:11:27 +0100464 irqstat = esdhc_read32(&regs->irqstat);
Andy Fleming50586ef2008-10-30 16:47:16 -0500465
Andrew Gabbasov8a573022014-03-24 02:41:06 -0500466 if (irqstat & IRQSTAT_DTOE) {
467 err = TIMEOUT;
468 goto out;
469 }
Frans Meulenbroeks63fb5a72010-07-31 04:45:18 +0000470
Andrew Gabbasov8a573022014-03-24 02:41:06 -0500471 if (irqstat & DATA_ERR) {
472 err = COMM_ERR;
473 goto out;
474 }
Andrew Gabbasov9b74dc52013-04-07 23:06:08 +0000475 } while ((irqstat & DATA_COMPLETE) != DATA_COMPLETE);
Ye.Li71689772014-02-20 18:00:57 +0800476
Peng Fan4683b222015-06-25 10:32:26 +0800477 /*
478 * Need invalidate the dcache here again to avoid any
479 * cache-fill during the DMA operations such as the
480 * speculative pre-fetching etc.
481 */
Eric Nelson54899fc2013-04-03 12:31:56 +0000482 if (data->flags & MMC_DATA_READ)
483 check_and_invalidate_dcache_range(cmd, data);
Ye.Li71689772014-02-20 18:00:57 +0800484#endif
Andy Fleming50586ef2008-10-30 16:47:16 -0500485 }
486
Andrew Gabbasov8a573022014-03-24 02:41:06 -0500487out:
488 /* Reset CMD and DATA portions on error */
489 if (err) {
490 esdhc_write32(&regs->sysctl, esdhc_read32(&regs->sysctl) |
491 SYSCTL_RSTC);
492 while (esdhc_read32(&regs->sysctl) & SYSCTL_RSTC)
493 ;
494
495 if (data) {
496 esdhc_write32(&regs->sysctl,
497 esdhc_read32(&regs->sysctl) |
498 SYSCTL_RSTD);
499 while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTD))
500 ;
501 }
Otavio Salvadorf022d362015-02-17 10:42:43 -0200502
503 /* If this was CMD11, then notify that power cycle is needed */
504 if (cmd->cmdidx == SD_CMD_SWITCH_UHS18V)
505 printf("CMD11 to switch to 1.8V mode failed, card requires power cycle.\n");
Andrew Gabbasov8a573022014-03-24 02:41:06 -0500506 }
507
Stefano Babicc67bee12010-02-05 15:11:27 +0100508 esdhc_write32(&regs->irqstat, -1);
Andy Fleming50586ef2008-10-30 16:47:16 -0500509
Andrew Gabbasov8a573022014-03-24 02:41:06 -0500510 return err;
Andy Fleming50586ef2008-10-30 16:47:16 -0500511}
512
Kim Phillipseafa90a2012-10-29 13:34:44 +0000513static void set_sysctl(struct mmc *mmc, uint clock)
Andy Fleming50586ef2008-10-30 16:47:16 -0500514{
Andy Fleming50586ef2008-10-30 16:47:16 -0500515 int div, pre_div;
Peng Fan96f04072016-03-25 14:16:56 +0800516 struct fsl_esdhc_priv *priv = mmc->priv;
517 struct fsl_esdhc *regs = priv->esdhc_regs;
518 int sdhc_clk = priv->sdhc_clk;
Andy Fleming50586ef2008-10-30 16:47:16 -0500519 uint clk;
520
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200521 if (clock < mmc->cfg->f_min)
522 clock = mmc->cfg->f_min;
Stefano Babicc67bee12010-02-05 15:11:27 +0100523
Andy Fleming50586ef2008-10-30 16:47:16 -0500524 if (sdhc_clk / 16 > clock) {
525 for (pre_div = 2; pre_div < 256; pre_div *= 2)
526 if ((sdhc_clk / pre_div) <= (clock * 16))
527 break;
528 } else
529 pre_div = 2;
530
531 for (div = 1; div <= 16; div++)
532 if ((sdhc_clk / (div * pre_div)) <= clock)
533 break;
534
Volodymyr Riazantsev0e1bf612015-01-20 10:16:44 -0500535 pre_div >>= mmc->ddr_mode ? 2 : 1;
Andy Fleming50586ef2008-10-30 16:47:16 -0500536 div -= 1;
537
538 clk = (pre_div << 8) | (div << 4);
539
Eric Nelsonf0b5f232015-12-04 12:32:48 -0700540#ifdef CONFIG_FSL_USDHC
541 esdhc_setbits32(&regs->sysctl, SYSCTL_RSTA);
542#else
Kumar Galacc4d1222010-03-18 15:51:05 -0500543 esdhc_clrbits32(&regs->sysctl, SYSCTL_CKEN);
Eric Nelsonf0b5f232015-12-04 12:32:48 -0700544#endif
Stefano Babicc67bee12010-02-05 15:11:27 +0100545
546 esdhc_clrsetbits32(&regs->sysctl, SYSCTL_CLOCK_MASK, clk);
Andy Fleming50586ef2008-10-30 16:47:16 -0500547
548 udelay(10000);
549
Eric Nelsonf0b5f232015-12-04 12:32:48 -0700550#ifdef CONFIG_FSL_USDHC
551 esdhc_clrbits32(&regs->sysctl, SYSCTL_RSTA);
552#else
553 esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_CKEN);
554#endif
Stefano Babicc67bee12010-02-05 15:11:27 +0100555
Andy Fleming50586ef2008-10-30 16:47:16 -0500556}
557
Yangbo Lu2d9ca2c2015-04-22 13:57:40 +0800558#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
559static void esdhc_clock_control(struct mmc *mmc, bool enable)
560{
Peng Fan96f04072016-03-25 14:16:56 +0800561 struct fsl_esdhc_priv *priv = mmc->priv;
562 struct fsl_esdhc *regs = priv->esdhc_regs;
Yangbo Lu2d9ca2c2015-04-22 13:57:40 +0800563 u32 value;
564 u32 time_out;
565
566 value = esdhc_read32(&regs->sysctl);
567
568 if (enable)
569 value |= SYSCTL_CKEN;
570 else
571 value &= ~SYSCTL_CKEN;
572
573 esdhc_write32(&regs->sysctl, value);
574
575 time_out = 20;
576 value = PRSSTAT_SDSTB;
577 while (!(esdhc_read32(&regs->prsstat) & value)) {
578 if (time_out == 0) {
579 printf("fsl_esdhc: Internal clock never stabilised.\n");
580 break;
581 }
582 time_out--;
583 mdelay(1);
584 }
585}
586#endif
587
Andy Fleming50586ef2008-10-30 16:47:16 -0500588static void esdhc_set_ios(struct mmc *mmc)
589{
Peng Fan96f04072016-03-25 14:16:56 +0800590 struct fsl_esdhc_priv *priv = mmc->priv;
591 struct fsl_esdhc *regs = priv->esdhc_regs;
Andy Fleming50586ef2008-10-30 16:47:16 -0500592
Yangbo Lu2d9ca2c2015-04-22 13:57:40 +0800593#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
594 /* Select to use peripheral clock */
595 esdhc_clock_control(mmc, false);
596 esdhc_setbits32(&regs->scr, ESDHCCTL_PCS);
597 esdhc_clock_control(mmc, true);
598#endif
Andy Fleming50586ef2008-10-30 16:47:16 -0500599 /* Set the clock speed */
600 set_sysctl(mmc, mmc->clock);
601
602 /* Set the bus width */
Stefano Babicc67bee12010-02-05 15:11:27 +0100603 esdhc_clrbits32(&regs->proctl, PROCTL_DTW_4 | PROCTL_DTW_8);
Andy Fleming50586ef2008-10-30 16:47:16 -0500604
605 if (mmc->bus_width == 4)
Stefano Babicc67bee12010-02-05 15:11:27 +0100606 esdhc_setbits32(&regs->proctl, PROCTL_DTW_4);
Andy Fleming50586ef2008-10-30 16:47:16 -0500607 else if (mmc->bus_width == 8)
Stefano Babicc67bee12010-02-05 15:11:27 +0100608 esdhc_setbits32(&regs->proctl, PROCTL_DTW_8);
609
Andy Fleming50586ef2008-10-30 16:47:16 -0500610}
611
612static int esdhc_init(struct mmc *mmc)
613{
Peng Fan96f04072016-03-25 14:16:56 +0800614 struct fsl_esdhc_priv *priv = mmc->priv;
615 struct fsl_esdhc *regs = priv->esdhc_regs;
Andy Fleming50586ef2008-10-30 16:47:16 -0500616 int timeout = 1000;
617
Stefano Babicc67bee12010-02-05 15:11:27 +0100618 /* Reset the entire host controller */
Dirk Behmea61da722013-07-15 15:44:29 +0200619 esdhc_setbits32(&regs->sysctl, SYSCTL_RSTA);
Stefano Babicc67bee12010-02-05 15:11:27 +0100620
621 /* Wait until the controller is available */
622 while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA) && --timeout)
623 udelay(1000);
624
Peng Fanf53225c2016-06-15 10:53:00 +0800625#if defined(CONFIG_FSL_USDHC)
626 /* RSTA doesn't reset MMC_BOOT register, so manually reset it */
627 esdhc_write32(&regs->mmcboot, 0x0);
628 /* Reset MIX_CTRL and CLK_TUNE_CTRL_STATUS regs to 0 */
629 esdhc_write32(&regs->mixctrl, 0x0);
630 esdhc_write32(&regs->clktunectrlstatus, 0x0);
631
632 /* Put VEND_SPEC to default value */
633 esdhc_write32(&regs->vendorspec, VENDORSPEC_INIT);
634
635 /* Disable DLL_CTRL delay line */
636 esdhc_write32(&regs->dllctrl, 0x0);
637#endif
638
Benoît Thébaudeau16e43f32012-08-13 07:28:16 +0000639#ifndef ARCH_MXC
P.V.Suresh2c1764e2010-12-04 10:37:23 +0530640 /* Enable cache snooping */
Benoît Thébaudeau16e43f32012-08-13 07:28:16 +0000641 esdhc_write32(&regs->scr, 0x00000040);
642#endif
P.V.Suresh2c1764e2010-12-04 10:37:23 +0530643
Eric Nelsonf0b5f232015-12-04 12:32:48 -0700644#ifndef CONFIG_FSL_USDHC
Dirk Behmea61da722013-07-15 15:44:29 +0200645 esdhc_setbits32(&regs->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN);
Eric Nelsonf0b5f232015-12-04 12:32:48 -0700646#endif
Andy Fleming50586ef2008-10-30 16:47:16 -0500647
648 /* Set the initial clock speed */
Jerry Huang4a6ee172010-11-25 17:06:07 +0000649 mmc_set_clock(mmc, 400000);
Andy Fleming50586ef2008-10-30 16:47:16 -0500650
651 /* Disable the BRR and BWR bits in IRQSTAT */
Stefano Babicc67bee12010-02-05 15:11:27 +0100652 esdhc_clrbits32(&regs->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR);
Andy Fleming50586ef2008-10-30 16:47:16 -0500653
654 /* Put the PROCTL reg back to the default */
Stefano Babicc67bee12010-02-05 15:11:27 +0100655 esdhc_write32(&regs->proctl, PROCTL_INIT);
Andy Fleming50586ef2008-10-30 16:47:16 -0500656
Stefano Babicc67bee12010-02-05 15:11:27 +0100657 /* Set timout to the maximum value */
658 esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16);
Andy Fleming50586ef2008-10-30 16:47:16 -0500659
Otavio Salvadoree0c5382015-02-17 10:42:44 -0200660#ifdef CONFIG_SYS_FSL_ESDHC_FORCE_VSELECT
661 esdhc_setbits32(&regs->vendorspec, ESDHC_VENDORSPEC_VSELECT);
662#endif
663
Thierry Redingd48d2e22012-01-02 01:15:38 +0000664 return 0;
665}
Andy Fleming50586ef2008-10-30 16:47:16 -0500666
Thierry Redingd48d2e22012-01-02 01:15:38 +0000667static int esdhc_getcd(struct mmc *mmc)
668{
Peng Fan96f04072016-03-25 14:16:56 +0800669 struct fsl_esdhc_priv *priv = mmc->priv;
670 struct fsl_esdhc *regs = priv->esdhc_regs;
Thierry Redingd48d2e22012-01-02 01:15:38 +0000671 int timeout = 1000;
Stefano Babicc67bee12010-02-05 15:11:27 +0100672
Haijun.Zhangf7e27cc2014-01-10 13:52:17 +0800673#ifdef CONFIG_ESDHC_DETECT_QUIRK
674 if (CONFIG_ESDHC_DETECT_QUIRK)
675 return 1;
676#endif
Peng Fan96f04072016-03-25 14:16:56 +0800677
678#ifdef CONFIG_DM_MMC
679 if (priv->non_removable)
680 return 1;
681
682 if (dm_gpio_is_valid(&priv->cd_gpio))
683 return dm_gpio_get_value(&priv->cd_gpio);
684#endif
685
Thierry Redingd48d2e22012-01-02 01:15:38 +0000686 while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_CINS) && --timeout)
687 udelay(1000);
688
689 return timeout > 0;
Andy Fleming50586ef2008-10-30 16:47:16 -0500690}
691
Jerry Huang48bb3bb2010-03-18 15:57:06 -0500692static void esdhc_reset(struct fsl_esdhc *regs)
693{
694 unsigned long timeout = 100; /* wait max 100 ms */
695
696 /* reset the controller */
Dirk Behmea61da722013-07-15 15:44:29 +0200697 esdhc_setbits32(&regs->sysctl, SYSCTL_RSTA);
Jerry Huang48bb3bb2010-03-18 15:57:06 -0500698
699 /* hardware clears the bit when it is done */
700 while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA) && --timeout)
701 udelay(1000);
702 if (!timeout)
703 printf("MMC/SD: Reset never completed.\n");
704}
705
Pantelis Antoniouab769f22014-02-26 19:28:45 +0200706static const struct mmc_ops esdhc_ops = {
707 .send_cmd = esdhc_send_cmd,
708 .set_ios = esdhc_set_ios,
709 .init = esdhc_init,
710 .getcd = esdhc_getcd,
711};
712
Peng Fan96f04072016-03-25 14:16:56 +0800713static int fsl_esdhc_cfg_to_priv(struct fsl_esdhc_cfg *cfg,
714 struct fsl_esdhc_priv *priv)
715{
716 if (!cfg || !priv)
717 return -EINVAL;
718
719 priv->esdhc_regs = (struct fsl_esdhc *)(unsigned long)(cfg->esdhc_base);
720 priv->bus_width = cfg->max_bus_width;
721 priv->sdhc_clk = cfg->sdhc_clk;
722
723 return 0;
724};
725
726static int fsl_esdhc_init(struct fsl_esdhc_priv *priv)
Andy Fleming50586ef2008-10-30 16:47:16 -0500727{
Stefano Babicc67bee12010-02-05 15:11:27 +0100728 struct fsl_esdhc *regs;
Andy Fleming50586ef2008-10-30 16:47:16 -0500729 struct mmc *mmc;
Li Yang030955c2010-11-25 17:06:09 +0000730 u32 caps, voltage_caps;
Andy Fleming50586ef2008-10-30 16:47:16 -0500731
Peng Fan96f04072016-03-25 14:16:56 +0800732 if (!priv)
733 return -EINVAL;
Stefano Babicc67bee12010-02-05 15:11:27 +0100734
Peng Fan96f04072016-03-25 14:16:56 +0800735 regs = priv->esdhc_regs;
Stefano Babicc67bee12010-02-05 15:11:27 +0100736
Jerry Huang48bb3bb2010-03-18 15:57:06 -0500737 /* First reset the eSDHC controller */
738 esdhc_reset(regs);
739
Eric Nelsonf0b5f232015-12-04 12:32:48 -0700740#ifndef CONFIG_FSL_USDHC
Jerry Huang975324a2012-05-17 23:57:02 +0000741 esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN
742 | SYSCTL_IPGEN | SYSCTL_CKEN);
Eric Nelsonf0b5f232015-12-04 12:32:48 -0700743#endif
Jerry Huang975324a2012-05-17 23:57:02 +0000744
Ye.Lia3d6e382014-11-04 15:35:49 +0800745 writel(SDHCI_IRQ_EN_BITS, &regs->irqstaten);
Peng Fan96f04072016-03-25 14:16:56 +0800746 memset(&priv->cfg, 0, sizeof(priv->cfg));
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200747
Li Yang030955c2010-11-25 17:06:09 +0000748 voltage_caps = 0;
Wang Huan19060bd2014-09-05 13:52:40 +0800749 caps = esdhc_read32(&regs->hostcapblt);
Roy Zang3b4456e2011-01-07 00:06:47 -0600750
751#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC135
752 caps = caps & ~(ESDHC_HOSTCAPBLT_SRS |
753 ESDHC_HOSTCAPBLT_VS18 | ESDHC_HOSTCAPBLT_VS30);
754#endif
Haijun.Zhangef38f3f2013-10-31 09:38:19 +0800755
756/* T4240 host controller capabilities register should have VS33 bit */
757#ifdef CONFIG_SYS_FSL_MMC_HAS_CAPBLT_VS33
758 caps = caps | ESDHC_HOSTCAPBLT_VS33;
759#endif
760
Andy Fleming50586ef2008-10-30 16:47:16 -0500761 if (caps & ESDHC_HOSTCAPBLT_VS18)
Li Yang030955c2010-11-25 17:06:09 +0000762 voltage_caps |= MMC_VDD_165_195;
Andy Fleming50586ef2008-10-30 16:47:16 -0500763 if (caps & ESDHC_HOSTCAPBLT_VS30)
Li Yang030955c2010-11-25 17:06:09 +0000764 voltage_caps |= MMC_VDD_29_30 | MMC_VDD_30_31;
Andy Fleming50586ef2008-10-30 16:47:16 -0500765 if (caps & ESDHC_HOSTCAPBLT_VS33)
Li Yang030955c2010-11-25 17:06:09 +0000766 voltage_caps |= MMC_VDD_32_33 | MMC_VDD_33_34;
767
Peng Fan96f04072016-03-25 14:16:56 +0800768 priv->cfg.name = "FSL_SDHC";
769 priv->cfg.ops = &esdhc_ops;
Li Yang030955c2010-11-25 17:06:09 +0000770#ifdef CONFIG_SYS_SD_VOLTAGE
Peng Fan96f04072016-03-25 14:16:56 +0800771 priv->cfg.voltages = CONFIG_SYS_SD_VOLTAGE;
Li Yang030955c2010-11-25 17:06:09 +0000772#else
Peng Fan96f04072016-03-25 14:16:56 +0800773 priv->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
Li Yang030955c2010-11-25 17:06:09 +0000774#endif
Peng Fan96f04072016-03-25 14:16:56 +0800775 if ((priv->cfg.voltages & voltage_caps) == 0) {
Li Yang030955c2010-11-25 17:06:09 +0000776 printf("voltage not supported by controller\n");
777 return -1;
778 }
Andy Fleming50586ef2008-10-30 16:47:16 -0500779
Peng Fan96f04072016-03-25 14:16:56 +0800780 if (priv->bus_width == 8)
781 priv->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
782 else if (priv->bus_width == 4)
783 priv->cfg.host_caps = MMC_MODE_4BIT;
784
785 priv->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
Volodymyr Riazantsev0e1bf612015-01-20 10:16:44 -0500786#ifdef CONFIG_SYS_FSL_ESDHC_HAS_DDR_MODE
Peng Fan96f04072016-03-25 14:16:56 +0800787 priv->cfg.host_caps |= MMC_MODE_DDR_52MHz;
Volodymyr Riazantsev0e1bf612015-01-20 10:16:44 -0500788#endif
Andy Fleming50586ef2008-10-30 16:47:16 -0500789
Peng Fan96f04072016-03-25 14:16:56 +0800790 if (priv->bus_width > 0) {
791 if (priv->bus_width < 8)
792 priv->cfg.host_caps &= ~MMC_MODE_8BIT;
793 if (priv->bus_width < 4)
794 priv->cfg.host_caps &= ~MMC_MODE_4BIT;
Abbas Razaaad46592013-03-25 09:13:34 +0000795 }
796
Andy Fleming50586ef2008-10-30 16:47:16 -0500797 if (caps & ESDHC_HOSTCAPBLT_HSS)
Peng Fan96f04072016-03-25 14:16:56 +0800798 priv->cfg.host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
Andy Fleming50586ef2008-10-30 16:47:16 -0500799
Haijun.Zhangd47e3d22014-01-10 13:52:18 +0800800#ifdef CONFIG_ESDHC_DETECT_8_BIT_QUIRK
801 if (CONFIG_ESDHC_DETECT_8_BIT_QUIRK)
Peng Fan96f04072016-03-25 14:16:56 +0800802 priv->cfg.host_caps &= ~MMC_MODE_8BIT;
Haijun.Zhangd47e3d22014-01-10 13:52:18 +0800803#endif
804
Peng Fan96f04072016-03-25 14:16:56 +0800805 priv->cfg.f_min = 400000;
806 priv->cfg.f_max = min(priv->sdhc_clk, (u32)52000000);
Andy Fleming50586ef2008-10-30 16:47:16 -0500807
Peng Fan96f04072016-03-25 14:16:56 +0800808 priv->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200809
Peng Fan96f04072016-03-25 14:16:56 +0800810 mmc = mmc_create(&priv->cfg, priv);
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200811 if (mmc == NULL)
812 return -1;
Andy Fleming50586ef2008-10-30 16:47:16 -0500813
Peng Fan96f04072016-03-25 14:16:56 +0800814 priv->mmc = mmc;
815
816 return 0;
817}
818
819int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
820{
821 struct fsl_esdhc_priv *priv;
822 int ret;
823
824 if (!cfg)
825 return -EINVAL;
826
827 priv = calloc(sizeof(struct fsl_esdhc_priv), 1);
828 if (!priv)
829 return -ENOMEM;
830
831 ret = fsl_esdhc_cfg_to_priv(cfg, priv);
832 if (ret) {
833 debug("%s xlate failure\n", __func__);
834 free(priv);
835 return ret;
836 }
837
838 ret = fsl_esdhc_init(priv);
839 if (ret) {
840 debug("%s init failure\n", __func__);
841 free(priv);
842 return ret;
843 }
844
Andy Fleming50586ef2008-10-30 16:47:16 -0500845 return 0;
846}
847
848int fsl_esdhc_mmc_init(bd_t *bis)
849{
Stefano Babicc67bee12010-02-05 15:11:27 +0100850 struct fsl_esdhc_cfg *cfg;
851
Fabio Estevam88227a12012-12-27 08:51:08 +0000852 cfg = calloc(sizeof(struct fsl_esdhc_cfg), 1);
Stefano Babicc67bee12010-02-05 15:11:27 +0100853 cfg->esdhc_base = CONFIG_SYS_FSL_ESDHC_ADDR;
Simon Glasse9adeca2012-12-13 20:49:05 +0000854 cfg->sdhc_clk = gd->arch.sdhc_clk;
Stefano Babicc67bee12010-02-05 15:11:27 +0100855 return fsl_esdhc_initialize(bis, cfg);
Andy Fleming50586ef2008-10-30 16:47:16 -0500856}
Anton Vorontsovb33433a2009-06-10 00:25:29 +0400857
Yangbo Lu5a8dbdc2015-04-22 13:57:00 +0800858#ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
859void mmc_adapter_card_type_ident(void)
860{
861 u8 card_id;
862 u8 value;
863
864 card_id = QIXIS_READ(present) & QIXIS_SDID_MASK;
865 gd->arch.sdhc_adapter = card_id;
866
867 switch (card_id) {
868 case QIXIS_ESDHC_ADAPTER_TYPE_EMMC45:
Yangbo Lucdc69552015-09-17 10:27:12 +0800869 value = QIXIS_READ(brdcfg[5]);
870 value |= (QIXIS_DAT4 | QIXIS_DAT5_6_7);
871 QIXIS_WRITE(brdcfg[5], value);
Yangbo Lu5a8dbdc2015-04-22 13:57:00 +0800872 break;
873 case QIXIS_ESDHC_ADAPTER_TYPE_SDMMC_LEGACY:
Yangbo Lubf50be82015-09-17 10:27:48 +0800874 value = QIXIS_READ(pwr_ctl[1]);
875 value |= QIXIS_EVDD_BY_SDHC_VS;
876 QIXIS_WRITE(pwr_ctl[1], value);
Yangbo Lu5a8dbdc2015-04-22 13:57:00 +0800877 break;
878 case QIXIS_ESDHC_ADAPTER_TYPE_EMMC44:
879 value = QIXIS_READ(brdcfg[5]);
880 value |= (QIXIS_SDCLKIN | QIXIS_SDCLKOUT);
881 QIXIS_WRITE(brdcfg[5], value);
882 break;
883 case QIXIS_ESDHC_ADAPTER_TYPE_RSV:
884 break;
885 case QIXIS_ESDHC_ADAPTER_TYPE_MMC:
886 break;
887 case QIXIS_ESDHC_ADAPTER_TYPE_SD:
888 break;
889 case QIXIS_ESDHC_NO_ADAPTER:
890 break;
891 default:
892 break;
893 }
894}
895#endif
896
Stefano Babicc67bee12010-02-05 15:11:27 +0100897#ifdef CONFIG_OF_LIBFDT
Anton Vorontsovb33433a2009-06-10 00:25:29 +0400898void fdt_fixup_esdhc(void *blob, bd_t *bd)
899{
900 const char *compat = "fsl,esdhc";
Anton Vorontsovb33433a2009-06-10 00:25:29 +0400901
Chenhui Zhaoa6da8b82011-01-04 17:23:05 +0800902#ifdef CONFIG_FSL_ESDHC_PIN_MUX
Anton Vorontsovb33433a2009-06-10 00:25:29 +0400903 if (!hwconfig("esdhc")) {
Chenhui Zhaoa6da8b82011-01-04 17:23:05 +0800904 do_fixup_by_compat(blob, compat, "status", "disabled",
905 8 + 1, 1);
906 return;
Anton Vorontsovb33433a2009-06-10 00:25:29 +0400907 }
Chenhui Zhaoa6da8b82011-01-04 17:23:05 +0800908#endif
Anton Vorontsovb33433a2009-06-10 00:25:29 +0400909
Yangbo Lu2d9ca2c2015-04-22 13:57:40 +0800910#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
911 do_fixup_by_compat_u32(blob, compat, "peripheral-frequency",
912 gd->arch.sdhc_clk, 1);
913#else
Anton Vorontsovb33433a2009-06-10 00:25:29 +0400914 do_fixup_by_compat_u32(blob, compat, "clock-frequency",
Simon Glasse9adeca2012-12-13 20:49:05 +0000915 gd->arch.sdhc_clk, 1);
Yangbo Lu2d9ca2c2015-04-22 13:57:40 +0800916#endif
Yangbo Lu5a8dbdc2015-04-22 13:57:00 +0800917#ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
918 do_fixup_by_compat_u32(blob, compat, "adapter-type",
919 (u32)(gd->arch.sdhc_adapter), 1);
920#endif
Chenhui Zhaoa6da8b82011-01-04 17:23:05 +0800921 do_fixup_by_compat(blob, compat, "status", "okay",
922 4 + 1, 1);
Anton Vorontsovb33433a2009-06-10 00:25:29 +0400923}
Stefano Babicc67bee12010-02-05 15:11:27 +0100924#endif
Peng Fan96f04072016-03-25 14:16:56 +0800925
926#ifdef CONFIG_DM_MMC
927#include <asm/arch/clock.h>
928static int fsl_esdhc_probe(struct udevice *dev)
929{
930 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
931 struct fsl_esdhc_priv *priv = dev_get_priv(dev);
932 const void *fdt = gd->fdt_blob;
933 int node = dev->of_offset;
934 fdt_addr_t addr;
935 unsigned int val;
936 int ret;
937
938 addr = dev_get_addr(dev);
939 if (addr == FDT_ADDR_T_NONE)
940 return -EINVAL;
941
942 priv->esdhc_regs = (struct fsl_esdhc *)addr;
943 priv->dev = dev;
944
945 val = fdtdec_get_int(fdt, node, "bus-width", -1);
946 if (val == 8)
947 priv->bus_width = 8;
948 else if (val == 4)
949 priv->bus_width = 4;
950 else
951 priv->bus_width = 1;
952
953 if (fdt_get_property(fdt, node, "non-removable", NULL)) {
954 priv->non_removable = 1;
955 } else {
956 priv->non_removable = 0;
957 gpio_request_by_name_nodev(fdt, node, "cd-gpios", 0,
958 &priv->cd_gpio, GPIOD_IS_IN);
959 }
960
961 /*
962 * TODO:
963 * Because lack of clk driver, if SDHC clk is not enabled,
964 * need to enable it first before this driver is invoked.
965 *
966 * we use MXC_ESDHC_CLK to get clk freq.
967 * If one would like to make this function work,
968 * the aliases should be provided in dts as this:
969 *
970 * aliases {
971 * mmc0 = &usdhc1;
972 * mmc1 = &usdhc2;
973 * mmc2 = &usdhc3;
974 * mmc3 = &usdhc4;
975 * };
976 * Then if your board only supports mmc2 and mmc3, but we can
977 * correctly get the seq as 2 and 3, then let mxc_get_clock
978 * work as expected.
979 */
980 priv->sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK + dev->seq);
981 if (priv->sdhc_clk <= 0) {
982 dev_err(dev, "Unable to get clk for %s\n", dev->name);
983 return -EINVAL;
984 }
985
986 ret = fsl_esdhc_init(priv);
987 if (ret) {
988 dev_err(dev, "fsl_esdhc_init failure\n");
989 return ret;
990 }
991
992 upriv->mmc = priv->mmc;
993
994 return 0;
995}
996
997static const struct udevice_id fsl_esdhc_ids[] = {
998 { .compatible = "fsl,imx6ul-usdhc", },
999 { .compatible = "fsl,imx6sx-usdhc", },
1000 { .compatible = "fsl,imx6sl-usdhc", },
1001 { .compatible = "fsl,imx6q-usdhc", },
1002 { .compatible = "fsl,imx7d-usdhc", },
1003 { /* sentinel */ }
1004};
1005
1006U_BOOT_DRIVER(fsl_esdhc) = {
1007 .name = "fsl-esdhc-mmc",
1008 .id = UCLASS_MMC,
1009 .of_match = fsl_esdhc_ids,
1010 .probe = fsl_esdhc_probe,
1011 .priv_auto_alloc_size = sizeof(struct fsl_esdhc_priv),
1012};
1013#endif