Revision 38641a52 hw/pxa2xx_gpio.c
b/hw/pxa2xx_gpio.c | ||
---|---|---|
16 | 16 |
qemu_irq *pic; |
17 | 17 |
int lines; |
18 | 18 |
CPUState *cpu_env; |
19 |
qemu_irq *in; |
|
19 | 20 |
|
20 | 21 |
/* XXX: GNU C vectors are more suitable */ |
21 | 22 |
uint32_t ilevel[PXA2XX_GPIO_BANKS]; |
... | ... | |
28 | 29 |
uint32_t gafr[PXA2XX_GPIO_BANKS * 2]; |
29 | 30 |
|
30 | 31 |
uint32_t prev_level[PXA2XX_GPIO_BANKS]; |
31 |
struct { |
|
32 |
gpio_handler_t fn; |
|
33 |
void *opaque; |
|
34 |
} handler[PXA2XX_GPIO_BANKS * 32]; |
|
35 |
|
|
36 |
void (*read_notify)(void *opaque); |
|
37 |
void *opaque; |
|
32 |
qemu_irq handler[PXA2XX_GPIO_BANKS * 32]; |
|
33 |
qemu_irq read_notify; |
|
38 | 34 |
}; |
39 | 35 |
|
40 | 36 |
static struct { |
... | ... | |
86 | 82 |
} |
87 | 83 |
|
88 | 84 |
/* Bitmap of pins used as standby and sleep wake-up sources. */ |
89 |
const int pxa2xx_gpio_wake[PXA2XX_GPIO_BANKS] = { |
|
85 |
static const int pxa2xx_gpio_wake[PXA2XX_GPIO_BANKS] = {
|
|
90 | 86 |
0x8003fe1b, 0x002001fc, 0xec080000, 0x0012007f, |
91 | 87 |
}; |
92 | 88 |
|
93 |
void pxa2xx_gpio_set(struct pxa2xx_gpio_info_s *s, int line, int level)
|
|
89 |
static void pxa2xx_gpio_set(void *opaque, int line, int level)
|
|
94 | 90 |
{ |
91 |
struct pxa2xx_gpio_info_s *s = (struct pxa2xx_gpio_info_s *) opaque; |
|
95 | 92 |
int bank; |
96 | 93 |
uint32_t mask; |
97 | 94 |
|
... | ... | |
130 | 127 |
for (diff = s->prev_level[i] ^ level; diff; diff ^= 1 << bit) { |
131 | 128 |
bit = ffs(diff) - 1; |
132 | 129 |
line = bit + 32 * i; |
133 |
if (s->handler[line].fn) |
|
134 |
s->handler[line].fn(line, (level >> bit) & 1, |
|
135 |
s->handler[line].opaque); |
|
130 |
qemu_set_irq(s->handler[line], (level >> bit) & 1); |
|
136 | 131 |
} |
137 | 132 |
|
138 | 133 |
s->prev_level[i] = level; |
... | ... | |
173 | 168 |
case GPLR: /* GPIO Pin-Level registers */ |
174 | 169 |
ret = (s->olevel[bank] & s->dir[bank]) | |
175 | 170 |
(s->ilevel[bank] & ~s->dir[bank]); |
176 |
if (s->read_notify) |
|
177 |
s->read_notify(s->opaque); |
|
171 |
qemu_irq_raise(s->read_notify); |
|
178 | 172 |
return ret; |
179 | 173 |
|
180 | 174 |
case GEDR: /* GPIO Edge Detect Status registers */ |
... | ... | |
312 | 306 |
s->pic = pic; |
313 | 307 |
s->lines = lines; |
314 | 308 |
s->cpu_env = env; |
309 |
s->in = qemu_allocate_irqs(pxa2xx_gpio_set, s, lines); |
|
315 | 310 |
|
316 | 311 |
iomemtype = cpu_register_io_memory(0, pxa2xx_gpio_readfn, |
317 | 312 |
pxa2xx_gpio_writefn, s); |
... | ... | |
323 | 318 |
return s; |
324 | 319 |
} |
325 | 320 |
|
326 |
void pxa2xx_gpio_handler_set(struct pxa2xx_gpio_info_s *s, int line, |
|
327 |
gpio_handler_t handler, void *opaque) { |
|
321 |
qemu_irq *pxa2xx_gpio_in_get(struct pxa2xx_gpio_info_s *s) |
|
322 |
{ |
|
323 |
return s->in; |
|
324 |
} |
|
325 |
|
|
326 |
void pxa2xx_gpio_out_set(struct pxa2xx_gpio_info_s *s, |
|
327 |
int line, qemu_irq handler) |
|
328 |
{ |
|
328 | 329 |
if (line >= s->lines) { |
329 | 330 |
printf("%s: No GPIO pin %i\n", __FUNCTION__, line); |
330 | 331 |
return; |
331 | 332 |
} |
332 | 333 |
|
333 |
s->handler[line].fn = handler; |
|
334 |
s->handler[line].opaque = opaque; |
|
334 |
s->handler[line] = handler; |
|
335 | 335 |
} |
336 | 336 |
|
337 | 337 |
/* |
338 | 338 |
* Registers a callback to notify on GPLR reads. This normally |
339 | 339 |
* shouldn't be needed but it is used for the hack on Spitz machines. |
340 | 340 |
*/ |
341 |
void pxa2xx_gpio_read_notifier(struct pxa2xx_gpio_info_s *s, |
|
342 |
void (*handler)(void *opaque), void *opaque) {
|
|
341 |
void pxa2xx_gpio_read_notifier(struct pxa2xx_gpio_info_s *s, qemu_irq handler)
|
|
342 |
{ |
|
343 | 343 |
s->read_notify = handler; |
344 |
s->opaque = opaque; |
|
345 | 344 |
} |
Also available in: Unified diff