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