1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "hw.h"
22#include "omap.h"
23
24struct omap_gpio_s {
25 qemu_irq irq;
26 qemu_irq *in;
27 qemu_irq handler[16];
28
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;
36};
37
38static void omap_gpio_set(void *opaque, int line, int level)
39{
40 struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
41 uint16_t prev = s->inputs;
42
43 if (level)
44 s->inputs |= 1 << line;
45 else
46 s->inputs &= ~(1 << line);
47
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);
52 }
53}
54
55static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
56{
57 struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
58 int offset = addr & OMAP_MPUI_REG_MASK;
59
60 switch (offset) {
61 case 0x00:
62 return s->inputs & s->pins;
63
64 case 0x04:
65 return s->outputs;
66
67 case 0x08:
68 return s->dir;
69
70 case 0x0c:
71 return s->edge;
72
73 case 0x10:
74 return s->mask;
75
76 case 0x14:
77 return s->ints;
78
79 case 0x18:
80 OMAP_BAD_REG(addr);
81 return s->pins;
82 }
83
84 OMAP_BAD_REG(addr);
85 return 0;
86}
87
88static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
89 uint32_t value)
90{
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;
95
96 switch (offset) {
97 case 0x00:
98 OMAP_RO_REG(addr);
99 return;
100
101 case 0x04:
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);
109 }
110 break;
111
112 case 0x08:
113 diff = s->outputs & (s->dir ^ value);
114 s->dir = value;
115
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);
122 }
123 break;
124
125 case 0x0c:
126 s->edge = value;
127 break;
128
129 case 0x10:
130 s->mask = value;
131 break;
132
133 case 0x14:
134 s->ints &= ~value;
135 if (!s->ints)
136 qemu_irq_lower(s->irq);
137 break;
138
139 case 0x18:
140 OMAP_BAD_REG(addr);
141 s->pins = value;
142 break;
143
144 default:
145 OMAP_BAD_REG(addr);
146 return;
147 }
148}
149
150
151static CPUReadMemoryFunc * const omap_gpio_readfn[] = {
152 omap_badwidth_read16,
153 omap_gpio_read,
154 omap_badwidth_read16,
155};
156
157static CPUWriteMemoryFunc * const omap_gpio_writefn[] = {
158 omap_badwidth_write16,
159 omap_gpio_write,
160 omap_badwidth_write16,
161};
162
163void omap_gpio_reset(struct omap_gpio_s *s)
164{
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;
172}
173
174struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
175 qemu_irq irq, omap_clk clk)
176{
177 int iomemtype;
178 struct omap_gpio_s *s = (struct omap_gpio_s *)
179 qemu_mallocz(sizeof(struct omap_gpio_s));
180
181 s->irq = irq;
182 s->in = qemu_allocate_irqs(omap_gpio_set, s, 16);
183 omap_gpio_reset(s);
184
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);
188
189 return s;
190}
191
192qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s)
193{
194 return s->in;
195}
196
197void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
198{
199 if (line >= 16 || line < 0)
200 hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
201 s->handler[line] = handler;
202}
203
204
205struct omap2_gpio_s {
206 qemu_irq irq[2];
207 qemu_irq wkup;
208 qemu_irq *in;
209 qemu_irq handler[32];
210
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;
222};
223
224static inline void omap2_gpio_module_int_update(struct omap2_gpio_s *s,
225 int line)
226{
227 qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]);
228}
229
230static void omap2_gpio_module_wake(struct omap2_gpio_s *s, int line)
231{
232 if (!(s->config[0] & (1 << 2)))
233 return;
234 if (!(s->config[0] & (3 << 3)))
235 return;
236 if (!(s->wumask & (1 << line)))
237 return;
238
239 qemu_irq_raise(s->wkup);
240}
241
242static inline void omap2_gpio_module_out_update(struct omap2_gpio_s *s,
243 uint32_t diff)
244{
245 int ln;
246
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);
253 }
254}
255
256static void omap2_gpio_module_level_update(struct omap2_gpio_s *s, int line)
257{
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);
261}
262
263static inline void omap2_gpio_module_int(struct omap2_gpio_s *s, int line)
264{
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);
270}
271
272static void omap2_gpio_module_set(void *opaque, int line, int level)
273{
274 struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
275
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);
284 }
285}
286
287static void omap2_gpio_module_reset(struct omap2_gpio_s *s)
288{
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;
303}
304
305static uint32_t omap2_gpio_module_read(void *opaque, target_phys_addr_t addr)
306{
307 struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
308
309 switch (addr) {
310 case 0x00:
311 return 0x18;
312
313 case 0x10:
314 return s->config[0];
315
316 case 0x14:
317 return 0x01;
318
319 case 0x18:
320 return s->ints[0];
321
322 case 0x1c:
323 case 0x60:
324 case 0x64:
325 return s->mask[0];
326
327 case 0x20:
328 case 0x80:
329 case 0x84:
330 return s->wumask;
331
332 case 0x28:
333 return s->ints[1];
334
335 case 0x2c:
336 case 0x70:
337 case 0x74:
338 return s->mask[1];
339
340 case 0x30:
341 return s->config[1];
342
343 case 0x34:
344 return s->dir;
345
346 case 0x38:
347 return s->inputs;
348
349 case 0x3c:
350 case 0x90:
351 case 0x94:
352 return s->outputs;
353
354 case 0x40:
355 return s->level[0];
356
357 case 0x44:
358 return s->level[1];
359
360 case 0x48:
361 return s->edge[0];
362
363 case 0x4c:
364 return s->edge[1];
365
366 case 0x50:
367 return s->debounce;
368
369 case 0x54:
370 return s->delay;
371 }
372
373 OMAP_BAD_REG(addr);
374 return 0;
375}
376
377static void omap2_gpio_module_write(void *opaque, target_phys_addr_t addr,
378 uint32_t value)
379{
380 struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
381 uint32_t diff;
382 int ln;
383
384 switch (addr) {
385 case 0x00:
386 case 0x14:
387 case 0x38:
388 OMAP_RO_REG(addr);
389 break;
390
391 case 0x10:
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;
398
399 case 0x18:
400 if (s->ints[0] & value) {
401 s->ints[0] &= ~value;
402 omap2_gpio_module_level_update(s, 0);
403 }
404 break;
405
406 case 0x1c:
407 s->mask[0] = value;
408 omap2_gpio_module_int_update(s, 0);
409 break;
410
411 case 0x20:
412 s->wumask = value;
413 break;
414
415 case 0x28:
416 if (s->ints[1] & value) {
417 s->ints[1] &= ~value;
418 omap2_gpio_module_level_update(s, 1);
419 }
420 break;
421
422 case 0x2c:
423 s->mask[1] = value;
424 omap2_gpio_module_int_update(s, 1);
425 break;
426
427 case 0x30:
428 s->config[1] = value & 7;
429 break;
430
431 case 0x34:
432 diff = s->outputs & (s->dir ^ value);
433 s->dir = value;
434
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);
439 }
440
441 omap2_gpio_module_level_update(s, 0);
442 omap2_gpio_module_level_update(s, 1);
443 break;
444
445 case 0x3c:
446 omap2_gpio_module_out_update(s, s->outputs ^ value);
447 break;
448
449 case 0x40:
450 s->level[0] = value;
451 omap2_gpio_module_level_update(s, 0);
452 omap2_gpio_module_level_update(s, 1);
453 break;
454
455 case 0x44:
456 s->level[1] = value;
457 omap2_gpio_module_level_update(s, 0);
458 omap2_gpio_module_level_update(s, 1);
459 break;
460
461 case 0x48:
462 s->edge[0] = value;
463 break;
464
465 case 0x4c:
466 s->edge[1] = value;
467 break;
468
469 case 0x50:
470 s->debounce = value;
471 break;
472
473 case 0x54:
474 s->delay = value;
475 break;
476
477 case 0x60:
478 s->mask[0] &= ~value;
479 omap2_gpio_module_int_update(s, 0);
480 break;
481
482 case 0x64:
483 s->mask[0] |= value;
484 omap2_gpio_module_int_update(s, 0);
485 break;
486
487 case 0x70:
488 s->mask[1] &= ~value;
489 omap2_gpio_module_int_update(s, 1);
490 break;
491
492 case 0x74:
493 s->mask[1] |= value;
494 omap2_gpio_module_int_update(s, 1);
495 break;
496
497 case 0x80:
498 s->wumask &= ~value;
499 break;
500
501 case 0x84:
502 s->wumask |= value;
503 break;
504
505 case 0x90:
506 omap2_gpio_module_out_update(s, s->outputs & value);
507 break;
508
509 case 0x94:
510 omap2_gpio_module_out_update(s, ~s->outputs & value);
511 break;
512
513 default:
514 OMAP_BAD_REG(addr);
515 return;
516 }
517}
518
519static uint32_t omap2_gpio_module_readp(void *opaque, target_phys_addr_t addr)
520{
521 return omap2_gpio_module_readp(opaque, addr) >> ((addr & 3) << 3);
522}
523
524static void omap2_gpio_module_writep(void *opaque, target_phys_addr_t addr,
525 uint32_t value)
526{
527 uint32_t cur = 0;
528 uint32_t mask = 0xffff;
529
530 switch (addr & ~3) {
531 case 0x00:
532 case 0x14:
533 case 0x38:
534 OMAP_RO_REG(addr);
535 break;
536
537 case 0x10:
538 case 0x1c:
539 case 0x20:
540 case 0x2c:
541 case 0x30:
542 case 0x34:
543 case 0x3c:
544 case 0x40:
545 case 0x44:
546 case 0x48:
547 case 0x4c:
548 case 0x50:
549 case 0x54:
550 cur = omap2_gpio_module_read(opaque, addr & ~3) &
551 ~(mask << ((addr & 3) << 3));
552
553
554 case 0x18:
555 case 0x28:
556 case 0x60:
557 case 0x64:
558 case 0x70:
559 case 0x74:
560 case 0x80:
561 case 0x84:
562 case 0x90:
563 case 0x94:
564 value <<= (addr & 3) << 3;
565 omap2_gpio_module_write(opaque, addr, cur | value);
566 break;
567
568 default:
569 OMAP_BAD_REG(addr);
570 return;
571 }
572}
573
574static CPUReadMemoryFunc * const omap2_gpio_module_readfn[] = {
575 omap2_gpio_module_readp,
576 omap2_gpio_module_readp,
577 omap2_gpio_module_read,
578};
579
580static CPUWriteMemoryFunc * const omap2_gpio_module_writefn[] = {
581 omap2_gpio_module_writep,
582 omap2_gpio_module_writep,
583 omap2_gpio_module_write,
584};
585
586static 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)
590{
591 int iomemtype;
592
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);
597
598 iomemtype = l4_register_io_memory(omap2_gpio_module_readfn,
599 omap2_gpio_module_writefn, s);
600 omap_l4_attach(ta, region, iomemtype);
601}
602
603struct omap_gpif_s {
604 struct omap2_gpio_s module[5];
605 int modules;
606
607 int autoidle;
608 int gpo;
609};
610
611void omap_gpif_reset(struct omap_gpif_s *s)
612{
613 int i;
614
615 for (i = 0; i < s->modules; i ++)
616 omap2_gpio_module_reset(s->module + i);
617
618 s->autoidle = 0;
619 s->gpo = 0;
620}
621
622static uint32_t omap_gpif_top_read(void *opaque, target_phys_addr_t addr)
623{
624 struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
625
626 switch (addr) {
627 case 0x00:
628 return 0x18;
629
630 case 0x10:
631 return s->autoidle;
632
633 case 0x14:
634 return 0x01;
635
636 case 0x18:
637 return 0x00;
638
639 case 0x40:
640 return s->gpo;
641
642 case 0x50:
643 return 0x00;
644 }
645
646 OMAP_BAD_REG(addr);
647 return 0;
648}
649
650static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,
651 uint32_t value)
652{
653 struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
654
655 switch (addr) {
656 case 0x00:
657 case 0x14:
658 case 0x18:
659 case 0x50:
660 OMAP_RO_REG(addr);
661 break;
662
663 case 0x10:
664 if (value & (1 << 1))
665 omap_gpif_reset(s);
666 s->autoidle = value & 1;
667 break;
668
669 case 0x40:
670 s->gpo = value & 1;
671 break;
672
673 default:
674 OMAP_BAD_REG(addr);
675 return;
676 }
677}
678
679static CPUReadMemoryFunc * const omap_gpif_top_readfn[] = {
680 omap_gpif_top_read,
681 omap_gpif_top_read,
682 omap_gpif_top_read,
683};
684
685static CPUWriteMemoryFunc * const omap_gpif_top_writefn[] = {
686 omap_gpif_top_write,
687 omap_gpif_top_write,
688 omap_gpif_top_write,
689};
690
691struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
692 qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules)
693{
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 };
698
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);
703
704 omap_gpif_reset(s);
705
706 iomemtype = l4_register_io_memory(omap_gpif_top_readfn,
707 omap_gpif_top_writefn, s);
708 omap_l4_attach(ta, 1, iomemtype);
709
710 return s;
711}
712
713qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start)
714{
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);
718}
719
720void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler)
721{
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;
725}
726