Statistics
| Branch: | Revision:

root / hw / i2c / smbus.c @ 49ab747f

History | View | Annotate | Download (8.1 kB)

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 "hw/hw.h"
13
#include "hw/i2c/i2c.h"
14
#include "hw/i2c/smbus.h"
15

    
16
//#define DEBUG_SMBUS 1
17

    
18
#ifdef DEBUG_SMBUS
19
#define DPRINTF(fmt, ...) \
20
do { printf("smbus(%02x): " fmt , dev->i2c.address, ## __VA_ARGS__); } while (0)
21
#define BADF(fmt, ...) \
22
do { fprintf(stderr, "smbus: error: " fmt , ## __VA_ARGS__); exit(1);} while (0)
23
#else
24
#define DPRINTF(fmt, ...) do {} while(0)
25
#define BADF(fmt, ...) \
26
do { fprintf(stderr, "smbus: error: " fmt , ## __VA_ARGS__);} while (0)
27
#endif
28

    
29
enum {
30
    SMBUS_IDLE,
31
    SMBUS_WRITE_DATA,
32
    SMBUS_RECV_BYTE,
33
    SMBUS_READ_DATA,
34
    SMBUS_DONE,
35
    SMBUS_CONFUSED = -1
36
};
37

    
38
static void smbus_do_quick_cmd(SMBusDevice *dev, int recv)
39
{
40
    SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
41

    
42
    DPRINTF("Quick Command %d\n", recv);
43
    if (sc->quick_cmd) {
44
        sc->quick_cmd(dev, recv);
45
    }
46
}
47

    
48
static void smbus_do_write(SMBusDevice *dev)
49
{
50
    SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
51

    
52
    if (dev->data_len == 0) {
53
        smbus_do_quick_cmd(dev, 0);
54
    } else if (dev->data_len == 1) {
55
        DPRINTF("Send Byte\n");
56
        if (sc->send_byte) {
57
            sc->send_byte(dev, dev->data_buf[0]);
58
        }
59
    } else {
60
        dev->command = dev->data_buf[0];
61
        DPRINTF("Command %d len %d\n", dev->command, dev->data_len - 1);
62
        if (sc->write_data) {
63
            sc->write_data(dev, dev->command, dev->data_buf + 1,
64
                           dev->data_len - 1);
65
        }
66
    }
67
}
68

    
69
static void smbus_i2c_event(I2CSlave *s, enum i2c_event event)
70
{
71
    SMBusDevice *dev = SMBUS_DEVICE(s);
72

    
73
    switch (event) {
74
    case I2C_START_SEND:
75
        switch (dev->mode) {
76
        case SMBUS_IDLE:
77
            DPRINTF("Incoming data\n");
78
            dev->mode = SMBUS_WRITE_DATA;
79
            break;
80
        default:
81
            BADF("Unexpected send start condition in state %d\n", dev->mode);
82
            dev->mode = SMBUS_CONFUSED;
83
            break;
84
        }
85
        break;
86

    
87
    case I2C_START_RECV:
88
        switch (dev->mode) {
89
        case SMBUS_IDLE:
90
            DPRINTF("Read mode\n");
91
            dev->mode = SMBUS_RECV_BYTE;
92
            break;
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
                if (dev->data_len > 1) {
99
                    smbus_do_write(dev);
100
                } else {
101
                    dev->command = dev->data_buf[0];
102
                    DPRINTF("%02x: Command %d\n", dev->i2c.address,
103
                            dev->command);
104
                }
105
                DPRINTF("Read mode\n");
106
                dev->data_len = 0;
107
                dev->mode = SMBUS_READ_DATA;
108
            }
109
            break;
110
        default:
111
            BADF("Unexpected recv start condition in state %d\n", dev->mode);
112
            dev->mode = SMBUS_CONFUSED;
113
            break;
114
        }
115
        break;
116

    
117
    case I2C_FINISH:
118
        switch (dev->mode) {
119
        case SMBUS_WRITE_DATA:
120
            smbus_do_write(dev);
121
            break;
122
        case SMBUS_RECV_BYTE:
123
            smbus_do_quick_cmd(dev, 1);
124
            break;
125
        case SMBUS_READ_DATA:
126
            BADF("Unexpected stop during receive\n");
127
            break;
128
        default:
129
            /* Nothing to do.  */
130
            break;
131
        }
132
        dev->mode = SMBUS_IDLE;
133
        dev->data_len = 0;
134
        break;
135

    
136
    case I2C_NACK:
137
        switch (dev->mode) {
138
        case SMBUS_DONE:
139
            /* Nothing to do.  */
140
            break;
141
        case SMBUS_READ_DATA:
142
            dev->mode = SMBUS_DONE;
143
            break;
144
        default:
145
            BADF("Unexpected NACK in state %d\n", dev->mode);
146
            dev->mode = SMBUS_CONFUSED;
147
            break;
148
        }
149
    }
150
}
151

    
152
static int smbus_i2c_recv(I2CSlave *s)
153
{
154
    SMBusDevice *dev = SMBUS_DEVICE(s);
155
    SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
156
    int ret;
157

    
158
    switch (dev->mode) {
159
    case SMBUS_RECV_BYTE:
160
        if (sc->receive_byte) {
161
            ret = sc->receive_byte(dev);
162
        } else {
163
            ret = 0;
164
        }
165
        DPRINTF("Receive Byte %02x\n", ret);
166
        dev->mode = SMBUS_DONE;
167
        break;
168
    case SMBUS_READ_DATA:
169
        if (sc->read_data) {
170
            ret = sc->read_data(dev, dev->command, dev->data_len);
171
            dev->data_len++;
172
        } else {
173
            ret = 0;
174
        }
175
        DPRINTF("Read data %02x\n", ret);
176
        break;
177
    default:
178
        BADF("Unexpected read in state %d\n", dev->mode);
179
        dev->mode = SMBUS_CONFUSED;
180
        ret = 0;
181
        break;
182
    }
183
    return ret;
184
}
185

    
186
static int smbus_i2c_send(I2CSlave *s, uint8_t data)
187
{
188
    SMBusDevice *dev = SMBUS_DEVICE(s);
189

    
190
    switch (dev->mode) {
191
    case SMBUS_WRITE_DATA:
192
        DPRINTF("Write data %02x\n", data);
193
        dev->data_buf[dev->data_len++] = data;
194
        break;
195
    default:
196
        BADF("Unexpected write in state %d\n", dev->mode);
197
        break;
198
    }
199
    return 0;
200
}
201

    
202
static int smbus_device_init(I2CSlave *i2c)
203
{
204
    SMBusDevice *dev = SMBUS_DEVICE(i2c);
205
    SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
206

    
207
    return sc->init(dev);
208
}
209

    
210
/* Master device commands.  */
211
void smbus_quick_command(i2c_bus *bus, uint8_t addr, int read)
212
{
213
    i2c_start_transfer(bus, addr, read);
214
    i2c_end_transfer(bus);
215
}
216

    
217
uint8_t smbus_receive_byte(i2c_bus *bus, uint8_t addr)
218
{
219
    uint8_t data;
220

    
221
    i2c_start_transfer(bus, addr, 1);
222
    data = i2c_recv(bus);
223
    i2c_nack(bus);
224
    i2c_end_transfer(bus);
225
    return data;
226
}
227

    
228
void smbus_send_byte(i2c_bus *bus, uint8_t addr, uint8_t data)
229
{
230
    i2c_start_transfer(bus, addr, 0);
231
    i2c_send(bus, data);
232
    i2c_end_transfer(bus);
233
}
234

    
235
uint8_t smbus_read_byte(i2c_bus *bus, uint8_t addr, uint8_t command)
236
{
237
    uint8_t data;
238
    i2c_start_transfer(bus, addr, 0);
239
    i2c_send(bus, command);
240
    i2c_start_transfer(bus, addr, 1);
241
    data = i2c_recv(bus);
242
    i2c_nack(bus);
243
    i2c_end_transfer(bus);
244
    return data;
245
}
246

    
247
void smbus_write_byte(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t data)
248
{
249
    i2c_start_transfer(bus, addr, 0);
250
    i2c_send(bus, command);
251
    i2c_send(bus, data);
252
    i2c_end_transfer(bus);
253
}
254

    
255
uint16_t smbus_read_word(i2c_bus *bus, uint8_t addr, uint8_t command)
256
{
257
    uint16_t data;
258
    i2c_start_transfer(bus, addr, 0);
259
    i2c_send(bus, command);
260
    i2c_start_transfer(bus, addr, 1);
261
    data = i2c_recv(bus);
262
    data |= i2c_recv(bus) << 8;
263
    i2c_nack(bus);
264
    i2c_end_transfer(bus);
265
    return data;
266
}
267

    
268
void smbus_write_word(i2c_bus *bus, uint8_t addr, uint8_t command, uint16_t data)
269
{
270
    i2c_start_transfer(bus, addr, 0);
271
    i2c_send(bus, command);
272
    i2c_send(bus, data & 0xff);
273
    i2c_send(bus, data >> 8);
274
    i2c_end_transfer(bus);
275
}
276

    
277
int smbus_read_block(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t *data)
278
{
279
    int len;
280
    int i;
281

    
282
    i2c_start_transfer(bus, addr, 0);
283
    i2c_send(bus, command);
284
    i2c_start_transfer(bus, addr, 1);
285
    len = i2c_recv(bus);
286
    if (len > 32)
287
        len = 0;
288
    for (i = 0; i < len; i++)
289
        data[i] = i2c_recv(bus);
290
    i2c_nack(bus);
291
    i2c_end_transfer(bus);
292
    return len;
293
}
294

    
295
void smbus_write_block(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t *data,
296
                       int len)
297
{
298
    int i;
299

    
300
    if (len > 32)
301
        len = 32;
302

    
303
    i2c_start_transfer(bus, addr, 0);
304
    i2c_send(bus, command);
305
    i2c_send(bus, len);
306
    for (i = 0; i < len; i++)
307
        i2c_send(bus, data[i]);
308
    i2c_end_transfer(bus);
309
}
310

    
311
static void smbus_device_class_init(ObjectClass *klass, void *data)
312
{
313
    I2CSlaveClass *sc = I2C_SLAVE_CLASS(klass);
314

    
315
    sc->init = smbus_device_init;
316
    sc->event = smbus_i2c_event;
317
    sc->recv = smbus_i2c_recv;
318
    sc->send = smbus_i2c_send;
319
}
320

    
321
static const TypeInfo smbus_device_type_info = {
322
    .name = TYPE_SMBUS_DEVICE,
323
    .parent = TYPE_I2C_SLAVE,
324
    .instance_size = sizeof(SMBusDevice),
325
    .abstract = true,
326
    .class_size = sizeof(SMBusDeviceClass),
327
    .class_init = smbus_device_class_init,
328
};
329

    
330
static void smbus_device_register_types(void)
331
{
332
    type_register_static(&smbus_device_type_info);
333
}
334

    
335
type_init(smbus_device_register_types)