Annotation of qemu/hw/mcf5208.c, revision 1.1.1.8

1.1       root        1: /*
                      2:  * Motorola ColdFire MCF5208 SoC emulation.
                      3:  *
                      4:  * Copyright (c) 2007 CodeSourcery.
                      5:  *
1.1.1.7   root        6:  * This code is licensed under the GPL
1.1       root        7:  */
                      8: #include "hw.h"
                      9: #include "mcf.h"
                     10: #include "qemu-timer.h"
                     11: #include "sysemu.h"
                     12: #include "net.h"
                     13: #include "boards.h"
1.1.1.4   root       14: #include "loader.h"
                     15: #include "elf.h"
1.1.1.8 ! root       16: #include "exec-memory.h"
1.1       root       17: 
                     18: #define SYS_FREQ 66000000
                     19: 
                     20: #define PCSR_EN         0x0001
                     21: #define PCSR_RLD        0x0002
                     22: #define PCSR_PIF        0x0004
                     23: #define PCSR_PIE        0x0008
                     24: #define PCSR_OVW        0x0010
                     25: #define PCSR_DBG        0x0020
                     26: #define PCSR_DOZE       0x0040
                     27: #define PCSR_PRE_SHIFT  8
                     28: #define PCSR_PRE_MASK   0x0f00
                     29: 
                     30: typedef struct {
1.1.1.8 ! root       31:     MemoryRegion iomem;
1.1       root       32:     qemu_irq irq;
                     33:     ptimer_state *timer;
                     34:     uint16_t pcsr;
                     35:     uint16_t pmr;
                     36:     uint16_t pcntr;
                     37: } m5208_timer_state;
                     38: 
                     39: static void m5208_timer_update(m5208_timer_state *s)
                     40: {
                     41:     if ((s->pcsr & (PCSR_PIE | PCSR_PIF)) == (PCSR_PIE | PCSR_PIF))
                     42:         qemu_irq_raise(s->irq);
                     43:     else
                     44:         qemu_irq_lower(s->irq);
                     45: }
                     46: 
1.1.1.2   root       47: static void m5208_timer_write(void *opaque, target_phys_addr_t offset,
1.1.1.8 ! root       48:                               uint64_t value, unsigned size)
1.1       root       49: {
1.1.1.2   root       50:     m5208_timer_state *s = (m5208_timer_state *)opaque;
1.1       root       51:     int prescale;
                     52:     int limit;
                     53:     switch (offset) {
                     54:     case 0:
                     55:         /* The PIF bit is set-to-clear.  */
                     56:         if (value & PCSR_PIF) {
                     57:             s->pcsr &= ~PCSR_PIF;
                     58:             value &= ~PCSR_PIF;
                     59:         }
                     60:         /* Avoid frobbing the timer if we're just twiddling IRQ bits. */
                     61:         if (((s->pcsr ^ value) & ~PCSR_PIE) == 0) {
                     62:             s->pcsr = value;
                     63:             m5208_timer_update(s);
                     64:             return;
                     65:         }
                     66: 
                     67:         if (s->pcsr & PCSR_EN)
                     68:             ptimer_stop(s->timer);
                     69: 
                     70:         s->pcsr = value;
                     71: 
                     72:         prescale = 1 << ((s->pcsr & PCSR_PRE_MASK) >> PCSR_PRE_SHIFT);
                     73:         ptimer_set_freq(s->timer, (SYS_FREQ / 2) / prescale);
                     74:         if (s->pcsr & PCSR_RLD)
                     75:             limit = s->pmr;
                     76:         else
                     77:             limit = 0xffff;
                     78:         ptimer_set_limit(s->timer, limit, 0);
                     79: 
                     80:         if (s->pcsr & PCSR_EN)
                     81:             ptimer_run(s->timer, 0);
                     82:         break;
                     83:     case 2:
                     84:         s->pmr = value;
                     85:         s->pcsr &= ~PCSR_PIF;
                     86:         if ((s->pcsr & PCSR_RLD) == 0) {
                     87:             if (s->pcsr & PCSR_OVW)
                     88:                 ptimer_set_count(s->timer, value);
                     89:         } else {
                     90:             ptimer_set_limit(s->timer, value, s->pcsr & PCSR_OVW);
                     91:         }
                     92:         break;
                     93:     case 4:
                     94:         break;
                     95:     default:
1.1.1.3   root       96:         hw_error("m5208_timer_write: Bad offset 0x%x\n", (int)offset);
1.1.1.2   root       97:         break;
1.1       root       98:     }
                     99:     m5208_timer_update(s);
                    100: }
                    101: 
                    102: static void m5208_timer_trigger(void *opaque)
                    103: {
                    104:     m5208_timer_state *s = (m5208_timer_state *)opaque;
                    105:     s->pcsr |= PCSR_PIF;
                    106:     m5208_timer_update(s);
                    107: }
                    108: 
