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

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

unix.superglobalmegacorp.com

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