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

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