1
2
3
4
5
6
7
8
9
10#include "qemu/osdep.h"
11#include "hw/i2c/i2c.h"
12#include "hw/fdt_generic_util.h"
13
14typedef struct I2CNode I2CNode;
15
16struct I2CNode {
17 I2CSlave *elt;
18 QLIST_ENTRY(I2CNode) next;
19};
20
21#define I2C_BROADCAST 0x00
22
23static Property i2c_props[] = {
24 DEFINE_PROP_UINT8("address", struct I2CSlave, address, 0),
25 DEFINE_PROP_UINT8("address-range", struct I2CSlave, address_range, 1),
26 DEFINE_PROP_END_OF_LIST(),
27};
28
29#define TYPE_I2C_BUS "i2c-bus"
30#define I2C_BUS(obj) OBJECT_CHECK(I2CBus, (obj), TYPE_I2C_BUS)
31
32static const TypeInfo i2c_bus_info = {
33 .name = TYPE_I2C_BUS,
34 .parent = TYPE_BUS,
35 .instance_size = sizeof(I2CBus),
36};
37
38static void i2c_bus_pre_save(void *opaque)
39{
40 I2CBus *bus = opaque;
41
42 bus->saved_address = -1;
43 if (!QLIST_EMPTY(&bus->current_devs)) {
44 if (!bus->broadcast) {
45 bus->saved_address = QLIST_FIRST(&bus->current_devs)->elt->address;
46 } else {
47 bus->saved_address = I2C_BROADCAST;
48 }
49 }
50}
51
52static const VMStateDescription vmstate_i2c_bus = {
53 .name = "i2c_bus",
54 .version_id = 1,
55 .minimum_version_id = 1,
56 .pre_save = i2c_bus_pre_save,
57 .fields = (VMStateField[]) {
58 VMSTATE_UINT8(saved_address, I2CBus),
59 VMSTATE_END_OF_LIST()
60 }
61};
62
63
64I2CBus *i2c_init_bus(DeviceState *parent, const char *name)
65{
66 I2CBus *bus;
67
68 bus = I2C_BUS(qbus_create(TYPE_I2C_BUS, parent, name));
69 QLIST_INIT(&bus->current_devs);
70 vmstate_register(NULL, -1, &vmstate_i2c_bus, bus);
71 return bus;
72}
73
74void i2c_set_slave_address(I2CSlave *dev, uint8_t address)
75{
76 dev->address = address;
77}
78
79
80int i2c_bus_busy(I2CBus *bus)
81{
82 return !QLIST_EMPTY(&bus->current_devs);
83}
84
85
86
87int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv)
88{
89 BusChild *kid;
90 I2CSlaveClass *sc;
91 I2CNode *node;
92
93 if (address == I2C_BROADCAST) {
94
95
96
97
98 bus->broadcast = true;
99 }
100
101 QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) {
102 DeviceState *qdev = kid->child;
103 I2CSlave *candidate = I2C_SLAVE(qdev);
104 if ((candidate->address <= address &&
105 address < candidate->address + candidate->address_range) ||
106 (bus->broadcast)) {
107 node = g_malloc(sizeof(struct I2CNode));
108 node->elt = candidate;
109 QLIST_INSERT_HEAD(&bus->current_devs, node, next);
110 if (!bus->broadcast) {
111 break;
112 }
113 }
114 }
115
116 if (QLIST_EMPTY(&bus->current_devs)) {
117 return 1;
118 }
119
120 QLIST_FOREACH(node, &bus->current_devs, next) {
121 sc = I2C_SLAVE_GET_CLASS(node->elt);
122
123
124 if (sc->event) {
125 sc->event(node->elt, recv ? I2C_START_RECV : I2C_START_SEND);
126 }
127 if (sc->decode_address) {
128 if (sc->decode_address(node->elt, address)) {
129 return 1;
130 }
131 }
132 }
133 return 0;
134}
135
136void i2c_end_transfer(I2CBus *bus)
137{
138 I2CSlaveClass *sc;
139 I2CNode *node, *next;
140
141 if (QLIST_EMPTY(&bus->current_devs)) {
142 return;
143 }
144
145 QLIST_FOREACH_SAFE(node, &bus->current_devs, next, next) {
146 sc = I2C_SLAVE_GET_CLASS(node->elt);
147 if (sc->event) {
148 sc->event(node->elt, I2C_FINISH);
149 }
150 QLIST_REMOVE(node, next);
151 g_free(node);
152 }
153 bus->broadcast = false;
154}
155
156int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send)
157{
158 I2CSlaveClass *sc;
159 I2CNode *node;
160 int ret = 0;
161
162 if (send) {
163 QLIST_FOREACH(node, &bus->current_devs, next) {
164 sc = I2C_SLAVE_GET_CLASS(node->elt);
165 if (sc->send) {
166 ret = ret || sc->send(node->elt, *data);
167 } else {
168 ret = -1;
169 }
170 }
171 return ret ? -1 : 0;
172 } else {
173 if ((QLIST_EMPTY(&bus->current_devs)) || (bus->broadcast)) {
174 return -1;
175 }
176
177 sc = I2C_SLAVE_GET_CLASS(QLIST_FIRST(&bus->current_devs)->elt);
178 if (sc->recv) {
179 ret = sc->recv(QLIST_FIRST(&bus->current_devs)->elt);
180 if (ret < 0) {
181 return ret;
182 } else {
183 *data = ret;
184 return 0;
185 }
186 }
187 return -1;
188 }
189}
190
191int i2c_send(I2CBus *bus, uint8_t data)
192{
193 return i2c_send_recv(bus, &data, true);
194}
195
196int i2c_recv(I2CBus *bus)
197{
198 uint8_t data;
199 int ret = i2c_send_recv(bus, &data, false);
200
201 return ret < 0 ? ret : data;
202}
203
204void i2c_nack(I2CBus *bus)
205{
206 I2CSlaveClass *sc;
207 I2CNode *node;
208
209 if (QLIST_EMPTY(&bus->current_devs)) {
210 return;
211 }
212
213 QLIST_FOREACH(node, &bus->current_devs, next) {
214 sc = I2C_SLAVE_GET_CLASS(node->elt);
215 if (sc->event) {
216 sc->event(node->elt, I2C_NACK);
217 }
218 }
219}
220
221static int i2c_slave_post_load(void *opaque, int version_id)
222{
223 I2CSlave *dev = opaque;
224 I2CBus *bus;
225 I2CNode *node;
226
227 bus = I2C_BUS(qdev_get_parent_bus(DEVICE(dev)));
228 if ((bus->saved_address == dev->address) ||
229 (bus->saved_address == I2C_BROADCAST)) {
230 node = g_malloc(sizeof(struct I2CNode));
231 node->elt = dev;
232 QLIST_INSERT_HEAD(&bus->current_devs, node, next);
233 }
234 return 0;
235}
236
237const VMStateDescription vmstate_i2c_slave = {
238 .name = "I2CSlave",
239 .version_id = 1,
240 .minimum_version_id = 1,
241 .post_load = i2c_slave_post_load,
242 .fields = (VMStateField[]) {
243 VMSTATE_UINT8(address, I2CSlave),
244 VMSTATE_UINT8(address_range, I2CSlave),
245 VMSTATE_BOOL(broadcast, I2CBus),
246 VMSTATE_END_OF_LIST()
247 }
248};
249
250static int i2c_slave_qdev_init(DeviceState *dev)
251{
252 I2CSlave *s = I2C_SLAVE(dev);
253 I2CSlaveClass *sc = I2C_SLAVE_GET_CLASS(s);
254
255 return sc->init(s);
256}
257
258DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr)
259{
260 DeviceState *dev;
261
262 dev = qdev_create(&bus->qbus, name);
263 qdev_prop_set_uint8(dev, "address", addr);
264 qdev_init_nofail(dev);
265 return dev;
266}
267
268static bool i2c_slave_parse_reg(FDTGenericMMap *obj, FDTGenericRegPropInfo reg,
269 Error **errp)
270{
271 DeviceState *parent;
272 I2CSlave *slave;
273
274 slave = I2C_SLAVE(obj);
275
276 slave->address = reg.a[0];
277 parent = (DeviceState *)object_dynamic_cast(reg.parents[0], TYPE_DEVICE);
278
279 if (!parent) {
280 return false;
281 }
282
283 if (!parent->realized) {
284 return true;
285 }
286
287 qdev_set_parent_bus(DEVICE(obj), qdev_get_child_bus(parent, "i2c"));
288
289 return false;
290}
291
292static void i2c_slave_class_init(ObjectClass *klass, void *data)
293{
294 DeviceClass *k = DEVICE_CLASS(klass);
295 FDTGenericMMapClass *fmc = FDT_GENERIC_MMAP_CLASS(klass);
296 k->init = i2c_slave_qdev_init;
297 set_bit(DEVICE_CATEGORY_MISC, k->categories);
298 k->bus_type = TYPE_I2C_BUS;
299 k->props = i2c_props;
300 fmc->parse_reg = i2c_slave_parse_reg;
301}
302
303static const TypeInfo i2c_slave_type_info = {
304 .name = TYPE_I2C_SLAVE,
305 .parent = TYPE_DEVICE,
306 .instance_size = sizeof(I2CSlave),
307 .abstract = true,
308 .class_size = sizeof(I2CSlaveClass),
309 .class_init = i2c_slave_class_init,
310 .interfaces = (InterfaceInfo []) {
311 { TYPE_FDT_GENERIC_MMAP },
312 },
313};
314
315static void i2c_slave_register_types(void)
316{
317 type_register_static(&i2c_bus_info);
318 type_register_static(&i2c_slave_type_info);
319}
320
321type_init(i2c_slave_register_types)
322