|
|
1.1 root 1: /*
2: * TI OMAP processors GPIO emulation.
3: *
4: * Copyright (C) 2006-2008 Andrzej Zaborowski <[email protected]>
5: * Copyright (C) 2007-2009 Nokia Corporation
6: *
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.
11: *
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.
16: *
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/>.
19: */
20:
21: #include "hw.h"
22: #include "omap.h"
1.1.1.3 root 23: #include "sysbus.h"
24:
1.1 root 25: struct omap_gpio_s {
26: qemu_irq irq;
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:
1.1.1.3 root 38: struct omap_gpif_s {
39: SysBusDevice busdev;
1.1.1.4 ! root 40: MemoryRegion iomem;
1.1.1.3 root 41: int mpu_model;
42: void *clk;
43: struct omap_gpio_s omap1;
44: };
45:
46: /* General-Purpose I/O of OMAP1 */
1.1 root 47: static void omap_gpio_set(void *opaque, int line, int level)
48: {
1.1.1.3 root 49: struct omap_gpio_s *s = &((struct omap_gpif_s *) opaque)->omap1;
1.1 root 50: uint16_t prev = s->inputs;
51:
52: if (level)
53: s->inputs |= 1 << line;
54: else
55: s->inputs &= ~(1 << line);
56:
57: if (((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) &
58: (1 << line) & s->dir & ~s->mask) {
59: s->ints |= 1 << line;
60: qemu_irq_raise(s->irq);
61: }
62: }
63:
1.1.1.4 ! root 64: static uint64_t omap_gpio_read(void *opaque, target_phys_addr_t addr,
! 65: unsigned size)
1.1 root 66: {
67: struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
68: int offset = addr & OMAP_MPUI_REG_MASK;
69:
1.1.1.4 ! root 70: if (size != 2) {
! 71: return omap_badwidth_read16(opaque, addr);
! 72: }
! 73:
1.1 root 74: switch (offset) {
75: case 0x00: /* DATA_INPUT */
76: return s->inputs & s->pins;
77:
78: case 0x04: /* DATA_OUTPUT */
79: return s->outputs;
80:
81: case 0x08: /* DIRECTION_CONTROL */
82: return s->dir;
83:
84: case 0x0c: /* INTERRUPT_CONTROL */
85: return s->edge;
86:
87: case 0x10: /* INTERRUPT_MASK */
88: return s->mask;
89:
90: case 0x14: /* INTERRUPT_STATUS */
91: return s->ints;
92:
93: case 0x18: /* PIN_CONTROL (not in OMAP310) */
94: OMAP_BAD_REG(addr);
95: return s->pins;
96: }
97:
98: OMAP_BAD_REG(addr);
99: return 0;
100: }
101:
102: static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
1.1.1.4 ! root 103: uint64_t value, unsigned size)
1.1 root 104: {
105: struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
106: int offset = addr & OMAP_MPUI_REG_MASK;
107: uint16_t diff;
108: int ln;
109:
1.1.1.4 ! root 110: if (size != 2) {
! 111: return omap_badwidth_write16(opaque, addr, value);
! 112: }
! 113:
1.1 root 114: switch (offset) {
115: case 0x00: /* DATA_INPUT */
116: OMAP_RO_REG(addr);
117: return;
118:
119: case 0x04: /* DATA_OUTPUT */
120: diff = (s->outputs ^ value) & ~s->dir;
121: s->outputs = value;
122: while ((ln = ffs(diff))) {
123: ln --;
124: if (s->handler[ln])
125: qemu_set_irq(s->handler[ln], (value >> ln) & 1);
126: diff &= ~(1 << ln);
127: }
128: break;
129:
130: case 0x08: /* DIRECTION_CONTROL */
131: diff = s->outputs & (s->dir ^ value);
132: s->dir = value;
133:
134: value = s->outputs & ~s->dir;
135: while ((ln = ffs(diff))) {
136: ln --;
137: if (s->handler[ln])
138: qemu_set_irq(s->handler[ln], (value >> ln) & 1);
139: diff &= ~(1 << ln);
140: }
141: break;
142:
143: case 0x0c: /* INTERRUPT_CONTROL */
144: s->edge = value;
145: break;
146:
147: case 0x10: /* INTERRUPT_MASK */
148: s->mask = value;
149: break;
150:
151: case 0x14: /* INTERRUPT_STATUS */
152: s->ints &= ~value;
153: if (!s->ints)
154: qemu_irq_lower(s->irq);
155: break;
156:
157: case 0x18: /* PIN_CONTROL (not in OMAP310 TRM) */
158: OMAP_BAD_REG(addr);
159: s->pins = value;
160: break;
161:
162: default:
163: OMAP_BAD_REG(addr);
164: return;
165: }
166: }
167:
168: /* *Some* sources say the memory region is 32-bit. */
1.1.1.4 ! root 169: static const MemoryRegionOps omap_gpio_ops = {
! 170: .read = omap_gpio_read,
! 171: .write = omap_gpio_write,
! 172: .endianness = DEVICE_NATIVE_ENDIAN,
1.1 root 173: };
174:
1.1.1.3 root 175: static void omap_gpio_reset(struct omap_gpio_s *s)
1.1 root 176: {
177: s->inputs = 0;
178: s->outputs = ~0;
179: s->dir = ~0;
180: s->edge = ~0;
181: s->mask = ~0;
182: s->ints = 0;
183: s->pins = ~0;
184: }
185:
186: struct omap2_gpio_s {
187: qemu_irq irq[2];
188: qemu_irq wkup;
1.1.1.3 root 189: qemu_irq *handler;
1.1.1.4 ! root 190: MemoryRegion iomem;
1.1 root 191:
1.1.1.3 root 192: uint8_t revision;
1.1 root 193: uint8_t config[2];
194: uint32_t inputs;
195: uint32_t outputs;
196: uint32_t dir;
197: uint32_t level[2];
198: uint32_t edge[2];
199: uint32_t mask[2];
200: uint32_t wumask;
201: uint32_t ints[2];
202: uint32_t debounce;
203: uint8_t delay;
204: };
205:
1.1.1.3 root 206: struct omap2_gpif_s {
207: SysBusDevice busdev;
1.1.1.4 ! root 208: MemoryRegion iomem;
1.1.1.3 root 209: int mpu_model;
210: void *iclk;
211: void *fclk[6];
212: int modulecount;
213: struct omap2_gpio_s *modules;
214: qemu_irq *handler;
215: int autoidle;
216: int gpo;
217: };
218:
219: /* General-Purpose Interface of OMAP2/3 */
1.1 root 220: static inline void omap2_gpio_module_int_update(struct omap2_gpio_s *s,
1.1.1.3 root 221: int line)
1.1 root 222: {
223: qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]);
224: }
225:
226: static void omap2_gpio_module_wake(struct omap2_gpio_s *s, int line)
227: {
228: if (!(s->config[0] & (1 << 2))) /* ENAWAKEUP */
229: return;
230: if (!(s->config[0] & (3 << 3))) /* Force Idle */
231: return;
232: if (!(s->wumask & (1 << line)))
233: return;
234:
235: qemu_irq_raise(s->wkup);
236: }
237:
238: static inline void omap2_gpio_module_out_update(struct omap2_gpio_s *s,
239: uint32_t diff)
240: {
241: int ln;
242:
243: s->outputs ^= diff;
244: diff &= ~s->dir;
245: while ((ln = ffs(diff))) {
246: ln --;
247: qemu_set_irq(s->handler[ln], (s->outputs >> ln) & 1);
248: diff &= ~(1 << ln);
249: }
250: }
251:
252: static void omap2_gpio_module_level_update(struct omap2_gpio_s *s, int line)
253: {
254: s->ints[line] |= s->dir &
255: ((s->inputs & s->level[1]) | (~s->inputs & s->level[0]));
256: omap2_gpio_module_int_update(s, line);
257: }
258:
259: static inline void omap2_gpio_module_int(struct omap2_gpio_s *s, int line)
260: {
261: s->ints[0] |= 1 << line;
262: omap2_gpio_module_int_update(s, 0);
263: s->ints[1] |= 1 << line;
264: omap2_gpio_module_int_update(s, 1);
265: omap2_gpio_module_wake(s, line);
266: }
267:
1.1.1.3 root 268: static void omap2_gpio_set(void *opaque, int line, int level)
1.1 root 269: {
1.1.1.3 root 270: struct omap2_gpif_s *p = opaque;
271: struct omap2_gpio_s *s = &p->modules[line >> 5];
1.1 root 272:
1.1.1.3 root 273: line &= 31;
1.1 root 274: if (level) {
275: if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1]))
276: omap2_gpio_module_int(s, line);
277: s->inputs |= 1 << line;
278: } else {
279: if (s->dir & (1 << line) & ((s->inputs & s->edge[1]) | s->level[0]))
280: omap2_gpio_module_int(s, line);
281: s->inputs &= ~(1 << line);
282: }
283: }
284:
285: static void omap2_gpio_module_reset(struct omap2_gpio_s *s)
286: {
287: s->config[0] = 0;
288: s->config[1] = 2;
289: s->ints[0] = 0;
290: s->ints[1] = 0;
291: s->mask[0] = 0;
292: s->mask[1] = 0;
293: s->wumask = 0;
294: s->dir = ~0;
295: s->level[0] = 0;
296: s->level[1] = 0;
297: s->edge[0] = 0;
298: s->edge[1] = 0;
299: s->debounce = 0;
300: s->delay = 0;
301: }
302:
303: static uint32_t omap2_gpio_module_read(void *opaque, target_phys_addr_t addr)
304: {
305: struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
306:
307: switch (addr) {
308: case 0x00: /* GPIO_REVISION */
1.1.1.3 root 309: return s->revision;
1.1 root 310:
311: case 0x10: /* GPIO_SYSCONFIG */
312: return s->config[0];
313:
314: case 0x14: /* GPIO_SYSSTATUS */
315: return 0x01;
316:
317: case 0x18: /* GPIO_IRQSTATUS1 */
318: return s->ints[0];
319:
320: case 0x1c: /* GPIO_IRQENABLE1 */
321: case 0x60: /* GPIO_CLEARIRQENABLE1 */
322: case 0x64: /* GPIO_SETIRQENABLE1 */
323: return s->mask[0];
324:
325: case 0x20: /* GPIO_WAKEUPENABLE */
326: case 0x80: /* GPIO_CLEARWKUENA */
327: case 0x84: /* GPIO_SETWKUENA */
328: return s->wumask;
329:
330: case 0x28: /* GPIO_IRQSTATUS2 */
331: return s->ints[1];
332:
333: case 0x2c: /* GPIO_IRQENABLE2 */
334: case 0x70: /* GPIO_CLEARIRQENABLE2 */
335: case 0x74: /* GPIO_SETIREQNEABLE2 */
336: return s->mask[1];
337:
338: case 0x30: /* GPIO_CTRL */
339: return s->config[1];
340:
341: case 0x34: /* GPIO_OE */
342: return s->dir;
343:
344: case 0x38: /* GPIO_DATAIN */
345: return s->inputs;
346:
347: case 0x3c: /* GPIO_DATAOUT */
348: case 0x90: /* GPIO_CLEARDATAOUT */
349: case 0x94: /* GPIO_SETDATAOUT */
350: return s->outputs;
351:
352: case 0x40: /* GPIO_LEVELDETECT0 */
353: return s->level[0];
354:
355: case 0x44: /* GPIO_LEVELDETECT1 */
356: return s->level[1];
357:
358: case 0x48: /* GPIO_RISINGDETECT */
359: return s->edge[0];
360:
361: case 0x4c: /* GPIO_FALLINGDETECT */
362: return s->edge[1];
363:
364: case 0x50: /* GPIO_DEBOUNCENABLE */
365: return s->debounce;
366:
367: case 0x54: /* GPIO_DEBOUNCINGTIME */
368: return s->delay;
369: }
370:
371: OMAP_BAD_REG(addr);
372: return 0;
373: }
374:
375: static void omap2_gpio_module_write(void *opaque, target_phys_addr_t addr,
376: uint32_t value)
377: {
378: struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
379: uint32_t diff;
380: int ln;
381:
382: switch (addr) {
383: case 0x00: /* GPIO_REVISION */
384: case 0x14: /* GPIO_SYSSTATUS */
385: case 0x38: /* GPIO_DATAIN */
386: OMAP_RO_REG(addr);
387: break;
388:
389: case 0x10: /* GPIO_SYSCONFIG */
390: if (((value >> 3) & 3) == 3)
391: fprintf(stderr, "%s: bad IDLEMODE value\n", __FUNCTION__);
392: if (value & 2)
393: omap2_gpio_module_reset(s);
394: s->config[0] = value & 0x1d;
395: break;
396:
397: case 0x18: /* GPIO_IRQSTATUS1 */
398: if (s->ints[0] & value) {
399: s->ints[0] &= ~value;
400: omap2_gpio_module_level_update(s, 0);
401: }
402: break;
403:
404: case 0x1c: /* GPIO_IRQENABLE1 */
405: s->mask[0] = value;
406: omap2_gpio_module_int_update(s, 0);
407: break;
408:
409: case 0x20: /* GPIO_WAKEUPENABLE */
410: s->wumask = value;
411: break;
412:
413: case 0x28: /* GPIO_IRQSTATUS2 */
414: if (s->ints[1] & value) {
415: s->ints[1] &= ~value;
416: omap2_gpio_module_level_update(s, 1);
417: }
418: break;
419:
420: case 0x2c: /* GPIO_IRQENABLE2 */
421: s->mask[1] = value;
422: omap2_gpio_module_int_update(s, 1);
423: break;
424:
425: case 0x30: /* GPIO_CTRL */
426: s->config[1] = value & 7;
427: break;
428:
429: case 0x34: /* GPIO_OE */
430: diff = s->outputs & (s->dir ^ value);
431: s->dir = value;
432:
433: value = s->outputs & ~s->dir;
434: while ((ln = ffs(diff))) {
435: diff &= ~(1 <<-- ln);
436: qemu_set_irq(s->handler[ln], (value >> ln) & 1);
437: }
438:
439: omap2_gpio_module_level_update(s, 0);
440: omap2_gpio_module_level_update(s, 1);
441: break;
442:
443: case 0x3c: /* GPIO_DATAOUT */
444: omap2_gpio_module_out_update(s, s->outputs ^ value);
445: break;
446:
447: case 0x40: /* GPIO_LEVELDETECT0 */
448: s->level[0] = value;
449: omap2_gpio_module_level_update(s, 0);
450: omap2_gpio_module_level_update(s, 1);
451: break;
452:
453: case 0x44: /* GPIO_LEVELDETECT1 */
454: s->level[1] = value;
455: omap2_gpio_module_level_update(s, 0);
456: omap2_gpio_module_level_update(s, 1);
457: break;
458:
459: case 0x48: /* GPIO_RISINGDETECT */
460: s->edge[0] = value;
461: break;
462:
463: case 0x4c: /* GPIO_FALLINGDETECT */
464: s->edge[1] = value;
465: break;
466:
467: case 0x50: /* GPIO_DEBOUNCENABLE */
468: s->debounce = value;
469: break;
470:
471: case 0x54: /* GPIO_DEBOUNCINGTIME */
472: s->delay = value;
473: break;
474:
475: case 0x60: /* GPIO_CLEARIRQENABLE1 */
476: s->mask[0] &= ~value;
477: omap2_gpio_module_int_update(s, 0);
478: break;
479:
480: case 0x64: /* GPIO_SETIRQENABLE1 */
481: s->mask[0] |= value;
482: omap2_gpio_module_int_update(s, 0);
483: break;
484:
485: case 0x70: /* GPIO_CLEARIRQENABLE2 */
486: s->mask[1] &= ~value;
487: omap2_gpio_module_int_update(s, 1);
488: break;
489:
490: case 0x74: /* GPIO_SETIREQNEABLE2 */
491: s->mask[1] |= value;
492: omap2_gpio_module_int_update(s, 1);
493: break;
494:
495: case 0x80: /* GPIO_CLEARWKUENA */
496: s->wumask &= ~value;
497: break;
498:
499: case 0x84: /* GPIO_SETWKUENA */
500: s->wumask |= value;
501: break;
502:
503: case 0x90: /* GPIO_CLEARDATAOUT */
504: omap2_gpio_module_out_update(s, s->outputs & value);
505: break;
506:
507: case 0x94: /* GPIO_SETDATAOUT */
508: omap2_gpio_module_out_update(s, ~s->outputs & value);
509: break;
510:
511: default:
512: OMAP_BAD_REG(addr);
513: return;
514: }
515: }
516:
517: static uint32_t omap2_gpio_module_readp(void *opaque, target_phys_addr_t addr)
518: {
1.1.1.3 root 519: return omap2_gpio_module_read(opaque, addr & ~3) >> ((addr & 3) << 3);
1.1 root 520: }
521:
522: static void omap2_gpio_module_writep(void *opaque, target_phys_addr_t addr,
523: uint32_t value)
524: {
525: uint32_t cur = 0;
526: uint32_t mask = 0xffff;
527:
528: switch (addr & ~3) {
529: case 0x00: /* GPIO_REVISION */
530: case 0x14: /* GPIO_SYSSTATUS */
531: case 0x38: /* GPIO_DATAIN */
532: OMAP_RO_REG(addr);
533: break;
534:
535: case 0x10: /* GPIO_SYSCONFIG */
536: case 0x1c: /* GPIO_IRQENABLE1 */
537: case 0x20: /* GPIO_WAKEUPENABLE */
538: case 0x2c: /* GPIO_IRQENABLE2 */
539: case 0x30: /* GPIO_CTRL */
540: case 0x34: /* GPIO_OE */
541: case 0x3c: /* GPIO_DATAOUT */
542: case 0x40: /* GPIO_LEVELDETECT0 */
543: case 0x44: /* GPIO_LEVELDETECT1 */
544: case 0x48: /* GPIO_RISINGDETECT */
545: case 0x4c: /* GPIO_FALLINGDETECT */
546: case 0x50: /* GPIO_DEBOUNCENABLE */
547: case 0x54: /* GPIO_DEBOUNCINGTIME */
548: cur = omap2_gpio_module_read(opaque, addr & ~3) &
549: ~(mask << ((addr & 3) << 3));
550:
551: /* Fall through. */
552: case 0x18: /* GPIO_IRQSTATUS1 */
553: case 0x28: /* GPIO_IRQSTATUS2 */
554: case 0x60: /* GPIO_CLEARIRQENABLE1 */
555: case 0x64: /* GPIO_SETIRQENABLE1 */
556: case 0x70: /* GPIO_CLEARIRQENABLE2 */
557: case 0x74: /* GPIO_SETIREQNEABLE2 */
558: case 0x80: /* GPIO_CLEARWKUENA */
559: case 0x84: /* GPIO_SETWKUENA */
560: case 0x90: /* GPIO_CLEARDATAOUT */
561: case 0x94: /* GPIO_SETDATAOUT */
562: value <<= (addr & 3) << 3;
563: omap2_gpio_module_write(opaque, addr, cur | value);
564: break;
565:
566: default:
567: OMAP_BAD_REG(addr);
568: return;
569: }
570: }
571:
1.1.1.4 ! root 572: static const MemoryRegionOps omap2_gpio_module_ops = {
! 573: .old_mmio = {
! 574: .read = {
! 575: omap2_gpio_module_readp,
! 576: omap2_gpio_module_readp,
! 577: omap2_gpio_module_read,
! 578: },
! 579: .write = {
! 580: omap2_gpio_module_writep,
! 581: omap2_gpio_module_writep,
! 582: omap2_gpio_module_write,
! 583: },
! 584: },
! 585: .endianness = DEVICE_NATIVE_ENDIAN,
1.1 root 586: };
587:
1.1.1.3 root 588: static void omap_gpif_reset(DeviceState *dev)
589: {
590: struct omap_gpif_s *s = FROM_SYSBUS(struct omap_gpif_s,
591: sysbus_from_qdev(dev));
592: omap_gpio_reset(&s->omap1);
1.1 root 593: }
594:
1.1.1.3 root 595: static void omap2_gpif_reset(DeviceState *dev)
1.1 root 596: {
597: int i;
1.1.1.3 root 598: struct omap2_gpif_s *s = FROM_SYSBUS(struct omap2_gpif_s,
599: sysbus_from_qdev(dev));
600: for (i = 0; i < s->modulecount; i++) {
601: omap2_gpio_module_reset(&s->modules[i]);
602: }
1.1 root 603: s->autoidle = 0;
604: s->gpo = 0;
605: }
606:
1.1.1.4 ! root 607: static uint64_t omap2_gpif_top_read(void *opaque, target_phys_addr_t addr,
! 608: unsigned size)
1.1 root 609: {
1.1.1.3 root 610: struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
1.1 root 611:
612: switch (addr) {
613: case 0x00: /* IPGENERICOCPSPL_REVISION */
614: return 0x18;
615:
616: case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */
617: return s->autoidle;
618:
619: case 0x14: /* IPGENERICOCPSPL_SYSSTATUS */
620: return 0x01;
621:
622: case 0x18: /* IPGENERICOCPSPL_IRQSTATUS */
623: return 0x00;
624:
625: case 0x40: /* IPGENERICOCPSPL_GPO */
626: return s->gpo;
627:
628: case 0x50: /* IPGENERICOCPSPL_GPI */
629: return 0x00;
630: }
631:
632: OMAP_BAD_REG(addr);
633: return 0;
634: }
635:
1.1.1.3 root 636: static void omap2_gpif_top_write(void *opaque, target_phys_addr_t addr,
1.1.1.4 ! root 637: uint64_t value, unsigned size)
1.1 root 638: {
1.1.1.3 root 639: struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
1.1 root 640:
641: switch (addr) {
642: case 0x00: /* IPGENERICOCPSPL_REVISION */
643: case 0x14: /* IPGENERICOCPSPL_SYSSTATUS */
644: case 0x18: /* IPGENERICOCPSPL_IRQSTATUS */
645: case 0x50: /* IPGENERICOCPSPL_GPI */
646: OMAP_RO_REG(addr);
647: break;
648:
649: case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */
650: if (value & (1 << 1)) /* SOFTRESET */
1.1.1.3 root 651: omap2_gpif_reset(&s->busdev.qdev);
1.1 root 652: s->autoidle = value & 1;
653: break;
654:
655: case 0x40: /* IPGENERICOCPSPL_GPO */
656: s->gpo = value & 1;
657: break;
658:
659: default:
660: OMAP_BAD_REG(addr);
661: return;
662: }
663: }
664:
1.1.1.4 ! root 665: static const MemoryRegionOps omap2_gpif_top_ops = {
! 666: .read = omap2_gpif_top_read,
! 667: .write = omap2_gpif_top_write,
! 668: .endianness = DEVICE_NATIVE_ENDIAN,
1.1 root 669: };
670:
1.1.1.3 root 671: static int omap_gpio_init(SysBusDevice *dev)
1.1 root 672: {
1.1.1.3 root 673: struct omap_gpif_s *s = FROM_SYSBUS(struct omap_gpif_s, dev);
674: if (!s->clk) {
675: hw_error("omap-gpio: clk not connected\n");
676: }
677: qdev_init_gpio_in(&dev->qdev, omap_gpio_set, 16);
678: qdev_init_gpio_out(&dev->qdev, s->omap1.handler, 16);
679: sysbus_init_irq(dev, &s->omap1.irq);
1.1.1.4 ! root 680: memory_region_init_io(&s->iomem, &omap_gpio_ops, &s->omap1,
! 681: "omap.gpio", 0x1000);
! 682: sysbus_init_mmio(dev, &s->iomem);
1.1.1.3 root 683: return 0;
1.1 root 684: }
685:
1.1.1.3 root 686: static int omap2_gpio_init(SysBusDevice *dev)
1.1 root 687: {
1.1.1.3 root 688: int i;
689: struct omap2_gpif_s *s = FROM_SYSBUS(struct omap2_gpif_s, dev);
690: if (!s->iclk) {
691: hw_error("omap2-gpio: iclk not connected\n");
692: }
693: if (s->mpu_model < omap3430) {
694: s->modulecount = (s->mpu_model < omap2430) ? 4 : 5;
1.1.1.4 ! root 695: memory_region_init_io(&s->iomem, &omap2_gpif_top_ops, s,
! 696: "omap2.gpio", 0x1000);
! 697: sysbus_init_mmio(dev, &s->iomem);
1.1.1.3 root 698: } else {
699: s->modulecount = 6;
700: }
701: s->modules = g_malloc0(s->modulecount * sizeof(struct omap2_gpio_s));
702: s->handler = g_malloc0(s->modulecount * 32 * sizeof(qemu_irq));
703: qdev_init_gpio_in(&dev->qdev, omap2_gpio_set, s->modulecount * 32);
704: qdev_init_gpio_out(&dev->qdev, s->handler, s->modulecount * 32);
705: for (i = 0; i < s->modulecount; i++) {
706: struct omap2_gpio_s *m = &s->modules[i];
707: if (!s->fclk[i]) {
708: hw_error("omap2-gpio: fclk%d not connected\n", i);
709: }
710: m->revision = (s->mpu_model < omap3430) ? 0x18 : 0x25;
711: m->handler = &s->handler[i * 32];
712: sysbus_init_irq(dev, &m->irq[0]); /* mpu irq */
713: sysbus_init_irq(dev, &m->irq[1]); /* dsp irq */
714: sysbus_init_irq(dev, &m->wkup);
1.1.1.4 ! root 715: memory_region_init_io(&m->iomem, &omap2_gpio_module_ops, m,
! 716: "omap.gpio-module", 0x1000);
! 717: sysbus_init_mmio(dev, &m->iomem);
1.1.1.3 root 718: }
719: return 0;
1.1 root 720: }
721:
1.1.1.3 root 722: /* Using qdev pointer properties for the clocks is not ideal.
723: * qdev should support a generic means of defining a 'port' with
724: * an arbitrary interface for connecting two devices. Then we
725: * could reframe the omap clock API in terms of clock ports,
726: * and get some type safety. For now the best qdev provides is
727: * passing an arbitrary pointer.
728: * (It's not possible to pass in the string which is the clock
729: * name, because this device does not have the necessary information
730: * (ie the struct omap_mpu_state_s*) to do the clockname to pointer
731: * translation.)
732: */
733:
1.1.1.4 ! root 734: static Property omap_gpio_properties[] = {
! 735: DEFINE_PROP_INT32("mpu_model", struct omap_gpif_s, mpu_model, 0),
! 736: DEFINE_PROP_PTR("clk", struct omap_gpif_s, clk),
! 737: DEFINE_PROP_END_OF_LIST(),
1.1.1.3 root 738: };
739:
1.1.1.4 ! root 740: static void omap_gpio_class_init(ObjectClass *klass, void *data)
! 741: {
! 742: DeviceClass *dc = DEVICE_CLASS(klass);
! 743: SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
! 744:
! 745: k->init = omap_gpio_init;
! 746: dc->reset = omap_gpif_reset;
! 747: dc->props = omap_gpio_properties;
! 748: }
! 749:
! 750: static TypeInfo omap_gpio_info = {
! 751: .name = "omap-gpio",
! 752: .parent = TYPE_SYS_BUS_DEVICE,
! 753: .instance_size = sizeof(struct omap_gpif_s),
! 754: .class_init = omap_gpio_class_init,
! 755: };
! 756:
! 757: static Property omap2_gpio_properties[] = {
! 758: DEFINE_PROP_INT32("mpu_model", struct omap2_gpif_s, mpu_model, 0),
! 759: DEFINE_PROP_PTR("iclk", struct omap2_gpif_s, iclk),
! 760: DEFINE_PROP_PTR("fclk0", struct omap2_gpif_s, fclk[0]),
! 761: DEFINE_PROP_PTR("fclk1", struct omap2_gpif_s, fclk[1]),
! 762: DEFINE_PROP_PTR("fclk2", struct omap2_gpif_s, fclk[2]),
! 763: DEFINE_PROP_PTR("fclk3", struct omap2_gpif_s, fclk[3]),
! 764: DEFINE_PROP_PTR("fclk4", struct omap2_gpif_s, fclk[4]),
! 765: DEFINE_PROP_PTR("fclk5", struct omap2_gpif_s, fclk[5]),
! 766: DEFINE_PROP_END_OF_LIST(),
! 767: };
! 768:
! 769: static void omap2_gpio_class_init(ObjectClass *klass, void *data)
! 770: {
! 771: DeviceClass *dc = DEVICE_CLASS(klass);
! 772: SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
! 773:
! 774: k->init = omap2_gpio_init;
! 775: dc->reset = omap2_gpif_reset;
! 776: dc->props = omap2_gpio_properties;
! 777: }
! 778:
! 779: static TypeInfo omap2_gpio_info = {
! 780: .name = "omap2-gpio",
! 781: .parent = TYPE_SYS_BUS_DEVICE,
! 782: .instance_size = sizeof(struct omap2_gpif_s),
! 783: .class_init = omap2_gpio_class_init,
1.1.1.3 root 784: };
785:
1.1.1.4 ! root 786: static void omap_gpio_register_types(void)
1.1 root 787: {
1.1.1.4 ! root 788: type_register_static(&omap_gpio_info);
! 789: type_register_static(&omap2_gpio_info);
1.1 root 790: }
1.1.1.3 root 791:
1.1.1.4 ! root 792: type_init(omap_gpio_register_types)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.