xref: /qemu/hw/i2c/core.c (revision 08bb9b347b9597252338a599421818f4a4e333cb)
10ff596d0Spbrook /*
20ff596d0Spbrook  * QEMU I2C bus interface.
30ff596d0Spbrook  *
40ff596d0Spbrook  * Copyright (c) 2007 CodeSourcery.
50ff596d0Spbrook  * Written by Paul Brook
60ff596d0Spbrook  *
78e31bf38SMatthew Fernandez  * This code is licensed under the LGPL.
80ff596d0Spbrook  */
90ff596d0Spbrook 
100430891cSPeter Maydell #include "qemu/osdep.h"
110d09e41aSPaolo Bonzini #include "hw/i2c/i2c.h"
12*08bb9b34SPhilippe Mathieu-Daudé #include "trace.h"
130ff596d0Spbrook 
1471ae65e5SIgor Mammedov #define I2C_BROADCAST 0x00
1571ae65e5SIgor Mammedov 
163cb75a7cSPaolo Bonzini static Property i2c_props[] = {
173cb75a7cSPaolo Bonzini     DEFINE_PROP_UINT8("address", struct I2CSlave, address, 0),
183cb75a7cSPaolo Bonzini     DEFINE_PROP_END_OF_LIST(),
193cb75a7cSPaolo Bonzini };
203cb75a7cSPaolo Bonzini 
210d936928SAnthony Liguori static const TypeInfo i2c_bus_info = {
220d936928SAnthony Liguori     .name = TYPE_I2C_BUS,
230d936928SAnthony Liguori     .parent = TYPE_BUS,
24a5c82852SAndreas Färber     .instance_size = sizeof(I2CBus),
2510c4c98aSGerd Hoffmann };
2610c4c98aSGerd Hoffmann 
2744b1ff31SDr. David Alan Gilbert static int i2c_bus_pre_save(void *opaque)
28c701b35bSpbrook {
29a5c82852SAndreas Färber     I2CBus *bus = opaque;
30c701b35bSpbrook 
312293c27fSKONRAD Frederic     bus->saved_address = -1;
322293c27fSKONRAD Frederic     if (!QLIST_EMPTY(&bus->current_devs)) {
332293c27fSKONRAD Frederic         if (!bus->broadcast) {
342293c27fSKONRAD Frederic             bus->saved_address = QLIST_FIRST(&bus->current_devs)->elt->address;
3571ae65e5SIgor Mammedov         } else {
3671ae65e5SIgor Mammedov             bus->saved_address = I2C_BROADCAST;
37c701b35bSpbrook         }
382293c27fSKONRAD Frederic     }
3944b1ff31SDr. David Alan Gilbert 
4044b1ff31SDr. David Alan Gilbert     return 0;
41c701b35bSpbrook }
42c701b35bSpbrook 
438d0eb050SJuan Quintela static const VMStateDescription vmstate_i2c_bus = {
448d0eb050SJuan Quintela     .name = "i2c_bus",
458d0eb050SJuan Quintela     .version_id = 1,
468d0eb050SJuan Quintela     .minimum_version_id = 1,
478d0eb050SJuan Quintela     .pre_save = i2c_bus_pre_save,
488d0eb050SJuan Quintela     .fields = (VMStateField[]) {
49a5c82852SAndreas Färber         VMSTATE_UINT8(saved_address, I2CBus),
508d0eb050SJuan Quintela         VMSTATE_END_OF_LIST()
518d0eb050SJuan Quintela     }
528d0eb050SJuan Quintela };
538d0eb050SJuan Quintela 
540ff596d0Spbrook /* Create a new I2C bus.  */
55a5c82852SAndreas Färber I2CBus *i2c_init_bus(DeviceState *parent, const char *name)
560ff596d0Spbrook {
57a5c82852SAndreas Färber     I2CBus *bus;
580ff596d0Spbrook 
59fef7fbc9SAndreas Färber     bus = I2C_BUS(qbus_create(TYPE_I2C_BUS, parent, name));
602293c27fSKONRAD Frederic     QLIST_INIT(&bus->current_devs);
610be71e32SAlex Williamson     vmstate_register(NULL, -1, &vmstate_i2c_bus, bus);
620ff596d0Spbrook     return bus;
630ff596d0Spbrook }
640ff596d0Spbrook 
659e07bdf8SAnthony Liguori void i2c_set_slave_address(I2CSlave *dev, uint8_t address)
660ff596d0Spbrook {
670ff596d0Spbrook     dev->address = address;
680ff596d0Spbrook }
690ff596d0Spbrook 
700ff596d0Spbrook /* Return nonzero if bus is busy.  */
71a5c82852SAndreas Färber int i2c_bus_busy(I2CBus *bus)
720ff596d0Spbrook {
732293c27fSKONRAD Frederic     return !QLIST_EMPTY(&bus->current_devs);
740ff596d0Spbrook }
750ff596d0Spbrook 
760ff596d0Spbrook /* TODO: Make this handle multiple masters.  */
77d307c28cSCorey Minyard /*
78d307c28cSCorey Minyard  * Start or continue an i2c transaction.  When this is called for the
79d307c28cSCorey Minyard  * first time or after an i2c_end_transfer(), if it returns an error
80d307c28cSCorey Minyard  * the bus transaction is terminated (or really never started).  If
81d307c28cSCorey Minyard  * this is called after another i2c_start_transfer() without an
82d307c28cSCorey Minyard  * intervening i2c_end_transfer(), and it returns an error, the
83d307c28cSCorey Minyard  * transaction will not be terminated.  The caller must do it.
84d307c28cSCorey Minyard  *
85d307c28cSCorey Minyard  * This corresponds with the way real hardware works.  The SMBus
86d307c28cSCorey Minyard  * protocol uses a start transfer to switch from write to read mode
87d307c28cSCorey Minyard  * without releasing the bus.  If that fails, the bus is still
88d307c28cSCorey Minyard  * in a transaction.
89d307c28cSCorey Minyard  */
90a5c82852SAndreas Färber int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv)
910ff596d0Spbrook {
920866aca1SAnthony Liguori     BusChild *kid;
93b5ea9327SAnthony Liguori     I2CSlaveClass *sc;
942293c27fSKONRAD Frederic     I2CNode *node;
95d307c28cSCorey Minyard     bool bus_scanned = false;
962293c27fSKONRAD Frederic 
9771ae65e5SIgor Mammedov     if (address == I2C_BROADCAST) {
982293c27fSKONRAD Frederic         /*
992293c27fSKONRAD Frederic          * This is a broadcast, the current_devs will be all the devices of the
1002293c27fSKONRAD Frederic          * bus.
1012293c27fSKONRAD Frederic          */
1022293c27fSKONRAD Frederic         bus->broadcast = true;
1032293c27fSKONRAD Frederic     }
1040ff596d0Spbrook 
1050fa758c3SCorey Minyard     /*
1060fa758c3SCorey Minyard      * If there are already devices in the list, that means we are in
1070fa758c3SCorey Minyard      * the middle of a transaction and we shouldn't rescan the bus.
1080fa758c3SCorey Minyard      *
1090fa758c3SCorey Minyard      * This happens with any SMBus transaction, even on a pure I2C
1100fa758c3SCorey Minyard      * device.  The interface does a transaction start without
1110fa758c3SCorey Minyard      * terminating the previous transaction.
1120fa758c3SCorey Minyard      */
1130fa758c3SCorey Minyard     if (QLIST_EMPTY(&bus->current_devs)) {
1140866aca1SAnthony Liguori         QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) {
1150866aca1SAnthony Liguori             DeviceState *qdev = kid->child;
1168aae84a1SAndreas Färber             I2CSlave *candidate = I2C_SLAVE(qdev);
1172293c27fSKONRAD Frederic             if ((candidate->address == address) || (bus->broadcast)) {
1182293c27fSKONRAD Frederic                 node = g_malloc(sizeof(struct I2CNode));
1192293c27fSKONRAD Frederic                 node->elt = candidate;
1202293c27fSKONRAD Frederic                 QLIST_INSERT_HEAD(&bus->current_devs, node, next);
1212293c27fSKONRAD Frederic                 if (!bus->broadcast) {
1220ff596d0Spbrook                     break;
1230ff596d0Spbrook                 }
124b3a21988SJuha Riihimäki             }
1252293c27fSKONRAD Frederic         }
126d307c28cSCorey Minyard         bus_scanned = true;
1270fa758c3SCorey Minyard     }
1280ff596d0Spbrook 
1292293c27fSKONRAD Frederic     if (QLIST_EMPTY(&bus->current_devs)) {
1300ff596d0Spbrook         return 1;
131b5ea9327SAnthony Liguori     }
1320ff596d0Spbrook 
1332293c27fSKONRAD Frederic     QLIST_FOREACH(node, &bus->current_devs, next) {
134*08bb9b34SPhilippe Mathieu-Daudé         I2CSlave *s = node->elt;
135d307c28cSCorey Minyard         int rv;
136d307c28cSCorey Minyard 
137*08bb9b34SPhilippe Mathieu-Daudé         sc = I2C_SLAVE_GET_CLASS(s);
1380ff596d0Spbrook         /* If the bus is already busy, assume this is a repeated
1390ff596d0Spbrook            start condition.  */
140d307c28cSCorey Minyard 
141b5ea9327SAnthony Liguori         if (sc->event) {
142*08bb9b34SPhilippe Mathieu-Daudé             trace_i2c_event("start", s->address);
143*08bb9b34SPhilippe Mathieu-Daudé             rv = sc->event(s, recv ? I2C_START_RECV : I2C_START_SEND);
144d307c28cSCorey Minyard             if (rv && !bus->broadcast) {
145d307c28cSCorey Minyard                 if (bus_scanned) {
146d307c28cSCorey Minyard                     /* First call, terminate the transfer. */
147d307c28cSCorey Minyard                     i2c_end_transfer(bus);
148d307c28cSCorey Minyard                 }
149d307c28cSCorey Minyard                 return rv;
150d307c28cSCorey Minyard             }
1512293c27fSKONRAD Frederic         }
152b5ea9327SAnthony Liguori     }
1530ff596d0Spbrook     return 0;
1540ff596d0Spbrook }
1550ff596d0Spbrook 
156a5c82852SAndreas Färber void i2c_end_transfer(I2CBus *bus)
1570ff596d0Spbrook {
158b5ea9327SAnthony Liguori     I2CSlaveClass *sc;
1592293c27fSKONRAD Frederic     I2CNode *node, *next;
1600ff596d0Spbrook 
1612293c27fSKONRAD Frederic     QLIST_FOREACH_SAFE(node, &bus->current_devs, next, next) {
162*08bb9b34SPhilippe Mathieu-Daudé         I2CSlave *s = node->elt;
163*08bb9b34SPhilippe Mathieu-Daudé         sc = I2C_SLAVE_GET_CLASS(s);
164b5ea9327SAnthony Liguori         if (sc->event) {
165*08bb9b34SPhilippe Mathieu-Daudé             trace_i2c_event("finish", s->address);
166*08bb9b34SPhilippe Mathieu-Daudé             sc->event(s, I2C_FINISH);
167b5ea9327SAnthony Liguori         }
1682293c27fSKONRAD Frederic         QLIST_REMOVE(node, next);
1692293c27fSKONRAD Frederic         g_free(node);
1702293c27fSKONRAD Frederic     }
1712293c27fSKONRAD Frederic     bus->broadcast = false;
1720ff596d0Spbrook }
1730ff596d0Spbrook 
174056fca7bSPeter Crosthwaite int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send)
1750ff596d0Spbrook {
176b5ea9327SAnthony Liguori     I2CSlaveClass *sc;
177*08bb9b34SPhilippe Mathieu-Daudé     I2CSlave *s;
1782293c27fSKONRAD Frederic     I2CNode *node;
1792293c27fSKONRAD Frederic     int ret = 0;
1800ff596d0Spbrook 
181056fca7bSPeter Crosthwaite     if (send) {
1822293c27fSKONRAD Frederic         QLIST_FOREACH(node, &bus->current_devs, next) {
183*08bb9b34SPhilippe Mathieu-Daudé             s = node->elt;
184*08bb9b34SPhilippe Mathieu-Daudé             sc = I2C_SLAVE_GET_CLASS(s);
185b5ea9327SAnthony Liguori             if (sc->send) {
186*08bb9b34SPhilippe Mathieu-Daudé                 trace_i2c_send(s->address, *data);
187*08bb9b34SPhilippe Mathieu-Daudé                 ret = ret || sc->send(s, *data);
1882293c27fSKONRAD Frederic             } else {
1892293c27fSKONRAD Frederic                 ret = -1;
190b5ea9327SAnthony Liguori             }
1912293c27fSKONRAD Frederic         }
1922293c27fSKONRAD Frederic         return ret ? -1 : 0;
193056fca7bSPeter Crosthwaite     } else {
1942293c27fSKONRAD Frederic         if ((QLIST_EMPTY(&bus->current_devs)) || (bus->broadcast)) {
1950ff596d0Spbrook             return -1;
196b5ea9327SAnthony Liguori         }
1970ff596d0Spbrook 
1982293c27fSKONRAD Frederic         sc = I2C_SLAVE_GET_CLASS(QLIST_FIRST(&bus->current_devs)->elt);
199b5ea9327SAnthony Liguori         if (sc->recv) {
200*08bb9b34SPhilippe Mathieu-Daudé             s = QLIST_FIRST(&bus->current_devs)->elt;
201*08bb9b34SPhilippe Mathieu-Daudé             ret = sc->recv(s);
202*08bb9b34SPhilippe Mathieu-Daudé             trace_i2c_recv(s->address, ret);
203056fca7bSPeter Crosthwaite             if (ret < 0) {
204056fca7bSPeter Crosthwaite                 return ret;
205056fca7bSPeter Crosthwaite             } else {
206056fca7bSPeter Crosthwaite                 *data = ret;
207056fca7bSPeter Crosthwaite                 return 0;
208056fca7bSPeter Crosthwaite             }
209b5ea9327SAnthony Liguori         }
210b5ea9327SAnthony Liguori         return -1;
2110ff596d0Spbrook     }
212056fca7bSPeter Crosthwaite }
213056fca7bSPeter Crosthwaite 
214056fca7bSPeter Crosthwaite int i2c_send(I2CBus *bus, uint8_t data)
215056fca7bSPeter Crosthwaite {
216056fca7bSPeter Crosthwaite     return i2c_send_recv(bus, &data, true);
217056fca7bSPeter Crosthwaite }
218056fca7bSPeter Crosthwaite 
219056fca7bSPeter Crosthwaite int i2c_recv(I2CBus *bus)
220056fca7bSPeter Crosthwaite {
221056fca7bSPeter Crosthwaite     uint8_t data;
222056fca7bSPeter Crosthwaite     int ret = i2c_send_recv(bus, &data, false);
223056fca7bSPeter Crosthwaite 
224056fca7bSPeter Crosthwaite     return ret < 0 ? ret : data;
225056fca7bSPeter Crosthwaite }
2260ff596d0Spbrook 
227a5c82852SAndreas Färber void i2c_nack(I2CBus *bus)
2280ff596d0Spbrook {
229b5ea9327SAnthony Liguori     I2CSlaveClass *sc;
2302293c27fSKONRAD Frederic     I2CNode *node;
2310ff596d0Spbrook 
2322293c27fSKONRAD Frederic     if (QLIST_EMPTY(&bus->current_devs)) {
2330ff596d0Spbrook         return;
234b5ea9327SAnthony Liguori     }
2350ff596d0Spbrook 
2362293c27fSKONRAD Frederic     QLIST_FOREACH(node, &bus->current_devs, next) {
2372293c27fSKONRAD Frederic         sc = I2C_SLAVE_GET_CLASS(node->elt);
238b5ea9327SAnthony Liguori         if (sc->event) {
239*08bb9b34SPhilippe Mathieu-Daudé             trace_i2c_event("nack", node->elt->address);
2402293c27fSKONRAD Frederic             sc->event(node->elt, I2C_NACK);
2412293c27fSKONRAD Frederic         }
242b5ea9327SAnthony Liguori     }
2430ff596d0Spbrook }
2440ff596d0Spbrook 
245bcbe8068SJuan Quintela static int i2c_slave_post_load(void *opaque, int version_id)
246bcbe8068SJuan Quintela {
2479e07bdf8SAnthony Liguori     I2CSlave *dev = opaque;
248a5c82852SAndreas Färber     I2CBus *bus;
2492293c27fSKONRAD Frederic     I2CNode *node;
2502293c27fSKONRAD Frederic 
251fef7fbc9SAndreas Färber     bus = I2C_BUS(qdev_get_parent_bus(DEVICE(dev)));
25271ae65e5SIgor Mammedov     if ((bus->saved_address == dev->address) ||
25371ae65e5SIgor Mammedov         (bus->saved_address == I2C_BROADCAST)) {
2542293c27fSKONRAD Frederic         node = g_malloc(sizeof(struct I2CNode));
2552293c27fSKONRAD Frederic         node->elt = dev;
2562293c27fSKONRAD Frederic         QLIST_INSERT_HEAD(&bus->current_devs, node, next);
257bcbe8068SJuan Quintela     }
258bcbe8068SJuan Quintela     return 0;
259bcbe8068SJuan Quintela }
260bcbe8068SJuan Quintela 
2611894839fSJuan Quintela const VMStateDescription vmstate_i2c_slave = {
2629e07bdf8SAnthony Liguori     .name = "I2CSlave",
263bcbe8068SJuan Quintela     .version_id = 1,
264bcbe8068SJuan Quintela     .minimum_version_id = 1,
265bcbe8068SJuan Quintela     .post_load = i2c_slave_post_load,
266bcbe8068SJuan Quintela     .fields = (VMStateField[]) {
2679e07bdf8SAnthony Liguori         VMSTATE_UINT8(address, I2CSlave),
268bcbe8068SJuan Quintela         VMSTATE_END_OF_LIST()
269bcbe8068SJuan Quintela     }
270bcbe8068SJuan Quintela };
271bcbe8068SJuan Quintela 
272a5c82852SAndreas Färber DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr)
273fe8de492SPaul Brook {
274fe8de492SPaul Brook     DeviceState *dev;
275fe8de492SPaul Brook 
27602e2da45SPaul Brook     dev = qdev_create(&bus->qbus, name);
2775b7f5327SJuan Quintela     qdev_prop_set_uint8(dev, "address", addr);
278e23a1b33SMarkus Armbruster     qdev_init_nofail(dev);
279fe8de492SPaul Brook     return dev;
280aa941b94Sbalrog }
281b5ea9327SAnthony Liguori 
28239bffca2SAnthony Liguori static void i2c_slave_class_init(ObjectClass *klass, void *data)
28339bffca2SAnthony Liguori {
28439bffca2SAnthony Liguori     DeviceClass *k = DEVICE_CLASS(klass);
285125ee0edSMarcel Apfelbaum     set_bit(DEVICE_CATEGORY_MISC, k->categories);
2860d936928SAnthony Liguori     k->bus_type = TYPE_I2C_BUS;
287bce54474SPaolo Bonzini     k->props = i2c_props;
28839bffca2SAnthony Liguori }
28939bffca2SAnthony Liguori 
2908c43a6f0SAndreas Färber static const TypeInfo i2c_slave_type_info = {
291b5ea9327SAnthony Liguori     .name = TYPE_I2C_SLAVE,
292b5ea9327SAnthony Liguori     .parent = TYPE_DEVICE,
293b5ea9327SAnthony Liguori     .instance_size = sizeof(I2CSlave),
294b5ea9327SAnthony Liguori     .abstract = true,
295b5ea9327SAnthony Liguori     .class_size = sizeof(I2CSlaveClass),
29639bffca2SAnthony Liguori     .class_init = i2c_slave_class_init,
297b5ea9327SAnthony Liguori };
298b5ea9327SAnthony Liguori 
29983f7d43aSAndreas Färber static void i2c_slave_register_types(void)
300b5ea9327SAnthony Liguori {
3010d936928SAnthony Liguori     type_register_static(&i2c_bus_info);
302b5ea9327SAnthony Liguori     type_register_static(&i2c_slave_type_info);
303b5ea9327SAnthony Liguori }
304b5ea9327SAnthony Liguori 
30583f7d43aSAndreas Färber type_init(i2c_slave_register_types)
306