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_RECV_BYTE, 38 SMBUS_READ_DATA, 39 SMBUS_DONE, 40 SMBUS_CONFUSED = -1 41 }; 42 43 static void smbus_do_quick_cmd(SMBusDevice *dev, int recv) 44 { 45 SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev); 46 47 DPRINTF("Quick Command %d\n", recv); 48 if (sc->quick_cmd) { 49 sc->quick_cmd(dev, recv); 50 } 51 } 52 53 static void smbus_do_write(SMBusDevice *dev) 54 { 55 SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev); 56 57 if (dev->data_len == 0) { 58 smbus_do_quick_cmd(dev, 0); 59 } else if (dev->data_len == 1) { 60 DPRINTF("Send Byte\n"); 61 if (sc->send_byte) { 62 sc->send_byte(dev, dev->data_buf[0]); 63 } 64 } else { 65 dev->command = dev->data_buf[0]; 66 DPRINTF("Command %d len %d\n", dev->command, dev->data_len - 1); 67 if (sc->write_data) { 68 sc->write_data(dev, dev->command, dev->data_buf + 1, 69 dev->data_len - 1); 70 } 71 } 72 } 73 74 static int smbus_i2c_event(I2CSlave *s, enum i2c_event event) 75 { 76 SMBusDevice *dev = SMBUS_DEVICE(s); 77 78 switch (event) { 79 case I2C_START_SEND: 80 switch (dev->mode) { 81 case SMBUS_IDLE: 82 DPRINTF("Incoming data\n"); 83 dev->mode = SMBUS_WRITE_DATA; 84 break; 85 default: 86 BADF("Unexpected send start condition in state %d\n", dev->mode); 87 dev->mode = SMBUS_CONFUSED; 88 break; 89 } 90 break; 91 92 case I2C_START_RECV: 93 switch (dev->mode) { 94 case SMBUS_IDLE: 95 DPRINTF("Read mode\n"); 96 dev->mode = SMBUS_RECV_BYTE; 97 break; 98 case SMBUS_WRITE_DATA: 99 if (dev->data_len == 0) { 100 BADF("Read after write with no data\n"); 101 dev->mode = SMBUS_CONFUSED; 102 } else { 103 if (dev->data_len > 1) { 104 smbus_do_write(dev); 105 } else { 106 dev->command = dev->data_buf[0]; 107 DPRINTF("%02x: Command %d\n", dev->i2c.address, 108 dev->command); 109 } 110 DPRINTF("Read mode\n"); 111 dev->data_len = 0; 112 dev->mode = SMBUS_READ_DATA; 113 } 114 break; 115 default: 116 BADF("Unexpected recv start condition in state %d\n", dev->mode); 117 dev->mode = SMBUS_CONFUSED; 118 break; 119 } 120 break; 121 122 case I2C_FINISH: 123 switch (dev->mode) { 124 case SMBUS_WRITE_DATA: 125 smbus_do_write(dev); 126 break; 127 case SMBUS_RECV_BYTE: 128 smbus_do_quick_cmd(dev, 1); 129 break; 130 case SMBUS_READ_DATA: 131 BADF("Unexpected stop during receive\n"); 132 break; 133 default: 134 /* Nothing to do. */ 135 break; 136 } 137 dev->mode = SMBUS_IDLE; 138 dev->data_len = 0; 139 break; 140 141 case I2C_NACK: 142 switch (dev->mode) { 143 case SMBUS_DONE: 144 /* Nothing to do. */ 145 break; 146 case SMBUS_READ_DATA: 147 dev->mode = SMBUS_DONE; 148 break; 149 default: 150 BADF("Unexpected NACK in state %d\n", dev->mode); 151 dev->mode = SMBUS_CONFUSED; 152 break; 153 } 154 } 155 156 return 0; 157 } 158 159 static int smbus_i2c_recv(I2CSlave *s) 160 { 161 SMBusDevice *dev = SMBUS_DEVICE(s); 162 SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev); 163 int ret; 164 165 switch (dev->mode) { 166 case SMBUS_RECV_BYTE: 167 if (sc->receive_byte) { 168 ret = sc->receive_byte(dev); 169 } else { 170 ret = 0; 171 } 172 DPRINTF("Receive Byte %02x\n", ret); 173 dev->mode = SMBUS_DONE; 174 break; 175 case SMBUS_READ_DATA: 176 if (sc->read_data) { 177 ret = sc->read_data(dev, dev->command, dev->data_len); 178 dev->data_len++; 179 } else { 180 ret = 0; 181 } 182 DPRINTF("Read data %02x\n", ret); 183 break; 184 default: 185 BADF("Unexpected read in state %d\n", dev->mode); 186 dev->mode = SMBUS_CONFUSED; 187 ret = 0; 188 break; 189 } 190 return ret; 191 } 192 193 static int smbus_i2c_send(I2CSlave *s, uint8_t data) 194 { 195 SMBusDevice *dev = SMBUS_DEVICE(s); 196 197 switch (dev->mode) { 198 case SMBUS_WRITE_DATA: 199 DPRINTF("Write data %02x\n", data); 200 if (dev->data_len >= sizeof(dev->data_buf)) { 201 BADF("Too many bytes sent\n"); 202 } else { 203 dev->data_buf[dev->data_len++] = data; 204 } 205 break; 206 default: 207 BADF("Unexpected write in state %d\n", dev->mode); 208 break; 209 } 210 return 0; 211 } 212 213 static void smbus_device_class_init(ObjectClass *klass, void *data) 214 { 215 I2CSlaveClass *sc = I2C_SLAVE_CLASS(klass); 216 217 sc->event = smbus_i2c_event; 218 sc->recv = smbus_i2c_recv; 219 sc->send = smbus_i2c_send; 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