Annotation of qemu/hw/i2c.c, revision 1.1.1.9

1.1       root        1: /*
                      2:  * QEMU I2C bus interface.
                      3:  *
                      4:  * Copyright (c) 2007 CodeSourcery.
                      5:  * Written by Paul Brook
                      6:  *
1.1.1.7   root        7:  * This code is licensed under the LGPL.
1.1       root        8:  */
                      9: 
                     10: #include "i2c.h"
                     11: 
                     12: struct i2c_bus
                     13: {
1.1.1.3   root       14:     BusState qbus;
1.1.1.9 ! root       15:     I2CSlave *current_dev;
        !            16:     I2CSlave *dev;
1.1.1.5   root       17:     uint8_t saved_address;
1.1       root       18: };
                     19: 
1.1.1.3   root       20: static struct BusInfo i2c_bus_info = {
                     21:     .name = "I2C",
                     22:     .size = sizeof(i2c_bus),
                     23:     .props = (Property[]) {
1.1.1.9 ! root       24:         DEFINE_PROP_UINT8("address", struct I2CSlave, address, 0),
1.1.1.5   root       25:         DEFINE_PROP_END_OF_LIST(),
1.1.1.3   root       26:     }
                     27: };
                     28: 
1.1.1.5   root       29: static void i2c_bus_pre_save(void *opaque)
1.1.1.2   root       30: {
1.1.1.5   root       31:     i2c_bus *bus = opaque;
1.1.1.2   root       32: 
1.1.1.5   root       33:     bus->saved_address = bus->current_dev ? bus->current_dev->address : -1;
1.1.1.2   root       34: }
                     35: 
1.1.1.5   root       36: static int i2c_bus_post_load(void *opaque, int version_id)
1.1.1.2   root       37: {
1.1.1.5   root       38:     i2c_bus *bus = opaque;
1.1.1.2   root       39: 
                     40:     /* The bus is loaded before attached devices, so load and save the
                     41:        current device id.  Devices will check themselves as loaded.  */
                     42:     bus->current_dev = NULL;
                     43:     return 0;
                     44: }
                     45: 
1.1.1.5   root       46: static const VMStateDescription vmstate_i2c_bus = {
                     47:     .name = "i2c_bus",
                     48:     .version_id = 1,
                     49:     .minimum_version_id = 1,
                     50:     .minimum_version_id_old = 1,
                     51:     .pre_save = i2c_bus_pre_save,
                     52:     .post_load = i2c_bus_post_load,
                     53:     .fields      = (VMStateField []) {
                     54:         VMSTATE_UINT8(saved_address, i2c_bus),
                     55:         VMSTATE_END_OF_LIST()
                     56:     }
                     57: };
                     58: 
1.1       root       59: /* Create a new I2C bus.  */
1.1.1.3   root       60: i2c_bus *i2c_init_bus(DeviceState *parent, const char *name)
1.1       root       61: {
                     62:     i2c_bus *bus;
                     63: 
1.1.1.3   root       64:     bus = FROM_QBUS(i2c_bus, qbus_create(&i2c_bus_info, parent, name));
1.1.1.6   root       65:     vmstate_register(NULL, -1, &vmstate_i2c_bus, bus);
1.1       root       66:     return bus;
                     67: }
                     68: 
1.1.1.9 ! root       69: void i2c_set_slave_address(I2CSlave *dev, uint8_t address)
1.1       root       70: {
                     71:     dev->address = address;
                     72: }
                     73: 
                     74: /* Return nonzero if bus is busy.  */
                     75: int i2c_bus_busy(i2c_bus *bus)
                     76: {
                     77:     return bus->current_dev != NULL;
                     78: }
                     79: 
                     80: /* Returns non-zero if the address is not valid.  */
                     81: /* TODO: Make this handle multiple masters.  */
