]> Git Repo - qemu.git/blob - hw/i2c/smbus.c
hw/misc/ivshmem: Remove deprecated "ivshmem" legacy device
[qemu.git] / hw / i2c / smbus.c
1 /*
2  * QEMU SMBus device emulation.
3  *
4  * Copyright (c) 2007 CodeSourcery.
5  * Written by Paul Brook
6  *
7  * This code is licensed under the LGPL.
8  */
9
10 /* TODO: Implement PEC.  */
11
12 #include "qemu/osdep.h"
13 #include "hw/hw.h"
14 #include "hw/i2c/i2c.h"
15 #include "hw/i2c/smbus.h"
16
17 //#define DEBUG_SMBUS 1
18
19 #ifdef DEBUG_SMBUS
20 #define DPRINTF(fmt, ...) \
21 do { printf("smbus(%02x): " fmt , dev->i2c.address, ## __VA_ARGS__); } while (0)
22 #define BADF(fmt, ...) \
23 do { fprintf(stderr, "smbus: error: " fmt , ## __VA_ARGS__); exit(1);} while (0)
24 #else
25 #define DPRINTF(fmt, ...) do {} while(0)
26 #define BADF(fmt, ...) \
27 do { fprintf(stderr, "smbus: error: " fmt , ## __VA_ARGS__);} while (0)
28 #endif
29
30 enum {
31     SMBUS_IDLE,
32     SMBUS_WRITE_DATA,
33     SMBUS_RECV_BYTE,
34     SMBUS_READ_DATA,
35     SMBUS_DONE,
36     SMBUS_CONFUSED = -1
37 };
38
39 static void smbus_do_quick_cmd(SMBusDevice *dev, int recv)
40 {
41     SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
42
43     DPRINTF("Quick Command %d\n", recv);
44     if (sc->quick_cmd) {
45         sc->quick_cmd(dev, recv);
46     }
47 }
48
49 static void smbus_do_write(SMBusDevice *dev)
50 {
51     SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
52
53     if (dev->data_len == 0) {
54         smbus_do_quick_cmd(dev, 0);
55     } else if (dev->data_len == 1) {
56         DPRINTF("Send Byte\n");
57         if (sc->send_byte) {
58             sc->send_byte(dev, dev->data_buf[0]);
59         }
60     } else {
61         dev->command = dev->data_buf[0];
62         DPRINTF("Command %d len %d\n", dev->command, dev->data_len - 1);
63         if (sc->write_data) {
64             sc->write_data(dev, dev->command, dev->data_buf + 1,
65                            dev->data_len - 1);
66         }
67     }
68 }
69
70 static int smbus_i2c_event(I2CSlave *s, enum i2c_event event)
71 {
72     SMBusDevice *dev = SMBUS_DEVICE(s);
73
74     switch (event) {
75     case I2C_START_SEND:
76         switch (dev->mode) {
77         case SMBUS_IDLE:
78             DPRINTF("Incoming data\n");
79             dev->mode = SMBUS_WRITE_DATA;
80             break;
81         default:
82             BADF("Unexpected send start condition in state %d\n", dev->mode);
83             dev->mode = SMBUS_CONFUSED;
84             break;
85         }
86         break;
87
88     case I2C_START_RECV:
89         switch (dev->mode) {
90         case SMBUS_IDLE:
91             DPRINTF("Read mode\n");
92             dev->mode = SMBUS_RECV_BYTE;
93             break;
94         case SMBUS_WRITE_DATA:
95             if (dev->data_len == 0) {
96                 BADF("Read after write with no data\n");
97                 dev->mode = SMBUS_CONFUSED;
98             } else {
99                 if (dev->data_len > 1) {
100                     smbus_do_write(dev);
101                 } else {
102                     dev->command = dev->data_buf[0];
103                     DPRINTF("%02x: Command %d\n", dev->i2c.address,
104                             dev->command);
105                 }
106                 DPRINTF("Read mode\n");
107                 dev->data_len = 0;
108                 dev->mode = SMBUS_READ_DATA;
109             }
110             break;
111         default:
112             BADF("Unexpected recv start condition in state %d\n", dev->mode);
113             dev->mode = SMBUS_CONFUSED;
114             break;
115         }
116         break;
117
118     case I2C_FINISH:
119         switch (dev->mode) {
120         case SMBUS_WRITE_DATA:
121             smbus_do_write(dev);
122             break;
123         case SMBUS_RECV_BYTE:
124             smbus_do_quick_cmd(dev, 1);
125             break;
126         case SMBUS_READ_DATA:
127             BADF("Unexpected stop during receive\n");
128             break;
129         default:
130             /* Nothing to do.  */
131             break;
132         }
133         dev->mode = SMBUS_IDLE;
134         dev->data_len = 0;
135         break;
136
137     case I2C_NACK:
138         switch (dev->mode) {
139         case SMBUS_DONE:
140             /* Nothing to do.  */
141             break;
142         case SMBUS_READ_DATA:
143             dev->mode = SMBUS_DONE;
144             break;
145         default:
146             BADF("Unexpected NACK in state %d\n", dev->mode);
147             dev->mode = SMBUS_CONFUSED;
148             break;
149         }
150     }
151
152     return 0;
153 }
154
155 static int smbus_i2c_recv(I2CSlave *s)
156 {
157     SMBusDevice *dev = SMBUS_DEVICE(s);
158     SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
159     int ret;
160
161     switch (dev->mode) {
162     case SMBUS_RECV_BYTE:
163         if (sc->receive_byte) {
164             ret = sc->receive_byte(dev);
165         } else {
166             ret = 0;
167         }
168         DPRINTF("Receive Byte %02x\n", ret);
169         dev->mode = SMBUS_DONE;
170         break;
171     case SMBUS_READ_DATA:
172         if (sc->read_data) {
173             ret = sc->read_data(dev, dev->command, dev->data_len);
174             dev->data_len++;
175         } else {
176             ret = 0;
177         }
178         DPRINTF("Read data %02x\n", ret);
179         break;
180     default:
181         BADF("Unexpected read in state %d\n", dev->mode);
182         dev->mode = SMBUS_CONFUSED;
183         ret = 0;
184         break;
185     }
186     return ret;
187 }
188
189 static int smbus_i2c_send(I2CSlave *s, uint8_t data)
190 {
191     SMBusDevice *dev = SMBUS_DEVICE(s);
192
193     switch (dev->mode) {
194     case SMBUS_WRITE_DATA:
195         DPRINTF("Write data %02x\n", data);
196         if (dev->data_len >= sizeof(dev->data_buf)) {
197             BADF("Too many bytes sent\n");
198         } else {
199             dev->data_buf[dev->data_len++] = data;
200         }
201         break;
202     default:
203         BADF("Unexpected write in state %d\n", dev->mode);
204         break;
205     }
206     return 0;
207 }
208
209 /* Master device commands.  */
210 int smbus_quick_command(I2CBus *bus, uint8_t addr, int read)
211 {
212     if (i2c_start_transfer(bus, addr, read)) {
213         return -1;
214     }
215     i2c_end_transfer(bus);
216     return 0;
217 }
218
219 int smbus_receive_byte(I2CBus *bus, uint8_t addr)
220 {
221     uint8_t data;
222
223     if (i2c_start_transfer(bus, addr, 1)) {
224         return -1;
225     }
226     data = i2c_recv(bus);
227     i2c_nack(bus);
228     i2c_end_transfer(bus);
229     return data;
230 }
231
232 int smbus_send_byte(I2CBus *bus, uint8_t addr, uint8_t data)
233 {
234     if (i2c_start_transfer(bus, addr, 0)) {
235         return -1;
236     }
237     i2c_send(bus, data);
238     i2c_end_transfer(bus);
239     return 0;
240 }
241
242 int smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command)
243 {
244     uint8_t data;
245     if (i2c_start_transfer(bus, addr, 0)) {
246         return -1;
247     }
248     i2c_send(bus, command);
249     if (i2c_start_transfer(bus, addr, 1)) {
250         i2c_end_transfer(bus);
251         return -1;
252     }
253     data = i2c_recv(bus);
254     i2c_nack(bus);
255     i2c_end_transfer(bus);
256     return data;
257 }
258
259 int smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data)
260 {
261     if (i2c_start_transfer(bus, addr, 0)) {
262         return -1;
263     }
264     i2c_send(bus, command);
265     i2c_send(bus, data);
266     i2c_end_transfer(bus);
267     return 0;
268 }
269
270 int smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command)
271 {
272     uint16_t data;
273     if (i2c_start_transfer(bus, addr, 0)) {
274         return -1;
275     }
276     i2c_send(bus, command);
277     if (i2c_start_transfer(bus, addr, 1)) {
278         i2c_end_transfer(bus);
279         return -1;
280     }
281     data = i2c_recv(bus);
282     data |= i2c_recv(bus) << 8;
283     i2c_nack(bus);
284     i2c_end_transfer(bus);
285     return data;
286 }
287
288 int smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data)
289 {
290     if (i2c_start_transfer(bus, addr, 0)) {
291         return -1;
292     }
293     i2c_send(bus, command);
294     i2c_send(bus, data & 0xff);
295     i2c_send(bus, data >> 8);
296     i2c_end_transfer(bus);
297     return 0;
298 }
299
300 int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
301                      int len, bool recv_len, bool send_cmd)
302 {
303     int rlen;
304     int i;
305
306     if (send_cmd) {
307         if (i2c_start_transfer(bus, addr, 0)) {
308             return -1;
309         }
310         i2c_send(bus, command);
311     }
312     if (i2c_start_transfer(bus, addr, 1)) {
313         if (send_cmd) {
314             i2c_end_transfer(bus);
315         }
316         return -1;
317     }
318     if (recv_len) {
319         rlen = i2c_recv(bus);
320     } else {
321         rlen = len;
322     }
323     if (rlen > len) {
324         rlen = 0;
325     }
326     for (i = 0; i < rlen; i++) {
327         data[i] = i2c_recv(bus);
328     }
329     i2c_nack(bus);
330     i2c_end_transfer(bus);
331     return rlen;
332 }
333
334 int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
335                       int len, bool send_len)
336 {
337     int i;
338
339     if (len > 32)
340         len = 32;
341
342     if (i2c_start_transfer(bus, addr, 0)) {
343         return -1;
344     }
345     i2c_send(bus, command);
346     if (send_len) {
347         i2c_send(bus, len);
348     }
349     for (i = 0; i < len; i++) {
350         i2c_send(bus, data[i]);
351     }
352     i2c_end_transfer(bus);
353     return 0;
354 }
355
356 static void smbus_device_class_init(ObjectClass *klass, void *data)
357 {
358     I2CSlaveClass *sc = I2C_SLAVE_CLASS(klass);
359
360     sc->event = smbus_i2c_event;
361     sc->recv = smbus_i2c_recv;
362     sc->send = smbus_i2c_send;
363 }
364
365 static const TypeInfo smbus_device_type_info = {
366     .name = TYPE_SMBUS_DEVICE,
367     .parent = TYPE_I2C_SLAVE,
368     .instance_size = sizeof(SMBusDevice),
369     .abstract = true,
370     .class_size = sizeof(SMBusDeviceClass),
371     .class_init = smbus_device_class_init,
372 };
373
374 static void smbus_device_register_types(void)
375 {
376     type_register_static(&smbus_device_type_info);
377 }
378
379 type_init(smbus_device_register_types)
This page took 0.045062 seconds and 4 git commands to generate.