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 licenced 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    SMBusDeviceInfo *t = container_of(dev->i2c.info, SMBusDeviceInfo, i2c);
  41
  42    DPRINTF("Quick Command %d\n", recv);
  43    if (t->quick_cmd)
  44        t->quick_cmd(dev, recv);
  45}
  46
  47static void smbus_do_write(SMBusDevice *dev)
  48{
  49    SMBusDeviceInfo *t = container_of(dev->i2c.info, SMBusDeviceInfo, i2c);
  50
  51    if (dev->data_len == 0) {
  52        smbus_do_quick_cmd(dev, 0);
  53    } else if (dev->data_len == 1) {
  54        DPRINTF("Send Byte\n");
  55        if (t->send_byte) {
  56            t->send_byte(dev, dev->data_buf[0]);
  57        }
  58    } else {
  59        dev->command = dev->data_buf[0];
  60        DPRINTF("Command %d len %d\n", dev->command, dev->data_len - 1);
  61        if (t->write_data) {
  62            t->write_data(dev, dev->command, dev->data_buf + 1,
  63                          dev->data_len - 1);
  64        }
  65    }
  66}
  67
  68static void smbus_i2c_event(i2c_slave *s, enum i2c_event event)
  69{
  70    SMBusDevice *dev = FROM_I2C_SLAVE(SMBusDevice, s);
  71
  72    switch (event) {
  73    case I2C_START_SEND:
  74        switch (dev->mode) {
  75        case SMBUS_IDLE:
  76            DPRINTF("Incoming data\n");
  77            dev->mode = SMBUS_WRITE_DATA;
  78            break;
  79        default:
  80            BADF("Unexpected send start condition in state %d\n", dev->mode);
  81            dev->mode = SMBUS_CONFUSED;
  82            break;
  83        }
  84        break;
  85
  86    case I2C_START_RECV:
  87        switch (dev->mode) {
  88        case SMBUS_IDLE:
  89            DPRINTF("Read mode\n");
  90            dev->mode = SMBUS_RECV_BYTE;
  91            break;
  92        case SMBUS_WRITE_DATA:
  93            if (dev->data_len == 0) {
  94                BADF("Read after write with no data\n");
  95                dev->mode = SMBUS_CONFUSED;
  96            } else {
  97                if (dev->data_len > 1) {
  98                    smbus_do_write(dev);
  99                } else {
 100                    dev->command = dev->data_buf[0];
 101                    DPRINTF("%02x: Command %d\n", dev->i2c.address,
 102                            dev->command);
 103                }
 104                DPRINTF("Read mode\n");
 105                dev->data_len = 0;
 106                dev->mode = SMBUS_READ_DATA;
 107            }
 108            break;
 109        default:
 110            BADF("Unexpected recv start condition in state %d\n", dev->mode);
 111            dev->mode = SMBUS_CONFUSED;
 112            break;
 113        }
 114        break;
 115
 116    case I2C_FINISH:
 117        switch (dev->mode) {
 118        case SMBUS_WRITE_DATA:
 119            smbus_do_write(dev);
 120            break;
 121        case SMBUS_RECV_BYTE:
 122            smbus_do_quick_cmd(dev, 1);
 123            break;
 124        case SMBUS_READ_DATA:
 125            BADF("Unexpected stop during receive\n");
 126            break;
 127        default:
 128            /* Nothing to do.  */
 129            break;
 130        }
 131        dev->mode = SMBUS_IDLE;
 132        dev->data_len = 0;
 133        break;
 134
 135    case I2C_NACK:
 136        switch (dev->mode) {
 137        case SMBUS_DONE:
 138            /* Nothing to do.  */
 139            break;
 140        case SMBUS_READ_DATA:
 141            dev->mode = SMBUS_DONE;
 142            break;
 143        default:
 144            BADF("Unexpected NACK in state %d\n", dev->mode);
 145            dev->mode = SMBUS_CONFUSED;
 146            break;
 147        }
 148    }
 149}
 150
 151static int smbus_i2c_recv(i2c_slave *s)
 152{
 153    SMBusDeviceInfo *t = container_of(s->info, SMBusDeviceInfo, i2c);
 154    SMBusDevice *dev = FROM_I2C_SLAVE(SMBusDevice, s);
 155    int ret;
 156
 157    switch (dev->mode) {
 158    case SMBUS_RECV_BYTE:
 159        if (t->receive_byte) {
 160            ret = t->receive_byte(dev);
 161        } else {
 162            ret = 0;
 163        }
 164        DPRINTF("Receive Byte %02x\n", ret);
 165        dev->mode = SMBUS_DONE;
 166        break;
 167    case SMBUS_READ_DATA:
 168        if (t->read_data) {
 169            ret = t->read_data(dev, dev->command, dev->data_len);
 170            dev->data_len++;
 171        } else {
 172            ret = 0;
 173        }
 174        DPRINTF("Read data %02x\n", ret);
 175        break;
 176    default:
 177        BADF("Unexpected read in state %d\n", dev->mode);
 178        dev->mode = SMBUS_CONFUSED;
 179        ret = 0;
 180        break;
 181    }
 182    return ret;
 183}
 184
 185static int smbus_i2c_send(i2c_slave *s, uint8_t data)
 186{
 187    SMBusDevice *dev = FROM_I2C_SLAVE(SMBusDevice, s);
 188
 189    switch (dev->mode) {
 190    case SMBUS_WRITE_DATA:
 191        DPRINTF("Write data %02x\n", data);
 192        dev->data_buf[dev->data_len++] = data;
 193        break;
 194    default:
 195        BADF("Unexpected write in state %d\n", dev->mode);
 196        break;
 197    }
 198    return 0;
 199}
 200
 201static int smbus_device_init(i2c_slave *i2c)
 202{
 203    SMBusDeviceInfo *t = container_of(i2c->info, SMBusDeviceInfo, i2c);
 204    SMBusDevice *dev = FROM_I2C_SLAVE(SMBusDevice, i2c);
 205
 206    return t->init(dev);
 207}
 208
 209void smbus_register_device(SMBusDeviceInfo *info)
 210{
 211    assert(info->i2c.qdev.size >= sizeof(SMBusDevice));
 212    info->i2c.init = smbus_device_init;
 213    info->i2c.event = smbus_i2c_event;
 214    info->i2c.recv = smbus_i2c_recv;
 215    info->i2c.send = smbus_i2c_send;
 216    i2c_register_slave(&info->i2c);
 217}
 218
 219/* Master device commands.  */
 220void smbus_quick_command(i2c_bus *bus, uint8_t addr, int read)
 221{
 222    i2c_start_transfer(bus, addr, read);
 223    i2c_end_transfer(bus);
 224}
 225
 226uint8_t smbus_receive_byte(i2c_bus *bus, uint8_t addr)
 227{
 228    uint8_t data;
 229
 230    i2c_start_transfer(bus, addr, 1);
 231    data = i2c_recv(bus);
 232    i2c_nack(bus);
 233    i2c_end_transfer(bus);
 234    return data;
 235}
 236
 237void smbus_send_byte(i2c_bus *bus, uint8_t addr, uint8_t data)
 238{
 239    i2c_start_transfer(bus, addr, 0);
 240    i2c_send(bus, data);
 241    i2c_end_transfer(bus);
 242}
 243
 244uint8_t smbus_read_byte(i2c_bus *bus, uint8_t addr, uint8_t command)
 245{
 246    uint8_t data;
 247    i2c_start_transfer(bus, addr, 0);
 248    i2c_send(bus, command);
 249    i2c_start_transfer(bus, addr, 1);
 250    data = i2c_recv(bus);
 251    i2c_nack(bus);
 252    i2c_end_transfer(bus);
 253    return data;
 254}
 255
 256void smbus_write_byte(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t data)
 257{
 258    i2c_start_transfer(bus, addr, 0);
 259    i2c_send(bus, command);
 260    i2c_send(bus, data);
 261    i2c_end_transfer(bus);
 262}
 263
 264uint16_t smbus_read_word(i2c_bus *bus, uint8_t addr, uint8_t command)
 265{
 266    uint16_t data;
 267    i2c_start_transfer(bus, addr, 0);
 268    i2c_send(bus, command);
 269    i2c_start_transfer(bus, addr, 1);
 270    data = i2c_recv(bus);
 271    data |= i2c_recv(bus) << 8;
 272    i2c_nack(bus);
 273    i2c_end_transfer(bus);
 274    return data;
 275}
 276
 277void smbus_write_word(i2c_bus *bus, uint8_t addr, uint8_t command, uint16_t data)
 278{
 279    i2c_start_transfer(bus, addr, 0);
 280    i2c_send(bus, command);
 281    i2c_send(bus, data & 0xff);
 282    i2c_send(bus, data >> 8);
 283    i2c_end_transfer(bus);
 284}
 285
 286int smbus_read_block(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t *data)
 287{
 288    int len;
 289    int i;
 290
 291    i2c_start_transfer(bus, addr, 0);
 292    i2c_send(bus, command);
 293    i2c_start_transfer(bus, addr, 1);
 294    len = i2c_recv(bus);
 295    if (len > 32)
 296        len = 0;
 297    for (i = 0; i < len; i++)
 298        data[i] = i2c_recv(bus);
 299    i2c_nack(bus);
 300    i2c_end_transfer(bus);
 301    return len;
 302}
 303
 304void smbus_write_block(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t *data,
 305                       int len)
 306{
 307    int i;
 308
 309    if (len > 32)
 310        len = 32;
 311
 312    i2c_start_transfer(bus, addr, 0);
 313    i2c_send(bus, command);
 314    i2c_send(bus, len);
 315    for (i = 0; i < len; i++)
 316        i2c_send(bus, data[i]);
 317    i2c_end_transfer(bus);
 318}
 319