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

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.2 ! root       92:         cpu_abort(cpu_single_env, "m5208_timer_write: Bad offset 0x%x\n",
        !            93:                   (int)offset);
        !            94:         break;
1.1       root       95:     }
                     96:     m5208_timer_update(s);
                     97: }
                     98: 
                     99: static void m5208_timer_trigger(void *opaque)
                    100: {
                    101:     m5208_timer_state *s = (m5208_timer_state *)opaque;
                    102:     s->pcsr |= PCSR_PIF;
                    103:     m5208_timer_update(s);
                    104: }
                    105: 
1.1.1.2 ! root      106: static uint32_t m5208_timer_read(void *opaque, target_phys_addr_t addr)
        !           107: {
        !           108:     m5208_timer_state *s = (m5208_timer_state *)opaque;
        !           109:     switch (addr) {
        !           110:     case 0:
        !           111:         return s->pcsr;
        !           112:     case 2:
        !           113:         return s->pmr;
        !           114:     case 4:
        !           115:         return ptimer_get_count(s->timer);
        !           116:     default:
        !           117:         cpu_abort(cpu_single_env, "m5208_timer_read: Bad offset 0x%x\n",
        !           118:                   (int)addr);
        !           119:         return 0;
        !           120:     }
        !           121: }
        !           122: 
        !           123: static CPUReadMemoryFunc *m5208_timer_readfn[] = {
        !           124:    m5208_timer_read,
        !           125:    m5208_timer_read,
        !           126:    m5208_timer_read
        !           127: };
        !           128: 
        !           129: static CPUWriteMemoryFunc *m5208_timer_writefn[] = {
        !           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:
                    151:         cpu_abort(cpu_single_env, "m5208_sys_read: Bad offset 0x%x\n",
                    152:                   (int)addr);
                    153:         return 0;
                    154:     }
                    155: }
                    156: 
                    157: static void m5208_sys_write(void *opaque, target_phys_addr_t addr,
                    158:                             uint32_t value)
                    159: {
1.1.1.2 ! root      160:     cpu_abort(cpu_single_env, "m5208_sys_write: Bad offset 0x%x\n",
        !           161:               (int)addr);
1.1       root      162: }
                    163: 
                    164: static CPUReadMemoryFunc *m5208_sys_readfn[] = {
                    165:    m5208_sys_read,
                    166:    m5208_sys_read,
                    167:    m5208_sys_read
                    168: };
                    169: 
                    170: static CPUWriteMemoryFunc *m5208_sys_writefn[] = {
                    171:    m5208_sys_write,
                    172:    m5208_sys_write,
                    173:    m5208_sys_write
                    174: };
                    175: 
                    176: static void mcf5208_sys_init(qemu_irq *pic)
                    177: {
                    178:     int iomemtype;
1.1.1.2 ! root      179:     m5208_timer_state *s;
1.1       root      180:     QEMUBH *bh;
                    181:     int i;
                    182: 
                    183:     iomemtype = cpu_register_io_memory(0, m5208_sys_readfn,
1.1.1.2 ! root      184:                                        m5208_sys_writefn, NULL);
1.1       root      185:     /* SDRAMC.  */
                    186:     cpu_register_physical_memory(0xfc0a8000, 0x00004000, iomemtype);
                    187:     /* Timers.  */
                    188:     for (i = 0; i < 2; i++) {
1.1.1.2 ! root      189:         s = (m5208_timer_state *)qemu_mallocz(sizeof(m5208_timer_state));
        !           190:         bh = qemu_bh_new(m5208_timer_trigger, s);
        !           191:         s->timer = ptimer_init(bh);
        !           192:         iomemtype = cpu_register_io_memory(0, m5208_timer_readfn,
        !           193:                                            m5208_timer_writefn, s);
1.1       root      194:         cpu_register_physical_memory(0xfc080000 + 0x4000 * i, 0x00004000,
                    195:                                      iomemtype);
1.1.1.2 ! root      196:         s->irq = pic[4 + i];
1.1       root      197:     }
                    198: }
                    199: 
