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