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 2731e17060SPaolo Bonzini #include "hw/sysbus.h" 2831e17060SPaolo Bonzini #include "sysemu/sysemu.h" 2931e17060SPaolo Bonzini #include "qemu/log.h" 3031e17060SPaolo Bonzini #include "qemu/fifo8.h" 3131e17060SPaolo Bonzini 3231e17060SPaolo Bonzini #include "hw/ssi.h" 3331e17060SPaolo Bonzini 3431e17060SPaolo Bonzini #ifdef XILINX_SPI_ERR_DEBUG 3531e17060SPaolo Bonzini #define DB_PRINT(...) do { \ 3631e17060SPaolo Bonzini fprintf(stderr, ": %s: ", __func__); \ 3731e17060SPaolo Bonzini fprintf(stderr, ## __VA_ARGS__); \ 3831e17060SPaolo Bonzini } while (0); 3931e17060SPaolo Bonzini #else 4031e17060SPaolo Bonzini #define DB_PRINT(...) 4131e17060SPaolo Bonzini #endif 4231e17060SPaolo Bonzini 4331e17060SPaolo Bonzini #define R_DGIER (0x1c / 4) 4431e17060SPaolo Bonzini #define R_DGIER_IE (1 << 31) 4531e17060SPaolo Bonzini 4631e17060SPaolo Bonzini #define R_IPISR (0x20 / 4) 4731e17060SPaolo Bonzini #define IRQ_DRR_NOT_EMPTY (1 << (31 - 23)) 4831e17060SPaolo Bonzini #define IRQ_DRR_OVERRUN (1 << (31 - 26)) 4931e17060SPaolo Bonzini #define IRQ_DRR_FULL (1 << (31 - 27)) 5031e17060SPaolo Bonzini #define IRQ_TX_FF_HALF_EMPTY (1 << 6) 5131e17060SPaolo Bonzini #define IRQ_DTR_UNDERRUN (1 << 3) 5231e17060SPaolo Bonzini #define IRQ_DTR_EMPTY (1 << (31 - 29)) 5331e17060SPaolo Bonzini 5431e17060SPaolo Bonzini #define R_IPIER (0x28 / 4) 5531e17060SPaolo Bonzini #define R_SRR (0x40 / 4) 5631e17060SPaolo Bonzini #define R_SPICR (0x60 / 4) 5731e17060SPaolo Bonzini #define R_SPICR_TXFF_RST (1 << 5) 5831e17060SPaolo Bonzini #define R_SPICR_RXFF_RST (1 << 6) 5931e17060SPaolo Bonzini #define R_SPICR_MTI (1 << 8) 6031e17060SPaolo Bonzini 6131e17060SPaolo Bonzini #define R_SPISR (0x64 / 4) 6231e17060SPaolo Bonzini #define SR_TX_FULL (1 << 3) 6331e17060SPaolo Bonzini #define SR_TX_EMPTY (1 << 2) 6431e17060SPaolo Bonzini #define SR_RX_FULL (1 << 1) 6531e17060SPaolo Bonzini #define SR_RX_EMPTY (1 << 0) 6631e17060SPaolo Bonzini 6731e17060SPaolo Bonzini #define R_SPIDTR (0x68 / 4) 6831e17060SPaolo Bonzini #define R_SPIDRR (0x6C / 4) 6931e17060SPaolo Bonzini #define R_SPISSR (0x70 / 4) 7031e17060SPaolo Bonzini #define R_TX_FF_OCY (0x74 / 4) 7131e17060SPaolo Bonzini #define R_RX_FF_OCY (0x78 / 4) 7231e17060SPaolo Bonzini #define R_MAX (0x7C / 4) 7331e17060SPaolo Bonzini 7431e17060SPaolo Bonzini #define FIFO_CAPACITY 256 7531e17060SPaolo Bonzini 763efc10e1SAndreas Färber #define TYPE_XILINX_SPI "xlnx.xps-spi" 773efc10e1SAndreas Färber #define XILINX_SPI(obj) OBJECT_CHECK(XilinxSPI, (obj), TYPE_XILINX_SPI) 783efc10e1SAndreas Färber 7931e17060SPaolo Bonzini typedef struct XilinxSPI { 803efc10e1SAndreas Färber SysBusDevice parent_obj; 813efc10e1SAndreas Färber 8231e17060SPaolo Bonzini MemoryRegion mmio; 8331e17060SPaolo Bonzini 8431e17060SPaolo Bonzini qemu_irq irq; 8531e17060SPaolo Bonzini int irqline; 8631e17060SPaolo Bonzini 8731e17060SPaolo Bonzini uint8_t num_cs; 8831e17060SPaolo Bonzini qemu_irq *cs_lines; 8931e17060SPaolo Bonzini 9031e17060SPaolo Bonzini SSIBus *spi; 9131e17060SPaolo Bonzini 9231e17060SPaolo Bonzini Fifo8 rx_fifo; 9331e17060SPaolo Bonzini Fifo8 tx_fifo; 9431e17060SPaolo Bonzini 9531e17060SPaolo Bonzini uint32_t regs[R_MAX]; 9631e17060SPaolo Bonzini } XilinxSPI; 9731e17060SPaolo Bonzini 9831e17060SPaolo Bonzini static void txfifo_reset(XilinxSPI *s) 9931e17060SPaolo Bonzini { 10031e17060SPaolo Bonzini fifo8_reset(&s->tx_fifo); 10131e17060SPaolo Bonzini 10231e17060SPaolo Bonzini s->regs[R_SPISR] &= ~SR_TX_FULL; 10331e17060SPaolo Bonzini s->regs[R_SPISR] |= SR_TX_EMPTY; 10431e17060SPaolo Bonzini } 10531e17060SPaolo Bonzini 10631e17060SPaolo Bonzini static void rxfifo_reset(XilinxSPI *s) 10731e17060SPaolo Bonzini { 10831e17060SPaolo Bonzini fifo8_reset(&s->rx_fifo); 10931e17060SPaolo Bonzini 11031e17060SPaolo Bonzini s->regs[R_SPISR] |= SR_RX_EMPTY; 11131e17060SPaolo Bonzini s->regs[R_SPISR] &= ~SR_RX_FULL; 11231e17060SPaolo Bonzini } 11331e17060SPaolo Bonzini 11431e17060SPaolo Bonzini static void xlx_spi_update_cs(XilinxSPI *s) 11531e17060SPaolo Bonzini { 11631e17060SPaolo Bonzini int i; 11731e17060SPaolo Bonzini 11831e17060SPaolo Bonzini for (i = 0; i < s->num_cs; ++i) { 11931e17060SPaolo Bonzini qemu_set_irq(s->cs_lines[i], !(~s->regs[R_SPISSR] & 1 << i)); 12031e17060SPaolo Bonzini } 12131e17060SPaolo Bonzini } 12231e17060SPaolo Bonzini 12331e17060SPaolo Bonzini static void xlx_spi_update_irq(XilinxSPI *s) 12431e17060SPaolo Bonzini { 12531e17060SPaolo Bonzini uint32_t pending; 12631e17060SPaolo Bonzini 12731e17060SPaolo Bonzini s->regs[R_IPISR] |= 12831e17060SPaolo Bonzini (!fifo8_is_empty(&s->rx_fifo) ? IRQ_DRR_NOT_EMPTY : 0) | 12931e17060SPaolo Bonzini (fifo8_is_full(&s->rx_fifo) ? IRQ_DRR_FULL : 0); 13031e17060SPaolo Bonzini 13131e17060SPaolo Bonzini pending = s->regs[R_IPISR] & s->regs[R_IPIER]; 13231e17060SPaolo Bonzini 13331e17060SPaolo Bonzini pending = pending && (s->regs[R_DGIER] & R_DGIER_IE); 13431e17060SPaolo Bonzini pending = !!pending; 13531e17060SPaolo Bonzini 13631e17060SPaolo Bonzini /* This call lies right in the data paths so don't call the 13731e17060SPaolo Bonzini irq chain unless things really changed. */ 13831e17060SPaolo Bonzini if (pending != s->irqline) { 13931e17060SPaolo Bonzini s->irqline = pending; 14031e17060SPaolo Bonzini DB_PRINT("irq_change of state %d ISR:%x IER:%X\n", 14131e17060SPaolo Bonzini pending, s->regs[R_IPISR], s->regs[R_IPIER]); 14231e17060SPaolo Bonzini qemu_set_irq(s->irq, pending); 14331e17060SPaolo Bonzini } 14431e17060SPaolo Bonzini 14531e17060SPaolo Bonzini } 14631e17060SPaolo Bonzini 14731e17060SPaolo Bonzini static void xlx_spi_do_reset(XilinxSPI *s) 14831e17060SPaolo Bonzini { 14931e17060SPaolo Bonzini memset(s->regs, 0, sizeof s->regs); 15031e17060SPaolo Bonzini 15131e17060SPaolo Bonzini rxfifo_reset(s); 15231e17060SPaolo Bonzini txfifo_reset(s); 15331e17060SPaolo Bonzini 15431e17060SPaolo Bonzini s->regs[R_SPISSR] = ~0; 15531e17060SPaolo Bonzini xlx_spi_update_irq(s); 15631e17060SPaolo Bonzini xlx_spi_update_cs(s); 15731e17060SPaolo Bonzini } 15831e17060SPaolo Bonzini 15931e17060SPaolo Bonzini static void xlx_spi_reset(DeviceState *d) 16031e17060SPaolo Bonzini { 1613efc10e1SAndreas Färber xlx_spi_do_reset(XILINX_SPI(d)); 16231e17060SPaolo Bonzini } 16331e17060SPaolo Bonzini 16431e17060SPaolo Bonzini static inline int spi_master_enabled(XilinxSPI *s) 16531e17060SPaolo Bonzini { 16631e17060SPaolo Bonzini return !(s->regs[R_SPICR] & R_SPICR_MTI); 16731e17060SPaolo Bonzini } 16831e17060SPaolo Bonzini 16931e17060SPaolo Bonzini static void spi_flush_txfifo(XilinxSPI *s) 17031e17060SPaolo Bonzini { 17131e17060SPaolo Bonzini uint32_t tx; 17231e17060SPaolo Bonzini uint32_t rx; 17331e17060SPaolo Bonzini 17431e17060SPaolo Bonzini while (!fifo8_is_empty(&s->tx_fifo)) { 17531e17060SPaolo Bonzini tx = (uint32_t)fifo8_pop(&s->tx_fifo); 17631e17060SPaolo Bonzini DB_PRINT("data tx:%x\n", tx); 17731e17060SPaolo Bonzini rx = ssi_transfer(s->spi, tx); 17831e17060SPaolo Bonzini DB_PRINT("data rx:%x\n", rx); 17931e17060SPaolo Bonzini if (fifo8_is_full(&s->rx_fifo)) { 18031e17060SPaolo Bonzini s->regs[R_IPISR] |= IRQ_DRR_OVERRUN; 18131e17060SPaolo Bonzini } else { 18231e17060SPaolo Bonzini fifo8_push(&s->rx_fifo, (uint8_t)rx); 18331e17060SPaolo Bonzini if (fifo8_is_full(&s->rx_fifo)) { 18431e17060SPaolo Bonzini s->regs[R_SPISR] |= SR_RX_FULL; 18531e17060SPaolo Bonzini s->regs[R_IPISR] |= IRQ_DRR_FULL; 18631e17060SPaolo Bonzini } 18731e17060SPaolo Bonzini } 18831e17060SPaolo Bonzini 18931e17060SPaolo Bonzini s->regs[R_SPISR] &= ~SR_RX_EMPTY; 19031e17060SPaolo Bonzini s->regs[R_SPISR] &= ~SR_TX_FULL; 19131e17060SPaolo Bonzini s->regs[R_SPISR] |= SR_TX_EMPTY; 19231e17060SPaolo Bonzini 19331e17060SPaolo Bonzini s->regs[R_IPISR] |= IRQ_DTR_EMPTY; 19431e17060SPaolo Bonzini s->regs[R_IPISR] |= IRQ_DRR_NOT_EMPTY; 19531e17060SPaolo Bonzini } 19631e17060SPaolo Bonzini 19731e17060SPaolo Bonzini } 19831e17060SPaolo Bonzini 19931e17060SPaolo Bonzini static uint64_t 20031e17060SPaolo Bonzini spi_read(void *opaque, hwaddr addr, unsigned int size) 20131e17060SPaolo Bonzini { 20231e17060SPaolo Bonzini XilinxSPI *s = opaque; 20331e17060SPaolo Bonzini uint32_t r = 0; 20431e17060SPaolo Bonzini 20531e17060SPaolo Bonzini addr >>= 2; 20631e17060SPaolo Bonzini switch (addr) { 20731e17060SPaolo Bonzini case R_SPIDRR: 20831e17060SPaolo Bonzini if (fifo8_is_empty(&s->rx_fifo)) { 20931e17060SPaolo Bonzini DB_PRINT("Read from empty FIFO!\n"); 21031e17060SPaolo Bonzini return 0xdeadbeef; 21131e17060SPaolo Bonzini } 21231e17060SPaolo Bonzini 21331e17060SPaolo Bonzini s->regs[R_SPISR] &= ~SR_RX_FULL; 21431e17060SPaolo Bonzini r = fifo8_pop(&s->rx_fifo); 21531e17060SPaolo Bonzini if (fifo8_is_empty(&s->rx_fifo)) { 21631e17060SPaolo Bonzini s->regs[R_SPISR] |= SR_RX_EMPTY; 21731e17060SPaolo Bonzini } 21831e17060SPaolo Bonzini break; 21931e17060SPaolo Bonzini 22031e17060SPaolo Bonzini case R_SPISR: 22131e17060SPaolo Bonzini r = s->regs[addr]; 22231e17060SPaolo Bonzini break; 22331e17060SPaolo Bonzini 22431e17060SPaolo Bonzini default: 22531e17060SPaolo Bonzini if (addr < ARRAY_SIZE(s->regs)) { 22631e17060SPaolo Bonzini r = s->regs[addr]; 22731e17060SPaolo Bonzini } 22831e17060SPaolo Bonzini break; 22931e17060SPaolo Bonzini 23031e17060SPaolo Bonzini } 23131e17060SPaolo Bonzini DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr * 4, r); 23231e17060SPaolo Bonzini xlx_spi_update_irq(s); 23331e17060SPaolo Bonzini return r; 23431e17060SPaolo Bonzini } 23531e17060SPaolo Bonzini 23631e17060SPaolo Bonzini static void 23731e17060SPaolo Bonzini spi_write(void *opaque, hwaddr addr, 23831e17060SPaolo Bonzini uint64_t val64, unsigned int size) 23931e17060SPaolo Bonzini { 24031e17060SPaolo Bonzini XilinxSPI *s = opaque; 24131e17060SPaolo Bonzini uint32_t value = val64; 24231e17060SPaolo Bonzini 24331e17060SPaolo Bonzini DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr, value); 24431e17060SPaolo Bonzini addr >>= 2; 24531e17060SPaolo Bonzini switch (addr) { 24631e17060SPaolo Bonzini case R_SRR: 24731e17060SPaolo Bonzini if (value != 0xa) { 24831e17060SPaolo Bonzini DB_PRINT("Invalid write to SRR %x\n", value); 24931e17060SPaolo Bonzini } else { 25031e17060SPaolo Bonzini xlx_spi_do_reset(s); 25131e17060SPaolo Bonzini } 25231e17060SPaolo Bonzini break; 25331e17060SPaolo Bonzini 25431e17060SPaolo Bonzini case R_SPIDTR: 25531e17060SPaolo Bonzini s->regs[R_SPISR] &= ~SR_TX_EMPTY; 25631e17060SPaolo Bonzini fifo8_push(&s->tx_fifo, (uint8_t)value); 25731e17060SPaolo Bonzini if (fifo8_is_full(&s->tx_fifo)) { 25831e17060SPaolo Bonzini s->regs[R_SPISR] |= SR_TX_FULL; 25931e17060SPaolo Bonzini } 26031e17060SPaolo Bonzini if (!spi_master_enabled(s)) { 26131e17060SPaolo Bonzini goto done; 26231e17060SPaolo Bonzini } else { 26331e17060SPaolo Bonzini DB_PRINT("DTR and master enabled\n"); 26431e17060SPaolo Bonzini } 26531e17060SPaolo Bonzini spi_flush_txfifo(s); 26631e17060SPaolo Bonzini break; 26731e17060SPaolo Bonzini 26831e17060SPaolo Bonzini case R_SPISR: 26931e17060SPaolo Bonzini DB_PRINT("Invalid write to SPISR %x\n", value); 27031e17060SPaolo Bonzini break; 27131e17060SPaolo Bonzini 27231e17060SPaolo Bonzini case R_IPISR: 27331e17060SPaolo Bonzini /* Toggle the bits. */ 27431e17060SPaolo Bonzini s->regs[addr] ^= value; 27531e17060SPaolo Bonzini break; 27631e17060SPaolo Bonzini 27731e17060SPaolo Bonzini /* Slave Select Register. */ 27831e17060SPaolo Bonzini case R_SPISSR: 27931e17060SPaolo Bonzini s->regs[addr] = value; 28031e17060SPaolo Bonzini xlx_spi_update_cs(s); 28131e17060SPaolo Bonzini break; 28231e17060SPaolo Bonzini 28331e17060SPaolo Bonzini case R_SPICR: 28431e17060SPaolo Bonzini /* FIXME: reset irq and sr state to empty queues. */ 28531e17060SPaolo Bonzini if (value & R_SPICR_RXFF_RST) { 28631e17060SPaolo Bonzini rxfifo_reset(s); 28731e17060SPaolo Bonzini } 28831e17060SPaolo Bonzini 28931e17060SPaolo Bonzini if (value & R_SPICR_TXFF_RST) { 29031e17060SPaolo Bonzini txfifo_reset(s); 29131e17060SPaolo Bonzini } 29231e17060SPaolo Bonzini value &= ~(R_SPICR_RXFF_RST | R_SPICR_TXFF_RST); 29331e17060SPaolo Bonzini s->regs[addr] = value; 29431e17060SPaolo Bonzini 29531e17060SPaolo Bonzini if (!(value & R_SPICR_MTI)) { 29631e17060SPaolo Bonzini spi_flush_txfifo(s); 29731e17060SPaolo Bonzini } 29831e17060SPaolo Bonzini break; 29931e17060SPaolo Bonzini 30031e17060SPaolo Bonzini default: 30131e17060SPaolo Bonzini if (addr < ARRAY_SIZE(s->regs)) { 30231e17060SPaolo Bonzini s->regs[addr] = value; 30331e17060SPaolo Bonzini } 30431e17060SPaolo Bonzini break; 30531e17060SPaolo Bonzini } 30631e17060SPaolo Bonzini 30731e17060SPaolo Bonzini done: 30831e17060SPaolo Bonzini xlx_spi_update_irq(s); 30931e17060SPaolo Bonzini } 31031e17060SPaolo Bonzini 31131e17060SPaolo Bonzini static const MemoryRegionOps spi_ops = { 31231e17060SPaolo Bonzini .read = spi_read, 31331e17060SPaolo Bonzini .write = spi_write, 31431e17060SPaolo Bonzini .endianness = DEVICE_NATIVE_ENDIAN, 31531e17060SPaolo Bonzini .valid = { 31631e17060SPaolo Bonzini .min_access_size = 4, 31731e17060SPaolo Bonzini .max_access_size = 4 31831e17060SPaolo Bonzini } 31931e17060SPaolo Bonzini }; 32031e17060SPaolo Bonzini 3213efc10e1SAndreas Färber static int xilinx_spi_init(SysBusDevice *sbd) 32231e17060SPaolo Bonzini { 3233efc10e1SAndreas Färber DeviceState *dev = DEVICE(sbd); 3243efc10e1SAndreas Färber XilinxSPI *s = XILINX_SPI(dev); 32531e17060SPaolo Bonzini int i; 32631e17060SPaolo Bonzini 32731e17060SPaolo Bonzini DB_PRINT("\n"); 32831e17060SPaolo Bonzini 3293efc10e1SAndreas Färber s->spi = ssi_create_bus(dev, "spi"); 33031e17060SPaolo Bonzini 3313efc10e1SAndreas Färber sysbus_init_irq(sbd, &s->irq); 332*c75f3c04SPeter Crosthwaite s->cs_lines = g_new0(qemu_irq, s->num_cs); 3333efc10e1SAndreas Färber ssi_auto_connect_slaves(dev, s->cs_lines, s->spi); 33431e17060SPaolo Bonzini for (i = 0; i < s->num_cs; ++i) { 3353efc10e1SAndreas Färber sysbus_init_irq(sbd, &s->cs_lines[i]); 33631e17060SPaolo Bonzini } 33731e17060SPaolo Bonzini 33829776739SPaolo Bonzini memory_region_init_io(&s->mmio, OBJECT(s), &spi_ops, s, 33929776739SPaolo Bonzini "xilinx-spi", R_MAX * 4); 3403efc10e1SAndreas Färber sysbus_init_mmio(sbd, &s->mmio); 34131e17060SPaolo Bonzini 34231e17060SPaolo Bonzini s->irqline = -1; 34331e17060SPaolo Bonzini 34431e17060SPaolo Bonzini fifo8_create(&s->tx_fifo, FIFO_CAPACITY); 34531e17060SPaolo Bonzini fifo8_create(&s->rx_fifo, FIFO_CAPACITY); 34631e17060SPaolo Bonzini 34731e17060SPaolo Bonzini return 0; 34831e17060SPaolo Bonzini } 34931e17060SPaolo Bonzini 35031e17060SPaolo Bonzini static const VMStateDescription vmstate_xilinx_spi = { 35131e17060SPaolo Bonzini .name = "xilinx_spi", 35231e17060SPaolo Bonzini .version_id = 1, 35331e17060SPaolo Bonzini .minimum_version_id = 1, 35431e17060SPaolo Bonzini .fields = (VMStateField[]) { 35531e17060SPaolo Bonzini VMSTATE_FIFO8(tx_fifo, XilinxSPI), 35631e17060SPaolo Bonzini VMSTATE_FIFO8(rx_fifo, XilinxSPI), 35731e17060SPaolo Bonzini VMSTATE_UINT32_ARRAY(regs, XilinxSPI, R_MAX), 35831e17060SPaolo Bonzini VMSTATE_END_OF_LIST() 35931e17060SPaolo Bonzini } 36031e17060SPaolo Bonzini }; 36131e17060SPaolo Bonzini 36231e17060SPaolo Bonzini static Property xilinx_spi_properties[] = { 36331e17060SPaolo Bonzini DEFINE_PROP_UINT8("num-ss-bits", XilinxSPI, num_cs, 1), 36431e17060SPaolo Bonzini DEFINE_PROP_END_OF_LIST(), 36531e17060SPaolo Bonzini }; 36631e17060SPaolo Bonzini 36731e17060SPaolo Bonzini static void xilinx_spi_class_init(ObjectClass *klass, void *data) 36831e17060SPaolo Bonzini { 36931e17060SPaolo Bonzini DeviceClass *dc = DEVICE_CLASS(klass); 37031e17060SPaolo Bonzini SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); 37131e17060SPaolo Bonzini 37231e17060SPaolo Bonzini k->init = xilinx_spi_init; 37331e17060SPaolo Bonzini dc->reset = xlx_spi_reset; 37431e17060SPaolo Bonzini dc->props = xilinx_spi_properties; 37531e17060SPaolo Bonzini dc->vmsd = &vmstate_xilinx_spi; 37631e17060SPaolo Bonzini } 37731e17060SPaolo Bonzini 37831e17060SPaolo Bonzini static const TypeInfo xilinx_spi_info = { 3793efc10e1SAndreas Färber .name = TYPE_XILINX_SPI, 38031e17060SPaolo Bonzini .parent = TYPE_SYS_BUS_DEVICE, 38131e17060SPaolo Bonzini .instance_size = sizeof(XilinxSPI), 38231e17060SPaolo Bonzini .class_init = xilinx_spi_class_init, 38331e17060SPaolo Bonzini }; 38431e17060SPaolo Bonzini 38531e17060SPaolo Bonzini static void xilinx_spi_register_types(void) 38631e17060SPaolo Bonzini { 38731e17060SPaolo Bonzini type_register_static(&xilinx_spi_info); 38831e17060SPaolo Bonzini } 38931e17060SPaolo Bonzini 39031e17060SPaolo Bonzini type_init(xilinx_spi_register_types) 391