1.1.1.2 ! root      200: static void mcf5208evb_init(ram_addr_t ram_size, int vga_ram_size,
        !           201:                      const char *boot_device,
1.1       root      202:                      const char *kernel_filename, const char *kernel_cmdline,
                    203:                      const char *initrd_filename, const char *cpu_model)
                    204: {
                    205:     CPUState *env;
                    206:     int kernel_size;
                    207:     uint64_t elf_entry;
                    208:     target_ulong entry;
                    209:     qemu_irq *pic;
                    210: 
                    211:     if (!cpu_model)
                    212:         cpu_model = "m5208";
                    213:     env = cpu_init(cpu_model);
                    214:     if (!env) {
                    215:         fprintf(stderr, "Unable to find m68k CPU definition\n");
                    216:         exit(1);
                    217:     }
                    218: 
                    219:     /* Initialize CPU registers.  */
                    220:     env->vbr = 0;
                    221:     /* TODO: Configure BARs.  */
                    222: 
                    223:     /* DRAM at 0x20000000 */
                    224:     cpu_register_physical_memory(0x40000000, ram_size,
                    225:         qemu_ram_alloc(ram_size) | IO_MEM_RAM);
                    226: 
                    227:     /* Internal SRAM.  */
                    228:     cpu_register_physical_memory(0x80000000, 16384,
                    229:         qemu_ram_alloc(16384) | IO_MEM_RAM);
                    230: 
                    231:     /* Internal peripherals.  */
                    232:     pic = mcf_intc_init(0xfc048000, env);
                    233: 
                    234:     mcf_uart_mm_init(0xfc060000, pic[26], serial_hds[0]);
                    235:     mcf_uart_mm_init(0xfc064000, pic[27], serial_hds[1]);
                    236:     mcf_uart_mm_init(0xfc068000, pic[28], serial_hds[2]);
                    237: 
                    238:     mcf5208_sys_init(pic);
                    239: 
                    240:     if (nb_nics > 1) {
                    241:         fprintf(stderr, "Too many NICs\n");
                    242:         exit(1);
                    243:     }
1.1.1.2 ! root      244:     if (nd_table[0].vlan)
        !           245:         mcf_fec_init(&nd_table[0], 0xfc030000, pic + 36);
1.1       root      246: 
                    247:     /*  0xfc000000 SCM.  */
                    248:     /*  0xfc004000 XBS.  */
                    249:     /*  0xfc008000 FlexBus CS.  */
                    250:     /* 0xfc030000 FEC.  */
                    251:     /*  0xfc040000 SCM + Power management.  */
                    252:     /*  0xfc044000 eDMA.  */
                    253:     /* 0xfc048000 INTC.  */
                    254:     /*  0xfc058000 I2C.  */
                    255:     /*  0xfc05c000 QSPI.  */
                    256:     /* 0xfc060000 UART0.  */
                    257:     /* 0xfc064000 UART0.  */
                    258:     /* 0xfc068000 UART0.  */
                    259:     /*  0xfc070000 DMA timers.  */
                    260:     /* 0xfc080000 PIT0.  */
                    261:     /* 0xfc084000 PIT1.  */
                    262:     /*  0xfc088000 EPORT.  */
                    263:     /*  0xfc08c000 Watchdog.  */
                    264:     /*  0xfc090000 clock module.  */
                    265:     /*  0xfc0a0000 CCM + reset.  */
                    266:     /*  0xfc0a4000 GPIO.  */
                    267:     /* 0xfc0a8000 SDRAM controller.  */
                    268: 
                    269:     /* Load kernel.  */
                    270:     if (!kernel_filename) {
                    271:         fprintf(stderr, "Kernel image must be specified\n");
                    272:         exit(1);
                    273:     }
                    274: 
                    275:     kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL);
                    276:     entry = elf_entry;
                    277:     if (kernel_size < 0) {
1.1.1.2 ! root      278:         kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
1.1       root      279:     }
                    280:     if (kernel_size < 0) {
                    281:         kernel_size = load_image(kernel_filename, phys_ram_base);
                    282:         entry = 0x20000000;
                    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: 
                    292: QEMUMachine mcf5208evb_machine = {
1.1.1.2 ! root      293:     .name = "mcf5208evb",
        !           294:     .desc = "MCF5206EVB",
        !           295:     .init = mcf5208evb_init,
        !           296:     .ram_require = 16384,
1.1       root      297: };

unix.superglobalmegacorp.com

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