xref: /qemu/include/hw/i2c/i2c.h (revision 37fa5ca42623ef08ac99c8d927b6a3af0c76dc7b)
10ff596d0Spbrook #ifndef QEMU_I2C_H
20ff596d0Spbrook #define QEMU_I2C_H
30ff596d0Spbrook 
4a27bd6c7SMarkus Armbruster #include "hw/qdev-core.h"
5db1015e9SEduardo Habkost #include "qom/object.h"
6fe8de492SPaul Brook 
70ff596d0Spbrook /* The QEMU I2C implementation only supports simple transfers that complete
80ff596d0Spbrook    immediately.  It does not support slave devices that need to be able to
90ff596d0Spbrook    defer their response (eg. CPU slave interfaces where the data is supplied
100ff596d0Spbrook    by the device driver in response to an interrupt).  */
110ff596d0Spbrook 
120ff596d0Spbrook enum i2c_event {
130ff596d0Spbrook     I2C_START_RECV,
140ff596d0Spbrook     I2C_START_SEND,
150ff596d0Spbrook     I2C_FINISH,
16aa1f17c1Sths     I2C_NACK /* Masker NACKed a receive byte.  */
170ff596d0Spbrook };
180ff596d0Spbrook 
19513ca82dSPatrick Venture typedef struct I2CNodeList I2CNodeList;
200ff596d0Spbrook 
21b5ea9327SAnthony Liguori #define TYPE_I2C_SLAVE "i2c-slave"
22c821774aSEduardo Habkost OBJECT_DECLARE_TYPE(I2CSlave, I2CSlaveClass,
2330b5707cSEduardo Habkost                     I2C_SLAVE)
249e07bdf8SAnthony Liguori 
25db1015e9SEduardo Habkost struct I2CSlaveClass {
26b5ea9327SAnthony Liguori     DeviceClass parent_class;
2702e2da45SPaul Brook 
28d307c28cSCorey Minyard     /* Master to slave. Returns non-zero for a NAK, 0 for success. */
29b5ea9327SAnthony Liguori     int (*send)(I2CSlave *s, uint8_t data);
30b5ea9327SAnthony Liguori 
31d307c28cSCorey Minyard     /*
32d307c28cSCorey Minyard      * Slave to master.  This cannot fail, the device should always
332ac4c5f4SCorey Minyard      * return something here.
34d307c28cSCorey Minyard      */
352ac4c5f4SCorey Minyard     uint8_t (*recv)(I2CSlave *s);
36b5ea9327SAnthony Liguori 
37d307c28cSCorey Minyard     /*
38d307c28cSCorey Minyard      * Notify the slave of a bus state change.  For start event,
39d307c28cSCorey Minyard      * returns non-zero to NAK an operation.  For other events the
40d307c28cSCorey Minyard      * return code is not used and should be zero.
41d307c28cSCorey Minyard      */
42d307c28cSCorey Minyard     int (*event)(I2CSlave *s, enum i2c_event event);
43513ca82dSPatrick Venture 
44513ca82dSPatrick Venture     /*
45513ca82dSPatrick Venture      * Check if this device matches the address provided.  Returns bool of
46513ca82dSPatrick Venture      * true if it matches (or broadcast), and updates the device list, false
47513ca82dSPatrick Venture      * otherwise.
48513ca82dSPatrick Venture      *
49513ca82dSPatrick Venture      * If broadcast is true, match should add the device and return true.
50513ca82dSPatrick Venture      */
51513ca82dSPatrick Venture     bool (*match_and_add)(I2CSlave *candidate, uint8_t address, bool broadcast,
52513ca82dSPatrick Venture                           I2CNodeList *current_devs);
53db1015e9SEduardo Habkost };
54fe8de492SPaul Brook 
55373b8ac7SCorey Minyard struct I2CSlave {
56fe8de492SPaul Brook     DeviceState qdev;
570ff596d0Spbrook 
580ff596d0Spbrook     /* Remaining fields for internal use by the I2C code.  */
595b7f5327SJuan Quintela     uint8_t address;
600ff596d0Spbrook };
610ff596d0Spbrook 
62aa88d7adSCorey Minyard #define TYPE_I2C_BUS "i2c-bus"
638063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(I2CBus, I2C_BUS)
64aa88d7adSCorey Minyard 
65aa88d7adSCorey Minyard typedef struct I2CNode I2CNode;
66aa88d7adSCorey Minyard 
67aa88d7adSCorey Minyard struct I2CNode {
68aa88d7adSCorey Minyard     I2CSlave *elt;
69aa88d7adSCorey Minyard     QLIST_ENTRY(I2CNode) next;
70aa88d7adSCorey Minyard };
71aa88d7adSCorey Minyard 
72*37fa5ca4SKlaus Jensen typedef struct I2CPendingMaster I2CPendingMaster;
73*37fa5ca4SKlaus Jensen 
74*37fa5ca4SKlaus Jensen struct I2CPendingMaster {
75*37fa5ca4SKlaus Jensen     QEMUBH *bh;
76*37fa5ca4SKlaus Jensen     QSIMPLEQ_ENTRY(I2CPendingMaster) entry;
77*37fa5ca4SKlaus Jensen };
78*37fa5ca4SKlaus Jensen 
79b98ec689SPatrick Venture typedef QLIST_HEAD(I2CNodeList, I2CNode) I2CNodeList;
80*37fa5ca4SKlaus Jensen typedef QSIMPLEQ_HEAD(I2CPendingMasters, I2CPendingMaster) I2CPendingMasters;
81b98ec689SPatrick Venture 
82aa88d7adSCorey Minyard struct I2CBus {
83aa88d7adSCorey Minyard     BusState qbus;
84b98ec689SPatrick Venture     I2CNodeList current_devs;
85*37fa5ca4SKlaus Jensen     I2CPendingMasters pending_masters;
86aa88d7adSCorey Minyard     uint8_t saved_address;
87aa88d7adSCorey Minyard     bool broadcast;
88*37fa5ca4SKlaus Jensen 
89*37fa5ca4SKlaus Jensen     /* Set from slave currently mastering the bus. */
90*37fa5ca4SKlaus Jensen     QEMUBH *bh;
91aa88d7adSCorey Minyard };
92aa88d7adSCorey Minyard 
93a5c82852SAndreas Färber I2CBus *i2c_init_bus(DeviceState *parent, const char *name);
94a5c82852SAndreas Färber int i2c_bus_busy(I2CBus *bus);
95e656e387SBALATON Zoltan 
96e656e387SBALATON Zoltan /**
97e656e387SBALATON Zoltan  * i2c_start_transfer: start a transfer on an I2C bus.
98e656e387SBALATON Zoltan  *
99e656e387SBALATON Zoltan  * @bus: #I2CBus to be used
100e656e387SBALATON Zoltan  * @address: address of the slave
101e656e387SBALATON Zoltan  * @is_recv: indicates the transfer direction
102e656e387SBALATON Zoltan  *
10390603c5bSPhilippe Mathieu-Daudé  * When @is_recv is a known boolean constant, use the
10490603c5bSPhilippe Mathieu-Daudé  * i2c_start_recv() or i2c_start_send() helper instead.
10590603c5bSPhilippe Mathieu-Daudé  *
106e656e387SBALATON Zoltan  * Returns: 0 on success, -1 on error
107e656e387SBALATON Zoltan  */
108e656e387SBALATON Zoltan int i2c_start_transfer(I2CBus *bus, uint8_t address, bool is_recv);
10990603c5bSPhilippe Mathieu-Daudé 
11090603c5bSPhilippe Mathieu-Daudé /**
11190603c5bSPhilippe Mathieu-Daudé  * i2c_start_recv: start a 'receive' transfer on an I2C bus.
11290603c5bSPhilippe Mathieu-Daudé  *
11390603c5bSPhilippe Mathieu-Daudé  * @bus: #I2CBus to be used
11490603c5bSPhilippe Mathieu-Daudé  * @address: address of the slave
11590603c5bSPhilippe Mathieu-Daudé  *
11690603c5bSPhilippe Mathieu-Daudé  * Returns: 0 on success, -1 on error
11790603c5bSPhilippe Mathieu-Daudé  */
11890603c5bSPhilippe Mathieu-Daudé int i2c_start_recv(I2CBus *bus, uint8_t address);
11990603c5bSPhilippe Mathieu-Daudé 
12090603c5bSPhilippe Mathieu-Daudé /**
12190603c5bSPhilippe Mathieu-Daudé  * i2c_start_send: start a 'send' transfer on an I2C bus.
12290603c5bSPhilippe Mathieu-Daudé  *
12390603c5bSPhilippe Mathieu-Daudé  * @bus: #I2CBus to be used
12490603c5bSPhilippe Mathieu-Daudé  * @address: address of the slave
12590603c5bSPhilippe Mathieu-Daudé  *
12690603c5bSPhilippe Mathieu-Daudé  * Returns: 0 on success, -1 on error
12790603c5bSPhilippe Mathieu-Daudé  */
12890603c5bSPhilippe Mathieu-Daudé int i2c_start_send(I2CBus *bus, uint8_t address);
12990603c5bSPhilippe Mathieu-Daudé 
130a5c82852SAndreas Färber void i2c_end_transfer(I2CBus *bus);
131a5c82852SAndreas Färber void i2c_nack(I2CBus *bus);
132*37fa5ca4SKlaus Jensen void i2c_bus_master(I2CBus *bus, QEMUBH *bh);
133*37fa5ca4SKlaus Jensen void i2c_bus_release(I2CBus *bus);
134a5c82852SAndreas Färber int i2c_send(I2CBus *bus, uint8_t data);
1352ac4c5f4SCorey Minyard uint8_t i2c_recv(I2CBus *bus);
1363f9b3259SPatrick Venture bool i2c_scan_bus(I2CBus *bus, uint8_t address, bool broadcast,
1373f9b3259SPatrick Venture                   I2CNodeList *current_devs);
1380ff596d0Spbrook 
13973d5f22eSPhilippe Mathieu-Daudé /**
14073d5f22eSPhilippe Mathieu-Daudé  * Create an I2C slave device on the heap.
14173d5f22eSPhilippe Mathieu-Daudé  * @name: a device type name
14273d5f22eSPhilippe Mathieu-Daudé  * @addr: I2C address of the slave when put on a bus
14373d5f22eSPhilippe Mathieu-Daudé  *
14473d5f22eSPhilippe Mathieu-Daudé  * This only initializes the device state structure and allows
14573d5f22eSPhilippe Mathieu-Daudé  * properties to be set. Type @name must exist. The device still
14673d5f22eSPhilippe Mathieu-Daudé  * needs to be realized. See qdev-core.h.
14773d5f22eSPhilippe Mathieu-Daudé  */
148db437ca6SPhilippe Mathieu-Daudé I2CSlave *i2c_slave_new(const char *name, uint8_t addr);
14973d5f22eSPhilippe Mathieu-Daudé 
15073d5f22eSPhilippe Mathieu-Daudé /**
15173d5f22eSPhilippe Mathieu-Daudé  * Create and realize an I2C slave device on the heap.
15273d5f22eSPhilippe Mathieu-Daudé  * @bus: I2C bus to put it on
15373d5f22eSPhilippe Mathieu-Daudé  * @name: I2C slave device type name
15473d5f22eSPhilippe Mathieu-Daudé  * @addr: I2C address of the slave when put on a bus
15573d5f22eSPhilippe Mathieu-Daudé  *
15673d5f22eSPhilippe Mathieu-Daudé  * Create the device state structure, initialize it, put it on the
15773d5f22eSPhilippe Mathieu-Daudé  * specified @bus, and drop the reference to it (the device is realized).
15873d5f22eSPhilippe Mathieu-Daudé  */
1591373b15bSPhilippe Mathieu-Daudé I2CSlave *i2c_slave_create_simple(I2CBus *bus, const char *name, uint8_t addr);
16073d5f22eSPhilippe Mathieu-Daudé 
16173d5f22eSPhilippe Mathieu-Daudé /**
162d4b23573SPhilippe Mathieu-Daudé  * Realize and drop a reference an I2C slave device
16373d5f22eSPhilippe Mathieu-Daudé  * @dev: I2C slave device to realize
16473d5f22eSPhilippe Mathieu-Daudé  * @bus: I2C bus to put it on
16573d5f22eSPhilippe Mathieu-Daudé  * @addr: I2C address of the slave on the bus
16673d5f22eSPhilippe Mathieu-Daudé  * @errp: pointer to NULL initialized error object
16773d5f22eSPhilippe Mathieu-Daudé  *
16873d5f22eSPhilippe Mathieu-Daudé  * Returns: %true on success, %false on failure.
16973d5f22eSPhilippe Mathieu-Daudé  *
17073d5f22eSPhilippe Mathieu-Daudé  * Call 'realize' on @dev, put it on the specified @bus, and drop the
17173d5f22eSPhilippe Mathieu-Daudé  * reference to it.
17273d5f22eSPhilippe Mathieu-Daudé  *
17373d5f22eSPhilippe Mathieu-Daudé  * This function is useful if you have created @dev via qdev_new(),
17473d5f22eSPhilippe Mathieu-Daudé  * i2c_slave_new() or i2c_slave_try_new() (which take a reference to
17573d5f22eSPhilippe Mathieu-Daudé  * the device it returns to you), so that you can set properties on it
17673d5f22eSPhilippe Mathieu-Daudé  * before realizing it. If you don't need to set properties then
17773d5f22eSPhilippe Mathieu-Daudé  * i2c_slave_create_simple() is probably better (as it does the create,
17873d5f22eSPhilippe Mathieu-Daudé  * init and realize in one step).
17973d5f22eSPhilippe Mathieu-Daudé  *
18073d5f22eSPhilippe Mathieu-Daudé  * If you are embedding the I2C slave into another QOM device and
18173d5f22eSPhilippe Mathieu-Daudé  * initialized it via some variant on object_initialize_child() then
18273d5f22eSPhilippe Mathieu-Daudé  * do not use this function, because that family of functions arrange
18373d5f22eSPhilippe Mathieu-Daudé  * for the only reference to the child device to be held by the parent
18473d5f22eSPhilippe Mathieu-Daudé  * via the child<> property, and so the reference-count-drop done here
18573d5f22eSPhilippe Mathieu-Daudé  * would be incorrect.  (Instead you would want i2c_slave_realize(),
18673d5f22eSPhilippe Mathieu-Daudé  * which doesn't currently exist but would be trivial to create if we
18773d5f22eSPhilippe Mathieu-Daudé  * had any code that wanted it.)
18873d5f22eSPhilippe Mathieu-Daudé  */
1892616f572SPhilippe Mathieu-Daudé bool i2c_slave_realize_and_unref(I2CSlave *dev, I2CBus *bus, Error **errp);
190fe8de492SPaul Brook 
191c8665a59SPhilippe Mathieu-Daudé /**
192c8665a59SPhilippe Mathieu-Daudé  * Set the I2C bus address of a slave device
193c8665a59SPhilippe Mathieu-Daudé  * @dev: I2C slave device
194c8665a59SPhilippe Mathieu-Daudé  * @address: I2C address of the slave when put on a bus
195c8665a59SPhilippe Mathieu-Daudé  */
196c8665a59SPhilippe Mathieu-Daudé void i2c_slave_set_address(I2CSlave *dev, uint8_t address);
197c8665a59SPhilippe Mathieu-Daudé 
198701a8f76SPaolo Bonzini extern const VMStateDescription vmstate_i2c_slave;
199701a8f76SPaolo Bonzini 
200701a8f76SPaolo Bonzini #define VMSTATE_I2C_SLAVE(_field, _state) {                          \
201701a8f76SPaolo Bonzini     .name       = (stringify(_field)),                               \
2029e07bdf8SAnthony Liguori     .size       = sizeof(I2CSlave),                                  \
203701a8f76SPaolo Bonzini     .vmsd       = &vmstate_i2c_slave,                                \
204701a8f76SPaolo Bonzini     .flags      = VMS_STRUCT,                                        \
2059e07bdf8SAnthony Liguori     .offset     = vmstate_offset_value(_state, _field, I2CSlave),    \
206701a8f76SPaolo Bonzini }
207701a8f76SPaolo Bonzini 
2080ff596d0Spbrook #endif
209