xref: /openbmc/u-boot/drivers/mmc/arm_pl180_mmci.c (revision fa9115616588770960827e9915d7a6de8f3aa616)
1  // SPDX-License-Identifier: GPL-2.0+
2  /*
3   * ARM PrimeCell MultiMedia Card Interface - PL180
4   *
5   * Copyright (C) ST-Ericsson SA 2010
6   *
7   * Author: Ulf Hansson <ulf.hansson@stericsson.com>
8   * Author: Martin Lundholm <martin.xa.lundholm@stericsson.com>
9   * Ported to drivers/mmc/ by: Matt Waddel <matt.waddel@linaro.org>
10   */
11  
12  /* #define DEBUG */
13  
14  #include "common.h"
15  #include <clk.h>
16  #include <errno.h>
17  #include <malloc.h>
18  #include <mmc.h>
19  
20  #include <asm/io.h>
21  #include <asm-generic/gpio.h>
22  
23  #include "arm_pl180_mmci.h"
24  
25  #ifdef CONFIG_DM_MMC
26  #include <dm.h>
27  #define MMC_CLOCK_MAX	48000000
28  #define MMC_CLOCK_MIN	400000
29  
30  struct arm_pl180_mmc_plat {
31  	struct mmc_config cfg;
32  	struct mmc mmc;
33  };
34  #endif
35  
wait_for_command_end(struct mmc * dev,struct mmc_cmd * cmd)36  static int wait_for_command_end(struct mmc *dev, struct mmc_cmd *cmd)
37  {
38  	u32 hoststatus, statusmask;
39  	struct pl180_mmc_host *host = dev->priv;
40  
41  	statusmask = SDI_STA_CTIMEOUT | SDI_STA_CCRCFAIL;
42  	if ((cmd->resp_type & MMC_RSP_PRESENT))
43  		statusmask |= SDI_STA_CMDREND;
44  	else
45  		statusmask |= SDI_STA_CMDSENT;
46  
47  	do
48  		hoststatus = readl(&host->base->status) & statusmask;
49  	while (!hoststatus);
50  
51  	writel(statusmask, &host->base->status_clear);
52  	if (hoststatus & SDI_STA_CTIMEOUT) {
53  		debug("CMD%d time out\n", cmd->cmdidx);
54  		return -ETIMEDOUT;
55  	} else if ((hoststatus & SDI_STA_CCRCFAIL) &&
56  		   (cmd->resp_type & MMC_RSP_CRC)) {
57  		printf("CMD%d CRC error\n", cmd->cmdidx);
58  		return -EILSEQ;
59  	}
60  
61  	if (cmd->resp_type & MMC_RSP_PRESENT) {
62  		cmd->response[0] = readl(&host->base->response0);
63  		cmd->response[1] = readl(&host->base->response1);
64  		cmd->response[2] = readl(&host->base->response2);
65  		cmd->response[3] = readl(&host->base->response3);
66  		debug("CMD%d response[0]:0x%08X, response[1]:0x%08X, "
67  			"response[2]:0x%08X, response[3]:0x%08X\n",
68  			cmd->cmdidx, cmd->response[0], cmd->response[1],
69  			cmd->response[2], cmd->response[3]);
70  	}
71  
72  	return 0;
73  }
74  
75  /* send command to the mmc card and wait for results */
do_command(struct mmc * dev,struct mmc_cmd * cmd)76  static int do_command(struct mmc *dev, struct mmc_cmd *cmd)
77  {
78  	int result;
79  	u32 sdi_cmd = 0;
80  	struct pl180_mmc_host *host = dev->priv;
81  
82  	sdi_cmd = ((cmd->cmdidx & SDI_CMD_CMDINDEX_MASK) | SDI_CMD_CPSMEN);
83  
84  	if (cmd->resp_type) {
85  		sdi_cmd |= SDI_CMD_WAITRESP;
86  		if (cmd->resp_type & MMC_RSP_136)
87  			sdi_cmd |= SDI_CMD_LONGRESP;
88  	}
89  
90  	writel((u32)cmd->cmdarg, &host->base->argument);
91  	udelay(COMMAND_REG_DELAY);
92  	writel(sdi_cmd, &host->base->command);
93  	result = wait_for_command_end(dev, cmd);
94  
95  	/* After CMD2 set RCA to a none zero value. */
96  	if ((result == 0) && (cmd->cmdidx == MMC_CMD_ALL_SEND_CID))
97  		dev->rca = 10;
98  
99  	/* After CMD3 open drain is switched off and push pull is used. */
100  	if ((result == 0) && (cmd->cmdidx == MMC_CMD_SET_RELATIVE_ADDR)) {
101  		u32 sdi_pwr = readl(&host->base->power) & ~SDI_PWR_OPD;
102  		writel(sdi_pwr, &host->base->power);
103  	}
104  
105  	return result;
106  }
107  
read_bytes(struct mmc * dev,u32 * dest,u32 blkcount,u32 blksize)108  static int read_bytes(struct mmc *dev, u32 *dest, u32 blkcount, u32 blksize)
109  {
110  	u32 *tempbuff = dest;
111  	u64 xfercount = blkcount * blksize;
112  	struct pl180_mmc_host *host = dev->priv;
113  	u32 status, status_err;
114  
115  	debug("read_bytes: blkcount=%u blksize=%u\n", blkcount, blksize);
116  
117  	status = readl(&host->base->status);
118  	status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT |
119  			       SDI_STA_RXOVERR);
120  	while ((!status_err) && (xfercount >= sizeof(u32))) {
121  		if (status & SDI_STA_RXDAVL) {
122  			*(tempbuff) = readl(&host->base->fifo);
123  			tempbuff++;
124  			xfercount -= sizeof(u32);
125  		}
126  		status = readl(&host->base->status);
127  		status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT |
128  				       SDI_STA_RXOVERR);
129  	}
130  
131  	status_err = status &
132  		(SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | SDI_STA_DBCKEND |
133  		 SDI_STA_RXOVERR);
134  	while (!status_err) {
135  		status = readl(&host->base->status);
136  		status_err = status &
137  			(SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | SDI_STA_DBCKEND |
138  			 SDI_STA_RXOVERR);
139  	}
140  
141  	if (status & SDI_STA_DTIMEOUT) {
142  		printf("Read data timed out, xfercount: %llu, status: 0x%08X\n",
143  			xfercount, status);
144  		return -ETIMEDOUT;
145  	} else if (status & SDI_STA_DCRCFAIL) {
146  		printf("Read data bytes CRC error: 0x%x\n", status);
147  		return -EILSEQ;
148  	} else if (status & SDI_STA_RXOVERR) {
149  		printf("Read data RX overflow error\n");
150  		return -EIO;
151  	}
152  
153  	writel(SDI_ICR_MASK, &host->base->status_clear);
154  
155  	if (xfercount) {
156  		printf("Read data error, xfercount: %llu\n", xfercount);
157  		return -ENOBUFS;
158  	}
159  
160  	return 0;
161  }
162  
write_bytes(struct mmc * dev,u32 * src,u32 blkcount,u32 blksize)163  static int write_bytes(struct mmc *dev, u32 *src, u32 blkcount, u32 blksize)
164  {
165  	u32 *tempbuff = src;
166  	int i;
167  	u64 xfercount = blkcount * blksize;
168  	struct pl180_mmc_host *host = dev->priv;
169  	u32 status, status_err;
170  
171  	debug("write_bytes: blkcount=%u blksize=%u\n", blkcount, blksize);
172  
173  	status = readl(&host->base->status);
174  	status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT);
175  	while (!status_err && xfercount) {
176  		if (status & SDI_STA_TXFIFOBW) {
177  			if (xfercount >= SDI_FIFO_BURST_SIZE * sizeof(u32)) {
178  				for (i = 0; i < SDI_FIFO_BURST_SIZE; i++)
179  					writel(*(tempbuff + i),
180  						&host->base->fifo);
181  				tempbuff += SDI_FIFO_BURST_SIZE;
182  				xfercount -= SDI_FIFO_BURST_SIZE * sizeof(u32);
183  			} else {
184  				while (xfercount >= sizeof(u32)) {
185  					writel(*(tempbuff), &host->base->fifo);
186  					tempbuff++;
187  					xfercount -= sizeof(u32);
188  				}
189  			}
190  		}
191  		status = readl(&host->base->status);
192  		status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT);
193  	}
194  
195  	status_err = status &
196  		(SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | SDI_STA_DBCKEND);
197  	while (!status_err) {
198  		status = readl(&host->base->status);
199  		status_err = status &
200  			(SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | SDI_STA_DBCKEND);
201  	}
202  
203  	if (status & SDI_STA_DTIMEOUT) {
204  		printf("Write data timed out, xfercount:%llu,status:0x%08X\n",
205  		       xfercount, status);
206  		return -ETIMEDOUT;
207  	} else if (status & SDI_STA_DCRCFAIL) {
208  		printf("Write data CRC error\n");
209  		return -EILSEQ;
210  	}
211  
212  	writel(SDI_ICR_MASK, &host->base->status_clear);
213  
214  	if (xfercount) {
215  		printf("Write data error, xfercount:%llu", xfercount);
216  		return -ENOBUFS;
217  	}
218  
219  	return 0;
220  }
221  
do_data_transfer(struct mmc * dev,struct mmc_cmd * cmd,struct mmc_data * data)222  static int do_data_transfer(struct mmc *dev,
223  			    struct mmc_cmd *cmd,
224  			    struct mmc_data *data)
225  {
226  	int error = -ETIMEDOUT;
227  	struct pl180_mmc_host *host = dev->priv;
228  	u32 blksz = 0;
229  	u32 data_ctrl = 0;
230  	u32 data_len = (u32) (data->blocks * data->blocksize);
231  
232  	if (!host->version2) {
233  		blksz = (ffs(data->blocksize) - 1);
234  		data_ctrl |= ((blksz << 4) & SDI_DCTRL_DBLKSIZE_MASK);
235  	} else {
236  		blksz = data->blocksize;
237  		data_ctrl |= (blksz << SDI_DCTRL_DBLOCKSIZE_V2_SHIFT);
238  	}
239  	data_ctrl |= SDI_DCTRL_DTEN | SDI_DCTRL_BUSYMODE;
240  
241  	writel(SDI_DTIMER_DEFAULT, &host->base->datatimer);
242  	writel(data_len, &host->base->datalength);
243  	udelay(DATA_REG_DELAY);
244  
245  	if (data->flags & MMC_DATA_READ) {
246  		data_ctrl |= SDI_DCTRL_DTDIR_IN;
247  		writel(data_ctrl, &host->base->datactrl);
248  
249  		error = do_command(dev, cmd);
250  		if (error)
251  			return error;
252  
253  		error = read_bytes(dev, (u32 *)data->dest, (u32)data->blocks,
254  				   (u32)data->blocksize);
255  	} else if (data->flags & MMC_DATA_WRITE) {
256  		error = do_command(dev, cmd);
257  		if (error)
258  			return error;
259  
260  		writel(data_ctrl, &host->base->datactrl);
261  		error = write_bytes(dev, (u32 *)data->src, (u32)data->blocks,
262  							(u32)data->blocksize);
263  	}
264  
265  	return error;
266  }
267  
host_request(struct mmc * dev,struct mmc_cmd * cmd,struct mmc_data * data)268  static int host_request(struct mmc *dev,
269  			struct mmc_cmd *cmd,
270  			struct mmc_data *data)
271  {
272  	int result;
273  
274  	if (data)
275  		result = do_data_transfer(dev, cmd, data);
276  	else
277  		result = do_command(dev, cmd);
278  
279  	return result;
280  }
281  
host_set_ios(struct mmc * dev)282  static int  host_set_ios(struct mmc *dev)
283  {
284  	struct pl180_mmc_host *host = dev->priv;
285  	u32 sdi_clkcr;
286  
287  	sdi_clkcr = readl(&host->base->clock);
288  
289  	/* Ramp up the clock rate */
290  	if (dev->clock) {
291  		u32 clkdiv = 0;
292  		u32 tmp_clock;
293  
294  		if (dev->clock >= dev->cfg->f_max) {
295  			clkdiv = 0;
296  			dev->clock = dev->cfg->f_max;
297  		} else {
298  			clkdiv = (host->clock_in / dev->clock) - 2;
299  		}
300  
301  		tmp_clock = host->clock_in / (clkdiv + 2);
302  		while (tmp_clock > dev->clock) {
303  			clkdiv++;
304  			tmp_clock = host->clock_in / (clkdiv + 2);
305  		}
306  
307  		if (clkdiv > SDI_CLKCR_CLKDIV_MASK)
308  			clkdiv = SDI_CLKCR_CLKDIV_MASK;
309  
310  		tmp_clock = host->clock_in / (clkdiv + 2);
311  		dev->clock = tmp_clock;
312  		sdi_clkcr &= ~(SDI_CLKCR_CLKDIV_MASK);
313  		sdi_clkcr |= clkdiv;
314  	}
315  
316  	/* Set the bus width */
317  	if (dev->bus_width) {
318  		u32 buswidth = 0;
319  
320  		switch (dev->bus_width) {
321  		case 1:
322  			buswidth |= SDI_CLKCR_WIDBUS_1;
323  			break;
324  		case 4:
325  			buswidth |= SDI_CLKCR_WIDBUS_4;
326  			break;
327  		case 8:
328  			buswidth |= SDI_CLKCR_WIDBUS_8;
329  			break;
330  		default:
331  			printf("Invalid bus width: %d\n", dev->bus_width);
332  			break;
333  		}
334  		sdi_clkcr &= ~(SDI_CLKCR_WIDBUS_MASK);
335  		sdi_clkcr |= buswidth;
336  	}
337  
338  	writel(sdi_clkcr, &host->base->clock);
339  	udelay(CLK_CHANGE_DELAY);
340  
341  	return 0;
342  }
343  
344  #ifndef CONFIG_DM_MMC
345  /* MMC uses open drain drivers in the enumeration phase */
mmc_host_reset(struct mmc * dev)346  static int mmc_host_reset(struct mmc *dev)
347  {
348  	struct pl180_mmc_host *host = dev->priv;
349  
350  	writel(host->pwr_init, &host->base->power);
351  
352  	return 0;
353  }
354  
355  static const struct mmc_ops arm_pl180_mmci_ops = {
356  	.send_cmd = host_request,
357  	.set_ios = host_set_ios,
358  	.init = mmc_host_reset,
359  };
360  
361  /*
362   * mmc_host_init - initialize the mmc controller.
363   * Set initial clock and power for mmc slot.
364   * Initialize mmc struct and register with mmc framework.
365   */
366  
arm_pl180_mmci_init(struct pl180_mmc_host * host,struct mmc ** mmc)367  int arm_pl180_mmci_init(struct pl180_mmc_host *host, struct mmc **mmc)
368  {
369  	u32 sdi_u32;
370  
371  	writel(host->pwr_init, &host->base->power);
372  	writel(host->clkdiv_init, &host->base->clock);
373  	udelay(CLK_CHANGE_DELAY);
374  
375  	/* Disable mmc interrupts */
376  	sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK;
377  	writel(sdi_u32, &host->base->mask0);
378  
379  	host->cfg.name = host->name;
380  	host->cfg.ops = &arm_pl180_mmci_ops;
381  
382  	/* TODO remove the duplicates */
383  	host->cfg.host_caps = host->caps;
384  	host->cfg.voltages = host->voltages;
385  	host->cfg.f_min = host->clock_min;
386  	host->cfg.f_max = host->clock_max;
387  	if (host->b_max != 0)
388  		host->cfg.b_max = host->b_max;
389  	else
390  		host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
391  
392  	*mmc = mmc_create(&host->cfg, host);
393  	if (!*mmc)
394  		return -1;
395  	debug("registered mmc interface number is:%d\n",
396  	      (*mmc)->block_dev.devnum);
397  
398  	return 0;
399  }
400  #endif
401  
402  #ifdef CONFIG_DM_MMC
arm_pl180_mmc_init(struct pl180_mmc_host * host)403  static void arm_pl180_mmc_init(struct pl180_mmc_host *host)
404  {
405  	u32 sdi_u32;
406  
407  	writel(host->pwr_init, &host->base->power);
408  	writel(host->clkdiv_init, &host->base->clock);
409  	udelay(CLK_CHANGE_DELAY);
410  
411  	/* Disable mmc interrupts */
412  	sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK;
413  	writel(sdi_u32, &host->base->mask0);
414  }
415  
arm_pl180_mmc_probe(struct udevice * dev)416  static int arm_pl180_mmc_probe(struct udevice *dev)
417  {
418  	struct arm_pl180_mmc_plat *pdata = dev_get_platdata(dev);
419  	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
420  	struct mmc *mmc = &pdata->mmc;
421  	struct pl180_mmc_host *host = dev->priv;
422  	struct mmc_config *cfg = &pdata->cfg;
423  	struct clk clk;
424  	u32 bus_width;
425  	int ret;
426  
427  	ret = clk_get_by_index(dev, 0, &clk);
428  	if (ret < 0)
429  		return ret;
430  
431  	ret = clk_enable(&clk);
432  	if (ret) {
433  		clk_free(&clk);
434  		dev_err(dev, "failed to enable clock\n");
435  		return ret;
436  	}
437  
438  	host->pwr_init = INIT_PWR;
439  	host->clkdiv_init = SDI_CLKCR_CLKDIV_INIT_V1 | SDI_CLKCR_CLKEN |
440  			    SDI_CLKCR_HWFC_EN;
441  	host->clock_in = clk_get_rate(&clk);
442  	host->version2 = dev_get_driver_data(dev);
443  
444  	cfg->name = dev->name;
445  	cfg->voltages = VOLTAGE_WINDOW_SD;
446  	cfg->host_caps = 0;
447  	cfg->f_min = host->clock_in / (2 * (SDI_CLKCR_CLKDIV_INIT_V1 + 1));
448  	cfg->f_max = dev_read_u32_default(dev, "max-frequency", MMC_CLOCK_MAX);
449  	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
450  
451  	gpio_request_by_name(dev, "cd-gpios", 0, &host->cd_gpio, GPIOD_IS_IN);
452  
453  	bus_width = dev_read_u32_default(dev, "bus-width", 1);
454  	switch (bus_width) {
455  	case 8:
456  		cfg->host_caps |= MMC_MODE_8BIT;
457  		/* Hosts capable of 8-bit transfers can also do 4 bits */
458  	case 4:
459  		cfg->host_caps |= MMC_MODE_4BIT;
460  		break;
461  	case 1:
462  		break;
463  	default:
464  		dev_err(dev, "Invalid bus-width value %u\n", bus_width);
465  	}
466  
467  	arm_pl180_mmc_init(host);
468  	mmc->priv = host;
469  	mmc->dev = dev;
470  	upriv->mmc = mmc;
471  
472  	return 0;
473  }
474  
arm_pl180_mmc_bind(struct udevice * dev)475  int arm_pl180_mmc_bind(struct udevice *dev)
476  {
477  	struct arm_pl180_mmc_plat *plat = dev_get_platdata(dev);
478  
479  	return mmc_bind(dev, &plat->mmc, &plat->cfg);
480  }
481  
dm_host_request(struct udevice * dev,struct mmc_cmd * cmd,struct mmc_data * data)482  static int dm_host_request(struct udevice *dev, struct mmc_cmd *cmd,
483  			   struct mmc_data *data)
484  {
485  	struct mmc *mmc = mmc_get_mmc_dev(dev);
486  
487  	return host_request(mmc, cmd, data);
488  }
489  
dm_host_set_ios(struct udevice * dev)490  static int dm_host_set_ios(struct udevice *dev)
491  {
492  	struct mmc *mmc = mmc_get_mmc_dev(dev);
493  
494  	return host_set_ios(mmc);
495  }
496  
dm_mmc_getcd(struct udevice * dev)497  static int dm_mmc_getcd(struct udevice *dev)
498  {
499  	struct pl180_mmc_host *host = dev->priv;
500  	int value = 1;
501  
502  	if (dm_gpio_is_valid(&host->cd_gpio))
503  		value = dm_gpio_get_value(&host->cd_gpio);
504  
505  	return value;
506  }
507  
508  static const struct dm_mmc_ops arm_pl180_dm_mmc_ops = {
509  	.send_cmd = dm_host_request,
510  	.set_ios = dm_host_set_ios,
511  	.get_cd = dm_mmc_getcd,
512  };
513  
arm_pl180_mmc_ofdata_to_platdata(struct udevice * dev)514  static int arm_pl180_mmc_ofdata_to_platdata(struct udevice *dev)
515  {
516  	struct pl180_mmc_host *host = dev->priv;
517  	fdt_addr_t addr;
518  
519  	addr = dev_read_addr(dev);
520  	if (addr == FDT_ADDR_T_NONE)
521  		return -EINVAL;
522  
523  	host->base = (void *)addr;
524  
525  	return 0;
526  }
527  
528  static const struct udevice_id arm_pl180_mmc_match[] = {
529  	{ .compatible = "st,stm32f4xx-sdio", .data = VERSION1 },
530  	{ /* sentinel */ }
531  };
532  
533  U_BOOT_DRIVER(arm_pl180_mmc) = {
534  	.name = "arm_pl180_mmc",
535  	.id = UCLASS_MMC,
536  	.of_match = arm_pl180_mmc_match,
537  	.ops = &arm_pl180_dm_mmc_ops,
538  	.probe = arm_pl180_mmc_probe,
539  	.ofdata_to_platdata = arm_pl180_mmc_ofdata_to_platdata,
540  	.bind = arm_pl180_mmc_bind,
541  	.priv_auto_alloc_size = sizeof(struct pl180_mmc_host),
542  	.platdata_auto_alloc_size = sizeof(struct arm_pl180_mmc_plat),
543  };
544  #endif
545