blob: 95390a5be7e59f17bb1641251784902f41e7e932 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Marek Vasut71a758e12011-11-08 23:18:09 +00002/*
3 * Freescale i.MX28 SSP MMC driver
4 *
Lukasz Majewski6116f4c2019-09-05 09:54:59 +02005 * Copyright (C) 2019 DENX Software Engineering
6 * Lukasz Majewski, DENX Software Engineering, lukma@denx.de
7 *
Marek Vasut71a758e12011-11-08 23:18:09 +00008 * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
9 * on behalf of DENX Software Engineering GmbH
10 *
11 * Based on code from LTIB:
12 * (C) Copyright 2008-2010 Freescale Semiconductor, Inc.
13 * Terry Lv
14 *
15 * Copyright 2007, Freescale Semiconductor, Inc
16 * Andy Fleming
17 *
18 * Based vaguely on the pxa mmc code:
19 * (C) Copyright 2003
20 * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
Marek Vasut71a758e12011-11-08 23:18:09 +000021 */
Lukasz Majewski6116f4c2019-09-05 09:54:59 +020022
Simon Glassf7ae49f2020-05-10 11:40:05 -060023#include <log.h>
Marek Vasut71a758e12011-11-08 23:18:09 +000024#include <malloc.h>
25#include <mmc.h>
Simon Glasscd93d622020-05-10 11:40:13 -060026#include <linux/bitops.h>
Simon Glassc05ed002020-05-10 11:40:11 -060027#include <linux/delay.h>
Masahiro Yamada1221ce42016-09-21 11:28:55 +090028#include <linux/errno.h>
Marek Vasut71a758e12011-11-08 23:18:09 +000029#include <asm/io.h>
30#include <asm/arch/clock.h>
31#include <asm/arch/imx-regs.h>
32#include <asm/arch/sys_proto.h>
Stefano Babic552a8482017-06-29 10:16:06 +020033#include <asm/mach-imx/dma.h>
Marek Vasut4e6d81d2012-08-26 15:19:07 +000034#include <bouncebuf.h>
Marek Vasut71a758e12011-11-08 23:18:09 +000035
Marek Vasut71a758e12011-11-08 23:18:09 +000036#define MXSMMC_MAX_TIMEOUT 10000
Marek Vasut20255902012-07-06 21:25:56 +000037#define MXSMMC_SMALL_TRANSFER 512
Marek Vasut71a758e12011-11-08 23:18:09 +000038
Lukasz Majewski6116f4c2019-09-05 09:54:59 +020039#if !CONFIG_IS_ENABLED(DM_MMC)
40struct mxsmmc_priv {
41 int id;
42 int (*mmc_is_wp)(int);
43 int (*mmc_cd)(int);
44 struct mmc_config cfg; /* mmc configuration */
45 struct mxs_dma_desc *desc;
46 uint32_t buswidth;
47 struct mxs_ssp_regs *regs;
48};
49#else /* CONFIG_IS_ENABLED(DM_MMC) */
50#include <dm/device.h>
51#include <dm/read.h>
52#include <dt-structs.h>
53
Simon Glass8a8d24b2020-12-03 16:55:23 -070054struct mxsmmc_plat {
Lukasz Majewski6116f4c2019-09-05 09:54:59 +020055#if CONFIG_IS_ENABLED(OF_PLATDATA)
Walter Lozanodf17cdc2020-07-23 00:22:04 -030056 struct dtd_fsl_imx23_mmc dtplat;
Lukasz Majewski6116f4c2019-09-05 09:54:59 +020057#endif
58 struct mmc_config cfg;
59 struct mmc mmc;
60 fdt_addr_t base;
61 int non_removable;
62 int buswidth;
63 int dma_id;
64 int clk_id;
65};
66
67struct mxsmmc_priv {
68 int clkid;
69 struct mxs_dma_desc *desc;
70 u32 buswidth;
71 struct mxs_ssp_regs *regs;
72 unsigned int dma_channel;
73};
74#endif
75
76#if !CONFIG_IS_ENABLED(DM_MMC)
77static int mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
78 struct mmc_data *data);
79
Marek Vasut90bc2bf2013-01-22 15:01:03 +000080static int mxsmmc_cd(struct mxsmmc_priv *priv)
81{
82 struct mxs_ssp_regs *ssp_regs = priv->regs;
83
84 if (priv->mmc_cd)
85 return priv->mmc_cd(priv->id);
86
87 return !(readl(&ssp_regs->hw_ssp_status) & SSP_STATUS_CARD_DETECT);
88}
89
Jaehoon Chung07b0b9c2016-12-30 15:30:16 +090090static int mxsmmc_set_ios(struct mmc *mmc)
Marek Vasut71a758e12011-11-08 23:18:09 +000091{
Pantelis Antoniou93bfd612014-03-11 19:34:20 +020092 struct mxsmmc_priv *priv = mmc->priv;
Otavio Salvador9c471142012-08-05 09:05:31 +000093 struct mxs_ssp_regs *ssp_regs = priv->regs;
Marek Vasut71a758e12011-11-08 23:18:09 +000094
95 /* Set the clock speed */
96 if (mmc->clock)
Otavio Salvadorbf48fcb2013-01-11 03:19:03 +000097 mxs_set_ssp_busclock(priv->id, mmc->clock / 1000);
Marek Vasut71a758e12011-11-08 23:18:09 +000098
99 switch (mmc->bus_width) {
100 case 1:
101 priv->buswidth = SSP_CTRL0_BUS_WIDTH_ONE_BIT;
102 break;
103 case 4:
104 priv->buswidth = SSP_CTRL0_BUS_WIDTH_FOUR_BIT;
105 break;
106 case 8:
107 priv->buswidth = SSP_CTRL0_BUS_WIDTH_EIGHT_BIT;
108 break;
109 }
110
111 /* Set the bus width */
112 clrsetbits_le32(&ssp_regs->hw_ssp_ctrl0,
113 SSP_CTRL0_BUS_WIDTH_MASK, priv->buswidth);
114
115 debug("MMC%d: Set %d bits bus width\n",
Lukasz Majewski6116f4c2019-09-05 09:54:59 +0200116 mmc->block_dev.devnum, mmc->bus_width);
Jaehoon Chung07b0b9c2016-12-30 15:30:16 +0900117
118 return 0;
Marek Vasut71a758e12011-11-08 23:18:09 +0000119}
120
121static int mxsmmc_init(struct mmc *mmc)
122{
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200123 struct mxsmmc_priv *priv = mmc->priv;
Otavio Salvador9c471142012-08-05 09:05:31 +0000124 struct mxs_ssp_regs *ssp_regs = priv->regs;
Marek Vasut71a758e12011-11-08 23:18:09 +0000125
126 /* Reset SSP */
Otavio Salvadorfa7a51c2012-08-13 09:53:12 +0000127 mxs_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
Marek Vasut71a758e12011-11-08 23:18:09 +0000128
Otavio Salvador8000d8a2013-01-22 15:01:02 +0000129 /* Reconfigure the SSP block for MMC operation */
130 writel(SSP_CTRL1_SSP_MODE_SD_MMC |
131 SSP_CTRL1_WORD_LENGTH_EIGHT_BITS |
132 SSP_CTRL1_DMA_ENABLE |
133 SSP_CTRL1_POLARITY |
134 SSP_CTRL1_RECV_TIMEOUT_IRQ_EN |
135 SSP_CTRL1_DATA_CRC_IRQ_EN |
136 SSP_CTRL1_DATA_TIMEOUT_IRQ_EN |
137 SSP_CTRL1_RESP_TIMEOUT_IRQ_EN |
138 SSP_CTRL1_RESP_ERR_IRQ_EN,
139 &ssp_regs->hw_ssp_ctrl1_set);
Marek Vasut71a758e12011-11-08 23:18:09 +0000140
141 /* Set initial bit clock 400 KHz */
Otavio Salvadorbf48fcb2013-01-11 03:19:03 +0000142 mxs_set_ssp_busclock(priv->id, 400);
Marek Vasut71a758e12011-11-08 23:18:09 +0000143
144 /* Send initial 74 clock cycles (185 us @ 400 KHz)*/
145 writel(SSP_CMD0_CONT_CLKING_EN, &ssp_regs->hw_ssp_cmd0_set);
146 udelay(200);
147 writel(SSP_CMD0_CONT_CLKING_EN, &ssp_regs->hw_ssp_cmd0_clr);
148
149 return 0;
150}
151
Pantelis Antoniouab769f22014-02-26 19:28:45 +0200152static const struct mmc_ops mxsmmc_ops = {
153 .send_cmd = mxsmmc_send_cmd,
154 .set_ios = mxsmmc_set_ios,
155 .init = mxsmmc_init,
156};
157
Masahiro Yamadab75d8dc2020-06-26 15:13:33 +0900158int mxsmmc_initialize(struct bd_info *bis, int id, int (*wp)(int),
159 int (*cd)(int))
Marek Vasut71a758e12011-11-08 23:18:09 +0000160{
Marek Vasut71a758e12011-11-08 23:18:09 +0000161 struct mmc *mmc = NULL;
162 struct mxsmmc_priv *priv = NULL;
Marek Vasut96666a32012-04-08 17:34:46 +0000163 int ret;
Marek Vasut3430e0b2013-02-23 02:42:58 +0000164 const unsigned int mxsmmc_clk_id = mxs_ssp_clock_by_bus(id);
Marek Vasut1a3c5ff2013-01-11 03:19:14 +0000165
Marek Vasut3430e0b2013-02-23 02:42:58 +0000166 if (!mxs_ssp_bus_id_valid(id))
Marek Vasut1a3c5ff2013-01-11 03:19:14 +0000167 return -ENODEV;
Marek Vasut71a758e12011-11-08 23:18:09 +0000168
Marek Vasut71a758e12011-11-08 23:18:09 +0000169 priv = malloc(sizeof(struct mxsmmc_priv));
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200170 if (!priv)
Marek Vasut71a758e12011-11-08 23:18:09 +0000171 return -ENOMEM;
Marek Vasut71a758e12011-11-08 23:18:09 +0000172
Marek Vasut3687c412012-03-15 18:33:21 +0000173 priv->desc = mxs_dma_desc_alloc();
174 if (!priv->desc) {
175 free(priv);
Marek Vasut3687c412012-03-15 18:33:21 +0000176 return -ENOMEM;
177 }
178
Marek Vasut3430e0b2013-02-23 02:42:58 +0000179 ret = mxs_dma_init_channel(MXS_DMA_CHANNEL_AHB_APBH_SSP0 + id);
Marek Vasut96666a32012-04-08 17:34:46 +0000180 if (ret)
181 return ret;
182
Marek Vasut71a758e12011-11-08 23:18:09 +0000183 priv->mmc_is_wp = wp;
Marek Vasut90bc2bf2013-01-22 15:01:03 +0000184 priv->mmc_cd = cd;
Marek Vasut71a758e12011-11-08 23:18:09 +0000185 priv->id = id;
Marek Vasut14e26bc2013-01-11 03:19:02 +0000186 priv->regs = mxs_ssp_regs_by_bus(id);
Marek Vasut71a758e12011-11-08 23:18:09 +0000187
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200188 priv->cfg.name = "MXS MMC";
189 priv->cfg.ops = &mxsmmc_ops;
Marek Vasut71a758e12011-11-08 23:18:09 +0000190
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200191 priv->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
Marek Vasut71a758e12011-11-08 23:18:09 +0000192
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200193 priv->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT |
Rob Herring5a203972015-03-23 17:56:59 -0500194 MMC_MODE_HS_52MHz | MMC_MODE_HS;
Marek Vasut71a758e12011-11-08 23:18:09 +0000195
196 /*
197 * SSPCLK = 480 * 18 / 29 / 1 = 297.731 MHz
198 * SSP bit rate = SSPCLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE)),
199 * CLOCK_DIVIDE has to be an even value from 2 to 254, and
200 * CLOCK_RATE could be any integer from 0 to 255.
201 */
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200202 priv->cfg.f_min = 400000;
Lukasz Majewski6116f4c2019-09-05 09:54:59 +0200203 priv->cfg.f_max = mxc_get_clock(MXC_SSP0_CLK + mxsmmc_clk_id)
204 * 1000 / 2;
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200205 priv->cfg.b_max = 0x20;
Marek Vasut71a758e12011-11-08 23:18:09 +0000206
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200207 mmc = mmc_create(&priv->cfg, priv);
Lukasz Majewski6116f4c2019-09-05 09:54:59 +0200208 if (!mmc) {
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200209 mxs_dma_desc_free(priv->desc);
210 free(priv);
211 return -ENOMEM;
212 }
Marek Vasut71a758e12011-11-08 23:18:09 +0000213 return 0;
214}
Lukasz Majewski6116f4c2019-09-05 09:54:59 +0200215#endif /* CONFIG_IS_ENABLED(DM_MMC) */
216
217static int mxsmmc_send_cmd_pio(struct mxsmmc_priv *priv, struct mmc_data *data)
218{
219 struct mxs_ssp_regs *ssp_regs = priv->regs;
220 uint32_t *data_ptr;
221 int timeout = MXSMMC_MAX_TIMEOUT;
222 uint32_t reg;
223 uint32_t data_count = data->blocksize * data->blocks;
224
225 if (data->flags & MMC_DATA_READ) {
226 data_ptr = (uint32_t *)data->dest;
227 while (data_count && --timeout) {
228 reg = readl(&ssp_regs->hw_ssp_status);
229 if (!(reg & SSP_STATUS_FIFO_EMPTY)) {
230 *data_ptr++ = readl(&ssp_regs->hw_ssp_data);
231 data_count -= 4;
232 timeout = MXSMMC_MAX_TIMEOUT;
233 } else
234 udelay(1000);
235 }
236 } else {
237 data_ptr = (uint32_t *)data->src;
238 timeout *= 100;
239 while (data_count && --timeout) {
240 reg = readl(&ssp_regs->hw_ssp_status);
241 if (!(reg & SSP_STATUS_FIFO_FULL)) {
242 writel(*data_ptr++, &ssp_regs->hw_ssp_data);
243 data_count -= 4;
244 timeout = MXSMMC_MAX_TIMEOUT;
245 } else
246 udelay(1000);
247 }
248 }
249
250 return timeout ? 0 : -ECOMM;
251}
252
253static int mxsmmc_send_cmd_dma(struct mxsmmc_priv *priv, struct mmc_data *data)
254{
255 uint32_t data_count = data->blocksize * data->blocks;
256 int dmach;
257 struct mxs_dma_desc *desc = priv->desc;
258 void *addr;
259 unsigned int flags;
260 struct bounce_buffer bbstate;
261
262 memset(desc, 0, sizeof(struct mxs_dma_desc));
263 desc->address = (dma_addr_t)desc;
264
265 if (data->flags & MMC_DATA_READ) {
266 priv->desc->cmd.data = MXS_DMA_DESC_COMMAND_DMA_WRITE;
267 addr = data->dest;
268 flags = GEN_BB_WRITE;
269 } else {
270 priv->desc->cmd.data = MXS_DMA_DESC_COMMAND_DMA_READ;
271 addr = (void *)data->src;
272 flags = GEN_BB_READ;
273 }
274
275 bounce_buffer_start(&bbstate, addr, data_count, flags);
276
277 priv->desc->cmd.address = (dma_addr_t)bbstate.bounce_buffer;
278
279 priv->desc->cmd.data |= MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM |
280 (data_count << MXS_DMA_DESC_BYTES_OFFSET);
281
282#if !CONFIG_IS_ENABLED(DM_MMC)
283 dmach = MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->id;
284#else
285 dmach = priv->dma_channel;
286#endif
287 mxs_dma_desc_append(dmach, priv->desc);
288 if (mxs_dma_go(dmach)) {
289 bounce_buffer_stop(&bbstate);
290 return -ECOMM;
291 }
292
293 bounce_buffer_stop(&bbstate);
294
295 return 0;
296}
297
298#if !CONFIG_IS_ENABLED(DM_MMC)
299/*
300 * Sends a command out on the bus. Takes the mmc pointer,
301 * a command pointer, and an optional data pointer.
302 */
303static int
304mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
305{
306 struct mxsmmc_priv *priv = mmc->priv;
307 struct mxs_ssp_regs *ssp_regs = priv->regs;
308#else
309static int
310mxsmmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, struct mmc_data *data)
311{
Simon Glass8a8d24b2020-12-03 16:55:23 -0700312 struct mxsmmc_plat *plat = dev_get_plat(dev);
Lukasz Majewski6116f4c2019-09-05 09:54:59 +0200313 struct mxsmmc_priv *priv = dev_get_priv(dev);
314 struct mxs_ssp_regs *ssp_regs = priv->regs;
315 struct mmc *mmc = &plat->mmc;
316#endif
317 uint32_t reg;
318 int timeout;
319 uint32_t ctrl0;
320 int ret;
321#if !CONFIG_IS_ENABLED(DM_MMC)
322 int devnum = mmc->block_dev.devnum;
323#else
324 int devnum = mmc_get_blk_desc(mmc)->devnum;
325#endif
326 debug("MMC%d: CMD%d\n", devnum, cmd->cmdidx);
327
328 /* Check bus busy */
329 timeout = MXSMMC_MAX_TIMEOUT;
330 while (--timeout) {
331 udelay(1000);
332 reg = readl(&ssp_regs->hw_ssp_status);
333 if (!(reg &
334 (SSP_STATUS_BUSY | SSP_STATUS_DATA_BUSY |
335 SSP_STATUS_CMD_BUSY))) {
336 break;
337 }
338 }
339
340 if (!timeout) {
341 printf("MMC%d: Bus busy timeout!\n", devnum);
342 return -ETIMEDOUT;
343 }
344#if !CONFIG_IS_ENABLED(DM_MMC)
345 /* See if card is present */
346 if (!mxsmmc_cd(priv)) {
347 printf("MMC%d: No card detected!\n", devnum);
348 return -ENOMEDIUM;
349 }
350#endif
351 /* Start building CTRL0 contents */
352 ctrl0 = priv->buswidth;
353
354 /* Set up command */
355 if (!(cmd->resp_type & MMC_RSP_CRC))
356 ctrl0 |= SSP_CTRL0_IGNORE_CRC;
357 if (cmd->resp_type & MMC_RSP_PRESENT) /* Need to get response */
358 ctrl0 |= SSP_CTRL0_GET_RESP;
359 if (cmd->resp_type & MMC_RSP_136) /* It's a 136 bits response */
360 ctrl0 |= SSP_CTRL0_LONG_RESP;
361
362 if (data && (data->blocksize * data->blocks < MXSMMC_SMALL_TRANSFER))
363 writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_clr);
364 else
365 writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_set);
366
367 /* Command index */
368 reg = readl(&ssp_regs->hw_ssp_cmd0);
369 reg &= ~(SSP_CMD0_CMD_MASK | SSP_CMD0_APPEND_8CYC);
370 reg |= cmd->cmdidx << SSP_CMD0_CMD_OFFSET;
371 if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
372 reg |= SSP_CMD0_APPEND_8CYC;
373 writel(reg, &ssp_regs->hw_ssp_cmd0);
374
375 /* Command argument */
376 writel(cmd->cmdarg, &ssp_regs->hw_ssp_cmd1);
377
378 /* Set up data */
379 if (data) {
380 /* READ or WRITE */
381 if (data->flags & MMC_DATA_READ) {
382 ctrl0 |= SSP_CTRL0_READ;
383#if !CONFIG_IS_ENABLED(DM_MMC)
384 } else if (priv->mmc_is_wp &&
385 priv->mmc_is_wp(devnum)) {
386 printf("MMC%d: Can not write a locked card!\n", devnum);
387 return -EOPNOTSUPP;
388#endif
389 }
390 ctrl0 |= SSP_CTRL0_DATA_XFER;
391
392 reg = data->blocksize * data->blocks;
393#if defined(CONFIG_MX23)
394 ctrl0 |= reg & SSP_CTRL0_XFER_COUNT_MASK;
395
396 clrsetbits_le32(&ssp_regs->hw_ssp_cmd0,
397 SSP_CMD0_BLOCK_SIZE_MASK | SSP_CMD0_BLOCK_COUNT_MASK,
398 ((data->blocks - 1) << SSP_CMD0_BLOCK_COUNT_OFFSET) |
399 ((ffs(data->blocksize) - 1) <<
400 SSP_CMD0_BLOCK_SIZE_OFFSET));
401#elif defined(CONFIG_MX28)
402 writel(reg, &ssp_regs->hw_ssp_xfer_size);
403
404 reg = ((data->blocks - 1) <<
405 SSP_BLOCK_SIZE_BLOCK_COUNT_OFFSET) |
406 ((ffs(data->blocksize) - 1) <<
407 SSP_BLOCK_SIZE_BLOCK_SIZE_OFFSET);
408 writel(reg, &ssp_regs->hw_ssp_block_size);
409#endif
410 }
411
412 /* Kick off the command */
413 ctrl0 |= SSP_CTRL0_WAIT_FOR_IRQ | SSP_CTRL0_ENABLE | SSP_CTRL0_RUN;
414 writel(ctrl0, &ssp_regs->hw_ssp_ctrl0);
415
416 /* Wait for the command to complete */
417 timeout = MXSMMC_MAX_TIMEOUT;
418 while (--timeout) {
419 udelay(1000);
420 reg = readl(&ssp_regs->hw_ssp_status);
421 if (!(reg & SSP_STATUS_CMD_BUSY))
422 break;
423 }
424
425 if (!timeout) {
426 printf("MMC%d: Command %d busy\n", devnum, cmd->cmdidx);
427 return -ETIMEDOUT;
428 }
429
430 /* Check command timeout */
431 if (reg & SSP_STATUS_RESP_TIMEOUT) {
Lukasz Majewskicf319142019-09-05 09:55:00 +0200432 debug("MMC%d: Command %d timeout (status 0x%08x)\n",
433 devnum, cmd->cmdidx, reg);
Lukasz Majewski6116f4c2019-09-05 09:54:59 +0200434 return -ETIMEDOUT;
435 }
436
437 /* Check command errors */
438 if (reg & (SSP_STATUS_RESP_CRC_ERR | SSP_STATUS_RESP_ERR)) {
439 printf("MMC%d: Command %d error (status 0x%08x)!\n",
440 devnum, cmd->cmdidx, reg);
441 return -ECOMM;
442 }
443
444 /* Copy response to response buffer */
445 if (cmd->resp_type & MMC_RSP_136) {
446 cmd->response[3] = readl(&ssp_regs->hw_ssp_sdresp0);
447 cmd->response[2] = readl(&ssp_regs->hw_ssp_sdresp1);
448 cmd->response[1] = readl(&ssp_regs->hw_ssp_sdresp2);
449 cmd->response[0] = readl(&ssp_regs->hw_ssp_sdresp3);
450 } else
451 cmd->response[0] = readl(&ssp_regs->hw_ssp_sdresp0);
452
453 /* Return if no data to process */
454 if (!data)
455 return 0;
456
457 if (data->blocksize * data->blocks < MXSMMC_SMALL_TRANSFER) {
458 ret = mxsmmc_send_cmd_pio(priv, data);
459 if (ret) {
460 printf("MMC%d: Data timeout with command %d "
461 "(status 0x%08x)!\n", devnum, cmd->cmdidx, reg);
462 return ret;
463 }
464 } else {
465 ret = mxsmmc_send_cmd_dma(priv, data);
466 if (ret) {
467 printf("MMC%d: DMA transfer failed\n", devnum);
468 return ret;
469 }
470 }
471
472 /* Check data errors */
473 reg = readl(&ssp_regs->hw_ssp_status);
474 if (reg &
475 (SSP_STATUS_TIMEOUT | SSP_STATUS_DATA_CRC_ERR |
476 SSP_STATUS_FIFO_OVRFLW | SSP_STATUS_FIFO_UNDRFLW)) {
477 printf("MMC%d: Data error with command %d (status 0x%08x)!\n",
478 devnum, cmd->cmdidx, reg);
479 return -ECOMM;
480 }
481
482 return 0;
483}
484
485#if CONFIG_IS_ENABLED(DM_MMC)
486/* Base numbers of i.MX2[38] clk for ssp0 IP block */
487#define MXS_SSP_IMX23_CLKID_SSP0 33
488#define MXS_SSP_IMX28_CLKID_SSP0 46
489
490static int mxsmmc_get_cd(struct udevice *dev)
491{
Simon Glass8a8d24b2020-12-03 16:55:23 -0700492 struct mxsmmc_plat *plat = dev_get_plat(dev);
Lukasz Majewski6116f4c2019-09-05 09:54:59 +0200493 struct mxsmmc_priv *priv = dev_get_priv(dev);
494 struct mxs_ssp_regs *ssp_regs = priv->regs;
495
496 if (plat->non_removable)
497 return 1;
498
499 return !(readl(&ssp_regs->hw_ssp_status) & SSP_STATUS_CARD_DETECT);
500}
501
502static int mxsmmc_set_ios(struct udevice *dev)
503{
Simon Glass8a8d24b2020-12-03 16:55:23 -0700504 struct mxsmmc_plat *plat = dev_get_plat(dev);
Lukasz Majewski6116f4c2019-09-05 09:54:59 +0200505 struct mxsmmc_priv *priv = dev_get_priv(dev);
506 struct mxs_ssp_regs *ssp_regs = priv->regs;
507 struct mmc *mmc = &plat->mmc;
508
509 /* Set the clock speed */
510 if (mmc->clock)
511 mxs_set_ssp_busclock(priv->clkid, mmc->clock / 1000);
512
513 switch (mmc->bus_width) {
514 case 1:
515 priv->buswidth = SSP_CTRL0_BUS_WIDTH_ONE_BIT;
516 break;
517 case 4:
518 priv->buswidth = SSP_CTRL0_BUS_WIDTH_FOUR_BIT;
519 break;
520 case 8:
521 priv->buswidth = SSP_CTRL0_BUS_WIDTH_EIGHT_BIT;
522 break;
523 }
524
525 /* Set the bus width */
526 clrsetbits_le32(&ssp_regs->hw_ssp_ctrl0,
527 SSP_CTRL0_BUS_WIDTH_MASK, priv->buswidth);
528
529 debug("MMC%d: Set %d bits bus width\n", mmc_get_blk_desc(mmc)->devnum,
530 mmc->bus_width);
531
532 return 0;
533}
534
535static int mxsmmc_init(struct udevice *dev)
536{
537 struct mxsmmc_priv *priv = dev_get_priv(dev);
538 struct mxs_ssp_regs *ssp_regs = priv->regs;
539
540 /* Reset SSP */
541 mxs_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
542
543 /* Reconfigure the SSP block for MMC operation */
544 writel(SSP_CTRL1_SSP_MODE_SD_MMC |
545 SSP_CTRL1_WORD_LENGTH_EIGHT_BITS |
546 SSP_CTRL1_DMA_ENABLE |
547 SSP_CTRL1_POLARITY |
548 SSP_CTRL1_RECV_TIMEOUT_IRQ_EN |
549 SSP_CTRL1_DATA_CRC_IRQ_EN |
550 SSP_CTRL1_DATA_TIMEOUT_IRQ_EN |
551 SSP_CTRL1_RESP_TIMEOUT_IRQ_EN |
552 SSP_CTRL1_RESP_ERR_IRQ_EN,
553 &ssp_regs->hw_ssp_ctrl1_set);
554
555 /* Set initial bit clock 400 KHz */
556 mxs_set_ssp_busclock(priv->clkid, 400);
557
558 /* Send initial 74 clock cycles (185 us @ 400 KHz)*/
559 writel(SSP_CMD0_CONT_CLKING_EN, &ssp_regs->hw_ssp_cmd0_set);
560 udelay(200);
561 writel(SSP_CMD0_CONT_CLKING_EN, &ssp_regs->hw_ssp_cmd0_clr);
562
563 return 0;
564}
565
566static int mxsmmc_probe(struct udevice *dev)
567{
568 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
Simon Glass8a8d24b2020-12-03 16:55:23 -0700569 struct mxsmmc_plat *plat = dev_get_plat(dev);
Lukasz Majewski6116f4c2019-09-05 09:54:59 +0200570 struct mxsmmc_priv *priv = dev_get_priv(dev);
571 struct blk_desc *bdesc;
572 struct mmc *mmc;
573 int ret, clkid;
574
575 debug("%s: probe\n", __func__);
576
577#if CONFIG_IS_ENABLED(OF_PLATDATA)
Walter Lozanodf17cdc2020-07-23 00:22:04 -0300578 struct dtd_fsl_imx23_mmc *dtplat = &plat->dtplat;
Lukasz Majewski6116f4c2019-09-05 09:54:59 +0200579 struct phandle_1_arg *p1a = &dtplat->clocks[0];
580
581 priv->buswidth = dtplat->bus_width;
582 priv->regs = (struct mxs_ssp_regs *)dtplat->reg[0];
583 priv->dma_channel = dtplat->dmas[1];
584 clkid = p1a->arg[0];
585 plat->non_removable = dtplat->non_removable;
586
587 debug("OF_PLATDATA: regs: 0x%p bw: %d clkid: %d non_removable: %d\n",
588 priv->regs, priv->buswidth, clkid, plat->non_removable);
589#else
590 priv->regs = (struct mxs_ssp_regs *)plat->base;
591 priv->dma_channel = plat->dma_id;
592 clkid = plat->clk_id;
593#endif
594
595#ifdef CONFIG_MX28
596 priv->clkid = clkid - MXS_SSP_IMX28_CLKID_SSP0;
597#else /* CONFIG_MX23 */
598 priv->clkid = clkid - MXS_SSP_IMX23_CLKID_SSP0;
599#endif
600 mmc = &plat->mmc;
601 mmc->cfg = &plat->cfg;
602 mmc->dev = dev;
603
604 priv->desc = mxs_dma_desc_alloc();
605 if (!priv->desc) {
606 printf("%s: Cannot allocate DMA descriptor\n", __func__);
607 return -ENOMEM;
608 }
609
610 ret = mxs_dma_init_channel(priv->dma_channel);
611 if (ret)
612 return ret;
613
614 plat->cfg.name = "MXS MMC";
615 plat->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
616
617 plat->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT |
618 MMC_MODE_HS_52MHz | MMC_MODE_HS;
619
620 /*
621 * SSPCLK = 480 * 18 / 29 / 1 = 297.731 MHz
622 * SSP bit rate = SSPCLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE)),
623 * CLOCK_DIVIDE has to be an even value from 2 to 254, and
624 * CLOCK_RATE could be any integer from 0 to 255.
625 */
626 plat->cfg.f_min = 400000;
627 plat->cfg.f_max = mxc_get_clock(MXC_SSP0_CLK + priv->clkid) * 1000 / 2;
628 plat->cfg.b_max = 0x20;
629
630 bdesc = mmc_get_blk_desc(mmc);
631 if (!bdesc) {
632 printf("%s: No block device descriptor!\n", __func__);
633 return -ENODEV;
634 }
635
636 if (plat->non_removable)
637 bdesc->removable = 0;
638
639 ret = mxsmmc_init(dev);
640 if (ret)
641 printf("%s: MMC%d init error %d\n", __func__,
642 bdesc->devnum, ret);
643
644 /* Set the initial clock speed */
645 mmc_set_clock(mmc, 400000, MMC_CLK_ENABLE);
646
647 upriv->mmc = mmc;
648
649 return 0;
650};
651
652#if CONFIG_IS_ENABLED(BLK)
653static int mxsmmc_bind(struct udevice *dev)
654{
Simon Glass8a8d24b2020-12-03 16:55:23 -0700655 struct mxsmmc_plat *plat = dev_get_plat(dev);
Lukasz Majewski6116f4c2019-09-05 09:54:59 +0200656
657 return mmc_bind(dev, &plat->mmc, &plat->cfg);
658}
659#endif
660
661static const struct dm_mmc_ops mxsmmc_ops = {
662 .get_cd = mxsmmc_get_cd,
663 .send_cmd = mxsmmc_send_cmd,
664 .set_ios = mxsmmc_set_ios,
665};
666
Simon Glass414cc152021-08-07 07:24:03 -0600667#if CONFIG_IS_ENABLED(OF_REAL)
Simon Glassd1998a92020-12-03 16:55:21 -0700668static int mxsmmc_of_to_plat(struct udevice *bus)
Lukasz Majewski6116f4c2019-09-05 09:54:59 +0200669{
Simon Glass0fd3d912020-12-22 19:30:28 -0700670 struct mxsmmc_plat *plat = dev_get_plat(bus);
Lukasz Majewski6116f4c2019-09-05 09:54:59 +0200671 u32 prop[2];
672 int ret;
673
674 plat->base = dev_read_addr(bus);
675 plat->buswidth =
676 dev_read_u32_default(bus, "bus-width", 1);
677 plat->non_removable = dev_read_bool(bus, "non-removable");
678
679 ret = dev_read_u32_array(bus, "dmas", prop, ARRAY_SIZE(prop));
680 if (ret) {
681 printf("%s: Reading 'dmas' property failed!\n", __func__);
682 return ret;
683 }
684 plat->dma_id = prop[1];
685
686 ret = dev_read_u32_array(bus, "clocks", prop, ARRAY_SIZE(prop));
687 if (ret) {
688 printf("%s: Reading 'clocks' property failed!\n", __func__);
689 return ret;
690 }
691 plat->clk_id = prop[1];
692
693 debug("%s: base=0x%x, bus_width=%d %s dma_id=%d clk_id=%d\n",
694 __func__, (uint)plat->base, plat->buswidth,
695 plat->non_removable ? "non-removable" : NULL,
696 plat->dma_id, plat->clk_id);
697
698 return 0;
699}
700
701static const struct udevice_id mxsmmc_ids[] = {
702 { .compatible = "fsl,imx23-mmc", },
703 { .compatible = "fsl,imx28-mmc", },
704 { /* sentinel */ }
705};
706#endif
707
Walter Lozanoe3e24702020-06-25 01:10:04 -0300708U_BOOT_DRIVER(fsl_imx23_mmc) = {
Lukasz Majewski6116f4c2019-09-05 09:54:59 +0200709 .name = "fsl_imx23_mmc",
Lukasz Majewski6116f4c2019-09-05 09:54:59 +0200710 .id = UCLASS_MMC,
Simon Glass414cc152021-08-07 07:24:03 -0600711#if CONFIG_IS_ENABLED(OF_REAL)
Lukasz Majewski6116f4c2019-09-05 09:54:59 +0200712 .of_match = mxsmmc_ids,
Simon Glassd1998a92020-12-03 16:55:21 -0700713 .of_to_plat = mxsmmc_of_to_plat,
Lukasz Majewski6116f4c2019-09-05 09:54:59 +0200714#endif
715 .ops = &mxsmmc_ops,
716#if CONFIG_IS_ENABLED(BLK)
717 .bind = mxsmmc_bind,
718#endif
719 .probe = mxsmmc_probe,
Simon Glass41575d82020-12-03 16:55:17 -0700720 .priv_auto = sizeof(struct mxsmmc_priv),
Simon Glass8a8d24b2020-12-03 16:55:23 -0700721 .plat_auto = sizeof(struct mxsmmc_plat),
Lukasz Majewski6116f4c2019-09-05 09:54:59 +0200722};
723
Simon Glassbdf8fd72020-12-28 20:34:57 -0700724DM_DRIVER_ALIAS(fsl_imx23_mmc, fsl_imx28_mmc)
Lukasz Majewski6116f4c2019-09-05 09:54:59 +0200725#endif /* CONFIG_DM_MMC */