1.1.1.8 ! root      109: static uint64_t m5208_timer_read(void *opaque, target_phys_addr_t addr,
        !           110:                                  unsigned size)
1.1.1.2   root      111: {
                    112:     m5208_timer_state *s = (m5208_timer_state *)opaque;
                    113:     switch (addr) {
                    114:     case 0:
                    115:         return s->pcsr;
                    116:     case 2:
                    117:         return s->pmr;
                    118:     case 4:
                    119:         return ptimer_get_count(s->timer);
                    120:     default:
1.1.1.3   root      121:         hw_error("m5208_timer_read: Bad offset 0x%x\n", (int)addr);
1.1.1.2   root      122:         return 0;
                    123:     }
                    124: }
                    125: 
1.1.1.8 ! root      126: static const MemoryRegionOps m5208_timer_ops = {
        !           127:     .read = m5208_timer_read,
        !           128:     .write = m5208_timer_write,
        !           129:     .endianness = DEVICE_NATIVE_ENDIAN,
1.1.1.2   root      130: };
                    131: 
1.1.1.8 ! root      132: static uint64_t m5208_sys_read(void *opaque, target_phys_addr_t addr,
        !           133:                                unsigned size)
1.1       root      134: {
                    135:     switch (addr) {
1.1.1.2   root      136:     case 0x110: /* SDCS0 */
1.1       root      137:         {
                    138:             int n;
                    139:             for (n = 0; n < 32; n++) {
                    140:                 if (ram_size < (2u << n))
                    141:                     break;
                    142:             }
                    143:             return (n - 1)  | 0x40000000;
                    144:         }
1.1.1.2   root      145:     case 0x114: /* SDCS1 */
1.1       root      146:         return 0;
                    147: 
                    148:     default:
1.1.1.3   root      149:         hw_error("m5208_sys_read: Bad offset 0x%x\n", (int)addr);
1.1       root      150:         return 0;
                    151:     }
                    152: }
                    153: 
                    154: static void m5208_sys_write(void *opaque, target_phys_addr_t addr,
1.1.1.8 ! root      155:                             uint64_t value, unsigned size)
1.1       root      156: {
1.1.1.3   root      157:     hw_error("m5208_sys_write: Bad offset 0x%x\n", (int)addr);
1.1       root      158: }
                    159: 
1.1.1.8 ! root      160: static const MemoryRegionOps m5208_sys_ops = {
        !           161:     .read = m5208_sys_read,
        !           162:     .write = m5208_sys_write,
        !           163:     .endianness = DEVICE_NATIVE_ENDIAN,
1.1       root      164: };
                    165: 
1.1.1.8 ! root      166: static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic)
1.1       root      167: {
1.1.1.8 ! root      168:     MemoryRegion *iomem = g_new(MemoryRegion, 1);
1.1.1.2   root      169:     m5208_timer_state *s;
1.1       root      170:     QEMUBH *bh;
                    171:     int i;
                    172: 
                    173:     /* SDRAMC.  */
1.1.1.8 ! root      174:     memory_region_init_io(iomem, &m5208_sys_ops, NULL, "m5208-sys", 0x00004000);
        !           175:     memory_region_add_subregion(address_space, 0xfc0a8000, iomem);
1.1       root      176:     /* Timers.  */
                    177:     for (i = 0; i < 2; i++) {
1.1.1.8 ! root      178:         s = (m5208_timer_state *)g_malloc0(sizeof(m5208_timer_state));
1.1.1.2   root      179:         bh = qemu_bh_new(m5208_timer_trigger, s);
                    180:         s->timer = ptimer_init(bh);
1.1.1.8 ! root      181:         memory_region_init_io(&s->iomem, &m5208_timer_ops, s,
        !           182:                               "m5208-timer", 0x00004000);
        !           183:         memory_region_add_subregion(address_space, 0xfc080000 + 0x4000 * i,
        !           184:                                     &s->iomem);
1.1.1.2   root      185:         s->irq = pic[4 + i];
1.1       root      186:     }
                    187: }
                    188: 
