]>
Commit | Line | Data |
---|---|---|
0ff596d0 PB |
1 | #ifndef QEMU_I2C_H |
2 | #define QEMU_I2C_H | |
3 | ||
a27bd6c7 | 4 | #include "hw/qdev-core.h" |
db1015e9 | 5 | #include "qom/object.h" |
fe8de492 | 6 | |
0ff596d0 PB |
7 | /* The QEMU I2C implementation only supports simple transfers that complete |
8 | immediately. It does not support slave devices that need to be able to | |
9 | defer their response (eg. CPU slave interfaces where the data is supplied | |
10 | by the device driver in response to an interrupt). */ | |
11 | ||
12 | enum i2c_event { | |
13 | I2C_START_RECV, | |
14 | I2C_START_SEND, | |
a78e9839 | 15 | I2C_START_SEND_ASYNC, |
0ff596d0 | 16 | I2C_FINISH, |
aa1f17c1 | 17 | I2C_NACK /* Masker NACKed a receive byte. */ |
0ff596d0 PB |
18 | }; |
19 | ||
513ca82d | 20 | typedef struct I2CNodeList I2CNodeList; |
9e07bdf8 | 21 | |
b5ea9327 | 22 | #define TYPE_I2C_SLAVE "i2c-slave" |
c821774a | 23 | OBJECT_DECLARE_TYPE(I2CSlave, I2CSlaveClass, |
30b5707c | 24 | I2C_SLAVE) |
0ff596d0 | 25 | |
db1015e9 | 26 | struct I2CSlaveClass { |
b5ea9327 | 27 | DeviceClass parent_class; |
02e2da45 | 28 | |
d307c28c | 29 | /* Master to slave. Returns non-zero for a NAK, 0 for success. */ |
b5ea9327 AL |
30 | int (*send)(I2CSlave *s, uint8_t data); |
31 | ||
a78e9839 KJ |
32 | /* Master to slave (asynchronous). Receiving slave must call i2c_ack(). */ |
33 | void (*send_async)(I2CSlave *s, uint8_t data); | |
34 | ||
d307c28c CM |
35 | /* |
36 | * Slave to master. This cannot fail, the device should always | |
2ac4c5f4 | 37 | * return something here. |
d307c28c | 38 | */ |
2ac4c5f4 | 39 | uint8_t (*recv)(I2CSlave *s); |
b5ea9327 | 40 | |
d307c28c CM |
41 | /* |
42 | * Notify the slave of a bus state change. For start event, | |
43 | * returns non-zero to NAK an operation. For other events the | |
44 | * return code is not used and should be zero. | |
45 | */ | |
46 | int (*event)(I2CSlave *s, enum i2c_event event); | |
513ca82d PV |
47 | |
48 | /* | |
49 | * Check if this device matches the address provided. Returns bool of | |
50 | * true if it matches (or broadcast), and updates the device list, false | |
51 | * otherwise. | |
52 | * | |
53 | * If broadcast is true, match should add the device and return true. | |
54 | */ | |
55 | bool (*match_and_add)(I2CSlave *candidate, uint8_t address, bool broadcast, | |
56 | I2CNodeList *current_devs); | |
db1015e9 | 57 | }; |
fe8de492 | 58 | |
373b8ac7 | 59 | struct I2CSlave { |
fe8de492 | 60 | DeviceState qdev; |
0ff596d0 PB |
61 | |
62 | /* Remaining fields for internal use by the I2C code. */ | |
5b7f5327 | 63 | uint8_t address; |
0ff596d0 PB |
64 | }; |
65 | ||
aa88d7ad | 66 | #define TYPE_I2C_BUS "i2c-bus" |
8063396b | 67 | OBJECT_DECLARE_SIMPLE_TYPE(I2CBus, I2C_BUS) |
aa88d7ad CM |
68 | |
69 | typedef struct I2CNode I2CNode; | |
70 | ||
71 | struct I2CNode { | |
72 | I2CSlave *elt; | |
73 | QLIST_ENTRY(I2CNode) next; | |
74 | }; | |
75 | ||
37fa5ca4 KJ |
76 | typedef struct I2CPendingMaster I2CPendingMaster; |
77 | ||
78 | struct I2CPendingMaster { | |
79 | QEMUBH *bh; | |
80 | QSIMPLEQ_ENTRY(I2CPendingMaster) entry; | |
81 | }; | |
82 | ||
b98ec689 | 83 | typedef QLIST_HEAD(I2CNodeList, I2CNode) I2CNodeList; |
37fa5ca4 | 84 | typedef QSIMPLEQ_HEAD(I2CPendingMasters, I2CPendingMaster) I2CPendingMasters; |
b98ec689 | 85 | |
aa88d7ad CM |
86 | struct I2CBus { |
87 | BusState qbus; | |
b98ec689 | 88 | I2CNodeList current_devs; |
37fa5ca4 | 89 | I2CPendingMasters pending_masters; |
aa88d7ad CM |
90 | uint8_t saved_address; |
91 | bool broadcast; | |
37fa5ca4 KJ |
92 | |
93 | /* Set from slave currently mastering the bus. */ | |
94 | QEMUBH *bh; | |
aa88d7ad CM |
95 | }; |
96 | ||
a5c82852 | 97 | I2CBus *i2c_init_bus(DeviceState *parent, const char *name); |
a5c82852 | 98 | int i2c_bus_busy(I2CBus *bus); |
e656e387 BZ |
99 | |
100 | /** | |
101 | * i2c_start_transfer: start a transfer on an I2C bus. | |
102 | * | |
103 | * @bus: #I2CBus to be used | |
104 | * @address: address of the slave | |
105 | * @is_recv: indicates the transfer direction | |
106 | * | |
90603c5b PMD |
107 | * When @is_recv is a known boolean constant, use the |
108 | * i2c_start_recv() or i2c_start_send() helper instead. | |
109 | * | |
e656e387 BZ |
110 | * Returns: 0 on success, -1 on error |
111 | */ | |
112 | int i2c_start_transfer(I2CBus *bus, uint8_t address, bool is_recv); | |
90603c5b PMD |
113 | |
114 | /** | |
115 | * i2c_start_recv: start a 'receive' transfer on an I2C bus. | |
116 | * | |
117 | * @bus: #I2CBus to be used | |
118 | * @address: address of the slave | |
119 | * | |
120 | * Returns: 0 on success, -1 on error | |
121 | */ | |
122 | int i2c_start_recv(I2CBus *bus, uint8_t address); | |
123 | ||
124 | /** | |
125 | * i2c_start_send: start a 'send' transfer on an I2C bus. | |
126 | * | |
127 | * @bus: #I2CBus to be used | |
128 | * @address: address of the slave | |
129 | * | |
130 | * Returns: 0 on success, -1 on error | |
131 | */ | |
132 | int i2c_start_send(I2CBus *bus, uint8_t address); | |
133 | ||
a78e9839 KJ |
134 | /** |
135 | * i2c_start_send_async: start an asynchronous 'send' transfer on an I2C bus. | |
136 | * | |
137 | * @bus: #I2CBus to be used | |
138 | * @address: address of the slave | |
139 | * | |
140 | * Return: 0 on success, -1 on error | |
141 | */ | |
142 | int i2c_start_send_async(I2CBus *bus, uint8_t address); | |
143 | ||
791cb95f KJ |
144 | void i2c_schedule_pending_master(I2CBus *bus); |
145 | ||
a5c82852 AF |
146 | void i2c_end_transfer(I2CBus *bus); |
147 | void i2c_nack(I2CBus *bus); | |
a78e9839 | 148 | void i2c_ack(I2CBus *bus); |
37fa5ca4 KJ |
149 | void i2c_bus_master(I2CBus *bus, QEMUBH *bh); |
150 | void i2c_bus_release(I2CBus *bus); | |
a5c82852 | 151 | int i2c_send(I2CBus *bus, uint8_t data); |
a78e9839 | 152 | int i2c_send_async(I2CBus *bus, uint8_t data); |
2ac4c5f4 | 153 | uint8_t i2c_recv(I2CBus *bus); |
3f9b3259 PV |
154 | bool i2c_scan_bus(I2CBus *bus, uint8_t address, bool broadcast, |
155 | I2CNodeList *current_devs); | |
0ff596d0 | 156 | |
73d5f22e PMD |
157 | /** |
158 | * Create an I2C slave device on the heap. | |
159 | * @name: a device type name | |
160 | * @addr: I2C address of the slave when put on a bus | |
161 | * | |
162 | * This only initializes the device state structure and allows | |
163 | * properties to be set. Type @name must exist. The device still | |
164 | * needs to be realized. See qdev-core.h. | |
165 | */ | |
db437ca6 | 166 | I2CSlave *i2c_slave_new(const char *name, uint8_t addr); |
73d5f22e PMD |
167 | |
168 | /** | |
169 | * Create and realize an I2C slave device on the heap. | |
170 | * @bus: I2C bus to put it on | |
171 | * @name: I2C slave device type name | |
172 | * @addr: I2C address of the slave when put on a bus | |
173 | * | |
174 | * Create the device state structure, initialize it, put it on the | |
175 | * specified @bus, and drop the reference to it (the device is realized). | |
176 | */ | |
1373b15b | 177 | I2CSlave *i2c_slave_create_simple(I2CBus *bus, const char *name, uint8_t addr); |
73d5f22e PMD |
178 | |
179 | /** | |
d4b23573 | 180 | * Realize and drop a reference an I2C slave device |
73d5f22e PMD |
181 | * @dev: I2C slave device to realize |
182 | * @bus: I2C bus to put it on | |
183 | * @addr: I2C address of the slave on the bus | |
184 | * @errp: pointer to NULL initialized error object | |
185 | * | |
186 | * Returns: %true on success, %false on failure. | |
187 | * | |
188 | * Call 'realize' on @dev, put it on the specified @bus, and drop the | |
189 | * reference to it. | |
190 | * | |
191 | * This function is useful if you have created @dev via qdev_new(), | |
192 | * i2c_slave_new() or i2c_slave_try_new() (which take a reference to | |
193 | * the device it returns to you), so that you can set properties on it | |
194 | * before realizing it. If you don't need to set properties then | |
195 | * i2c_slave_create_simple() is probably better (as it does the create, | |
196 | * init and realize in one step). | |
197 | * | |
198 | * If you are embedding the I2C slave into another QOM device and | |
199 | * initialized it via some variant on object_initialize_child() then | |
200 | * do not use this function, because that family of functions arrange | |
201 | * for the only reference to the child device to be held by the parent | |
202 | * via the child<> property, and so the reference-count-drop done here | |
203 | * would be incorrect. (Instead you would want i2c_slave_realize(), | |
204 | * which doesn't currently exist but would be trivial to create if we | |
205 | * had any code that wanted it.) | |
206 | */ | |
2616f572 | 207 | bool i2c_slave_realize_and_unref(I2CSlave *dev, I2CBus *bus, Error **errp); |
fe8de492 | 208 | |
c8665a59 PMD |
209 | /** |
210 | * Set the I2C bus address of a slave device | |
211 | * @dev: I2C slave device | |
212 | * @address: I2C address of the slave when put on a bus | |
213 | */ | |
214 | void i2c_slave_set_address(I2CSlave *dev, uint8_t address); | |
215 | ||
701a8f76 PB |
216 | extern const VMStateDescription vmstate_i2c_slave; |
217 | ||
218 | #define VMSTATE_I2C_SLAVE(_field, _state) { \ | |
219 | .name = (stringify(_field)), \ | |
9e07bdf8 | 220 | .size = sizeof(I2CSlave), \ |
701a8f76 PB |
221 | .vmsd = &vmstate_i2c_slave, \ |
222 | .flags = VMS_STRUCT, \ | |
9e07bdf8 | 223 | .offset = vmstate_offset_value(_state, _field, I2CSlave), \ |
701a8f76 PB |
224 | } |
225 | ||
0ff596d0 | 226 | #endif |