1 /*
2 * OMAP on-chip MMC/SD host emulation.
3 *
4 * Datasheet: TI Multimedia Card (MMC/SD/SDIO) Interface (SPRU765A)
5 *
6 * Copyright (C) 2006-2007 Andrzej Zaborowski <balrog@zabor.org>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 or
11 * (at your option) version 3 of the License.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "qemu/osdep.h"
23 #include "qemu/log.h"
24 #include "hw/irq.h"
25 #include "hw/arm/omap.h"
26 #include "hw/sd/sdcard_legacy.h"
27
28 struct omap_mmc_s {
29 qemu_irq irq;
30 qemu_irq *dma;
31 qemu_irq coverswitch;
32 MemoryRegion iomem;
33 omap_clk clk;
34 SDState *card;
35 uint16_t last_cmd;
36 uint16_t sdio;
37 uint16_t rsp[8];
38 uint32_t arg;
39 int lines;
40 int dw;
41 int mode;
42 int enable;
43 int be;
44 int rev;
45 uint16_t status;
46 uint16_t mask;
47 uint8_t cto;
48 uint16_t dto;
49 int clkdiv;
50 uint16_t fifo[32];
51 int fifo_start;
52 int fifo_len;
53 uint16_t blen;
54 uint16_t blen_counter;
55 uint16_t nblk;
56 uint16_t nblk_counter;
57 int tx_dma;
58 int rx_dma;
59 int af_level;
60 int ae_level;
61
62 int ddir;
63 int transfer;
64
65 int cdet_wakeup;
66 int cdet_enable;
67 int cdet_state;
68 qemu_irq cdet;
69 };
70
omap_mmc_interrupts_update(struct omap_mmc_s * s)71 static void omap_mmc_interrupts_update(struct omap_mmc_s *s)
72 {
73 qemu_set_irq(s->irq, !!(s->status & s->mask));
74 }
75
omap_mmc_fifolevel_update(struct omap_mmc_s * host)76 static void omap_mmc_fifolevel_update(struct omap_mmc_s *host)
77 {
78 if (!host->transfer && !host->fifo_len) {
79 host->status &= 0xf3ff;
80 return;
81 }
82
83 if (host->fifo_len > host->af_level && host->ddir) {
84 if (host->rx_dma) {
85 host->status &= 0xfbff;
86 qemu_irq_raise(host->dma[1]);
87 } else
88 host->status |= 0x0400;
89 } else {
90 host->status &= 0xfbff;
91 qemu_irq_lower(host->dma[1]);
92 }
93
94 if (host->fifo_len < host->ae_level && !host->ddir) {
95 if (host->tx_dma) {
96 host->status &= 0xf7ff;
97 qemu_irq_raise(host->dma[0]);
98 } else
99 host->status |= 0x0800;
100 } else {
101 qemu_irq_lower(host->dma[0]);
102 host->status &= 0xf7ff;
103 }
104 }
105
106 /* These must match the encoding of the MMC_CMD Response field */
107 typedef enum {
108 sd_nore = 0, /* no response */
109 sd_r1, /* normal response command */
110 sd_r2, /* CID, CSD registers */
111 sd_r3, /* OCR register */
112 sd_r6 = 6, /* Published RCA response */
113 sd_r1b = -1,
114 } sd_rsp_type_t;
115
116 /* These must match the encoding of the MMC_CMD Type field */
117 typedef enum {
118 SD_TYPE_BC = 0, /* broadcast -- no response */
119 SD_TYPE_BCR = 1, /* broadcast with response */
120 SD_TYPE_AC = 2, /* addressed -- no data transfer */
121 SD_TYPE_ADTC = 3, /* addressed with data transfer */
122 } MMCCmdType;
123
omap_mmc_command(struct omap_mmc_s * host,int cmd,int dir,MMCCmdType type,int busy,sd_rsp_type_t resptype,int init)124 static void omap_mmc_command(struct omap_mmc_s *host, int cmd, int dir,
125 MMCCmdType type, int busy,
126 sd_rsp_type_t resptype, int init)
127 {
128 uint32_t rspstatus, mask;
129 int rsplen, timeout;
130 SDRequest request;
131 uint8_t response[16];
132
133 if (init && cmd == 0) {
134 host->status |= 0x0001;
135 return;
136 }
137
138 if (resptype == sd_r1 && busy)
139 resptype = sd_r1b;
140
141 if (type == SD_TYPE_ADTC) {
142 host->fifo_start = 0;
143 host->fifo_len = 0;
144 host->transfer = 1;
145 host->ddir = dir;
146 } else
147 host->transfer = 0;
148 timeout = 0;
149 mask = 0;
150 rspstatus = 0;
151
152 request.cmd = cmd;
153 request.arg = host->arg;
154 request.crc = 0; /* FIXME */
155
156 rsplen = sd_do_command(host->card, &request, response);
157
158 /* TODO: validate CRCs */
159 switch (resptype) {
160 case sd_nore:
161 rsplen = 0;
162 break;
163
164 case sd_r1:
165 case sd_r1b:
166 if (rsplen < 4) {
167 timeout = 1;
168 break;
169 }
170 rsplen = 4;
171
172 mask = OUT_OF_RANGE | ADDRESS_ERROR | BLOCK_LEN_ERROR |
173 ERASE_SEQ_ERROR | ERASE_PARAM | WP_VIOLATION |
174 LOCK_UNLOCK_FAILED | COM_CRC_ERROR | ILLEGAL_COMMAND |
175 CARD_ECC_FAILED | CC_ERROR | SD_ERROR |
176 CID_CSD_OVERWRITE;
177 if (host->sdio & (1 << 13))
178 mask |= AKE_SEQ_ERROR;
179 rspstatus = ldl_be_p(response);
180 break;
181
182 case sd_r2:
183 if (rsplen < 16) {
184 timeout = 1;
185 break;
186 }
187 rsplen = 16;
188 break;
189
190 case sd_r3:
191 if (rsplen < 4) {
192 timeout = 1;
193 break;
194 }
195 rsplen = 4;
196
197 rspstatus = ldl_be_p(response);
198 if (rspstatus & 0x80000000)
199 host->status &= 0xe000;
200 else
201 host->status |= 0x1000;
202 break;
203
204 case sd_r6:
205 if (rsplen < 4) {
206 timeout = 1;
207 break;
208 }
209 rsplen = 4;
210
211 mask = 0xe000 | AKE_SEQ_ERROR;
212 rspstatus = (response[2] << 8) | (response[3] << 0);
213 }
214
215 if (rspstatus & mask)
216 host->status |= 0x4000;
217 else
218 host->status &= 0xb000;
219
220 if (rsplen)
221 for (rsplen = 0; rsplen < 8; rsplen ++)
222 host->rsp[~rsplen & 7] = response[(rsplen << 1) | 1] |
223 (response[(rsplen << 1) | 0] << 8);
224
225 if (timeout)
226 host->status |= 0x0080;
227 else if (cmd == 12)
228 host->status |= 0x0005; /* Makes it more real */
229 else
230 host->status |= 0x0001;
231 }
232
omap_mmc_transfer(struct omap_mmc_s * host)233 static void omap_mmc_transfer(struct omap_mmc_s *host)
234 {
235 uint8_t value;
236
237 if (!host->transfer)
238 return;
239
240 while (1) {
241 if (host->ddir) {
242 if (host->fifo_len > host->af_level)
243 break;
244
245 value = sd_read_byte(host->card);
246 host->fifo[(host->fifo_start + host->fifo_len) & 31] = value;
247 if (-- host->blen_counter) {
248 value = sd_read_byte(host->card);
249 host->fifo[(host->fifo_start + host->fifo_len) & 31] |=
250 value << 8;
251 host->blen_counter --;
252 }
253
254 host->fifo_len ++;
255 } else {
256 if (!host->fifo_len)
257 break;
258
259 value = host->fifo[host->fifo_start] & 0xff;
260 sd_write_byte(host->card, value);
261 if (-- host->blen_counter) {
262 value = host->fifo[host->fifo_start] >> 8;
263 sd_write_byte(host->card, value);
264 host->blen_counter --;
265 }
266
267 host->fifo_start ++;
268 host->fifo_len --;
269 host->fifo_start &= 31;
270 }
271
272 if (host->blen_counter == 0) {
273 host->nblk_counter --;
274 host->blen_counter = host->blen;
275
276 if (host->nblk_counter == 0) {
277 host->nblk_counter = host->nblk;
278 host->transfer = 0;
279 host->status |= 0x0008;
280 break;
281 }
282 }
283 }
284 }
285
omap_mmc_update(void * opaque)286 static void omap_mmc_update(void *opaque)
287 {
288 struct omap_mmc_s *s = opaque;
289 omap_mmc_transfer(s);
290 omap_mmc_fifolevel_update(s);
291 omap_mmc_interrupts_update(s);
292 }
293
omap_mmc_pseudo_reset(struct omap_mmc_s * host)294 static void omap_mmc_pseudo_reset(struct omap_mmc_s *host)
295 {
296 host->status = 0;
297 host->fifo_len = 0;
298 }
299
omap_mmc_reset(struct omap_mmc_s * host)300 void omap_mmc_reset(struct omap_mmc_s *host)
301 {
302 host->last_cmd = 0;
303 memset(host->rsp, 0, sizeof(host->rsp));
304 host->arg = 0;
305 host->dw = 0;
306 host->mode = 0;
307 host->enable = 0;
308 host->mask = 0;
309 host->cto = 0;
310 host->dto = 0;
311 host->blen = 0;
312 host->blen_counter = 0;
313 host->nblk = 0;
314 host->nblk_counter = 0;
315 host->tx_dma = 0;
316 host->rx_dma = 0;
317 host->ae_level = 0x00;
318 host->af_level = 0x1f;
319 host->transfer = 0;
320 host->cdet_wakeup = 0;
321 host->cdet_enable = 0;
322 qemu_set_irq(host->coverswitch, host->cdet_state);
323 host->clkdiv = 0;
324
325 omap_mmc_pseudo_reset(host);
326
327 /* Since we're still using the legacy SD API the card is not plugged
328 * into any bus, and we must reset it manually. When omap_mmc is
329 * QOMified this must move into the QOM reset function.
330 */
331 device_cold_reset(DEVICE(host->card));
332 }
333
omap_mmc_read(void * opaque,hwaddr offset,unsigned size)334 static uint64_t omap_mmc_read(void *opaque, hwaddr offset, unsigned size)
335 {
336 uint16_t i;
337 struct omap_mmc_s *s = opaque;
338
339 if (size != 2) {
340 return omap_badwidth_read16(opaque, offset);
341 }
342
343 switch (offset) {
344 case 0x00: /* MMC_CMD */
345 return s->last_cmd;
346
347 case 0x04: /* MMC_ARGL */
348 return s->arg & 0x0000ffff;
349
350 case 0x08: /* MMC_ARGH */
351 return s->arg >> 16;
352
353 case 0x0c: /* MMC_CON */
354 return (s->dw << 15) | (s->mode << 12) | (s->enable << 11) |
355 (s->be << 10) | s->clkdiv;
356
357 case 0x10: /* MMC_STAT */
358 return s->status;
359
360 case 0x14: /* MMC_IE */
361 return s->mask;
362
363 case 0x18: /* MMC_CTO */
364 return s->cto;
365
366 case 0x1c: /* MMC_DTO */
367 return s->dto;
368
369 case 0x20: /* MMC_DATA */
370 /* TODO: support 8-bit access */
371 i = s->fifo[s->fifo_start];
372 if (s->fifo_len == 0) {
373 printf("MMC: FIFO underrun\n");
374 return i;
375 }
376 s->fifo_start ++;
377 s->fifo_len --;
378 s->fifo_start &= 31;
379 omap_mmc_transfer(s);
380 omap_mmc_fifolevel_update(s);
381 omap_mmc_interrupts_update(s);
382 return i;
383
384 case 0x24: /* MMC_BLEN */
385 return s->blen_counter;
386
387 case 0x28: /* MMC_NBLK */
388 return s->nblk_counter;
389
390 case 0x2c: /* MMC_BUF */
391 return (s->rx_dma << 15) | (s->af_level << 8) |
392 (s->tx_dma << 7) | s->ae_level;
393
394 case 0x30: /* MMC_SPI */
395 return 0x0000;
396 case 0x34: /* MMC_SDIO */
397 return (s->cdet_wakeup << 2) | (s->cdet_enable) | s->sdio;
398 case 0x38: /* MMC_SYST */
399 return 0x0000;
400
401 case 0x3c: /* MMC_REV */
402 return s->rev;
403
404 case 0x40: /* MMC_RSP0 */
405 case 0x44: /* MMC_RSP1 */
406 case 0x48: /* MMC_RSP2 */
407 case 0x4c: /* MMC_RSP3 */
408 case 0x50: /* MMC_RSP4 */
409 case 0x54: /* MMC_RSP5 */
410 case 0x58: /* MMC_RSP6 */
411 case 0x5c: /* MMC_RSP7 */
412 return s->rsp[(offset - 0x40) >> 2];
413
414 /* OMAP2-specific */
415 case 0x60: /* MMC_IOSR */
416 case 0x64: /* MMC_SYSC */
417 return 0;
418 case 0x68: /* MMC_SYSS */
419 return 1; /* RSTD */
420 }
421
422 OMAP_BAD_REG(offset);
423 return 0;
424 }
425
omap_mmc_write(void * opaque,hwaddr offset,uint64_t value,unsigned size)426 static void omap_mmc_write(void *opaque, hwaddr offset,
427 uint64_t value, unsigned size)
428 {
429 int i;
430 struct omap_mmc_s *s = opaque;
431
432 if (size != 2) {
433 omap_badwidth_write16(opaque, offset, value);
434 return;
435 }
436
437 switch (offset) {
438 case 0x00: /* MMC_CMD */
439 if (!s->enable)
440 break;
441
442 s->last_cmd = value;
443 for (i = 0; i < 8; i ++)
444 s->rsp[i] = 0x0000;
445 omap_mmc_command(s, value & 63, (value >> 15) & 1,
446 (MMCCmdType)((value >> 12) & 3),
447 (value >> 11) & 1,
448 (sd_rsp_type_t) ((value >> 8) & 7),
449 (value >> 7) & 1);
450 omap_mmc_update(s);
451 break;
452
453 case 0x04: /* MMC_ARGL */
454 s->arg &= 0xffff0000;
455 s->arg |= 0x0000ffff & value;
456 break;
457
458 case 0x08: /* MMC_ARGH */
459 s->arg &= 0x0000ffff;
460 s->arg |= value << 16;
461 break;
462
463 case 0x0c: /* MMC_CON */
464 s->dw = (value >> 15) & 1;
465 s->mode = (value >> 12) & 3;
466 s->enable = (value >> 11) & 1;
467 s->be = (value >> 10) & 1;
468 s->clkdiv = (value >> 0) & (s->rev >= 2 ? 0x3ff : 0xff);
469 if (s->mode != 0) {
470 qemu_log_mask(LOG_UNIMP,
471 "omap_mmc_wr: mode #%i unimplemented\n", s->mode);
472 }
473 if (s->be != 0) {
474 qemu_log_mask(LOG_UNIMP,
475 "omap_mmc_wr: Big Endian not implemented\n");
476 }
477 if (s->dw != 0 && s->lines < 4)
478 printf("4-bit SD bus enabled\n");
479 if (!s->enable)
480 omap_mmc_pseudo_reset(s);
481 break;
482
483 case 0x10: /* MMC_STAT */
484 s->status &= ~value;
485 omap_mmc_interrupts_update(s);
486 break;
487
488 case 0x14: /* MMC_IE */
489 s->mask = value & 0x7fff;
490 omap_mmc_interrupts_update(s);
491 break;
492
493 case 0x18: /* MMC_CTO */
494 s->cto = value & 0xff;
495 if (s->cto > 0xfd && s->rev <= 1)
496 printf("MMC: CTO of 0xff and 0xfe cannot be used!\n");
497 break;
498
499 case 0x1c: /* MMC_DTO */
500 s->dto = value & 0xffff;
501 break;
502
503 case 0x20: /* MMC_DATA */
504 /* TODO: support 8-bit access */
505 if (s->fifo_len == 32)
506 break;
507 s->fifo[(s->fifo_start + s->fifo_len) & 31] = value;
508 s->fifo_len ++;
509 omap_mmc_transfer(s);
510 omap_mmc_fifolevel_update(s);
511 omap_mmc_interrupts_update(s);
512 break;
513
514 case 0x24: /* MMC_BLEN */
515 s->blen = (value & 0x07ff) + 1;
516 s->blen_counter = s->blen;
517 break;
518
519 case 0x28: /* MMC_NBLK */
520 s->nblk = (value & 0x07ff) + 1;
521 s->nblk_counter = s->nblk;
522 s->blen_counter = s->blen;
523 break;
524
525 case 0x2c: /* MMC_BUF */
526 s->rx_dma = (value >> 15) & 1;
527 s->af_level = (value >> 8) & 0x1f;
528 s->tx_dma = (value >> 7) & 1;
529 s->ae_level = value & 0x1f;
530
531 if (s->rx_dma)
532 s->status &= 0xfbff;
533 if (s->tx_dma)
534 s->status &= 0xf7ff;
535 omap_mmc_fifolevel_update(s);
536 omap_mmc_interrupts_update(s);
537 break;
538
539 /* SPI, SDIO and TEST modes unimplemented */
540 case 0x30: /* MMC_SPI (OMAP1 only) */
541 break;
542 case 0x34: /* MMC_SDIO */
543 s->sdio = value & (s->rev >= 2 ? 0xfbf3 : 0x2020);
544 s->cdet_wakeup = (value >> 9) & 1;
545 s->cdet_enable = (value >> 2) & 1;
546 break;
547 case 0x38: /* MMC_SYST */
548 break;
549
550 case 0x3c: /* MMC_REV */
551 case 0x40: /* MMC_RSP0 */
552 case 0x44: /* MMC_RSP1 */
553 case 0x48: /* MMC_RSP2 */
554 case 0x4c: /* MMC_RSP3 */
555 case 0x50: /* MMC_RSP4 */
556 case 0x54: /* MMC_RSP5 */
557 case 0x58: /* MMC_RSP6 */
558 case 0x5c: /* MMC_RSP7 */
559 OMAP_RO_REG(offset);
560 break;
561
562 /* OMAP2-specific */
563 case 0x60: /* MMC_IOSR */
564 if (value & 0xf)
565 printf("MMC: SDIO bits used!\n");
566 break;
567 case 0x64: /* MMC_SYSC */
568 if (value & (1 << 2)) /* SRTS */
569 omap_mmc_reset(s);
570 break;
571 case 0x68: /* MMC_SYSS */
572 OMAP_RO_REG(offset);
573 break;
574
575 default:
576 OMAP_BAD_REG(offset);
577 }
578 }
579
580 static const MemoryRegionOps omap_mmc_ops = {
581 .read = omap_mmc_read,
582 .write = omap_mmc_write,
583 .endianness = DEVICE_NATIVE_ENDIAN,
584 };
585
omap_mmc_init(hwaddr base,MemoryRegion * sysmem,BlockBackend * blk,qemu_irq irq,qemu_irq dma[],omap_clk clk)586 struct omap_mmc_s *omap_mmc_init(hwaddr base,
587 MemoryRegion *sysmem,
588 BlockBackend *blk,
589 qemu_irq irq, qemu_irq dma[], omap_clk clk)
590 {
591 struct omap_mmc_s *s = g_new0(struct omap_mmc_s, 1);
592
593 s->irq = irq;
594 s->dma = dma;
595 s->clk = clk;
596 s->lines = 1; /* TODO: needs to be settable per-board */
597 s->rev = 1;
598
599 memory_region_init_io(&s->iomem, NULL, &omap_mmc_ops, s, "omap.mmc", 0x800);
600 memory_region_add_subregion(sysmem, base, &s->iomem);
601
602 /* Instantiate the storage */
603 s->card = sd_init(blk, false);
604 if (s->card == NULL) {
605 exit(1);
606 }
607
608 omap_mmc_reset(s);
609
610 return s;
611 }
612