1*43ddc182SClement Deschamps /* 2*43ddc182SClement Deschamps * Raspberry Pi (BCM2835) SD Host Controller 3*43ddc182SClement Deschamps * 4*43ddc182SClement Deschamps * Copyright (c) 2017 Antfield SAS 5*43ddc182SClement Deschamps * 6*43ddc182SClement Deschamps * Authors: 7*43ddc182SClement Deschamps * Clement Deschamps <clement.deschamps@antfield.fr> 8*43ddc182SClement Deschamps * Luc Michel <luc.michel@antfield.fr> 9*43ddc182SClement Deschamps * 10*43ddc182SClement Deschamps * This work is licensed under the terms of the GNU GPL, version 2 or later. 11*43ddc182SClement Deschamps * See the COPYING file in the top-level directory. 12*43ddc182SClement Deschamps */ 13*43ddc182SClement Deschamps 14*43ddc182SClement Deschamps #include "qemu/osdep.h" 15*43ddc182SClement Deschamps #include "qemu/log.h" 16*43ddc182SClement Deschamps #include "sysemu/blockdev.h" 17*43ddc182SClement Deschamps #include "hw/sd/bcm2835_sdhost.h" 18*43ddc182SClement Deschamps 19*43ddc182SClement Deschamps #define TYPE_BCM2835_SDHOST_BUS "bcm2835-sdhost-bus" 20*43ddc182SClement Deschamps #define BCM2835_SDHOST_BUS(obj) \ 21*43ddc182SClement Deschamps OBJECT_CHECK(SDBus, (obj), TYPE_BCM2835_SDHOST_BUS) 22*43ddc182SClement Deschamps 23*43ddc182SClement Deschamps #define SDCMD 0x00 /* Command to SD card - 16 R/W */ 24*43ddc182SClement Deschamps #define SDARG 0x04 /* Argument to SD card - 32 R/W */ 25*43ddc182SClement Deschamps #define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */ 26*43ddc182SClement Deschamps #define SDCDIV 0x0c /* Start value for clock divider - 11 R/W */ 27*43ddc182SClement Deschamps #define SDRSP0 0x10 /* SD card rsp (31:0) - 32 R */ 28*43ddc182SClement Deschamps #define SDRSP1 0x14 /* SD card rsp (63:32) - 32 R */ 29*43ddc182SClement Deschamps #define SDRSP2 0x18 /* SD card rsp (95:64) - 32 R */ 30*43ddc182SClement Deschamps #define SDRSP3 0x1c /* SD card rsp (127:96) - 32 R */ 31*43ddc182SClement Deschamps #define SDHSTS 0x20 /* SD host status - 11 R */ 32*43ddc182SClement Deschamps #define SDVDD 0x30 /* SD card power control - 1 R/W */ 33*43ddc182SClement Deschamps #define SDEDM 0x34 /* Emergency Debug Mode - 13 R/W */ 34*43ddc182SClement Deschamps #define SDHCFG 0x38 /* Host configuration - 2 R/W */ 35*43ddc182SClement Deschamps #define SDHBCT 0x3c /* Host byte count (debug) - 32 R/W */ 36*43ddc182SClement Deschamps #define SDDATA 0x40 /* Data to/from SD card - 32 R/W */ 37*43ddc182SClement Deschamps #define SDHBLC 0x50 /* Host block count (SDIO/SDHC) - 9 R/W */ 38*43ddc182SClement Deschamps 39*43ddc182SClement Deschamps #define SDCMD_NEW_FLAG 0x8000 40*43ddc182SClement Deschamps #define SDCMD_FAIL_FLAG 0x4000 41*43ddc182SClement Deschamps #define SDCMD_BUSYWAIT 0x800 42*43ddc182SClement Deschamps #define SDCMD_NO_RESPONSE 0x400 43*43ddc182SClement Deschamps #define SDCMD_LONG_RESPONSE 0x200 44*43ddc182SClement Deschamps #define SDCMD_WRITE_CMD 0x80 45*43ddc182SClement Deschamps #define SDCMD_READ_CMD 0x40 46*43ddc182SClement Deschamps #define SDCMD_CMD_MASK 0x3f 47*43ddc182SClement Deschamps 48*43ddc182SClement Deschamps #define SDCDIV_MAX_CDIV 0x7ff 49*43ddc182SClement Deschamps 50*43ddc182SClement Deschamps #define SDHSTS_BUSY_IRPT 0x400 51*43ddc182SClement Deschamps #define SDHSTS_BLOCK_IRPT 0x200 52*43ddc182SClement Deschamps #define SDHSTS_SDIO_IRPT 0x100 53*43ddc182SClement Deschamps #define SDHSTS_REW_TIME_OUT 0x80 54*43ddc182SClement Deschamps #define SDHSTS_CMD_TIME_OUT 0x40 55*43ddc182SClement Deschamps #define SDHSTS_CRC16_ERROR 0x20 56*43ddc182SClement Deschamps #define SDHSTS_CRC7_ERROR 0x10 57*43ddc182SClement Deschamps #define SDHSTS_FIFO_ERROR 0x08 58*43ddc182SClement Deschamps /* Reserved */ 59*43ddc182SClement Deschamps /* Reserved */ 60*43ddc182SClement Deschamps #define SDHSTS_DATA_FLAG 0x01 61*43ddc182SClement Deschamps 62*43ddc182SClement Deschamps #define SDHCFG_BUSY_IRPT_EN (1 << 10) 63*43ddc182SClement Deschamps #define SDHCFG_BLOCK_IRPT_EN (1 << 8) 64*43ddc182SClement Deschamps #define SDHCFG_SDIO_IRPT_EN (1 << 5) 65*43ddc182SClement Deschamps #define SDHCFG_DATA_IRPT_EN (1 << 4) 66*43ddc182SClement Deschamps #define SDHCFG_SLOW_CARD (1 << 3) 67*43ddc182SClement Deschamps #define SDHCFG_WIDE_EXT_BUS (1 << 2) 68*43ddc182SClement Deschamps #define SDHCFG_WIDE_INT_BUS (1 << 1) 69*43ddc182SClement Deschamps #define SDHCFG_REL_CMD_LINE (1 << 0) 70*43ddc182SClement Deschamps 71*43ddc182SClement Deschamps #define SDEDM_FORCE_DATA_MODE (1 << 19) 72*43ddc182SClement Deschamps #define SDEDM_CLOCK_PULSE (1 << 20) 73*43ddc182SClement Deschamps #define SDEDM_BYPASS (1 << 21) 74*43ddc182SClement Deschamps 75*43ddc182SClement Deschamps #define SDEDM_WRITE_THRESHOLD_SHIFT 9 76*43ddc182SClement Deschamps #define SDEDM_READ_THRESHOLD_SHIFT 14 77*43ddc182SClement Deschamps #define SDEDM_THRESHOLD_MASK 0x1f 78*43ddc182SClement Deschamps 79*43ddc182SClement Deschamps #define SDEDM_FSM_MASK 0xf 80*43ddc182SClement Deschamps #define SDEDM_FSM_IDENTMODE 0x0 81*43ddc182SClement Deschamps #define SDEDM_FSM_DATAMODE 0x1 82*43ddc182SClement Deschamps #define SDEDM_FSM_READDATA 0x2 83*43ddc182SClement Deschamps #define SDEDM_FSM_WRITEDATA 0x3 84*43ddc182SClement Deschamps #define SDEDM_FSM_READWAIT 0x4 85*43ddc182SClement Deschamps #define SDEDM_FSM_READCRC 0x5 86*43ddc182SClement Deschamps #define SDEDM_FSM_WRITECRC 0x6 87*43ddc182SClement Deschamps #define SDEDM_FSM_WRITEWAIT1 0x7 88*43ddc182SClement Deschamps #define SDEDM_FSM_POWERDOWN 0x8 89*43ddc182SClement Deschamps #define SDEDM_FSM_POWERUP 0x9 90*43ddc182SClement Deschamps #define SDEDM_FSM_WRITESTART1 0xa 91*43ddc182SClement Deschamps #define SDEDM_FSM_WRITESTART2 0xb 92*43ddc182SClement Deschamps #define SDEDM_FSM_GENPULSES 0xc 93*43ddc182SClement Deschamps #define SDEDM_FSM_WRITEWAIT2 0xd 94*43ddc182SClement Deschamps #define SDEDM_FSM_STARTPOWDOWN 0xf 95*43ddc182SClement Deschamps 96*43ddc182SClement Deschamps #define SDDATA_FIFO_WORDS 16 97*43ddc182SClement Deschamps 98*43ddc182SClement Deschamps static void bcm2835_sdhost_update_irq(BCM2835SDHostState *s) 99*43ddc182SClement Deschamps { 100*43ddc182SClement Deschamps uint32_t irq = s->status & 101*43ddc182SClement Deschamps (SDHSTS_BUSY_IRPT | SDHSTS_BLOCK_IRPT | SDHSTS_SDIO_IRPT); 102*43ddc182SClement Deschamps qemu_set_irq(s->irq, !!irq); 103*43ddc182SClement Deschamps } 104*43ddc182SClement Deschamps 105*43ddc182SClement Deschamps static void bcm2835_sdhost_send_command(BCM2835SDHostState *s) 106*43ddc182SClement Deschamps { 107*43ddc182SClement Deschamps SDRequest request; 108*43ddc182SClement Deschamps uint8_t rsp[16]; 109*43ddc182SClement Deschamps int rlen; 110*43ddc182SClement Deschamps 111*43ddc182SClement Deschamps request.cmd = s->cmd & SDCMD_CMD_MASK; 112*43ddc182SClement Deschamps request.arg = s->cmdarg; 113*43ddc182SClement Deschamps 114*43ddc182SClement Deschamps rlen = sdbus_do_command(&s->sdbus, &request, rsp); 115*43ddc182SClement Deschamps if (rlen < 0) { 116*43ddc182SClement Deschamps goto error; 117*43ddc182SClement Deschamps } 118*43ddc182SClement Deschamps if (!(s->cmd & SDCMD_NO_RESPONSE)) { 119*43ddc182SClement Deschamps #define RWORD(n) (((uint32_t)rsp[n] << 24) | (rsp[n + 1] << 16) \ 120*43ddc182SClement Deschamps | (rsp[n + 2] << 8) | rsp[n + 3]) 121*43ddc182SClement Deschamps if (rlen == 0 || (rlen == 4 && (s->cmd & SDCMD_LONG_RESPONSE))) { 122*43ddc182SClement Deschamps goto error; 123*43ddc182SClement Deschamps } 124*43ddc182SClement Deschamps if (rlen != 4 && rlen != 16) { 125*43ddc182SClement Deschamps goto error; 126*43ddc182SClement Deschamps } 127*43ddc182SClement Deschamps if (rlen == 4) { 128*43ddc182SClement Deschamps s->rsp[0] = RWORD(0); 129*43ddc182SClement Deschamps s->rsp[1] = s->rsp[2] = s->rsp[3] = 0; 130*43ddc182SClement Deschamps } else { 131*43ddc182SClement Deschamps s->rsp[0] = RWORD(12); 132*43ddc182SClement Deschamps s->rsp[1] = RWORD(8); 133*43ddc182SClement Deschamps s->rsp[2] = RWORD(4); 134*43ddc182SClement Deschamps s->rsp[3] = RWORD(0); 135*43ddc182SClement Deschamps } 136*43ddc182SClement Deschamps #undef RWORD 137*43ddc182SClement Deschamps } 138*43ddc182SClement Deschamps return; 139*43ddc182SClement Deschamps 140*43ddc182SClement Deschamps error: 141*43ddc182SClement Deschamps s->cmd |= SDCMD_FAIL_FLAG; 142*43ddc182SClement Deschamps s->status |= SDHSTS_CMD_TIME_OUT; 143*43ddc182SClement Deschamps } 144*43ddc182SClement Deschamps 145*43ddc182SClement Deschamps static void bcm2835_sdhost_fifo_push(BCM2835SDHostState *s, uint32_t value) 146*43ddc182SClement Deschamps { 147*43ddc182SClement Deschamps int n; 148*43ddc182SClement Deschamps 149*43ddc182SClement Deschamps if (s->fifo_len == BCM2835_SDHOST_FIFO_LEN) { 150*43ddc182SClement Deschamps /* FIFO overflow */ 151*43ddc182SClement Deschamps return; 152*43ddc182SClement Deschamps } 153*43ddc182SClement Deschamps n = (s->fifo_pos + s->fifo_len) & (BCM2835_SDHOST_FIFO_LEN - 1); 154*43ddc182SClement Deschamps s->fifo_len++; 155*43ddc182SClement Deschamps s->fifo[n] = value; 156*43ddc182SClement Deschamps } 157*43ddc182SClement Deschamps 158*43ddc182SClement Deschamps static uint32_t bcm2835_sdhost_fifo_pop(BCM2835SDHostState *s) 159*43ddc182SClement Deschamps { 160*43ddc182SClement Deschamps uint32_t value; 161*43ddc182SClement Deschamps 162*43ddc182SClement Deschamps if (s->fifo_len == 0) { 163*43ddc182SClement Deschamps /* FIFO underflow */ 164*43ddc182SClement Deschamps return 0; 165*43ddc182SClement Deschamps } 166*43ddc182SClement Deschamps value = s->fifo[s->fifo_pos]; 167*43ddc182SClement Deschamps s->fifo_len--; 168*43ddc182SClement Deschamps s->fifo_pos = (s->fifo_pos + 1) & (BCM2835_SDHOST_FIFO_LEN - 1); 169*43ddc182SClement Deschamps return value; 170*43ddc182SClement Deschamps } 171*43ddc182SClement Deschamps 172*43ddc182SClement Deschamps static void bcm2835_sdhost_fifo_run(BCM2835SDHostState *s) 173*43ddc182SClement Deschamps { 174*43ddc182SClement Deschamps uint32_t value = 0; 175*43ddc182SClement Deschamps int n; 176*43ddc182SClement Deschamps int is_read; 177*43ddc182SClement Deschamps 178*43ddc182SClement Deschamps is_read = (s->cmd & SDCMD_READ_CMD) != 0; 179*43ddc182SClement Deschamps if (s->datacnt != 0 && (!is_read || sdbus_data_ready(&s->sdbus))) { 180*43ddc182SClement Deschamps if (is_read) { 181*43ddc182SClement Deschamps n = 0; 182*43ddc182SClement Deschamps while (s->datacnt && s->fifo_len < BCM2835_SDHOST_FIFO_LEN) { 183*43ddc182SClement Deschamps value |= (uint32_t)sdbus_read_data(&s->sdbus) << (n * 8); 184*43ddc182SClement Deschamps s->datacnt--; 185*43ddc182SClement Deschamps n++; 186*43ddc182SClement Deschamps if (n == 4) { 187*43ddc182SClement Deschamps bcm2835_sdhost_fifo_push(s, value); 188*43ddc182SClement Deschamps n = 0; 189*43ddc182SClement Deschamps value = 0; 190*43ddc182SClement Deschamps } 191*43ddc182SClement Deschamps } 192*43ddc182SClement Deschamps if (n != 0) { 193*43ddc182SClement Deschamps bcm2835_sdhost_fifo_push(s, value); 194*43ddc182SClement Deschamps } 195*43ddc182SClement Deschamps } else { /* write */ 196*43ddc182SClement Deschamps n = 0; 197*43ddc182SClement Deschamps while (s->datacnt > 0 && (s->fifo_len > 0 || n > 0)) { 198*43ddc182SClement Deschamps if (n == 0) { 199*43ddc182SClement Deschamps value = bcm2835_sdhost_fifo_pop(s); 200*43ddc182SClement Deschamps n = 4; 201*43ddc182SClement Deschamps } 202*43ddc182SClement Deschamps n--; 203*43ddc182SClement Deschamps s->datacnt--; 204*43ddc182SClement Deschamps sdbus_write_data(&s->sdbus, value & 0xff); 205*43ddc182SClement Deschamps value >>= 8; 206*43ddc182SClement Deschamps } 207*43ddc182SClement Deschamps } 208*43ddc182SClement Deschamps } 209*43ddc182SClement Deschamps if (s->datacnt == 0) { 210*43ddc182SClement Deschamps s->status |= SDHSTS_DATA_FLAG; 211*43ddc182SClement Deschamps 212*43ddc182SClement Deschamps s->edm &= ~0xf; 213*43ddc182SClement Deschamps s->edm |= SDEDM_FSM_DATAMODE; 214*43ddc182SClement Deschamps 215*43ddc182SClement Deschamps if (s->config & SDHCFG_DATA_IRPT_EN) { 216*43ddc182SClement Deschamps s->status |= SDHSTS_SDIO_IRPT; 217*43ddc182SClement Deschamps } 218*43ddc182SClement Deschamps 219*43ddc182SClement Deschamps if ((s->cmd & SDCMD_BUSYWAIT) && (s->config & SDHCFG_BUSY_IRPT_EN)) { 220*43ddc182SClement Deschamps s->status |= SDHSTS_BUSY_IRPT; 221*43ddc182SClement Deschamps } 222*43ddc182SClement Deschamps 223*43ddc182SClement Deschamps if ((s->cmd & SDCMD_WRITE_CMD) && (s->config & SDHCFG_BLOCK_IRPT_EN)) { 224*43ddc182SClement Deschamps s->status |= SDHSTS_BLOCK_IRPT; 225*43ddc182SClement Deschamps } 226*43ddc182SClement Deschamps 227*43ddc182SClement Deschamps bcm2835_sdhost_update_irq(s); 228*43ddc182SClement Deschamps } 229*43ddc182SClement Deschamps 230*43ddc182SClement Deschamps s->edm &= ~(0x1f << 4); 231*43ddc182SClement Deschamps s->edm |= ((s->fifo_len & 0x1f) << 4); 232*43ddc182SClement Deschamps } 233*43ddc182SClement Deschamps 234*43ddc182SClement Deschamps static uint64_t bcm2835_sdhost_read(void *opaque, hwaddr offset, 235*43ddc182SClement Deschamps unsigned size) 236*43ddc182SClement Deschamps { 237*43ddc182SClement Deschamps BCM2835SDHostState *s = (BCM2835SDHostState *)opaque; 238*43ddc182SClement Deschamps uint32_t res = 0; 239*43ddc182SClement Deschamps 240*43ddc182SClement Deschamps switch (offset) { 241*43ddc182SClement Deschamps case SDCMD: 242*43ddc182SClement Deschamps res = s->cmd; 243*43ddc182SClement Deschamps break; 244*43ddc182SClement Deschamps case SDHSTS: 245*43ddc182SClement Deschamps res = s->status; 246*43ddc182SClement Deschamps break; 247*43ddc182SClement Deschamps case SDRSP0: 248*43ddc182SClement Deschamps res = s->rsp[0]; 249*43ddc182SClement Deschamps break; 250*43ddc182SClement Deschamps case SDRSP1: 251*43ddc182SClement Deschamps res = s->rsp[1]; 252*43ddc182SClement Deschamps break; 253*43ddc182SClement Deschamps case SDRSP2: 254*43ddc182SClement Deschamps res = s->rsp[2]; 255*43ddc182SClement Deschamps break; 256*43ddc182SClement Deschamps case SDRSP3: 257*43ddc182SClement Deschamps res = s->rsp[3]; 258*43ddc182SClement Deschamps break; 259*43ddc182SClement Deschamps case SDEDM: 260*43ddc182SClement Deschamps res = s->edm; 261*43ddc182SClement Deschamps break; 262*43ddc182SClement Deschamps case SDVDD: 263*43ddc182SClement Deschamps res = s->vdd; 264*43ddc182SClement Deschamps break; 265*43ddc182SClement Deschamps case SDDATA: 266*43ddc182SClement Deschamps res = bcm2835_sdhost_fifo_pop(s); 267*43ddc182SClement Deschamps bcm2835_sdhost_fifo_run(s); 268*43ddc182SClement Deschamps break; 269*43ddc182SClement Deschamps case SDHBCT: 270*43ddc182SClement Deschamps res = s->hbct; 271*43ddc182SClement Deschamps break; 272*43ddc182SClement Deschamps case SDHBLC: 273*43ddc182SClement Deschamps res = s->hblc; 274*43ddc182SClement Deschamps break; 275*43ddc182SClement Deschamps 276*43ddc182SClement Deschamps default: 277*43ddc182SClement Deschamps qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", 278*43ddc182SClement Deschamps __func__, offset); 279*43ddc182SClement Deschamps res = 0; 280*43ddc182SClement Deschamps break; 281*43ddc182SClement Deschamps } 282*43ddc182SClement Deschamps 283*43ddc182SClement Deschamps return res; 284*43ddc182SClement Deschamps } 285*43ddc182SClement Deschamps 286*43ddc182SClement Deschamps static void bcm2835_sdhost_write(void *opaque, hwaddr offset, 287*43ddc182SClement Deschamps uint64_t value, unsigned size) 288*43ddc182SClement Deschamps { 289*43ddc182SClement Deschamps BCM2835SDHostState *s = (BCM2835SDHostState *)opaque; 290*43ddc182SClement Deschamps 291*43ddc182SClement Deschamps switch (offset) { 292*43ddc182SClement Deschamps case SDCMD: 293*43ddc182SClement Deschamps s->cmd = value; 294*43ddc182SClement Deschamps if (value & SDCMD_NEW_FLAG) { 295*43ddc182SClement Deschamps bcm2835_sdhost_send_command(s); 296*43ddc182SClement Deschamps bcm2835_sdhost_fifo_run(s); 297*43ddc182SClement Deschamps s->cmd &= ~SDCMD_NEW_FLAG; 298*43ddc182SClement Deschamps } 299*43ddc182SClement Deschamps break; 300*43ddc182SClement Deschamps case SDTOUT: 301*43ddc182SClement Deschamps break; 302*43ddc182SClement Deschamps case SDCDIV: 303*43ddc182SClement Deschamps break; 304*43ddc182SClement Deschamps case SDHSTS: 305*43ddc182SClement Deschamps s->status &= ~value; 306*43ddc182SClement Deschamps bcm2835_sdhost_update_irq(s); 307*43ddc182SClement Deschamps break; 308*43ddc182SClement Deschamps case SDARG: 309*43ddc182SClement Deschamps s->cmdarg = value; 310*43ddc182SClement Deschamps break; 311*43ddc182SClement Deschamps case SDEDM: 312*43ddc182SClement Deschamps if ((value & 0xf) == 0xf) { 313*43ddc182SClement Deschamps /* power down */ 314*43ddc182SClement Deschamps value &= ~0xf; 315*43ddc182SClement Deschamps } 316*43ddc182SClement Deschamps s->edm = value; 317*43ddc182SClement Deschamps break; 318*43ddc182SClement Deschamps case SDHCFG: 319*43ddc182SClement Deschamps s->config = value; 320*43ddc182SClement Deschamps bcm2835_sdhost_fifo_run(s); 321*43ddc182SClement Deschamps break; 322*43ddc182SClement Deschamps case SDVDD: 323*43ddc182SClement Deschamps s->vdd = value; 324*43ddc182SClement Deschamps break; 325*43ddc182SClement Deschamps case SDDATA: 326*43ddc182SClement Deschamps bcm2835_sdhost_fifo_push(s, value); 327*43ddc182SClement Deschamps bcm2835_sdhost_fifo_run(s); 328*43ddc182SClement Deschamps break; 329*43ddc182SClement Deschamps case SDHBCT: 330*43ddc182SClement Deschamps s->hbct = value; 331*43ddc182SClement Deschamps break; 332*43ddc182SClement Deschamps case SDHBLC: 333*43ddc182SClement Deschamps s->hblc = value; 334*43ddc182SClement Deschamps s->datacnt = s->hblc * s->hbct; 335*43ddc182SClement Deschamps bcm2835_sdhost_fifo_run(s); 336*43ddc182SClement Deschamps break; 337*43ddc182SClement Deschamps 338*43ddc182SClement Deschamps default: 339*43ddc182SClement Deschamps qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", 340*43ddc182SClement Deschamps __func__, offset); 341*43ddc182SClement Deschamps break; 342*43ddc182SClement Deschamps } 343*43ddc182SClement Deschamps } 344*43ddc182SClement Deschamps 345*43ddc182SClement Deschamps static const MemoryRegionOps bcm2835_sdhost_ops = { 346*43ddc182SClement Deschamps .read = bcm2835_sdhost_read, 347*43ddc182SClement Deschamps .write = bcm2835_sdhost_write, 348*43ddc182SClement Deschamps .endianness = DEVICE_NATIVE_ENDIAN, 349*43ddc182SClement Deschamps }; 350*43ddc182SClement Deschamps 351*43ddc182SClement Deschamps static const VMStateDescription vmstate_bcm2835_sdhost = { 352*43ddc182SClement Deschamps .name = TYPE_BCM2835_SDHOST, 353*43ddc182SClement Deschamps .version_id = 1, 354*43ddc182SClement Deschamps .minimum_version_id = 1, 355*43ddc182SClement Deschamps .fields = (VMStateField[]) { 356*43ddc182SClement Deschamps VMSTATE_UINT32(cmd, BCM2835SDHostState), 357*43ddc182SClement Deschamps VMSTATE_UINT32(cmdarg, BCM2835SDHostState), 358*43ddc182SClement Deschamps VMSTATE_UINT32(status, BCM2835SDHostState), 359*43ddc182SClement Deschamps VMSTATE_UINT32_ARRAY(rsp, BCM2835SDHostState, 4), 360*43ddc182SClement Deschamps VMSTATE_UINT32(config, BCM2835SDHostState), 361*43ddc182SClement Deschamps VMSTATE_UINT32(edm, BCM2835SDHostState), 362*43ddc182SClement Deschamps VMSTATE_UINT32(vdd, BCM2835SDHostState), 363*43ddc182SClement Deschamps VMSTATE_UINT32(hbct, BCM2835SDHostState), 364*43ddc182SClement Deschamps VMSTATE_UINT32(hblc, BCM2835SDHostState), 365*43ddc182SClement Deschamps VMSTATE_INT32(fifo_pos, BCM2835SDHostState), 366*43ddc182SClement Deschamps VMSTATE_INT32(fifo_len, BCM2835SDHostState), 367*43ddc182SClement Deschamps VMSTATE_UINT32_ARRAY(fifo, BCM2835SDHostState, BCM2835_SDHOST_FIFO_LEN), 368*43ddc182SClement Deschamps VMSTATE_UINT32(datacnt, BCM2835SDHostState), 369*43ddc182SClement Deschamps VMSTATE_END_OF_LIST() 370*43ddc182SClement Deschamps } 371*43ddc182SClement Deschamps }; 372*43ddc182SClement Deschamps 373*43ddc182SClement Deschamps static void bcm2835_sdhost_init(Object *obj) 374*43ddc182SClement Deschamps { 375*43ddc182SClement Deschamps BCM2835SDHostState *s = BCM2835_SDHOST(obj); 376*43ddc182SClement Deschamps 377*43ddc182SClement Deschamps qbus_create_inplace(&s->sdbus, sizeof(s->sdbus), 378*43ddc182SClement Deschamps TYPE_BCM2835_SDHOST_BUS, DEVICE(s), "sd-bus"); 379*43ddc182SClement Deschamps 380*43ddc182SClement Deschamps memory_region_init_io(&s->iomem, obj, &bcm2835_sdhost_ops, s, 381*43ddc182SClement Deschamps TYPE_BCM2835_SDHOST, 0x1000); 382*43ddc182SClement Deschamps sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); 383*43ddc182SClement Deschamps sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq); 384*43ddc182SClement Deschamps } 385*43ddc182SClement Deschamps 386*43ddc182SClement Deschamps static void bcm2835_sdhost_reset(DeviceState *dev) 387*43ddc182SClement Deschamps { 388*43ddc182SClement Deschamps BCM2835SDHostState *s = BCM2835_SDHOST(dev); 389*43ddc182SClement Deschamps 390*43ddc182SClement Deschamps s->cmd = 0; 391*43ddc182SClement Deschamps s->cmdarg = 0; 392*43ddc182SClement Deschamps s->edm = 0x0000c60f; 393*43ddc182SClement Deschamps s->config = 0; 394*43ddc182SClement Deschamps s->hbct = 0; 395*43ddc182SClement Deschamps s->hblc = 0; 396*43ddc182SClement Deschamps s->datacnt = 0; 397*43ddc182SClement Deschamps s->fifo_pos = 0; 398*43ddc182SClement Deschamps s->fifo_len = 0; 399*43ddc182SClement Deschamps } 400*43ddc182SClement Deschamps 401*43ddc182SClement Deschamps static void bcm2835_sdhost_class_init(ObjectClass *klass, void *data) 402*43ddc182SClement Deschamps { 403*43ddc182SClement Deschamps DeviceClass *dc = DEVICE_CLASS(klass); 404*43ddc182SClement Deschamps 405*43ddc182SClement Deschamps dc->reset = bcm2835_sdhost_reset; 406*43ddc182SClement Deschamps dc->vmsd = &vmstate_bcm2835_sdhost; 407*43ddc182SClement Deschamps } 408*43ddc182SClement Deschamps 409*43ddc182SClement Deschamps static TypeInfo bcm2835_sdhost_info = { 410*43ddc182SClement Deschamps .name = TYPE_BCM2835_SDHOST, 411*43ddc182SClement Deschamps .parent = TYPE_SYS_BUS_DEVICE, 412*43ddc182SClement Deschamps .instance_size = sizeof(BCM2835SDHostState), 413*43ddc182SClement Deschamps .class_init = bcm2835_sdhost_class_init, 414*43ddc182SClement Deschamps .instance_init = bcm2835_sdhost_init, 415*43ddc182SClement Deschamps }; 416*43ddc182SClement Deschamps 417*43ddc182SClement Deschamps static const TypeInfo bcm2835_sdhost_bus_info = { 418*43ddc182SClement Deschamps .name = TYPE_BCM2835_SDHOST_BUS, 419*43ddc182SClement Deschamps .parent = TYPE_SD_BUS, 420*43ddc182SClement Deschamps .instance_size = sizeof(SDBus), 421*43ddc182SClement Deschamps }; 422*43ddc182SClement Deschamps 423*43ddc182SClement Deschamps static void bcm2835_sdhost_register_types(void) 424*43ddc182SClement Deschamps { 425*43ddc182SClement Deschamps type_register_static(&bcm2835_sdhost_info); 426*43ddc182SClement Deschamps type_register_static(&bcm2835_sdhost_bus_info); 427*43ddc182SClement Deschamps } 428*43ddc182SClement Deschamps 429*43ddc182SClement Deschamps type_init(bcm2835_sdhost_register_types) 430