Statistics
| Branch: | Revision:

root / hw / smbus.c @ 074f2fff

History | View | Annotate | Download (7.8 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
    SMBusDeviceInfo *t = container_of(dev->i2c.info, SMBusDeviceInfo, i2c);
41

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

    
47
static void smbus_do_write(SMBusDevice *dev)
48
{
49
    SMBusDeviceInfo *t = container_of(dev->i2c.info, SMBusDeviceInfo, i2c);
50

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

    
68
static void smbus_i2c_event(i2c_slave *s, enum i2c_event event)
69
{
70
    SMBusDevice *dev = FROM_I2C_SLAVE(SMBusDevice, s);
71

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

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

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

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

    
151
static int smbus_i2c_recv(i2c_slave *s)
152
{
153
    SMBusDeviceInfo *t = container_of(s->info, SMBusDeviceInfo, i2c);
154
    SMBusDevice *dev = FROM_I2C_SLAVE(SMBusDevice, s);
155
    int ret;
156

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

    
185
static int smbus_i2c_send(i2c_slave *s, uint8_t data)
186
{
187
    SMBusDevice *dev = FROM_I2C_SLAVE(SMBusDevice, s);
188

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

    
201
static void smbus_device_init(i2c_slave *i2c)
202
{
203
    SMBusDeviceInfo *t = container_of(i2c->info, SMBusDeviceInfo, i2c);
204
    SMBusDevice *dev = FROM_I2C_SLAVE(SMBusDevice, i2c);
205

    
206
    t->init(dev);
207
}
208

    
209
void smbus_register_device(SMBusDeviceInfo *info)
210
{
211
    assert(info->i2c.qdev.size >= sizeof(SMBusDevice));
212
    info->i2c.init = smbus_device_init;
213
    info->i2c.event = smbus_i2c_event;
214
    info->i2c.recv = smbus_i2c_recv;
215
    info->i2c.send = smbus_i2c_send;
216
    i2c_register_slave(&info->i2c);
217
}
218

    
219
/* Master device commands.  */
220
void smbus_quick_command(i2c_bus *bus, int addr, int read)
221
{
222
    i2c_start_transfer(bus, addr, read);
223
    i2c_end_transfer(bus);
224
}
225

    
226
uint8_t smbus_receive_byte(i2c_bus *bus, int addr)
227
{
228
    uint8_t data;
229

    
230
    i2c_start_transfer(bus, addr, 1);
231
    data = i2c_recv(bus);
232
    i2c_nack(bus);
233
    i2c_end_transfer(bus);
234
    return data;
235
}
236

    
237
void smbus_send_byte(i2c_bus *bus, int addr, uint8_t data)
238
{
239
    i2c_start_transfer(bus, addr, 0);
240
    i2c_send(bus, data);
241
    i2c_end_transfer(bus);
242
}
243

    
244
uint8_t smbus_read_byte(i2c_bus *bus, int addr, uint8_t command)
245
{
246
    uint8_t data;
247
    i2c_start_transfer(bus, addr, 0);
248
    i2c_send(bus, command);
249
    i2c_start_transfer(bus, addr, 1);
250
    data = i2c_recv(bus);
251
    i2c_nack(bus);
252
    i2c_end_transfer(bus);
253
    return data;
254
}
255

    
256
void smbus_write_byte(i2c_bus *bus, int addr, uint8_t command, uint8_t data)
257
{
258
    i2c_start_transfer(bus, addr, 0);
259
    i2c_send(bus, command);
260
    i2c_send(bus, data);
261
    i2c_end_transfer(bus);
262
}
263

    
264
uint16_t smbus_read_word(i2c_bus *bus, int addr, uint8_t command)
265
{
266
    uint16_t data;
267
    i2c_start_transfer(bus, addr, 0);
268
    i2c_send(bus, command);
269
    i2c_start_transfer(bus, addr, 1);
270
    data = i2c_recv(bus);
271
    data |= i2c_recv(bus) << 8;
272
    i2c_nack(bus);
273
    i2c_end_transfer(bus);
274
    return data;
275
}
276

    
277
void smbus_write_word(i2c_bus *bus, int addr, uint8_t command, uint16_t data)
278
{
279
    i2c_start_transfer(bus, addr, 0);
280
    i2c_send(bus, command);
281
    i2c_send(bus, data & 0xff);
282
    i2c_send(bus, data >> 8);
283
    i2c_end_transfer(bus);
284
}
285

    
286
int smbus_read_block(i2c_bus *bus, int addr, uint8_t command, uint8_t *data)
287
{
288
    int len;
289
    int i;
290

    
291
    i2c_start_transfer(bus, addr, 0);
292
    i2c_send(bus, command);
293
    i2c_start_transfer(bus, addr, 1);
294
    len = i2c_recv(bus);
295
    if (len > 32)
296
        len = 0;
297
    for (i = 0; i < len; i++)
298
        data[i] = i2c_recv(bus);
299
    i2c_nack(bus);
300
    i2c_end_transfer(bus);
301
    return len;
302
}
303

    
304
void smbus_write_block(i2c_bus *bus, int addr, uint8_t command, uint8_t *data,
305
                       int len)
306
{
307
    int i;
308

    
309
    if (len > 32)
310
        len = 32;
311

    
312
    i2c_start_transfer(bus, addr, 0);
313
    i2c_send(bus, command);
314
    i2c_send(bus, len);
315
    for (i = 0; i < len; i++)
316
        i2c_send(bus, data[i]);
317
    i2c_end_transfer(bus);
318
}