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 <log.h>
18#include <malloc.h>
19#include <mmc.h>
20#include <dm/device_compat.h>
21#include <dm.h>
22
23#include <asm/io.h>
24#include <asm-generic/gpio.h>
25
26#include "arm_pl180_mmci.h"
27#include <linux/delay.h>
28
29#define MMC_CLOCK_MAX	48000000
30#define MMC_CLOCK_MIN	400000
31
32struct arm_pl180_mmc_plat {
33	struct mmc_config cfg;
34	struct mmc mmc;
35};
36
37static int wait_for_command_end(struct mmc *dev, struct mmc_cmd *cmd)
38{
39	u32 hoststatus, statusmask;
40	struct pl180_mmc_host *host = dev->priv;
41
42	statusmask = SDI_STA_CTIMEOUT | SDI_STA_CCRCFAIL;
43	if ((cmd->resp_type & MMC_RSP_PRESENT))
44		statusmask |= SDI_STA_CMDREND;
45	else
46		statusmask |= SDI_STA_CMDSENT;
47
48	do
49		hoststatus = readl(&host->base->status) & statusmask;
50	while (!hoststatus);
51
52	writel(statusmask, &host->base->status_clear);
53	if (hoststatus & SDI_STA_CTIMEOUT) {
54		debug("CMD%d time out\n", cmd->cmdidx);
55		return -ETIMEDOUT;
56	} else if ((hoststatus & SDI_STA_CCRCFAIL) &&
57		   (cmd->resp_type & MMC_RSP_CRC)) {
58		printf("CMD%d CRC error\n", cmd->cmdidx);
59		return -EILSEQ;
60	}
61
62	if (cmd->resp_type & MMC_RSP_PRESENT) {
63		cmd->response[0] = readl(&host->base->response0);
64		cmd->response[1] = readl(&host->base->response1);
65		cmd->response[2] = readl(&host->base->response2);
66		cmd->response[3] = readl(&host->base->response3);
67		debug("CMD%d response[0]:0x%08X, response[1]:0x%08X, "
68			"response[2]:0x%08X, response[3]:0x%08X\n",
69			cmd->cmdidx, cmd->response[0], cmd->response[1],
70			cmd->response[2], cmd->response[3]);
71	}
72
73	return 0;
74}
75
76/* send command to the mmc card and wait for results */
77static int do_command(struct mmc *dev, struct mmc_cmd *cmd)
78{
79	int result;
80	u32 sdi_cmd = 0;
81	struct pl180_mmc_host *host = dev->priv;
82
83	sdi_cmd = ((cmd->cmdidx & SDI_CMD_CMDINDEX_MASK) | SDI_CMD_CPSMEN);
84
85	if (cmd->resp_type) {
86		sdi_cmd |= SDI_CMD_WAITRESP;
87		if (cmd->resp_type & MMC_RSP_136)
88			sdi_cmd |= SDI_CMD_LONGRESP;
89	}
90
91	writel((u32)cmd->cmdarg, &host->base->argument);
92	udelay(COMMAND_REG_DELAY);
93	writel(sdi_cmd, &host->base->command);
94	result = wait_for_command_end(dev, cmd);
95
96	/* After CMD2 set RCA to a none zero value. */
97	if ((result == 0) && (cmd->cmdidx == MMC_CMD_ALL_SEND_CID))
98		dev->rca = 10;
99
100	/* After CMD3 open drain is switched off and push pull is used. */
101	if ((result == 0) && (cmd->cmdidx == MMC_CMD_SET_RELATIVE_ADDR)) {
102		u32 sdi_pwr = readl(&host->base->power) & ~SDI_PWR_OPD;
103		writel(sdi_pwr, &host->base->power);
104	}
105
106	return result;
107}
108
109static int read_bytes(struct mmc *dev, u32 *dest, u32 blkcount, u32 blksize)
110{
111	u32 *tempbuff = dest;
112	u64 xfercount = blkcount * blksize;
113	struct pl180_mmc_host *host = dev->priv;
114	u32 status, status_err;
115
116	debug("read_bytes: blkcount=%u blksize=%u\n", blkcount, blksize);
117
118	status = readl(&host->base->status);
119	status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT |
120			       SDI_STA_RXOVERR);
121	while ((!status_err) && (xfercount >= sizeof(u32))) {
122		if (status & SDI_STA_RXDAVL) {
123			*(tempbuff) = readl(&host->base->fifo);
124			tempbuff++;
125			xfercount -= sizeof(u32);
126		}
127		status = readl(&host->base->status);
128		status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT |
129				       SDI_STA_RXOVERR);
130	}
131
132	status_err = status &
133		(SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | SDI_STA_DBCKEND |
134		 SDI_STA_RXOVERR);
135	while (!status_err) {
136		status = readl(&host->base->status);
137		status_err = status &
138			(SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | SDI_STA_DBCKEND |
139			 SDI_STA_RXOVERR);
140	}
141
142	if (status & SDI_STA_DTIMEOUT) {
143		printf("Read data timed out, xfercount: %llu, status: 0x%08X\n",
144			xfercount, status);
145		return -ETIMEDOUT;
146	} else if (status & SDI_STA_DCRCFAIL) {
147		printf("Read data bytes CRC error: 0x%x\n", status);
148		return -EILSEQ;
149	} else if (status & SDI_STA_RXOVERR) {
150		printf("Read data RX overflow error\n");
151		return -EIO;
152	}
153
154	writel(SDI_ICR_MASK, &host->base->status_clear);
155
156	if (xfercount) {
157		printf("Read data error, xfercount: %llu\n", xfercount);
158		return -ENOBUFS;
159	}
160
161	return 0;
162}
163
164static int write_bytes(struct mmc *dev, u32 *src, u32 blkcount, u32 blksize)
165{
166	u32 *tempbuff = src;
167	int i;
168	u64 xfercount = blkcount * blksize;
169	struct pl180_mmc_host *host = dev->priv;
170	u32 status, status_err;
171
172	debug("write_bytes: blkcount=%u blksize=%u\n", blkcount, blksize);
173
174	status = readl(&host->base->status);
175	status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT);
176	while (!status_err && xfercount) {
177		if (status & SDI_STA_TXFIFOBW) {
178			if (xfercount >= SDI_FIFO_BURST_SIZE * sizeof(u32)) {
179				for (i = 0; i < SDI_FIFO_BURST_SIZE; i++)
180					writel(*(tempbuff + i),
181						&host->base->fifo);
182				tempbuff += SDI_FIFO_BURST_SIZE;
183				xfercount -= SDI_FIFO_BURST_SIZE * sizeof(u32);
184			} else {
185				while (xfercount >= sizeof(u32)) {
186					writel(*(tempbuff), &host->base->fifo);
187					tempbuff++;
188					xfercount -= sizeof(u32);
189				}
190			}
191		}
192		status = readl(&host->base->status);
193		status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT);
194	}
195
196	status_err = status &
197		(SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | SDI_STA_DBCKEND);
198	while (!status_err) {
199		status = readl(&host->base->status);
200		status_err = status &
201			(SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | SDI_STA_DBCKEND);
202	}
203
204	if (status & SDI_STA_DTIMEOUT) {
205		printf("Write data timed out, xfercount:%llu,status:0x%08X\n",
206		       xfercount, status);
207		return -ETIMEDOUT;
208	} else if (status & SDI_STA_DCRCFAIL) {
209		printf("Write data CRC error\n");
210		return -EILSEQ;
211	}
212
213	writel(SDI_ICR_MASK, &host->base->status_clear);
214
215	if (xfercount) {
216		printf("Write data error, xfercount:%llu", xfercount);
217		return -ENOBUFS;
218	}
219
220	return 0;
221}
222
223static int do_data_transfer(struct mmc *dev,
224			    struct mmc_cmd *cmd,
225			    struct mmc_data *data)
226{
227	int error = -ETIMEDOUT;
228	struct pl180_mmc_host *host = dev->priv;
229	u32 blksz = 0;
230	u32 data_ctrl = 0;
231	u32 data_len = (u32) (data->blocks * data->blocksize);
232	assert(data_len < U16_MAX); /* should be ensured by arm_pl180_get_b_max */
233
234	if (!host->version2) {
235		blksz = (ffs(data->blocksize) - 1);
236		data_ctrl |= ((blksz << 4) & SDI_DCTRL_DBLKSIZE_MASK);
237	} else {
238		blksz = data->blocksize;
239		data_ctrl |= (blksz << SDI_DCTRL_DBLOCKSIZE_V2_SHIFT);
240	}
241	data_ctrl |= SDI_DCTRL_DTEN | SDI_DCTRL_BUSYMODE;
242
243	writel(SDI_DTIMER_DEFAULT, &host->base->datatimer);
244	writel(data_len, &host->base->datalength);
245	udelay(DATA_REG_DELAY);
246
247	if (data->flags & MMC_DATA_READ) {
248		data_ctrl |= SDI_DCTRL_DTDIR_IN;
249		writel(data_ctrl, &host->base->datactrl);
250
251		error = do_command(dev, cmd);
252		if (error)
253			return error;
254
255		error = read_bytes(dev, (u32 *)data->dest, (u32)data->blocks,
256				   (u32)data->blocksize);
257	} else if (data->flags & MMC_DATA_WRITE) {
258		error = do_command(dev, cmd);
259		if (error)
260			return error;
261
262		writel(data_ctrl, &host->base->datactrl);
263		error = write_bytes(dev, (u32 *)data->src, (u32)data->blocks,
264							(u32)data->blocksize);
265	}
266
267	return error;
268}
269
270static int host_request(struct mmc *dev,
271			struct mmc_cmd *cmd,
272			struct mmc_data *data)
273{
274	int result;
275
276	if (data)
277		result = do_data_transfer(dev, cmd, data);
278	else
279		result = do_command(dev, cmd);
280
281	return result;
282}
283
284static int check_peripheral_id(struct pl180_mmc_host *host, u32 periph_id)
285{
286	return readl(&host->base->periph_id0) == (periph_id & 0xFF) &&
287		readl(&host->base->periph_id1) == ((periph_id >> 8) & 0xFF)  &&
288		readl(&host->base->periph_id2) == ((periph_id >> 16) & 0xFF) &&
289		readl(&host->base->periph_id3) == ((periph_id >> 24) & 0xFF);
290}
291
292static int  host_set_ios(struct mmc *dev)
293{
294	struct pl180_mmc_host *host = dev->priv;
295	u32 sdi_clkcr;
296
297	sdi_clkcr = readl(&host->base->clock);
298
299	/* Ramp up the clock rate */
300	if (dev->clock) {
301		u32 clkdiv = 0;
302		u32 tmp_clock;
303
304		if (dev->clock >= dev->cfg->f_max) {
305			clkdiv = 0;
306			dev->clock = dev->cfg->f_max;
307		} else {
308			clkdiv = (host->clock_in / dev->clock) - 2;
309		}
310
311		tmp_clock = host->clock_in / (clkdiv + 2);
312		while (tmp_clock > dev->clock) {
313			clkdiv++;
314			tmp_clock = host->clock_in / (clkdiv + 2);
315		}
316
317		if (clkdiv > SDI_CLKCR_CLKDIV_MASK)
318			clkdiv = SDI_CLKCR_CLKDIV_MASK;
319
320		tmp_clock = host->clock_in / (clkdiv + 2);
321		dev->clock = tmp_clock;
322		sdi_clkcr &= ~(SDI_CLKCR_CLKDIV_MASK);
323		sdi_clkcr |= clkdiv;
324	}
325
326	/* Set the bus width */
327	if (dev->bus_width) {
328		u32 buswidth = 0;
329
330		switch (dev->bus_width) {
331		case 1:
332			buswidth |= SDI_CLKCR_WIDBUS_1;
333			break;
334		case 4:
335			buswidth |= SDI_CLKCR_WIDBUS_4;
336			break;
337		case 8:
338			buswidth |= SDI_CLKCR_WIDBUS_8;
339			break;
340		default:
341			printf("Invalid bus width: %d\n", dev->bus_width);
342			break;
343		}
344		sdi_clkcr &= ~(SDI_CLKCR_WIDBUS_MASK);
345		sdi_clkcr |= buswidth;
346	}
347	/* For MMCs' with peripheral id 0x02041180 and 0x03041180, H/W flow control
348	 * needs to be enabled for multi block writes (MMC CMD 18).
349	 */
350	if (check_peripheral_id(host, 0x02041180) ||
351		check_peripheral_id(host, 0x03041180))
352		sdi_clkcr |= SDI_CLKCR_HWFCEN;
353
354	writel(sdi_clkcr, &host->base->clock);
355	udelay(CLK_CHANGE_DELAY);
356
357	return 0;
358}
359
360static int arm_pl180_get_b_max(struct udevice *dev, void *dst, lbaint_t blkcnt)
361{
362	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
363	struct mmc *mmc = upriv->mmc;
364
365	return U16_MAX / mmc->read_bl_len;
366}
367
368static void arm_pl180_mmc_init(struct pl180_mmc_host *host)
369{
370	u32 sdi_u32;
371
372	writel(host->pwr_init, &host->base->power);
373	writel(host->clkdiv_init, &host->base->clock);
374	udelay(CLK_CHANGE_DELAY);
375
376	/* Disable mmc interrupts */
377	sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK;
378	writel(sdi_u32, &host->base->mask0);
379}
380
381static int arm_pl180_mmc_probe(struct udevice *dev)
382{
383	struct arm_pl180_mmc_plat *pdata = dev_get_plat(dev);
384	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
385	struct mmc *mmc = &pdata->mmc;
386	struct pl180_mmc_host *host = dev_get_priv(dev);
387	struct mmc_config *cfg = &pdata->cfg;
388	struct clk clk;
389	u32 periphid;
390	int ret;
391
392	ret = clk_get_by_index(dev, 0, &clk);
393	if (ret < 0)
394		return ret;
395
396	ret = clk_enable(&clk);
397	if (ret) {
398		dev_err(dev, "failed to enable clock\n");
399		return ret;
400	}
401
402	host->pwr_init = INIT_PWR;
403	host->clkdiv_init = SDI_CLKCR_CLKDIV_INIT_V1 | SDI_CLKCR_CLKEN |
404			    SDI_CLKCR_HWFC_EN;
405	host->clock_in = clk_get_rate(&clk);
406
407	cfg->name = dev->name;
408	cfg->voltages = VOLTAGE_WINDOW_SD;
409	cfg->host_caps = 0;
410	cfg->f_min = host->clock_in / (2 * (SDI_CLKCR_CLKDIV_INIT_V1 + 1));
411	cfg->f_max = MMC_CLOCK_MAX;
412	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
413
414	periphid = dev_read_u32_default(dev, "arm,primecell-periphid", 0);
415	switch (periphid) {
416	case STM32_MMCI_ID: /* stm32 variant */
417		host->version2 = false;
418		break;
419	case UX500V2_MMCI_ID:
420		host->pwr_init = SDI_PWR_OPD | SDI_PWR_PWRCTRL_ON;
421		host->clkdiv_init = SDI_CLKCR_CLKDIV_INIT_V2 | SDI_CLKCR_CLKEN |
422				    SDI_CLKCR_HWFC_EN;
423		cfg->voltages = VOLTAGE_WINDOW_MMC;
424		cfg->f_min = host->clock_in / (2 + SDI_CLKCR_CLKDIV_INIT_V2);
425		host->version2 = true;
426		break;
427	default:
428		host->version2 = false; /* ARM variant */
429	}
430
431	gpio_request_by_name(dev, "cd-gpios", 0, &host->cd_gpio, GPIOD_IS_IN);
432
433	ret = mmc_of_parse(dev, cfg);
434	if (ret)
435		return ret;
436
437	arm_pl180_mmc_init(host);
438	mmc->priv = host;
439	mmc->dev = dev;
440	upriv->mmc = mmc;
441
442	return 0;
443}
444
445int arm_pl180_mmc_bind(struct udevice *dev)
446{
447	struct arm_pl180_mmc_plat *plat = dev_get_plat(dev);
448
449	return mmc_bind(dev, &plat->mmc, &plat->cfg);
450}
451
452static int dm_host_request(struct udevice *dev, struct mmc_cmd *cmd,
453			   struct mmc_data *data)
454{
455	struct mmc *mmc = mmc_get_mmc_dev(dev);
456
457	return host_request(mmc, cmd, data);
458}
459
460static int dm_host_set_ios(struct udevice *dev)
461{
462	struct mmc *mmc = mmc_get_mmc_dev(dev);
463
464	return host_set_ios(mmc);
465}
466
467static int dm_mmc_getcd(struct udevice *dev)
468{
469	struct pl180_mmc_host *host = dev_get_priv(dev);
470	int value = 1;
471
472	if (dm_gpio_is_valid(&host->cd_gpio))
473		value = dm_gpio_get_value(&host->cd_gpio);
474
475	return value;
476}
477
478static const struct dm_mmc_ops arm_pl180_dm_mmc_ops = {
479	.send_cmd = dm_host_request,
480	.set_ios = dm_host_set_ios,
481	.get_cd = dm_mmc_getcd,
482	.get_b_max = arm_pl180_get_b_max,
483};
484
485static int arm_pl180_mmc_of_to_plat(struct udevice *dev)
486{
487	struct pl180_mmc_host *host = dev_get_priv(dev);
488
489	host->base = dev_read_addr_ptr(dev);
490	if (!host->base)
491		return -EINVAL;
492
493	return 0;
494}
495
496static const struct udevice_id arm_pl180_mmc_match[] = {
497	{ .compatible = "arm,pl180" },
498	{ .compatible = "arm,pl18x" },
499	{ /* sentinel */ }
500};
501
502U_BOOT_DRIVER(arm_pl180_mmc) = {
503	.name = "arm_pl180_mmc",
504	.id = UCLASS_MMC,
505	.of_match = arm_pl180_mmc_match,
506	.ops = &arm_pl180_dm_mmc_ops,
507	.probe = arm_pl180_mmc_probe,
508	.of_to_plat = arm_pl180_mmc_of_to_plat,
509	.bind = arm_pl180_mmc_bind,
510	.priv_auto	= sizeof(struct pl180_mmc_host),
511	.plat_auto	= sizeof(struct arm_pl180_mmc_plat),
512};
513