Statistics
| Branch: | Revision:

root / hw / smbus.c @ 001faf32

History | View | Annotate | Download (7.5 kB)

1
/*
2
 * QEMU SMBus device emulation.
3
 *
4
 * Copyright (c) 2007 CodeSourcery.
5
 * Written by Paul Brook
6
 *
7
 * This code is licenced under the LGPL.
8
 */
9

    
10
/* TODO: Implement PEC.  */
11

    
12
#include "hw.h"
13
#include "i2c.h"
14
#include "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
    DPRINTF("Quick Command %d\n", recv);
41
    if (dev->quick_cmd)
42
        dev->quick_cmd(dev, recv);
43
}
44

    
45
static void smbus_do_write(SMBusDevice *dev)
46
{
47
    if (dev->data_len == 0) {
48
        smbus_do_quick_cmd(dev, 0);
49
    } else if (dev->data_len == 1) {
50
        DPRINTF("Send Byte\n");
51
        if (dev->send_byte) {
52
            dev->send_byte(dev, dev->data_buf[0]);
53
        }
54
    } else {
55
        dev->command = dev->data_buf[0];
56
        DPRINTF("Command %d len %d\n", dev->command, dev->data_len - 1);
57
        if (dev->write_data) {
58
            dev->write_data(dev, dev->command, dev->data_buf + 1,
59
                            dev->data_len - 1);
60
        }
61
    }
62
}
63

    
64
static void smbus_i2c_event(i2c_slave *s, enum i2c_event event)
65
{
66
    SMBusDevice *dev = (SMBusDevice *)s;
67
    switch (event) {
68
    case I2C_START_SEND:
69
        switch (dev->mode) {
70
        case SMBUS_IDLE:
71
            DPRINTF("Incoming data\n");
72
            dev->mode = SMBUS_WRITE_DATA;
73
            break;
74
        default:
75
            BADF("Unexpected send start condition in state %d\n", dev->mode);
76
            dev->mode = SMBUS_CONFUSED;
77
            break;
78
        }
79
        break;
80

    
81
    case I2C_START_RECV:
82
        switch (dev->mode) {
83
        case SMBUS_IDLE:
84
            DPRINTF("Read mode\n");
85
            dev->mode = SMBUS_RECV_BYTE;
86
            break;
87
        case SMBUS_WRITE_DATA:
88
            if (dev->data_len == 0) {
89
                BADF("Read after write with no data\n");
90
                dev->mode = SMBUS_CONFUSED;
91
            } else {
92
                if (dev->data_len > 1) {
93
                    smbus_do_write(dev);
94
                } else {
95
                    dev->command = dev->data_buf[0];
96
                    DPRINTF("%02x: Command %d\n", dev->i2c.address,
97
                            dev->command);
98
                }
99
                DPRINTF("Read mode\n");
100
                dev->data_len = 0;
101
                dev->mode = SMBUS_READ_DATA;
102
            }
103
            break;
104
        default:
105
            BADF("Unexpected recv start condition in state %d\n", dev->mode);
106
            dev->mode = SMBUS_CONFUSED;
107
            break;
108
        }
109
        break;
110

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

    
130
    case I2C_NACK:
131
        switch (dev->mode) {
132
        case SMBUS_DONE:
133
            /* Nothing to do.  */
134
            break;
135
        case SMBUS_READ_DATA:
136
            dev->mode = SMBUS_DONE;
137
            break;
138
        default:
139
            BADF("Unexpected NACK in state %d\n", dev->mode);
140
            dev->mode = SMBUS_CONFUSED;
141
            break;
142
        }
143
    }
144
}
145

    
146
static int smbus_i2c_recv(i2c_slave *s)
147
{
148
    SMBusDevice *dev = (SMBusDevice *)s;
149
    int ret;
150

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

    
179
static int smbus_i2c_send(i2c_slave *s, uint8_t data)
180
{
181
    SMBusDevice *dev = (SMBusDevice *)s;
182
    switch (dev->mode) {
183
    case SMBUS_WRITE_DATA:
184
        DPRINTF("Write data %02x\n", data);
185
        dev->data_buf[dev->data_len++] = data;
186
        break;
187
    default:
188
        BADF("Unexpected write in state %d\n", dev->mode);
189
        break;
190
    }
191
    return 0;
192
}
193

    
194
SMBusDevice *smbus_device_init(i2c_bus *bus, int address, int size)
195
{
196
    SMBusDevice *dev;
197

    
198
    if (size < sizeof(SMBusDevice))
199
        hw_error("SMBus struct too small");
200

    
201
    dev = (SMBusDevice *)i2c_slave_init(bus, address, size);
202
    dev->i2c.event = smbus_i2c_event;
203
    dev->i2c.recv = smbus_i2c_recv;
204
    dev->i2c.send = smbus_i2c_send;
205

    
206
    return dev;
207
}
208

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

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

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

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

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

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

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

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

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

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

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

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

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