1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * generic mmc spi driver
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
5*4882a593Smuzhiyun * Licensed under the GPL-2 or later.
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <errno.h>
9*4882a593Smuzhiyun #include <malloc.h>
10*4882a593Smuzhiyun #include <part.h>
11*4882a593Smuzhiyun #include <mmc.h>
12*4882a593Smuzhiyun #include <spi.h>
13*4882a593Smuzhiyun #include <crc.h>
14*4882a593Smuzhiyun #include <linux/crc7.h>
15*4882a593Smuzhiyun #include <asm/byteorder.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun /* MMC/SD in SPI mode reports R1 status always */
18*4882a593Smuzhiyun #define R1_SPI_IDLE (1 << 0)
19*4882a593Smuzhiyun #define R1_SPI_ERASE_RESET (1 << 1)
20*4882a593Smuzhiyun #define R1_SPI_ILLEGAL_COMMAND (1 << 2)
21*4882a593Smuzhiyun #define R1_SPI_COM_CRC (1 << 3)
22*4882a593Smuzhiyun #define R1_SPI_ERASE_SEQ (1 << 4)
23*4882a593Smuzhiyun #define R1_SPI_ADDRESS (1 << 5)
24*4882a593Smuzhiyun #define R1_SPI_PARAMETER (1 << 6)
25*4882a593Smuzhiyun /* R1 bit 7 is always zero, reuse this bit for error */
26*4882a593Smuzhiyun #define R1_SPI_ERROR (1 << 7)
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun /* Response tokens used to ack each block written: */
29*4882a593Smuzhiyun #define SPI_MMC_RESPONSE_CODE(x) ((x) & 0x1f)
30*4882a593Smuzhiyun #define SPI_RESPONSE_ACCEPTED ((2 << 1)|1)
31*4882a593Smuzhiyun #define SPI_RESPONSE_CRC_ERR ((5 << 1)|1)
32*4882a593Smuzhiyun #define SPI_RESPONSE_WRITE_ERR ((6 << 1)|1)
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun /* Read and write blocks start with these tokens and end with crc;
35*4882a593Smuzhiyun * on error, read tokens act like a subset of R2_SPI_* values.
36*4882a593Smuzhiyun */
37*4882a593Smuzhiyun #define SPI_TOKEN_SINGLE 0xfe /* single block r/w, multiblock read */
38*4882a593Smuzhiyun #define SPI_TOKEN_MULTI_WRITE 0xfc /* multiblock write */
39*4882a593Smuzhiyun #define SPI_TOKEN_STOP_TRAN 0xfd /* terminate multiblock write */
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun /* MMC SPI commands start with a start bit "0" and a transmit bit "1" */
42*4882a593Smuzhiyun #define MMC_SPI_CMD(x) (0x40 | (x & 0x3f))
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun /* bus capability */
45*4882a593Smuzhiyun #define MMC_SPI_VOLTAGE (MMC_VDD_32_33 | MMC_VDD_33_34)
46*4882a593Smuzhiyun #define MMC_SPI_MIN_CLOCK 400000 /* 400KHz to meet MMC spec */
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun /* timeout value */
49*4882a593Smuzhiyun #define CTOUT 8
50*4882a593Smuzhiyun #define RTOUT 3000000 /* 1 sec */
51*4882a593Smuzhiyun #define WTOUT 3000000 /* 1 sec */
52*4882a593Smuzhiyun
mmc_spi_sendcmd(struct mmc * mmc,ushort cmdidx,u32 cmdarg)53*4882a593Smuzhiyun static uint mmc_spi_sendcmd(struct mmc *mmc, ushort cmdidx, u32 cmdarg)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun struct spi_slave *spi = mmc->priv;
56*4882a593Smuzhiyun u8 cmdo[7];
57*4882a593Smuzhiyun u8 r1;
58*4882a593Smuzhiyun int i;
59*4882a593Smuzhiyun cmdo[0] = 0xff;
60*4882a593Smuzhiyun cmdo[1] = MMC_SPI_CMD(cmdidx);
61*4882a593Smuzhiyun cmdo[2] = cmdarg >> 24;
62*4882a593Smuzhiyun cmdo[3] = cmdarg >> 16;
63*4882a593Smuzhiyun cmdo[4] = cmdarg >> 8;
64*4882a593Smuzhiyun cmdo[5] = cmdarg;
65*4882a593Smuzhiyun cmdo[6] = (crc7(0, &cmdo[1], 5) << 1) | 0x01;
66*4882a593Smuzhiyun spi_xfer(spi, sizeof(cmdo) * 8, cmdo, NULL, 0);
67*4882a593Smuzhiyun for (i = 0; i < CTOUT; i++) {
68*4882a593Smuzhiyun spi_xfer(spi, 1 * 8, NULL, &r1, 0);
69*4882a593Smuzhiyun if (i && (r1 & 0x80) == 0) /* r1 response */
70*4882a593Smuzhiyun break;
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun debug("%s:cmd%d resp%d %x\n", __func__, cmdidx, i, r1);
73*4882a593Smuzhiyun return r1;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
mmc_spi_readdata(struct mmc * mmc,void * xbuf,u32 bcnt,u32 bsize)76*4882a593Smuzhiyun static uint mmc_spi_readdata(struct mmc *mmc, void *xbuf,
77*4882a593Smuzhiyun u32 bcnt, u32 bsize)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun struct spi_slave *spi = mmc->priv;
80*4882a593Smuzhiyun u8 *buf = xbuf;
81*4882a593Smuzhiyun u8 r1;
82*4882a593Smuzhiyun u16 crc;
83*4882a593Smuzhiyun int i;
84*4882a593Smuzhiyun while (bcnt--) {
85*4882a593Smuzhiyun for (i = 0; i < RTOUT; i++) {
86*4882a593Smuzhiyun spi_xfer(spi, 1 * 8, NULL, &r1, 0);
87*4882a593Smuzhiyun if (r1 != 0xff) /* data token */
88*4882a593Smuzhiyun break;
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun debug("%s:tok%d %x\n", __func__, i, r1);
91*4882a593Smuzhiyun if (r1 == SPI_TOKEN_SINGLE) {
92*4882a593Smuzhiyun spi_xfer(spi, bsize * 8, NULL, buf, 0);
93*4882a593Smuzhiyun spi_xfer(spi, 2 * 8, NULL, &crc, 0);
94*4882a593Smuzhiyun #ifdef CONFIG_MMC_SPI_CRC_ON
95*4882a593Smuzhiyun if (be_to_cpu16(crc16_ccitt(0, buf, bsize)) != crc) {
96*4882a593Smuzhiyun debug("%s: CRC error\n", mmc->cfg->name);
97*4882a593Smuzhiyun r1 = R1_SPI_COM_CRC;
98*4882a593Smuzhiyun break;
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun #endif
101*4882a593Smuzhiyun r1 = 0;
102*4882a593Smuzhiyun } else {
103*4882a593Smuzhiyun r1 = R1_SPI_ERROR;
104*4882a593Smuzhiyun break;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun buf += bsize;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun return r1;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun
mmc_spi_writedata(struct mmc * mmc,const void * xbuf,u32 bcnt,u32 bsize,int multi)111*4882a593Smuzhiyun static uint mmc_spi_writedata(struct mmc *mmc, const void *xbuf,
112*4882a593Smuzhiyun u32 bcnt, u32 bsize, int multi)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun struct spi_slave *spi = mmc->priv;
115*4882a593Smuzhiyun const u8 *buf = xbuf;
116*4882a593Smuzhiyun u8 r1;
117*4882a593Smuzhiyun u16 crc;
118*4882a593Smuzhiyun u8 tok[2];
119*4882a593Smuzhiyun int i;
120*4882a593Smuzhiyun tok[0] = 0xff;
121*4882a593Smuzhiyun tok[1] = multi ? SPI_TOKEN_MULTI_WRITE : SPI_TOKEN_SINGLE;
122*4882a593Smuzhiyun while (bcnt--) {
123*4882a593Smuzhiyun #ifdef CONFIG_MMC_SPI_CRC_ON
124*4882a593Smuzhiyun crc = cpu_to_be16(crc16_ccitt(0, (u8 *)buf, bsize));
125*4882a593Smuzhiyun #endif
126*4882a593Smuzhiyun spi_xfer(spi, 2 * 8, tok, NULL, 0);
127*4882a593Smuzhiyun spi_xfer(spi, bsize * 8, buf, NULL, 0);
128*4882a593Smuzhiyun spi_xfer(spi, 2 * 8, &crc, NULL, 0);
129*4882a593Smuzhiyun for (i = 0; i < CTOUT; i++) {
130*4882a593Smuzhiyun spi_xfer(spi, 1 * 8, NULL, &r1, 0);
131*4882a593Smuzhiyun if ((r1 & 0x10) == 0) /* response token */
132*4882a593Smuzhiyun break;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun debug("%s:tok%d %x\n", __func__, i, r1);
135*4882a593Smuzhiyun if (SPI_MMC_RESPONSE_CODE(r1) == SPI_RESPONSE_ACCEPTED) {
136*4882a593Smuzhiyun for (i = 0; i < WTOUT; i++) { /* wait busy */
137*4882a593Smuzhiyun spi_xfer(spi, 1 * 8, NULL, &r1, 0);
138*4882a593Smuzhiyun if (i && r1 == 0xff) {
139*4882a593Smuzhiyun r1 = 0;
140*4882a593Smuzhiyun break;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun if (i == WTOUT) {
144*4882a593Smuzhiyun debug("%s:wtout %x\n", __func__, r1);
145*4882a593Smuzhiyun r1 = R1_SPI_ERROR;
146*4882a593Smuzhiyun break;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun } else {
149*4882a593Smuzhiyun debug("%s: err %x\n", __func__, r1);
150*4882a593Smuzhiyun r1 = R1_SPI_COM_CRC;
151*4882a593Smuzhiyun break;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun buf += bsize;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun if (multi && bcnt == -1) { /* stop multi write */
156*4882a593Smuzhiyun tok[1] = SPI_TOKEN_STOP_TRAN;
157*4882a593Smuzhiyun spi_xfer(spi, 2 * 8, tok, NULL, 0);
158*4882a593Smuzhiyun for (i = 0; i < WTOUT; i++) { /* wait busy */
159*4882a593Smuzhiyun spi_xfer(spi, 1 * 8, NULL, &r1, 0);
160*4882a593Smuzhiyun if (i && r1 == 0xff) {
161*4882a593Smuzhiyun r1 = 0;
162*4882a593Smuzhiyun break;
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun if (i == WTOUT) {
166*4882a593Smuzhiyun debug("%s:wstop %x\n", __func__, r1);
167*4882a593Smuzhiyun r1 = R1_SPI_ERROR;
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun return r1;
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun
mmc_spi_request(struct mmc * mmc,struct mmc_cmd * cmd,struct mmc_data * data)173*4882a593Smuzhiyun static int mmc_spi_request(struct mmc *mmc, struct mmc_cmd *cmd,
174*4882a593Smuzhiyun struct mmc_data *data)
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun struct spi_slave *spi = mmc->priv;
177*4882a593Smuzhiyun u8 r1;
178*4882a593Smuzhiyun int i;
179*4882a593Smuzhiyun int ret = 0;
180*4882a593Smuzhiyun debug("%s:cmd%d %x %x\n", __func__,
181*4882a593Smuzhiyun cmd->cmdidx, cmd->resp_type, cmd->cmdarg);
182*4882a593Smuzhiyun spi_claim_bus(spi);
183*4882a593Smuzhiyun spi_cs_activate(spi);
184*4882a593Smuzhiyun r1 = mmc_spi_sendcmd(mmc, cmd->cmdidx, cmd->cmdarg);
185*4882a593Smuzhiyun if (r1 == 0xff) { /* no response */
186*4882a593Smuzhiyun ret = -ENOMEDIUM;
187*4882a593Smuzhiyun goto done;
188*4882a593Smuzhiyun } else if (r1 & R1_SPI_COM_CRC) {
189*4882a593Smuzhiyun ret = -ECOMM;
190*4882a593Smuzhiyun goto done;
191*4882a593Smuzhiyun } else if (r1 & ~R1_SPI_IDLE) { /* other errors */
192*4882a593Smuzhiyun ret = -ETIMEDOUT;
193*4882a593Smuzhiyun goto done;
194*4882a593Smuzhiyun } else if (cmd->resp_type == MMC_RSP_R2) {
195*4882a593Smuzhiyun r1 = mmc_spi_readdata(mmc, cmd->response, 1, 16);
196*4882a593Smuzhiyun for (i = 0; i < 4; i++)
197*4882a593Smuzhiyun cmd->response[i] = be32_to_cpu(cmd->response[i]);
198*4882a593Smuzhiyun debug("r128 %x %x %x %x\n", cmd->response[0], cmd->response[1],
199*4882a593Smuzhiyun cmd->response[2], cmd->response[3]);
200*4882a593Smuzhiyun } else if (!data) {
201*4882a593Smuzhiyun switch (cmd->cmdidx) {
202*4882a593Smuzhiyun case SD_CMD_APP_SEND_OP_COND:
203*4882a593Smuzhiyun case MMC_CMD_SEND_OP_COND:
204*4882a593Smuzhiyun cmd->response[0] = (r1 & R1_SPI_IDLE) ? 0 : OCR_BUSY;
205*4882a593Smuzhiyun break;
206*4882a593Smuzhiyun case SD_CMD_SEND_IF_COND:
207*4882a593Smuzhiyun case MMC_CMD_SPI_READ_OCR:
208*4882a593Smuzhiyun spi_xfer(spi, 4 * 8, NULL, cmd->response, 0);
209*4882a593Smuzhiyun cmd->response[0] = be32_to_cpu(cmd->response[0]);
210*4882a593Smuzhiyun debug("r32 %x\n", cmd->response[0]);
211*4882a593Smuzhiyun break;
212*4882a593Smuzhiyun case MMC_CMD_SEND_STATUS:
213*4882a593Smuzhiyun spi_xfer(spi, 1 * 8, NULL, cmd->response, 0);
214*4882a593Smuzhiyun cmd->response[0] = (cmd->response[0] & 0xff) ?
215*4882a593Smuzhiyun MMC_STATUS_ERROR : MMC_STATUS_RDY_FOR_DATA;
216*4882a593Smuzhiyun break;
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun } else {
219*4882a593Smuzhiyun debug("%s:data %x %x %x\n", __func__,
220*4882a593Smuzhiyun data->flags, data->blocks, data->blocksize);
221*4882a593Smuzhiyun if (data->flags == MMC_DATA_READ)
222*4882a593Smuzhiyun r1 = mmc_spi_readdata(mmc, data->dest,
223*4882a593Smuzhiyun data->blocks, data->blocksize);
224*4882a593Smuzhiyun else if (data->flags == MMC_DATA_WRITE)
225*4882a593Smuzhiyun r1 = mmc_spi_writedata(mmc, data->src,
226*4882a593Smuzhiyun data->blocks, data->blocksize,
227*4882a593Smuzhiyun (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK));
228*4882a593Smuzhiyun if (r1 & R1_SPI_COM_CRC)
229*4882a593Smuzhiyun ret = -ECOMM;
230*4882a593Smuzhiyun else if (r1) /* other errors */
231*4882a593Smuzhiyun ret = -ETIMEDOUT;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun done:
234*4882a593Smuzhiyun spi_cs_deactivate(spi);
235*4882a593Smuzhiyun spi_release_bus(spi);
236*4882a593Smuzhiyun return ret;
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun
mmc_spi_set_ios(struct mmc * mmc)239*4882a593Smuzhiyun static int mmc_spi_set_ios(struct mmc *mmc)
240*4882a593Smuzhiyun {
241*4882a593Smuzhiyun struct spi_slave *spi = mmc->priv;
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun debug("%s: clock %u\n", __func__, mmc->clock);
244*4882a593Smuzhiyun if (mmc->clock)
245*4882a593Smuzhiyun spi_set_speed(spi, mmc->clock);
246*4882a593Smuzhiyun return 0;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
mmc_spi_init_p(struct mmc * mmc)249*4882a593Smuzhiyun static int mmc_spi_init_p(struct mmc *mmc)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun struct spi_slave *spi = mmc->priv;
252*4882a593Smuzhiyun spi_set_speed(spi, MMC_SPI_MIN_CLOCK);
253*4882a593Smuzhiyun spi_claim_bus(spi);
254*4882a593Smuzhiyun /* cs deactivated for 100+ clock */
255*4882a593Smuzhiyun spi_xfer(spi, 18 * 8, NULL, NULL, 0);
256*4882a593Smuzhiyun spi_release_bus(spi);
257*4882a593Smuzhiyun return 0;
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun static const struct mmc_ops mmc_spi_ops = {
261*4882a593Smuzhiyun .send_cmd = mmc_spi_request,
262*4882a593Smuzhiyun .set_ios = mmc_spi_set_ios,
263*4882a593Smuzhiyun .init = mmc_spi_init_p,
264*4882a593Smuzhiyun };
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun static struct mmc_config mmc_spi_cfg = {
267*4882a593Smuzhiyun .name = "MMC_SPI",
268*4882a593Smuzhiyun .ops = &mmc_spi_ops,
269*4882a593Smuzhiyun .host_caps = MMC_MODE_SPI,
270*4882a593Smuzhiyun .voltages = MMC_SPI_VOLTAGE,
271*4882a593Smuzhiyun .f_min = MMC_SPI_MIN_CLOCK,
272*4882a593Smuzhiyun .part_type = PART_TYPE_DOS,
273*4882a593Smuzhiyun .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT,
274*4882a593Smuzhiyun };
275*4882a593Smuzhiyun
mmc_spi_init(uint bus,uint cs,uint speed,uint mode)276*4882a593Smuzhiyun struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun struct mmc *mmc;
279*4882a593Smuzhiyun struct spi_slave *spi;
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun spi = spi_setup_slave(bus, cs, speed, mode);
282*4882a593Smuzhiyun if (spi == NULL)
283*4882a593Smuzhiyun return NULL;
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun mmc_spi_cfg.f_max = speed;
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun mmc = mmc_create(&mmc_spi_cfg, spi);
288*4882a593Smuzhiyun if (mmc == NULL) {
289*4882a593Smuzhiyun spi_free_slave(spi);
290*4882a593Smuzhiyun return NULL;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun return mmc;
293*4882a593Smuzhiyun }
294