xref: /rk3399_rockchip-uboot/drivers/mmc/ftsdc010_mci.c (revision dbb713baa608d3397e56bc32b26d2efe07c756ee)
1 /*
2  * Faraday MMC/SD Host Controller
3  *
4  * (C) Copyright 2010 Faraday Technology
5  * Dante Su <dantesu@faraday-tech.com>
6  *
7  * This file is released under the terms of GPL v2 and any later version.
8  * See the file COPYING in the root directory of the source tree for details.
9  */
10 
11 #include <common.h>
12 #include <malloc.h>
13 #include <part.h>
14 #include <mmc.h>
15 
16 #include <asm/io.h>
17 #include <asm/errno.h>
18 #include <asm/byteorder.h>
19 #include <faraday/ftsdc010.h>
20 
21 #define CFG_CMD_TIMEOUT (CONFIG_SYS_HZ >> 4) /* 250 ms */
22 #define CFG_RST_TIMEOUT CONFIG_SYS_HZ /* 1 sec reset timeout */
23 
24 struct ftsdc010_chip {
25 	void __iomem *regs;
26 	uint32_t wprot;   /* write protected (locked) */
27 	uint32_t rate;    /* actual SD clock in Hz */
28 	uint32_t sclk;    /* FTSDC010 source clock in Hz */
29 	uint32_t fifo;    /* fifo depth in bytes */
30 	uint32_t acmd;
31 };
32 
33 static inline int ftsdc010_send_cmd(struct mmc *mmc, struct mmc_cmd *mmc_cmd)
34 {
35 	struct ftsdc010_chip *chip = mmc->priv;
36 	struct ftsdc010_mmc __iomem *regs = chip->regs;
37 	int ret = TIMEOUT;
38 	uint32_t ts, st;
39 	uint32_t cmd   = FTSDC010_CMD_IDX(mmc_cmd->cmdidx);
40 	uint32_t arg   = mmc_cmd->cmdarg;
41 	uint32_t flags = mmc_cmd->resp_type;
42 
43 	cmd |= FTSDC010_CMD_CMD_EN;
44 
45 	if (chip->acmd) {
46 		cmd |= FTSDC010_CMD_APP_CMD;
47 		chip->acmd = 0;
48 	}
49 
50 	if (flags & MMC_RSP_PRESENT)
51 		cmd |= FTSDC010_CMD_NEED_RSP;
52 
53 	if (flags & MMC_RSP_136)
54 		cmd |= FTSDC010_CMD_LONG_RSP;
55 
56 	writel(FTSDC010_STATUS_RSP_MASK | FTSDC010_STATUS_CMD_SEND,
57 		&regs->clr);
58 	writel(arg, &regs->argu);
59 	writel(cmd, &regs->cmd);
60 
61 	if (!(flags & (MMC_RSP_PRESENT | MMC_RSP_136))) {
62 		for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) {
63 			if (readl(&regs->status) & FTSDC010_STATUS_CMD_SEND) {
64 				writel(FTSDC010_STATUS_CMD_SEND, &regs->clr);
65 				ret = 0;
66 				break;
67 			}
68 		}
69 	} else {
70 		st = 0;
71 		for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) {
72 			st = readl(&regs->status);
73 			writel(st & FTSDC010_STATUS_RSP_MASK, &regs->clr);
74 			if (st & FTSDC010_STATUS_RSP_MASK)
75 				break;
76 		}
77 		if (st & FTSDC010_STATUS_RSP_CRC_OK) {
78 			if (flags & MMC_RSP_136) {
79 				mmc_cmd->response[0] = readl(&regs->rsp3);
80 				mmc_cmd->response[1] = readl(&regs->rsp2);
81 				mmc_cmd->response[2] = readl(&regs->rsp1);
82 				mmc_cmd->response[3] = readl(&regs->rsp0);
83 			} else {
84 				mmc_cmd->response[0] = readl(&regs->rsp0);
85 			}
86 			ret = 0;
87 		} else {
88 			debug("ftsdc010: rsp err (cmd=%d, st=0x%x)\n",
89 				mmc_cmd->cmdidx, st);
90 		}
91 	}
92 
93 	if (ret) {
94 		debug("ftsdc010: cmd timeout (op code=%d)\n",
95 			mmc_cmd->cmdidx);
96 	} else if (mmc_cmd->cmdidx == MMC_CMD_APP_CMD) {
97 		chip->acmd = 1;
98 	}
99 
100 	return ret;
101 }
102 
103 static void ftsdc010_clkset(struct mmc *mmc, uint32_t rate)
104 {
105 	struct ftsdc010_chip *chip = mmc->priv;
106 	struct ftsdc010_mmc __iomem *regs = chip->regs;
107 	uint32_t div;
108 
109 	for (div = 0; div < 0x7f; ++div) {
110 		if (rate >= chip->sclk / (2 * (div + 1)))
111 			break;
112 	}
113 	chip->rate = chip->sclk / (2 * (div + 1));
114 
115 	writel(FTSDC010_CCR_CLK_DIV(div), &regs->ccr);
116 
117 	if (IS_SD(mmc)) {
118 		setbits_le32(&regs->ccr, FTSDC010_CCR_CLK_SD);
119 
120 		if (chip->rate > 25000000)
121 			setbits_le32(&regs->ccr, FTSDC010_CCR_CLK_HISPD);
122 		else
123 			clrbits_le32(&regs->ccr, FTSDC010_CCR_CLK_HISPD);
124 	}
125 }
126 
127 static inline int ftsdc010_is_ro(struct mmc *mmc)
128 {
129 	struct ftsdc010_chip *chip = mmc->priv;
130 	const uint8_t *csd = (const uint8_t *)mmc->csd;
131 
132 	return chip->wprot || (csd[1] & 0x30);
133 }
134 
135 static int ftsdc010_wait(struct ftsdc010_mmc __iomem *regs, uint32_t mask)
136 {
137 	int ret = TIMEOUT;
138 	uint32_t st, ts;
139 
140 	for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) {
141 		st = readl(&regs->status);
142 		if (!(st & mask))
143 			continue;
144 		writel(st & mask, &regs->clr);
145 		ret = 0;
146 		break;
147 	}
148 
149 	if (ret)
150 		debug("ftsdc010: wait st(0x%x) timeout\n", mask);
151 
152 	return ret;
153 }
154 
155 /*
156  * u-boot mmc api
157  */
158 
159 static int ftsdc010_request(struct mmc *mmc, struct mmc_cmd *cmd,
160 	struct mmc_data *data)
161 {
162 	int ret = UNUSABLE_ERR;
163 	uint32_t len = 0;
164 	struct ftsdc010_chip *chip = mmc->priv;
165 	struct ftsdc010_mmc __iomem *regs = chip->regs;
166 
167 	if (data && (data->flags & MMC_DATA_WRITE) && chip->wprot) {
168 		printf("ftsdc010: the card is write protected!\n");
169 		return ret;
170 	}
171 
172 	if (data) {
173 		uint32_t dcr;
174 
175 		len = data->blocksize * data->blocks;
176 
177 		/* 1. data disable + fifo reset */
178 		dcr = 0;
179 #ifdef CONFIG_FTSDC010_SDIO
180 		dcr |= FTSDC010_DCR_FIFO_RST;
181 #endif
182 		writel(dcr, &regs->dcr);
183 
184 		/* 2. clear status register */
185 		writel(FTSDC010_STATUS_DATA_MASK | FTSDC010_STATUS_FIFO_URUN
186 			| FTSDC010_STATUS_FIFO_ORUN, &regs->clr);
187 
188 		/* 3. data timeout (1 sec) */
189 		writel(chip->rate, &regs->dtr);
190 
191 		/* 4. data length (bytes) */
192 		writel(len, &regs->dlr);
193 
194 		/* 5. data enable */
195 		dcr = (ffs(data->blocksize) - 1) | FTSDC010_DCR_DATA_EN;
196 		if (data->flags & MMC_DATA_WRITE)
197 			dcr |= FTSDC010_DCR_DATA_WRITE;
198 		writel(dcr, &regs->dcr);
199 	}
200 
201 	ret = ftsdc010_send_cmd(mmc, cmd);
202 	if (ret) {
203 		printf("ftsdc010: CMD%d failed\n", cmd->cmdidx);
204 		return ret;
205 	}
206 
207 	if (!data)
208 		return ret;
209 
210 	if (data->flags & MMC_DATA_WRITE) {
211 		const uint8_t *buf = (const uint8_t *)data->src;
212 
213 		while (len > 0) {
214 			int wlen;
215 
216 			/* wait for tx ready */
217 			ret = ftsdc010_wait(regs, FTSDC010_STATUS_FIFO_URUN);
218 			if (ret)
219 				break;
220 
221 			/* write bytes to ftsdc010 */
222 			for (wlen = 0; wlen < len && wlen < chip->fifo; ) {
223 				writel(*(uint32_t *)buf, &regs->dwr);
224 				buf  += 4;
225 				wlen += 4;
226 			}
227 
228 			len -= wlen;
229 		}
230 
231 	} else {
232 		uint8_t *buf = (uint8_t *)data->dest;
233 
234 		while (len > 0) {
235 			int rlen;
236 
237 			/* wait for rx ready */
238 			ret = ftsdc010_wait(regs, FTSDC010_STATUS_FIFO_ORUN);
239 			if (ret)
240 				break;
241 
242 			/* fetch bytes from ftsdc010 */
243 			for (rlen = 0; rlen < len && rlen < chip->fifo; ) {
244 				*(uint32_t *)buf = readl(&regs->dwr);
245 				buf  += 4;
246 				rlen += 4;
247 			}
248 
249 			len -= rlen;
250 		}
251 
252 	}
253 
254 	if (!ret) {
255 		ret = ftsdc010_wait(regs,
256 			FTSDC010_STATUS_DATA_END | FTSDC010_STATUS_DATA_ERROR);
257 	}
258 
259 	return ret;
260 }
261 
262 static void ftsdc010_set_ios(struct mmc *mmc)
263 {
264 	struct ftsdc010_chip *chip = mmc->priv;
265 	struct ftsdc010_mmc __iomem *regs = chip->regs;
266 
267 	ftsdc010_clkset(mmc, mmc->clock);
268 
269 	clrbits_le32(&regs->bwr, FTSDC010_BWR_MODE_MASK);
270 	switch (mmc->bus_width) {
271 	case 4:
272 		setbits_le32(&regs->bwr, FTSDC010_BWR_MODE_4BIT);
273 		break;
274 	case 8:
275 		setbits_le32(&regs->bwr, FTSDC010_BWR_MODE_8BIT);
276 		break;
277 	default:
278 		setbits_le32(&regs->bwr, FTSDC010_BWR_MODE_1BIT);
279 		break;
280 	}
281 }
282 
283 static int ftsdc010_init(struct mmc *mmc)
284 {
285 	struct ftsdc010_chip *chip = mmc->priv;
286 	struct ftsdc010_mmc __iomem *regs = chip->regs;
287 	uint32_t ts;
288 
289 	if (readl(&regs->status) & FTSDC010_STATUS_CARD_DETECT)
290 		return NO_CARD_ERR;
291 
292 	if (readl(&regs->status) & FTSDC010_STATUS_WRITE_PROT) {
293 		printf("ftsdc010: write protected\n");
294 		chip->wprot = 1;
295 	}
296 
297 	chip->fifo = (readl(&regs->feature) & 0xff) << 2;
298 
299 	/* 1. chip reset */
300 	writel(FTSDC010_CMD_SDC_RST, &regs->cmd);
301 	for (ts = get_timer(0); get_timer(ts) < CFG_RST_TIMEOUT; ) {
302 		if (readl(&regs->cmd) & FTSDC010_CMD_SDC_RST)
303 			continue;
304 		break;
305 	}
306 	if (readl(&regs->cmd) & FTSDC010_CMD_SDC_RST) {
307 		printf("ftsdc010: reset failed\n");
308 		return UNUSABLE_ERR;
309 	}
310 
311 	/* 2. enter low speed mode (400k card detection) */
312 	ftsdc010_clkset(mmc, 400000);
313 
314 	/* 3. interrupt disabled */
315 	writel(0, &regs->int_mask);
316 
317 	return 0;
318 }
319 
320 int ftsdc010_mmc_init(int devid)
321 {
322 	struct mmc *mmc;
323 	struct ftsdc010_chip *chip;
324 	struct ftsdc010_mmc __iomem *regs;
325 #ifdef CONFIG_FTSDC010_BASE_LIST
326 	uint32_t base_list[] = CONFIG_FTSDC010_BASE_LIST;
327 
328 	if (devid < 0 || devid >= ARRAY_SIZE(base_list))
329 		return -1;
330 	regs = (void __iomem *)base_list[devid];
331 #else
332 	regs = (void __iomem *)(CONFIG_FTSDC010_BASE + (devid << 20));
333 #endif
334 
335 	mmc = malloc(sizeof(struct mmc));
336 	if (!mmc)
337 		return -ENOMEM;
338 	memset(mmc, 0, sizeof(struct mmc));
339 
340 	chip = malloc(sizeof(struct ftsdc010_chip));
341 	if (!chip) {
342 		free(mmc);
343 		return -ENOMEM;
344 	}
345 	memset(chip, 0, sizeof(struct ftsdc010_chip));
346 
347 	chip->regs = regs;
348 	mmc->priv  = chip;
349 
350 	sprintf(mmc->name, "ftsdc010");
351 	mmc->send_cmd  = ftsdc010_request;
352 	mmc->set_ios   = ftsdc010_set_ios;
353 	mmc->init      = ftsdc010_init;
354 
355 	mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz;
356 	switch (readl(&regs->bwr) & FTSDC010_BWR_CAPS_MASK) {
357 	case FTSDC010_BWR_CAPS_4BIT:
358 		mmc->host_caps |= MMC_MODE_4BIT;
359 		break;
360 	case FTSDC010_BWR_CAPS_8BIT:
361 		mmc->host_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
362 		break;
363 	default:
364 		break;
365 	}
366 
367 #ifdef CONFIG_SYS_CLK_FREQ
368 	chip->sclk = CONFIG_SYS_CLK_FREQ;
369 #else
370 	chip->sclk = clk_get_rate("SDC");
371 #endif
372 
373 	mmc->voltages  = MMC_VDD_32_33 | MMC_VDD_33_34;
374 	mmc->f_max     = chip->sclk / 2;
375 	mmc->f_min     = chip->sclk / 0x100;
376 	mmc->block_dev.part_type = PART_TYPE_DOS;
377 
378 	mmc_register(mmc);
379 
380 	return 0;
381 }
382