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

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,
        !           186:                     omap_gpio_writefn, s);
        !           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.