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