190d37239SPaul Brook /* QEMU Synchronous Serial Interface support. */ 290d37239SPaul Brook 390d37239SPaul Brook /* In principle SSI is a point-point interface. As such the qemu 490d37239SPaul Brook implementation has a single slave device on a "bus". 590d37239SPaul Brook However it is fairly common for boards to have multiple slaves 690d37239SPaul Brook connected to a single master, and select devices with an external 790d37239SPaul Brook chip select. This is implemented in qemu by having an explicit mux device. 890d37239SPaul Brook It is assumed that master and slave are both using the same transfer width. 990d37239SPaul Brook */ 1090d37239SPaul Brook 1190d37239SPaul Brook #ifndef QEMU_SSI_H 1290d37239SPaul Brook #define QEMU_SSI_H 1390d37239SPaul Brook 14*a27bd6c7SMarkus Armbruster #include "hw/qdev-core.h" 1590d37239SPaul Brook 1690d37239SPaul Brook typedef struct SSISlave SSISlave; 178fd06719SAlistair Francis typedef struct SSISlaveClass SSISlaveClass; 188fd06719SAlistair Francis typedef enum SSICSMode SSICSMode; 1990d37239SPaul Brook 20cd6c4cf2SAnthony Liguori #define TYPE_SSI_SLAVE "ssi-slave" 21cd6c4cf2SAnthony Liguori #define SSI_SLAVE(obj) \ 22cd6c4cf2SAnthony Liguori OBJECT_CHECK(SSISlave, (obj), TYPE_SSI_SLAVE) 23cd6c4cf2SAnthony Liguori #define SSI_SLAVE_CLASS(klass) \ 24cd6c4cf2SAnthony Liguori OBJECT_CLASS_CHECK(SSISlaveClass, (klass), TYPE_SSI_SLAVE) 25cd6c4cf2SAnthony Liguori #define SSI_SLAVE_GET_CLASS(obj) \ 26cd6c4cf2SAnthony Liguori OBJECT_GET_CLASS(SSISlaveClass, (obj), TYPE_SSI_SLAVE) 27cd6c4cf2SAnthony Liguori 28de77914eSPeter Crosthwaite #define SSI_GPIO_CS "ssi-gpio-cs" 29de77914eSPeter Crosthwaite 308fd06719SAlistair Francis enum SSICSMode { 3166530953SPeter A. G. Crosthwaite SSI_CS_NONE = 0, 3266530953SPeter A. G. Crosthwaite SSI_CS_LOW, 3366530953SPeter A. G. Crosthwaite SSI_CS_HIGH, 348fd06719SAlistair Francis }; 3566530953SPeter A. G. Crosthwaite 3690d37239SPaul Brook /* Slave devices. */ 378fd06719SAlistair Francis struct SSISlaveClass { 38cd6c4cf2SAnthony Liguori DeviceClass parent_class; 39cd6c4cf2SAnthony Liguori 407673bb4cSCédric Le Goater void (*realize)(SSISlave *dev, Error **errp); 4166530953SPeter A. G. Crosthwaite 4266530953SPeter A. G. Crosthwaite /* if you have standard or no CS behaviour, just override transfer. 4366530953SPeter A. G. Crosthwaite * This is called when the device cs is active (true by default). 4466530953SPeter A. G. Crosthwaite */ 4590d37239SPaul Brook uint32_t (*transfer)(SSISlave *dev, uint32_t val); 4666530953SPeter A. G. Crosthwaite /* called when the CS line changes. Optional, devices only need to implement 4766530953SPeter A. G. Crosthwaite * this if they have side effects associated with the cs line (beyond 4866530953SPeter A. G. Crosthwaite * tristating the txrx lines). 4966530953SPeter A. G. Crosthwaite */ 5066530953SPeter A. G. Crosthwaite int (*set_cs)(SSISlave *dev, bool select); 5166530953SPeter A. G. Crosthwaite /* define whether or not CS exists and is active low/high */ 5266530953SPeter A. G. Crosthwaite SSICSMode cs_polarity; 5366530953SPeter A. G. Crosthwaite 5466530953SPeter A. G. Crosthwaite /* if you have non-standard CS behaviour override this to take control 5566530953SPeter A. G. Crosthwaite * of the CS behaviour at the device level. transfer, set_cs, and 5666530953SPeter A. G. Crosthwaite * cs_polarity are unused if this is overwritten. Transfer_raw will 5766530953SPeter A. G. Crosthwaite * always be called for the device for every txrx access to the parent bus 5866530953SPeter A. G. Crosthwaite */ 5966530953SPeter A. G. Crosthwaite uint32_t (*transfer_raw)(SSISlave *dev, uint32_t val); 608fd06719SAlistair Francis }; 6190d37239SPaul Brook 6290d37239SPaul Brook struct SSISlave { 631f760d5fSPeter Crosthwaite DeviceState parent_obj; 6466530953SPeter A. G. Crosthwaite 6566530953SPeter A. G. Crosthwaite /* Chip select state */ 6666530953SPeter A. G. Crosthwaite bool cs; 6790d37239SPaul Brook }; 6890d37239SPaul Brook 6990d37239SPaul Brook #define FROM_SSI_SLAVE(type, dev) DO_UPCAST(type, ssidev, dev) 7090d37239SPaul Brook 7166530953SPeter A. G. Crosthwaite extern const VMStateDescription vmstate_ssi_slave; 7266530953SPeter A. G. Crosthwaite 7366530953SPeter A. G. Crosthwaite #define VMSTATE_SSI_SLAVE(_field, _state) { \ 7466530953SPeter A. G. Crosthwaite .name = (stringify(_field)), \ 7566530953SPeter A. G. Crosthwaite .size = sizeof(SSISlave), \ 7666530953SPeter A. G. Crosthwaite .vmsd = &vmstate_ssi_slave, \ 7766530953SPeter A. G. Crosthwaite .flags = VMS_STRUCT, \ 7866530953SPeter A. G. Crosthwaite .offset = vmstate_offset_value(_state, _field, SSISlave), \ 7966530953SPeter A. G. Crosthwaite } 8066530953SPeter A. G. Crosthwaite 8190d37239SPaul Brook DeviceState *ssi_create_slave(SSIBus *bus, const char *name); 8274687e40SPeter A. G. Crosthwaite DeviceState *ssi_create_slave_no_init(SSIBus *bus, const char *name); 8390d37239SPaul Brook 8490d37239SPaul Brook /* Master interface. */ 8502e2da45SPaul Brook SSIBus *ssi_create_bus(DeviceState *parent, const char *name); 8690d37239SPaul Brook 8790d37239SPaul Brook uint32_t ssi_transfer(SSIBus *bus, uint32_t val); 8890d37239SPaul Brook 89b4ae3cfaSPeter Crosthwaite /* Automatically connect all children nodes a spi controller as slaves */ 90b4ae3cfaSPeter Crosthwaite void ssi_auto_connect_slaves(DeviceState *parent, qemu_irq *cs_lines, 91b4ae3cfaSPeter Crosthwaite SSIBus *bus); 92b4ae3cfaSPeter Crosthwaite 93a984a69eSPaul Brook /* max111x.c */ 94a984a69eSPaul Brook void max111x_set_input(DeviceState *dev, int line, uint8_t value); 95a984a69eSPaul Brook 9690d37239SPaul Brook #endif 97