1*31e17060SPaolo Bonzini /* 2*31e17060SPaolo Bonzini * QEMU model of the Xilinx SPI Controller 3*31e17060SPaolo Bonzini * 4*31e17060SPaolo Bonzini * Copyright (C) 2010 Edgar E. Iglesias. 5*31e17060SPaolo Bonzini * Copyright (C) 2012 Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com> 6*31e17060SPaolo Bonzini * Copyright (C) 2012 PetaLogix 7*31e17060SPaolo Bonzini * 8*31e17060SPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy 9*31e17060SPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal 10*31e17060SPaolo Bonzini * in the Software without restriction, including without limitation the rights 11*31e17060SPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12*31e17060SPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is 13*31e17060SPaolo Bonzini * furnished to do so, subject to the following conditions: 14*31e17060SPaolo Bonzini * 15*31e17060SPaolo Bonzini * The above copyright notice and this permission notice shall be included in 16*31e17060SPaolo Bonzini * all copies or substantial portions of the Software. 17*31e17060SPaolo Bonzini * 18*31e17060SPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19*31e17060SPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20*31e17060SPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21*31e17060SPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22*31e17060SPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23*31e17060SPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24*31e17060SPaolo Bonzini * THE SOFTWARE. 25*31e17060SPaolo Bonzini */ 26*31e17060SPaolo Bonzini 27*31e17060SPaolo Bonzini #include "hw/sysbus.h" 28*31e17060SPaolo Bonzini #include "sysemu/sysemu.h" 29*31e17060SPaolo Bonzini #include "qemu/log.h" 30*31e17060SPaolo Bonzini #include "qemu/fifo8.h" 31*31e17060SPaolo Bonzini 32*31e17060SPaolo Bonzini #include "hw/ssi.h" 33*31e17060SPaolo Bonzini 34*31e17060SPaolo Bonzini #ifdef XILINX_SPI_ERR_DEBUG 35*31e17060SPaolo Bonzini #define DB_PRINT(...) do { \ 36*31e17060SPaolo Bonzini fprintf(stderr, ": %s: ", __func__); \ 37*31e17060SPaolo Bonzini fprintf(stderr, ## __VA_ARGS__); \ 38*31e17060SPaolo Bonzini } while (0); 39*31e17060SPaolo Bonzini #else 40*31e17060SPaolo Bonzini #define DB_PRINT(...) 41*31e17060SPaolo Bonzini #endif 42*31e17060SPaolo Bonzini 43*31e17060SPaolo Bonzini #define R_DGIER (0x1c / 4) 44*31e17060SPaolo Bonzini #define R_DGIER_IE (1 << 31) 45*31e17060SPaolo Bonzini 46*31e17060SPaolo Bonzini #define R_IPISR (0x20 / 4) 47*31e17060SPaolo Bonzini #define IRQ_DRR_NOT_EMPTY (1 << (31 - 23)) 48*31e17060SPaolo Bonzini #define IRQ_DRR_OVERRUN (1 << (31 - 26)) 49*31e17060SPaolo Bonzini #define IRQ_DRR_FULL (1 << (31 - 27)) 50*31e17060SPaolo Bonzini #define IRQ_TX_FF_HALF_EMPTY (1 << 6) 51*31e17060SPaolo Bonzini #define IRQ_DTR_UNDERRUN (1 << 3) 52*31e17060SPaolo Bonzini #define IRQ_DTR_EMPTY (1 << (31 - 29)) 53*31e17060SPaolo Bonzini 54*31e17060SPaolo Bonzini #define R_IPIER (0x28 / 4) 55*31e17060SPaolo Bonzini #define R_SRR (0x40 / 4) 56*31e17060SPaolo Bonzini #define R_SPICR (0x60 / 4) 57*31e17060SPaolo Bonzini #define R_SPICR_TXFF_RST (1 << 5) 58*31e17060SPaolo Bonzini #define R_SPICR_RXFF_RST (1 << 6) 59*31e17060SPaolo Bonzini #define R_SPICR_MTI (1 << 8) 60*31e17060SPaolo Bonzini 61*31e17060SPaolo Bonzini #define R_SPISR (0x64 / 4) 62*31e17060SPaolo Bonzini #define SR_TX_FULL (1 << 3) 63*31e17060SPaolo Bonzini #define SR_TX_EMPTY (1 << 2) 64*31e17060SPaolo Bonzini #define SR_RX_FULL (1 << 1) 65*31e17060SPaolo Bonzini #define SR_RX_EMPTY (1 << 0) 66*31e17060SPaolo Bonzini 67*31e17060SPaolo Bonzini #define R_SPIDTR (0x68 / 4) 68*31e17060SPaolo Bonzini #define R_SPIDRR (0x6C / 4) 69*31e17060SPaolo Bonzini #define R_SPISSR (0x70 / 4) 70*31e17060SPaolo Bonzini #define R_TX_FF_OCY (0x74 / 4) 71*31e17060SPaolo Bonzini #define R_RX_FF_OCY (0x78 / 4) 72*31e17060SPaolo Bonzini #define R_MAX (0x7C / 4) 73*31e17060SPaolo Bonzini 74*31e17060SPaolo Bonzini #define FIFO_CAPACITY 256 75*31e17060SPaolo Bonzini 76*31e17060SPaolo Bonzini typedef struct XilinxSPI { 77*31e17060SPaolo Bonzini SysBusDevice busdev; 78*31e17060SPaolo Bonzini MemoryRegion mmio; 79*31e17060SPaolo Bonzini 80*31e17060SPaolo Bonzini qemu_irq irq; 81*31e17060SPaolo Bonzini int irqline; 82*31e17060SPaolo Bonzini 83*31e17060SPaolo Bonzini uint8_t num_cs; 84*31e17060SPaolo Bonzini qemu_irq *cs_lines; 85*31e17060SPaolo Bonzini 86*31e17060SPaolo Bonzini SSIBus *spi; 87*31e17060SPaolo Bonzini 88*31e17060SPaolo Bonzini Fifo8 rx_fifo; 89*31e17060SPaolo Bonzini Fifo8 tx_fifo; 90*31e17060SPaolo Bonzini 91*31e17060SPaolo Bonzini uint32_t regs[R_MAX]; 92*31e17060SPaolo Bonzini } XilinxSPI; 93*31e17060SPaolo Bonzini 94*31e17060SPaolo Bonzini static void txfifo_reset(XilinxSPI *s) 95*31e17060SPaolo Bonzini { 96*31e17060SPaolo Bonzini fifo8_reset(&s->tx_fifo); 97*31e17060SPaolo Bonzini 98*31e17060SPaolo Bonzini s->regs[R_SPISR] &= ~SR_TX_FULL; 99*31e17060SPaolo Bonzini s->regs[R_SPISR] |= SR_TX_EMPTY; 100*31e17060SPaolo Bonzini } 101*31e17060SPaolo Bonzini 102*31e17060SPaolo Bonzini static void rxfifo_reset(XilinxSPI *s) 103*31e17060SPaolo Bonzini { 104*31e17060SPaolo Bonzini fifo8_reset(&s->rx_fifo); 105*31e17060SPaolo Bonzini 106*31e17060SPaolo Bonzini s->regs[R_SPISR] |= SR_RX_EMPTY; 107*31e17060SPaolo Bonzini s->regs[R_SPISR] &= ~SR_RX_FULL; 108*31e17060SPaolo Bonzini } 109*31e17060SPaolo Bonzini 110*31e17060SPaolo Bonzini static void xlx_spi_update_cs(XilinxSPI *s) 111*31e17060SPaolo Bonzini { 112*31e17060SPaolo Bonzini int i; 113*31e17060SPaolo Bonzini 114*31e17060SPaolo Bonzini for (i = 0; i < s->num_cs; ++i) { 115*31e17060SPaolo Bonzini qemu_set_irq(s->cs_lines[i], !(~s->regs[R_SPISSR] & 1 << i)); 116*31e17060SPaolo Bonzini } 117*31e17060SPaolo Bonzini } 118*31e17060SPaolo Bonzini 119*31e17060SPaolo Bonzini static void xlx_spi_update_irq(XilinxSPI *s) 120*31e17060SPaolo Bonzini { 121*31e17060SPaolo Bonzini uint32_t pending; 122*31e17060SPaolo Bonzini 123*31e17060SPaolo Bonzini s->regs[R_IPISR] |= 124*31e17060SPaolo Bonzini (!fifo8_is_empty(&s->rx_fifo) ? IRQ_DRR_NOT_EMPTY : 0) | 125*31e17060SPaolo Bonzini (fifo8_is_full(&s->rx_fifo) ? IRQ_DRR_FULL : 0); 126*31e17060SPaolo Bonzini 127*31e17060SPaolo Bonzini pending = s->regs[R_IPISR] & s->regs[R_IPIER]; 128*31e17060SPaolo Bonzini 129*31e17060SPaolo Bonzini pending = pending && (s->regs[R_DGIER] & R_DGIER_IE); 130*31e17060SPaolo Bonzini pending = !!pending; 131*31e17060SPaolo Bonzini 132*31e17060SPaolo Bonzini /* This call lies right in the data paths so don't call the 133*31e17060SPaolo Bonzini irq chain unless things really changed. */ 134*31e17060SPaolo Bonzini if (pending != s->irqline) { 135*31e17060SPaolo Bonzini s->irqline = pending; 136*31e17060SPaolo Bonzini DB_PRINT("irq_change of state %d ISR:%x IER:%X\n", 137*31e17060SPaolo Bonzini pending, s->regs[R_IPISR], s->regs[R_IPIER]); 138*31e17060SPaolo Bonzini qemu_set_irq(s->irq, pending); 139*31e17060SPaolo Bonzini } 140*31e17060SPaolo Bonzini 141*31e17060SPaolo Bonzini } 142*31e17060SPaolo Bonzini 143*31e17060SPaolo Bonzini static void xlx_spi_do_reset(XilinxSPI *s) 144*31e17060SPaolo Bonzini { 145*31e17060SPaolo Bonzini memset(s->regs, 0, sizeof s->regs); 146*31e17060SPaolo Bonzini 147*31e17060SPaolo Bonzini rxfifo_reset(s); 148*31e17060SPaolo Bonzini txfifo_reset(s); 149*31e17060SPaolo Bonzini 150*31e17060SPaolo Bonzini s->regs[R_SPISSR] = ~0; 151*31e17060SPaolo Bonzini xlx_spi_update_irq(s); 152*31e17060SPaolo Bonzini xlx_spi_update_cs(s); 153*31e17060SPaolo Bonzini } 154*31e17060SPaolo Bonzini 155*31e17060SPaolo Bonzini static void xlx_spi_reset(DeviceState *d) 156*31e17060SPaolo Bonzini { 157*31e17060SPaolo Bonzini xlx_spi_do_reset(DO_UPCAST(XilinxSPI, busdev.qdev, d)); 158*31e17060SPaolo Bonzini } 159*31e17060SPaolo Bonzini 160*31e17060SPaolo Bonzini static inline int spi_master_enabled(XilinxSPI *s) 161*31e17060SPaolo Bonzini { 162*31e17060SPaolo Bonzini return !(s->regs[R_SPICR] & R_SPICR_MTI); 163*31e17060SPaolo Bonzini } 164*31e17060SPaolo Bonzini 165*31e17060SPaolo Bonzini static void spi_flush_txfifo(XilinxSPI *s) 166*31e17060SPaolo Bonzini { 167*31e17060SPaolo Bonzini uint32_t tx; 168*31e17060SPaolo Bonzini uint32_t rx; 169*31e17060SPaolo Bonzini 170*31e17060SPaolo Bonzini while (!fifo8_is_empty(&s->tx_fifo)) { 171*31e17060SPaolo Bonzini tx = (uint32_t)fifo8_pop(&s->tx_fifo); 172*31e17060SPaolo Bonzini DB_PRINT("data tx:%x\n", tx); 173*31e17060SPaolo Bonzini rx = ssi_transfer(s->spi, tx); 174*31e17060SPaolo Bonzini DB_PRINT("data rx:%x\n", rx); 175*31e17060SPaolo Bonzini if (fifo8_is_full(&s->rx_fifo)) { 176*31e17060SPaolo Bonzini s->regs[R_IPISR] |= IRQ_DRR_OVERRUN; 177*31e17060SPaolo Bonzini } else { 178*31e17060SPaolo Bonzini fifo8_push(&s->rx_fifo, (uint8_t)rx); 179*31e17060SPaolo Bonzini if (fifo8_is_full(&s->rx_fifo)) { 180*31e17060SPaolo Bonzini s->regs[R_SPISR] |= SR_RX_FULL; 181*31e17060SPaolo Bonzini s->regs[R_IPISR] |= IRQ_DRR_FULL; 182*31e17060SPaolo Bonzini } 183*31e17060SPaolo Bonzini } 184*31e17060SPaolo Bonzini 185*31e17060SPaolo Bonzini s->regs[R_SPISR] &= ~SR_RX_EMPTY; 186*31e17060SPaolo Bonzini s->regs[R_SPISR] &= ~SR_TX_FULL; 187*31e17060SPaolo Bonzini s->regs[R_SPISR] |= SR_TX_EMPTY; 188*31e17060SPaolo Bonzini 189*31e17060SPaolo Bonzini s->regs[R_IPISR] |= IRQ_DTR_EMPTY; 190*31e17060SPaolo Bonzini s->regs[R_IPISR] |= IRQ_DRR_NOT_EMPTY; 191*31e17060SPaolo Bonzini } 192*31e17060SPaolo Bonzini 193*31e17060SPaolo Bonzini } 194*31e17060SPaolo Bonzini 195*31e17060SPaolo Bonzini static uint64_t 196*31e17060SPaolo Bonzini spi_read(void *opaque, hwaddr addr, unsigned int size) 197*31e17060SPaolo Bonzini { 198*31e17060SPaolo Bonzini XilinxSPI *s = opaque; 199*31e17060SPaolo Bonzini uint32_t r = 0; 200*31e17060SPaolo Bonzini 201*31e17060SPaolo Bonzini addr >>= 2; 202*31e17060SPaolo Bonzini switch (addr) { 203*31e17060SPaolo Bonzini case R_SPIDRR: 204*31e17060SPaolo Bonzini if (fifo8_is_empty(&s->rx_fifo)) { 205*31e17060SPaolo Bonzini DB_PRINT("Read from empty FIFO!\n"); 206*31e17060SPaolo Bonzini return 0xdeadbeef; 207*31e17060SPaolo Bonzini } 208*31e17060SPaolo Bonzini 209*31e17060SPaolo Bonzini s->regs[R_SPISR] &= ~SR_RX_FULL; 210*31e17060SPaolo Bonzini r = fifo8_pop(&s->rx_fifo); 211*31e17060SPaolo Bonzini if (fifo8_is_empty(&s->rx_fifo)) { 212*31e17060SPaolo Bonzini s->regs[R_SPISR] |= SR_RX_EMPTY; 213*31e17060SPaolo Bonzini } 214*31e17060SPaolo Bonzini break; 215*31e17060SPaolo Bonzini 216*31e17060SPaolo Bonzini case R_SPISR: 217*31e17060SPaolo Bonzini r = s->regs[addr]; 218*31e17060SPaolo Bonzini break; 219*31e17060SPaolo Bonzini 220*31e17060SPaolo Bonzini default: 221*31e17060SPaolo Bonzini if (addr < ARRAY_SIZE(s->regs)) { 222*31e17060SPaolo Bonzini r = s->regs[addr]; 223*31e17060SPaolo Bonzini } 224*31e17060SPaolo Bonzini break; 225*31e17060SPaolo Bonzini 226*31e17060SPaolo Bonzini } 227*31e17060SPaolo Bonzini DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr * 4, r); 228*31e17060SPaolo Bonzini xlx_spi_update_irq(s); 229*31e17060SPaolo Bonzini return r; 230*31e17060SPaolo Bonzini } 231*31e17060SPaolo Bonzini 232*31e17060SPaolo Bonzini static void 233*31e17060SPaolo Bonzini spi_write(void *opaque, hwaddr addr, 234*31e17060SPaolo Bonzini uint64_t val64, unsigned int size) 235*31e17060SPaolo Bonzini { 236*31e17060SPaolo Bonzini XilinxSPI *s = opaque; 237*31e17060SPaolo Bonzini uint32_t value = val64; 238*31e17060SPaolo Bonzini 239*31e17060SPaolo Bonzini DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr, value); 240*31e17060SPaolo Bonzini addr >>= 2; 241*31e17060SPaolo Bonzini switch (addr) { 242*31e17060SPaolo Bonzini case R_SRR: 243*31e17060SPaolo Bonzini if (value != 0xa) { 244*31e17060SPaolo Bonzini DB_PRINT("Invalid write to SRR %x\n", value); 245*31e17060SPaolo Bonzini } else { 246*31e17060SPaolo Bonzini xlx_spi_do_reset(s); 247*31e17060SPaolo Bonzini } 248*31e17060SPaolo Bonzini break; 249*31e17060SPaolo Bonzini 250*31e17060SPaolo Bonzini case R_SPIDTR: 251*31e17060SPaolo Bonzini s->regs[R_SPISR] &= ~SR_TX_EMPTY; 252*31e17060SPaolo Bonzini fifo8_push(&s->tx_fifo, (uint8_t)value); 253*31e17060SPaolo Bonzini if (fifo8_is_full(&s->tx_fifo)) { 254*31e17060SPaolo Bonzini s->regs[R_SPISR] |= SR_TX_FULL; 255*31e17060SPaolo Bonzini } 256*31e17060SPaolo Bonzini if (!spi_master_enabled(s)) { 257*31e17060SPaolo Bonzini goto done; 258*31e17060SPaolo Bonzini } else { 259*31e17060SPaolo Bonzini DB_PRINT("DTR and master enabled\n"); 260*31e17060SPaolo Bonzini } 261*31e17060SPaolo Bonzini spi_flush_txfifo(s); 262*31e17060SPaolo Bonzini break; 263*31e17060SPaolo Bonzini 264*31e17060SPaolo Bonzini case R_SPISR: 265*31e17060SPaolo Bonzini DB_PRINT("Invalid write to SPISR %x\n", value); 266*31e17060SPaolo Bonzini break; 267*31e17060SPaolo Bonzini 268*31e17060SPaolo Bonzini case R_IPISR: 269*31e17060SPaolo Bonzini /* Toggle the bits. */ 270*31e17060SPaolo Bonzini s->regs[addr] ^= value; 271*31e17060SPaolo Bonzini break; 272*31e17060SPaolo Bonzini 273*31e17060SPaolo Bonzini /* Slave Select Register. */ 274*31e17060SPaolo Bonzini case R_SPISSR: 275*31e17060SPaolo Bonzini s->regs[addr] = value; 276*31e17060SPaolo Bonzini xlx_spi_update_cs(s); 277*31e17060SPaolo Bonzini break; 278*31e17060SPaolo Bonzini 279*31e17060SPaolo Bonzini case R_SPICR: 280*31e17060SPaolo Bonzini /* FIXME: reset irq and sr state to empty queues. */ 281*31e17060SPaolo Bonzini if (value & R_SPICR_RXFF_RST) { 282*31e17060SPaolo Bonzini rxfifo_reset(s); 283*31e17060SPaolo Bonzini } 284*31e17060SPaolo Bonzini 285*31e17060SPaolo Bonzini if (value & R_SPICR_TXFF_RST) { 286*31e17060SPaolo Bonzini txfifo_reset(s); 287*31e17060SPaolo Bonzini } 288*31e17060SPaolo Bonzini value &= ~(R_SPICR_RXFF_RST | R_SPICR_TXFF_RST); 289*31e17060SPaolo Bonzini s->regs[addr] = value; 290*31e17060SPaolo Bonzini 291*31e17060SPaolo Bonzini if (!(value & R_SPICR_MTI)) { 292*31e17060SPaolo Bonzini spi_flush_txfifo(s); 293*31e17060SPaolo Bonzini } 294*31e17060SPaolo Bonzini break; 295*31e17060SPaolo Bonzini 296*31e17060SPaolo Bonzini default: 297*31e17060SPaolo Bonzini if (addr < ARRAY_SIZE(s->regs)) { 298*31e17060SPaolo Bonzini s->regs[addr] = value; 299*31e17060SPaolo Bonzini } 300*31e17060SPaolo Bonzini break; 301*31e17060SPaolo Bonzini } 302*31e17060SPaolo Bonzini 303*31e17060SPaolo Bonzini done: 304*31e17060SPaolo Bonzini xlx_spi_update_irq(s); 305*31e17060SPaolo Bonzini } 306*31e17060SPaolo Bonzini 307*31e17060SPaolo Bonzini static const MemoryRegionOps spi_ops = { 308*31e17060SPaolo Bonzini .read = spi_read, 309*31e17060SPaolo Bonzini .write = spi_write, 310*31e17060SPaolo Bonzini .endianness = DEVICE_NATIVE_ENDIAN, 311*31e17060SPaolo Bonzini .valid = { 312*31e17060SPaolo Bonzini .min_access_size = 4, 313*31e17060SPaolo Bonzini .max_access_size = 4 314*31e17060SPaolo Bonzini } 315*31e17060SPaolo Bonzini }; 316*31e17060SPaolo Bonzini 317*31e17060SPaolo Bonzini static int xilinx_spi_init(SysBusDevice *dev) 318*31e17060SPaolo Bonzini { 319*31e17060SPaolo Bonzini int i; 320*31e17060SPaolo Bonzini XilinxSPI *s = FROM_SYSBUS(typeof(*s), dev); 321*31e17060SPaolo Bonzini 322*31e17060SPaolo Bonzini DB_PRINT("\n"); 323*31e17060SPaolo Bonzini 324*31e17060SPaolo Bonzini s->spi = ssi_create_bus(&dev->qdev, "spi"); 325*31e17060SPaolo Bonzini 326*31e17060SPaolo Bonzini sysbus_init_irq(dev, &s->irq); 327*31e17060SPaolo Bonzini s->cs_lines = g_new(qemu_irq, s->num_cs); 328*31e17060SPaolo Bonzini ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi); 329*31e17060SPaolo Bonzini for (i = 0; i < s->num_cs; ++i) { 330*31e17060SPaolo Bonzini sysbus_init_irq(dev, &s->cs_lines[i]); 331*31e17060SPaolo Bonzini } 332*31e17060SPaolo Bonzini 333*31e17060SPaolo Bonzini memory_region_init_io(&s->mmio, &spi_ops, s, "xilinx-spi", R_MAX * 4); 334*31e17060SPaolo Bonzini sysbus_init_mmio(dev, &s->mmio); 335*31e17060SPaolo Bonzini 336*31e17060SPaolo Bonzini s->irqline = -1; 337*31e17060SPaolo Bonzini 338*31e17060SPaolo Bonzini fifo8_create(&s->tx_fifo, FIFO_CAPACITY); 339*31e17060SPaolo Bonzini fifo8_create(&s->rx_fifo, FIFO_CAPACITY); 340*31e17060SPaolo Bonzini 341*31e17060SPaolo Bonzini return 0; 342*31e17060SPaolo Bonzini } 343*31e17060SPaolo Bonzini 344*31e17060SPaolo Bonzini static const VMStateDescription vmstate_xilinx_spi = { 345*31e17060SPaolo Bonzini .name = "xilinx_spi", 346*31e17060SPaolo Bonzini .version_id = 1, 347*31e17060SPaolo Bonzini .minimum_version_id = 1, 348*31e17060SPaolo Bonzini .minimum_version_id_old = 1, 349*31e17060SPaolo Bonzini .fields = (VMStateField[]) { 350*31e17060SPaolo Bonzini VMSTATE_FIFO8(tx_fifo, XilinxSPI), 351*31e17060SPaolo Bonzini VMSTATE_FIFO8(rx_fifo, XilinxSPI), 352*31e17060SPaolo Bonzini VMSTATE_UINT32_ARRAY(regs, XilinxSPI, R_MAX), 353*31e17060SPaolo Bonzini VMSTATE_END_OF_LIST() 354*31e17060SPaolo Bonzini } 355*31e17060SPaolo Bonzini }; 356*31e17060SPaolo Bonzini 357*31e17060SPaolo Bonzini static Property xilinx_spi_properties[] = { 358*31e17060SPaolo Bonzini DEFINE_PROP_UINT8("num-ss-bits", XilinxSPI, num_cs, 1), 359*31e17060SPaolo Bonzini DEFINE_PROP_END_OF_LIST(), 360*31e17060SPaolo Bonzini }; 361*31e17060SPaolo Bonzini 362*31e17060SPaolo Bonzini static void xilinx_spi_class_init(ObjectClass *klass, void *data) 363*31e17060SPaolo Bonzini { 364*31e17060SPaolo Bonzini DeviceClass *dc = DEVICE_CLASS(klass); 365*31e17060SPaolo Bonzini SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); 366*31e17060SPaolo Bonzini 367*31e17060SPaolo Bonzini k->init = xilinx_spi_init; 368*31e17060SPaolo Bonzini dc->reset = xlx_spi_reset; 369*31e17060SPaolo Bonzini dc->props = xilinx_spi_properties; 370*31e17060SPaolo Bonzini dc->vmsd = &vmstate_xilinx_spi; 371*31e17060SPaolo Bonzini } 372*31e17060SPaolo Bonzini 373*31e17060SPaolo Bonzini static const TypeInfo xilinx_spi_info = { 374*31e17060SPaolo Bonzini .name = "xlnx.xps-spi", 375*31e17060SPaolo Bonzini .parent = TYPE_SYS_BUS_DEVICE, 376*31e17060SPaolo Bonzini .instance_size = sizeof(XilinxSPI), 377*31e17060SPaolo Bonzini .class_init = xilinx_spi_class_init, 378*31e17060SPaolo Bonzini }; 379*31e17060SPaolo Bonzini 380*31e17060SPaolo Bonzini static void xilinx_spi_register_types(void) 381*31e17060SPaolo Bonzini { 382*31e17060SPaolo Bonzini type_register_static(&xilinx_spi_info); 383*31e17060SPaolo Bonzini } 384*31e17060SPaolo Bonzini 385*31e17060SPaolo Bonzini type_init(xilinx_spi_register_types) 386