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

1.1     ! root        1: /*
        !             2:  * Luminary Micro Stellaris preipherals
        !             3:  *
        !             4:  * Copyright (c) 2006 CodeSourcery.
        !             5:  * Written by Paul Brook
        !             6:  *
        !             7:  * This code is licenced under the GPL.
        !             8:  */
        !             9: 
        !            10: #include "hw.h"
        !            11: #include "arm-misc.h"
        !            12: #include "primecell.h"
        !            13: #include "devices.h"
        !            14: #include "qemu-timer.h"
        !            15: #include "i2c.h"
        !            16: #include "net.h"
        !            17: #include "sd.h"
        !            18: #include "sysemu.h"
        !            19: #include "boards.h"
        !            20: 
        !            21: #define GPIO_A 0
        !            22: #define GPIO_B 1
        !            23: #define GPIO_C 2
        !            24: #define GPIO_D 3
        !            25: #define GPIO_E 4
        !            26: #define GPIO_F 5
        !            27: #define GPIO_G 6
        !            28: 
        !            29: #define BP_OLED_I2C  0x01
        !            30: #define BP_OLED_SSI  0x02
        !            31: #define BP_GAMEPAD   0x04
        !            32: 
        !            33: typedef const struct {
        !            34:     const char *name;
        !            35:     uint32_t did0;
        !            36:     uint32_t did1;
        !            37:     uint32_t dc0;
        !            38:     uint32_t dc1;
        !            39:     uint32_t dc2;
        !            40:     uint32_t dc3;
        !            41:     uint32_t dc4;
        !            42:     uint32_t peripherals;
        !            43: } stellaris_board_info;
        !            44: 
        !            45: /* General purpose timer module.  */
        !            46: 
        !            47: typedef struct gptm_state {
        !            48:     uint32_t config;
        !            49:     uint32_t mode[2];
        !            50:     uint32_t control;
        !            51:     uint32_t state;
        !            52:     uint32_t mask;
        !            53:     uint32_t load[2];
        !            54:     uint32_t match[2];
        !            55:     uint32_t prescale[2];
        !            56:     uint32_t match_prescale[2];
        !            57:     uint32_t rtc;
        !            58:     int64_t tick[2];
        !            59:     struct gptm_state *opaque[2];
        !            60:     uint32_t base;
        !            61:     QEMUTimer *timer[2];
        !            62:     /* The timers have an alternate output used to trigger the ADC.  */
        !            63:     qemu_irq trigger;
        !            64:     qemu_irq irq;
        !            65: } gptm_state;
        !            66: 
        !            67: static void gptm_update_irq(gptm_state *s)
        !            68: {
        !            69:     int level;
        !            70:     level = (s->state & s->mask) != 0;
        !            71:     qemu_set_irq(s->irq, level);
        !            72: }
        !            73: 
        !            74: static void gptm_stop(gptm_state *s, int n)
        !            75: {
        !            76:     qemu_del_timer(s->timer[n]);
        !            77: }
        !            78: 
        !            79: static void gptm_reload(gptm_state *s, int n, int reset)
        !            80: {
        !            81:     int64_t tick;
        !            82:     if (reset)
        !            83:         tick = qemu_get_clock(vm_clock);
        !            84:     else
        !            85:         tick = s->tick[n];
        !            86: 
        !            87:     if (s->config == 0) {
        !            88:         /* 32-bit CountDown.  */
        !            89:         uint32_t count;
        !            90:         count = s->load[0] | (s->load[1] << 16);
        !            91:         tick += (int64_t)count * system_clock_scale;
        !            92:     } else if (s->config == 1) {
        !            93:         /* 32-bit RTC.  1Hz tick.  */
        !            94:         tick += ticks_per_sec;
        !            95:     } else if (s->mode[n] == 0xa) {
        !            96:         /* PWM mode.  Not implemented.  */
        !            97:     } else {
        !            98:         cpu_abort(cpu_single_env, "TODO: 16-bit timer mode 0x%x\n",
        !            99:                   s->mode[n]);
        !           100:     }
        !           101:     s->tick[n] = tick;
        !           102:     qemu_mod_timer(s->timer[n], tick);
        !           103: }
        !           104: 
        !           105: static void gptm_tick(void *opaque)
        !           106: {
        !           107:     gptm_state **p = (gptm_state **)opaque;
        !           108:     gptm_state *s;
        !           109:     int n;
        !           110: 
        !           111:     s = *p;
        !           112:     n = p - s->opaque;
        !           113:     if (s->config == 0) {
        !           114:         s->state |= 1;
        !           115:         if ((s->control & 0x20)) {
        !           116:             /* Output trigger.  */
        !           117:            qemu_irq_raise(s->trigger);
        !           118:            qemu_irq_lower(s->trigger);
        !           119:         }
        !           120:         if (s->mode[0] & 1) {
        !           121:             /* One-shot.  */
        !           122:             s->control &= ~1;
        !           123:         } else {
        !           124:             /* Periodic.  */
        !           125:             gptm_reload(s, 0, 0);
        !           126:         }
        !           127:     } else if (s->config == 1) {
        !           128:         /* RTC.  */
        !           129:         uint32_t match;
        !           130:         s->rtc++;
        !           131:         match = s->match[0] | (s->match[1] << 16);
        !           132:         if (s->rtc > match)
        !           133:             s->rtc = 0;
        !           134:         if (s->rtc == 0) {
        !           135:             s->state |= 8;
        !           136:         }
        !           137:         gptm_reload(s, 0, 0);
        !           138:     } else if (s->mode[n] == 0xa) {
        !           139:         /* PWM mode.  Not implemented.  */
        !           140:     } else {
        !           141:         cpu_abort(cpu_single_env, "TODO: 16-bit timer mode 0x%x\n",
        !           142:                   s->mode[n]);
        !           143:     }
        !           144:     gptm_update_irq(s);
        !           145: }
        !           146: 
        !           147: static uint32_t gptm_read(void *opaque, target_phys_addr_t offset)
        !           148: {
        !           149:     gptm_state *s = (gptm_state *)opaque;
        !           150: 
        !           151:     offset -= s->base;
        !           152:     switch (offset) {
        !           153:     case 0x00: /* CFG */
        !           154:         return s->config;
        !           155:     case 0x04: /* TAMR */
        !           156:         return s->mode[0];
        !           157:     case 0x08: /* TBMR */
        !           158:         return s->mode[1];
        !           159:     case 0x0c: /* CTL */
        !           160:         return s->control;
        !           161:     case 0x18: /* IMR */
        !           162:         return s->mask;
        !           163:     case 0x1c: /* RIS */
        !           164:         return s->state;
        !           165:     case 0x20: /* MIS */
        !           166:         return s->state & s->mask;
        !           167:     case 0x24: /* CR */
        !           168:         return 0;
        !           169:     case 0x28: /* TAILR */
        !           170:         return s->load[0] | ((s->config < 4) ? (s->load[1] << 16) : 0);
        !           171:     case 0x2c: /* TBILR */
        !           172:         return s->load[1];
        !           173:     case 0x30: /* TAMARCHR */
        !           174:         return s->match[0] | ((s->config < 4) ? (s->match[1] << 16) : 0);
        !           175:     case 0x34: /* TBMATCHR */
        !           176:         return s->match[1];
        !           177:     case 0x38: /* TAPR */
        !           178:         return s->prescale[0];
        !           179:     case 0x3c: /* TBPR */
        !           180:         return s->prescale[1];
        !           181:     case 0x40: /* TAPMR */
        !           182:         return s->match_prescale[0];
        !           183:     case 0x44: /* TBPMR */
        !           184:         return s->match_prescale[1];
        !           185:     case 0x48: /* TAR */
        !           186:         if (s->control == 1)
        !           187:             return s->rtc;
        !           188:     case 0x4c: /* TBR */
        !           189:         cpu_abort(cpu_single_env, "TODO: Timer value read\n");
        !           190:     default:
        !           191:         cpu_abort(cpu_single_env, "gptm_read: Bad offset 0x%x\n", (int)offset);
        !           192:         return 0;
        !           193:     }
        !           194: }
        !           195: 
        !           196: static void gptm_write(void *opaque, target_phys_addr_t offset, uint32_t value)
        !           197: {
        !           198:     gptm_state *s = (gptm_state *)opaque;
        !           199:     uint32_t oldval;
        !           200: 
        !           201:     offset -= s->base;
        !           202:     /* The timers should be disabled before changing the configuration.
        !           203:        We take advantage of this and defer everything until the timer
        !           204:        is enabled.  */
        !           205:     switch (offset) {
        !           206:     case 0x00: /* CFG */
        !           207:         s->config = value;
        !           208:         break;
        !           209:     case 0x04: /* TAMR */
        !           210:         s->mode[0] = value;
        !           211:         break;
        !           212:     case 0x08: /* TBMR */
        !           213:         s->mode[1] = value;
        !           214:         break;
        !           215:     case 0x0c: /* CTL */
        !           216:         oldval = s->control;
        !           217:         s->control = value;
        !           218:         /* TODO: Implement pause.  */
        !           219:         if ((oldval ^ value) & 1) {
        !           220:             if (value & 1) {
        !           221:                 gptm_reload(s, 0, 1);
        !           222:             } else {
        !           223:                 gptm_stop(s, 0);
        !           224:             }
        !           225:         }
        !           226:         if (((oldval ^ value) & 0x100) && s->config >= 4) {
        !           227:             if (value & 0x100) {
        !           228:                 gptm_reload(s, 1, 1);
        !           229:             } else {
        !           230:                 gptm_stop(s, 1);
        !           231:             }
        !           232:         }
        !           233:         break;
        !           234:     case 0x18: /* IMR */
        !           235:         s->mask = value & 0x77;
        !           236:         gptm_update_irq(s);
        !           237:         break;
        !           238:     case 0x24: /* CR */
        !           239:         s->state &= ~value;
        !           240:         break;
        !           241:     case 0x28: /* TAILR */
        !           242:         s->load[0] = value & 0xffff;
        !           243:         if (s->config < 4) {
        !           244:             s->load[1] = value >> 16;
        !           245:         }
        !           246:         break;
        !           247:     case 0x2c: /* TBILR */
        !           248:         s->load[1] = value & 0xffff;
        !           249:         break;
        !           250:     case 0x30: /* TAMARCHR */
        !           251:         s->match[0] = value & 0xffff;
        !           252:         if (s->config < 4) {
        !           253:             s->match[1] = value >> 16;
        !           254:         }
        !           255:         break;
        !           256:     case 0x34: /* TBMATCHR */
        !           257:         s->match[1] = value >> 16;
        !           258:         break;
        !           259:     case 0x38: /* TAPR */
        !           260:         s->prescale[0] = value;
        !           261:         break;
        !           262:     case 0x3c: /* TBPR */
        !           263:         s->prescale[1] = value;
        !           264:         break;
        !           265:     case 0x40: /* TAPMR */
        !           266:         s->match_prescale[0] = value;
        !           267:         break;
        !           268:     case 0x44: /* TBPMR */
        !           269:         s->match_prescale[0] = value;
        !           270:         break;
        !           271:     default:
        !           272:         cpu_abort(cpu_single_env, "gptm_write: Bad offset 0x%x\n", (int)offset);
        !           273:     }
        !           274:     gptm_update_irq(s);
        !           275: }
        !           276: 
        !           277: static CPUReadMemoryFunc *gptm_readfn[] = {
        !           278:    gptm_read,
        !           279:    gptm_read,
        !           280:    gptm_read
        !           281: };
        !           282: 
        !           283: static CPUWriteMemoryFunc *gptm_writefn[] = {
        !           284:    gptm_write,
        !           285:    gptm_write,
        !           286:    gptm_write
        !           287: };
        !           288: 
        !           289: static void stellaris_gptm_init(uint32_t base, qemu_irq irq, qemu_irq trigger)
        !           290: {
        !           291:     int iomemtype;
        !           292:     gptm_state *s;
        !           293: 
        !           294:     s = (gptm_state *)qemu_mallocz(sizeof(gptm_state));
        !           295:     s->base = base;
        !           296:     s->irq = irq;
        !           297:     s->trigger = trigger;
        !           298:     s->opaque[0] = s->opaque[1] = s;
        !           299: 
        !           300:     iomemtype = cpu_register_io_memory(0, gptm_readfn,
        !           301:                                        gptm_writefn, s);
        !           302:     cpu_register_physical_memory(base, 0x00001000, iomemtype);
        !           303:     s->timer[0] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[0]);
        !           304:     s->timer[1] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[1]);
        !           305:     /* ??? Save/restore.  */
        !           306: }
        !           307: 
        !           308: 
        !           309: /* System controller.  */
        !           310: 
        !           311: typedef struct {
        !           312:     uint32_t base;
        !           313:     uint32_t pborctl;
        !           314:     uint32_t ldopctl;
        !           315:     uint32_t int_status;
        !           316:     uint32_t int_mask;
        !           317:     uint32_t resc;
        !           318:     uint32_t rcc;
        !           319:     uint32_t rcgc[3];
        !           320:     uint32_t scgc[3];
        !           321:     uint32_t dcgc[3];
        !           322:     uint32_t clkvclr;
        !           323:     uint32_t ldoarst;
        !           324:     uint32_t user0;
        !           325:     uint32_t user1;
        !           326:     qemu_irq irq;
        !           327:     stellaris_board_info *board;
        !           328: } ssys_state;
        !           329: 
        !           330: static void ssys_update(ssys_state *s)
        !           331: {
        !           332:   qemu_set_irq(s->irq, (s->int_status & s->int_mask) != 0);
        !           333: }
        !           334: 
        !           335: static uint32_t pllcfg_sandstorm[16] = {
        !           336:     0x31c0, /* 1 Mhz */
        !           337:     0x1ae0, /* 1.8432 Mhz */
        !           338:     0x18c0, /* 2 Mhz */
        !           339:     0xd573, /* 2.4576 Mhz */
        !           340:     0x37a6, /* 3.57954 Mhz */
        !           341:     0x1ae2, /* 3.6864 Mhz */
        !           342:     0x0c40, /* 4 Mhz */
        !           343:     0x98bc, /* 4.906 Mhz */
        !           344:     0x935b, /* 4.9152 Mhz */
        !           345:     0x09c0, /* 5 Mhz */
        !           346:     0x4dee, /* 5.12 Mhz */
        !           347:     0x0c41, /* 6 Mhz */
        !           348:     0x75db, /* 6.144 Mhz */
        !           349:     0x1ae6, /* 7.3728 Mhz */
        !           350:     0x0600, /* 8 Mhz */
        !           351:     0x585b /* 8.192 Mhz */
        !           352: };
        !           353: 
        !           354: static uint32_t pllcfg_fury[16] = {
        !           355:     0x3200, /* 1 Mhz */
        !           356:     0x1b20, /* 1.8432 Mhz */
        !           357:     0x1900, /* 2 Mhz */
        !           358:     0xf42b, /* 2.4576 Mhz */
        !           359:     0x37e3, /* 3.57954 Mhz */
        !           360:     0x1b21, /* 3.6864 Mhz */
        !           361:     0x0c80, /* 4 Mhz */
        !           362:     0x98ee, /* 4.906 Mhz */
        !           363:     0xd5b4, /* 4.9152 Mhz */
        !           364:     0x0a00, /* 5 Mhz */
        !           365:     0x4e27, /* 5.12 Mhz */
        !           366:     0x1902, /* 6 Mhz */
        !           367:     0xec1c, /* 6.144 Mhz */
        !           368:     0x1b23, /* 7.3728 Mhz */
        !           369:     0x0640, /* 8 Mhz */
        !           370:     0xb11c /* 8.192 Mhz */
        !           371: };
        !           372: 
        !           373: static uint32_t ssys_read(void *opaque, target_phys_addr_t offset)
        !           374: {
        !           375:     ssys_state *s = (ssys_state *)opaque;
        !           376: 
        !           377:     offset -= s->base;
        !           378:     switch (offset) {
        !           379:     case 0x000: /* DID0 */
        !           380:         return s->board->did0;
        !           381:     case 0x004: /* DID1 */
        !           382:         return s->board->did1;
        !           383:     case 0x008: /* DC0 */
        !           384:         return s->board->dc0;
        !           385:     case 0x010: /* DC1 */
        !           386:         return s->board->dc1;
        !           387:     case 0x014: /* DC2 */
        !           388:         return s->board->dc2;
        !           389:     case 0x018: /* DC3 */
        !           390:         return s->board->dc3;
        !           391:     case 0x01c: /* DC4 */
        !           392:         return s->board->dc4;
        !           393:     case 0x030: /* PBORCTL */
        !           394:         return s->pborctl;
        !           395:     case 0x034: /* LDOPCTL */
        !           396:         return s->ldopctl;
        !           397:     case 0x040: /* SRCR0 */
        !           398:         return 0;
        !           399:     case 0x044: /* SRCR1 */
        !           400:         return 0;
        !           401:     case 0x048: /* SRCR2 */
        !           402:         return 0;
        !           403:     case 0x050: /* RIS */
        !           404:         return s->int_status;
        !           405:     case 0x054: /* IMC */
        !           406:         return s->int_mask;
        !           407:     case 0x058: /* MISC */
        !           408:         return s->int_status & s->int_mask;
        !           409:     case 0x05c: /* RESC */
        !           410:         return s->resc;
        !           411:     case 0x060: /* RCC */
        !           412:         return s->rcc;
        !           413:     case 0x064: /* PLLCFG */
        !           414:         {
        !           415:             int xtal;
        !           416:             xtal = (s->rcc >> 6) & 0xf;
        !           417:             if (s->board->did0 & (1 << 16)) {
        !           418:                 return pllcfg_fury[xtal];
        !           419:             } else {
        !           420:                 return pllcfg_sandstorm[xtal];
        !           421:             }
        !           422:         }
        !           423:     case 0x100: /* RCGC0 */
        !           424:         return s->rcgc[0];
        !           425:     case 0x104: /* RCGC1 */
        !           426:         return s->rcgc[1];
        !           427:     case 0x108: /* RCGC2 */
        !           428:         return s->rcgc[2];
        !           429:     case 0x110: /* SCGC0 */
        !           430:         return s->scgc[0];
        !           431:     case 0x114: /* SCGC1 */
        !           432:         return s->scgc[1];
        !           433:     case 0x118: /* SCGC2 */
        !           434:         return s->scgc[2];
        !           435:     case 0x120: /* DCGC0 */
        !           436:         return s->dcgc[0];
        !           437:     case 0x124: /* DCGC1 */
        !           438:         return s->dcgc[1];
        !           439:     case 0x128: /* DCGC2 */
        !           440:         return s->dcgc[2];
        !           441:     case 0x150: /* CLKVCLR */
        !           442:         return s->clkvclr;
        !           443:     case 0x160: /* LDOARST */
        !           444:         return s->ldoarst;
        !           445:     case 0x1e0: /* USER0 */
        !           446:         return s->user0;
        !           447:     case 0x1e4: /* USER1 */
        !           448:         return s->user1;
        !           449:     default:
        !           450:         cpu_abort(cpu_single_env, "ssys_read: Bad offset 0x%x\n", (int)offset);
        !           451:         return 0;
        !           452:     }
        !           453: }
        !           454: 
        !           455: static void ssys_write(void *opaque, target_phys_addr_t offset, uint32_t value)
        !           456: {
        !           457:     ssys_state *s = (ssys_state *)opaque;
        !           458: 
        !           459:     offset -= s->base;
        !           460:     switch (offset) {
        !           461:     case 0x030: /* PBORCTL */
        !           462:         s->pborctl = value & 0xffff;
        !           463:         break;
        !           464:     case 0x034: /* LDOPCTL */
        !           465:         s->ldopctl = value & 0x1f;
        !           466:         break;
        !           467:     case 0x040: /* SRCR0 */
        !           468:     case 0x044: /* SRCR1 */
        !           469:     case 0x048: /* SRCR2 */
        !           470:         fprintf(stderr, "Peripheral reset not implemented\n");
        !           471:         break;
        !           472:     case 0x054: /* IMC */
        !           473:         s->int_mask = value & 0x7f;
        !           474:         break;
        !           475:     case 0x058: /* MISC */
        !           476:         s->int_status &= ~value;
        !           477:         break;
        !           478:     case 0x05c: /* RESC */
        !           479:         s->resc = value & 0x3f;
        !           480:         break;
        !           481:     case 0x060: /* RCC */
        !           482:         if ((s->rcc & (1 << 13)) != 0 && (value & (1 << 13)) == 0) {
        !           483:             /* PLL enable.  */
        !           484:             s->int_status |= (1 << 6);
        !           485:         }
        !           486:         s->rcc = value;
        !           487:         system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1);
        !           488:         break;
        !           489:     case 0x100: /* RCGC0 */
        !           490:         s->rcgc[0] = value;
        !           491:         break;
        !           492:     case 0x104: /* RCGC1 */
        !           493:         s->rcgc[1] = value;
        !           494:         break;
        !           495:     case 0x108: /* RCGC2 */
        !           496:         s->rcgc[2] = value;
        !           497:         break;
        !           498:     case 0x110: /* SCGC0 */
        !           499:         s->scgc[0] = value;
        !           500:         break;
        !           501:     case 0x114: /* SCGC1 */
        !           502:         s->scgc[1] = value;
        !           503:         break;
        !           504:     case 0x118: /* SCGC2 */
        !           505:         s->scgc[2] = value;
        !           506:         break;
        !           507:     case 0x120: /* DCGC0 */
        !           508:         s->dcgc[0] = value;
        !           509:         break;
        !           510:     case 0x124: /* DCGC1 */
        !           511:         s->dcgc[1] = value;
        !           512:         break;
        !           513:     case 0x128: /* DCGC2 */
        !           514:         s->dcgc[2] = value;
        !           515:         break;
        !           516:     case 0x150: /* CLKVCLR */
        !           517:         s->clkvclr = value;
        !           518:         break;
        !           519:     case 0x160: /* LDOARST */
        !           520:         s->ldoarst = value;
        !           521:         break;
        !           522:     default:
        !           523:         cpu_abort(cpu_single_env, "ssys_write: Bad offset 0x%x\n", (int)offset);
        !           524:     }
        !           525:     ssys_update(s);
        !           526: }
        !           527: 
        !           528: static CPUReadMemoryFunc *ssys_readfn[] = {
        !           529:    ssys_read,
        !           530:    ssys_read,
        !           531:    ssys_read
        !           532: };
        !           533: 
        !           534: static CPUWriteMemoryFunc *ssys_writefn[] = {
        !           535:    ssys_write,
        !           536:    ssys_write,
        !           537:    ssys_write
        !           538: };
        !           539: 
        !           540: static void ssys_reset(void *opaque)
        !           541: {
        !           542:     ssys_state *s = (ssys_state *)opaque;
        !           543: 
        !           544:     s->pborctl = 0x7ffd;
        !           545:     s->rcc = 0x078e3ac0;
        !           546:     s->rcgc[0] = 1;
        !           547:     s->scgc[0] = 1;
        !           548:     s->dcgc[0] = 1;
        !           549: }
        !           550: 
        !           551: static void stellaris_sys_init(uint32_t base, qemu_irq irq,
        !           552:                                stellaris_board_info * board,
        !           553:                                uint8_t *macaddr)
        !           554: {
        !           555:     int iomemtype;
        !           556:     ssys_state *s;
        !           557: 
        !           558:     s = (ssys_state *)qemu_mallocz(sizeof(ssys_state));
        !           559:     s->base = base;
        !           560:     s->irq = irq;
        !           561:     s->board = board;
        !           562:     /* Most devices come preprogrammed with a MAC address in the user data. */
        !           563:     s->user0 = macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16);
        !           564:     s->user1 = macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16);
        !           565: 
        !           566:     iomemtype = cpu_register_io_memory(0, ssys_readfn,
        !           567:                                        ssys_writefn, s);
        !           568:     cpu_register_physical_memory(base, 0x00001000, iomemtype);
        !           569:     ssys_reset(s);
        !           570:     /* ??? Save/restore.  */
        !           571: }
        !           572: 
        !           573: 
        !           574: /* I2C controller.  */
        !           575: 
        !           576: typedef struct {
        !           577:     i2c_bus *bus;
        !           578:     qemu_irq irq;
        !           579:     uint32_t base;
        !           580:     uint32_t msa;
        !           581:     uint32_t mcs;
        !           582:     uint32_t mdr;
        !           583:     uint32_t mtpr;
        !           584:     uint32_t mimr;
        !           585:     uint32_t mris;
        !           586:     uint32_t mcr;
        !           587: } stellaris_i2c_state;
        !           588: 
        !           589: #define STELLARIS_I2C_MCS_BUSY    0x01
        !           590: #define STELLARIS_I2C_MCS_ERROR   0x02
        !           591: #define STELLARIS_I2C_MCS_ADRACK  0x04
        !           592: #define STELLARIS_I2C_MCS_DATACK  0x08
        !           593: #define STELLARIS_I2C_MCS_ARBLST  0x10
        !           594: #define STELLARIS_I2C_MCS_IDLE    0x20
        !           595: #define STELLARIS_I2C_MCS_BUSBSY  0x40
        !           596: 
        !           597: static uint32_t stellaris_i2c_read(void *opaque, target_phys_addr_t offset)
        !           598: {
        !           599:     stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
        !           600: 
        !           601:     offset -= s->base;
        !           602:     switch (offset) {
        !           603:     case 0x00: /* MSA */
        !           604:         return s->msa;
        !           605:     case 0x04: /* MCS */
        !           606:         /* We don't emulate timing, so the controller is never busy.  */
        !           607:         return s->mcs | STELLARIS_I2C_MCS_IDLE;
        !           608:     case 0x08: /* MDR */
        !           609:         return s->mdr;
        !           610:     case 0x0c: /* MTPR */
        !           611:         return s->mtpr;
        !           612:     case 0x10: /* MIMR */
        !           613:         return s->mimr;
        !           614:     case 0x14: /* MRIS */
        !           615:         return s->mris;
        !           616:     case 0x18: /* MMIS */
        !           617:         return s->mris & s->mimr;
        !           618:     case 0x20: /* MCR */
        !           619:         return s->mcr;
        !           620:     default:
        !           621:         cpu_abort(cpu_single_env, "strllaris_i2c_read: Bad offset 0x%x\n",
        !           622:                   (int)offset);
        !           623:         return 0;
        !           624:     }
        !           625: }
        !           626: 
        !           627: static void stellaris_i2c_update(stellaris_i2c_state *s)
        !           628: {
        !           629:     int level;
        !           630: 
        !           631:     level = (s->mris & s->mimr) != 0;
        !           632:     qemu_set_irq(s->irq, level);
        !           633: }
        !           634: 
        !           635: static void stellaris_i2c_write(void *opaque, target_phys_addr_t offset,
        !           636:                                 uint32_t value)
        !           637: {
        !           638:     stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
        !           639: 
        !           640:     offset -= s->base;
        !           641:     switch (offset) {
        !           642:     case 0x00: /* MSA */
        !           643:         s->msa = value & 0xff;
        !           644:         break;
        !           645:     case 0x04: /* MCS */
        !           646:         if ((s->mcr & 0x10) == 0) {
        !           647:             /* Disabled.  Do nothing.  */
        !           648:             break;
        !           649:         }
        !           650:         /* Grab the bus if this is starting a transfer.  */
        !           651:         if ((value & 2) && (s->mcs & STELLARIS_I2C_MCS_BUSBSY) == 0) {
        !           652:             if (i2c_start_transfer(s->bus, s->msa >> 1, s->msa & 1)) {
        !           653:                 s->mcs |= STELLARIS_I2C_MCS_ARBLST;
        !           654:             } else {
        !           655:                 s->mcs &= ~STELLARIS_I2C_MCS_ARBLST;
        !           656:                 s->mcs |= STELLARIS_I2C_MCS_BUSBSY;
        !           657:             }
        !           658:         }
        !           659:         /* If we don't have the bus then indicate an error.  */
        !           660:         if (!i2c_bus_busy(s->bus)
        !           661:                 || (s->mcs & STELLARIS_I2C_MCS_BUSBSY) == 0) {
        !           662:             s->mcs |= STELLARIS_I2C_MCS_ERROR;
        !           663:             break;
        !           664:         }
        !           665:         s->mcs &= ~STELLARIS_I2C_MCS_ERROR;
        !           666:         if (value & 1) {
        !           667:             /* Transfer a byte.  */
        !           668:             /* TODO: Handle errors.  */
        !           669:             if (s->msa & 1) {
        !           670:                 /* Recv */
        !           671:                 s->mdr = i2c_recv(s->bus) & 0xff;
        !           672:             } else {
        !           673:                 /* Send */
        !           674:                 i2c_send(s->bus, s->mdr);
        !           675:             }
        !           676:             /* Raise an interrupt.  */
        !           677:             s->mris |= 1;
        !           678:         }
        !           679:         if (value & 4) {
        !           680:             /* Finish transfer.  */
        !           681:             i2c_end_transfer(s->bus);
        !           682:             s->mcs &= ~STELLARIS_I2C_MCS_BUSBSY;
        !           683:         }
        !           684:         break;
        !           685:     case 0x08: /* MDR */
        !           686:         s->mdr = value & 0xff;
        !           687:         break;
        !           688:     case 0x0c: /* MTPR */
        !           689:         s->mtpr = value & 0xff;
        !           690:         break;
        !           691:     case 0x10: /* MIMR */
        !           692:         s->mimr = 1;
        !           693:         break;
        !           694:     case 0x1c: /* MICR */
        !           695:         s->mris &= ~value;
        !           696:         break;
        !           697:     case 0x20: /* MCR */
        !           698:         if (value & 1)
        !           699:             cpu_abort(cpu_single_env,
        !           700:                       "stellaris_i2c_write: Loopback not implemented\n");
        !           701:         if (value & 0x20)
        !           702:             cpu_abort(cpu_single_env,
        !           703:                       "stellaris_i2c_write: Slave mode not implemented\n");
        !           704:         s->mcr = value & 0x31;
        !           705:         break;
        !           706:     default:
        !           707:         cpu_abort(cpu_single_env, "stellaris_i2c_write: Bad offset 0x%x\n",
        !           708:                   (int)offset);
        !           709:     }
        !           710:     stellaris_i2c_update(s);
        !           711: }
        !           712: 
        !           713: static void stellaris_i2c_reset(stellaris_i2c_state *s)
        !           714: {
        !           715:     if (s->mcs & STELLARIS_I2C_MCS_BUSBSY)
        !           716:         i2c_end_transfer(s->bus);
        !           717: 
        !           718:     s->msa = 0;
        !           719:     s->mcs = 0;
        !           720:     s->mdr = 0;
        !           721:     s->mtpr = 1;
        !           722:     s->mimr = 0;
        !           723:     s->mris = 0;
        !           724:     s->mcr = 0;
        !           725:     stellaris_i2c_update(s);
        !           726: }
        !           727: 
        !           728: static CPUReadMemoryFunc *stellaris_i2c_readfn[] = {
        !           729:    stellaris_i2c_read,
        !           730:    stellaris_i2c_read,
        !           731:    stellaris_i2c_read
        !           732: };
        !           733: 
        !           734: static CPUWriteMemoryFunc *stellaris_i2c_writefn[] = {
        !           735:    stellaris_i2c_write,
        !           736:    stellaris_i2c_write,
        !           737:    stellaris_i2c_write
        !           738: };
        !           739: 
        !           740: static void stellaris_i2c_init(uint32_t base, qemu_irq irq, i2c_bus *bus)
        !           741: {
        !           742:     stellaris_i2c_state *s;
        !           743:     int iomemtype;
        !           744: 
        !           745:     s = (stellaris_i2c_state *)qemu_mallocz(sizeof(stellaris_i2c_state));
        !           746:     s->base = base;
        !           747:     s->irq = irq;
        !           748:     s->bus = bus;
        !           749: 
        !           750:     iomemtype = cpu_register_io_memory(0, stellaris_i2c_readfn,
        !           751:                                        stellaris_i2c_writefn, s);
        !           752:     cpu_register_physical_memory(base, 0x00001000, iomemtype);
        !           753:     /* ??? For now we only implement the master interface.  */
        !           754:     stellaris_i2c_reset(s);
        !           755: }
        !           756: 
        !           757: /* Analogue to Digital Converter.  This is only partially implemented,
        !           758:    enough for applications that use a combined ADC and timer tick.  */
        !           759: 
        !           760: #define STELLARIS_ADC_EM_CONTROLLER 0
        !           761: #define STELLARIS_ADC_EM_COMP       1
        !           762: #define STELLARIS_ADC_EM_EXTERNAL   4
        !           763: #define STELLARIS_ADC_EM_TIMER      5
        !           764: #define STELLARIS_ADC_EM_PWM0       6
        !           765: #define STELLARIS_ADC_EM_PWM1       7
        !           766: #define STELLARIS_ADC_EM_PWM2       8
        !           767: 
        !           768: #define STELLARIS_ADC_FIFO_EMPTY    0x0100
        !           769: #define STELLARIS_ADC_FIFO_FULL     0x1000
        !           770: 
        !           771: typedef struct
        !           772: {
        !           773:     uint32_t base;
        !           774:     uint32_t actss;
        !           775:     uint32_t ris;
        !           776:     uint32_t im;
        !           777:     uint32_t emux;
        !           778:     uint32_t ostat;
        !           779:     uint32_t ustat;
        !           780:     uint32_t sspri;
        !           781:     uint32_t sac;
        !           782:     struct {
        !           783:         uint32_t state;
        !           784:         uint32_t data[16];
        !           785:     } fifo[4];
        !           786:     uint32_t ssmux[4];
        !           787:     uint32_t ssctl[4];
        !           788:     qemu_irq irq;
        !           789: } stellaris_adc_state;
        !           790: 
        !           791: static uint32_t stellaris_adc_fifo_read(stellaris_adc_state *s, int n)
        !           792: {
        !           793:     int tail;
        !           794: 
        !           795:     tail = s->fifo[n].state & 0xf;
        !           796:     if (s->fifo[n].state & STELLARIS_ADC_FIFO_EMPTY) {
        !           797:         s->ustat |= 1 << n;
        !           798:     } else {
        !           799:         s->fifo[n].state = (s->fifo[n].state & ~0xf) | ((tail + 1) & 0xf);
        !           800:         s->fifo[n].state &= ~STELLARIS_ADC_FIFO_FULL;
        !           801:         if (tail + 1 == ((s->fifo[n].state >> 4) & 0xf))
        !           802:             s->fifo[n].state |= STELLARIS_ADC_FIFO_EMPTY;
        !           803:     }
        !           804:     return s->fifo[n].data[tail];
        !           805: }
        !           806: 
        !           807: static void stellaris_adc_fifo_write(stellaris_adc_state *s, int n,
        !           808:                                      uint32_t value)
        !           809: {
        !           810:     int head;
        !           811: 
        !           812:     head = (s->fifo[n].state >> 4) & 0xf;
        !           813:     if (s->fifo[n].state & STELLARIS_ADC_FIFO_FULL) {
        !           814:         s->ostat |= 1 << n;
        !           815:         return;
        !           816:     }
        !           817:     s->fifo[n].data[head] = value;
        !           818:     head = (head + 1) & 0xf;
        !           819:     s->fifo[n].state &= ~STELLARIS_ADC_FIFO_EMPTY;
        !           820:     s->fifo[n].state = (s->fifo[n].state & ~0xf0) | (head << 4);
        !           821:     if ((s->fifo[n].state & 0xf) == head)
        !           822:         s->fifo[n].state |= STELLARIS_ADC_FIFO_FULL;
        !           823: }
        !           824: 
        !           825: static void stellaris_adc_update(stellaris_adc_state *s)
        !           826: {
        !           827:     int level;
        !           828: 
        !           829:     level = (s->ris & s->im) != 0;
        !           830:     qemu_set_irq(s->irq, level);
        !           831: }
        !           832: 
        !           833: static void stellaris_adc_trigger(void *opaque, int irq, int level)
        !           834: {
        !           835:     stellaris_adc_state *s = (stellaris_adc_state *)opaque;
        !           836:     /* Some applications use the ADC as a random number source, so introduce
        !           837:        some variation into the signal.  */
        !           838:     static uint32_t noise = 0;
        !           839: 
        !           840:     if ((s->actss & 1) == 0) {
        !           841:         return;
        !           842:     }
        !           843: 
        !           844:     noise = noise * 314159 + 1;
        !           845:     /* ??? actual inputs not implemented.  Return an arbitrary value.  */
        !           846:     stellaris_adc_fifo_write(s, 0, 0x200 + ((noise >> 16) & 7));
        !           847:     s->ris |= 1;
        !           848:     stellaris_adc_update(s);
        !           849: }
        !           850: 
        !           851: static void stellaris_adc_reset(stellaris_adc_state *s)
        !           852: {
        !           853:     int n;
        !           854: 
        !           855:     for (n = 0; n < 4; n++) {
        !           856:         s->ssmux[n] = 0;
        !           857:         s->ssctl[n] = 0;
        !           858:         s->fifo[n].state = STELLARIS_ADC_FIFO_EMPTY;
        !           859:     }
        !           860: }
        !           861: 
        !           862: static uint32_t stellaris_adc_read(void *opaque, target_phys_addr_t offset)
        !           863: {
        !           864:     stellaris_adc_state *s = (stellaris_adc_state *)opaque;
        !           865: 
        !           866:     /* TODO: Implement this.  */
        !           867:     offset -= s->base;
        !           868:     if (offset >= 0x40 && offset < 0xc0) {
        !           869:         int n;
        !           870:         n = (offset - 0x40) >> 5;
        !           871:         switch (offset & 0x1f) {
        !           872:         case 0x00: /* SSMUX */
        !           873:             return s->ssmux[n];
        !           874:         case 0x04: /* SSCTL */
        !           875:             return s->ssctl[n];
        !           876:         case 0x08: /* SSFIFO */
        !           877:             return stellaris_adc_fifo_read(s, n);
        !           878:         case 0x0c: /* SSFSTAT */
        !           879:             return s->fifo[n].state;
        !           880:         default:
        !           881:             break;
        !           882:         }
        !           883:     }
        !           884:     switch (offset) {
        !           885:     case 0x00: /* ACTSS */
        !           886:         return s->actss;
        !           887:     case 0x04: /* RIS */
        !           888:         return s->ris;
        !           889:     case 0x08: /* IM */
        !           890:         return s->im;
        !           891:     case 0x0c: /* ISC */
        !           892:         return s->ris & s->im;
        !           893:     case 0x10: /* OSTAT */
        !           894:         return s->ostat;
        !           895:     case 0x14: /* EMUX */
        !           896:         return s->emux;
        !           897:     case 0x18: /* USTAT */
        !           898:         return s->ustat;
        !           899:     case 0x20: /* SSPRI */
        !           900:         return s->sspri;
        !           901:     case 0x30: /* SAC */
        !           902:         return s->sac;
        !           903:     default:
        !           904:         cpu_abort(cpu_single_env, "strllaris_adc_read: Bad offset 0x%x\n",
        !           905:                   (int)offset);
        !           906:         return 0;
        !           907:     }
        !           908: }
        !           909: 
        !           910: static void stellaris_adc_write(void *opaque, target_phys_addr_t offset,
        !           911:                                 uint32_t value)
        !           912: {
        !           913:     stellaris_adc_state *s = (stellaris_adc_state *)opaque;
        !           914: 
        !           915:     /* TODO: Implement this.  */
        !           916:     offset -= s->base;
        !           917:     if (offset >= 0x40 && offset < 0xc0) {
        !           918:         int n;
        !           919:         n = (offset - 0x40) >> 5;
        !           920:         switch (offset & 0x1f) {
        !           921:         case 0x00: /* SSMUX */
        !           922:             s->ssmux[n] = value & 0x33333333;
        !           923:             return;
        !           924:         case 0x04: /* SSCTL */
        !           925:             if (value != 6) {
        !           926:                 cpu_abort(cpu_single_env, "ADC: Unimplemented sequence %x\n",
        !           927:                           value);
        !           928:             }
        !           929:             s->ssctl[n] = value;
        !           930:             return;
        !           931:         default:
        !           932:             break;
        !           933:         }
        !           934:     }
        !           935:     switch (offset) {
        !           936:     case 0x00: /* ACTSS */
        !           937:         s->actss = value & 0xf;
        !           938:         if (value & 0xe) {
        !           939:             cpu_abort(cpu_single_env,
        !           940:                       "Not implemented:  ADC sequencers 1-3\n");
        !           941:         }
        !           942:         break;
        !           943:     case 0x08: /* IM */
        !           944:         s->im = value;
        !           945:         break;
        !           946:     case 0x0c: /* ISC */
        !           947:         s->ris &= ~value;
        !           948:         break;
        !           949:     case 0x10: /* OSTAT */
        !           950:         s->ostat &= ~value;
        !           951:         break;
        !           952:     case 0x14: /* EMUX */
        !           953:         s->emux = value;
        !           954:         break;
        !           955:     case 0x18: /* USTAT */
        !           956:         s->ustat &= ~value;
        !           957:         break;
        !           958:     case 0x20: /* SSPRI */
        !           959:         s->sspri = value;
        !           960:         break;
        !           961:     case 0x28: /* PSSI */
        !           962:         cpu_abort(cpu_single_env, "Not implemented:  ADC sample initiate\n");
        !           963:         break;
        !           964:     case 0x30: /* SAC */
        !           965:         s->sac = value;
        !           966:         break;
        !           967:     default:
        !           968:         cpu_abort(cpu_single_env, "stellaris_adc_write: Bad offset 0x%x\n",
        !           969:                   (int)offset);
        !           970:     }
        !           971:     stellaris_adc_update(s);
        !           972: }
        !           973: 
        !           974: static CPUReadMemoryFunc *stellaris_adc_readfn[] = {
        !           975:    stellaris_adc_read,
        !           976:    stellaris_adc_read,
        !           977:    stellaris_adc_read
        !           978: };
        !           979: 
        !           980: static CPUWriteMemoryFunc *stellaris_adc_writefn[] = {
        !           981:    stellaris_adc_write,
        !           982:    stellaris_adc_write,
        !           983:    stellaris_adc_write
        !           984: };
        !           985: 
        !           986: static qemu_irq stellaris_adc_init(uint32_t base, qemu_irq irq)
        !           987: {
        !           988:     stellaris_adc_state *s;
        !           989:     int iomemtype;
        !           990:     qemu_irq *qi;
        !           991: 
        !           992:     s = (stellaris_adc_state *)qemu_mallocz(sizeof(stellaris_adc_state));
        !           993:     s->base = base;
        !           994:     s->irq = irq;
        !           995: 
        !           996:     iomemtype = cpu_register_io_memory(0, stellaris_adc_readfn,
        !           997:                                        stellaris_adc_writefn, s);
        !           998:     cpu_register_physical_memory(base, 0x00001000, iomemtype);
        !           999:     stellaris_adc_reset(s);
        !          1000:     qi = qemu_allocate_irqs(stellaris_adc_trigger, s, 1);
        !          1001:     return qi[0];
        !          1002: }
        !          1003: 
        !          1004: /* Some boards have both an OLED controller and SD card connected to
        !          1005:    the same SSI port, with the SD card chip select connected to a
        !          1006:    GPIO pin.  Technically the OLED chip select is connected to the SSI
        !          1007:    Fss pin.  We do not bother emulating that as both devices should
        !          1008:    never be selected simultaneously, and our OLED controller ignores stray
        !          1009:    0xff commands that occur when deselecting the SD card.  */
        !          1010: 
        !          1011: typedef struct {
        !          1012:     ssi_xfer_cb xfer_cb[2];
        !          1013:     void *opaque[2];
        !          1014:     qemu_irq irq;
        !          1015:     int current_dev;
        !          1016: } stellaris_ssi_bus_state;
        !          1017: 
        !          1018: static void stellaris_ssi_bus_select(void *opaque, int irq, int level)
        !          1019: {
        !          1020:     stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque;
        !          1021: 
        !          1022:     s->current_dev = level;
        !          1023: }
        !          1024: 
        !          1025: static int stellaris_ssi_bus_xfer(void *opaque, int val)
        !          1026: {
        !          1027:     stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque;
        !          1028: 
        !          1029:     return s->xfer_cb[s->current_dev](s->opaque[s->current_dev], val);
        !          1030: }
        !          1031: 
        !          1032: static void *stellaris_ssi_bus_init(qemu_irq *irqp,
        !          1033:                                     ssi_xfer_cb cb0, void *opaque0,
        !          1034:                                     ssi_xfer_cb cb1, void *opaque1)
        !          1035: {
        !          1036:     qemu_irq *qi;
        !          1037:     stellaris_ssi_bus_state *s;
        !          1038: 
        !          1039:     s = (stellaris_ssi_bus_state *)qemu_mallocz(sizeof(stellaris_ssi_bus_state));
        !          1040:     s->xfer_cb[0] = cb0;
        !          1041:     s->opaque[0] = opaque0;
        !          1042:     s->xfer_cb[1] = cb1;
        !          1043:     s->opaque[1] = opaque1;
        !          1044:     qi = qemu_allocate_irqs(stellaris_ssi_bus_select, s, 1);
        !          1045:     *irqp = *qi;
        !          1046:     return s;
        !          1047: }
        !          1048: 
        !          1049: /* Board init.  */
        !          1050: static stellaris_board_info stellaris_boards[] = {
        !          1051:   { "LM3S811EVB",
        !          1052:     0,
        !          1053:     0x0032000e,
        !          1054:     0x001f001f, /* dc0 */
        !          1055:     0x001132bf,
        !          1056:     0x01071013,
        !          1057:     0x3f0f01ff,
        !          1058:     0x0000001f,
        !          1059:     BP_OLED_I2C
        !          1060:   },
        !          1061:   { "LM3S6965EVB",
        !          1062:     0x10010002,
        !          1063:     0x1073402e,
        !          1064:     0x00ff007f, /* dc0 */
        !          1065:     0x001133ff,
        !          1066:     0x030f5317,
        !          1067:     0x0f0f87ff,
        !          1068:     0x5000007f,
        !          1069:     BP_OLED_SSI | BP_GAMEPAD
        !          1070:   }
        !          1071: };
        !          1072: 
        !          1073: static void stellaris_init(const char *kernel_filename, const char *cpu_model,
        !          1074:                            DisplayState *ds, stellaris_board_info *board)
        !          1075: {
        !          1076:     static const int uart_irq[] = {5, 6, 33, 34};
        !          1077:     static const int timer_irq[] = {19, 21, 23, 35};
        !          1078:     static const uint32_t gpio_addr[7] =
        !          1079:       { 0x40004000, 0x40005000, 0x40006000, 0x40007000,
        !          1080:         0x40024000, 0x40025000, 0x40026000};
        !          1081:     static const int gpio_irq[7] = {0, 1, 2, 3, 4, 30, 31};
        !          1082: 
        !          1083:     qemu_irq *pic;
        !          1084:     qemu_irq *gpio_in[5];
        !          1085:     qemu_irq *gpio_out[5];
        !          1086:     qemu_irq adc;
        !          1087:     int sram_size;
        !          1088:     int flash_size;
        !          1089:     i2c_bus *i2c;
        !          1090:     int i;
        !          1091: 
        !          1092:     flash_size = ((board->dc0 & 0xffff) + 1) << 1;
        !          1093:     sram_size = (board->dc0 >> 18) + 1;
        !          1094:     pic = armv7m_init(flash_size, sram_size, kernel_filename, cpu_model);
        !          1095: 
        !          1096:     if (board->dc1 & (1 << 16)) {
        !          1097:         adc = stellaris_adc_init(0x40038000, pic[14]);
        !          1098:     } else {
        !          1099:         adc = NULL;
        !          1100:     }
        !          1101:     for (i = 0; i < 4; i++) {
        !          1102:         if (board->dc2 & (0x10000 << i)) {
        !          1103:             stellaris_gptm_init(0x40030000 + i * 0x1000,
        !          1104:                                 pic[timer_irq[i]], adc);
        !          1105:         }
        !          1106:     }
        !          1107: 
        !          1108:     stellaris_sys_init(0x400fe000, pic[28], board, nd_table[0].macaddr);
        !          1109: 
        !          1110:     for (i = 0; i < 7; i++) {
        !          1111:         if (board->dc4 & (1 << i)) {
        !          1112:             gpio_in[i] = pl061_init(gpio_addr[i], pic[gpio_irq[i]],
        !          1113:                                     &gpio_out[i]);
        !          1114:         }
        !          1115:     }
        !          1116: 
        !          1117:     if (board->dc2 & (1 << 12)) {
        !          1118:         i2c = i2c_init_bus();
        !          1119:         stellaris_i2c_init(0x40020000, pic[8], i2c);
        !          1120:         if (board->peripherals & BP_OLED_I2C) {
        !          1121:             ssd0303_init(ds, i2c, 0x3d);
        !          1122:         }
        !          1123:     }
        !          1124: 
        !          1125:     for (i = 0; i < 4; i++) {
        !          1126:         if (board->dc2 & (1 << i)) {
        !          1127:             pl011_init(0x4000c000 + i * 0x1000, pic[uart_irq[i]],
        !          1128:                        serial_hds[i], PL011_LUMINARY);
        !          1129:         }
        !          1130:     }
        !          1131:     if (board->dc2 & (1 << 4)) {
        !          1132:         if (board->peripherals & BP_OLED_SSI) {
        !          1133:             void * oled;
        !          1134:             void * sd;
        !          1135:             void *ssi_bus;
        !          1136:             int index;
        !          1137: 
        !          1138:             oled = ssd0323_init(ds, &gpio_out[GPIO_C][7]);
        !          1139:             index = drive_get_index(IF_SD, 0, 0);
        !          1140:             sd = ssi_sd_init(drives_table[index].bdrv);
        !          1141: 
        !          1142:             ssi_bus = stellaris_ssi_bus_init(&gpio_out[GPIO_D][0],
        !          1143:                                              ssi_sd_xfer, sd,
        !          1144:                                              ssd0323_xfer_ssi, oled);
        !          1145: 
        !          1146:             pl022_init(0x40008000, pic[7], stellaris_ssi_bus_xfer, ssi_bus);
        !          1147:             /* Make sure the select pin is high.  */
        !          1148:             qemu_irq_raise(gpio_out[GPIO_D][0]);
        !          1149:         } else {
        !          1150:             pl022_init(0x40008000, pic[7], NULL, NULL);
        !          1151:         }
        !          1152:     }
        !          1153:     if (board->dc4 & (1 << 28)) {
        !          1154:         /* FIXME: Obey network model.  */
        !          1155:         stellaris_enet_init(&nd_table[0], 0x40048000, pic[42]);
        !          1156:     }
        !          1157:     if (board->peripherals & BP_GAMEPAD) {
        !          1158:         qemu_irq gpad_irq[5];
        !          1159:         static const int gpad_keycode[5] = { 0xc8, 0xd0, 0xcb, 0xcd, 0x1d };
        !          1160: 
        !          1161:         gpad_irq[0] = qemu_irq_invert(gpio_in[GPIO_E][0]); /* up */
        !          1162:         gpad_irq[1] = qemu_irq_invert(gpio_in[GPIO_E][1]); /* down */
        !          1163:         gpad_irq[2] = qemu_irq_invert(gpio_in[GPIO_E][2]); /* left */
        !          1164:         gpad_irq[3] = qemu_irq_invert(gpio_in[GPIO_E][3]); /* right */
        !          1165:         gpad_irq[4] = qemu_irq_invert(gpio_in[GPIO_F][1]); /* select */
        !          1166: 
        !          1167:         stellaris_gamepad_init(5, gpad_irq, gpad_keycode);
        !          1168:     }
        !          1169: }
        !          1170: 
        !          1171: /* FIXME: Figure out how to generate these from stellaris_boards.  */
        !          1172: static void lm3s811evb_init(int ram_size, int vga_ram_size,
        !          1173:                      const char *boot_device, DisplayState *ds,
        !          1174:                      const char *kernel_filename, const char *kernel_cmdline,
        !          1175:                      const char *initrd_filename, const char *cpu_model)
        !          1176: {
        !          1177:     stellaris_init(kernel_filename, cpu_model, ds, &stellaris_boards[0]);
        !          1178: }
        !          1179: 
        !          1180: static void lm3s6965evb_init(int ram_size, int vga_ram_size,
        !          1181:                      const char *boot_device, DisplayState *ds,
        !          1182:                      const char *kernel_filename, const char *kernel_cmdline,
        !          1183:                      const char *initrd_filename, const char *cpu_model)
        !          1184: {
        !          1185:     stellaris_init(kernel_filename, cpu_model, ds, &stellaris_boards[1]);
        !          1186: }
        !          1187: 
        !          1188: QEMUMachine lm3s811evb_machine = {
        !          1189:     "lm3s811evb",
        !          1190:     "Stellaris LM3S811EVB",
        !          1191:     lm3s811evb_init,
        !          1192: };
        !          1193: 
        !          1194: QEMUMachine lm3s6965evb_machine = {
        !          1195:     "lm3s6965evb",
        !          1196:     "Stellaris LM3S6965EVB",
        !          1197:     lm3s6965evb_init,
        !          1198: };

unix.superglobalmegacorp.com

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