softfloat: Resolve type mismatches between declaration and implementation
[qemu/opensuse.git] / hw / omap_gpio.c
blob478f7d9825318db66336f25e662e281cd499fe0d
1 /*
2 * TI OMAP processors GPIO emulation.
4 * Copyright (C) 2006-2008 Andrzej Zaborowski <balrog@zabor.org>
5 * Copyright (C) 2007-2009 Nokia Corporation
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 or
10 * (at your option) version 3 of the License.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "hw.h"
22 #include "omap.h"
23 /* General-Purpose I/O */
24 struct omap_gpio_s {
25 qemu_irq irq;
26 qemu_irq *in;
27 qemu_irq handler[16];
29 uint16_t inputs;
30 uint16_t outputs;
31 uint16_t dir;
32 uint16_t edge;
33 uint16_t mask;
34 uint16_t ints;
35 uint16_t pins;
38 static void omap_gpio_set(void *opaque, int line, int level)
40 struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
41 uint16_t prev = s->inputs;
43 if (level)
44 s->inputs |= 1 << line;
45 else
46 s->inputs &= ~(1 << line);
48 if (((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) &
49 (1 << line) & s->dir & ~s->mask) {
50 s->ints |= 1 << line;
51 qemu_irq_raise(s->irq);
55 static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
57 struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
58 int offset = addr & OMAP_MPUI_REG_MASK;
60 switch (offset) {
61 case 0x00: /* DATA_INPUT */
62 return s->inputs & s->pins;
64 case 0x04: /* DATA_OUTPUT */
65 return s->outputs;
67 case 0x08: /* DIRECTION_CONTROL */
68 return s->dir;
70 case 0x0c: /* INTERRUPT_CONTROL */
71 return s->edge;
73 case 0x10: /* INTERRUPT_MASK */
74 return s->mask;
76 case 0x14: /* INTERRUPT_STATUS */
77 return s->ints;
79 case 0x18: /* PIN_CONTROL (not in OMAP310) */
80 OMAP_BAD_REG(addr);
81 return s->pins;
84 OMAP_BAD_REG(addr);
85 return 0;
88 static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
89 uint32_t value)
91 struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
92 int offset = addr & OMAP_MPUI_REG_MASK;
93 uint16_t diff;
94 int ln;
96 switch (offset) {
97 case 0x00: /* DATA_INPUT */
98 OMAP_RO_REG(addr);
99 return;
101 case 0x04: /* DATA_OUTPUT */
102 diff = (s->outputs ^ value) & ~s->dir;
103 s->outputs = value;
104 while ((ln = ffs(diff))) {
105 ln --;
106 if (s->handler[ln])
107 qemu_set_irq(s->handler[ln], (value >> ln) & 1);
108 diff &= ~(1 << ln);
110 break;
112 case 0x08: /* DIRECTION_CONTROL */
113 diff = s->outputs & (s->dir ^ value);
114 s->dir = value;
116 value = s->outputs & ~s->dir;
117 while ((ln = ffs(diff))) {
118 ln --;
119 if (s->handler[ln])
120 qemu_set_irq(s->handler[ln], (value >> ln) & 1);
121 diff &= ~(1 << ln);
123 break;
125 case 0x0c: /* INTERRUPT_CONTROL */
126 s->edge = value;
127 break;
129 case 0x10: /* INTERRUPT_MASK */
130 s->mask = value;
131 break;
133 case 0x14: /* INTERRUPT_STATUS */
134 s->ints &= ~value;
135 if (!s->ints)
136 qemu_irq_lower(s->irq);
137 break;
139 case 0x18: /* PIN_CONTROL (not in OMAP310 TRM) */
140 OMAP_BAD_REG(addr);
141 s->pins = value;
142 break;
144 default:
145 OMAP_BAD_REG(addr);
146 return;
150 /* *Some* sources say the memory region is 32-bit. */
151 static CPUReadMemoryFunc * const omap_gpio_readfn[] = {
152 omap_badwidth_read16,
153 omap_gpio_read,
154 omap_badwidth_read16,
157 static CPUWriteMemoryFunc * const omap_gpio_writefn[] = {
158 omap_badwidth_write16,
159 omap_gpio_write,
160 omap_badwidth_write16,
163 void omap_gpio_reset(struct omap_gpio_s *s)
165 s->inputs = 0;
166 s->outputs = ~0;
167 s->dir = ~0;
168 s->edge = ~0;
169 s->mask = ~0;
170 s->ints = 0;
171 s->pins = ~0;
174 struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
175 qemu_irq irq, omap_clk clk)
177 int iomemtype;
178 struct omap_gpio_s *s = (struct omap_gpio_s *)
179 qemu_mallocz(sizeof(struct omap_gpio_s));
181 s->irq = irq;
182 s->in = qemu_allocate_irqs(omap_gpio_set, s, 16);
183 omap_gpio_reset(s);
185 iomemtype = cpu_register_io_memory(omap_gpio_readfn,
186 omap_gpio_writefn, s, DEVICE_NATIVE_ENDIAN);
187 cpu_register_physical_memory(base, 0x1000, iomemtype);
189 return s;
192 qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s)
194 return s->in;
197 void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
199 if (line >= 16 || line < 0)
200 hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
201 s->handler[line] = handler;
204 /* General-Purpose Interface of OMAP2 */
205 struct omap2_gpio_s {
206 qemu_irq irq[2];
207 qemu_irq wkup;
208 qemu_irq *in;
209 qemu_irq handler[32];
211 uint8_t config[2];
212 uint32_t inputs;
213 uint32_t outputs;
214 uint32_t dir;
215 uint32_t level[2];
216 uint32_t edge[2];
217 uint32_t mask[2];
218 uint32_t wumask;
219 uint32_t ints[2];
220 uint32_t debounce;
221 uint8_t delay;
224 static inline void omap2_gpio_module_int_update(struct omap2_gpio_s *s,
225 int line)
227 qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]);
230 static void omap2_gpio_module_wake(struct omap2_gpio_s *s, int line)
232 if (!(s->config[0] & (1 << 2))) /* ENAWAKEUP */
233 return;
234 if (!(s->config[0] & (3 << 3))) /* Force Idle */
235 return;
236 if (!(s->wumask & (1 << line)))
237 return;
239 qemu_irq_raise(s->wkup);
242 static inline void omap2_gpio_module_out_update(struct omap2_gpio_s *s,
243 uint32_t diff)
245 int ln;
247 s->outputs ^= diff;
248 diff &= ~s->dir;
249 while ((ln = ffs(diff))) {
250 ln --;
251 qemu_set_irq(s->handler[ln], (s->outputs >> ln) & 1);
252 diff &= ~(1 << ln);
256 static void omap2_gpio_module_level_update(struct omap2_gpio_s *s, int line)
258 s->ints[line] |= s->dir &
259 ((s->inputs & s->level[1]) | (~s->inputs & s->level[0]));
260 omap2_gpio_module_int_update(s, line);
263 static inline void omap2_gpio_module_int(struct omap2_gpio_s *s, int line)
265 s->ints[0] |= 1 << line;
266 omap2_gpio_module_int_update(s, 0);
267 s->ints[1] |= 1 << line;
268 omap2_gpio_module_int_update(s, 1);
269 omap2_gpio_module_wake(s, line);
272 static void omap2_gpio_module_set(void *opaque, int line, int level)
274 struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
276 if (level) {
277 if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1]))
278 omap2_gpio_module_int(s, line);
279 s->inputs |= 1 << line;
280 } else {
281 if (s->dir & (1 << line) & ((s->inputs & s->edge[1]) | s->level[0]))
282 omap2_gpio_module_int(s, line);
283 s->inputs &= ~(1 << line);
287 static void omap2_gpio_module_reset(struct omap2_gpio_s *s)
289 s->config[0] = 0;
290 s->config[1] = 2;
291 s->ints[0] = 0;
292 s->ints[1] = 0;
293 s->mask[0] = 0;
294 s->mask[1] = 0;
295 s->wumask = 0;
296 s->dir = ~0;
297 s->level[0] = 0;
298 s->level[1] = 0;
299 s->edge[0] = 0;
300 s->edge[1] = 0;
301 s->debounce = 0;
302 s->delay = 0;
305 static uint32_t omap2_gpio_module_read(void *opaque, target_phys_addr_t addr)
307 struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
309 switch (addr) {
310 case 0x00: /* GPIO_REVISION */
311 return 0x18;
313 case 0x10: /* GPIO_SYSCONFIG */
314 return s->config[0];
316 case 0x14: /* GPIO_SYSSTATUS */
317 return 0x01;
319 case 0x18: /* GPIO_IRQSTATUS1 */
320 return s->ints[0];
322 case 0x1c: /* GPIO_IRQENABLE1 */
323 case 0x60: /* GPIO_CLEARIRQENABLE1 */
324 case 0x64: /* GPIO_SETIRQENABLE1 */
325 return s->mask[0];
327 case 0x20: /* GPIO_WAKEUPENABLE */
328 case 0x80: /* GPIO_CLEARWKUENA */
329 case 0x84: /* GPIO_SETWKUENA */
330 return s->wumask;
332 case 0x28: /* GPIO_IRQSTATUS2 */
333 return s->ints[1];
335 case 0x2c: /* GPIO_IRQENABLE2 */
336 case 0x70: /* GPIO_CLEARIRQENABLE2 */
337 case 0x74: /* GPIO_SETIREQNEABLE2 */
338 return s->mask[1];
340 case 0x30: /* GPIO_CTRL */
341 return s->config[1];
343 case 0x34: /* GPIO_OE */
344 return s->dir;
346 case 0x38: /* GPIO_DATAIN */
347 return s->inputs;
349 case 0x3c: /* GPIO_DATAOUT */
350 case 0x90: /* GPIO_CLEARDATAOUT */
351 case 0x94: /* GPIO_SETDATAOUT */
352 return s->outputs;
354 case 0x40: /* GPIO_LEVELDETECT0 */
355 return s->level[0];
357 case 0x44: /* GPIO_LEVELDETECT1 */
358 return s->level[1];
360 case 0x48: /* GPIO_RISINGDETECT */
361 return s->edge[0];
363 case 0x4c: /* GPIO_FALLINGDETECT */
364 return s->edge[1];
366 case 0x50: /* GPIO_DEBOUNCENABLE */
367 return s->debounce;
369 case 0x54: /* GPIO_DEBOUNCINGTIME */
370 return s->delay;
373 OMAP_BAD_REG(addr);
374 return 0;
377 static void omap2_gpio_module_write(void *opaque, target_phys_addr_t addr,
378 uint32_t value)
380 struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
381 uint32_t diff;
382 int ln;
384 switch (addr) {
385 case 0x00: /* GPIO_REVISION */
386 case 0x14: /* GPIO_SYSSTATUS */
387 case 0x38: /* GPIO_DATAIN */
388 OMAP_RO_REG(addr);
389 break;
391 case 0x10: /* GPIO_SYSCONFIG */
392 if (((value >> 3) & 3) == 3)
393 fprintf(stderr, "%s: bad IDLEMODE value\n", __FUNCTION__);
394 if (value & 2)
395 omap2_gpio_module_reset(s);
396 s->config[0] = value & 0x1d;
397 break;
399 case 0x18: /* GPIO_IRQSTATUS1 */
400 if (s->ints[0] & value) {
401 s->ints[0] &= ~value;
402 omap2_gpio_module_level_update(s, 0);
404 break;
406 case 0x1c: /* GPIO_IRQENABLE1 */
407 s->mask[0] = value;
408 omap2_gpio_module_int_update(s, 0);
409 break;
411 case 0x20: /* GPIO_WAKEUPENABLE */
412 s->wumask = value;
413 break;
415 case 0x28: /* GPIO_IRQSTATUS2 */
416 if (s->ints[1] & value) {
417 s->ints[1] &= ~value;
418 omap2_gpio_module_level_update(s, 1);
420 break;
422 case 0x2c: /* GPIO_IRQENABLE2 */
423 s->mask[1] = value;
424 omap2_gpio_module_int_update(s, 1);
425 break;
427 case 0x30: /* GPIO_CTRL */
428 s->config[1] = value & 7;
429 break;
431 case 0x34: /* GPIO_OE */
432 diff = s->outputs & (s->dir ^ value);
433 s->dir = value;
435 value = s->outputs & ~s->dir;
436 while ((ln = ffs(diff))) {
437 diff &= ~(1 <<-- ln);
438 qemu_set_irq(s->handler[ln], (value >> ln) & 1);
441 omap2_gpio_module_level_update(s, 0);
442 omap2_gpio_module_level_update(s, 1);
443 break;
445 case 0x3c: /* GPIO_DATAOUT */
446 omap2_gpio_module_out_update(s, s->outputs ^ value);
447 break;
449 case 0x40: /* GPIO_LEVELDETECT0 */
450 s->level[0] = value;
451 omap2_gpio_module_level_update(s, 0);
452 omap2_gpio_module_level_update(s, 1);
453 break;
455 case 0x44: /* GPIO_LEVELDETECT1 */
456 s->level[1] = value;
457 omap2_gpio_module_level_update(s, 0);
458 omap2_gpio_module_level_update(s, 1);
459 break;
461 case 0x48: /* GPIO_RISINGDETECT */
462 s->edge[0] = value;
463 break;
465 case 0x4c: /* GPIO_FALLINGDETECT */
466 s->edge[1] = value;
467 break;
469 case 0x50: /* GPIO_DEBOUNCENABLE */
470 s->debounce = value;
471 break;
473 case 0x54: /* GPIO_DEBOUNCINGTIME */
474 s->delay = value;
475 break;
477 case 0x60: /* GPIO_CLEARIRQENABLE1 */
478 s->mask[0] &= ~value;
479 omap2_gpio_module_int_update(s, 0);
480 break;
482 case 0x64: /* GPIO_SETIRQENABLE1 */
483 s->mask[0] |= value;
484 omap2_gpio_module_int_update(s, 0);
485 break;
487 case 0x70: /* GPIO_CLEARIRQENABLE2 */
488 s->mask[1] &= ~value;
489 omap2_gpio_module_int_update(s, 1);
490 break;
492 case 0x74: /* GPIO_SETIREQNEABLE2 */
493 s->mask[1] |= value;
494 omap2_gpio_module_int_update(s, 1);
495 break;
497 case 0x80: /* GPIO_CLEARWKUENA */
498 s->wumask &= ~value;
499 break;
501 case 0x84: /* GPIO_SETWKUENA */
502 s->wumask |= value;
503 break;
505 case 0x90: /* GPIO_CLEARDATAOUT */
506 omap2_gpio_module_out_update(s, s->outputs & value);
507 break;
509 case 0x94: /* GPIO_SETDATAOUT */
510 omap2_gpio_module_out_update(s, ~s->outputs & value);
511 break;
513 default:
514 OMAP_BAD_REG(addr);
515 return;
519 static uint32_t omap2_gpio_module_readp(void *opaque, target_phys_addr_t addr)
521 return omap2_gpio_module_readp(opaque, addr) >> ((addr & 3) << 3);
524 static void omap2_gpio_module_writep(void *opaque, target_phys_addr_t addr,
525 uint32_t value)
527 uint32_t cur = 0;
528 uint32_t mask = 0xffff;
530 switch (addr & ~3) {
531 case 0x00: /* GPIO_REVISION */
532 case 0x14: /* GPIO_SYSSTATUS */
533 case 0x38: /* GPIO_DATAIN */
534 OMAP_RO_REG(addr);
535 break;
537 case 0x10: /* GPIO_SYSCONFIG */
538 case 0x1c: /* GPIO_IRQENABLE1 */
539 case 0x20: /* GPIO_WAKEUPENABLE */
540 case 0x2c: /* GPIO_IRQENABLE2 */
541 case 0x30: /* GPIO_CTRL */
542 case 0x34: /* GPIO_OE */
543 case 0x3c: /* GPIO_DATAOUT */
544 case 0x40: /* GPIO_LEVELDETECT0 */
545 case 0x44: /* GPIO_LEVELDETECT1 */
546 case 0x48: /* GPIO_RISINGDETECT */
547 case 0x4c: /* GPIO_FALLINGDETECT */
548 case 0x50: /* GPIO_DEBOUNCENABLE */
549 case 0x54: /* GPIO_DEBOUNCINGTIME */
550 cur = omap2_gpio_module_read(opaque, addr & ~3) &
551 ~(mask << ((addr & 3) << 3));
553 /* Fall through. */
554 case 0x18: /* GPIO_IRQSTATUS1 */
555 case 0x28: /* GPIO_IRQSTATUS2 */
556 case 0x60: /* GPIO_CLEARIRQENABLE1 */
557 case 0x64: /* GPIO_SETIRQENABLE1 */
558 case 0x70: /* GPIO_CLEARIRQENABLE2 */
559 case 0x74: /* GPIO_SETIREQNEABLE2 */
560 case 0x80: /* GPIO_CLEARWKUENA */
561 case 0x84: /* GPIO_SETWKUENA */
562 case 0x90: /* GPIO_CLEARDATAOUT */
563 case 0x94: /* GPIO_SETDATAOUT */
564 value <<= (addr & 3) << 3;
565 omap2_gpio_module_write(opaque, addr, cur | value);
566 break;
568 default:
569 OMAP_BAD_REG(addr);
570 return;
574 static CPUReadMemoryFunc * const omap2_gpio_module_readfn[] = {
575 omap2_gpio_module_readp,
576 omap2_gpio_module_readp,
577 omap2_gpio_module_read,
580 static CPUWriteMemoryFunc * const omap2_gpio_module_writefn[] = {
581 omap2_gpio_module_writep,
582 omap2_gpio_module_writep,
583 omap2_gpio_module_write,
586 static void omap2_gpio_module_init(struct omap2_gpio_s *s,
587 struct omap_target_agent_s *ta, int region,
588 qemu_irq mpu, qemu_irq dsp, qemu_irq wkup,
589 omap_clk fclk, omap_clk iclk)
591 int iomemtype;
593 s->irq[0] = mpu;
594 s->irq[1] = dsp;
595 s->wkup = wkup;
596 s->in = qemu_allocate_irqs(omap2_gpio_module_set, s, 32);
598 iomemtype = l4_register_io_memory(omap2_gpio_module_readfn,
599 omap2_gpio_module_writefn, s);
600 omap_l4_attach(ta, region, iomemtype);
603 struct omap_gpif_s {
604 struct omap2_gpio_s module[5];
605 int modules;
607 int autoidle;
608 int gpo;
611 void omap_gpif_reset(struct omap_gpif_s *s)
613 int i;
615 for (i = 0; i < s->modules; i ++)
616 omap2_gpio_module_reset(s->module + i);
618 s->autoidle = 0;
619 s->gpo = 0;
622 static uint32_t omap_gpif_top_read(void *opaque, target_phys_addr_t addr)
624 struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
626 switch (addr) {
627 case 0x00: /* IPGENERICOCPSPL_REVISION */
628 return 0x18;
630 case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */
631 return s->autoidle;
633 case 0x14: /* IPGENERICOCPSPL_SYSSTATUS */
634 return 0x01;
636 case 0x18: /* IPGENERICOCPSPL_IRQSTATUS */
637 return 0x00;
639 case 0x40: /* IPGENERICOCPSPL_GPO */
640 return s->gpo;
642 case 0x50: /* IPGENERICOCPSPL_GPI */
643 return 0x00;
646 OMAP_BAD_REG(addr);
647 return 0;
650 static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,
651 uint32_t value)
653 struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
655 switch (addr) {
656 case 0x00: /* IPGENERICOCPSPL_REVISION */
657 case 0x14: /* IPGENERICOCPSPL_SYSSTATUS */
658 case 0x18: /* IPGENERICOCPSPL_IRQSTATUS */
659 case 0x50: /* IPGENERICOCPSPL_GPI */
660 OMAP_RO_REG(addr);
661 break;
663 case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */
664 if (value & (1 << 1)) /* SOFTRESET */
665 omap_gpif_reset(s);
666 s->autoidle = value & 1;
667 break;
669 case 0x40: /* IPGENERICOCPSPL_GPO */
670 s->gpo = value & 1;
671 break;
673 default:
674 OMAP_BAD_REG(addr);
675 return;
679 static CPUReadMemoryFunc * const omap_gpif_top_readfn[] = {
680 omap_gpif_top_read,
681 omap_gpif_top_read,
682 omap_gpif_top_read,
685 static CPUWriteMemoryFunc * const omap_gpif_top_writefn[] = {
686 omap_gpif_top_write,
687 omap_gpif_top_write,
688 omap_gpif_top_write,
691 struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
692 qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules)
694 int iomemtype, i;
695 struct omap_gpif_s *s = (struct omap_gpif_s *)
696 qemu_mallocz(sizeof(struct omap_gpif_s));
697 int region[4] = { 0, 2, 4, 5 };
699 s->modules = modules;
700 for (i = 0; i < modules; i ++)
701 omap2_gpio_module_init(s->module + i, ta, region[i],
702 irq[i], NULL, NULL, fclk[i], iclk);
704 omap_gpif_reset(s);
706 iomemtype = l4_register_io_memory(omap_gpif_top_readfn,
707 omap_gpif_top_writefn, s);
708 omap_l4_attach(ta, 1, iomemtype);
710 return s;
713 qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start)
715 if (start >= s->modules * 32 || start < 0)
716 hw_error("%s: No GPIO line %i\n", __FUNCTION__, start);
717 return s->module[start >> 5].in + (start & 31);
720 void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler)
722 if (line >= s->modules * 32 || line < 0)
723 hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
724 s->module[line >> 5].handler[line & 31] = handler;