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

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"
                     14: 
                     15: #define SYS_FREQ 66000000
                     16: 
                     17: #define PCSR_EN         0x0001
                     18: #define PCSR_RLD        0x0002
                     19: #define PCSR_PIF        0x0004
                     20: #define PCSR_PIE        0x0008
                     21: #define PCSR_OVW        0x0010
                     22: #define PCSR_DBG        0x0020
                     23: #define PCSR_DOZE       0x0040
                     24: #define PCSR_PRE_SHIFT  8
                     25: #define PCSR_PRE_MASK   0x0f00
                     26: 
                     27: typedef struct {
                     28:     qemu_irq irq;
                     29:     ptimer_state *timer;
                     30:     uint16_t pcsr;
                     31:     uint16_t pmr;
                     32:     uint16_t pcntr;
                     33: } m5208_timer_state;
                     34: 
                     35: static void m5208_timer_update(m5208_timer_state *s)
                     36: {
                     37:     if ((s->pcsr & (PCSR_PIE | PCSR_PIF)) == (PCSR_PIE | PCSR_PIF))
                     38:         qemu_irq_raise(s->irq);
                     39:     else
                     40:         qemu_irq_lower(s->irq);
                     41: }
                     42: 
1.1.1.2   root       43: static void m5208_timer_write(void *opaque, target_phys_addr_t offset,
1.1       root       44:                               uint32_t value)
                     45: {
1.1.1.2   root       46:     m5208_timer_state *s = (m5208_timer_state *)opaque;
1.1       root       47:     int prescale;
                     48:     int limit;
                     49:     switch (offset) {
                     50:     case 0:
                     51:         /* The PIF bit is set-to-clear.  */
                     52:         if (value & PCSR_PIF) {
                     53:             s->pcsr &= ~PCSR_PIF;
                     54:             value &= ~PCSR_PIF;
                     55:         }
                     56:         /* Avoid frobbing the timer if we're just twiddling IRQ bits. */
                     57:         if (((s->pcsr ^ value) & ~PCSR_PIE) == 0) {
                     58:             s->pcsr = value;
                     59:             m5208_timer_update(s);
                     60:             return;
                     61:         }
                     62: 
                     63:         if (s->pcsr & PCSR_EN)
                     64:             ptimer_stop(s->timer);
                     65: 
                     66:         s->pcsr = value;
                     67: 
                     68:         prescale = 1 << ((s->pcsr & PCSR_PRE_MASK) >> PCSR_PRE_SHIFT);
                     69:         ptimer_set_freq(s->timer, (SYS_FREQ / 2) / prescale);
                     70:         if (s->pcsr & PCSR_RLD)
                     71:             limit = s->pmr;
                     72:         else
                     73:             limit = 0xffff;
                     74:         ptimer_set_limit(s->timer, limit, 0);
                     75: 
                     76:         if (s->pcsr & PCSR_EN)
                     77:             ptimer_run(s->timer, 0);
                     78:         break;
                     79:     case 2:
                     80:         s->pmr = value;
                     81:         s->pcsr &= ~PCSR_PIF;
                     82:         if ((s->pcsr & PCSR_RLD) == 0) {
                     83:             if (s->pcsr & PCSR_OVW)
                     84:                 ptimer_set_count(s->timer, value);
                     85:         } else {
                     86:             ptimer_set_limit(s->timer, value, s->pcsr & PCSR_OVW);
                     87:         }
                     88:         break;
                     89:     case 4:
                     90:         break;
                     91:     default:
1.1.1.3 ! root       92:         hw_error("m5208_timer_write: Bad offset 0x%x\n", (int)offset);
1.1.1.2   root       93:         break;
1.1       root       94:     }
                     95:     m5208_timer_update(s);
                     96: }
                     97: 
                     98: static void m5208_timer_trigger(void *opaque)
                     99: {
                    100:     m5208_timer_state *s = (m5208_timer_state *)opaque;
                    101:     s->pcsr |= PCSR_PIF;
                    102:     m5208_timer_update(s);
                    103: }
                    104: 
1.1.1.2   root      105: static uint32_t m5208_timer_read(void *opaque, target_phys_addr_t addr)
                    106: {
                    107:     m5208_timer_state *s = (m5208_timer_state *)opaque;
                    108:     switch (addr) {
                    109:     case 0:
                    110:         return s->pcsr;
                    111:     case 2:
                    112:         return s->pmr;
                    113:     case 4:
                    114:         return ptimer_get_count(s->timer);
                    115:     default:
1.1.1.3 ! root      116:         hw_error("m5208_timer_read: Bad offset 0x%x\n", (int)addr);
1.1.1.2   root      117:         return 0;
                    118:     }
                    119: }
                    120: 
                    121: static CPUReadMemoryFunc *m5208_timer_readfn[] = {
                    122:    m5208_timer_read,
                    123:    m5208_timer_read,
                    124:    m5208_timer_read
                    125: };
                    126: 
                    127: static CPUWriteMemoryFunc *m5208_timer_writefn[] = {
                    128:    m5208_timer_write,
                    129:    m5208_timer_write,
                    130:    m5208_timer_write
                    131: };