1.1.1.5   root       82: int i2c_start_transfer(i2c_bus *bus, uint8_t address, int recv)
1.1       root       83: {
1.1.1.3   root       84:     DeviceState *qdev;
1.1.1.9 ! root       85:     I2CSlave *slave = NULL;
        !            86:     I2CSlaveClass *sc;
1.1       root       87: 
1.1.1.8   root       88:     QTAILQ_FOREACH(qdev, &bus->qbus.children, sibling) {
1.1.1.9 ! root       89:         I2CSlave *candidate = I2C_SLAVE_FROM_QDEV(qdev);
1.1.1.4   root       90:         if (candidate->address == address) {
                     91:             slave = candidate;
1.1       root       92:             break;
1.1.1.4   root       93:         }
1.1       root       94:     }
                     95: 
1.1.1.9 ! root       96:     if (!slave) {
1.1       root       97:         return 1;
1.1.1.9 ! root       98:     }
1.1       root       99: 
1.1.1.9 ! root      100:     sc = I2C_SLAVE_GET_CLASS(slave);
1.1       root      101:     /* If the bus is already busy, assume this is a repeated
                    102:        start condition.  */
1.1.1.3   root      103:     bus->current_dev = slave;
1.1.1.9 ! root      104:     if (sc->event) {
        !           105:         sc->event(slave, recv ? I2C_START_RECV : I2C_START_SEND);
        !           106:     }
1.1       root      107:     return 0;
                    108: }
                    109: 
                    110: void i2c_end_transfer(i2c_bus *bus)
                    111: {
1.1.1.9 ! root      112:     I2CSlave *dev = bus->current_dev;
        !           113:     I2CSlaveClass *sc;
1.1       root      114: 
1.1.1.9 ! root      115:     if (!dev) {
1.1       root      116:         return;
1.1.1.9 ! root      117:     }
1.1       root      118: 
1.1.1.9 ! root      119:     sc = I2C_SLAVE_GET_CLASS(dev);
        !           120:     if (sc->event) {
        !           121:         sc->event(dev, I2C_FINISH);
        !           122:     }
1.1       root      123: 
                    124:     bus->current_dev = NULL;
                    125: }
                    126: 
                    127: int i2c_send(i2c_bus *bus, uint8_t data)
                    128: {
1.1.1.9 ! root      129:     I2CSlave *dev = bus->current_dev;
        !           130:     I2CSlaveClass *sc;
1.1       root      131: 
1.1.1.9 ! root      132:     if (!dev) {
1.1       root      133:         return -1;
1.1.1.9 ! root      134:     }
        !           135: 
        !           136:     sc = I2C_SLAVE_GET_CLASS(dev);
        !           137:     if (sc->send) {
        !           138:         return sc->send(dev, data);
        !           139:     }
1.1       root      140: 
1.1.1.9 ! root      141:     return -1;
1.1       root      142: }
                    143: 
                    144: int i2c_recv(i2c_bus *bus)
                    145: {
1.1.1.9 ! root      146:     I2CSlave *dev = bus->current_dev;
        !           147:     I2CSlaveClass *sc;
1.1       root      148: 
1.1.1.9 ! root      149:     if (!dev) {
1.1       root      150:         return -1;
1.1.1.9 ! root      151:     }
        !           152: 
        !           153:     sc = I2C_SLAVE_GET_CLASS(dev);
        !           154:     if (sc->recv) {
        !           155:         return sc->recv(dev);
        !           156:     }
1.1       root      157: 
1.1.1.9 ! root      158:     return -1;
1.1       root      159: }
                    160: 
                    161: void i2c_nack(i2c_bus *bus)
                    162: {
1.1.1.9 ! root      163:     I2CSlave *dev = bus->current_dev;
        !           164:     I2CSlaveClass *sc;
1.1       root      165: 
1.1.1.9 ! root      166:     if (!dev) {
1.1       root      167:         return;
1.1.1.9 ! root      168:     }
1.1       root      169: 
1.1.1.9 ! root      170:     sc = I2C_SLAVE_GET_CLASS(dev);
        !           171:     if (sc->event) {
        !           172:         sc->event(dev, I2C_NACK);
        !           173:     }
1.1       root      174: }
                    175: 
1.1.1.5   root      176: static int i2c_slave_post_load(void *opaque, int version_id)
1.1       root      177: {
1.1.1.9 ! root      178:     I2CSlave *dev = opaque;
1.1.1.3   root      179:     i2c_bus *bus;
                    180:     bus = FROM_QBUS(i2c_bus, qdev_get_parent_bus(&dev->qdev));
                    181:     if (bus->saved_address == dev->address) {
                    182:         bus->current_dev = dev;
                    183:     }
1.1.1.5   root      184:     return 0;
1.1.1.3   root      185: }
                    186: 
1.1.1.5   root      187: const VMStateDescription vmstate_i2c_slave = {
1.1.1.9 ! root      188:     .name = "I2CSlave",
1.1.1.5   root      189:     .version_id = 1,
                    190:     .minimum_version_id = 1,
                    191:     .minimum_version_id_old = 1,
                    192:     .post_load = i2c_slave_post_load,
                    193:     .fields      = (VMStateField []) {
1.1.1.9 ! root      194:         VMSTATE_UINT8(address, I2CSlave),
1.1.1.5   root      195:         VMSTATE_END_OF_LIST()
                    196:     }
                    197: };
                    198: 
1.1.1.9 ! root      199: static int i2c_slave_qdev_init(DeviceState *dev)
1.1.1.3   root      200: {
1.1.1.9 ! root      201:     I2CSlave *s = I2C_SLAVE_FROM_QDEV(dev);
        !           202:     I2CSlaveClass *sc = I2C_SLAVE_GET_CLASS(s);
1.1.1.3   root      203: 
1.1.1.9 ! root      204:     return sc->init(s);
1.1.1.3   root      205: }
                    206: 
1.1.1.5   root      207: DeviceState *i2c_create_slave(i2c_bus *bus, const char *name, uint8_t addr)
1.1.1.3   root      208: {
                    209:     DeviceState *dev;
                    210: 
                    211:     dev = qdev_create(&bus->qbus, name);
1.1.1.5   root      212:     qdev_prop_set_uint8(dev, "address", addr);
                    213:     qdev_init_nofail(dev);
1.1.1.3   root      214:     return dev;
1.1       root      215: }
1.1.1.9 ! root      216: 
        !           217: static void i2c_slave_class_init(ObjectClass *klass, void *data)
        !           218: {
        !           219:     DeviceClass *k = DEVICE_CLASS(klass);
        !           220:     k->init = i2c_slave_qdev_init;
        !           221:     k->bus_info = &i2c_bus_info;
        !           222: }
        !           223: 
        !           224: static TypeInfo i2c_slave_type_info = {
        !           225:     .name = TYPE_I2C_SLAVE,
        !           226:     .parent = TYPE_DEVICE,
        !           227:     .instance_size = sizeof(I2CSlave),
        !           228:     .abstract = true,
        !           229:     .class_size = sizeof(I2CSlaveClass),
        !           230:     .class_init = i2c_slave_class_init,
        !           231: };
        !           232: 
        !           233: static void i2c_slave_register_types(void)
        !           234: {
        !           235:     type_register_static(&i2c_slave_type_info);
        !           236: }
        !           237: 
        !           238: type_init(i2c_slave_register_types)

unix.superglobalmegacorp.com