xref: /openbmc/qemu/hw/sd/ssi-sd.c (revision 6683d7bc)
1 /*
2  * SSI to SD card adapter.
3  *
4  * Copyright (c) 2007-2009 CodeSourcery.
5  * Written by Paul Brook
6  *
7  * This code is licensed under the GNU GPL v2.
8  *
9  * Contributions after 2012-01-13 are licensed under the terms of the
10  * GNU GPL, version 2 or (at your option) any later version.
11  */
12 
13 #include "sysemu/blockdev.h"
14 #include "hw/ssi.h"
15 #include "hw/sd.h"
16 
17 //#define DEBUG_SSI_SD 1
18 
19 #ifdef DEBUG_SSI_SD
20 #define DPRINTF(fmt, ...) \
21 do { printf("ssi_sd: " fmt , ## __VA_ARGS__); } while (0)
22 #define BADF(fmt, ...) \
23 do { fprintf(stderr, "ssi_sd: error: " fmt , ## __VA_ARGS__); exit(1);} while (0)
24 #else
25 #define DPRINTF(fmt, ...) do {} while(0)
26 #define BADF(fmt, ...) \
27 do { fprintf(stderr, "ssi_sd: error: " fmt , ## __VA_ARGS__);} while (0)
28 #endif
29 
30 typedef enum {
31     SSI_SD_CMD,
32     SSI_SD_CMDARG,
33     SSI_SD_RESPONSE,
34     SSI_SD_DATA_START,
35     SSI_SD_DATA_READ,
36 } ssi_sd_mode;
37 
38 typedef struct {
39     SSISlave ssidev;
40     ssi_sd_mode mode;
41     int cmd;
42     uint8_t cmdarg[4];
43     uint8_t response[5];
44     int arglen;
45     int response_pos;
46     int stopping;
47     SDState *sd;
48 } ssi_sd_state;
49 
50 /* State word bits.  */
51 #define SSI_SDR_LOCKED          0x0001
52 #define SSI_SDR_WP_ERASE        0x0002
53 #define SSI_SDR_ERROR           0x0004
54 #define SSI_SDR_CC_ERROR        0x0008
55 #define SSI_SDR_ECC_FAILED      0x0010
56 #define SSI_SDR_WP_VIOLATION    0x0020
57 #define SSI_SDR_ERASE_PARAM     0x0040
58 #define SSI_SDR_OUT_OF_RANGE    0x0080
59 #define SSI_SDR_IDLE            0x0100
60 #define SSI_SDR_ERASE_RESET     0x0200
61 #define SSI_SDR_ILLEGAL_COMMAND 0x0400
62 #define SSI_SDR_COM_CRC_ERROR   0x0800
63 #define SSI_SDR_ERASE_SEQ_ERROR 0x1000
64 #define SSI_SDR_ADDRESS_ERROR   0x2000
65 #define SSI_SDR_PARAMETER_ERROR 0x4000
66 
67 static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val)
68 {
69     ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, dev);
70 
71     /* Special case: allow CMD12 (STOP TRANSMISSION) while reading data.  */
72     if (s->mode == SSI_SD_DATA_READ && val == 0x4d) {
73         s->mode = SSI_SD_CMD;
74         /* There must be at least one byte delay before the card responds.  */
75         s->stopping = 1;
76     }
77 
78     switch (s->mode) {
79     case SSI_SD_CMD:
80         if (val == 0xff) {
81             DPRINTF("NULL command\n");
82             return 0xff;
83         }
84         s->cmd = val & 0x3f;
85         s->mode = SSI_SD_CMDARG;
86         s->arglen = 0;
87         return 0xff;
88     case SSI_SD_CMDARG:
89         if (s->arglen == 4) {
90             SDRequest request;
91             uint8_t longresp[16];
92             /* FIXME: Check CRC.  */
93             request.cmd = s->cmd;
94             request.arg = (s->cmdarg[0] << 24) | (s->cmdarg[1] << 16)
95                            | (s->cmdarg[2] << 8) | s->cmdarg[3];
96             DPRINTF("CMD%d arg 0x%08x\n", s->cmd, request.arg);
97             s->arglen = sd_do_command(s->sd, &request, longresp);
98             if (s->arglen <= 0) {
99                 s->arglen = 1;
100                 s->response[0] = 4;
101                 DPRINTF("SD command failed\n");
102             } else if (s->cmd == 58) {
103                 /* CMD58 returns R3 response (OCR)  */
104                 DPRINTF("Returned OCR\n");
105                 s->arglen = 5;
106                 s->response[0] = 1;
107                 memcpy(&s->response[1], longresp, 4);
108             } else if (s->arglen != 4) {
109                 BADF("Unexpected response to cmd %d\n", s->cmd);
110                 /* Illegal command is about as near as we can get.  */
111                 s->arglen = 1;
112                 s->response[0] = 4;
113             } else {
114                 /* All other commands return status.  */
115                 uint32_t cardstatus;
116                 uint16_t status;
117                 /* CMD13 returns a 2-byte statuse work. Other commands
118                    only return the first byte.  */
119                 s->arglen = (s->cmd == 13) ? 2 : 1;
120                 cardstatus = (longresp[0] << 24) | (longresp[1] << 16)
121                              | (longresp[2] << 8) | longresp[3];
122                 status = 0;
123                 if (((cardstatus >> 9) & 0xf) < 4)
124                     status |= SSI_SDR_IDLE;
125                 if (cardstatus & ERASE_RESET)
126                     status |= SSI_SDR_ERASE_RESET;
127                 if (cardstatus & ILLEGAL_COMMAND)
128                     status |= SSI_SDR_ILLEGAL_COMMAND;
129                 if (cardstatus & COM_CRC_ERROR)
130                     status |= SSI_SDR_COM_CRC_ERROR;
131                 if (cardstatus & ERASE_SEQ_ERROR)
132                     status |= SSI_SDR_ERASE_SEQ_ERROR;
133                 if (cardstatus & ADDRESS_ERROR)
134                     status |= SSI_SDR_ADDRESS_ERROR;
135                 if (cardstatus & CARD_IS_LOCKED)
136                     status |= SSI_SDR_LOCKED;
137                 if (cardstatus & (LOCK_UNLOCK_FAILED | WP_ERASE_SKIP))
138                     status |= SSI_SDR_WP_ERASE;
139                 if (cardstatus & SD_ERROR)
140                     status |= SSI_SDR_ERROR;
141                 if (cardstatus & CC_ERROR)
142                     status |= SSI_SDR_CC_ERROR;
143                 if (cardstatus & CARD_ECC_FAILED)
144                     status |= SSI_SDR_ECC_FAILED;
145                 if (cardstatus & WP_VIOLATION)
146                     status |= SSI_SDR_WP_VIOLATION;
147                 if (cardstatus & ERASE_PARAM)
148                     status |= SSI_SDR_ERASE_PARAM;
149                 if (cardstatus & (OUT_OF_RANGE | CID_CSD_OVERWRITE))
150                     status |= SSI_SDR_OUT_OF_RANGE;
151                 /* ??? Don't know what Parameter Error really means, so
152                    assume it's set if the second byte is nonzero.  */
153                 if (status & 0xff)
154                     status |= SSI_SDR_PARAMETER_ERROR;
155                 s->response[0] = status >> 8;
156                 s->response[1] = status;
157                 DPRINTF("Card status 0x%02x\n", status);
158             }
159             s->mode = SSI_SD_RESPONSE;
160             s->response_pos = 0;
161         } else {
162             s->cmdarg[s->arglen++] = val;
163         }
164         return 0xff;
165     case SSI_SD_RESPONSE:
166         if (s->stopping) {
167             s->stopping = 0;
168             return 0xff;
169         }
170         if (s->response_pos < s->arglen) {
171             DPRINTF("Response 0x%02x\n", s->response[s->response_pos]);
172             return s->response[s->response_pos++];
173         }
174         if (sd_data_ready(s->sd)) {
175             DPRINTF("Data read\n");
176             s->mode = SSI_SD_DATA_START;
177         } else {
178             DPRINTF("End of command\n");
179             s->mode = SSI_SD_CMD;
180         }
181         return 0xff;
182     case SSI_SD_DATA_START:
183         DPRINTF("Start read block\n");
184         s->mode = SSI_SD_DATA_READ;
185         return 0xfe;
186     case SSI_SD_DATA_READ:
187         val = sd_read_data(s->sd);
188         if (!sd_data_ready(s->sd)) {
189             DPRINTF("Data read end\n");
190             s->mode = SSI_SD_CMD;
191         }
192         return val;
193     }
194     /* Should never happen.  */
195     return 0xff;
196 }
197 
198 static void ssi_sd_save(QEMUFile *f, void *opaque)
199 {
200     SSISlave *ss = SSI_SLAVE(opaque);
201     ssi_sd_state *s = (ssi_sd_state *)opaque;
202     int i;
203 
204     qemu_put_be32(f, s->mode);
205     qemu_put_be32(f, s->cmd);
206     for (i = 0; i < 4; i++)
207         qemu_put_be32(f, s->cmdarg[i]);
208     for (i = 0; i < 5; i++)
209         qemu_put_be32(f, s->response[i]);
210     qemu_put_be32(f, s->arglen);
211     qemu_put_be32(f, s->response_pos);
212     qemu_put_be32(f, s->stopping);
213 
214     qemu_put_be32(f, ss->cs);
215 }
216 
217 static int ssi_sd_load(QEMUFile *f, void *opaque, int version_id)
218 {
219     SSISlave *ss = SSI_SLAVE(opaque);
220     ssi_sd_state *s = (ssi_sd_state *)opaque;
221     int i;
222 
223     if (version_id != 1)
224         return -EINVAL;
225 
226     s->mode = qemu_get_be32(f);
227     s->cmd = qemu_get_be32(f);
228     for (i = 0; i < 4; i++)
229         s->cmdarg[i] = qemu_get_be32(f);
230     for (i = 0; i < 5; i++)
231         s->response[i] = qemu_get_be32(f);
232     s->arglen = qemu_get_be32(f);
233     s->response_pos = qemu_get_be32(f);
234     s->stopping = qemu_get_be32(f);
235 
236     ss->cs = qemu_get_be32(f);
237 
238     return 0;
239 }
240 
241 static int ssi_sd_init(SSISlave *dev)
242 {
243     ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, dev);
244     DriveInfo *dinfo;
245 
246     s->mode = SSI_SD_CMD;
247     dinfo = drive_get_next(IF_SD);
248     s->sd = sd_init(dinfo ? dinfo->bdrv : NULL, 1);
249     register_savevm(&dev->qdev, "ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s);
250     return 0;
251 }
252 
253 static void ssi_sd_class_init(ObjectClass *klass, void *data)
254 {
255     SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
256 
257     k->init = ssi_sd_init;
258     k->transfer = ssi_sd_transfer;
259     k->cs_polarity = SSI_CS_LOW;
260 }
261 
262 static const TypeInfo ssi_sd_info = {
263     .name          = "ssi-sd",
264     .parent        = TYPE_SSI_SLAVE,
265     .instance_size = sizeof(ssi_sd_state),
266     .class_init    = ssi_sd_class_init,
267 };
268 
269 static void ssi_sd_register_types(void)
270 {
271     type_register_static(&ssi_sd_info);
272 }
273 
274 type_init(ssi_sd_register_types)
275