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