1 /* 2 * QEMU SMBus device emulation. 3 * 4 * This code is a helper for SMBus device emulation. It implements an 5 * I2C device inteface and runs the SMBus protocol from the device 6 * point of view and maps those to simple calls to emulate. 7 * 8 * Copyright (c) 2007 CodeSourcery. 9 * Written by Paul Brook 10 * 11 * This code is licensed under the LGPL. 12 */ 13 14 /* TODO: Implement PEC. */ 15 16 #include "qemu/osdep.h" 17 #include "hw/hw.h" 18 #include "hw/i2c/i2c.h" 19 #include "hw/i2c/smbus_slave.h" 20 21 //#define DEBUG_SMBUS 1 22 23 #ifdef DEBUG_SMBUS 24 #define DPRINTF(fmt, ...) \ 25 do { printf("smbus(%02x): " fmt , dev->i2c.address, ## __VA_ARGS__); } while (0) 26 #define BADF(fmt, ...) \ 27 do { fprintf(stderr, "smbus: error: " fmt , ## __VA_ARGS__); exit(1);} while (0) 28 #else 29 #define DPRINTF(fmt, ...) do {} while(0) 30 #define BADF(fmt, ...) \ 31 do { fprintf(stderr, "smbus: error: " fmt , ## __VA_ARGS__);} while (0) 32 #endif 33 34 enum { 35 SMBUS_IDLE, 36 SMBUS_WRITE_DATA, 37 SMBUS_READ_DATA, 38 SMBUS_DONE, 39 SMBUS_CONFUSED = -1 40 }; 41 42 static void smbus_do_quick_cmd(SMBusDevice *dev, int recv) 43 { 44 SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev); 45 46 DPRINTF("Quick Command %d\n", recv); 47 if (sc->quick_cmd) { 48 sc->quick_cmd(dev, recv); 49 } 50 } 51 52 static void smbus_do_write(SMBusDevice *dev) 53 { 54 SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev); 55 56 DPRINTF("Command %d len %d\n", dev->data_buf[0], dev->data_len); 57 if (sc->write_data) { 58 sc->write_data(dev, dev->data_buf, dev->data_len); 59 } 60 } 61 62 static int smbus_i2c_event(I2CSlave *s, enum i2c_event event) 63 { 64 SMBusDevice *dev = SMBUS_DEVICE(s); 65 66 switch (event) { 67 case I2C_START_SEND: 68 switch (dev->mode) { 69 case SMBUS_IDLE: 70 DPRINTF("Incoming data\n"); 71 dev->mode = SMBUS_WRITE_DATA; 72 break; 73 74 default: 75 BADF("Unexpected send start condition in state %d\n", dev->mode); 76 dev->mode = SMBUS_CONFUSED; 77 break; 78 } 79 break; 80 81 case I2C_START_RECV: 82 switch (dev->mode) { 83 case SMBUS_IDLE: 84 DPRINTF("Read mode\n"); 85 dev->mode = SMBUS_READ_DATA; 86 break; 87 88 case SMBUS_WRITE_DATA: 89 if (dev->data_len == 0) { 90 BADF("Read after write with no data\n"); 91 dev->mode = SMBUS_CONFUSED; 92 } else { 93 smbus_do_write(dev); 94 DPRINTF("Read mode\n"); 95 dev->mode = SMBUS_READ_DATA; 96 } 97 break; 98 99 default: 100 BADF("Unexpected recv start condition in state %d\n", dev->mode); 101 dev->mode = SMBUS_CONFUSED; 102 break; 103 } 104 break; 105 106 case I2C_FINISH: 107 if (dev->data_len == 0) { 108 if (dev->mode == SMBUS_WRITE_DATA || dev->mode == SMBUS_READ_DATA) { 109 smbus_do_quick_cmd(dev, dev->mode == SMBUS_READ_DATA); 110 } 111 } else { 112 switch (dev->mode) { 113 case SMBUS_WRITE_DATA: 114 smbus_do_write(dev); 115 break; 116 117 case SMBUS_READ_DATA: 118 BADF("Unexpected stop during receive\n"); 119 break; 120 121 default: 122 /* Nothing to do. */ 123 break; 124 } 125 } 126 dev->mode = SMBUS_IDLE; 127 dev->data_len = 0; 128 break; 129 130 case I2C_NACK: 131 switch (dev->mode) { 132 case SMBUS_DONE: 133 /* Nothing to do. */ 134 break; 135 136 case SMBUS_READ_DATA: 137 dev->mode = SMBUS_DONE; 138 break; 139 140 default: 141 BADF("Unexpected NACK in state %d\n", dev->mode); 142 dev->mode = SMBUS_CONFUSED; 143 break; 144 } 145 } 146 147 return 0; 148 } 149 150 static uint8_t smbus_i2c_recv(I2CSlave *s) 151 { 152 SMBusDevice *dev = SMBUS_DEVICE(s); 153 SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev); 154 uint8_t ret = 0xff; 155 156 switch (dev->mode) { 157 case SMBUS_READ_DATA: 158 if (sc->receive_byte) { 159 ret = sc->receive_byte(dev); 160 } 161 DPRINTF("Read data %02x\n", ret); 162 break; 163 164 default: 165 BADF("Unexpected read in state %d\n", dev->mode); 166 dev->mode = SMBUS_CONFUSED; 167 break; 168 } 169 170 return ret; 171 } 172 173 static int smbus_i2c_send(I2CSlave *s, uint8_t data) 174 { 175 SMBusDevice *dev = SMBUS_DEVICE(s); 176 177 switch (dev->mode) { 178 case SMBUS_WRITE_DATA: 179 DPRINTF("Write data %02x\n", data); 180 if (dev->data_len >= sizeof(dev->data_buf)) { 181 BADF("Too many bytes sent\n"); 182 } else { 183 dev->data_buf[dev->data_len++] = data; 184 } 185 break; 186 187 default: 188 BADF("Unexpected write in state %d\n", dev->mode); 189 break; 190 } 191 192 return 0; 193 } 194 195 static void smbus_device_class_init(ObjectClass *klass, void *data) 196 { 197 I2CSlaveClass *sc = I2C_SLAVE_CLASS(klass); 198 199 sc->event = smbus_i2c_event; 200 sc->recv = smbus_i2c_recv; 201 sc->send = smbus_i2c_send; 202 } 203 204 bool smbus_vmstate_needed(SMBusDevice *dev) 205 { 206 return dev->mode != SMBUS_IDLE; 207 } 208 209 const VMStateDescription vmstate_smbus_device = { 210 .name = TYPE_SMBUS_DEVICE, 211 .version_id = 1, 212 .minimum_version_id = 1, 213 .fields = (VMStateField[]) { 214 VMSTATE_I2C_SLAVE(i2c, SMBusDevice), 215 VMSTATE_INT32(mode, SMBusDevice), 216 VMSTATE_INT32(data_len, SMBusDevice), 217 VMSTATE_UINT8_ARRAY(data_buf, SMBusDevice, SMBUS_DATA_MAX_LEN), 218 VMSTATE_END_OF_LIST() 219 } 220 }; 221 222 static const TypeInfo smbus_device_type_info = { 223 .name = TYPE_SMBUS_DEVICE, 224 .parent = TYPE_I2C_SLAVE, 225 .instance_size = sizeof(SMBusDevice), 226 .abstract = true, 227 .class_size = sizeof(SMBusDeviceClass), 228 .class_init = smbus_device_class_init, 229 }; 230 231 static void smbus_device_register_types(void) 232 { 233 type_register_static(&smbus_device_type_info); 234 } 235 236 type_init(smbus_device_register_types) 237