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

1.1     ! root        1: /*
        !             2:  * QEMU model for the AXIS devboard 88.
        !             3:  *
        !             4:  * Copyright (c) 2009 Edgar E. Iglesias, Axis Communications AB.
        !             5:  *
        !             6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
        !             7:  * of this software and associated documentation files (the "Software"), to deal
        !             8:  * in the Software without restriction, including without limitation the rights
        !             9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        !            10:  * copies of the Software, and to permit persons to whom the Software is
        !            11:  * furnished to do so, subject to the following conditions:
        !            12:  *
        !            13:  * The above copyright notice and this permission notice shall be included in
        !            14:  * all copies or substantial portions of the Software.
        !            15:  *
        !            16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        !            17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
        !            19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        !            20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        !            21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        !            22:  * THE SOFTWARE.
        !            23:  */
        !            24: #include <time.h>
        !            25: #include <sys/time.h>
        !            26: #include "hw.h"
        !            27: #include "net.h"
        !            28: #include "flash.h"
        !            29: #include "sysemu.h"
        !            30: #include "devices.h"
        !            31: #include "boards.h"
        !            32: 
        !            33: #include "etraxfs.h"
        !            34: 
        !            35: #define D(x)
        !            36: #define DNAND(x)
        !            37: 
        !            38: struct nand_state_t
        !            39: {
        !            40:     struct nand_flash_s *nand;
        !            41:     unsigned int rdy:1;
        !            42:     unsigned int ale:1;
        !            43:     unsigned int cle:1;
        !            44:     unsigned int ce:1;
        !            45: };
        !            46: 
        !            47: static struct nand_state_t nand_state;
        !            48: static uint32_t nand_readl (void *opaque, target_phys_addr_t addr)
        !            49: {
        !            50:     struct nand_state_t *s = opaque;
        !            51:     uint32_t r;
        !            52:     int rdy;
        !            53: 
        !            54:     r = nand_getio(s->nand);
        !            55:     nand_getpins(s->nand, &rdy);
        !            56:     s->rdy = rdy;
        !            57: 
        !            58:     DNAND(printf("%s addr=%x r=%x\n", __func__, addr, r));
        !            59:     return r;
        !            60: }
        !            61: 
        !            62: static void
        !            63: nand_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
        !            64: {
        !            65:     struct nand_state_t *s = opaque;
        !            66:     int rdy;
        !            67: 
        !            68:     DNAND(printf("%s addr=%x v=%x\n", __func__, addr, value));
        !            69:     nand_setpins(s->nand, s->cle, s->ale, s->ce, 1, 0);
        !            70:     nand_setio(s->nand, value);
        !            71:     nand_getpins(s->nand, &rdy);
        !            72:     s->rdy = rdy;
        !            73: }
        !            74: 
        !            75: static CPUReadMemoryFunc *nand_read[] = {
        !            76:     &nand_readl,
        !            77:     &nand_readl,
        !            78:     &nand_readl,
        !            79: };
        !            80: 
        !            81: static CPUWriteMemoryFunc *nand_write[] = {
        !            82:     &nand_writel,
        !            83:     &nand_writel,
        !            84:     &nand_writel,
        !            85: };
        !            86: 
        !            87: 
        !            88: struct tempsensor_t
        !            89: {
        !            90:     unsigned int shiftreg;
        !            91:     unsigned int count;
        !            92:     enum {
        !            93:         ST_OUT, ST_IN, ST_Z
        !            94:     } state;
        !            95: 
        !            96:     uint16_t regs[3];
        !            97: };
        !            98: 
        !            99: static void tempsensor_clkedge(struct tempsensor_t *s,
        !           100:                                unsigned int clk, unsigned int data_in)
        !           101: {
        !           102:     D(printf("%s clk=%d state=%d sr=%x\n", __func__,
        !           103:              clk, s->state, s->shiftreg));
        !           104:     if (s->count == 0) {
        !           105:         s->count = 16;
        !           106:         s->state = ST_OUT;
        !           107:     }
        !           108:     switch (s->state) {
        !           109:         case ST_OUT:
        !           110:             /* Output reg is clocked at negedge.  */
        !           111:             if (!clk) {
        !           112:                 s->count--;
        !           113:                 s->shiftreg <<= 1;
        !           114:                 if (s->count == 0) {
        !           115:                     s->shiftreg = 0;
        !           116:                     s->state = ST_IN;
        !           117:                     s->count = 16;
        !           118:                 }
        !           119:             }
        !           120:             break;
        !           121:         case ST_Z:
        !           122:             if (clk) {
        !           123:                 s->count--;
        !           124:                 if (s->count == 0) {
        !           125:                     s->shiftreg = 0;
        !           126:                     s->state = ST_OUT;
        !           127:                     s->count = 16;
        !           128:                 }
        !           129:             }
        !           130:             break;
        !           131:         case ST_IN:
        !           132:             /* Indata is sampled at posedge.  */
        !           133:             if (clk) {
        !           134:                 s->count--;
        !           135:                 s->shiftreg <<= 1;
        !           136:                 s->shiftreg |= data_in & 1;
        !           137:                 if (s->count == 0) {
        !           138:                     D(printf("%s cfgreg=%x\n", __func__, s->shiftreg));
        !           139:                     s->regs[0] = s->shiftreg;
        !           140:                     s->state = ST_OUT;
        !           141:                     s->count = 16;
        !           142: 
        !           143:                     if ((s->regs[0] & 0xff) == 0) {
        !           144:                         /* 25 degrees celcius.  */
        !           145:                         s->shiftreg = 0x0b9f;
        !           146:                     } else if ((s->regs[0] & 0xff) == 0xff) {
        !           147:                         /* Sensor ID, 0x8100 LM70.  */
        !           148:                         s->shiftreg = 0x8100;
        !           149:                     } else
        !           150:                         printf("Invalid tempsens state %x\n", s->regs[0]);
        !           151:                 }
        !           152:             }
        !           153:             break;
        !           154:     }
        !           155: }
        !           156: 
        !           157: 
        !           158: #define RW_PA_DOUT    0x00
        !           159: #define R_PA_DIN      0x01
        !           160: #define RW_PA_OE      0x02
        !           161: #define RW_PD_DOUT    0x10
        !           162: #define R_PD_DIN      0x11
        !           163: #define RW_PD_OE      0x12
        !           164: 
        !           165: static struct gpio_state_t
        !           166: {
        !           167:     struct nand_state_t *nand;
        !           168:     struct tempsensor_t tempsensor;
        !           169:     uint32_t regs[0x5c / 4];
        !           170: } gpio_state;
        !           171: 
        !           172: static uint32_t gpio_readl (void *opaque, target_phys_addr_t addr)
        !           173: {
        !           174:     struct gpio_state_t *s = opaque;
        !           175:     uint32_t r = 0;
        !           176: 
        !           177:     addr >>= 2;
        !           178:     switch (addr)
        !           179:     {
        !           180:         case R_PA_DIN:
        !           181:             r = s->regs[RW_PA_DOUT] & s->regs[RW_PA_OE];
        !           182: 
        !           183:             /* Encode pins from the nand.  */
        !           184:             r |= s->nand->rdy << 7;
        !           185:             break;
        !           186:         case R_PD_DIN:
        !           187:             r = s->regs[RW_PD_DOUT] & s->regs[RW_PD_OE];
        !           188: 
        !           189:             /* Encode temp sensor pins.  */
        !           190:             r |= (!!(s->tempsensor.shiftreg & 0x10000)) << 4;
        !           191:             break;
        !           192: 
        !           193:         default:
        !           194:             r = s->regs[addr];
        !           195:             break;
        !           196:     }
        !           197:     return r;
        !           198:     D(printf("%s %x=%x\n", __func__, addr, r));
        !           199: }
        !           200: 
        !           201: static void gpio_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
        !           202: {
        !           203:     struct gpio_state_t *s = opaque;
        !           204:     D(printf("%s %x=%x\n", __func__, addr, value));
        !           205: 
        !           206:     addr >>= 2;
        !           207:     switch (addr)
        !           208:     {
        !           209:         case RW_PA_DOUT:
        !           210:             /* Decode nand pins.  */
        !           211:             s->nand->ale = !!(value & (1 << 6));
        !           212:             s->nand->cle = !!(value & (1 << 5));
        !           213:             s->nand->ce  = !!(value & (1 << 4));
        !           214: 
        !           215:             s->regs[addr] = value;
        !           216:             break;
        !           217: 
        !           218:         case RW_PD_DOUT:
        !           219:             /* Temp sensor clk.  */
        !           220:             if ((s->regs[addr] ^ value) & 2)
        !           221:                 tempsensor_clkedge(&s->tempsensor, !!(value & 2),
        !           222:                                    !!(value & 16));
        !           223:             s->regs[addr] = value;
        !           224:             break;
        !           225: 
        !           226:         default:
        !           227:             s->regs[addr] = value;
        !           228:             break;
        !           229:     }
        !           230: }
        !           231: 
        !           232: static CPUReadMemoryFunc *gpio_read[] = {
        !           233:     NULL, NULL,
        !           234:     &gpio_readl,
        !           235: };
        !           236: 
        !           237: static CPUWriteMemoryFunc *gpio_write[] = {
        !           238:     NULL, NULL,
        !           239:     &gpio_writel,
        !           240: };
        !           241: 
        !           242: #define INTMEM_SIZE (128 * 1024)
        !           243: 
        !           244: static uint32_t bootstrap_pc;
        !           245: static void main_cpu_reset(void *opaque)
        !           246: {
        !           247:     CPUState *env = opaque;
        !           248:     cpu_reset(env);
        !           249: 
        !           250:     env->pc = bootstrap_pc;
        !           251: }
        !           252: 
        !           253: static
        !           254: void axisdev88_init (ram_addr_t ram_size, int vga_ram_size,
        !           255:                      const char *boot_device,
        !           256:                      const char *kernel_filename, const char *kernel_cmdline,
        !           257:                      const char *initrd_filename, const char *cpu_model)
        !           258: {
        !           259:     CPUState *env;
        !           260:     struct etraxfs_pic *pic;
        !           261:     void *etraxfs_dmac;
        !           262:     struct etraxfs_dma_client *eth[2] = {NULL, NULL};
        !           263:     int kernel_size;
        !           264:     int i;
        !           265:     int nand_regs;
        !           266:     int gpio_regs;
        !           267:     ram_addr_t phys_ram;
        !           268:     ram_addr_t phys_intmem;
        !           269: 
        !           270:     /* init CPUs */
        !           271:     if (cpu_model == NULL) {
        !           272:         cpu_model = "crisv32";
        !           273:     }
        !           274:     env = cpu_init(cpu_model);
        !           275:     qemu_register_reset(main_cpu_reset, env);
        !           276: 
        !           277:     /* allocate RAM */
        !           278:     phys_ram = qemu_ram_alloc(ram_size);
        !           279:     cpu_register_physical_memory(0x40000000, ram_size, phys_ram | IO_MEM_RAM);
        !           280: 
        !           281:     /* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the 
        !           282:        internal memory.  */
        !           283:     phys_intmem = qemu_ram_alloc(INTMEM_SIZE);
        !           284:     cpu_register_physical_memory(0x38000000, INTMEM_SIZE,
        !           285:                                  phys_intmem | IO_MEM_RAM);
        !           286: 
        !           287: 
        !           288:       /* Attach a NAND flash to CS1.  */
        !           289:     nand_state.nand = nand_init(NAND_MFR_STMICRO, 0x39);
        !           290:     nand_regs = cpu_register_io_memory(0, nand_read, nand_write, &nand_state);
        !           291:     cpu_register_physical_memory(0x10000000, 0x05000000, nand_regs);
        !           292: 
        !           293:     gpio_state.nand = &nand_state;
        !           294:     gpio_regs = cpu_register_io_memory(0, gpio_read, gpio_write, &gpio_state);
        !           295:     cpu_register_physical_memory(0x3001a000, 0x5c, gpio_regs);
        !           296: 
        !           297: 
        !           298:     pic = etraxfs_pic_init(env, 0x3001c000);
        !           299:     etraxfs_dmac = etraxfs_dmac_init(env, 0x30000000, 10);
        !           300:     for (i = 0; i < 10; i++) {
        !           301:         /* On ETRAX, odd numbered channels are inputs.  */
        !           302:         etraxfs_dmac_connect(etraxfs_dmac, i, pic->irq + 7 + i, i & 1);
        !           303:     }
        !           304: 
        !           305:     /* Add the two ethernet blocks.  */
        !           306:     eth[0] = etraxfs_eth_init(&nd_table[0], env, pic->irq + 25, 0x30034000, 1);
        !           307:     if (nb_nics > 1)
        !           308:         eth[1] = etraxfs_eth_init(&nd_table[1], env,
        !           309:                                   pic->irq + 26, 0x30036000, 2);
        !           310: 
        !           311:     /* The DMA Connector block is missing, hardwire things for now.  */
        !           312:     etraxfs_dmac_connect_client(etraxfs_dmac, 0, eth[0]);
        !           313:     etraxfs_dmac_connect_client(etraxfs_dmac, 1, eth[0] + 1);
        !           314:     if (eth[1]) {
        !           315:         etraxfs_dmac_connect_client(etraxfs_dmac, 6, eth[1]);
        !           316:         etraxfs_dmac_connect_client(etraxfs_dmac, 7, eth[1] + 1);
        !           317:     }
        !           318: 
        !           319:     /* 2 timers.  */
        !           320:     etraxfs_timer_init(env, pic->irq + 0x1b, pic->nmi + 1, 0x3001e000);
        !           321:     etraxfs_timer_init(env, pic->irq + 0x1b, pic->nmi + 1, 0x3005e000);
        !           322: 
        !           323:     for (i = 0; i < 4; i++) {
        !           324:         if (serial_hds[i]) {
        !           325:             etraxfs_ser_init(env, pic->irq + 0x14 + i,
        !           326:                              serial_hds[i], 0x30026000 + i * 0x2000);
        !           327:         }
        !           328:     }
        !           329: 
        !           330:     if (kernel_filename) {
        !           331:         uint64_t entry, high;
        !           332:         int kcmdline_len;
        !           333: 
        !           334:         /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis 
        !           335:            devboard SDK.  */
        !           336:         kernel_size = load_elf(kernel_filename, -0x80000000LL,
        !           337:                                &entry, NULL, &high);
        !           338:         bootstrap_pc = entry;
        !           339:         if (kernel_size < 0) {
        !           340:             /* Takes a kimage from the axis devboard SDK.  */
        !           341:             kernel_size = load_image(kernel_filename, phys_ram_base + 0x4000);
        !           342:             bootstrap_pc = 0x40004000;
        !           343:             env->regs[9] = 0x40004000 + kernel_size;
        !           344:         }
        !           345:         env->regs[8] = 0x56902387; /* RAM init magic.  */
        !           346: 
        !           347:         if (kernel_cmdline && (kcmdline_len = strlen(kernel_cmdline))) {
        !           348:             if (kcmdline_len > 256) {
        !           349:                 fprintf(stderr, "Too long CRIS kernel cmdline (max 256)\n");
        !           350:                 exit(1);
        !           351:             }
        !           352:             pstrcpy_targphys(high, 256, kernel_cmdline);
        !           353:             /* Let the kernel know we are modifying the cmdline.  */
        !           354:             env->regs[10] = 0x87109563;
        !           355:             env->regs[11] = high;
        !           356:         }
        !           357:     }
        !           358:     env->pc = bootstrap_pc;
        !           359: 
        !           360:     printf ("pc =%x\n", env->pc);
        !           361:     printf ("ram size =%ld\n", ram_size);
        !           362: }
        !           363: 
        !           364: QEMUMachine axisdev88_machine = {
        !           365:     .name = "axis-dev88",
        !           366:     .desc = "AXIS devboard 88",
        !           367:     .init = axisdev88_init,
        !           368:     .ram_require = 0x8000000,
        !           369: };

unix.superglobalmegacorp.com

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