Annotation of qemu/hw/omap_gpio.c, revision 1.1.1.2

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"
                     23: /* General-Purpose I/O */
                     24: struct 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: 
                     38: static 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: 
                     55: static 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: /* DATA_INPUT */
                     62:         return s->inputs & s->pins;
                     63: 
                     64:     case 0x04: /* DATA_OUTPUT */
                     65:         return s->outputs;
                     66: 
                     67:     case 0x08: /* DIRECTION_CONTROL */
                     68:         return s->dir;
                     69: 
                     70:     case 0x0c: /* INTERRUPT_CONTROL */
                     71:         return s->edge;
                     72: 
                     73:     case 0x10: /* INTERRUPT_MASK */
                     74:         return s->mask;
                     75: 
                     76:     case 0x14: /* INTERRUPT_STATUS */
                     77:         return s->ints;
                     78: 
                     79:     case 0x18: /* PIN_CONTROL (not in OMAP310) */
                     80:         OMAP_BAD_REG(addr);
                     81:         return s->pins;
                     82:     }
                     83: 
                     84:     OMAP_BAD_REG(addr);
                     85:     return 0;
                     86: }
                     87: 
                     88: static 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: /* DATA_INPUT */
                     98:         OMAP_RO_REG(addr);
                     99:         return;
                    100: 
                    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);
                    109:         }
                    110:         break;
                    111: 
                    112:     case 0x08: /* DIRECTION_CONTROL */
                    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: /* INTERRUPT_CONTROL */
                    126:         s->edge = value;
                    127:         break;
                    128: 
                    129:     case 0x10: /* INTERRUPT_MASK */
                    130:         s->mask = value;
                    131:         break;
                    132: 
                    133:     case 0x14: /* INTERRUPT_STATUS */
                    134:         s->ints &= ~value;
                    135:         if (!s->ints)
                    136:             qemu_irq_lower(s->irq);
                    137:         break;
                    138: 
                    139:     case 0x18: /* PIN_CONTROL (not in OMAP310 TRM) */
                    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: /* *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,
                    155: };
                    156: 
                    157: static CPUWriteMemoryFunc * const omap_gpio_writefn[] = {
                    158:     omap_badwidth_write16,
                    159:     omap_gpio_write,
                    160:     omap_badwidth_write16,
                    161: };
                    162: 
                    163: void 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: 
                    174: struct 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,
1.1.1.2 ! root      186:                     omap_gpio_writefn, s, DEVICE_NATIVE_ENDIAN);
1.1       root      187:     cpu_register_physical_memory(base, 0x1000, iomemtype);
                    188: 
                    189:     return s;
                    190: }
                    191: 
                    192: qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s)
                    193: {
                    194:     return s->in;
                    195: }
                    196: 
                    197: void 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: /* 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];
                    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: 
                    224: static 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: 
                    230: static void omap2_gpio_module_wake(struct omap2_gpio_s *s, int line)
                    231: {
                    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;
                    238: 
                    239:     qemu_irq_raise(s->wkup);
                    240: }
                    241: 
                    242: static 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: 
                    256: static 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: 
                    263: static 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: 
                    272: static 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: 
                    287: static 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: 
                    305: static 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: /* GPIO_REVISION */
                    311:         return 0x18;
                    312: 
                    313:     case 0x10: /* GPIO_SYSCONFIG */
                    314:         return s->config[0];
                    315: 
                    316:     case 0x14: /* GPIO_SYSSTATUS */
                    317:         return 0x01;
                    318: 
                    319:     case 0x18: /* GPIO_IRQSTATUS1 */
                    320:         return s->ints[0];
                    321: 
                    322:     case 0x1c: /* GPIO_IRQENABLE1 */
                    323:     case 0x60: /* GPIO_CLEARIRQENABLE1 */
                    324:     case 0x64: /* GPIO_SETIRQENABLE1 */
                    325:         return s->mask[0];
                    326: 
                    327:     case 0x20: /* GPIO_WAKEUPENABLE */
                    328:     case 0x80: /* GPIO_CLEARWKUENA */
                    329:     case 0x84: /* GPIO_SETWKUENA */
                    330:         return s->wumask;
                    331: 
                    332:     case 0x28: /* GPIO_IRQSTATUS2 */
                    333:         return s->ints[1];
                    334: 
                    335:     case 0x2c: /* GPIO_IRQENABLE2 */
                    336:     case 0x70: /* GPIO_CLEARIRQENABLE2 */
                    337:     case 0x74: /* GPIO_SETIREQNEABLE2 */
                    338:         return s->mask[1];
                    339: 
                    340:     case 0x30: /* GPIO_CTRL */
                    341:         return s->config[1];
                    342: 
                    343:     case 0x34: /* GPIO_OE */
                    344:         return s->dir;
                    345: 
                    346:     case 0x38: /* GPIO_DATAIN */
                    347:         return s->inputs;
                    348: 
                    349:     case 0x3c: /* GPIO_DATAOUT */
                    350:     case 0x90: /* GPIO_CLEARDATAOUT */
                    351:     case 0x94: /* GPIO_SETDATAOUT */
                    352:         return s->outputs;
                    353: 
                    354:     case 0x40: /* GPIO_LEVELDETECT0 */
                    355:         return s->level[0];
                    356: 
                    357:     case 0x44: /* GPIO_LEVELDETECT1 */
                    358:         return s->level[1];
                    359: 
                    360:     case 0x48: /* GPIO_RISINGDETECT */
                    361:         return s->edge[0];
                    362: 
                    363:     case 0x4c: /* GPIO_FALLINGDETECT */
                    364:         return s->edge[1];
                    365: 
                    366:     case 0x50: /* GPIO_DEBOUNCENABLE */
                    367:         return s->debounce;
                    368: 
                    369:     case 0x54: /* GPIO_DEBOUNCINGTIME */
                    370:         return s->delay;
                    371:     }
                    372: 
                    373:     OMAP_BAD_REG(addr);
                    374:     return 0;
                    375: }
                    376: 
                    377: static 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: /* GPIO_REVISION */
                    386:     case 0x14: /* GPIO_SYSSTATUS */
                    387:     case 0x38: /* GPIO_DATAIN */
                    388:         OMAP_RO_REG(addr);
                    389:         break;
                    390: 
                    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;
                    398: 
                    399:     case 0x18: /* GPIO_IRQSTATUS1 */
                    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: /* GPIO_IRQENABLE1 */
                    407:         s->mask[0] = value;
                    408:         omap2_gpio_module_int_update(s, 0);
                    409:         break;
                    410: 
                    411:     case 0x20: /* GPIO_WAKEUPENABLE */
                    412:         s->wumask = value;
                    413:         break;
                    414: 
                    415:     case 0x28: /* GPIO_IRQSTATUS2 */
                    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: /* GPIO_IRQENABLE2 */
                    423:         s->mask[1] = value;
                    424:         omap2_gpio_module_int_update(s, 1);
                    425:         break;
                    426: 
                    427:     case 0x30: /* GPIO_CTRL */
                    428:         s->config[1] = value & 7;
                    429:         break;
                    430: 
                    431:     case 0x34: /* GPIO_OE */
                    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: /* GPIO_DATAOUT */
                    446:         omap2_gpio_module_out_update(s, s->outputs ^ value);
                    447:         break;
                    448: 
                    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;
                    454: 
                    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;
                    460: 
                    461:     case 0x48: /* GPIO_RISINGDETECT */
                    462:         s->edge[0] = value;
                    463:         break;
                    464: 
                    465:     case 0x4c: /* GPIO_FALLINGDETECT */
                    466:         s->edge[1] = value;
                    467:         break;
                    468: 
                    469:     case 0x50: /* GPIO_DEBOUNCENABLE */
                    470:         s->debounce = value;
                    471:         break;
                    472: 
                    473:     case 0x54: /* GPIO_DEBOUNCINGTIME */
                    474:         s->delay = value;
                    475:         break;
                    476: 
                    477:     case 0x60: /* GPIO_CLEARIRQENABLE1 */
                    478:         s->mask[0] &= ~value;
                    479:         omap2_gpio_module_int_update(s, 0);
                    480:         break;
                    481: 
                    482:     case 0x64: /* GPIO_SETIRQENABLE1 */
                    483:         s->mask[0] |= value;
                    484:         omap2_gpio_module_int_update(s, 0);
                    485:         break;
                    486: 
                    487:     case 0x70: /* GPIO_CLEARIRQENABLE2 */
                    488:         s->mask[1] &= ~value;
                    489:         omap2_gpio_module_int_update(s, 1);
                    490:         break;
                    491: 
                    492:     case 0x74: /* GPIO_SETIREQNEABLE2 */
                    493:         s->mask[1] |= value;
                    494:         omap2_gpio_module_int_update(s, 1);
                    495:         break;
                    496: 
                    497:     case 0x80: /* GPIO_CLEARWKUENA */
                    498:         s->wumask &= ~value;
                    499:         break;
                    500: 
                    501:     case 0x84: /* GPIO_SETWKUENA */
                    502:         s->wumask |= value;
                    503:         break;
                    504: 
                    505:     case 0x90: /* GPIO_CLEARDATAOUT */
                    506:         omap2_gpio_module_out_update(s, s->outputs & value);
                    507:         break;
                    508: 
                    509:     case 0x94: /* GPIO_SETDATAOUT */
                    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: 
                    519: static 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: 
                    524: static 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: /* GPIO_REVISION */
                    532:     case 0x14: /* GPIO_SYSSTATUS */
                    533:     case 0x38: /* GPIO_DATAIN */
                    534:         OMAP_RO_REG(addr);
                    535:         break;
                    536: 
                    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));
                    552: 
                    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;
                    567: 
                    568:     default:
                    569:         OMAP_BAD_REG(addr);
                    570:         return;
                    571:     }
                    572: }
                    573: 
                    574: static CPUReadMemoryFunc * const omap2_gpio_module_readfn[] = {
                    575:     omap2_gpio_module_readp,
                    576:     omap2_gpio_module_readp,
                    577:     omap2_gpio_module_read,
                    578: };
                    579: 
                    580: static CPUWriteMemoryFunc * const omap2_gpio_module_writefn[] = {
                    581:     omap2_gpio_module_writep,
                    582:     omap2_gpio_module_writep,
                    583:     omap2_gpio_module_write,
                    584: };
                    585: 
                    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)
                    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: 
                    603: struct omap_gpif_s {
                    604:     struct omap2_gpio_s module[5];
                    605:     int modules;
                    606: 
                    607:     int autoidle;
                    608:     int gpo;
                    609: };
                    610: 
                    611: void 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: 
                    622: static 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: /* IPGENERICOCPSPL_REVISION */
                    628:         return 0x18;
                    629: 
                    630:     case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */
                    631:         return s->autoidle;
                    632: 
                    633:     case 0x14: /* IPGENERICOCPSPL_SYSSTATUS */
                    634:         return 0x01;
                    635: 
                    636:     case 0x18: /* IPGENERICOCPSPL_IRQSTATUS */
                    637:         return 0x00;
                    638: 
                    639:     case 0x40: /* IPGENERICOCPSPL_GPO */
                    640:         return s->gpo;
                    641: 
                    642:     case 0x50: /* IPGENERICOCPSPL_GPI */
                    643:         return 0x00;
                    644:     }
                    645: 
                    646:     OMAP_BAD_REG(addr);
                    647:     return 0;
                    648: }
                    649: 
                    650: static 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: /* IPGENERICOCPSPL_REVISION */
                    657:     case 0x14: /* IPGENERICOCPSPL_SYSSTATUS */
                    658:     case 0x18: /* IPGENERICOCPSPL_IRQSTATUS */
                    659:     case 0x50: /* IPGENERICOCPSPL_GPI */
                    660:         OMAP_RO_REG(addr);
                    661:         break;
                    662: 
                    663:     case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */
                    664:         if (value & (1 << 1))                                  /* SOFTRESET */
                    665:             omap_gpif_reset(s);
                    666:         s->autoidle = value & 1;
                    667:         break;
                    668: 
                    669:     case 0x40: /* IPGENERICOCPSPL_GPO */
                    670:         s->gpo = value & 1;
                    671:         break;
                    672: 
                    673:     default:
                    674:         OMAP_BAD_REG(addr);
                    675:         return;
                    676:     }
                    677: }
                    678: 
                    679: static CPUReadMemoryFunc * const omap_gpif_top_readfn[] = {
                    680:     omap_gpif_top_read,
                    681:     omap_gpif_top_read,
                    682:     omap_gpif_top_read,
                    683: };
                    684: 
                    685: static CPUWriteMemoryFunc * const omap_gpif_top_writefn[] = {
                    686:     omap_gpif_top_write,
                    687:     omap_gpif_top_write,
                    688:     omap_gpif_top_write,
                    689: };
                    690: 
                    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)
                    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: 
                    713: qemu_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: 
                    720: void 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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.