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

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