1.1       root      132: 
                    133: static uint32_t m5208_sys_read(void *opaque, target_phys_addr_t addr)
                    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,
                    155:                             uint32_t value)
                    156: {
1.1.1.3 ! root      157:     hw_error("m5208_sys_write: Bad offset 0x%x\n", (int)addr);
1.1       root      158: }
                    159: 
                    160: static CPUReadMemoryFunc *m5208_sys_readfn[] = {
                    161:    m5208_sys_read,
                    162:    m5208_sys_read,
                    163:    m5208_sys_read
                    164: };
                    165: 
                    166: static CPUWriteMemoryFunc *m5208_sys_writefn[] = {
                    167:    m5208_sys_write,
                    168:    m5208_sys_write,
                    169:    m5208_sys_write
                    170: };
                    171: 
                    172: static void mcf5208_sys_init(qemu_irq *pic)
                    173: {
                    174:     int iomemtype;
1.1.1.2   root      175:     m5208_timer_state *s;
1.1       root      176:     QEMUBH *bh;
                    177:     int i;
                    178: 
1.1.1.3 ! root      179:     iomemtype = cpu_register_io_memory(m5208_sys_readfn,
1.1.1.2   root      180:                                        m5208_sys_writefn, NULL);
1.1       root      181:     /* SDRAMC.  */
                    182:     cpu_register_physical_memory(0xfc0a8000, 0x00004000, iomemtype);
                    183:     /* Timers.  */
                    184:     for (i = 0; i < 2; i++) {
1.1.1.2   root      185:         s = (m5208_timer_state *)qemu_mallocz(sizeof(m5208_timer_state));
                    186:         bh = qemu_bh_new(m5208_timer_trigger, s);
                    187:         s->timer = ptimer_init(bh);
1.1.1.3 ! root      188:         iomemtype = cpu_register_io_memory(m5208_timer_readfn,
1.1.1.2   root      189:                                            m5208_timer_writefn, s);
1.1       root      190:         cpu_register_physical_memory(0xfc080000 + 0x4000 * i, 0x00004000,
                    191:                                      iomemtype);
1.1.1.2   root      192:         s->irq = pic[4 + i];
1.1       root      193:     }
                    194: }
                    195: 
1.1.1.3 ! root      196: static void mcf5208evb_init(ram_addr_t ram_size,
1.1.1.2   root      197:                      const char *boot_device,
1.1       root      198:                      const char *kernel_filename, const char *kernel_cmdline,
                    199:                      const char *initrd_filename, const char *cpu_model)
                    200: {
                    201:     CPUState *env;
                    202:     int kernel_size;
                    203:     uint64_t elf_entry;
                    204:     target_ulong entry;
                    205:     qemu_irq *pic;
                    206: 
                    207:     if (!cpu_model)
                    208:         cpu_model = "m5208";
                    209:     env = cpu_init(cpu_model);
                    210:     if (!env) {
                    211:         fprintf(stderr, "Unable to find m68k CPU definition\n");
                    212:         exit(1);
                    213:     }
                    214: 
                    215:     /* Initialize CPU registers.  */
                    216:     env->vbr = 0;
                    217:     /* TODO: Configure BARs.  */
                    218: 
1.1.1.3 ! root      219:     /* DRAM at 0x40000000 */
1.1       root      220:     cpu_register_physical_memory(0x40000000, ram_size,
                    221:         qemu_ram_alloc(ram_size) | IO_MEM_RAM);
                    222: 
                    223:     /* Internal SRAM.  */
                    224:     cpu_register_physical_memory(0x80000000, 16384,
                    225:         qemu_ram_alloc(16384) | IO_MEM_RAM);
                    226: 
                    227:     /* Internal peripherals.  */
                    228:     pic = mcf_intc_init(0xfc048000, env);
                    229: 
                    230:     mcf_uart_mm_init(0xfc060000, pic[26], serial_hds[0]);
                    231:     mcf_uart_mm_init(0xfc064000, pic[27], serial_hds[1]);
                    232:     mcf_uart_mm_init(0xfc068000, pic[28], serial_hds[2]);
                    233: 
                    234:     mcf5208_sys_init(pic);
                    235: 
                    236:     if (nb_nics > 1) {
                    237:         fprintf(stderr, "Too many NICs\n");
                    238:         exit(1);
                    239:     }
1.1.1.2   root      240:     if (nd_table[0].vlan)
                    241:         mcf_fec_init(&nd_table[0], 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: 
                    271:     kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL);
                    272:     entry = elf_entry;
                    273:     if (kernel_size < 0) {
1.1.1.2   root      274:         kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
1.1       root      275:     }
                    276:     if (kernel_size < 0) {
1.1.1.3 ! root      277:         kernel_size = load_image_targphys(kernel_filename, 0x40000000,
        !           278:                                           ram_size);
        !           279:         entry = 0x40000000;
1.1       root      280:     }
                    281:     if (kernel_size < 0) {
                    282:         fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
                    283:         exit(1);
                    284:     }
                    285: 
                    286:     env->pc = entry;
                    287: }
                    288: 
1.1.1.3 ! root      289: static QEMUMachine mcf5208evb_machine = {
1.1.1.2   root      290:     .name = "mcf5208evb",
                    291:     .desc = "MCF5206EVB",
                    292:     .init = mcf5208evb_init,
1.1.1.3 ! root      293:     .is_default = 1,
1.1       root      294: };
1.1.1.3 ! root      295: 
        !           296: static void mcf5208evb_machine_init(void)
        !           297: {
        !           298:     qemu_register_machine(&mcf5208evb_machine);
        !           299: }
        !           300: 
        !           301: 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.