]> Git Repo - u-boot.git/blame - drivers/mmc/mmc_spi.c
common: Drop log.h from common header
[u-boot.git] / drivers / mmc / mmc_spi.c
CommitLineData
d52ebf10
TC
1/*
2 * generic mmc spi driver
3 *
4 * Copyright (C) 2010 Thomas Chou <[email protected]>
05e35d42
BS
5 * Copyright 2019 Bhargav Shah <[email protected]>
6 *
d52ebf10
TC
7 * Licensed under the GPL-2 or later.
8 */
9#include <common.h>
915ffa52 10#include <errno.h>
f7ae49fc 11#include <log.h>
d52ebf10
TC
12#include <malloc.h>
13#include <part.h>
14#include <mmc.h>
05e35d42 15#include <stdlib.h>
a740ee91 16#include <u-boot/crc.h>
d52ebf10 17#include <linux/crc7.h>
6f67b69b 18#include <asm/byteorder.h>
05e35d42
BS
19#include <dm.h>
20#include <spi.h>
d52ebf10
TC
21
22/* MMC/SD in SPI mode reports R1 status always */
05e35d42
BS
23#define R1_SPI_IDLE BIT(0)
24#define R1_SPI_ERASE_RESET BIT(1)
25#define R1_SPI_ILLEGAL_COMMAND BIT(2)
26#define R1_SPI_COM_CRC BIT(3)
27#define R1_SPI_ERASE_SEQ BIT(4)
28#define R1_SPI_ADDRESS BIT(5)
29#define R1_SPI_PARAMETER BIT(6)
d52ebf10 30/* R1 bit 7 is always zero, reuse this bit for error */
05e35d42 31#define R1_SPI_ERROR BIT(7)
d52ebf10
TC
32
33/* Response tokens used to ack each block written: */
34#define SPI_MMC_RESPONSE_CODE(x) ((x) & 0x1f)
35#define SPI_RESPONSE_ACCEPTED ((2 << 1)|1)
36#define SPI_RESPONSE_CRC_ERR ((5 << 1)|1)
37#define SPI_RESPONSE_WRITE_ERR ((6 << 1)|1)
38
39/* Read and write blocks start with these tokens and end with crc;
40 * on error, read tokens act like a subset of R2_SPI_* values.
41 */
05e35d42
BS
42/* single block write multiblock read */
43#define SPI_TOKEN_SINGLE 0xfe
44/* multiblock write */
45#define SPI_TOKEN_MULTI_WRITE 0xfc
46/* terminate multiblock write */
47#define SPI_TOKEN_STOP_TRAN 0xfd
d52ebf10
TC
48
49/* MMC SPI commands start with a start bit "0" and a transmit bit "1" */
05e35d42 50#define MMC_SPI_CMD(x) (0x40 | (x))
d52ebf10
TC
51
52/* bus capability */
05e35d42
BS
53#define MMC_SPI_VOLTAGE (MMC_VDD_32_33 | MMC_VDD_33_34)
54#define MMC_SPI_MIN_CLOCK 400000 /* 400KHz to meet MMC spec */
55#define MMC_SPI_MAX_CLOCK 25000000 /* SD/MMC legacy speed */
d52ebf10
TC
56
57/* timeout value */
05e35d42
BS
58#define CMD_TIMEOUT 8
59#define READ_TIMEOUT 3000000 /* 1 sec */
60#define WRITE_TIMEOUT 3000000 /* 1 sec */
d52ebf10 61
d3302395 62struct mmc_spi_plat {
05e35d42
BS
63 struct mmc_config cfg;
64 struct mmc mmc;
65};
66
d3302395
BM
67struct mmc_spi_priv {
68 struct spi_slave *spi;
69};
70
05e35d42
BS
71static int mmc_spi_sendcmd(struct udevice *dev,
72 ushort cmdidx, u32 cmdarg, u32 resp_type,
73 u8 *resp, u32 resp_size,
74 bool resp_match, u8 resp_match_value)
d52ebf10 75{
05e35d42
BS
76 int i, rpos = 0, ret = 0;
77 u8 cmdo[7], r;
78
79 debug("%s: cmd%d cmdarg=0x%x resp_type=0x%x "
80 "resp_size=%d resp_match=%d resp_match_value=0x%x\n",
81 __func__, cmdidx, cmdarg, resp_type,
82 resp_size, resp_match, resp_match_value);
83
d52ebf10
TC
84 cmdo[0] = 0xff;
85 cmdo[1] = MMC_SPI_CMD(cmdidx);
86 cmdo[2] = cmdarg >> 24;
87 cmdo[3] = cmdarg >> 16;
88 cmdo[4] = cmdarg >> 8;
89 cmdo[5] = cmdarg;
90 cmdo[6] = (crc7(0, &cmdo[1], 5) << 1) | 0x01;
a7060294 91 ret = dm_spi_xfer(dev, sizeof(cmdo) * 8, cmdo, NULL, SPI_XFER_BEGIN);
05e35d42
BS
92 if (ret)
93 return ret;
94
95 ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0);
96 if (ret)
97 return ret;
98
99 if (!resp || !resp_size)
100 return 0;
101
102 debug("%s: cmd%d", __func__, cmdidx);
103
104 if (resp_match) {
105 r = ~resp_match_value;
106 i = CMD_TIMEOUT;
107 while (i--) {
108 ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0);
109 if (ret)
110 return ret;
111 debug(" resp%d=0x%x", rpos, r);
112 rpos++;
113 if (r == resp_match_value)
114 break;
115 }
116 if (!i && (r != resp_match_value))
117 return -ETIMEDOUT;
118 }
119
120 for (i = 0; i < resp_size; i++) {
121 if (i == 0 && resp_match) {
122 resp[i] = resp_match_value;
123 continue;
124 }
125 ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0);
126 if (ret)
127 return ret;
128 debug(" resp%d=0x%x", rpos, r);
129 rpos++;
130 resp[i] = r;
d52ebf10 131 }
05e35d42
BS
132
133 debug("\n");
134
135 return 0;
d52ebf10
TC
136}
137
05e35d42
BS
138static int mmc_spi_readdata(struct udevice *dev,
139 void *xbuf, u32 bcnt, u32 bsize)
d52ebf10 140{
d52ebf10 141 u16 crc;
05e35d42
BS
142 u8 *buf = xbuf, r1;
143 int i, ret = 0;
144
d52ebf10 145 while (bcnt--) {
05e35d42
BS
146 for (i = 0; i < READ_TIMEOUT; i++) {
147 ret = dm_spi_xfer(dev, 1 * 8, NULL, &r1, 0);
148 if (ret)
149 return ret;
150 if (r1 == SPI_TOKEN_SINGLE)
d52ebf10
TC
151 break;
152 }
05e35d42 153 debug("%s: data tok%d 0x%x\n", __func__, i, r1);
d52ebf10 154 if (r1 == SPI_TOKEN_SINGLE) {
05e35d42
BS
155 ret = dm_spi_xfer(dev, bsize * 8, NULL, buf, 0);
156 if (ret)
157 return ret;
158 ret = dm_spi_xfer(dev, 2 * 8, NULL, &crc, 0);
159 if (ret)
160 return ret;
d52ebf10 161#ifdef CONFIG_MMC_SPI_CRC_ON
05e35d42
BS
162 if (be16_to_cpu(crc16_ccitt(0, buf, bsize)) != crc) {
163 debug("%s: data crc error\n", __func__);
d52ebf10
TC
164 r1 = R1_SPI_COM_CRC;
165 break;
166 }
167#endif
168 r1 = 0;
169 } else {
170 r1 = R1_SPI_ERROR;
171 break;
172 }
173 buf += bsize;
174 }
05e35d42
BS
175
176 if (r1 & R1_SPI_COM_CRC)
177 ret = -ECOMM;
178 else if (r1) /* other errors */
179 ret = -ETIMEDOUT;
180
181 return ret;
d52ebf10
TC
182}
183
05e35d42
BS
184static int mmc_spi_writedata(struct udevice *dev, const void *xbuf,
185 u32 bcnt, u32 bsize, int multi)
d52ebf10 186{
d52ebf10 187 const u8 *buf = xbuf;
05e35d42 188 u8 r1, tok[2];
d52ebf10 189 u16 crc;
05e35d42
BS
190 int i, ret = 0;
191
d52ebf10
TC
192 tok[0] = 0xff;
193 tok[1] = multi ? SPI_TOKEN_MULTI_WRITE : SPI_TOKEN_SINGLE;
05e35d42 194
d52ebf10
TC
195 while (bcnt--) {
196#ifdef CONFIG_MMC_SPI_CRC_ON
ecb57f69 197 crc = cpu_to_be16(crc16_ccitt(0, (u8 *)buf, bsize));
d52ebf10 198#endif
05e35d42
BS
199 dm_spi_xfer(dev, 2 * 8, tok, NULL, 0);
200 dm_spi_xfer(dev, bsize * 8, buf, NULL, 0);
201 dm_spi_xfer(dev, 2 * 8, &crc, NULL, 0);
202 for (i = 0; i < CMD_TIMEOUT; i++) {
203 dm_spi_xfer(dev, 1 * 8, NULL, &r1, 0);
d52ebf10
TC
204 if ((r1 & 0x10) == 0) /* response token */
205 break;
206 }
05e35d42 207 debug("%s: data tok%d 0x%x\n", __func__, i, r1);
d52ebf10 208 if (SPI_MMC_RESPONSE_CODE(r1) == SPI_RESPONSE_ACCEPTED) {
05e35d42
BS
209 debug("%s: data accepted\n", __func__);
210 for (i = 0; i < WRITE_TIMEOUT; i++) { /* wait busy */
211 dm_spi_xfer(dev, 1 * 8, NULL, &r1, 0);
d52ebf10
TC
212 if (i && r1 == 0xff) {
213 r1 = 0;
214 break;
215 }
216 }
05e35d42
BS
217 if (i == WRITE_TIMEOUT) {
218 debug("%s: data write timeout 0x%x\n",
219 __func__, r1);
d52ebf10
TC
220 r1 = R1_SPI_ERROR;
221 break;
222 }
223 } else {
05e35d42 224 debug("%s: data error 0x%x\n", __func__, r1);
d52ebf10
TC
225 r1 = R1_SPI_COM_CRC;
226 break;
227 }
228 buf += bsize;
229 }
230 if (multi && bcnt == -1) { /* stop multi write */
231 tok[1] = SPI_TOKEN_STOP_TRAN;
05e35d42
BS
232 dm_spi_xfer(dev, 2 * 8, tok, NULL, 0);
233 for (i = 0; i < WRITE_TIMEOUT; i++) { /* wait busy */
234 dm_spi_xfer(dev, 1 * 8, NULL, &r1, 0);
d52ebf10
TC
235 if (i && r1 == 0xff) {
236 r1 = 0;
237 break;
238 }
239 }
05e35d42
BS
240 if (i == WRITE_TIMEOUT) {
241 debug("%s: data write timeout 0x%x\n", __func__, r1);
d52ebf10
TC
242 r1 = R1_SPI_ERROR;
243 }
244 }
d52ebf10 245
05e35d42 246 if (r1 & R1_SPI_COM_CRC)
915ffa52 247 ret = -ECOMM;
05e35d42 248 else if (r1) /* other errors */
915ffa52 249 ret = -ETIMEDOUT;
05e35d42
BS
250
251 return ret;
252}
253
254static int dm_mmc_spi_set_ios(struct udevice *dev)
255{
256 return 0;
257}
258
259static int dm_mmc_spi_request(struct udevice *dev, struct mmc_cmd *cmd,
260 struct mmc_data *data)
261{
262 int i, multi, ret = 0;
263 u8 *resp = NULL;
264 u32 resp_size = 0;
265 bool resp_match = false;
266 u8 resp8 = 0, resp40[5] = { 0 }, resp_match_value = 0;
267
268 dm_spi_claim_bus(dev);
269
270 for (i = 0; i < 4; i++)
271 cmd->response[i] = 0;
272
273 switch (cmd->cmdidx) {
274 case SD_CMD_APP_SEND_OP_COND:
275 case MMC_CMD_SEND_OP_COND:
276 resp = &resp8;
277 resp_size = sizeof(resp8);
278 cmd->cmdarg = 0x40000000;
279 break;
280 case SD_CMD_SEND_IF_COND:
281 resp = (u8 *)&resp40[0];
282 resp_size = sizeof(resp40);
283 resp_match = true;
284 resp_match_value = R1_SPI_IDLE;
285 break;
286 case MMC_CMD_SPI_READ_OCR:
287 resp = (u8 *)&resp40[0];
288 resp_size = sizeof(resp40);
289 break;
290 case MMC_CMD_SEND_STATUS:
291 case MMC_CMD_SET_BLOCKLEN:
292 case MMC_CMD_SPI_CRC_ON_OFF:
293 case MMC_CMD_STOP_TRANSMISSION:
294 resp = &resp8;
295 resp_size = sizeof(resp8);
296 resp_match = true;
297 resp_match_value = 0x0;
298 break;
299 case MMC_CMD_SEND_CSD:
300 case MMC_CMD_SEND_CID:
301 case MMC_CMD_READ_SINGLE_BLOCK:
302 case MMC_CMD_READ_MULTIPLE_BLOCK:
303 case MMC_CMD_WRITE_SINGLE_BLOCK:
304 case MMC_CMD_WRITE_MULTIPLE_BLOCK:
305 break;
306 default:
307 resp = &resp8;
308 resp_size = sizeof(resp8);
309 resp_match = true;
310 resp_match_value = R1_SPI_IDLE;
311 break;
312 };
313
314 ret = mmc_spi_sendcmd(dev, cmd->cmdidx, cmd->cmdarg, cmd->resp_type,
315 resp, resp_size, resp_match, resp_match_value);
316 if (ret)
d52ebf10 317 goto done;
05e35d42
BS
318
319 switch (cmd->cmdidx) {
320 case SD_CMD_APP_SEND_OP_COND:
321 case MMC_CMD_SEND_OP_COND:
322 cmd->response[0] = (resp8 & R1_SPI_IDLE) ? 0 : OCR_BUSY;
323 break;
324 case SD_CMD_SEND_IF_COND:
325 case MMC_CMD_SPI_READ_OCR:
326 cmd->response[0] = resp40[4];
327 cmd->response[0] |= (uint)resp40[3] << 8;
328 cmd->response[0] |= (uint)resp40[2] << 16;
329 cmd->response[0] |= (uint)resp40[1] << 24;
330 break;
331 case MMC_CMD_SEND_STATUS:
332 cmd->response[0] = (resp8 & 0xff) ?
333 MMC_STATUS_ERROR : MMC_STATUS_RDY_FOR_DATA;
334 break;
335 case MMC_CMD_SEND_CID:
336 case MMC_CMD_SEND_CSD:
337 ret = mmc_spi_readdata(dev, cmd->response, 1, 16);
338 if (ret)
339 return ret;
d52ebf10 340 for (i = 0; i < 4; i++)
05e35d42
BS
341 cmd->response[i] =
342 cpu_to_be32(cmd->response[i]);
343 break;
344 default:
345 cmd->response[0] = resp8;
346 break;
347 }
348
349 debug("%s: cmd%d resp0=0x%x resp1=0x%x resp2=0x%x resp3=0x%x\n",
350 __func__, cmd->cmdidx, cmd->response[0], cmd->response[1],
351 cmd->response[2], cmd->response[3]);
352
353 if (data) {
354 debug("%s: data flags=0x%x blocks=%d block_size=%d\n",
355 __func__, data->flags, data->blocks, data->blocksize);
356 multi = (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK);
d52ebf10 357 if (data->flags == MMC_DATA_READ)
05e35d42
BS
358 ret = mmc_spi_readdata(dev, data->dest,
359 data->blocks, data->blocksize);
d52ebf10 360 else if (data->flags == MMC_DATA_WRITE)
05e35d42
BS
361 ret = mmc_spi_writedata(dev, data->src,
362 data->blocks, data->blocksize,
363 multi);
d52ebf10 364 }
05e35d42 365
d52ebf10 366done:
a7060294
AP
367 dm_spi_xfer(dev, 0, NULL, NULL, SPI_XFER_END);
368
05e35d42
BS
369 dm_spi_release_bus(dev);
370
d52ebf10
TC
371 return ret;
372}
373
05e35d42 374static int mmc_spi_probe(struct udevice *dev)
d52ebf10 375{
05e35d42 376 struct mmc_spi_priv *priv = dev_get_priv(dev);
d3302395 377 struct mmc_spi_plat *plat = dev_get_platdata(dev);
05e35d42
BS
378 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
379 char *name;
380
381 priv->spi = dev_get_parent_priv(dev);
382 if (!priv->spi->max_hz)
383 priv->spi->max_hz = MMC_SPI_MAX_CLOCK;
384 priv->spi->speed = 0;
385 priv->spi->mode = SPI_MODE_0;
386 priv->spi->wordlen = 8;
387
388 name = malloc(strlen(dev->parent->name) + strlen(dev->name) + 4);
389 if (!name)
390 return -ENOMEM;
391 sprintf(name, "%s:%s", dev->parent->name, dev->name);
392
d3302395
BM
393 plat->cfg.name = name;
394 plat->cfg.host_caps = MMC_MODE_SPI;
395 plat->cfg.voltages = MMC_SPI_VOLTAGE;
396 plat->cfg.f_min = MMC_SPI_MIN_CLOCK;
397 plat->cfg.f_max = priv->spi->max_hz;
398 plat->cfg.part_type = PART_TYPE_DOS;
399 plat->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
05e35d42 400
d3302395
BM
401 plat->mmc.cfg = &plat->cfg;
402 plat->mmc.priv = priv;
403 plat->mmc.dev = dev;
05e35d42 404
d3302395 405 upriv->mmc = &plat->mmc;
93bfd616 406
07b0b9c0 407 return 0;
d52ebf10
TC
408}
409
05e35d42 410static int mmc_spi_bind(struct udevice *dev)
d52ebf10 411{
d3302395 412 struct mmc_spi_plat *plat = dev_get_platdata(dev);
05e35d42 413
d3302395 414 return mmc_bind(dev, &plat->mmc, &plat->cfg);
d52ebf10
TC
415}
416
05e35d42
BS
417static const struct dm_mmc_ops mmc_spi_ops = {
418 .send_cmd = dm_mmc_spi_request,
419 .set_ios = dm_mmc_spi_set_ios,
ab769f22
PA
420};
421
05e35d42
BS
422static const struct udevice_id dm_mmc_spi_match[] = {
423 { .compatible = "mmc-spi-slot" },
424 { /* sentinel */ }
93bfd616
PA
425};
426
05e35d42
BS
427U_BOOT_DRIVER(mmc_spi) = {
428 .name = "mmc_spi",
429 .id = UCLASS_MMC,
430 .of_match = dm_mmc_spi_match,
431 .ops = &mmc_spi_ops,
432 .probe = mmc_spi_probe,
433 .bind = mmc_spi_bind,
d3302395 434 .platdata_auto_alloc_size = sizeof(struct mmc_spi_plat),
05e35d42
BS
435 .priv_auto_alloc_size = sizeof(struct mmc_spi_priv),
436};
This page took 0.325322 seconds and 4 git commands to generate.