xref: /openbmc/qemu/hw/sd/ssi-sd.c (revision e9e51b71)
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 "qemu/osdep.h"
14 #include "sysemu/blockdev.h"
15 #include "hw/ssi/ssi.h"
16 #include "migration/vmstate.h"
17 #include "hw/qdev-properties.h"
18 #include "hw/sd/sd.h"
19 #include "qapi/error.h"
20 #include "qemu/crc-ccitt.h"
21 #include "qemu/module.h"
22 #include "qom/object.h"
23 
24 //#define DEBUG_SSI_SD 1
25 
26 #ifdef DEBUG_SSI_SD
27 #define DPRINTF(fmt, ...) \
28 do { printf("ssi_sd: " fmt , ## __VA_ARGS__); } while (0)
29 #define BADF(fmt, ...) \
30 do { fprintf(stderr, "ssi_sd: error: " fmt , ## __VA_ARGS__); exit(1);} while (0)
31 #else
32 #define DPRINTF(fmt, ...) do {} while(0)
33 #define BADF(fmt, ...) \
34 do { fprintf(stderr, "ssi_sd: error: " fmt , ## __VA_ARGS__);} while (0)
35 #endif
36 
37 typedef enum {
38     SSI_SD_CMD = 0,
39     SSI_SD_CMDARG,
40     SSI_SD_PREP_RESP,
41     SSI_SD_RESPONSE,
42     SSI_SD_PREP_DATA,
43     SSI_SD_DATA_START,
44     SSI_SD_DATA_READ,
45     SSI_SD_DATA_CRC16,
46 } ssi_sd_mode;
47 
48 struct ssi_sd_state {
49     SSIPeripheral ssidev;
50     uint32_t mode;
51     int cmd;
52     uint8_t cmdarg[4];
53     uint8_t response[5];
54     uint16_t crc16;
55     int32_t arglen;
56     int32_t response_pos;
57     int32_t stopping;
58     SDBus sdbus;
59 };
60 
61 #define TYPE_SSI_SD "ssi-sd"
62 OBJECT_DECLARE_SIMPLE_TYPE(ssi_sd_state, SSI_SD)
63 
64 /* State word bits.  */
65 #define SSI_SDR_LOCKED          0x0001
66 #define SSI_SDR_WP_ERASE        0x0002
67 #define SSI_SDR_ERROR           0x0004
68 #define SSI_SDR_CC_ERROR        0x0008
69 #define SSI_SDR_ECC_FAILED      0x0010
70 #define SSI_SDR_WP_VIOLATION    0x0020
71 #define SSI_SDR_ERASE_PARAM     0x0040
72 #define SSI_SDR_OUT_OF_RANGE    0x0080
73 #define SSI_SDR_IDLE            0x0100
74 #define SSI_SDR_ERASE_RESET     0x0200
75 #define SSI_SDR_ILLEGAL_COMMAND 0x0400
76 #define SSI_SDR_COM_CRC_ERROR   0x0800
77 #define SSI_SDR_ERASE_SEQ_ERROR 0x1000
78 #define SSI_SDR_ADDRESS_ERROR   0x2000
79 #define SSI_SDR_PARAMETER_ERROR 0x4000
80 
81 /* single block read/write, multiple block read */
82 #define SSI_TOKEN_SINGLE        0xfe
83 
84 /* dummy value - don't care */
85 #define SSI_DUMMY               0xff
86 
87 static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val)
88 {
89     ssi_sd_state *s = SSI_SD(dev);
90 
91     /* Special case: allow CMD12 (STOP TRANSMISSION) while reading data.  */
92     if (s->mode == SSI_SD_DATA_READ && val == 0x4c) {
93         s->mode = SSI_SD_CMD;
94         /* There must be at least one byte delay before the card responds.  */
95         s->stopping = 1;
96     }
97 
98     switch (s->mode) {
99     case SSI_SD_CMD:
100         if (val == SSI_DUMMY) {
101             DPRINTF("NULL command\n");
102             return SSI_DUMMY;
103         }
104         s->cmd = val & 0x3f;
105         s->mode = SSI_SD_CMDARG;
106         s->arglen = 0;
107         return SSI_DUMMY;
108     case SSI_SD_CMDARG:
109         if (s->arglen == 4) {
110             SDRequest request;
111             uint8_t longresp[16];
112             /* FIXME: Check CRC.  */
113             request.cmd = s->cmd;
114             request.arg = ldl_be_p(s->cmdarg);
115             DPRINTF("CMD%d arg 0x%08x\n", s->cmd, request.arg);
116             s->arglen = sdbus_do_command(&s->sdbus, &request, longresp);
117             if (s->arglen <= 0) {
118                 s->arglen = 1;
119                 s->response[0] = 4;
120                 DPRINTF("SD command failed\n");
121             } else if (s->cmd == 58) {
122                 /* CMD58 returns R3 response (OCR)  */
123                 DPRINTF("Returned OCR\n");
124                 s->arglen = 5;
125                 s->response[0] = 1;
126                 memcpy(&s->response[1], longresp, 4);
127             } else if (s->arglen != 4) {
128                 BADF("Unexpected response to cmd %d\n", s->cmd);
129                 /* Illegal command is about as near as we can get.  */
130                 s->arglen = 1;
131                 s->response[0] = 4;
132             } else {
133                 /* All other commands return status.  */
134                 uint32_t cardstatus;
135                 uint16_t status;
136                 /* CMD13 returns a 2-byte statuse work. Other commands
137                    only return the first byte.  */
138                 s->arglen = (s->cmd == 13) ? 2 : 1;
139                 cardstatus = ldl_be_p(longresp);
140                 status = 0;
141                 if (((cardstatus >> 9) & 0xf) < 4)
142                     status |= SSI_SDR_IDLE;
143                 if (cardstatus & ERASE_RESET)
144                     status |= SSI_SDR_ERASE_RESET;
145                 if (cardstatus & ILLEGAL_COMMAND)
146                     status |= SSI_SDR_ILLEGAL_COMMAND;
147                 if (cardstatus & COM_CRC_ERROR)
148                     status |= SSI_SDR_COM_CRC_ERROR;
149                 if (cardstatus & ERASE_SEQ_ERROR)
150                     status |= SSI_SDR_ERASE_SEQ_ERROR;
151                 if (cardstatus & ADDRESS_ERROR)
152                     status |= SSI_SDR_ADDRESS_ERROR;
153                 if (cardstatus & CARD_IS_LOCKED)
154                     status |= SSI_SDR_LOCKED;
155                 if (cardstatus & (LOCK_UNLOCK_FAILED | WP_ERASE_SKIP))
156                     status |= SSI_SDR_WP_ERASE;
157                 if (cardstatus & SD_ERROR)
158                     status |= SSI_SDR_ERROR;
159                 if (cardstatus & CC_ERROR)
160                     status |= SSI_SDR_CC_ERROR;
161                 if (cardstatus & CARD_ECC_FAILED)
162                     status |= SSI_SDR_ECC_FAILED;
163                 if (cardstatus & WP_VIOLATION)
164                     status |= SSI_SDR_WP_VIOLATION;
165                 if (cardstatus & ERASE_PARAM)
166                     status |= SSI_SDR_ERASE_PARAM;
167                 if (cardstatus & (OUT_OF_RANGE | CID_CSD_OVERWRITE))
168                     status |= SSI_SDR_OUT_OF_RANGE;
169                 /* ??? Don't know what Parameter Error really means, so
170                    assume it's set if the second byte is nonzero.  */
171                 if (status & 0xff)
172                     status |= SSI_SDR_PARAMETER_ERROR;
173                 s->response[0] = status >> 8;
174                 s->response[1] = status;
175                 DPRINTF("Card status 0x%02x\n", status);
176             }
177             s->mode = SSI_SD_PREP_RESP;
178             s->response_pos = 0;
179         } else {
180             s->cmdarg[s->arglen++] = val;
181         }
182         return SSI_DUMMY;
183     case SSI_SD_PREP_RESP:
184         DPRINTF("Prepare card response (Ncr)\n");
185         s->mode = SSI_SD_RESPONSE;
186         return SSI_DUMMY;
187     case SSI_SD_RESPONSE:
188         if (s->stopping) {
189             s->stopping = 0;
190             return SSI_DUMMY;
191         }
192         if (s->response_pos < s->arglen) {
193             DPRINTF("Response 0x%02x\n", s->response[s->response_pos]);
194             return s->response[s->response_pos++];
195         }
196         if (sdbus_data_ready(&s->sdbus)) {
197             DPRINTF("Data read\n");
198             s->mode = SSI_SD_DATA_START;
199         } else {
200             DPRINTF("End of command\n");
201             s->mode = SSI_SD_CMD;
202         }
203         return SSI_DUMMY;
204     case SSI_SD_PREP_DATA:
205         DPRINTF("Prepare data block (Nac)\n");
206         s->mode = SSI_SD_DATA_START;
207         return SSI_DUMMY;
208     case SSI_SD_DATA_START:
209         DPRINTF("Start read block\n");
210         s->mode = SSI_SD_DATA_READ;
211         s->response_pos = 0;
212         return SSI_TOKEN_SINGLE;
213     case SSI_SD_DATA_READ:
214         val = sdbus_read_byte(&s->sdbus);
215         s->crc16 = crc_ccitt_false(s->crc16, (uint8_t *)&val, 1);
216         if (!sdbus_data_ready(&s->sdbus)) {
217             DPRINTF("Data read end\n");
218             s->mode = SSI_SD_DATA_CRC16;
219         }
220         return val;
221     case SSI_SD_DATA_CRC16:
222         val = (s->crc16 & 0xff00) >> 8;
223         s->crc16 <<= 8;
224         s->response_pos++;
225         if (s->response_pos == 2) {
226             DPRINTF("CRC16 read end\n");
227             s->mode = SSI_SD_CMD;
228             s->response_pos = 0;
229         }
230         return val;
231     }
232     /* Should never happen.  */
233     return SSI_DUMMY;
234 }
235 
236 static int ssi_sd_post_load(void *opaque, int version_id)
237 {
238     ssi_sd_state *s = (ssi_sd_state *)opaque;
239 
240     if (s->mode > SSI_SD_DATA_CRC16) {
241         return -EINVAL;
242     }
243     if (s->mode == SSI_SD_CMDARG &&
244         (s->arglen < 0 || s->arglen >= ARRAY_SIZE(s->cmdarg))) {
245         return -EINVAL;
246     }
247     if (s->mode == SSI_SD_RESPONSE &&
248         (s->response_pos < 0 || s->response_pos >= ARRAY_SIZE(s->response) ||
249         (!s->stopping && s->arglen > ARRAY_SIZE(s->response)))) {
250         return -EINVAL;
251     }
252 
253     return 0;
254 }
255 
256 static const VMStateDescription vmstate_ssi_sd = {
257     .name = "ssi_sd",
258     .version_id = 5,
259     .minimum_version_id = 5,
260     .post_load = ssi_sd_post_load,
261     .fields = (VMStateField []) {
262         VMSTATE_UINT32(mode, ssi_sd_state),
263         VMSTATE_INT32(cmd, ssi_sd_state),
264         VMSTATE_UINT8_ARRAY(cmdarg, ssi_sd_state, 4),
265         VMSTATE_UINT8_ARRAY(response, ssi_sd_state, 5),
266         VMSTATE_UINT16(crc16, ssi_sd_state),
267         VMSTATE_INT32(arglen, ssi_sd_state),
268         VMSTATE_INT32(response_pos, ssi_sd_state),
269         VMSTATE_INT32(stopping, ssi_sd_state),
270         VMSTATE_SSI_PERIPHERAL(ssidev, ssi_sd_state),
271         VMSTATE_END_OF_LIST()
272     }
273 };
274 
275 static void ssi_sd_realize(SSIPeripheral *d, Error **errp)
276 {
277     ERRP_GUARD();
278     ssi_sd_state *s = SSI_SD(d);
279     DeviceState *carddev;
280     DriveInfo *dinfo;
281 
282     qbus_create_inplace(&s->sdbus, sizeof(s->sdbus), TYPE_SD_BUS,
283                         DEVICE(d), "sd-bus");
284 
285     /* Create and plug in the sd card */
286     /* FIXME use a qdev drive property instead of drive_get_next() */
287     dinfo = drive_get_next(IF_SD);
288     carddev = qdev_new(TYPE_SD_CARD);
289     if (dinfo) {
290         if (!qdev_prop_set_drive_err(carddev, "drive",
291                                      blk_by_legacy_dinfo(dinfo), errp)) {
292             goto fail;
293         }
294     }
295 
296     if (!object_property_set_bool(OBJECT(carddev), "spi", true, errp)) {
297         goto fail;
298     }
299 
300     if (!qdev_realize_and_unref(carddev, BUS(&s->sdbus), errp)) {
301         goto fail;
302     }
303 
304     return;
305 
306 fail:
307     error_prepend(errp, "failed to init SD card: ");
308 }
309 
310 static void ssi_sd_reset(DeviceState *dev)
311 {
312     ssi_sd_state *s = SSI_SD(dev);
313 
314     s->mode = SSI_SD_CMD;
315     s->cmd = 0;
316     memset(s->cmdarg, 0, sizeof(s->cmdarg));
317     memset(s->response, 0, sizeof(s->response));
318     s->crc16 = 0;
319     s->arglen = 0;
320     s->response_pos = 0;
321     s->stopping = 0;
322 }
323 
324 static void ssi_sd_class_init(ObjectClass *klass, void *data)
325 {
326     DeviceClass *dc = DEVICE_CLASS(klass);
327     SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass);
328 
329     k->realize = ssi_sd_realize;
330     k->transfer = ssi_sd_transfer;
331     k->cs_polarity = SSI_CS_LOW;
332     dc->vmsd = &vmstate_ssi_sd;
333     dc->reset = ssi_sd_reset;
334     /* Reason: init() method uses drive_get_next() */
335     dc->user_creatable = false;
336 }
337 
338 static const TypeInfo ssi_sd_info = {
339     .name          = TYPE_SSI_SD,
340     .parent        = TYPE_SSI_PERIPHERAL,
341     .instance_size = sizeof(ssi_sd_state),
342     .class_init    = ssi_sd_class_init,
343 };
344 
345 static void ssi_sd_register_types(void)
346 {
347     type_register_static(&ssi_sd_info);
348 }
349 
350 type_init(ssi_sd_register_types)
351