1.1.1.3   root      189: static void mcf5208evb_init(ram_addr_t ram_size,
1.1.1.2   root      190:                      const char *boot_device,
1.1       root      191:                      const char *kernel_filename, const char *kernel_cmdline,
                    192:                      const char *initrd_filename, const char *cpu_model)
                    193: {
                    194:     CPUState *env;
                    195:     int kernel_size;
                    196:     uint64_t elf_entry;
1.1.1.4   root      197:     target_phys_addr_t entry;
1.1       root      198:     qemu_irq *pic;
1.1.1.8 ! root      199:     MemoryRegion *address_space_mem = get_system_memory();
        !           200:     MemoryRegion *ram = g_new(MemoryRegion, 1);
        !           201:     MemoryRegion *sram = g_new(MemoryRegion, 1);
1.1       root      202: 
                    203:     if (!cpu_model)
                    204:         cpu_model = "m5208";
                    205:     env = cpu_init(cpu_model);
                    206:     if (!env) {
                    207:         fprintf(stderr, "Unable to find m68k CPU definition\n");
                    208:         exit(1);
                    209:     }
                    210: 
                    211:     /* Initialize CPU registers.  */
                    212:     env->vbr = 0;
                    213:     /* TODO: Configure BARs.  */
                    214: 
1.1.1.3   root      215:     /* DRAM at 0x40000000 */
1.1.1.8 ! root      216:     memory_region_init_ram(ram, NULL, "mcf5208.ram", ram_size);
        !           217:     memory_region_add_subregion(address_space_mem, 0x40000000, ram);
1.1       root      218: 
                    219:     /* Internal SRAM.  */
1.1.1.8 ! root      220:     memory_region_init_ram(sram, NULL, "mcf5208.sram", 16384);
        !           221:     memory_region_add_subregion(address_space_mem, 0x80000000, sram);
1.1       root      222: 
                    223:     /* Internal peripherals.  */
                    224:     pic = mcf_intc_init(0xfc048000, env);
                    225: 
                    226:     mcf_uart_mm_init(0xfc060000, pic[26], serial_hds[0]);
                    227:     mcf_uart_mm_init(0xfc064000, pic[27], serial_hds[1]);
                    228:     mcf_uart_mm_init(0xfc068000, pic[28], serial_hds[2]);
                    229: 
1.1.1.8 ! root      230:     mcf5208_sys_init(address_space_mem, pic);
1.1       root      231: 
                    232:     if (nb_nics > 1) {
                    233:         fprintf(stderr, "Too many NICs\n");
                    234:         exit(1);
                    235:     }
1.1.1.2   root      236:     if (nd_table[0].vlan)
                    237:         mcf_fec_init(&nd_table[0], 0xfc030000, pic + 36);
1.1       root      238: 
                    239:     /*  0xfc000000 SCM.  */
                    240:     /*  0xfc004000 XBS.  */
                    241:     /*  0xfc008000 FlexBus CS.  */
                    242:     /* 0xfc030000 FEC.  */
                    243:     /*  0xfc040000 SCM + Power management.  */
                    244:     /*  0xfc044000 eDMA.  */
                    245:     /* 0xfc048000 INTC.  */
                    246:     /*  0xfc058000 I2C.  */
                    247:     /*  0xfc05c000 QSPI.  */
                    248:     /* 0xfc060000 UART0.  */
                    249:     /* 0xfc064000 UART0.  */
                    250:     /* 0xfc068000 UART0.  */
                    251:     /*  0xfc070000 DMA timers.  */
                    252:     /* 0xfc080000 PIT0.  */
                    253:     /* 0xfc084000 PIT1.  */
                    254:     /*  0xfc088000 EPORT.  */
                    255:     /*  0xfc08c000 Watchdog.  */
                    256:     /*  0xfc090000 clock module.  */
                    257:     /*  0xfc0a0000 CCM + reset.  */
                    258:     /*  0xfc0a4000 GPIO.  */
                    259:     /* 0xfc0a8000 SDRAM controller.  */
                    260: 
                    261:     /* Load kernel.  */
                    262:     if (!kernel_filename) {
                    263:         fprintf(stderr, "Kernel image must be specified\n");
                    264:         exit(1);
                    265:     }
                    266: 
1.1.1.5   root      267:     kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
                    268:                            NULL, NULL, 1, ELF_MACHINE, 0);
1.1       root      269:     entry = elf_entry;
                    270:     if (kernel_size < 0) {
1.1.1.2   root      271:         kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
1.1       root      272:     }
                    273:     if (kernel_size < 0) {
1.1.1.3   root      274:         kernel_size = load_image_targphys(kernel_filename, 0x40000000,
                    275:                                           ram_size);
                    276:         entry = 0x40000000;
1.1       root      277:     }
                    278:     if (kernel_size < 0) {
                    279:         fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
                    280:         exit(1);
                    281:     }
                    282: 
                    283:     env->pc = entry;
                    284: }
                    285: 
1.1.1.3   root      286: static QEMUMachine mcf5208evb_machine = {
1.1.1.2   root      287:     .name = "mcf5208evb",
                    288:     .desc = "MCF5206EVB",
                    289:     .init = mcf5208evb_init,
1.1.1.3   root      290:     .is_default = 1,
1.1       root      291: };
1.1.1.3   root      292: 
                    293: static void mcf5208evb_machine_init(void)
                    294: {
                    295:     qemu_register_machine(&mcf5208evb_machine);
                    296: }
                    297: 
                    298: machine_init(mcf5208evb_machine_init);

unix.superglobalmegacorp.com

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