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