Statistics
| Branch: | Revision:

root / hw / bitbang_i2c.c @ 3a38d437

History | View | Annotate | Download (4.5 kB)

1 3ead03bd Andrzej Zaborowski
/*
2 3ead03bd Andrzej Zaborowski
 * Bit-Bang i2c emulation extracted from
3 3ead03bd Andrzej Zaborowski
 * Marvell MV88W8618 / Freecom MusicPal emulation.
4 3ead03bd Andrzej Zaborowski
 *
5 3ead03bd Andrzej Zaborowski
 * Copyright (c) 2008 Jan Kiszka
6 3ead03bd Andrzej Zaborowski
 *
7 3ead03bd Andrzej Zaborowski
 * This code is licenced under the GNU GPL v2.
8 3ead03bd Andrzej Zaborowski
 */
9 3ead03bd Andrzej Zaborowski
#include "hw.h"
10 3ead03bd Andrzej Zaborowski
#include "i2c.h"
11 3ead03bd Andrzej Zaborowski
#include "sysbus.h"
12 3ead03bd Andrzej Zaborowski
13 3ead03bd Andrzej Zaborowski
typedef enum bitbang_i2c_state {
14 3ead03bd Andrzej Zaborowski
    STOPPED = 0,
15 3ead03bd Andrzej Zaborowski
    INITIALIZING,
16 3ead03bd Andrzej Zaborowski
    SENDING_BIT7,
17 3ead03bd Andrzej Zaborowski
    SENDING_BIT6,
18 3ead03bd Andrzej Zaborowski
    SENDING_BIT5,
19 3ead03bd Andrzej Zaborowski
    SENDING_BIT4,
20 3ead03bd Andrzej Zaborowski
    SENDING_BIT3,
21 3ead03bd Andrzej Zaborowski
    SENDING_BIT2,
22 3ead03bd Andrzej Zaborowski
    SENDING_BIT1,
23 3ead03bd Andrzej Zaborowski
    SENDING_BIT0,
24 3ead03bd Andrzej Zaborowski
    WAITING_FOR_ACK,
25 3ead03bd Andrzej Zaborowski
    RECEIVING_BIT7,
26 3ead03bd Andrzej Zaborowski
    RECEIVING_BIT6,
27 3ead03bd Andrzej Zaborowski
    RECEIVING_BIT5,
28 3ead03bd Andrzej Zaborowski
    RECEIVING_BIT4,
29 3ead03bd Andrzej Zaborowski
    RECEIVING_BIT3,
30 3ead03bd Andrzej Zaborowski
    RECEIVING_BIT2,
31 3ead03bd Andrzej Zaborowski
    RECEIVING_BIT1,
32 3ead03bd Andrzej Zaborowski
    RECEIVING_BIT0,
33 3ead03bd Andrzej Zaborowski
    SENDING_ACK
34 3ead03bd Andrzej Zaborowski
} bitbang_i2c_state;
35 3ead03bd Andrzej Zaborowski
36 3ead03bd Andrzej Zaborowski
typedef struct bitbang_i2c_interface {
37 3ead03bd Andrzej Zaborowski
    SysBusDevice busdev;
38 3ead03bd Andrzej Zaborowski
    i2c_bus *bus;
39 3ead03bd Andrzej Zaborowski
    bitbang_i2c_state state;
40 3ead03bd Andrzej Zaborowski
    int last_data;
41 3ead03bd Andrzej Zaborowski
    int last_clock;
42 3ead03bd Andrzej Zaborowski
    uint8_t buffer;
43 3ead03bd Andrzej Zaborowski
    int current_addr;
44 3ead03bd Andrzej Zaborowski
    qemu_irq out;
45 3ead03bd Andrzej Zaborowski
} bitbang_i2c_interface;
46 3ead03bd Andrzej Zaborowski
47 3ead03bd Andrzej Zaborowski
static void bitbang_i2c_enter_stop(bitbang_i2c_interface *i2c)
48 3ead03bd Andrzej Zaborowski
{
49 3ead03bd Andrzej Zaborowski
    if (i2c->current_addr >= 0)
50 3ead03bd Andrzej Zaborowski
        i2c_end_transfer(i2c->bus);
51 3ead03bd Andrzej Zaborowski
    i2c->current_addr = -1;
52 3ead03bd Andrzej Zaborowski
    i2c->state = STOPPED;
53 3ead03bd Andrzej Zaborowski
}
54 3ead03bd Andrzej Zaborowski
55 3ead03bd Andrzej Zaborowski
static void bitbang_i2c_gpio_set(void *opaque, int irq, int level)
56 3ead03bd Andrzej Zaborowski
{
57 3ead03bd Andrzej Zaborowski
    bitbang_i2c_interface *i2c = opaque;
58 3ead03bd Andrzej Zaborowski
    int data;
59 3ead03bd Andrzej Zaborowski
    int clock;
60 3ead03bd Andrzej Zaborowski
    int data_goes_up;
61 3ead03bd Andrzej Zaborowski
    int data_goes_down;
62 3ead03bd Andrzej Zaborowski
    int clock_goes_up;
63 3ead03bd Andrzej Zaborowski
    int clock_goes_down;
64 3ead03bd Andrzej Zaborowski
65 3ead03bd Andrzej Zaborowski
    /* get pins states */
66 3ead03bd Andrzej Zaborowski
    data    = i2c->last_data;
67 3ead03bd Andrzej Zaborowski
    clock   = i2c->last_clock;
68 3ead03bd Andrzej Zaborowski
69 3ead03bd Andrzej Zaborowski
    if (irq == 0)
70 3ead03bd Andrzej Zaborowski
        data = level;
71 3ead03bd Andrzej Zaborowski
    if (irq == 1)
72 3ead03bd Andrzej Zaborowski
        clock = level;
73 3ead03bd Andrzej Zaborowski
74 3ead03bd Andrzej Zaborowski
    /* compute pins changes */
75 3ead03bd Andrzej Zaborowski
    data_goes_up    = data == 1 && i2c->last_data == 0;
76 3ead03bd Andrzej Zaborowski
    data_goes_down  = data == 0 && i2c->last_data == 1;
77 3ead03bd Andrzej Zaborowski
    clock_goes_up   = clock == 1 && i2c->last_clock == 0;
78 3ead03bd Andrzej Zaborowski
    clock_goes_down = clock == 0 && i2c->last_clock == 1;
79 3ead03bd Andrzej Zaborowski
80 3ead03bd Andrzej Zaborowski
    if (data_goes_up == 0 && data_goes_down == 0 &&
81 3ead03bd Andrzej Zaborowski
        clock_goes_up == 0 && clock_goes_down == 0)
82 3ead03bd Andrzej Zaborowski
        return;
83 3ead03bd Andrzej Zaborowski
84 3ead03bd Andrzej Zaborowski
    if (!i2c)
85 3ead03bd Andrzej Zaborowski
        return;
86 3ead03bd Andrzej Zaborowski
87 3ead03bd Andrzej Zaborowski
    if ((RECEIVING_BIT7 > i2c->state && i2c->state > RECEIVING_BIT0)
88 3ead03bd Andrzej Zaborowski
            || i2c->state == WAITING_FOR_ACK)
89 3ead03bd Andrzej Zaborowski
        qemu_set_irq(i2c->out, 0);
90 3ead03bd Andrzej Zaborowski
91 3ead03bd Andrzej Zaborowski
    switch (i2c->state) {
92 3ead03bd Andrzej Zaborowski
    case STOPPED:
93 3ead03bd Andrzej Zaborowski
        if (data_goes_down && clock == 1)
94 3ead03bd Andrzej Zaborowski
            i2c->state = INITIALIZING;
95 3ead03bd Andrzej Zaborowski
        break;
96 3ead03bd Andrzej Zaborowski
97 3ead03bd Andrzej Zaborowski
    case INITIALIZING:
98 3ead03bd Andrzej Zaborowski
        if (clock_goes_down && data == 0)
99 3ead03bd Andrzej Zaborowski
            i2c->state = SENDING_BIT7;
100 3ead03bd Andrzej Zaborowski
        else
101 3ead03bd Andrzej Zaborowski
            bitbang_i2c_enter_stop(i2c);
102 3ead03bd Andrzej Zaborowski
        break;
103 3ead03bd Andrzej Zaborowski
104 3ead03bd Andrzej Zaborowski
    case SENDING_BIT7 ... SENDING_BIT0:
105 3ead03bd Andrzej Zaborowski
        if (clock_goes_down) {
106 3ead03bd Andrzej Zaborowski
            i2c->buffer = (i2c->buffer << 1) | data;
107 3ead03bd Andrzej Zaborowski
            /* will end up in WAITING_FOR_ACK */
108 3ead03bd Andrzej Zaborowski
            i2c->state++; 
109 3ead03bd Andrzej Zaborowski
        } else if (data_goes_up && clock == 1)
110 3ead03bd Andrzej Zaborowski
            bitbang_i2c_enter_stop(i2c);
111 3ead03bd Andrzej Zaborowski
        break;
112 3ead03bd Andrzej Zaborowski
113 3ead03bd Andrzej Zaborowski
    case WAITING_FOR_ACK:
114 3ead03bd Andrzej Zaborowski
        if (clock_goes_down) {
115 3ead03bd Andrzej Zaborowski
            if (i2c->current_addr < 0) {
116 3ead03bd Andrzej Zaborowski
                i2c->current_addr = i2c->buffer;
117 3ead03bd Andrzej Zaborowski
                i2c_start_transfer(i2c->bus, (i2c->current_addr & 0xfe) / 2,
118 3ead03bd Andrzej Zaborowski
                                   i2c->buffer & 1);
119 3ead03bd Andrzej Zaborowski
            } else
120 3ead03bd Andrzej Zaborowski
                i2c_send(i2c->bus, i2c->buffer);
121 3ead03bd Andrzej Zaborowski
            if (i2c->current_addr & 1) {
122 3ead03bd Andrzej Zaborowski
                i2c->state = RECEIVING_BIT7;
123 3ead03bd Andrzej Zaborowski
                i2c->buffer = i2c_recv(i2c->bus);
124 3ead03bd Andrzej Zaborowski
            } else
125 3ead03bd Andrzej Zaborowski
                i2c->state = SENDING_BIT7;
126 3ead03bd Andrzej Zaborowski
        } else if (data_goes_up && clock == 1)
127 3ead03bd Andrzej Zaborowski
            bitbang_i2c_enter_stop(i2c);
128 3ead03bd Andrzej Zaborowski
        break;
129 3ead03bd Andrzej Zaborowski
130 3ead03bd Andrzej Zaborowski
    case RECEIVING_BIT7 ... RECEIVING_BIT0:
131 3ead03bd Andrzej Zaborowski
        qemu_set_irq(i2c->out, i2c->buffer >> 7);
132 3ead03bd Andrzej Zaborowski
        if (clock_goes_down) {
133 3ead03bd Andrzej Zaborowski
            /* will end up in SENDING_ACK */
134 3ead03bd Andrzej Zaborowski
            i2c->state++;
135 3ead03bd Andrzej Zaborowski
            i2c->buffer <<= 1;
136 3ead03bd Andrzej Zaborowski
        } else if (data_goes_up && clock == 1)
137 3ead03bd Andrzej Zaborowski
            bitbang_i2c_enter_stop(i2c);
138 3ead03bd Andrzej Zaborowski
        break;
139 3ead03bd Andrzej Zaborowski
140 3ead03bd Andrzej Zaborowski
    case SENDING_ACK:
141 3ead03bd Andrzej Zaborowski
        if (clock_goes_down) {
142 3ead03bd Andrzej Zaborowski
            i2c->state = RECEIVING_BIT7;
143 3ead03bd Andrzej Zaborowski
            if (data == 0)
144 3ead03bd Andrzej Zaborowski
                i2c->buffer = i2c_recv(i2c->bus);
145 3ead03bd Andrzej Zaborowski
            else
146 3ead03bd Andrzej Zaborowski
                i2c_nack(i2c->bus);
147 3ead03bd Andrzej Zaborowski
        } else if (data_goes_up && clock == 1)
148 3ead03bd Andrzej Zaborowski
            bitbang_i2c_enter_stop(i2c);
149 3ead03bd Andrzej Zaborowski
        break;
150 3ead03bd Andrzej Zaborowski
    }
151 3ead03bd Andrzej Zaborowski
152 3ead03bd Andrzej Zaborowski
    i2c->last_data = data;
153 3ead03bd Andrzej Zaborowski
    i2c->last_clock = clock;
154 3ead03bd Andrzej Zaborowski
}
155 3ead03bd Andrzej Zaborowski
156 3ead03bd Andrzej Zaborowski
static void bitbang_i2c_init(SysBusDevice *dev)
157 3ead03bd Andrzej Zaborowski
{
158 3ead03bd Andrzej Zaborowski
    bitbang_i2c_interface *s = FROM_SYSBUS(bitbang_i2c_interface, dev);
159 3ead03bd Andrzej Zaborowski
    i2c_bus *bus;
160 3ead03bd Andrzej Zaborowski
161 3ead03bd Andrzej Zaborowski
    sysbus_init_mmio(dev, 0x0, 0);
162 3ead03bd Andrzej Zaborowski
163 3ead03bd Andrzej Zaborowski
    bus = i2c_init_bus(&dev->qdev, "i2c");
164 3ead03bd Andrzej Zaborowski
    s->bus = bus;
165 3ead03bd Andrzej Zaborowski
166 3ead03bd Andrzej Zaborowski
    s->last_data = 1;
167 3ead03bd Andrzej Zaborowski
    s->last_clock = 1;
168 3ead03bd Andrzej Zaborowski
169 3ead03bd Andrzej Zaborowski
    qdev_init_gpio_in(&dev->qdev, bitbang_i2c_gpio_set, 2);
170 3ead03bd Andrzej Zaborowski
    qdev_init_gpio_out(&dev->qdev, &s->out, 1);
171 3ead03bd Andrzej Zaborowski
}
172 3ead03bd Andrzej Zaborowski
173 3ead03bd Andrzej Zaborowski
static void bitbang_i2c_register(void)
174 3ead03bd Andrzej Zaborowski
{
175 3ead03bd Andrzej Zaborowski
    sysbus_register_dev("bitbang_i2c",
176 3ead03bd Andrzej Zaborowski
        sizeof(bitbang_i2c_interface), bitbang_i2c_init);
177 3ead03bd Andrzej Zaborowski
}
178 3ead03bd Andrzej Zaborowski
179 3ead03bd Andrzej Zaborowski
device_init(bitbang_i2c_register)