xref: /qemu/include/hw/ssi/ssi.h (revision db1015e92e04835c9eb50c29625fe566d1202dbd)
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 
14a27bd6c7SMarkus Armbruster #include "hw/qdev-core.h"
15*db1015e9SEduardo Habkost #include "qom/object.h"
1690d37239SPaul Brook 
1790d37239SPaul Brook typedef struct SSISlave SSISlave;
188fd06719SAlistair Francis typedef struct SSISlaveClass SSISlaveClass;
198fd06719SAlistair Francis typedef enum SSICSMode SSICSMode;
2090d37239SPaul Brook 
21cd6c4cf2SAnthony Liguori #define TYPE_SSI_SLAVE "ssi-slave"
22cd6c4cf2SAnthony Liguori #define SSI_SLAVE(obj) \
23cd6c4cf2SAnthony Liguori      OBJECT_CHECK(SSISlave, (obj), TYPE_SSI_SLAVE)
24cd6c4cf2SAnthony Liguori #define SSI_SLAVE_CLASS(klass) \
25cd6c4cf2SAnthony Liguori      OBJECT_CLASS_CHECK(SSISlaveClass, (klass), TYPE_SSI_SLAVE)
26cd6c4cf2SAnthony Liguori #define SSI_SLAVE_GET_CLASS(obj) \
27cd6c4cf2SAnthony Liguori      OBJECT_GET_CLASS(SSISlaveClass, (obj), TYPE_SSI_SLAVE)
28cd6c4cf2SAnthony Liguori 
29de77914eSPeter Crosthwaite #define SSI_GPIO_CS "ssi-gpio-cs"
30de77914eSPeter Crosthwaite 
318fd06719SAlistair Francis enum SSICSMode {
3266530953SPeter A. G. Crosthwaite     SSI_CS_NONE = 0,
3366530953SPeter A. G. Crosthwaite     SSI_CS_LOW,
3466530953SPeter A. G. Crosthwaite     SSI_CS_HIGH,
358fd06719SAlistair Francis };
3666530953SPeter A. G. Crosthwaite 
3790d37239SPaul Brook /* Slave devices.  */
388fd06719SAlistair Francis struct SSISlaveClass {
39cd6c4cf2SAnthony Liguori     DeviceClass parent_class;
40cd6c4cf2SAnthony Liguori 
417673bb4cSCédric Le Goater     void (*realize)(SSISlave *dev, Error **errp);
4266530953SPeter A. G. Crosthwaite 
4366530953SPeter A. G. Crosthwaite     /* if you have standard or no CS behaviour, just override transfer.
4466530953SPeter A. G. Crosthwaite      * This is called when the device cs is active (true by default).
4566530953SPeter A. G. Crosthwaite      */
4690d37239SPaul Brook     uint32_t (*transfer)(SSISlave *dev, uint32_t val);
4766530953SPeter A. G. Crosthwaite     /* called when the CS line changes. Optional, devices only need to implement
4866530953SPeter A. G. Crosthwaite      * this if they have side effects associated with the cs line (beyond
4966530953SPeter A. G. Crosthwaite      * tristating the txrx lines).
5066530953SPeter A. G. Crosthwaite      */
5166530953SPeter A. G. Crosthwaite     int (*set_cs)(SSISlave *dev, bool select);
5266530953SPeter A. G. Crosthwaite     /* define whether or not CS exists and is active low/high */
5366530953SPeter A. G. Crosthwaite     SSICSMode cs_polarity;
5466530953SPeter A. G. Crosthwaite 
5566530953SPeter A. G. Crosthwaite     /* if you have non-standard CS behaviour override this to take control
5666530953SPeter A. G. Crosthwaite      * of the CS behaviour at the device level. transfer, set_cs, and
5766530953SPeter A. G. Crosthwaite      * cs_polarity are unused if this is overwritten. Transfer_raw will
5866530953SPeter A. G. Crosthwaite      * always be called for the device for every txrx access to the parent bus
5966530953SPeter A. G. Crosthwaite      */
6066530953SPeter A. G. Crosthwaite     uint32_t (*transfer_raw)(SSISlave *dev, uint32_t val);
618fd06719SAlistair Francis };
6290d37239SPaul Brook 
6390d37239SPaul Brook struct SSISlave {
641f760d5fSPeter Crosthwaite     DeviceState parent_obj;
6566530953SPeter A. G. Crosthwaite 
6666530953SPeter A. G. Crosthwaite     /* Chip select state */
6766530953SPeter A. G. Crosthwaite     bool cs;
6890d37239SPaul Brook };
6990d37239SPaul Brook 
7066530953SPeter A. G. Crosthwaite extern const VMStateDescription vmstate_ssi_slave;
7166530953SPeter A. G. Crosthwaite 
7266530953SPeter A. G. Crosthwaite #define VMSTATE_SSI_SLAVE(_field, _state) {                          \
7366530953SPeter A. G. Crosthwaite     .name       = (stringify(_field)),                               \
7466530953SPeter A. G. Crosthwaite     .size       = sizeof(SSISlave),                                  \
7566530953SPeter A. G. Crosthwaite     .vmsd       = &vmstate_ssi_slave,                                \
7666530953SPeter A. G. Crosthwaite     .flags      = VMS_STRUCT,                                        \
7766530953SPeter A. G. Crosthwaite     .offset     = vmstate_offset_value(_state, _field, SSISlave),    \
7866530953SPeter A. G. Crosthwaite }
7966530953SPeter A. G. Crosthwaite 
8090d37239SPaul Brook DeviceState *ssi_create_slave(SSIBus *bus, const char *name);
81581e109dSPeter Maydell /**
82581e109dSPeter Maydell  * ssi_realize_and_unref: realize and unref an SSI slave device
83581e109dSPeter Maydell  * @dev: SSI slave device to realize
84581e109dSPeter Maydell  * @bus: SSI bus to put it on
85581e109dSPeter Maydell  * @errp: error pointer
86581e109dSPeter Maydell  *
87581e109dSPeter Maydell  * Call 'realize' on @dev, put it on the specified @bus, and drop the
88581e109dSPeter Maydell  * reference to it. Errors are reported via @errp and by returning
89581e109dSPeter Maydell  * false.
90581e109dSPeter Maydell  *
91581e109dSPeter Maydell  * This function is useful if you have created @dev via qdev_new()
92581e109dSPeter Maydell  * (which takes a reference to the device it returns to you), so that
93581e109dSPeter Maydell  * you can set properties on it before realizing it. If you don't need
94581e109dSPeter Maydell  * to set properties then ssi_create_slave() is probably better (as it
95581e109dSPeter Maydell  * does the create, init and realize in one step).
96581e109dSPeter Maydell  *
97581e109dSPeter Maydell  * If you are embedding the SSI slave into another QOM device and
98581e109dSPeter Maydell  * initialized it via some variant on object_initialize_child() then
99581e109dSPeter Maydell  * do not use this function, because that family of functions arrange
100581e109dSPeter Maydell  * for the only reference to the child device to be held by the parent
101581e109dSPeter Maydell  * via the child<> property, and so the reference-count-drop done here
102581e109dSPeter Maydell  * would be incorrect.  (Instead you would want ssi_realize(), which
103581e109dSPeter Maydell  * doesn't currently exist but would be trivial to create if we had
104581e109dSPeter Maydell  * any code that wanted it.)
105581e109dSPeter Maydell  */
106581e109dSPeter Maydell bool ssi_realize_and_unref(DeviceState *dev, SSIBus *bus, Error **errp);
10790d37239SPaul Brook 
10890d37239SPaul Brook /* Master interface.  */
10902e2da45SPaul Brook SSIBus *ssi_create_bus(DeviceState *parent, const char *name);
11090d37239SPaul Brook 
11190d37239SPaul Brook uint32_t ssi_transfer(SSIBus *bus, uint32_t val);
11290d37239SPaul Brook 
11390d37239SPaul Brook #endif
114