131e17060SPaolo Bonzini /* 231e17060SPaolo Bonzini * QEMU model of the Xilinx SPI Controller 331e17060SPaolo Bonzini * 431e17060SPaolo Bonzini * Copyright (C) 2010 Edgar E. Iglesias. 531e17060SPaolo Bonzini * Copyright (C) 2012 Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com> 631e17060SPaolo Bonzini * Copyright (C) 2012 PetaLogix 731e17060SPaolo Bonzini * 831e17060SPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy 931e17060SPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal 1031e17060SPaolo Bonzini * in the Software without restriction, including without limitation the rights 1131e17060SPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1231e17060SPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is 1331e17060SPaolo Bonzini * furnished to do so, subject to the following conditions: 1431e17060SPaolo Bonzini * 1531e17060SPaolo Bonzini * The above copyright notice and this permission notice shall be included in 1631e17060SPaolo Bonzini * all copies or substantial portions of the Software. 1731e17060SPaolo Bonzini * 1831e17060SPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1931e17060SPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2031e17060SPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2131e17060SPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2231e17060SPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2331e17060SPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 2431e17060SPaolo Bonzini * THE SOFTWARE. 2531e17060SPaolo Bonzini */ 2631e17060SPaolo Bonzini 278ef94f0bSPeter Maydell #include "qemu/osdep.h" 2831e17060SPaolo Bonzini #include "hw/sysbus.h" 29d6454270SMarkus Armbruster #include "migration/vmstate.h" 3031e17060SPaolo Bonzini #include "qemu/log.h" 310b8fa32fSMarkus Armbruster #include "qemu/module.h" 3231e17060SPaolo Bonzini #include "qemu/fifo8.h" 3331e17060SPaolo Bonzini 3464552b6bSMarkus Armbruster #include "hw/irq.h" 35a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 368fd06719SAlistair Francis #include "hw/ssi/ssi.h" 37db1015e9SEduardo Habkost #include "qom/object.h" 3831e17060SPaolo Bonzini 3931e17060SPaolo Bonzini #ifdef XILINX_SPI_ERR_DEBUG 4031e17060SPaolo Bonzini #define DB_PRINT(...) do { \ 4131e17060SPaolo Bonzini fprintf(stderr, ": %s: ", __func__); \ 4231e17060SPaolo Bonzini fprintf(stderr, ## __VA_ARGS__); \ 432562755eSEric Blake } while (0) 4431e17060SPaolo Bonzini #else 4531e17060SPaolo Bonzini #define DB_PRINT(...) 4631e17060SPaolo Bonzini #endif 4731e17060SPaolo Bonzini 4831e17060SPaolo Bonzini #define R_DGIER (0x1c / 4) 4931e17060SPaolo Bonzini #define R_DGIER_IE (1 << 31) 5031e17060SPaolo Bonzini 5131e17060SPaolo Bonzini #define R_IPISR (0x20 / 4) 5231e17060SPaolo Bonzini #define IRQ_DRR_NOT_EMPTY (1 << (31 - 23)) 5331e17060SPaolo Bonzini #define IRQ_DRR_OVERRUN (1 << (31 - 26)) 5431e17060SPaolo Bonzini #define IRQ_DRR_FULL (1 << (31 - 27)) 5531e17060SPaolo Bonzini #define IRQ_TX_FF_HALF_EMPTY (1 << 6) 5631e17060SPaolo Bonzini #define IRQ_DTR_UNDERRUN (1 << 3) 5731e17060SPaolo Bonzini #define IRQ_DTR_EMPTY (1 << (31 - 29)) 5831e17060SPaolo Bonzini 5931e17060SPaolo Bonzini #define R_IPIER (0x28 / 4) 6031e17060SPaolo Bonzini #define R_SRR (0x40 / 4) 6131e17060SPaolo Bonzini #define R_SPICR (0x60 / 4) 6231e17060SPaolo Bonzini #define R_SPICR_TXFF_RST (1 << 5) 6331e17060SPaolo Bonzini #define R_SPICR_RXFF_RST (1 << 6) 6431e17060SPaolo Bonzini #define R_SPICR_MTI (1 << 8) 6531e17060SPaolo Bonzini 6631e17060SPaolo Bonzini #define R_SPISR (0x64 / 4) 6731e17060SPaolo Bonzini #define SR_TX_FULL (1 << 3) 6831e17060SPaolo Bonzini #define SR_TX_EMPTY (1 << 2) 6931e17060SPaolo Bonzini #define SR_RX_FULL (1 << 1) 7031e17060SPaolo Bonzini #define SR_RX_EMPTY (1 << 0) 7131e17060SPaolo Bonzini 7231e17060SPaolo Bonzini #define R_SPIDTR (0x68 / 4) 7331e17060SPaolo Bonzini #define R_SPIDRR (0x6C / 4) 7431e17060SPaolo Bonzini #define R_SPISSR (0x70 / 4) 7531e17060SPaolo Bonzini #define R_TX_FF_OCY (0x74 / 4) 7631e17060SPaolo Bonzini #define R_RX_FF_OCY (0x78 / 4) 7731e17060SPaolo Bonzini #define R_MAX (0x7C / 4) 7831e17060SPaolo Bonzini 7931e17060SPaolo Bonzini #define FIFO_CAPACITY 256 8031e17060SPaolo Bonzini 813efc10e1SAndreas Färber #define TYPE_XILINX_SPI "xlnx.xps-spi" 82*8063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(XilinxSPI, XILINX_SPI) 833efc10e1SAndreas Färber 84db1015e9SEduardo Habkost struct XilinxSPI { 853efc10e1SAndreas Färber SysBusDevice parent_obj; 863efc10e1SAndreas Färber 8731e17060SPaolo Bonzini MemoryRegion mmio; 8831e17060SPaolo Bonzini 8931e17060SPaolo Bonzini qemu_irq irq; 9031e17060SPaolo Bonzini int irqline; 9131e17060SPaolo Bonzini 9231e17060SPaolo Bonzini uint8_t num_cs; 9331e17060SPaolo Bonzini qemu_irq *cs_lines; 9431e17060SPaolo Bonzini 9531e17060SPaolo Bonzini SSIBus *spi; 9631e17060SPaolo Bonzini 9731e17060SPaolo Bonzini Fifo8 rx_fifo; 9831e17060SPaolo Bonzini Fifo8 tx_fifo; 9931e17060SPaolo Bonzini 10031e17060SPaolo Bonzini uint32_t regs[R_MAX]; 101db1015e9SEduardo Habkost }; 10231e17060SPaolo Bonzini 10331e17060SPaolo Bonzini static void txfifo_reset(XilinxSPI *s) 10431e17060SPaolo Bonzini { 10531e17060SPaolo Bonzini fifo8_reset(&s->tx_fifo); 10631e17060SPaolo Bonzini 10731e17060SPaolo Bonzini s->regs[R_SPISR] &= ~SR_TX_FULL; 10831e17060SPaolo Bonzini s->regs[R_SPISR] |= SR_TX_EMPTY; 10931e17060SPaolo Bonzini } 11031e17060SPaolo Bonzini 11131e17060SPaolo Bonzini static void rxfifo_reset(XilinxSPI *s) 11231e17060SPaolo Bonzini { 11331e17060SPaolo Bonzini fifo8_reset(&s->rx_fifo); 11431e17060SPaolo Bonzini 11531e17060SPaolo Bonzini s->regs[R_SPISR] |= SR_RX_EMPTY; 11631e17060SPaolo Bonzini s->regs[R_SPISR] &= ~SR_RX_FULL; 11731e17060SPaolo Bonzini } 11831e17060SPaolo Bonzini 11931e17060SPaolo Bonzini static void xlx_spi_update_cs(XilinxSPI *s) 12031e17060SPaolo Bonzini { 12131e17060SPaolo Bonzini int i; 12231e17060SPaolo Bonzini 12331e17060SPaolo Bonzini for (i = 0; i < s->num_cs; ++i) { 12431e17060SPaolo Bonzini qemu_set_irq(s->cs_lines[i], !(~s->regs[R_SPISSR] & 1 << i)); 12531e17060SPaolo Bonzini } 12631e17060SPaolo Bonzini } 12731e17060SPaolo Bonzini 12831e17060SPaolo Bonzini static void xlx_spi_update_irq(XilinxSPI *s) 12931e17060SPaolo Bonzini { 13031e17060SPaolo Bonzini uint32_t pending; 13131e17060SPaolo Bonzini 13231e17060SPaolo Bonzini s->regs[R_IPISR] |= 13331e17060SPaolo Bonzini (!fifo8_is_empty(&s->rx_fifo) ? IRQ_DRR_NOT_EMPTY : 0) | 13431e17060SPaolo Bonzini (fifo8_is_full(&s->rx_fifo) ? IRQ_DRR_FULL : 0); 13531e17060SPaolo Bonzini 13631e17060SPaolo Bonzini pending = s->regs[R_IPISR] & s->regs[R_IPIER]; 13731e17060SPaolo Bonzini 13831e17060SPaolo Bonzini pending = pending && (s->regs[R_DGIER] & R_DGIER_IE); 13931e17060SPaolo Bonzini pending = !!pending; 14031e17060SPaolo Bonzini 14131e17060SPaolo Bonzini /* This call lies right in the data paths so don't call the 14231e17060SPaolo Bonzini irq chain unless things really changed. */ 14331e17060SPaolo Bonzini if (pending != s->irqline) { 14431e17060SPaolo Bonzini s->irqline = pending; 14531e17060SPaolo Bonzini DB_PRINT("irq_change of state %d ISR:%x IER:%X\n", 14631e17060SPaolo Bonzini pending, s->regs[R_IPISR], s->regs[R_IPIER]); 14731e17060SPaolo Bonzini qemu_set_irq(s->irq, pending); 14831e17060SPaolo Bonzini } 14931e17060SPaolo Bonzini 15031e17060SPaolo Bonzini } 15131e17060SPaolo Bonzini 15231e17060SPaolo Bonzini static void xlx_spi_do_reset(XilinxSPI *s) 15331e17060SPaolo Bonzini { 15431e17060SPaolo Bonzini memset(s->regs, 0, sizeof s->regs); 15531e17060SPaolo Bonzini 15631e17060SPaolo Bonzini rxfifo_reset(s); 15731e17060SPaolo Bonzini txfifo_reset(s); 15831e17060SPaolo Bonzini 15931e17060SPaolo Bonzini s->regs[R_SPISSR] = ~0; 16031e17060SPaolo Bonzini xlx_spi_update_irq(s); 16131e17060SPaolo Bonzini xlx_spi_update_cs(s); 16231e17060SPaolo Bonzini } 16331e17060SPaolo Bonzini 16431e17060SPaolo Bonzini static void xlx_spi_reset(DeviceState *d) 16531e17060SPaolo Bonzini { 1663efc10e1SAndreas Färber xlx_spi_do_reset(XILINX_SPI(d)); 16731e17060SPaolo Bonzini } 16831e17060SPaolo Bonzini 16931e17060SPaolo Bonzini static inline int spi_master_enabled(XilinxSPI *s) 17031e17060SPaolo Bonzini { 17131e17060SPaolo Bonzini return !(s->regs[R_SPICR] & R_SPICR_MTI); 17231e17060SPaolo Bonzini } 17331e17060SPaolo Bonzini 17431e17060SPaolo Bonzini static void spi_flush_txfifo(XilinxSPI *s) 17531e17060SPaolo Bonzini { 17631e17060SPaolo Bonzini uint32_t tx; 17731e17060SPaolo Bonzini uint32_t rx; 17831e17060SPaolo Bonzini 17931e17060SPaolo Bonzini while (!fifo8_is_empty(&s->tx_fifo)) { 18031e17060SPaolo Bonzini tx = (uint32_t)fifo8_pop(&s->tx_fifo); 18131e17060SPaolo Bonzini DB_PRINT("data tx:%x\n", tx); 18231e17060SPaolo Bonzini rx = ssi_transfer(s->spi, tx); 18331e17060SPaolo Bonzini DB_PRINT("data rx:%x\n", rx); 18431e17060SPaolo Bonzini if (fifo8_is_full(&s->rx_fifo)) { 18531e17060SPaolo Bonzini s->regs[R_IPISR] |= IRQ_DRR_OVERRUN; 18631e17060SPaolo Bonzini } else { 18731e17060SPaolo Bonzini fifo8_push(&s->rx_fifo, (uint8_t)rx); 18831e17060SPaolo Bonzini if (fifo8_is_full(&s->rx_fifo)) { 18931e17060SPaolo Bonzini s->regs[R_SPISR] |= SR_RX_FULL; 19031e17060SPaolo Bonzini s->regs[R_IPISR] |= IRQ_DRR_FULL; 19131e17060SPaolo Bonzini } 19231e17060SPaolo Bonzini } 19331e17060SPaolo Bonzini 19431e17060SPaolo Bonzini s->regs[R_SPISR] &= ~SR_RX_EMPTY; 19531e17060SPaolo Bonzini s->regs[R_SPISR] &= ~SR_TX_FULL; 19631e17060SPaolo Bonzini s->regs[R_SPISR] |= SR_TX_EMPTY; 19731e17060SPaolo Bonzini 19831e17060SPaolo Bonzini s->regs[R_IPISR] |= IRQ_DTR_EMPTY; 19931e17060SPaolo Bonzini s->regs[R_IPISR] |= IRQ_DRR_NOT_EMPTY; 20031e17060SPaolo Bonzini } 20131e17060SPaolo Bonzini 20231e17060SPaolo Bonzini } 20331e17060SPaolo Bonzini 20431e17060SPaolo Bonzini static uint64_t 20531e17060SPaolo Bonzini spi_read(void *opaque, hwaddr addr, unsigned int size) 20631e17060SPaolo Bonzini { 20731e17060SPaolo Bonzini XilinxSPI *s = opaque; 20831e17060SPaolo Bonzini uint32_t r = 0; 20931e17060SPaolo Bonzini 21031e17060SPaolo Bonzini addr >>= 2; 21131e17060SPaolo Bonzini switch (addr) { 21231e17060SPaolo Bonzini case R_SPIDRR: 21331e17060SPaolo Bonzini if (fifo8_is_empty(&s->rx_fifo)) { 21431e17060SPaolo Bonzini DB_PRINT("Read from empty FIFO!\n"); 21531e17060SPaolo Bonzini return 0xdeadbeef; 21631e17060SPaolo Bonzini } 21731e17060SPaolo Bonzini 21831e17060SPaolo Bonzini s->regs[R_SPISR] &= ~SR_RX_FULL; 21931e17060SPaolo Bonzini r = fifo8_pop(&s->rx_fifo); 22031e17060SPaolo Bonzini if (fifo8_is_empty(&s->rx_fifo)) { 22131e17060SPaolo Bonzini s->regs[R_SPISR] |= SR_RX_EMPTY; 22231e17060SPaolo Bonzini } 22331e17060SPaolo Bonzini break; 22431e17060SPaolo Bonzini 22531e17060SPaolo Bonzini case R_SPISR: 22631e17060SPaolo Bonzini r = s->regs[addr]; 22731e17060SPaolo Bonzini break; 22831e17060SPaolo Bonzini 22931e17060SPaolo Bonzini default: 23031e17060SPaolo Bonzini if (addr < ARRAY_SIZE(s->regs)) { 23131e17060SPaolo Bonzini r = s->regs[addr]; 23231e17060SPaolo Bonzini } 23331e17060SPaolo Bonzini break; 23431e17060SPaolo Bonzini 23531e17060SPaolo Bonzini } 23631e17060SPaolo Bonzini DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr * 4, r); 23731e17060SPaolo Bonzini xlx_spi_update_irq(s); 23831e17060SPaolo Bonzini return r; 23931e17060SPaolo Bonzini } 24031e17060SPaolo Bonzini 24131e17060SPaolo Bonzini static void 24231e17060SPaolo Bonzini spi_write(void *opaque, hwaddr addr, 24331e17060SPaolo Bonzini uint64_t val64, unsigned int size) 24431e17060SPaolo Bonzini { 24531e17060SPaolo Bonzini XilinxSPI *s = opaque; 24631e17060SPaolo Bonzini uint32_t value = val64; 24731e17060SPaolo Bonzini 24831e17060SPaolo Bonzini DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr, value); 24931e17060SPaolo Bonzini addr >>= 2; 25031e17060SPaolo Bonzini switch (addr) { 25131e17060SPaolo Bonzini case R_SRR: 25231e17060SPaolo Bonzini if (value != 0xa) { 25331e17060SPaolo Bonzini DB_PRINT("Invalid write to SRR %x\n", value); 25431e17060SPaolo Bonzini } else { 25531e17060SPaolo Bonzini xlx_spi_do_reset(s); 25631e17060SPaolo Bonzini } 25731e17060SPaolo Bonzini break; 25831e17060SPaolo Bonzini 25931e17060SPaolo Bonzini case R_SPIDTR: 26031e17060SPaolo Bonzini s->regs[R_SPISR] &= ~SR_TX_EMPTY; 26131e17060SPaolo Bonzini fifo8_push(&s->tx_fifo, (uint8_t)value); 26231e17060SPaolo Bonzini if (fifo8_is_full(&s->tx_fifo)) { 26331e17060SPaolo Bonzini s->regs[R_SPISR] |= SR_TX_FULL; 26431e17060SPaolo Bonzini } 26531e17060SPaolo Bonzini if (!spi_master_enabled(s)) { 26631e17060SPaolo Bonzini goto done; 26731e17060SPaolo Bonzini } else { 26831e17060SPaolo Bonzini DB_PRINT("DTR and master enabled\n"); 26931e17060SPaolo Bonzini } 27031e17060SPaolo Bonzini spi_flush_txfifo(s); 27131e17060SPaolo Bonzini break; 27231e17060SPaolo Bonzini 27331e17060SPaolo Bonzini case R_SPISR: 27431e17060SPaolo Bonzini DB_PRINT("Invalid write to SPISR %x\n", value); 27531e17060SPaolo Bonzini break; 27631e17060SPaolo Bonzini 27731e17060SPaolo Bonzini case R_IPISR: 27831e17060SPaolo Bonzini /* Toggle the bits. */ 27931e17060SPaolo Bonzini s->regs[addr] ^= value; 28031e17060SPaolo Bonzini break; 28131e17060SPaolo Bonzini 28231e17060SPaolo Bonzini /* Slave Select Register. */ 28331e17060SPaolo Bonzini case R_SPISSR: 28431e17060SPaolo Bonzini s->regs[addr] = value; 28531e17060SPaolo Bonzini xlx_spi_update_cs(s); 28631e17060SPaolo Bonzini break; 28731e17060SPaolo Bonzini 28831e17060SPaolo Bonzini case R_SPICR: 28931e17060SPaolo Bonzini /* FIXME: reset irq and sr state to empty queues. */ 29031e17060SPaolo Bonzini if (value & R_SPICR_RXFF_RST) { 29131e17060SPaolo Bonzini rxfifo_reset(s); 29231e17060SPaolo Bonzini } 29331e17060SPaolo Bonzini 29431e17060SPaolo Bonzini if (value & R_SPICR_TXFF_RST) { 29531e17060SPaolo Bonzini txfifo_reset(s); 29631e17060SPaolo Bonzini } 29731e17060SPaolo Bonzini value &= ~(R_SPICR_RXFF_RST | R_SPICR_TXFF_RST); 29831e17060SPaolo Bonzini s->regs[addr] = value; 29931e17060SPaolo Bonzini 30031e17060SPaolo Bonzini if (!(value & R_SPICR_MTI)) { 30131e17060SPaolo Bonzini spi_flush_txfifo(s); 30231e17060SPaolo Bonzini } 30331e17060SPaolo Bonzini break; 30431e17060SPaolo Bonzini 30531e17060SPaolo Bonzini default: 30631e17060SPaolo Bonzini if (addr < ARRAY_SIZE(s->regs)) { 30731e17060SPaolo Bonzini s->regs[addr] = value; 30831e17060SPaolo Bonzini } 30931e17060SPaolo Bonzini break; 31031e17060SPaolo Bonzini } 31131e17060SPaolo Bonzini 31231e17060SPaolo Bonzini done: 31331e17060SPaolo Bonzini xlx_spi_update_irq(s); 31431e17060SPaolo Bonzini } 31531e17060SPaolo Bonzini 31631e17060SPaolo Bonzini static const MemoryRegionOps spi_ops = { 31731e17060SPaolo Bonzini .read = spi_read, 31831e17060SPaolo Bonzini .write = spi_write, 31931e17060SPaolo Bonzini .endianness = DEVICE_NATIVE_ENDIAN, 32031e17060SPaolo Bonzini .valid = { 32131e17060SPaolo Bonzini .min_access_size = 4, 32231e17060SPaolo Bonzini .max_access_size = 4 32331e17060SPaolo Bonzini } 32431e17060SPaolo Bonzini }; 32531e17060SPaolo Bonzini 326a7e1562cSPhilippe Mathieu-Daudé static void xilinx_spi_realize(DeviceState *dev, Error **errp) 32731e17060SPaolo Bonzini { 328a7e1562cSPhilippe Mathieu-Daudé SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 3293efc10e1SAndreas Färber XilinxSPI *s = XILINX_SPI(dev); 33031e17060SPaolo Bonzini int i; 33131e17060SPaolo Bonzini 33231e17060SPaolo Bonzini DB_PRINT("\n"); 33331e17060SPaolo Bonzini 3343efc10e1SAndreas Färber s->spi = ssi_create_bus(dev, "spi"); 33531e17060SPaolo Bonzini 3363efc10e1SAndreas Färber sysbus_init_irq(sbd, &s->irq); 337c75f3c04SPeter Crosthwaite s->cs_lines = g_new0(qemu_irq, s->num_cs); 33831e17060SPaolo Bonzini for (i = 0; i < s->num_cs; ++i) { 3393efc10e1SAndreas Färber sysbus_init_irq(sbd, &s->cs_lines[i]); 34031e17060SPaolo Bonzini } 34131e17060SPaolo Bonzini 34229776739SPaolo Bonzini memory_region_init_io(&s->mmio, OBJECT(s), &spi_ops, s, 34329776739SPaolo Bonzini "xilinx-spi", R_MAX * 4); 3443efc10e1SAndreas Färber sysbus_init_mmio(sbd, &s->mmio); 34531e17060SPaolo Bonzini 34631e17060SPaolo Bonzini s->irqline = -1; 34731e17060SPaolo Bonzini 34831e17060SPaolo Bonzini fifo8_create(&s->tx_fifo, FIFO_CAPACITY); 34931e17060SPaolo Bonzini fifo8_create(&s->rx_fifo, FIFO_CAPACITY); 35031e17060SPaolo Bonzini } 35131e17060SPaolo Bonzini 35231e17060SPaolo Bonzini static const VMStateDescription vmstate_xilinx_spi = { 35331e17060SPaolo Bonzini .name = "xilinx_spi", 35431e17060SPaolo Bonzini .version_id = 1, 35531e17060SPaolo Bonzini .minimum_version_id = 1, 35631e17060SPaolo Bonzini .fields = (VMStateField[]) { 35731e17060SPaolo Bonzini VMSTATE_FIFO8(tx_fifo, XilinxSPI), 35831e17060SPaolo Bonzini VMSTATE_FIFO8(rx_fifo, XilinxSPI), 35931e17060SPaolo Bonzini VMSTATE_UINT32_ARRAY(regs, XilinxSPI, R_MAX), 36031e17060SPaolo Bonzini VMSTATE_END_OF_LIST() 36131e17060SPaolo Bonzini } 36231e17060SPaolo Bonzini }; 36331e17060SPaolo Bonzini 36431e17060SPaolo Bonzini static Property xilinx_spi_properties[] = { 36531e17060SPaolo Bonzini DEFINE_PROP_UINT8("num-ss-bits", XilinxSPI, num_cs, 1), 36631e17060SPaolo Bonzini DEFINE_PROP_END_OF_LIST(), 36731e17060SPaolo Bonzini }; 36831e17060SPaolo Bonzini 36931e17060SPaolo Bonzini static void xilinx_spi_class_init(ObjectClass *klass, void *data) 37031e17060SPaolo Bonzini { 37131e17060SPaolo Bonzini DeviceClass *dc = DEVICE_CLASS(klass); 37231e17060SPaolo Bonzini 373a7e1562cSPhilippe Mathieu-Daudé dc->realize = xilinx_spi_realize; 37431e17060SPaolo Bonzini dc->reset = xlx_spi_reset; 3754f67d30bSMarc-André Lureau device_class_set_props(dc, xilinx_spi_properties); 37631e17060SPaolo Bonzini dc->vmsd = &vmstate_xilinx_spi; 37731e17060SPaolo Bonzini } 37831e17060SPaolo Bonzini 37931e17060SPaolo Bonzini static const TypeInfo xilinx_spi_info = { 3803efc10e1SAndreas Färber .name = TYPE_XILINX_SPI, 38131e17060SPaolo Bonzini .parent = TYPE_SYS_BUS_DEVICE, 38231e17060SPaolo Bonzini .instance_size = sizeof(XilinxSPI), 38331e17060SPaolo Bonzini .class_init = xilinx_spi_class_init, 38431e17060SPaolo Bonzini }; 38531e17060SPaolo Bonzini 38631e17060SPaolo Bonzini static void xilinx_spi_register_types(void) 38731e17060SPaolo Bonzini { 38831e17060SPaolo Bonzini type_register_static(&xilinx_spi_info); 38931e17060SPaolo Bonzini } 39031e17060SPaolo Bonzini 39131e17060SPaolo Bonzini type_init(xilinx_spi_register_types) 392