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