xref: /openbmc/u-boot/drivers/mmc/ftsdc010_mci.c (revision d5cc3f52)
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 		writel(FTSDC010_DCR_FIFO_RST, &regs->dcr);
179 
180 		/* 2. clear status register */
181 		writel(FTSDC010_STATUS_DATA_MASK | FTSDC010_STATUS_FIFO_URUN
182 			| FTSDC010_STATUS_FIFO_ORUN, &regs->clr);
183 
184 		/* 3. data timeout (1 sec) */
185 		writel(chip->rate, &regs->dtr);
186 
187 		/* 4. data length (bytes) */
188 		writel(len, &regs->dlr);
189 
190 		/* 5. data enable */
191 		dcr = (ffs(data->blocksize) - 1) | FTSDC010_DCR_DATA_EN;
192 		if (data->flags & MMC_DATA_WRITE)
193 			dcr |= FTSDC010_DCR_DATA_WRITE;
194 		writel(dcr, &regs->dcr);
195 	}
196 
197 	ret = ftsdc010_send_cmd(mmc, cmd);
198 	if (ret) {
199 		printf("ftsdc010: CMD%d failed\n", cmd->cmdidx);
200 		return ret;
201 	}
202 
203 	if (!data)
204 		return ret;
205 
206 	if (data->flags & MMC_DATA_WRITE) {
207 		const uint8_t *buf = (const uint8_t *)data->src;
208 
209 		while (len > 0) {
210 			int wlen;
211 
212 			/* wait for tx ready */
213 			ret = ftsdc010_wait(regs, FTSDC010_STATUS_FIFO_URUN);
214 			if (ret)
215 				break;
216 
217 			/* write bytes to ftsdc010 */
218 			for (wlen = 0; wlen < len && wlen < chip->fifo; ) {
219 				writel(*(uint32_t *)buf, &regs->dwr);
220 				buf  += 4;
221 				wlen += 4;
222 			}
223 
224 			len -= wlen;
225 		}
226 
227 	} else {
228 		uint8_t *buf = (uint8_t *)data->dest;
229 
230 		while (len > 0) {
231 			int rlen;
232 
233 			/* wait for rx ready */
234 			ret = ftsdc010_wait(regs, FTSDC010_STATUS_FIFO_ORUN);
235 			if (ret)
236 				break;
237 
238 			/* fetch bytes from ftsdc010 */
239 			for (rlen = 0; rlen < len && rlen < chip->fifo; ) {
240 				*(uint32_t *)buf = readl(&regs->dwr);
241 				buf  += 4;
242 				rlen += 4;
243 			}
244 
245 			len -= rlen;
246 		}
247 
248 	}
249 
250 	if (!ret) {
251 		ret = ftsdc010_wait(regs,
252 			FTSDC010_STATUS_DATA_END | FTSDC010_STATUS_DATA_ERROR);
253 	}
254 
255 	return ret;
256 }
257 
258 static void ftsdc010_set_ios(struct mmc *mmc)
259 {
260 	struct ftsdc010_chip *chip = mmc->priv;
261 	struct ftsdc010_mmc __iomem *regs = chip->regs;
262 
263 	ftsdc010_clkset(mmc, mmc->clock);
264 
265 	clrbits_le32(&regs->bwr, FTSDC010_BWR_MODE_MASK);
266 	switch (mmc->bus_width) {
267 	case 4:
268 		setbits_le32(&regs->bwr, FTSDC010_BWR_MODE_4BIT);
269 		break;
270 	case 8:
271 		setbits_le32(&regs->bwr, FTSDC010_BWR_MODE_8BIT);
272 		break;
273 	default:
274 		setbits_le32(&regs->bwr, FTSDC010_BWR_MODE_1BIT);
275 		break;
276 	}
277 }
278 
279 static int ftsdc010_init(struct mmc *mmc)
280 {
281 	struct ftsdc010_chip *chip = mmc->priv;
282 	struct ftsdc010_mmc __iomem *regs = chip->regs;
283 	uint32_t ts;
284 
285 	if (readl(&regs->status) & FTSDC010_STATUS_CARD_DETECT)
286 		return NO_CARD_ERR;
287 
288 	if (readl(&regs->status) & FTSDC010_STATUS_WRITE_PROT) {
289 		printf("ftsdc010: write protected\n");
290 		chip->wprot = 1;
291 	}
292 
293 	chip->fifo = (readl(&regs->feature) & 0xff) << 2;
294 
295 	/* 1. chip reset */
296 	writel(FTSDC010_CMD_SDC_RST, &regs->cmd);
297 	for (ts = get_timer(0); get_timer(ts) < CFG_RST_TIMEOUT; ) {
298 		if (readl(&regs->cmd) & FTSDC010_CMD_SDC_RST)
299 			continue;
300 		break;
301 	}
302 	if (readl(&regs->cmd) & FTSDC010_CMD_SDC_RST) {
303 		printf("ftsdc010: reset failed\n");
304 		return UNUSABLE_ERR;
305 	}
306 
307 	/* 2. enter low speed mode (400k card detection) */
308 	ftsdc010_clkset(mmc, 400000);
309 
310 	/* 3. interrupt disabled */
311 	writel(0, &regs->int_mask);
312 
313 	return 0;
314 }
315 
316 int ftsdc010_mmc_init(int devid)
317 {
318 	struct mmc *mmc;
319 	struct ftsdc010_chip *chip;
320 	struct ftsdc010_mmc __iomem *regs;
321 #ifdef CONFIG_FTSDC010_BASE_LIST
322 	uint32_t base_list[] = CONFIG_FTSDC010_BASE_LIST;
323 
324 	if (devid < 0 || devid >= ARRAY_SIZE(base_list))
325 		return -1;
326 	regs = (void __iomem *)base_list[devid];
327 #else
328 	regs = (void __iomem *)(CONFIG_FTSDC010_BASE + (devid << 20));
329 #endif
330 
331 	mmc = malloc(sizeof(struct mmc));
332 	if (!mmc)
333 		return -ENOMEM;
334 	memset(mmc, 0, sizeof(struct mmc));
335 
336 	chip = malloc(sizeof(struct ftsdc010_chip));
337 	if (!chip) {
338 		free(mmc);
339 		return -ENOMEM;
340 	}
341 	memset(chip, 0, sizeof(struct ftsdc010_chip));
342 
343 	chip->regs = regs;
344 	mmc->priv  = chip;
345 
346 	sprintf(mmc->name, "ftsdc010");
347 	mmc->send_cmd  = ftsdc010_request;
348 	mmc->set_ios   = ftsdc010_set_ios;
349 	mmc->init      = ftsdc010_init;
350 
351 	mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz;
352 	switch (readl(&regs->bwr) & FTSDC010_BWR_CAPS_MASK) {
353 	case FTSDC010_BWR_CAPS_4BIT:
354 		mmc->host_caps |= MMC_MODE_4BIT;
355 		break;
356 	case FTSDC010_BWR_CAPS_8BIT:
357 		mmc->host_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
358 		break;
359 	default:
360 		break;
361 	}
362 
363 #ifdef CONFIG_SYS_CLK_FREQ
364 	chip->sclk = CONFIG_SYS_CLK_FREQ;
365 #else
366 	chip->sclk = clk_get_rate("SDC");
367 #endif
368 
369 	mmc->voltages  = MMC_VDD_32_33 | MMC_VDD_33_34;
370 	mmc->f_max     = chip->sclk / 2;
371 	mmc->f_min     = chip->sclk / 0x100;
372 	mmc->block_dev.part_type = PART_TYPE_DOS;
373 
374 	mmc_register(mmc);
375 
376 	return 0;
377 }
378