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