1:
2:
3:
4:
5:
6:
7:
8:
9:
10: #include "hw.h"
11: #include "i2c.h"
12:
13: struct max7310_s {
14: i2c_slave i2c;
15: int i2c_command_byte;
16: int len;
17:
18: uint8_t level;
19: uint8_t direction;
20: uint8_t polarity;
21: uint8_t status;
22: uint8_t command;
23: qemu_irq handler[8];
24: qemu_irq *gpio_in;
25: };
26:
27: void max7310_reset(i2c_slave *i2c)
28: {
29: struct max7310_s *s = (struct max7310_s *) i2c;
30: s->level &= s->direction;
31: s->direction = 0xff;
32: s->polarity = 0xf0;
33: s->status = 0x01;
34: s->command = 0x00;
35: }
36:
37: static int max7310_rx(i2c_slave *i2c)
38: {
39: struct max7310_s *s = (struct max7310_s *) i2c;
40:
41: switch (s->command) {
42: case 0x00:
43: return s->level ^ s->polarity;
44: break;
45:
46: case 0x01:
47: return s->level & ~s->direction;
48: break;
49:
50: case 0x02:
51: return s->polarity;
52:
53: case 0x03:
54: return s->direction;
55:
56: case 0x04:
57: return s->status;
58: break;
59:
60: case 0xff:
61: return 0xff;
62:
63: default:
64: #ifdef VERBOSE
65: printf("%s: unknown register %02x\n", __FUNCTION__, s->command);
66: #endif
67: break;
68: }
69: return 0xff;
70: }
71:
72: static int max7310_tx(i2c_slave *i2c, uint8_t data)
73: {
74: struct max7310_s *s = (struct max7310_s *) i2c;
75: uint8_t diff;
76: int line;
77:
78: if (s->len ++ > 1) {
79: #ifdef VERBOSE
80: printf("%s: message too long (%i bytes)\n", __FUNCTION__, s->len);
81: #endif
82: return 1;
83: }
84:
85: if (s->i2c_command_byte) {
86: s->command = data;
87: s->i2c_command_byte = 0;
88: return 0;
89: }
90:
91: switch (s->command) {
92: case 0x01:
93: for (diff = (data ^ s->level) & ~s->direction; diff;
94: diff &= ~(1 << line)) {
95: line = ffs(diff) - 1;
96: if (s->handler[line])
97: qemu_set_irq(s->handler[line], (data >> line) & 1);
98: }
99: s->level = (s->level & s->direction) | (data & ~s->direction);
100: break;
101:
102: case 0x02:
103: s->polarity = data;
104: break;
105:
106: case 0x03:
107: s->level &= ~(s->direction ^ data);
108: s->direction = data;
109: break;
110:
111: case 0x04:
112: s->status = data;
113: break;
114:
115: case 0x00:
116: break;
117: default:
118: #ifdef VERBOSE
119: printf("%s: unknown register %02x\n", __FUNCTION__, s->command);
120: #endif
121: return 1;
122: }
123:
124: return 0;
125: }
126:
127: static void max7310_event(i2c_slave *i2c, enum i2c_event event)
128: {
129: struct max7310_s *s = (struct max7310_s *) i2c;
130: s->len = 0;
131:
132: switch (event) {
133: case I2C_START_SEND:
134: s->i2c_command_byte = 1;
135: break;
136: case I2C_FINISH:
137: if (s->len == 1)
138: #ifdef VERBOSE
139: printf("%s: message too short (%i bytes)\n", __FUNCTION__, s->len);
140: #endif
141: break;
142: default:
143: break;
144: }
145: }
146:
147: static void max7310_save(QEMUFile *f, void *opaque)
148: {
149: struct max7310_s *s = (struct max7310_s *) opaque;
150:
151: qemu_put_be32(f, s->i2c_command_byte);
152: qemu_put_be32(f, s->len);
153:
154: qemu_put_8s(f, &s->level);
155: qemu_put_8s(f, &s->direction);
156: qemu_put_8s(f, &s->polarity);
157: qemu_put_8s(f, &s->status);
158: qemu_put_8s(f, &s->command);
159:
160: i2c_slave_save(f, &s->i2c);
161: }
162:
163: static int max7310_load(QEMUFile *f, void *opaque, int version_id)
164: {
165: struct max7310_s *s = (struct max7310_s *) opaque;
166:
167: s->i2c_command_byte = qemu_get_be32(f);
168: s->len = qemu_get_be32(f);
169:
170: qemu_get_8s(f, &s->level);
171: qemu_get_8s(f, &s->direction);
172: qemu_get_8s(f, &s->polarity);
173: qemu_get_8s(f, &s->status);
174: qemu_get_8s(f, &s->command);
175:
176: i2c_slave_load(f, &s->i2c);
177: return 0;
178: }
179:
180: static int max7310_iid = 0;
181:
182: static void max7310_gpio_set(void *opaque, int line, int level)
183: {
184: struct max7310_s *s = (struct max7310_s *) opaque;
185: if (line >= sizeof(s->handler) / sizeof(*s->handler) || line < 0)
186: hw_error("bad GPIO line");
187:
188: if (level)
189: s->level |= s->direction & (1 << line);
190: else
191: s->level &= ~(s->direction & (1 << line));
192: }
193:
194:
195:
196: struct i2c_slave *max7310_init(i2c_bus *bus)
197: {
198: struct max7310_s *s = (struct max7310_s *)
199: i2c_slave_init(bus, 0, sizeof(struct max7310_s));
200: s->i2c.event = max7310_event;
201: s->i2c.recv = max7310_rx;
202: s->i2c.send = max7310_tx;
203: s->gpio_in = qemu_allocate_irqs(max7310_gpio_set, s,
204: sizeof(s->handler) / sizeof(*s->handler));
205:
206: max7310_reset(&s->i2c);
207:
208: register_savevm("max7310", max7310_iid ++, 0,
209: max7310_save, max7310_load, s);
210:
211: return &s->i2c;
212: }
213:
214: qemu_irq *max7310_gpio_in_get(i2c_slave *i2c)
215: {
216: struct max7310_s *s = (struct max7310_s *) i2c;
217: return s->gpio_in;
218: }
219:
220: void max7310_gpio_out_set(i2c_slave *i2c, int line, qemu_irq handler)
221: {
222: struct max7310_s *s = (struct max7310_s *) i2c;
223: if (line >= sizeof(s->handler) / sizeof(*s->handler) || line < 0)
224: hw_error("bad GPIO line");
225:
226: s->handler[line] = handler;
227: }