(linenum→info "unix/slp.c:2238")

qemu/0.9.1/hw/mcf5208.c

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