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