qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

pxa2xx_mmci.c (16259B)


      1 /*
      2  * Intel XScale PXA255/270 MultiMediaCard/SD/SDIO Controller emulation.
      3  *
      4  * Copyright (c) 2006 Openedhand Ltd.
      5  * Written by Andrzej Zaborowski <balrog@zabor.org>
      6  *
      7  * This code is licensed under the GPLv2.
      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 "qapi/error.h"
     15 #include "hw/irq.h"
     16 #include "hw/sysbus.h"
     17 #include "migration/vmstate.h"
     18 #include "hw/arm/pxa.h"
     19 #include "hw/sd/sd.h"
     20 #include "hw/qdev-properties.h"
     21 #include "qemu/log.h"
     22 #include "qemu/module.h"
     23 #include "trace.h"
     24 #include "qom/object.h"
     25 
     26 #define TYPE_PXA2XX_MMCI_BUS "pxa2xx-mmci-bus"
     27 /* This is reusing the SDBus typedef from SD_BUS */
     28 DECLARE_INSTANCE_CHECKER(SDBus, PXA2XX_MMCI_BUS,
     29                          TYPE_PXA2XX_MMCI_BUS)
     30 
     31 struct PXA2xxMMCIState {
     32     SysBusDevice parent_obj;
     33 
     34     MemoryRegion iomem;
     35     qemu_irq irq;
     36     qemu_irq rx_dma;
     37     qemu_irq tx_dma;
     38     qemu_irq inserted;
     39     qemu_irq readonly;
     40 
     41     BlockBackend *blk;
     42     SDBus sdbus;
     43 
     44     uint32_t status;
     45     uint32_t clkrt;
     46     uint32_t spi;
     47     uint32_t cmdat;
     48     uint32_t resp_tout;
     49     uint32_t read_tout;
     50     int32_t blklen;
     51     int32_t numblk;
     52     uint32_t intmask;
     53     uint32_t intreq;
     54     int32_t cmd;
     55     uint32_t arg;
     56 
     57     int32_t active;
     58     int32_t bytesleft;
     59     uint8_t tx_fifo[64];
     60     uint32_t tx_start;
     61     uint32_t tx_len;
     62     uint8_t rx_fifo[32];
     63     uint32_t rx_start;
     64     uint32_t rx_len;
     65     uint16_t resp_fifo[9];
     66     uint32_t resp_len;
     67 
     68     int32_t cmdreq;
     69 };
     70 
     71 static bool pxa2xx_mmci_vmstate_validate(void *opaque, int version_id)
     72 {
     73     PXA2xxMMCIState *s = opaque;
     74 
     75     return s->tx_start < ARRAY_SIZE(s->tx_fifo)
     76         && s->rx_start < ARRAY_SIZE(s->rx_fifo)
     77         && s->tx_len <= ARRAY_SIZE(s->tx_fifo)
     78         && s->rx_len <= ARRAY_SIZE(s->rx_fifo)
     79         && s->resp_len <= ARRAY_SIZE(s->resp_fifo);
     80 }
     81 
     82 
     83 static const VMStateDescription vmstate_pxa2xx_mmci = {
     84     .name = "pxa2xx-mmci",
     85     .version_id = 2,
     86     .minimum_version_id = 2,
     87     .fields = (VMStateField[]) {
     88         VMSTATE_UINT32(status, PXA2xxMMCIState),
     89         VMSTATE_UINT32(clkrt, PXA2xxMMCIState),
     90         VMSTATE_UINT32(spi, PXA2xxMMCIState),
     91         VMSTATE_UINT32(cmdat, PXA2xxMMCIState),
     92         VMSTATE_UINT32(resp_tout, PXA2xxMMCIState),
     93         VMSTATE_UINT32(read_tout, PXA2xxMMCIState),
     94         VMSTATE_INT32(blklen, PXA2xxMMCIState),
     95         VMSTATE_INT32(numblk, PXA2xxMMCIState),
     96         VMSTATE_UINT32(intmask, PXA2xxMMCIState),
     97         VMSTATE_UINT32(intreq, PXA2xxMMCIState),
     98         VMSTATE_INT32(cmd, PXA2xxMMCIState),
     99         VMSTATE_UINT32(arg, PXA2xxMMCIState),
    100         VMSTATE_INT32(cmdreq, PXA2xxMMCIState),
    101         VMSTATE_INT32(active, PXA2xxMMCIState),
    102         VMSTATE_INT32(bytesleft, PXA2xxMMCIState),
    103         VMSTATE_UINT32(tx_start, PXA2xxMMCIState),
    104         VMSTATE_UINT32(tx_len, PXA2xxMMCIState),
    105         VMSTATE_UINT32(rx_start, PXA2xxMMCIState),
    106         VMSTATE_UINT32(rx_len, PXA2xxMMCIState),
    107         VMSTATE_UINT32(resp_len, PXA2xxMMCIState),
    108         VMSTATE_VALIDATE("fifo size incorrect", pxa2xx_mmci_vmstate_validate),
    109         VMSTATE_UINT8_ARRAY(tx_fifo, PXA2xxMMCIState, 64),
    110         VMSTATE_UINT8_ARRAY(rx_fifo, PXA2xxMMCIState, 32),
    111         VMSTATE_UINT16_ARRAY(resp_fifo, PXA2xxMMCIState, 9),
    112         VMSTATE_END_OF_LIST()
    113     }
    114 };
    115 
    116 #define MMC_STRPCL	0x00	/* MMC Clock Start/Stop register */
    117 #define MMC_STAT	0x04	/* MMC Status register */
    118 #define MMC_CLKRT	0x08	/* MMC Clock Rate register */
    119 #define MMC_SPI		0x0c	/* MMC SPI Mode register */
    120 #define MMC_CMDAT	0x10	/* MMC Command/Data register */
    121 #define MMC_RESTO	0x14	/* MMC Response Time-Out register */
    122 #define MMC_RDTO	0x18	/* MMC Read Time-Out register */
    123 #define MMC_BLKLEN	0x1c	/* MMC Block Length register */
    124 #define MMC_NUMBLK	0x20	/* MMC Number of Blocks register */
    125 #define MMC_PRTBUF	0x24	/* MMC Buffer Partly Full register */
    126 #define MMC_I_MASK	0x28	/* MMC Interrupt Mask register */
    127 #define MMC_I_REG	0x2c	/* MMC Interrupt Request register */
    128 #define MMC_CMD		0x30	/* MMC Command register */
    129 #define MMC_ARGH	0x34	/* MMC Argument High register */
    130 #define MMC_ARGL	0x38	/* MMC Argument Low register */
    131 #define MMC_RES		0x3c	/* MMC Response FIFO */
    132 #define MMC_RXFIFO	0x40	/* MMC Receive FIFO */
    133 #define MMC_TXFIFO	0x44	/* MMC Transmit FIFO */
    134 #define MMC_RDWAIT	0x48	/* MMC RD_WAIT register */
    135 #define MMC_BLKS_REM	0x4c	/* MMC Blocks Remaining register */
    136 
    137 /* Bitfield masks */
    138 #define STRPCL_STOP_CLK	(1 << 0)
    139 #define STRPCL_STRT_CLK	(1 << 1)
    140 #define STAT_TOUT_RES	(1 << 1)
    141 #define STAT_CLK_EN	(1 << 8)
    142 #define STAT_DATA_DONE	(1 << 11)
    143 #define STAT_PRG_DONE	(1 << 12)
    144 #define STAT_END_CMDRES	(1 << 13)
    145 #define SPI_SPI_MODE	(1 << 0)
    146 #define CMDAT_RES_TYPE	(3 << 0)
    147 #define CMDAT_DATA_EN	(1 << 2)
    148 #define CMDAT_WR_RD	(1 << 3)
    149 #define CMDAT_DMA_EN	(1 << 7)
    150 #define CMDAT_STOP_TRAN	(1 << 10)
    151 #define INT_DATA_DONE	(1 << 0)
    152 #define INT_PRG_DONE	(1 << 1)
    153 #define INT_END_CMD	(1 << 2)
    154 #define INT_STOP_CMD	(1 << 3)
    155 #define INT_CLK_OFF	(1 << 4)
    156 #define INT_RXFIFO_REQ	(1 << 5)
    157 #define INT_TXFIFO_REQ	(1 << 6)
    158 #define INT_TINT	(1 << 7)
    159 #define INT_DAT_ERR	(1 << 8)
    160 #define INT_RES_ERR	(1 << 9)
    161 #define INT_RD_STALLED	(1 << 10)
    162 #define INT_SDIO_INT	(1 << 11)
    163 #define INT_SDIO_SACK	(1 << 12)
    164 #define PRTBUF_PRT_BUF	(1 << 0)
    165 
    166 /* Route internal interrupt lines to the global IC and DMA */
    167 static void pxa2xx_mmci_int_update(PXA2xxMMCIState *s)
    168 {
    169     uint32_t mask = s->intmask;
    170     if (s->cmdat & CMDAT_DMA_EN) {
    171         mask |= INT_RXFIFO_REQ | INT_TXFIFO_REQ;
    172 
    173         qemu_set_irq(s->rx_dma, !!(s->intreq & INT_RXFIFO_REQ));
    174         qemu_set_irq(s->tx_dma, !!(s->intreq & INT_TXFIFO_REQ));
    175     }
    176 
    177     qemu_set_irq(s->irq, !!(s->intreq & ~mask));
    178 }
    179 
    180 static void pxa2xx_mmci_fifo_update(PXA2xxMMCIState *s)
    181 {
    182     if (!s->active)
    183         return;
    184 
    185     if (s->cmdat & CMDAT_WR_RD) {
    186         while (s->bytesleft && s->tx_len) {
    187             sdbus_write_byte(&s->sdbus, s->tx_fifo[s->tx_start++]);
    188             s->tx_start &= 0x1f;
    189             s->tx_len --;
    190             s->bytesleft --;
    191         }
    192         if (s->bytesleft)
    193             s->intreq |= INT_TXFIFO_REQ;
    194     } else
    195         while (s->bytesleft && s->rx_len < 32) {
    196             s->rx_fifo[(s->rx_start + (s->rx_len ++)) & 0x1f] =
    197                 sdbus_read_byte(&s->sdbus);
    198             s->bytesleft --;
    199             s->intreq |= INT_RXFIFO_REQ;
    200         }
    201 
    202     if (!s->bytesleft) {
    203         s->active = 0;
    204         s->intreq |= INT_DATA_DONE;
    205         s->status |= STAT_DATA_DONE;
    206 
    207         if (s->cmdat & CMDAT_WR_RD) {
    208             s->intreq |= INT_PRG_DONE;
    209             s->status |= STAT_PRG_DONE;
    210         }
    211     }
    212 
    213     pxa2xx_mmci_int_update(s);
    214 }
    215 
    216 static void pxa2xx_mmci_wakequeues(PXA2xxMMCIState *s)
    217 {
    218     int rsplen, i;
    219     SDRequest request;
    220     uint8_t response[16];
    221 
    222     s->active = 1;
    223     s->rx_len = 0;
    224     s->tx_len = 0;
    225     s->cmdreq = 0;
    226 
    227     request.cmd = s->cmd;
    228     request.arg = s->arg;
    229     request.crc = 0;	/* FIXME */
    230 
    231     rsplen = sdbus_do_command(&s->sdbus, &request, response);
    232     s->intreq |= INT_END_CMD;
    233 
    234     memset(s->resp_fifo, 0, sizeof(s->resp_fifo));
    235     switch (s->cmdat & CMDAT_RES_TYPE) {
    236 #define PXAMMCI_RESP(wd, value0, value1)	\
    237         s->resp_fifo[(wd) + 0] |= (value0);	\
    238         s->resp_fifo[(wd) + 1] |= (value1) << 8;
    239     case 0:	/* No response */
    240         goto complete;
    241 
    242     case 1:	/* R1, R4, R5 or R6 */
    243         if (rsplen < 4)
    244             goto timeout;
    245         goto complete;
    246 
    247     case 2:	/* R2 */
    248         if (rsplen < 16)
    249             goto timeout;
    250         goto complete;
    251 
    252     case 3:	/* R3 */
    253         if (rsplen < 4)
    254             goto timeout;
    255         goto complete;
    256 
    257     complete:
    258         for (i = 0; rsplen > 0; i ++, rsplen -= 2) {
    259             PXAMMCI_RESP(i, response[i * 2], response[i * 2 + 1]);
    260         }
    261         s->status |= STAT_END_CMDRES;
    262 
    263         if (!(s->cmdat & CMDAT_DATA_EN))
    264             s->active = 0;
    265         else
    266             s->bytesleft = s->numblk * s->blklen;
    267 
    268         s->resp_len = 0;
    269         break;
    270 
    271     timeout:
    272         s->active = 0;
    273         s->status |= STAT_TOUT_RES;
    274         break;
    275     }
    276 
    277     pxa2xx_mmci_fifo_update(s);
    278 }
    279 
    280 static uint64_t pxa2xx_mmci_read(void *opaque, hwaddr offset, unsigned size)
    281 {
    282     PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
    283     uint32_t ret = 0;
    284 
    285     switch (offset) {
    286     case MMC_STRPCL:
    287         break;
    288     case MMC_STAT:
    289         ret = s->status;
    290         break;
    291     case MMC_CLKRT:
    292         ret = s->clkrt;
    293         break;
    294     case MMC_SPI:
    295         ret = s->spi;
    296         break;
    297     case MMC_CMDAT:
    298         ret = s->cmdat;
    299         break;
    300     case MMC_RESTO:
    301         ret = s->resp_tout;
    302         break;
    303     case MMC_RDTO:
    304         ret = s->read_tout;
    305         break;
    306     case MMC_BLKLEN:
    307         ret = s->blklen;
    308         break;
    309     case MMC_NUMBLK:
    310         ret = s->numblk;
    311         break;
    312     case MMC_PRTBUF:
    313         break;
    314     case MMC_I_MASK:
    315         ret = s->intmask;
    316         break;
    317     case MMC_I_REG:
    318         ret = s->intreq;
    319         break;
    320     case MMC_CMD:
    321         ret = s->cmd | 0x40;
    322         break;
    323     case MMC_ARGH:
    324         ret = s->arg >> 16;
    325         break;
    326     case MMC_ARGL:
    327         ret = s->arg & 0xffff;
    328         break;
    329     case MMC_RES:
    330         ret = (s->resp_len < 9) ? s->resp_fifo[s->resp_len++] : 0;
    331         break;
    332     case MMC_RXFIFO:
    333         while (size-- && s->rx_len) {
    334             ret |= s->rx_fifo[s->rx_start++] << (size << 3);
    335             s->rx_start &= 0x1f;
    336             s->rx_len --;
    337         }
    338         s->intreq &= ~INT_RXFIFO_REQ;
    339         pxa2xx_mmci_fifo_update(s);
    340         break;
    341     case MMC_RDWAIT:
    342         break;
    343     case MMC_BLKS_REM:
    344         ret = s->numblk;
    345         break;
    346     default:
    347         qemu_log_mask(LOG_GUEST_ERROR,
    348                       "%s: incorrect register 0x%02" HWADDR_PRIx "\n",
    349                       __func__, offset);
    350     }
    351     trace_pxa2xx_mmci_read(size, offset, ret);
    352 
    353     return ret;
    354 }
    355 
    356 static void pxa2xx_mmci_write(void *opaque,
    357                               hwaddr offset, uint64_t value, unsigned size)
    358 {
    359     PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
    360 
    361     trace_pxa2xx_mmci_write(size, offset, value);
    362     switch (offset) {
    363     case MMC_STRPCL:
    364         if (value & STRPCL_STRT_CLK) {
    365             s->status |= STAT_CLK_EN;
    366             s->intreq &= ~INT_CLK_OFF;
    367 
    368             if (s->cmdreq && !(s->cmdat & CMDAT_STOP_TRAN)) {
    369                 s->status &= STAT_CLK_EN;
    370                 pxa2xx_mmci_wakequeues(s);
    371             }
    372         }
    373 
    374         if (value & STRPCL_STOP_CLK) {
    375             s->status &= ~STAT_CLK_EN;
    376             s->intreq |= INT_CLK_OFF;
    377             s->active = 0;
    378         }
    379 
    380         pxa2xx_mmci_int_update(s);
    381         break;
    382 
    383     case MMC_CLKRT:
    384         s->clkrt = value & 7;
    385         break;
    386 
    387     case MMC_SPI:
    388         s->spi = value & 0xf;
    389         if (value & SPI_SPI_MODE) {
    390             qemu_log_mask(LOG_GUEST_ERROR,
    391                           "%s: attempted to use card in SPI mode\n", __func__);
    392         }
    393         break;
    394 
    395     case MMC_CMDAT:
    396         s->cmdat = value & 0x3dff;
    397         s->active = 0;
    398         s->cmdreq = 1;
    399         if (!(value & CMDAT_STOP_TRAN)) {
    400             s->status &= STAT_CLK_EN;
    401 
    402             if (s->status & STAT_CLK_EN)
    403                 pxa2xx_mmci_wakequeues(s);
    404         }
    405 
    406         pxa2xx_mmci_int_update(s);
    407         break;
    408 
    409     case MMC_RESTO:
    410         s->resp_tout = value & 0x7f;
    411         break;
    412 
    413     case MMC_RDTO:
    414         s->read_tout = value & 0xffff;
    415         break;
    416 
    417     case MMC_BLKLEN:
    418         s->blklen = value & 0xfff;
    419         break;
    420 
    421     case MMC_NUMBLK:
    422         s->numblk = value & 0xffff;
    423         break;
    424 
    425     case MMC_PRTBUF:
    426         if (value & PRTBUF_PRT_BUF) {
    427             s->tx_start ^= 32;
    428             s->tx_len = 0;
    429         }
    430         pxa2xx_mmci_fifo_update(s);
    431         break;
    432 
    433     case MMC_I_MASK:
    434         s->intmask = value & 0x1fff;
    435         pxa2xx_mmci_int_update(s);
    436         break;
    437 
    438     case MMC_CMD:
    439         s->cmd = value & 0x3f;
    440         break;
    441 
    442     case MMC_ARGH:
    443         s->arg &= 0x0000ffff;
    444         s->arg |= value << 16;
    445         break;
    446 
    447     case MMC_ARGL:
    448         s->arg &= 0xffff0000;
    449         s->arg |= value & 0x0000ffff;
    450         break;
    451 
    452     case MMC_TXFIFO:
    453         while (size-- && s->tx_len < 0x20)
    454             s->tx_fifo[(s->tx_start + (s->tx_len ++)) & 0x1f] =
    455                     (value >> (size << 3)) & 0xff;
    456         s->intreq &= ~INT_TXFIFO_REQ;
    457         pxa2xx_mmci_fifo_update(s);
    458         break;
    459 
    460     case MMC_RDWAIT:
    461     case MMC_BLKS_REM:
    462         break;
    463 
    464     default:
    465         qemu_log_mask(LOG_GUEST_ERROR,
    466                       "%s: incorrect reg 0x%02" HWADDR_PRIx " "
    467                       "(value 0x%08" PRIx64 ")\n", __func__, offset, value);
    468     }
    469 }
    470 
    471 static const MemoryRegionOps pxa2xx_mmci_ops = {
    472     .read = pxa2xx_mmci_read,
    473     .write = pxa2xx_mmci_write,
    474     .endianness = DEVICE_NATIVE_ENDIAN,
    475 };
    476 
    477 PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
    478                 hwaddr base,
    479                 qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma)
    480 {
    481     DeviceState *dev;
    482     SysBusDevice *sbd;
    483 
    484     dev = qdev_new(TYPE_PXA2XX_MMCI);
    485     sbd = SYS_BUS_DEVICE(dev);
    486     sysbus_mmio_map(sbd, 0, base);
    487     sysbus_connect_irq(sbd, 0, irq);
    488     qdev_connect_gpio_out_named(dev, "rx-dma", 0, rx_dma);
    489     qdev_connect_gpio_out_named(dev, "tx-dma", 0, tx_dma);
    490     sysbus_realize_and_unref(sbd, &error_fatal);
    491 
    492     return PXA2XX_MMCI(dev);
    493 }
    494 
    495 static void pxa2xx_mmci_set_inserted(DeviceState *dev, bool inserted)
    496 {
    497     PXA2xxMMCIState *s = PXA2XX_MMCI(dev);
    498 
    499     qemu_set_irq(s->inserted, inserted);
    500 }
    501 
    502 static void pxa2xx_mmci_set_readonly(DeviceState *dev, bool readonly)
    503 {
    504     PXA2xxMMCIState *s = PXA2XX_MMCI(dev);
    505 
    506     qemu_set_irq(s->readonly, readonly);
    507 }
    508 
    509 void pxa2xx_mmci_handlers(PXA2xxMMCIState *s, qemu_irq readonly,
    510                           qemu_irq coverswitch)
    511 {
    512     DeviceState *dev = DEVICE(s);
    513 
    514     s->readonly = readonly;
    515     s->inserted = coverswitch;
    516 
    517     pxa2xx_mmci_set_inserted(dev, sdbus_get_inserted(&s->sdbus));
    518     pxa2xx_mmci_set_readonly(dev, sdbus_get_readonly(&s->sdbus));
    519 }
    520 
    521 static void pxa2xx_mmci_reset(DeviceState *d)
    522 {
    523     PXA2xxMMCIState *s = PXA2XX_MMCI(d);
    524 
    525     s->status = 0;
    526     s->clkrt = 0;
    527     s->spi = 0;
    528     s->cmdat = 0;
    529     s->resp_tout = 0;
    530     s->read_tout = 0;
    531     s->blklen = 0;
    532     s->numblk = 0;
    533     s->intmask = 0;
    534     s->intreq = 0;
    535     s->cmd = 0;
    536     s->arg = 0;
    537     s->active = 0;
    538     s->bytesleft = 0;
    539     s->tx_start = 0;
    540     s->tx_len = 0;
    541     s->rx_start = 0;
    542     s->rx_len = 0;
    543     s->resp_len = 0;
    544     s->cmdreq = 0;
    545     memset(s->tx_fifo, 0, sizeof(s->tx_fifo));
    546     memset(s->rx_fifo, 0, sizeof(s->rx_fifo));
    547     memset(s->resp_fifo, 0, sizeof(s->resp_fifo));
    548 }
    549 
    550 static void pxa2xx_mmci_instance_init(Object *obj)
    551 {
    552     PXA2xxMMCIState *s = PXA2XX_MMCI(obj);
    553     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    554     DeviceState *dev = DEVICE(obj);
    555 
    556     memory_region_init_io(&s->iomem, obj, &pxa2xx_mmci_ops, s,
    557                           "pxa2xx-mmci", 0x00100000);
    558     sysbus_init_mmio(sbd, &s->iomem);
    559     sysbus_init_irq(sbd, &s->irq);
    560     qdev_init_gpio_out_named(dev, &s->rx_dma, "rx-dma", 1);
    561     qdev_init_gpio_out_named(dev, &s->tx_dma, "tx-dma", 1);
    562 
    563     qbus_init(&s->sdbus, sizeof(s->sdbus),
    564               TYPE_PXA2XX_MMCI_BUS, DEVICE(obj), "sd-bus");
    565 }
    566 
    567 static void pxa2xx_mmci_class_init(ObjectClass *klass, void *data)
    568 {
    569     DeviceClass *dc = DEVICE_CLASS(klass);
    570 
    571     dc->vmsd = &vmstate_pxa2xx_mmci;
    572     dc->reset = pxa2xx_mmci_reset;
    573 }
    574 
    575 static void pxa2xx_mmci_bus_class_init(ObjectClass *klass, void *data)
    576 {
    577     SDBusClass *sbc = SD_BUS_CLASS(klass);
    578 
    579     sbc->set_inserted = pxa2xx_mmci_set_inserted;
    580     sbc->set_readonly = pxa2xx_mmci_set_readonly;
    581 }
    582 
    583 static const TypeInfo pxa2xx_mmci_info = {
    584     .name = TYPE_PXA2XX_MMCI,
    585     .parent = TYPE_SYS_BUS_DEVICE,
    586     .instance_size = sizeof(PXA2xxMMCIState),
    587     .instance_init = pxa2xx_mmci_instance_init,
    588     .class_init = pxa2xx_mmci_class_init,
    589 };
    590 
    591 static const TypeInfo pxa2xx_mmci_bus_info = {
    592     .name = TYPE_PXA2XX_MMCI_BUS,
    593     .parent = TYPE_SD_BUS,
    594     .instance_size = sizeof(SDBus),
    595     .class_init = pxa2xx_mmci_bus_class_init,
    596 };
    597 
    598 static void pxa2xx_mmci_register_types(void)
    599 {
    600     type_register_static(&pxa2xx_mmci_info);
    601     type_register_static(&pxa2xx_mmci_bus_info);
    602 }
    603 
    604 type_init(pxa2xx_mmci_register_types)