qemu/hw/smbus.c
<<
>>
Prefs
   1/*
   2 * QEMU SMBus device emulation.
   3 *
   4 * Copyright (c) 2007 CodeSourcery.
   5 * Written by Paul Brook
   6 *
   7 * This code is licensed under the LGPL.
   8 */
   9
  10/* TODO: Implement PEC.  */
  11
  12#include "hw.h"
  13#include "i2c.h"
  14#include "smbus.h"
  15
  16//#define DEBUG_SMBUS 1
  17
  18#ifdef DEBUG_SMBUS
  19#define DPRINTF(fmt, ...) \
  20do { printf("smbus(%02x): " fmt , dev->i2c.address, ## __VA_ARGS__); } while (0)
  21#define BADF(fmt, ...) \
  22do { fprintf(stderr, "smbus: error: " fmt , ## __VA_ARGS__); exit(1);} while (0)
  23#else
  24#define DPRINTF(fmt, ...) do {} while(0)
  25#define BADF(fmt, ...) \
  26do { fprintf(stderr, "smbus: error: " fmt , ## __VA_ARGS__);} while (0)
  27#endif
  28
  29enum {
  30    SMBUS_IDLE,
  31    SMBUS_WRITE_DATA,
  32    SMBUS_RECV_BYTE,
  33    SMBUS_READ_DATA,
  34    SMBUS_DONE,
  35    SMBUS_CONFUSED = -1
  36};
  37
  38static void smbus_do_quick_cmd(SMBusDevice *dev, int recv)
  39{
  40    SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
  41
  42    DPRINTF("Quick Command %d\n", recv);
  43    if (sc->quick_cmd) {
  44        sc->quick_cmd(dev, recv);
  45    }
  46}
  47
  48static void smbus_do_write(SMBusDevice *dev)
  49{
  50    SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
  51
  52    if (dev->data_len == 0) {
  53        smbus_do_quick_cmd(dev, 0);
  54    } else if (dev->data_len == 1) {
  55        DPRINTF("Send Byte\n");
  56        if (sc->send_byte) {
  57            sc->send_byte(dev, dev->data_buf[0]);
  58        }
  59    } else {
  60        dev->command = dev->data_buf[0];
  61        DPRINTF("Command %d len %d\n", dev->command, dev->data_len - 1);
  62        if (sc->write_data) {
  63            sc->write_data(dev, dev->command, dev->data_buf + 1,
  64                           dev->data_len - 1);
  65        }
  66    }
  67}
  68
  69static void smbus_i2c_event(I2CSlave *s, enum i2c_event event)
  70{
  71    SMBusDevice *dev = SMBUS_DEVICE(s);
  72
  73    switch (event) {
  74    case I2C_START_SEND:
  75        switch (dev->mode) {
  76        case SMBUS_IDLE:
  77            DPRINTF("Incoming data\n");
  78            dev->mode = SMBUS_WRITE_DATA;
  79            break;
  80        default:
  81            BADF("Unexpected send start condition in state %d\n", dev->mode);
  82            dev->mode = SMBUS_CONFUSED;
  83            break;
  84        }
  85        break;
  86
  87    case I2C_START_RECV:
  88        switch (dev->mode) {
  89        case SMBUS_IDLE:
  90            DPRINTF("Read mode\n");
  91            dev->mode = SMBUS_RECV_BYTE;
  92            break;
  93        case SMBUS_WRITE_DATA:
  94            if (dev->data_len == 0) {
  95                BADF("Read after write with no data\n");
  96                dev->mode = SMBUS_CONFUSED;
  97            } else {
  98                if (dev->data_len > 1) {
  99                    smbus_do_write(dev);
 100                } else {
 101                    dev->command = dev->data_buf[0];
 102                    DPRINTF("%02x: Command %d\n", dev->i2c.address,
 103                            dev->command);
 104                }
 105                DPRINTF("Read mode\n");
 106                dev->data_len = 0;
 107                dev->mode = SMBUS_READ_DATA;
 108            }
 109            break;
 110        default:
 111            BADF("Unexpected recv start condition in state %d\n", dev->mode);
 112            dev->mode = SMBUS_CONFUSED;
 113            break;
 114        }
 115        break;
 116
 117    case I2C_FINISH:
 118        switch (dev->mode) {
 119        case SMBUS_WRITE_DATA:
 120            smbus_do_write(dev);
 121            break;
 122        case SMBUS_RECV_BYTE:
 123            smbus_do_quick_cmd(dev, 1);
 124            break;
 125        case SMBUS_READ_DATA:
 126            BADF("Unexpected stop during receive\n");
 127            break;
 128        default:
 129            /* Nothing to do.  */
 130            break;
 131        }
 132        dev->mode = SMBUS_IDLE;
 133        dev->data_len = 0;
 134        break;
 135
 136    case I2C_NACK:
 137        switch (dev->mode) {
 138        case SMBUS_DONE:
 139            /* Nothing to do.  */
 140            break;
 141        case SMBUS_READ_DATA:
 142            dev->mode = SMBUS_DONE;
 143            break;
 144        default:
 145            BADF("Unexpected NACK in state %d\n", dev->mode);
 146            dev->mode = SMBUS_CONFUSED;
 147            break;
 148        }
 149    }
 150}
 151
 152static int smbus_i2c_recv(I2CSlave *s)
 153{
 154    SMBusDevice *dev = SMBUS_DEVICE(s);
 155    SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
 156    int ret;
 157
 158    switch (dev->mode) {
 159    case SMBUS_RECV_BYTE:
 160        if (sc->receive_byte) {
 161            ret = sc->receive_byte(dev);
 162        } else {
 163            ret = 0;
 164        }
 165        DPRINTF("Receive Byte %02x\n", ret);
 166        dev->mode = SMBUS_DONE;
 167        break;
 168    case SMBUS_READ_DATA:
 169        if (sc->read_data) {
 170            ret = sc->read_data(dev, dev->command, dev->data_len);
 171            dev->data_len++;
 172        } else {
 173            ret = 0;
 174        }
 175        DPRINTF("Read data %02x\n", ret);
 176        break;
 177    default:
 178        BADF("Unexpected read in state %d\n", dev->mode);
 179        dev->mode = SMBUS_CONFUSED;
 180        ret = 0;
 181        break;
 182    }
 183    return ret;
 184}
 185
 186static int smbus_i2c_send(I2CSlave *s, uint8_t data)
 187{
 188    SMBusDevice *dev = SMBUS_DEVICE(s);
 189
 190    switch (dev->mode) {
 191    case SMBUS_WRITE_DATA:
 192        DPRINTF("Write data %02x\n", data);
 193        dev->data_buf[dev->data_len++] = data;
 194        break;
 195    default:
 196        BADF("Unexpected write in state %d\n", dev->mode);
 197        break;
 198    }
 199    return 0;
 200}
 201
 202static int smbus_device_init(I2CSlave *i2c)
 203{
 204    SMBusDevice *dev = SMBUS_DEVICE(i2c);
 205    SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
 206
 207    return sc->init(dev);
 208}
 209
 210/* Master device commands.  */
 211void smbus_quick_command(i2c_bus *bus, uint8_t addr, int read)
 212{
 213    i2c_start_transfer(bus, addr, read);
 214    i2c_end_transfer(bus);
 215}
 216
 217uint8_t smbus_receive_byte(i2c_bus *bus, uint8_t addr)
 218{
 219    uint8_t data;
 220
 221    i2c_start_transfer(bus, addr, 1);
 222    data = i2c_recv(bus);
 223    i2c_nack(bus);
 224    i2c_end_transfer(bus);
 225    return data;
 226}
 227
 228void smbus_send_byte(i2c_bus *bus, uint8_t addr, uint8_t data)
 229{
 230    i2c_start_transfer(bus, addr, 0);
 231    i2c_send(bus, data);
 232    i2c_end_transfer(bus);
 233}
 234
 235uint8_t smbus_read_byte(i2c_bus *bus, uint8_t addr, uint8_t command)
 236{
 237    uint8_t data;
 238    i2c_start_transfer(bus, addr, 0);
 239    i2c_send(bus, command);
 240    i2c_start_transfer(bus, addr, 1);
 241    data = i2c_recv(bus);
 242    i2c_nack(bus);
 243    i2c_end_transfer(bus);
 244    return data;
 245}
 246
 247void smbus_write_byte(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t data)
 248{
 249    i2c_start_transfer(bus, addr, 0);
 250    i2c_send(bus, command);
 251    i2c_send(bus, data);
 252    i2c_end_transfer(bus);
 253}
 254
 255uint16_t smbus_read_word(i2c_bus *bus, uint8_t addr, uint8_t command)
 256{
 257    uint16_t data;
 258    i2c_start_transfer(bus, addr, 0);
 259    i2c_send(bus, command);
 260    i2c_start_transfer(bus, addr, 1);
 261    data = i2c_recv(bus);
 262    data |= i2c_recv(bus) << 8;
 263    i2c_nack(bus);
 264    i2c_end_transfer(bus);
 265    return data;
 266}
 267
 268void smbus_write_word(i2c_bus *bus, uint8_t addr, uint8_t command, uint16_t data)
 269{
 270    i2c_start_transfer(bus, addr, 0);
 271    i2c_send(bus, command);
 272    i2c_send(bus, data & 0xff);
 273    i2c_send(bus, data >> 8);
 274    i2c_end_transfer(bus);
 275}
 276
 277int smbus_read_block(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t *data)
 278{
 279    int len;
 280    int i;
 281
 282    i2c_start_transfer(bus, addr, 0);
 283    i2c_send(bus, command);
 284    i2c_start_transfer(bus, addr, 1);
 285    len = i2c_recv(bus);
 286    if (len > 32)
 287        len = 0;
 288    for (i = 0; i < len; i++)
 289        data[i] = i2c_recv(bus);
 290    i2c_nack(bus);
 291    i2c_end_transfer(bus);
 292    return len;
 293}
 294
 295void smbus_write_block(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t *data,
 296                       int len)
 297{
 298    int i;
 299
 300    if (len > 32)
 301        len = 32;
 302
 303    i2c_start_transfer(bus, addr, 0);
 304    i2c_send(bus, command);
 305    i2c_send(bus, len);
 306    for (i = 0; i < len; i++)
 307        i2c_send(bus, data[i]);
 308    i2c_end_transfer(bus);
 309}
 310
 311static void smbus_device_class_init(ObjectClass *klass, void *data)
 312{
 313    I2CSlaveClass *sc = I2C_SLAVE_CLASS(klass);
 314
 315    sc->init = smbus_device_init;
 316    sc->event = smbus_i2c_event;
 317    sc->recv = smbus_i2c_recv;
 318    sc->send = smbus_i2c_send;
 319}
 320
 321static TypeInfo smbus_device_type_info = {
 322    .name = TYPE_SMBUS_DEVICE,
 323    .parent = TYPE_I2C_SLAVE,
 324    .instance_size = sizeof(SMBusDevice),
 325    .abstract = true,
 326    .class_size = sizeof(SMBusDeviceClass),
 327    .class_init = smbus_device_class_init,
 328};
 329
 330static void smbus_device_register_types(void)
 331{
 332    type_register_static(&smbus_device_type_info);
 333}
 334
 335type_init(smbus_device_register_types)
 336