]> Git Repo - qemu.git/blob - hw/i2c/smbus.c
dirty-bitmaps: clean-up bitmaps loading and migration logic
[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         dev->data_buf[dev->data_len++] = data;
197         break;
198     default:
199         BADF("Unexpected write in state %d\n", dev->mode);
200         break;
201     }
202     return 0;
203 }
204
205 /* Master device commands.  */
206 int smbus_quick_command(I2CBus *bus, uint8_t addr, int read)
207 {
208     if (i2c_start_transfer(bus, addr, read)) {
209         return -1;
210     }
211     i2c_end_transfer(bus);
212     return 0;
213 }
214
215 int smbus_receive_byte(I2CBus *bus, uint8_t addr)
216 {
217     uint8_t data;
218
219     if (i2c_start_transfer(bus, addr, 1)) {
220         return -1;
221     }
222     data = i2c_recv(bus);
223     i2c_nack(bus);
224     i2c_end_transfer(bus);
225     return data;
226 }
227
228 int smbus_send_byte(I2CBus *bus, uint8_t addr, uint8_t data)
229 {
230     if (i2c_start_transfer(bus, addr, 0)) {
231         return -1;
232     }
233     i2c_send(bus, data);
234     i2c_end_transfer(bus);
235     return 0;
236 }
237
238 int smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command)
239 {
240     uint8_t data;
241     if (i2c_start_transfer(bus, addr, 0)) {
242         return -1;
243     }
244     i2c_send(bus, command);
245     if (i2c_start_transfer(bus, addr, 1)) {
246         i2c_end_transfer(bus);
247         return -1;
248     }
249     data = i2c_recv(bus);
250     i2c_nack(bus);
251     i2c_end_transfer(bus);
252     return data;
253 }
254
255 int smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data)
256 {
257     if (i2c_start_transfer(bus, addr, 0)) {
258         return -1;
259     }
260     i2c_send(bus, command);
261     i2c_send(bus, data);
262     i2c_end_transfer(bus);
263     return 0;
264 }
265
266 int smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command)
267 {
268     uint16_t data;
269     if (i2c_start_transfer(bus, addr, 0)) {
270         return -1;
271     }
272     i2c_send(bus, command);
273     if (i2c_start_transfer(bus, addr, 1)) {
274         i2c_end_transfer(bus);
275         return -1;
276     }
277     data = i2c_recv(bus);
278     data |= i2c_recv(bus) << 8;
279     i2c_nack(bus);
280     i2c_end_transfer(bus);
281     return data;
282 }
283
284 int smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data)
285 {
286     if (i2c_start_transfer(bus, addr, 0)) {
287         return -1;
288     }
289     i2c_send(bus, command);
290     i2c_send(bus, data & 0xff);
291     i2c_send(bus, data >> 8);
292     i2c_end_transfer(bus);
293     return 0;
294 }
295
296 int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
297                      int len, bool recv_len, bool send_cmd)
298 {
299     int rlen;
300     int i;
301
302     if (send_cmd) {
303         if (i2c_start_transfer(bus, addr, 0)) {
304             return -1;
305         }
306         i2c_send(bus, command);
307     }
308     if (i2c_start_transfer(bus, addr, 1)) {
309         if (send_cmd) {
310             i2c_end_transfer(bus);
311         }
312         return -1;
313     }
314     if (recv_len) {
315         rlen = i2c_recv(bus);
316     } else {
317         rlen = len;
318     }
319     if (rlen > len) {
320         rlen = 0;
321     }
322     for (i = 0; i < rlen; i++) {
323         data[i] = i2c_recv(bus);
324     }
325     i2c_nack(bus);
326     i2c_end_transfer(bus);
327     return rlen;
328 }
329
330 int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
331                       int len, bool send_len)
332 {
333     int i;
334
335     if (len > 32)
336         len = 32;
337
338     if (i2c_start_transfer(bus, addr, 0)) {
339         return -1;
340     }
341     i2c_send(bus, command);
342     if (send_len) {
343         i2c_send(bus, len);
344     }
345     for (i = 0; i < len; i++) {
346         i2c_send(bus, data[i]);
347     }
348     i2c_end_transfer(bus);
349     return 0;
350 }
351
352 static void smbus_device_class_init(ObjectClass *klass, void *data)
353 {
354     I2CSlaveClass *sc = I2C_SLAVE_CLASS(klass);
355
356     sc->event = smbus_i2c_event;
357     sc->recv = smbus_i2c_recv;
358     sc->send = smbus_i2c_send;
359 }
360
361 static const TypeInfo smbus_device_type_info = {
362     .name = TYPE_SMBUS_DEVICE,
363     .parent = TYPE_I2C_SLAVE,
364     .instance_size = sizeof(SMBusDevice),
365     .abstract = true,
366     .class_size = sizeof(SMBusDeviceClass),
367     .class_init = smbus_device_class_init,
368 };
369
370 static void smbus_device_register_types(void)
371 {
372     type_register_static(&smbus_device_type_info);
373 }
374
375 type_init(smbus_device_register_types)
This page took 0.041983 seconds and 4 git commands to generate.