Statistics
| Branch: | Revision:

root / hw / i2c.c @ 4a2c8ac2

History | View | Annotate | Download (2.7 kB)

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

    
10
#include "vl.h"
11

    
12
struct i2c_bus
13
{
14
    i2c_slave *current_dev;
15
    i2c_slave *dev;
16
};
17

    
18
/* Create a new I2C bus.  */
19
i2c_bus *i2c_init_bus(void)
20
{
21
    i2c_bus *bus;
22

    
23
    bus = (i2c_bus *)qemu_mallocz(sizeof(i2c_bus));
24
    return bus;
25
}
26

    
27
/* Create a new slave device.  */
28
i2c_slave *i2c_slave_init(i2c_bus *bus, int address, int size)
29
{
30
    i2c_slave *dev;
31

    
32
    if (size < sizeof(i2c_slave))
33
        cpu_abort(cpu_single_env, "I2C struct too small");
34

    
35
    dev = (i2c_slave *)qemu_mallocz(size);
36
    dev->address = address;
37
    dev->next = bus->dev;
38
    bus->dev = dev;
39

    
40
    return dev;
41
}
42

    
43
void i2c_set_slave_address(i2c_slave *dev, int address)
44
{
45
    dev->address = address;
46
}
47

    
48
/* Return nonzero if bus is busy.  */
49
int i2c_bus_busy(i2c_bus *bus)
50
{
51
    return bus->current_dev != NULL;
52
}
53

    
54
/* Returns non-zero if the address is not valid.  */
55
/* TODO: Make this handle multiple masters.  */
56
int i2c_start_transfer(i2c_bus *bus, int address, int recv)
57
{
58
    i2c_slave *dev;
59

    
60
    for (dev = bus->dev; dev; dev = dev->next) {
61
        if (dev->address == address)
62
            break;
63
    }
64

    
65
    if (!dev)
66
        return 1;
67

    
68
    /* If the bus is already busy, assume this is a repeated
69
       start condition.  */
70
    bus->current_dev = dev;
71
    dev->event(dev, recv ? I2C_START_RECV : I2C_START_SEND);
72
    return 0;
73
}
74

    
75
void i2c_end_transfer(i2c_bus *bus)
76
{
77
    i2c_slave *dev = bus->current_dev;
78

    
79
    if (!dev)
80
        return;
81

    
82
    dev->event(dev, I2C_FINISH);
83

    
84
    bus->current_dev = NULL;
85
}
86

    
87
int i2c_send(i2c_bus *bus, uint8_t data)
88
{
89
    i2c_slave *dev = bus->current_dev;
90

    
91
    if (!dev)
92
        return -1;
93

    
94
    return dev->send(dev, data);
95
}
96

    
97
int i2c_recv(i2c_bus *bus)
98
{
99
    i2c_slave *dev = bus->current_dev;
100

    
101
    if (!dev)
102
        return -1;
103

    
104
    return dev->recv(dev);
105
}
106

    
107
void i2c_nack(i2c_bus *bus)
108
{
109
    i2c_slave *dev = bus->current_dev;
110

    
111
    if (!dev)
112
        return;
113

    
114
    dev->event(dev, I2C_NACK);
115
}
116

    
117
void i2c_bus_save(QEMUFile *f, i2c_bus *bus)
118
{
119
    qemu_put_byte(f, bus->current_dev ? bus->current_dev->address : 0x00);
120
}
121

    
122
void i2c_bus_load(QEMUFile *f, i2c_bus *bus)
123
{
124
    i2c_slave *dev;
125
    uint8_t address = qemu_get_byte(f);
126

    
127
    if (address) {
128
        for (dev = bus->dev; dev; dev = dev->next)
129
            if (dev->address == address) {
130
                bus->current_dev = dev;
131
                return;
132
            }
133

    
134
        fprintf(stderr, "%s: I2C slave with address %02x disappeared\n",
135
                __FUNCTION__, address);
136
    }
137
}
138

    
139
void i2c_slave_save(QEMUFile *f, i2c_slave *dev)
140
{
141
    qemu_put_byte(f, dev->address);
142
}
143

    
144
void i2c_slave_load(QEMUFile *f, i2c_slave *dev)
145
{
146
    dev->address = qemu_get_byte(f);
147
}