Statistics
| Branch: | Revision:

root / hw / smbus.c @ 3f582262

History | View | Annotate | Download (7.4 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 "vl.h"
13

    
14
//#define DEBUG_SMBUS 1
15

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

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

    
36
static void smbus_do_quick_cmd(SMBusDevice *dev, int recv)
37
{
38
    DPRINTF("Quick Command %d\n", recv);
39
    if (dev->quick_cmd)
40
        dev->quick_cmd(dev, recv);
41
}
42

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

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

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

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

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

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

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

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

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

    
196
    if (size < sizeof(SMBusDevice))
197
        cpu_abort(cpu_single_env, "SMBus struct too small");
198

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

    
204
    return dev;
205
}
206

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

    
214
uint8_t smbus_receive_byte(i2c_bus *bus, int addr)
215
{
216
    uint8_t data;
217

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

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

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

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

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

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

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

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

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

    
297
    if (len > 32)
298
        len = 32;
299

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