10ff596d0Spbrook /* 20ff596d0Spbrook * QEMU SMBus device emulation. 30ff596d0Spbrook * 40ff596d0Spbrook * Copyright (c) 2007 CodeSourcery. 50ff596d0Spbrook * Written by Paul Brook 60ff596d0Spbrook * 78e31bf38SMatthew Fernandez * This code is licensed under the LGPL. 80ff596d0Spbrook */ 90ff596d0Spbrook 100ff596d0Spbrook /* TODO: Implement PEC. */ 110ff596d0Spbrook 120430891cSPeter Maydell #include "qemu/osdep.h" 1383c9f4caSPaolo Bonzini #include "hw/hw.h" 140d09e41aSPaolo Bonzini #include "hw/i2c/i2c.h" 150d09e41aSPaolo Bonzini #include "hw/i2c/smbus.h" 160ff596d0Spbrook 170ff596d0Spbrook //#define DEBUG_SMBUS 1 180ff596d0Spbrook 190ff596d0Spbrook #ifdef DEBUG_SMBUS 20001faf32SBlue Swirl #define DPRINTF(fmt, ...) \ 21001faf32SBlue Swirl do { printf("smbus(%02x): " fmt , dev->i2c.address, ## __VA_ARGS__); } while (0) 22001faf32SBlue Swirl #define BADF(fmt, ...) \ 23001faf32SBlue Swirl do { fprintf(stderr, "smbus: error: " fmt , ## __VA_ARGS__); exit(1);} while (0) 240ff596d0Spbrook #else 25001faf32SBlue Swirl #define DPRINTF(fmt, ...) do {} while(0) 26001faf32SBlue Swirl #define BADF(fmt, ...) \ 27001faf32SBlue Swirl do { fprintf(stderr, "smbus: error: " fmt , ## __VA_ARGS__);} while (0) 280ff596d0Spbrook #endif 290ff596d0Spbrook 300ff596d0Spbrook enum { 310ff596d0Spbrook SMBUS_IDLE, 320ff596d0Spbrook SMBUS_WRITE_DATA, 330ff596d0Spbrook SMBUS_RECV_BYTE, 340ff596d0Spbrook SMBUS_READ_DATA, 350ff596d0Spbrook SMBUS_DONE, 360ff596d0Spbrook SMBUS_CONFUSED = -1 370ff596d0Spbrook }; 380ff596d0Spbrook 390ff596d0Spbrook static void smbus_do_quick_cmd(SMBusDevice *dev, int recv) 400ff596d0Spbrook { 41b5ea9327SAnthony Liguori SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev); 421ea96673SPaul Brook 430ff596d0Spbrook DPRINTF("Quick Command %d\n", recv); 44b5ea9327SAnthony Liguori if (sc->quick_cmd) { 45b5ea9327SAnthony Liguori sc->quick_cmd(dev, recv); 46b5ea9327SAnthony Liguori } 470ff596d0Spbrook } 480ff596d0Spbrook 490ff596d0Spbrook static void smbus_do_write(SMBusDevice *dev) 500ff596d0Spbrook { 51b5ea9327SAnthony Liguori SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev); 521ea96673SPaul Brook 530ff596d0Spbrook if (dev->data_len == 0) { 540ff596d0Spbrook smbus_do_quick_cmd(dev, 0); 550ff596d0Spbrook } else if (dev->data_len == 1) { 560ff596d0Spbrook DPRINTF("Send Byte\n"); 57b5ea9327SAnthony Liguori if (sc->send_byte) { 58b5ea9327SAnthony Liguori sc->send_byte(dev, dev->data_buf[0]); 590ff596d0Spbrook } 600ff596d0Spbrook } else { 610ff596d0Spbrook dev->command = dev->data_buf[0]; 620ff596d0Spbrook DPRINTF("Command %d len %d\n", dev->command, dev->data_len - 1); 63b5ea9327SAnthony Liguori if (sc->write_data) { 64b5ea9327SAnthony Liguori sc->write_data(dev, dev->command, dev->data_buf + 1, 650ff596d0Spbrook dev->data_len - 1); 660ff596d0Spbrook } 670ff596d0Spbrook } 680ff596d0Spbrook } 690ff596d0Spbrook 70d307c28cSCorey Minyard static int smbus_i2c_event(I2CSlave *s, enum i2c_event event) 710ff596d0Spbrook { 72b5ea9327SAnthony Liguori SMBusDevice *dev = SMBUS_DEVICE(s); 731ea96673SPaul Brook 740ff596d0Spbrook switch (event) { 750ff596d0Spbrook case I2C_START_SEND: 760ff596d0Spbrook switch (dev->mode) { 770ff596d0Spbrook case SMBUS_IDLE: 780ff596d0Spbrook DPRINTF("Incoming data\n"); 790ff596d0Spbrook dev->mode = SMBUS_WRITE_DATA; 800ff596d0Spbrook break; 810ff596d0Spbrook default: 820ff596d0Spbrook BADF("Unexpected send start condition in state %d\n", dev->mode); 830ff596d0Spbrook dev->mode = SMBUS_CONFUSED; 840ff596d0Spbrook break; 850ff596d0Spbrook } 860ff596d0Spbrook break; 870ff596d0Spbrook 880ff596d0Spbrook case I2C_START_RECV: 890ff596d0Spbrook switch (dev->mode) { 900ff596d0Spbrook case SMBUS_IDLE: 910ff596d0Spbrook DPRINTF("Read mode\n"); 920ff596d0Spbrook dev->mode = SMBUS_RECV_BYTE; 930ff596d0Spbrook break; 940ff596d0Spbrook case SMBUS_WRITE_DATA: 950ff596d0Spbrook if (dev->data_len == 0) { 960ff596d0Spbrook BADF("Read after write with no data\n"); 970ff596d0Spbrook dev->mode = SMBUS_CONFUSED; 980ff596d0Spbrook } else { 990ff596d0Spbrook if (dev->data_len > 1) { 1000ff596d0Spbrook smbus_do_write(dev); 1010ff596d0Spbrook } else { 1020ff596d0Spbrook dev->command = dev->data_buf[0]; 1030ff596d0Spbrook DPRINTF("%02x: Command %d\n", dev->i2c.address, 1040ff596d0Spbrook dev->command); 1050ff596d0Spbrook } 1060ff596d0Spbrook DPRINTF("Read mode\n"); 1070ff596d0Spbrook dev->data_len = 0; 1080ff596d0Spbrook dev->mode = SMBUS_READ_DATA; 1090ff596d0Spbrook } 1100ff596d0Spbrook break; 1110ff596d0Spbrook default: 1120ff596d0Spbrook BADF("Unexpected recv start condition in state %d\n", dev->mode); 1130ff596d0Spbrook dev->mode = SMBUS_CONFUSED; 1140ff596d0Spbrook break; 1150ff596d0Spbrook } 1160ff596d0Spbrook break; 1170ff596d0Spbrook 1180ff596d0Spbrook case I2C_FINISH: 1190ff596d0Spbrook switch (dev->mode) { 1200ff596d0Spbrook case SMBUS_WRITE_DATA: 1210ff596d0Spbrook smbus_do_write(dev); 1220ff596d0Spbrook break; 1230ff596d0Spbrook case SMBUS_RECV_BYTE: 1240ff596d0Spbrook smbus_do_quick_cmd(dev, 1); 1250ff596d0Spbrook break; 1260ff596d0Spbrook case SMBUS_READ_DATA: 1270ff596d0Spbrook BADF("Unexpected stop during receive\n"); 1280ff596d0Spbrook break; 1290ff596d0Spbrook default: 1300ff596d0Spbrook /* Nothing to do. */ 1310ff596d0Spbrook break; 1320ff596d0Spbrook } 1330ff596d0Spbrook dev->mode = SMBUS_IDLE; 1340ff596d0Spbrook dev->data_len = 0; 1350ff596d0Spbrook break; 1360ff596d0Spbrook 1370ff596d0Spbrook case I2C_NACK: 1380ff596d0Spbrook switch (dev->mode) { 1390ff596d0Spbrook case SMBUS_DONE: 1400ff596d0Spbrook /* Nothing to do. */ 1410ff596d0Spbrook break; 1420ff596d0Spbrook case SMBUS_READ_DATA: 1430ff596d0Spbrook dev->mode = SMBUS_DONE; 1440ff596d0Spbrook break; 1450ff596d0Spbrook default: 1460ff596d0Spbrook BADF("Unexpected NACK in state %d\n", dev->mode); 1470ff596d0Spbrook dev->mode = SMBUS_CONFUSED; 1480ff596d0Spbrook break; 1490ff596d0Spbrook } 1500ff596d0Spbrook } 151d307c28cSCorey Minyard 152d307c28cSCorey Minyard return 0; 1530ff596d0Spbrook } 1540ff596d0Spbrook 1559e07bdf8SAnthony Liguori static int smbus_i2c_recv(I2CSlave *s) 1560ff596d0Spbrook { 157b5ea9327SAnthony Liguori SMBusDevice *dev = SMBUS_DEVICE(s); 158b5ea9327SAnthony Liguori SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev); 1590ff596d0Spbrook int ret; 1600ff596d0Spbrook 1610ff596d0Spbrook switch (dev->mode) { 1620ff596d0Spbrook case SMBUS_RECV_BYTE: 163b5ea9327SAnthony Liguori if (sc->receive_byte) { 164b5ea9327SAnthony Liguori ret = sc->receive_byte(dev); 1650ff596d0Spbrook } else { 1660ff596d0Spbrook ret = 0; 1670ff596d0Spbrook } 1680ff596d0Spbrook DPRINTF("Receive Byte %02x\n", ret); 1690ff596d0Spbrook dev->mode = SMBUS_DONE; 1700ff596d0Spbrook break; 1710ff596d0Spbrook case SMBUS_READ_DATA: 172b5ea9327SAnthony Liguori if (sc->read_data) { 173b5ea9327SAnthony Liguori ret = sc->read_data(dev, dev->command, dev->data_len); 1740ff596d0Spbrook dev->data_len++; 1750ff596d0Spbrook } else { 1760ff596d0Spbrook ret = 0; 1770ff596d0Spbrook } 1780ff596d0Spbrook DPRINTF("Read data %02x\n", ret); 1790ff596d0Spbrook break; 1800ff596d0Spbrook default: 1810ff596d0Spbrook BADF("Unexpected read in state %d\n", dev->mode); 1820ff596d0Spbrook dev->mode = SMBUS_CONFUSED; 1830ff596d0Spbrook ret = 0; 1840ff596d0Spbrook break; 1850ff596d0Spbrook } 1860ff596d0Spbrook return ret; 1870ff596d0Spbrook } 1880ff596d0Spbrook 1899e07bdf8SAnthony Liguori static int smbus_i2c_send(I2CSlave *s, uint8_t data) 1900ff596d0Spbrook { 191b5ea9327SAnthony Liguori SMBusDevice *dev = SMBUS_DEVICE(s); 1921ea96673SPaul Brook 1930ff596d0Spbrook switch (dev->mode) { 1940ff596d0Spbrook case SMBUS_WRITE_DATA: 1950ff596d0Spbrook DPRINTF("Write data %02x\n", data); 196*629457a1SCorey Minyard if (dev->data_len >= sizeof(dev->data_buf)) { 197*629457a1SCorey Minyard BADF("Too many bytes sent\n"); 198*629457a1SCorey Minyard } else { 1990ff596d0Spbrook dev->data_buf[dev->data_len++] = data; 200*629457a1SCorey Minyard } 2010ff596d0Spbrook break; 2020ff596d0Spbrook default: 2030ff596d0Spbrook BADF("Unexpected write in state %d\n", dev->mode); 2040ff596d0Spbrook break; 2050ff596d0Spbrook } 2060ff596d0Spbrook return 0; 2070ff596d0Spbrook } 2080ff596d0Spbrook 2090ff596d0Spbrook /* Master device commands. */ 210046a1844SPaolo Bonzini int smbus_quick_command(I2CBus *bus, uint8_t addr, int read) 2110ff596d0Spbrook { 212046a1844SPaolo Bonzini if (i2c_start_transfer(bus, addr, read)) { 213046a1844SPaolo Bonzini return -1; 214046a1844SPaolo Bonzini } 2150ff596d0Spbrook i2c_end_transfer(bus); 216046a1844SPaolo Bonzini return 0; 2170ff596d0Spbrook } 2180ff596d0Spbrook 219285364e9SPaolo Bonzini int smbus_receive_byte(I2CBus *bus, uint8_t addr) 2200ff596d0Spbrook { 2210ff596d0Spbrook uint8_t data; 2220ff596d0Spbrook 223046a1844SPaolo Bonzini if (i2c_start_transfer(bus, addr, 1)) { 224046a1844SPaolo Bonzini return -1; 225046a1844SPaolo Bonzini } 2260ff596d0Spbrook data = i2c_recv(bus); 2270ff596d0Spbrook i2c_nack(bus); 2280ff596d0Spbrook i2c_end_transfer(bus); 2290ff596d0Spbrook return data; 2300ff596d0Spbrook } 2310ff596d0Spbrook 232046a1844SPaolo Bonzini int smbus_send_byte(I2CBus *bus, uint8_t addr, uint8_t data) 2330ff596d0Spbrook { 234046a1844SPaolo Bonzini if (i2c_start_transfer(bus, addr, 0)) { 235046a1844SPaolo Bonzini return -1; 236046a1844SPaolo Bonzini } 2370ff596d0Spbrook i2c_send(bus, data); 2380ff596d0Spbrook i2c_end_transfer(bus); 239046a1844SPaolo Bonzini return 0; 2400ff596d0Spbrook } 2410ff596d0Spbrook 242285364e9SPaolo Bonzini int smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command) 2430ff596d0Spbrook { 2440ff596d0Spbrook uint8_t data; 245046a1844SPaolo Bonzini if (i2c_start_transfer(bus, addr, 0)) { 246046a1844SPaolo Bonzini return -1; 247046a1844SPaolo Bonzini } 2480ff596d0Spbrook i2c_send(bus, command); 249cc083d8aSCorey Minyard if (i2c_start_transfer(bus, addr, 1)) { 250d307c28cSCorey Minyard i2c_end_transfer(bus); 251d307c28cSCorey Minyard return -1; 252cc083d8aSCorey Minyard } 2530ff596d0Spbrook data = i2c_recv(bus); 2540ff596d0Spbrook i2c_nack(bus); 2550ff596d0Spbrook i2c_end_transfer(bus); 2560ff596d0Spbrook return data; 2570ff596d0Spbrook } 2580ff596d0Spbrook 259046a1844SPaolo Bonzini int smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data) 2600ff596d0Spbrook { 261046a1844SPaolo Bonzini if (i2c_start_transfer(bus, addr, 0)) { 262046a1844SPaolo Bonzini return -1; 263046a1844SPaolo Bonzini } 2640ff596d0Spbrook i2c_send(bus, command); 2650ff596d0Spbrook i2c_send(bus, data); 2660ff596d0Spbrook i2c_end_transfer(bus); 267046a1844SPaolo Bonzini return 0; 2680ff596d0Spbrook } 2690ff596d0Spbrook 270285364e9SPaolo Bonzini int smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command) 2710ff596d0Spbrook { 2720ff596d0Spbrook uint16_t data; 273046a1844SPaolo Bonzini if (i2c_start_transfer(bus, addr, 0)) { 274046a1844SPaolo Bonzini return -1; 275046a1844SPaolo Bonzini } 2760ff596d0Spbrook i2c_send(bus, command); 277cc083d8aSCorey Minyard if (i2c_start_transfer(bus, addr, 1)) { 278d307c28cSCorey Minyard i2c_end_transfer(bus); 279d307c28cSCorey Minyard return -1; 280cc083d8aSCorey Minyard } 2810ff596d0Spbrook data = i2c_recv(bus); 2820ff596d0Spbrook data |= i2c_recv(bus) << 8; 2830ff596d0Spbrook i2c_nack(bus); 2840ff596d0Spbrook i2c_end_transfer(bus); 2850ff596d0Spbrook return data; 2860ff596d0Spbrook } 2870ff596d0Spbrook 288046a1844SPaolo Bonzini int smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data) 2890ff596d0Spbrook { 290046a1844SPaolo Bonzini if (i2c_start_transfer(bus, addr, 0)) { 291046a1844SPaolo Bonzini return -1; 292046a1844SPaolo Bonzini } 2930ff596d0Spbrook i2c_send(bus, command); 2940ff596d0Spbrook i2c_send(bus, data & 0xff); 2950ff596d0Spbrook i2c_send(bus, data >> 8); 2960ff596d0Spbrook i2c_end_transfer(bus); 297046a1844SPaolo Bonzini return 0; 2980ff596d0Spbrook } 2990ff596d0Spbrook 3004b615be5SCorey Minyard int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data, 3014b615be5SCorey Minyard int len, bool recv_len, bool send_cmd) 3020ff596d0Spbrook { 3034b615be5SCorey Minyard int rlen; 3040ff596d0Spbrook int i; 3050ff596d0Spbrook 3064b615be5SCorey Minyard if (send_cmd) { 307046a1844SPaolo Bonzini if (i2c_start_transfer(bus, addr, 0)) { 308046a1844SPaolo Bonzini return -1; 309046a1844SPaolo Bonzini } 3100ff596d0Spbrook i2c_send(bus, command); 3114b615be5SCorey Minyard } 312cc083d8aSCorey Minyard if (i2c_start_transfer(bus, addr, 1)) { 3134b615be5SCorey Minyard if (send_cmd) { 314d307c28cSCorey Minyard i2c_end_transfer(bus); 3154b615be5SCorey Minyard } 316d307c28cSCorey Minyard return -1; 317cc083d8aSCorey Minyard } 3184b615be5SCorey Minyard if (recv_len) { 3194b615be5SCorey Minyard rlen = i2c_recv(bus); 3204b615be5SCorey Minyard } else { 3214b615be5SCorey Minyard rlen = len; 322046a1844SPaolo Bonzini } 3234b615be5SCorey Minyard if (rlen > len) { 3244b615be5SCorey Minyard rlen = 0; 3254b615be5SCorey Minyard } 3264b615be5SCorey Minyard for (i = 0; i < rlen; i++) { 3270ff596d0Spbrook data[i] = i2c_recv(bus); 328046a1844SPaolo Bonzini } 3290ff596d0Spbrook i2c_nack(bus); 3300ff596d0Spbrook i2c_end_transfer(bus); 3314b615be5SCorey Minyard return rlen; 3320ff596d0Spbrook } 3330ff596d0Spbrook 334046a1844SPaolo Bonzini int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data, 3354b615be5SCorey Minyard int len, bool send_len) 3360ff596d0Spbrook { 3370ff596d0Spbrook int i; 3380ff596d0Spbrook 3390ff596d0Spbrook if (len > 32) 3400ff596d0Spbrook len = 32; 3410ff596d0Spbrook 342046a1844SPaolo Bonzini if (i2c_start_transfer(bus, addr, 0)) { 343046a1844SPaolo Bonzini return -1; 344046a1844SPaolo Bonzini } 3450ff596d0Spbrook i2c_send(bus, command); 3464b615be5SCorey Minyard if (send_len) { 3470ff596d0Spbrook i2c_send(bus, len); 3484b615be5SCorey Minyard } 349046a1844SPaolo Bonzini for (i = 0; i < len; i++) { 3500ff596d0Spbrook i2c_send(bus, data[i]); 351046a1844SPaolo Bonzini } 3520ff596d0Spbrook i2c_end_transfer(bus); 353046a1844SPaolo Bonzini return 0; 3540ff596d0Spbrook } 355b5ea9327SAnthony Liguori 356b5ea9327SAnthony Liguori static void smbus_device_class_init(ObjectClass *klass, void *data) 357b5ea9327SAnthony Liguori { 358b5ea9327SAnthony Liguori I2CSlaveClass *sc = I2C_SLAVE_CLASS(klass); 359b5ea9327SAnthony Liguori 360b5ea9327SAnthony Liguori sc->event = smbus_i2c_event; 361b5ea9327SAnthony Liguori sc->recv = smbus_i2c_recv; 362b5ea9327SAnthony Liguori sc->send = smbus_i2c_send; 363b5ea9327SAnthony Liguori } 364b5ea9327SAnthony Liguori 3658c43a6f0SAndreas Färber static const TypeInfo smbus_device_type_info = { 366b5ea9327SAnthony Liguori .name = TYPE_SMBUS_DEVICE, 367b5ea9327SAnthony Liguori .parent = TYPE_I2C_SLAVE, 368b5ea9327SAnthony Liguori .instance_size = sizeof(SMBusDevice), 369b5ea9327SAnthony Liguori .abstract = true, 370b5ea9327SAnthony Liguori .class_size = sizeof(SMBusDeviceClass), 371b5ea9327SAnthony Liguori .class_init = smbus_device_class_init, 372b5ea9327SAnthony Liguori }; 373b5ea9327SAnthony Liguori 37483f7d43aSAndreas Färber static void smbus_device_register_types(void) 375b5ea9327SAnthony Liguori { 376b5ea9327SAnthony Liguori type_register_static(&smbus_device_type_info); 377b5ea9327SAnthony Liguori } 378b5ea9327SAnthony Liguori 37983f7d43aSAndreas Färber type_init(smbus_device_register_types) 380