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

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)

unix.superglobalmegacorp.com

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