Commit 9ee6e8bb853bdea7ef6c645a1a07aa55fd206aba

Authored by pbrook
1 parent ee4e83ed

ARMv7 support.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3572 c046a42c-6fe2-441c-8c8c-71466251a162

Too many changes to show.

To preserve performance only 26 of 35 files are displayed.

Changelog
... ... @@ -17,6 +17,7 @@
17 17 - MIPS mipssim pequdo machine (Thiemo Seufer)
18 18 - Strace for Linux userland emulation (Stuart Anderson, Thayne Harbaugh)
19 19 - OMAP310 MPU emulation plus Palm T|E machine (Andrzej Zaborowski)
  20 + - ARM v6, v7, NEON SIMD and SMP emulation (Paul Brook/CodeSourcery)
20 21  
21 22 version 0.9.0:
22 23  
... ...
Makefile.target
... ... @@ -493,7 +493,9 @@ ifeq ($(TARGET_BASE_ARCH), arm)
493 493 VL_OBJS+= integratorcp.o versatilepb.o ps2.o smc91c111.o arm_pic.o arm_timer.o
494 494 VL_OBJS+= arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
495 495 VL_OBJS+= versatile_pci.o sd.o ptimer.o
496   -VL_OBJS+= arm_gic.o realview.o arm_sysctl.o
  496 +VL_OBJS+= realview_gic.o realview.o arm_sysctl.o mpcore.o
  497 +VL_OBJS+= armv7m.o armv7m_nvic.o stellaris.o i2c.o ssd0303.o pl022.o
  498 +VL_OBJS+= ssd0323.o pl061.o
497 499 VL_OBJS+= arm-semi.o
498 500 VL_OBJS+= pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
499 501 VL_OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o max111x.o max7310.o
... ...
cpu-exec.c
... ... @@ -173,6 +173,7 @@ static inline TranslationBlock *tb_find_fast(void)
173 173 flags |= (1 << 6);
174 174 if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
175 175 flags |= (1 << 7);
  176 + flags |= (env->condexec_bits << 8);
176 177 cs_base = 0;
177 178 pc = env->regs[15];
178 179 #elif defined(TARGET_SPARC)
... ... @@ -511,8 +512,18 @@ int cpu_exec(CPUState *env1)
511 512 env->exception_index = EXCP_FIQ;
512 513 do_interrupt(env);
513 514 }
  515 + /* ARMv7-M interrupt return works by loading a magic value
  516 + into the PC. On real hardware the load causes the
  517 + return to occur. The qemu implementation performs the
  518 + jump normally, then does the exception return when the
  519 + CPU tries to execute code at the magic address.
  520 + This will cause the magic PC value to be pushed to
  521 + the stack if an interrupt occured at the wrong time.
  522 + We avoid this by disabling interrupts when
  523 + pc contains a magic address. */
514 524 if (interrupt_request & CPU_INTERRUPT_HARD
515   - && !(env->uncached_cpsr & CPSR_I)) {
  525 + && ((IS_M(env) && env->regs[15] < 0xfffffff0)
  526 + || !(env->uncached_cpsr & CPSR_I))) {
516 527 env->exception_index = EXCP_IRQ;
517 528 do_interrupt(env);
518 529 }
... ...
fpu/softfloat-native.h
... ... @@ -224,6 +224,11 @@ INLINE float32 float32_chs(float32 a)
224 224 return -a;
225 225 }
226 226  
  227 +INLINE float32 float32_scalbn(float32 a, int n)
  228 +{
  229 + return scalbnf(a, n);
  230 +}
  231 +
227 232 /*----------------------------------------------------------------------------
228 233 | Software IEC/IEEE double-precision conversion routines.
229 234 *----------------------------------------------------------------------------*/
... ... @@ -311,6 +316,11 @@ INLINE float64 float64_chs(float64 a)
311 316 return -a;
312 317 }
313 318  
  319 +INLINE float64 float64_scalbn(float64 a, int n)
  320 +{
  321 + return scalbn(a, n);
  322 +}
  323 +
314 324 #ifdef FLOATX80
315 325  
316 326 /*----------------------------------------------------------------------------
... ... @@ -391,4 +401,10 @@ INLINE floatx80 floatx80_chs(floatx80 a)
391 401 {
392 402 return -a;
393 403 }
  404 +
  405 +INLINE floatx80 floatx80_scalbn(floatx80 a, int n)
  406 +{
  407 + return scalbnl(a, n);
  408 +}
  409 +
394 410 #endif
... ...
fpu/softfloat.c
... ... @@ -5377,3 +5377,78 @@ int float ## s ## _compare_quiet( float ## s a, float ## s b STATUS_PARAM ) \
5377 5377  
5378 5378 COMPARE(32, 0xff)
5379 5379 COMPARE(64, 0x7ff)
  5380 +
  5381 +/* Multiply A by 2 raised to the power N. */
  5382 +float32 float32_scalbn( float32 a, int n STATUS_PARAM )
  5383 +{
  5384 + flag aSign;
  5385 + int16 aExp;
  5386 + bits32 aSig;
  5387 +
  5388 + aSig = extractFloat32Frac( a );
  5389 + aExp = extractFloat32Exp( a );
  5390 + aSign = extractFloat32Sign( a );
  5391 +
  5392 + if ( aExp == 0xFF ) {
  5393 + return a;
  5394 + }
  5395 + aExp += n;
  5396 + return roundAndPackFloat32( aSign, aExp, aSig STATUS_VAR );
  5397 +}
  5398 +
  5399 +float64 float64_scalbn( float64 a, int n STATUS_PARAM )
  5400 +{
  5401 + flag aSign;
  5402 + int16 aExp;
  5403 + bits64 aSig;
  5404 +
  5405 + aSig = extractFloat64Frac( a );
  5406 + aExp = extractFloat64Exp( a );
  5407 + aSign = extractFloat64Sign( a );
  5408 +
  5409 + if ( aExp == 0x7FF ) {
  5410 + return a;
  5411 + }
  5412 + aExp += n;
  5413 + return roundAndPackFloat64( aSign, aExp, aSig STATUS_VAR );
  5414 +}
  5415 +
  5416 +#ifdef FLOATX80
  5417 +floatx80 floatx80_scalbn( floatx80 a, int n STATUS_PARAM )
  5418 +{
  5419 + flag aSign;
  5420 + int16 aExp;
  5421 + bits64 aSig;
  5422 +
  5423 + aSig = extractFloatx80Frac( a );
  5424 + aExp = extractFloatx80Exp( a );
  5425 + aSign = extractFloatx80Sign( a );
  5426 +
  5427 + if ( aExp == 0x7FF ) {
  5428 + return a;
  5429 + }
  5430 + aExp += n;
  5431 + return roundAndPackFloatx80( STATUS(floatx80_rounding_precision),
  5432 + aSign, aExp, aSig, 0 STATUS_VAR );
  5433 +}
  5434 +#endif
  5435 +
  5436 +#ifdef FLOAT128
  5437 +float128 float128_scalbn( float128 a, int n STATUS_PARAM )
  5438 +{
  5439 + flag aSign;
  5440 + int32 aExp;
  5441 + bits64 aSig0, aSig1;
  5442 +
  5443 + aSig1 = extractFloat128Frac1( a );
  5444 + aSig0 = extractFloat128Frac0( a );
  5445 + aExp = extractFloat128Exp( a );
  5446 + aSign = extractFloat128Sign( a );
  5447 + if ( aExp == 0x7FFF ) {
  5448 + return a;
  5449 + }
  5450 + aExp += n;
  5451 + return roundAndPackFloat128( aSign, aExp, aSig0, aSig1, 0 STATUS_VAR );
  5452 +
  5453 +}
  5454 +#endif
... ...
fpu/softfloat.h
... ... @@ -244,6 +244,7 @@ int float32_compare( float32, float32 STATUS_PARAM );
244 244 int float32_compare_quiet( float32, float32 STATUS_PARAM );
245 245 int float32_is_nan( float32 );
246 246 int float32_is_signaling_nan( float32 );
  247 +float32 float32_scalbn( float32, int STATUS_PARAM );
247 248  
248 249 INLINE float32 float32_abs(float32 a)
249 250 {
... ... @@ -295,6 +296,7 @@ int float64_compare( float64, float64 STATUS_PARAM );
295 296 int float64_compare_quiet( float64, float64 STATUS_PARAM );
296 297 int float64_is_nan( float64 a );
297 298 int float64_is_signaling_nan( float64 );
  299 +float64 float64_scalbn( float64, int STATUS_PARAM );
298 300  
299 301 INLINE float64 float64_abs(float64 a)
300 302 {
... ... @@ -339,6 +341,7 @@ int floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM );
339 341 int floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM );
340 342 int floatx80_is_nan( floatx80 );
341 343 int floatx80_is_signaling_nan( floatx80 );
  344 +floatx80 floatx80_scalbn( floatx80, int STATUS_PARAM );
342 345  
343 346 INLINE floatx80 floatx80_abs(floatx80 a)
344 347 {
... ... @@ -387,6 +390,7 @@ int float128_le_quiet( float128, float128 STATUS_PARAM );
387 390 int float128_lt_quiet( float128, float128 STATUS_PARAM );
388 391 int float128_is_nan( float128 );
389 392 int float128_is_signaling_nan( float128 );
  393 +float128 float128_scalbn( float128, int STATUS_PARAM );
390 394  
391 395 INLINE float128 float128_abs(float128 a)
392 396 {
... ...
hw/arm_boot.c
1 1 /*
2 2 * ARM kernel loader.
3 3 *
4   - * Copyright (c) 2006 CodeSourcery.
  4 + * Copyright (c) 2006-2007 CodeSourcery.
5 5 * Written by Paul Brook
6 6 *
7 7 * This code is licenced under the GPL.
... ... @@ -24,6 +24,22 @@ static uint32_t bootloader[] = {
24 24 0 /* Kernel entry point. Set by integratorcp_init. */
25 25 };
26 26  
  27 +/* Entry point for secondary CPUs. Enable interrupt controller and
  28 + Issue WFI until start address is written to system controller. */
  29 +static uint32_t smpboot[] = {
  30 + 0xe3a00201, /* mov r0, #0x10000000 */
  31 + 0xe3800601, /* orr r0, r0, #0x001000000 */
  32 + 0xe3a01001, /* mov r1, #1 */
  33 + 0xe5801100, /* str r1, [r0, #0x100] */
  34 + 0xe3a00201, /* mov r0, #0x10000000 */
  35 + 0xe3800030, /* orr r0, #0x30 */
  36 + 0xe320f003, /* wfi */
  37 + 0xe5901000, /* ldr r1, [r0] */
  38 + 0xe3110003, /* tst r1, #3 */
  39 + 0x1afffffb, /* bne <wfi> */
  40 + 0xe12fff11 /* bx r1 */
  41 +};
  42 +
27 43 static void main_cpu_reset(void *opaque)
28 44 {
29 45 CPUState *env = opaque;
... ... @@ -33,6 +49,8 @@ static void main_cpu_reset(void *opaque)
33 49 arm_load_kernel(env, env->ram_size, env->kernel_filename,
34 50 env->kernel_cmdline, env->initrd_filename,
35 51 env->board_id, env->loader_start);
  52 +
  53 + /* TODO: Reset secondary CPUs. */
36 54 }
37 55  
38 56 static void set_kernel_args(uint32_t ram_size, int initrd_size,
... ... @@ -211,6 +229,8 @@ void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename,
211 229 bootloader[6] = entry;
212 230 for (n = 0; n < sizeof(bootloader) / 4; n++)
213 231 stl_raw(phys_ram_base + (n * 4), bootloader[n]);
  232 + for (n = 0; n < sizeof(smpboot) / 4; n++)
  233 + stl_raw(phys_ram_base + ram_size + (n * 4), smpboot[n]);
214 234 if (old_param)
215 235 set_kernel_args_old(ram_size, initrd_size,
216 236 kernel_cmdline, loader_start);
... ...
hw/arm_gic.c
1 1 /*
2   - * ARM AMBA Generic/Distributed Interrupt Controller
  2 + * ARM Generic/Distributed Interrupt Controller
3 3 *
4   - * Copyright (c) 2006 CodeSourcery.
  4 + * Copyright (c) 2006-2007 CodeSourcery.
5 5 * Written by Paul Brook
6 6 *
7 7 * This code is licenced under the GPL.
8 8 */
9 9  
10   -/* TODO: Some variants of this controller can handle multiple CPUs.
11   - Currently only single CPU operation is implemented. */
12   -
13   -#include "vl.h"
14   -#include "arm_pic.h"
  10 +/* This file contains implementation code for the RealView EB interrupt
  11 + controller, MPCore distributed interrupt controller and ARMv7-M
  12 + Nested Vectored Interrupt Controller. */
15 13  
16 14 //#define DEBUG_GIC
17 15  
... ... @@ -22,58 +20,84 @@ do { printf(&quot;arm_gic: &quot; fmt , ##args); } while (0)
22 20 #define DPRINTF(fmt, args...) do {} while(0)
23 21 #endif
24 22  
25   -/* Distributed interrupt controller. */
26   -
  23 +#ifdef NVIC
  24 +static const uint8_t gic_id[] =
  25 +{ 0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1 };
  26 +#define GIC_DIST_OFFSET 0
  27 +/* The NVIC has 16 internal vectors. However these are not exposed
  28 + through the normal GIC interface. */
  29 +#define GIC_BASE_IRQ 32
  30 +#else
27 31 static const uint8_t gic_id[] =
28 32 { 0x90, 0x13, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
29   -
30   -#define GIC_NIRQ 96
  33 +#define GIC_DIST_OFFSET 0x1000
  34 +#define GIC_BASE_IRQ 0
  35 +#endif
31 36  
32 37 typedef struct gic_irq_state
33 38 {
  39 + /* ??? The documentation seems to imply the enable bits are global, even
  40 + for per-cpu interrupts. This seems strange. */
34 41 unsigned enabled:1;
35   - unsigned pending:1;
36   - unsigned active:1;
  42 + unsigned pending:NCPU;
  43 + unsigned active:NCPU;
37 44 unsigned level:1;
38   - unsigned model:1; /* 0 = 1:N, 1 = N:N */
  45 + unsigned model:1; /* 0 = N:N, 1 = 1:N */
39 46 unsigned trigger:1; /* nonzero = edge triggered. */
40 47 } gic_irq_state;
41 48  
  49 +#define ALL_CPU_MASK ((1 << NCPU) - 1)
  50 +
42 51 #define GIC_SET_ENABLED(irq) s->irq_state[irq].enabled = 1
43 52 #define GIC_CLEAR_ENABLED(irq) s->irq_state[irq].enabled = 0
44 53 #define GIC_TEST_ENABLED(irq) s->irq_state[irq].enabled
45   -#define GIC_SET_PENDING(irq) s->irq_state[irq].pending = 1
46   -#define GIC_CLEAR_PENDING(irq) s->irq_state[irq].pending = 0
47   -#define GIC_TEST_PENDING(irq) s->irq_state[irq].pending
48   -#define GIC_SET_ACTIVE(irq) s->irq_state[irq].active = 1
49   -#define GIC_CLEAR_ACTIVE(irq) s->irq_state[irq].active = 0
50   -#define GIC_TEST_ACTIVE(irq) s->irq_state[irq].active
  54 +#define GIC_SET_PENDING(irq, cm) s->irq_state[irq].pending |= (cm)
  55 +#define GIC_CLEAR_PENDING(irq, cm) s->irq_state[irq].pending &= ~(cm)
  56 +#define GIC_TEST_PENDING(irq, cm) ((s->irq_state[irq].pending & (cm)) != 0)
  57 +#define GIC_SET_ACTIVE(irq, cm) s->irq_state[irq].active |= (cm)
  58 +#define GIC_CLEAR_ACTIVE(irq, cm) s->irq_state[irq].active &= ~(cm)
  59 +#define GIC_TEST_ACTIVE(irq, cm) ((s->irq_state[irq].active & (cm)) != 0)
51 60 #define GIC_SET_MODEL(irq) s->irq_state[irq].model = 1
52 61 #define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = 0
53 62 #define GIC_TEST_MODEL(irq) s->irq_state[irq].model
54   -#define GIC_SET_LEVEL(irq) s->irq_state[irq].level = 1
55   -#define GIC_CLEAR_LEVEL(irq) s->irq_state[irq].level = 0
56   -#define GIC_TEST_LEVEL(irq) s->irq_state[irq].level
  63 +#define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level = (cm)
  64 +#define GIC_CLEAR_LEVEL(irq, cm) s->irq_state[irq].level &= ~(cm)
  65 +#define GIC_TEST_LEVEL(irq, cm) (s->irq_state[irq].level & (cm)) != 0
57 66 #define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = 1
58 67 #define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0
59 68 #define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
  69 +#define GIC_GET_PRIORITY(irq, cpu) \
  70 + (((irq) < 32) ? s->priority1[irq][cpu] : s->priority2[(irq) - 32])
  71 +#ifdef NVIC
  72 +#define GIC_TARGET(irq) 1
  73 +#else
  74 +#define GIC_TARGET(irq) s->irq_target[irq]
  75 +#endif
60 76  
61 77 typedef struct gic_state
62 78 {
63 79 uint32_t base;
64   - qemu_irq parent_irq;
  80 + qemu_irq parent_irq[NCPU];
65 81 int enabled;
66   - int cpu_enabled;
  82 + int cpu_enabled[NCPU];
67 83  
68 84 gic_irq_state irq_state[GIC_NIRQ];
  85 +#ifndef NVIC
69 86 int irq_target[GIC_NIRQ];
70   - int priority[GIC_NIRQ];
71   - int last_active[GIC_NIRQ];
72   -
73   - int priority_mask;
74   - int running_irq;
75   - int running_priority;
76   - int current_pending;
  87 +#endif
  88 + int priority1[32][NCPU];
  89 + int priority2[GIC_NIRQ - 32];
  90 + int last_active[GIC_NIRQ][NCPU];
  91 +
  92 + int priority_mask[NCPU];
  93 + int running_irq[NCPU];
  94 + int running_priority[NCPU];
  95 + int current_pending[NCPU];
  96 +
  97 + qemu_irq *in;
  98 +#ifdef NVIC
  99 + void *nvic;
  100 +#endif
77 101 } gic_state;
78 102  
79 103 /* TODO: Many places that call this routine could be optimized. */
... ... @@ -83,112 +107,136 @@ static void gic_update(gic_state *s)
83 107 int best_irq;
84 108 int best_prio;
85 109 int irq;
86   -
87   - s->current_pending = 1023;
88   - if (!s->enabled || !s->cpu_enabled) {
89   - qemu_irq_lower(s->parent_irq);
90   - return;
91   - }
92   - best_prio = 0x100;
93   - best_irq = 1023;
94   - for (irq = 0; irq < 96; irq++) {
95   - if (GIC_TEST_ENABLED(irq) && GIC_TEST_PENDING(irq)) {
96   - if (s->priority[irq] < best_prio) {
97   - best_prio = s->priority[irq];
98   - best_irq = irq;
  110 + int level;
  111 + int cpu;
  112 + int cm;
  113 +
  114 + for (cpu = 0; cpu < NCPU; cpu++) {
  115 + cm = 1 << cpu;
  116 + s->current_pending[cpu] = 1023;
  117 + if (!s->enabled || !s->cpu_enabled[cpu]) {
  118 + qemu_irq_lower(s->parent_irq[cpu]);
  119 + return;
  120 + }
  121 + best_prio = 0x100;
  122 + best_irq = 1023;
  123 + for (irq = 0; irq < GIC_NIRQ; irq++) {
  124 + if (GIC_TEST_ENABLED(irq) && GIC_TEST_PENDING(irq, cm)) {
  125 + if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
  126 + best_prio = GIC_GET_PRIORITY(irq, cpu);
  127 + best_irq = irq;
  128 + }
99 129 }
100 130 }
101   - }
102   - if (best_prio > s->priority_mask) {
103   - qemu_irq_lower(s->parent_irq);
104   - } else {
105   - s->current_pending = best_irq;
106   - if (best_prio < s->running_priority) {
107   - DPRINTF("Raised pending IRQ %d\n", best_irq);
108   - qemu_irq_raise(s->parent_irq);
  131 + level = 0;
  132 + if (best_prio <= s->priority_mask[cpu]) {
  133 + s->current_pending[cpu] = best_irq;
  134 + if (best_prio < s->running_priority[cpu]) {
  135 + DPRINTF("Raised pending IRQ %d\n", best_irq);
  136 + level = 1;
  137 + }
109 138 }
  139 + qemu_set_irq(s->parent_irq[cpu], level);
110 140 }
111 141 }
112 142  
  143 +static void __attribute__((unused))
  144 +gic_set_pending_private(gic_state *s, int cpu, int irq)
  145 +{
  146 + int cm = 1 << cpu;
  147 +
  148 + if (GIC_TEST_PENDING(irq, cm))
  149 + return;
  150 +
  151 + DPRINTF("Set %d pending cpu %d\n", irq, cpu);
  152 + GIC_SET_PENDING(irq, cm);
  153 + gic_update(s);
  154 +}
  155 +
  156 +/* Process a change in an external IRQ input. */
113 157 static void gic_set_irq(void *opaque, int irq, int level)
114 158 {
115 159 gic_state *s = (gic_state *)opaque;
116 160 /* The first external input line is internal interrupt 32. */
117 161 irq += 32;
118   - if (level == GIC_TEST_LEVEL(irq))
  162 + if (level == GIC_TEST_LEVEL(irq, ALL_CPU_MASK))
119 163 return;
120 164  
121 165 if (level) {
122   - GIC_SET_LEVEL(irq);
  166 + GIC_SET_LEVEL(irq, ALL_CPU_MASK);
123 167 if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq)) {
124   - DPRINTF("Set %d pending\n", irq);
125   - GIC_SET_PENDING(irq);
  168 + DPRINTF("Set %d pending mask %x\n", irq, GIC_TARGET(irq));
  169 + GIC_SET_PENDING(irq, GIC_TARGET(irq));
126 170 }
127 171 } else {
128   - GIC_CLEAR_LEVEL(irq);
  172 + GIC_CLEAR_LEVEL(irq, ALL_CPU_MASK);
129 173 }
130 174 gic_update(s);
131 175 }
132 176  
133   -static void gic_set_running_irq(gic_state *s, int irq)
  177 +static void gic_set_running_irq(gic_state *s, int cpu, int irq)
134 178 {
135   - s->running_irq = irq;
136   - if (irq == 1023)
137   - s->running_priority = 0x100;
138   - else
139   - s->running_priority = s->priority[irq];
  179 + s->running_irq[cpu] = irq;
  180 + if (irq == 1023) {
  181 + s->running_priority[cpu] = 0x100;
  182 + } else {
  183 + s->running_priority[cpu] = GIC_GET_PRIORITY(irq, cpu);
  184 + }
140 185 gic_update(s);
141 186 }
142 187  
143   -static uint32_t gic_acknowledge_irq(gic_state *s)
  188 +static uint32_t gic_acknowledge_irq(gic_state *s, int cpu)
144 189 {
145 190 int new_irq;
146   - new_irq = s->current_pending;
147   - if (new_irq == 1023 || s->priority[new_irq] >= s->running_priority) {
  191 + int cm = 1 << cpu;
  192 + new_irq = s->current_pending[cpu];
  193 + if (new_irq == 1023
  194 + || GIC_GET_PRIORITY(new_irq, cpu) >= s->running_priority[cpu]) {
148 195 DPRINTF("ACK no pending IRQ\n");
149 196 return 1023;
150 197 }
151   - qemu_irq_lower(s->parent_irq);
152   - s->last_active[new_irq] = s->running_irq;
153   - /* For level triggered interrupts we clear the pending bit while
154   - the interrupt is active. */
155   - GIC_CLEAR_PENDING(new_irq);
156   - gic_set_running_irq(s, new_irq);
  198 + s->last_active[new_irq][cpu] = s->running_irq[cpu];
  199 + /* Clear pending flags for both level and edge triggered interrupts.
  200 + Level triggered IRQs will be reasserted once they become inactive. */
  201 + GIC_CLEAR_PENDING(new_irq, GIC_TEST_MODEL(new_irq) ? ALL_CPU_MASK : cm);
  202 + gic_set_running_irq(s, cpu, new_irq);
157 203 DPRINTF("ACK %d\n", new_irq);
158 204 return new_irq;
159 205 }
160 206  
161   -static void gic_complete_irq(gic_state * s, int irq)
  207 +static void gic_complete_irq(gic_state * s, int cpu, int irq)
162 208 {
163 209 int update = 0;
  210 + int cm = 1 << cpu;
164 211 DPRINTF("EOI %d\n", irq);
165   - if (s->running_irq == 1023)
  212 + if (s->running_irq[cpu] == 1023)
166 213 return; /* No active IRQ. */
167 214 if (irq != 1023) {
168 215 /* Mark level triggered interrupts as pending if they are still
169 216 raised. */
170 217 if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq)
171   - && GIC_TEST_LEVEL(irq)) {
172   - GIC_SET_PENDING(irq);
  218 + && GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) {
  219 + DPRINTF("Set %d pending mask %x\n", irq, cm);
  220 + GIC_SET_PENDING(irq, cm);
173 221 update = 1;
174 222 }
175 223 }
176   - if (irq != s->running_irq) {
  224 + if (irq != s->running_irq[cpu]) {
177 225 /* Complete an IRQ that is not currently running. */
178   - int tmp = s->running_irq;
179   - while (s->last_active[tmp] != 1023) {
180   - if (s->last_active[tmp] == irq) {
181   - s->last_active[tmp] = s->last_active[irq];
  226 + int tmp = s->running_irq[cpu];
  227 + while (s->last_active[tmp][cpu] != 1023) {
  228 + if (s->last_active[tmp][cpu] == irq) {
  229 + s->last_active[tmp][cpu] = s->last_active[irq][cpu];
182 230 break;
183 231 }
184   - tmp = s->last_active[tmp];
  232 + tmp = s->last_active[tmp][cpu];
185 233 }
186 234 if (update) {
187 235 gic_update(s);
188 236 }
189 237 } else {
190 238 /* Complete the current running IRQ. */
191   - gic_set_running_irq(s, s->last_active[s->running_irq]);
  239 + gic_set_running_irq(s, cpu, s->last_active[s->running_irq[cpu]][cpu]);
192 240 }
193 241 }
194 242  
... ... @@ -198,15 +246,22 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
198 246 uint32_t res;
199 247 int irq;
200 248 int i;
  249 + int cpu;
  250 + int cm;
  251 + int mask;
201 252  
202   - offset -= s->base + 0x1000;
  253 + cpu = gic_get_current_cpu();
  254 + cm = 1 << cpu;
  255 + offset -= s->base + GIC_DIST_OFFSET;
203 256 if (offset < 0x100) {
  257 +#ifndef NVIC
204 258 if (offset == 0)
205 259 return s->enabled;
206 260 if (offset == 4)
207   - return (GIC_NIRQ / 32) - 1;
  261 + return ((GIC_NIRQ / 32) - 1) | ((NCPU - 1) << 5);
208 262 if (offset < 0x08)
209 263 return 0;
  264 +#endif
210 265 goto bad_reg;
211 266 } else if (offset < 0x200) {
212 267 /* Interrupt Set/Clear Enable. */
... ... @@ -214,6 +269,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
214 269 irq = (offset - 0x100) * 8;
215 270 else
216 271 irq = (offset - 0x180) * 8;
  272 + irq += GIC_BASE_IRQ;
217 273 if (irq >= GIC_NIRQ)
218 274 goto bad_reg;
219 275 res = 0;
... ... @@ -228,40 +284,48 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
228 284 irq = (offset - 0x200) * 8;
229 285 else
230 286 irq = (offset - 0x280) * 8;
  287 + irq += GIC_BASE_IRQ;
231 288 if (irq >= GIC_NIRQ)
232 289 goto bad_reg;
233 290 res = 0;
  291 + mask = (irq < 32) ? cm : ALL_CPU_MASK;
234 292 for (i = 0; i < 8; i++) {
235   - if (GIC_TEST_PENDING(irq + i)) {
  293 + if (GIC_TEST_PENDING(irq + i, mask)) {
236 294 res |= (1 << i);
237 295 }
238 296 }
239 297 } else if (offset < 0x400) {
240 298 /* Interrupt Active. */
241   - irq = (offset - 0x300) * 8;
  299 + irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
242 300 if (irq >= GIC_NIRQ)
243 301 goto bad_reg;
244 302 res = 0;
  303 + mask = (irq < 32) ? cm : ALL_CPU_MASK;
245 304 for (i = 0; i < 8; i++) {
246   - if (GIC_TEST_ACTIVE(irq + i)) {
  305 + if (GIC_TEST_ACTIVE(irq + i, mask)) {
247 306 res |= (1 << i);
248 307 }
249 308 }
250 309 } else if (offset < 0x800) {
251 310 /* Interrupt Priority. */
252   - irq = offset - 0x400;
  311 + irq = (offset - 0x400) + GIC_BASE_IRQ;
253 312 if (irq >= GIC_NIRQ)
254 313 goto bad_reg;
255   - res = s->priority[irq];
  314 + res = GIC_GET_PRIORITY(irq, cpu);
  315 +#ifndef NVIC
256 316 } else if (offset < 0xc00) {
257 317 /* Interrupt CPU Target. */
258   - irq = offset - 0x800;
  318 + irq = (offset - 0x800) + GIC_BASE_IRQ;
259 319 if (irq >= GIC_NIRQ)
260 320 goto bad_reg;
261   - res = s->irq_target[irq];
  321 + if (irq >= 29 && irq <= 31) {
  322 + res = cm;
  323 + } else {
  324 + res = GIC_TARGET(irq);
  325 + }
262 326 } else if (offset < 0xf00) {
263 327 /* Interrupt Configuration. */
264   - irq = (offset - 0xc00) * 2;
  328 + irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ;
265 329 if (irq >= GIC_NIRQ)
266 330 goto bad_reg;
267 331 res = 0;
... ... @@ -271,6 +335,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
271 335 if (GIC_TEST_TRIGGER(irq + i))
272 336 res |= (2 << (i * 2));
273 337 }
  338 +#endif
274 339 } else if (offset < 0xfe0) {
275 340 goto bad_reg;
276 341 } else /* offset >= 0xfe0 */ {
... ... @@ -282,7 +347,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
282 347 }
283 348 return res;
284 349 bad_reg:
285   - cpu_abort (cpu_single_env, "gic_dist_readb: Bad offset %x\n", offset);
  350 + cpu_abort(cpu_single_env, "gic_dist_readb: Bad offset %x\n", (int)offset);
286 351 return 0;
287 352 }
288 353  
... ... @@ -297,6 +362,13 @@ static uint32_t gic_dist_readw(void *opaque, target_phys_addr_t offset)
297 362 static uint32_t gic_dist_readl(void *opaque, target_phys_addr_t offset)
298 363 {
299 364 uint32_t val;
  365 +#ifdef NVIC
  366 + gic_state *s = (gic_state *)opaque;
  367 + uint32_t addr;
  368 + addr = offset - s->base;
  369 + if (addr < 0x100 || addr > 0xd00)
  370 + return nvic_readl(s->nvic, addr);
  371 +#endif
300 372 val = gic_dist_readw(opaque, offset);
301 373 val |= gic_dist_readw(opaque, offset + 2) << 16;
302 374 return val;
... ... @@ -308,9 +380,14 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
308 380 gic_state *s = (gic_state *)opaque;
309 381 int irq;
310 382 int i;
  383 + int cpu;
311 384  
312   - offset -= s->base + 0x1000;
  385 + cpu = gic_get_current_cpu();
  386 + offset -= s->base + GIC_DIST_OFFSET;
313 387 if (offset < 0x100) {
  388 +#ifdef NVIC
  389 + goto bad_reg;
  390 +#else
314 391 if (offset == 0) {
315 392 s->enabled = (value & 1);
316 393 DPRINTF("Distribution %sabled\n", s->enabled ? "En" : "Dis");
... ... @@ -319,27 +396,36 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
319 396 } else {
320 397 goto bad_reg;
321 398 }
  399 +#endif
322 400 } else if (offset < 0x180) {
323 401 /* Interrupt Set Enable. */
324   - irq = (offset - 0x100) * 8;
  402 + irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
325 403 if (irq >= GIC_NIRQ)
326 404 goto bad_reg;
  405 + if (irq < 16)
  406 + value = 0xff;
327 407 for (i = 0; i < 8; i++) {
328 408 if (value & (1 << i)) {
  409 + int mask = (irq < 32) ? (1 << cpu) : GIC_TARGET(irq);
329 410 if (!GIC_TEST_ENABLED(irq + i))
330 411 DPRINTF("Enabled IRQ %d\n", irq + i);
331 412 GIC_SET_ENABLED(irq + i);
332 413 /* If a raised level triggered IRQ enabled then mark
333 414 is as pending. */
334   - if (GIC_TEST_LEVEL(irq + i) && !GIC_TEST_TRIGGER(irq + i))
335   - GIC_SET_PENDING(irq + i);
  415 + if (GIC_TEST_LEVEL(irq + i, mask)
  416 + && !GIC_TEST_TRIGGER(irq + i)) {
  417 + DPRINTF("Set %d pending mask %x\n", irq + i, mask);
  418 + GIC_SET_PENDING(irq + i, mask);
  419 + }
336 420 }
337 421 }
338 422 } else if (offset < 0x200) {
339 423 /* Interrupt Clear Enable. */
340   - irq = (offset - 0x180) * 8;
  424 + irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
341 425 if (irq >= GIC_NIRQ)
342 426 goto bad_reg;
  427 + if (irq < 16)
  428 + value = 0;
343 429 for (i = 0; i < 8; i++) {
344 430 if (value & (1 << i)) {
345 431 if (GIC_TEST_ENABLED(irq + i))
... ... @@ -349,22 +435,28 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
349 435 }
350 436 } else if (offset < 0x280) {
351 437 /* Interrupt Set Pending. */
352   - irq = (offset - 0x200) * 8;
  438 + irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
353 439 if (irq >= GIC_NIRQ)
354 440 goto bad_reg;
  441 + if (irq < 16)
  442 + irq = 0;
  443 +
355 444 for (i = 0; i < 8; i++) {
356 445 if (value & (1 << i)) {
357   - GIC_SET_PENDING(irq + i);
  446 + GIC_SET_PENDING(irq + i, GIC_TARGET(irq));
358 447 }
359 448 }
360 449 } else if (offset < 0x300) {
361 450 /* Interrupt Clear Pending. */
362   - irq = (offset - 0x280) * 8;
  451 + irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
363 452 if (irq >= GIC_NIRQ)
364 453 goto bad_reg;
365 454 for (i = 0; i < 8; i++) {
  455 + /* ??? This currently clears the pending bit for all CPUs, even
  456 + for per-CPU interrupts. It's unclear whether this is the
  457 + corect behavior. */
366 458 if (value & (1 << i)) {
367   - GIC_CLEAR_PENDING(irq + i);
  459 + GIC_CLEAR_PENDING(irq + i, ALL_CPU_MASK);
368 460 }
369 461 }
370 462 } else if (offset < 0x400) {
... ... @@ -372,21 +464,32 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
372 464 goto bad_reg;
373 465 } else if (offset < 0x800) {
374 466 /* Interrupt Priority. */
375   - irq = offset - 0x400;
  467 + irq = (offset - 0x400) + GIC_BASE_IRQ;
376 468 if (irq >= GIC_NIRQ)
377 469 goto bad_reg;
378   - s->priority[irq] = value;
  470 + if (irq < 32) {
  471 + s->priority1[irq][cpu] = value;
  472 + } else {
  473 + s->priority2[irq - 32] = value;
  474 + }
  475 +#ifndef NVIC
379 476 } else if (offset < 0xc00) {
380 477 /* Interrupt CPU Target. */
381   - irq = offset - 0x800;
  478 + irq = (offset - 0x800) + GIC_BASE_IRQ;
382 479 if (irq >= GIC_NIRQ)
383 480 goto bad_reg;
384   - s->irq_target[irq] = value;
  481 + if (irq < 29)
  482 + value = 0;
  483 + else if (irq < 32)
  484 + value = ALL_CPU_MASK;
  485 + s->irq_target[irq] = value & ALL_CPU_MASK;
385 486 } else if (offset < 0xf00) {
386 487 /* Interrupt Configuration. */
387   - irq = (offset - 0xc00) * 4;
  488 + irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
388 489 if (irq >= GIC_NIRQ)
389 490 goto bad_reg;
  491 + if (irq < 32)
  492 + value |= 0xaa;
390 493 for (i = 0; i < 4; i++) {
391 494 if (value & (1 << (i * 2))) {
392 495 GIC_SET_MODEL(irq + i);
... ... @@ -399,25 +502,20 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
399 502 GIC_CLEAR_TRIGGER(irq + i);
400 503 }
401 504 }
  505 +#endif
402 506 } else {
403   - /* 0xf00 is only handled for word writes. */
  507 + /* 0xf00 is only handled for 32-bit writes. */
404 508 goto bad_reg;
405 509 }
406 510 gic_update(s);
407 511 return;
408 512 bad_reg:
409   - cpu_abort (cpu_single_env, "gic_dist_writeb: Bad offset %x\n", offset);
  513 + cpu_abort(cpu_single_env, "gic_dist_writeb: Bad offset %x\n", (int)offset);
410 514 }
411 515  
412 516 static void gic_dist_writew(void *opaque, target_phys_addr_t offset,
413 517 uint32_t value)
414 518 {
415   - gic_state *s = (gic_state *)opaque;
416   - if (offset - s->base == 0xf00) {
417   - GIC_SET_PENDING(value & 0x3ff);
418   - gic_update(s);
419   - return;
420   - }
421 519 gic_dist_writeb(opaque, offset, value & 0xff);
422 520 gic_dist_writeb(opaque, offset + 1, value >> 8);
423 521 }
... ... @@ -425,6 +523,41 @@ static void gic_dist_writew(void *opaque, target_phys_addr_t offset,
425 523 static void gic_dist_writel(void *opaque, target_phys_addr_t offset,
426 524 uint32_t value)
427 525 {
  526 + gic_state *s = (gic_state *)opaque;
  527 +#ifdef NVIC
  528 + uint32_t addr;
  529 + addr = offset - s->base;
  530 + if (addr < 0x100 || (addr > 0xd00 && addr != 0xf00)) {
  531 + nvic_writel(s->nvic, addr, value);
  532 + return;
  533 + }
  534 +#endif
  535 + if (offset - s->base == GIC_DIST_OFFSET + 0xf00) {
  536 + int cpu;
  537 + int irq;
  538 + int mask;
  539 +
  540 + cpu = gic_get_current_cpu();
  541 + irq = value & 0x3ff;
  542 + switch ((value >> 24) & 3) {
  543 + case 0:
  544 + mask = (value >> 16) & ALL_CPU_MASK;
  545 + break;
  546 + case 1:
  547 + mask = 1 << cpu;
  548 + break;
  549 + case 2:
  550 + mask = ALL_CPU_MASK ^ (1 << cpu);
  551 + break;
  552 + default:
  553 + DPRINTF("Bad Soft Int target filter\n");
  554 + mask = ALL_CPU_MASK;
  555 + break;
  556 + }
  557 + GIC_SET_PENDING(irq, mask);
  558 + gic_update(s);
  559 + return;
  560 + }
428 561 gic_dist_writew(opaque, offset, value & 0xffff);
429 562 gic_dist_writew(opaque, offset + 2, value >> 16);
430 563 }
... ... @@ -441,105 +574,100 @@ static CPUWriteMemoryFunc *gic_dist_writefn[] = {
441 574 gic_dist_writel
442 575 };
443 576  
444   -static uint32_t gic_cpu_read(void *opaque, target_phys_addr_t offset)
  577 +#ifndef NVIC
  578 +static uint32_t gic_cpu_read(gic_state *s, int cpu, int offset)
445 579 {
446   - gic_state *s = (gic_state *)opaque;
447   - offset -= s->base;
448 580 switch (offset) {
449 581 case 0x00: /* Control */
450   - return s->cpu_enabled;
  582 + return s->cpu_enabled[cpu];
451 583 case 0x04: /* Priority mask */
452   - return s->priority_mask;
  584 + return s->priority_mask[cpu];
453 585 case 0x08: /* Binary Point */
454 586 /* ??? Not implemented. */
455 587 return 0;
456 588 case 0x0c: /* Acknowledge */
457   - return gic_acknowledge_irq(s);
  589 + return gic_acknowledge_irq(s, cpu);
458 590 case 0x14: /* Runing Priority */
459   - return s->running_priority;
  591 + return s->running_priority[cpu];
460 592 case 0x18: /* Highest Pending Interrupt */
461   - return s->current_pending;
  593 + return s->current_pending[cpu];
462 594 default:
463   - cpu_abort (cpu_single_env, "gic_cpu_read: Bad offset %x\n", offset);
  595 + cpu_abort(cpu_single_env, "gic_cpu_read: Bad offset %x\n",
  596 + (int)offset);
464 597 return 0;
465 598 }
466 599 }
467 600  
468   -static void gic_cpu_write(void *opaque, target_phys_addr_t offset,
469   - uint32_t value)
  601 +static void gic_cpu_write(gic_state *s, int cpu, int offset, uint32_t value)
470 602 {
471   - gic_state *s = (gic_state *)opaque;
472   - offset -= s->base;
473 603 switch (offset) {
474 604 case 0x00: /* Control */
475   - s->cpu_enabled = (value & 1);
  605 + s->cpu_enabled[cpu] = (value & 1);
476 606 DPRINTF("CPU %sabled\n", s->cpu_enabled ? "En" : "Dis");
477 607 break;
478 608 case 0x04: /* Priority mask */
479   - s->priority_mask = (value & 0x3ff);
  609 + s->priority_mask[cpu] = (value & 0xff);
480 610 break;
481 611 case 0x08: /* Binary Point */
482 612 /* ??? Not implemented. */
483 613 break;
484 614 case 0x10: /* End Of Interrupt */
485   - return gic_complete_irq(s, value & 0x3ff);
  615 + return gic_complete_irq(s, cpu, value & 0x3ff);
486 616 default:
487   - cpu_abort (cpu_single_env, "gic_cpu_write: Bad offset %x\n", offset);
  617 + cpu_abort(cpu_single_env, "gic_cpu_write: Bad offset %x\n",
  618 + (int)offset);
488 619 return;
489 620 }
490 621 gic_update(s);
491 622 }
492   -
493   -static CPUReadMemoryFunc *gic_cpu_readfn[] = {
494   - gic_cpu_read,
495   - gic_cpu_read,
496   - gic_cpu_read
497   -};
498   -
499   -static CPUWriteMemoryFunc *gic_cpu_writefn[] = {
500   - gic_cpu_write,
501   - gic_cpu_write,
502   - gic_cpu_write
503   -};
  623 +#endif
504 624  
505 625 static void gic_reset(gic_state *s)
506 626 {
507 627 int i;
508 628 memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state));
509   - s->priority_mask = 0xf0;
510   - s->current_pending = 1023;
511   - s->running_irq = 1023;
512   - s->running_priority = 0x100;
  629 + for (i = 0 ; i < NCPU; i++) {
  630 + s->priority_mask[i] = 0xf0;
  631 + s->current_pending[i] = 1023;
  632 + s->running_irq[i] = 1023;
  633 + s->running_priority[i] = 0x100;
  634 +#ifdef NVIC
  635 + /* The NVIC doesn't have per-cpu interfaces, so enable by default. */
  636 + s->cpu_enabled[i] = 1;
  637 +#else
  638 + s->cpu_enabled[i] = 0;
  639 +#endif
  640 + }
513 641 for (i = 0; i < 15; i++) {
514 642 GIC_SET_ENABLED(i);
515 643 GIC_SET_TRIGGER(i);
516 644 }
  645 +#ifdef NVIC
  646 + /* The NVIC is always enabled. */
  647 + s->enabled = 1;
  648 +#else
517 649 s->enabled = 0;
518   - s->cpu_enabled = 0;
  650 +#endif
519 651 }
520 652  
521   -qemu_irq *arm_gic_init(uint32_t base, qemu_irq parent_irq)
  653 +static gic_state *gic_init(uint32_t base, qemu_irq *parent_irq)
522 654 {
523 655 gic_state *s;
524   - qemu_irq *qi;
525 656 int iomemtype;
  657 + int i;
526 658  
527 659 s = (gic_state *)qemu_mallocz(sizeof(gic_state));
528 660 if (!s)
529 661 return NULL;
530   - qi = qemu_allocate_irqs(gic_set_irq, s, GIC_NIRQ);
531   - s->parent_irq = parent_irq;
532   - if (base != 0xffffffff) {
533   - iomemtype = cpu_register_io_memory(0, gic_cpu_readfn,
534   - gic_cpu_writefn, s);
535   - cpu_register_physical_memory(base, 0x00001000, iomemtype);
536   - iomemtype = cpu_register_io_memory(0, gic_dist_readfn,
537   - gic_dist_writefn, s);
538   - cpu_register_physical_memory(base + 0x1000, 0x00001000, iomemtype);
539   - s->base = base;
540   - } else {
541   - s->base = 0;
  662 + s->in = qemu_allocate_irqs(gic_set_irq, s, GIC_NIRQ);
  663 + for (i = 0; i < NCPU; i++) {
  664 + s->parent_irq[i] = parent_irq[i];
542 665 }
  666 + iomemtype = cpu_register_io_memory(0, gic_dist_readfn,
  667 + gic_dist_writefn, s);
  668 + cpu_register_physical_memory(base + GIC_DIST_OFFSET, 0x00001000,
  669 + iomemtype);
  670 + s->base = base;
543 671 gic_reset(s);
544   - return qi;
  672 + return s;
545 673 }
... ...
hw/arm_sysctl.c
1 1 /*
2 2 * Status and system control registers for ARM RealView/Versatile boards.
3 3 *
4   - * Copyright (c) 2006 CodeSourcery.
  4 + * Copyright (c) 2006-2007 CodeSourcery.
5 5 * Written by Paul Brook
6 6 *
7 7 * This code is licenced under the GPL.
... ... @@ -200,6 +200,9 @@ void arm_sysctl_init(uint32_t base, uint32_t sys_id)
200 200 return;
201 201 s->base = base;
202 202 s->sys_id = sys_id;
  203 + /* The MPcore bootloader uses these flags to start secondary CPUs.
  204 + We don't use a bootloader, so do this here. */
  205 + s->flags = 3;
203 206 iomemtype = cpu_register_io_memory(0, arm_sysctl_readfn,
204 207 arm_sysctl_writefn, s);
205 208 cpu_register_physical_memory(base, 0x00001000, iomemtype);
... ...
hw/armv7m.c 0 โ†’ 100644
  1 +/*
  2 + * ARMV7M System emulation.
  3 + *
  4 + * Copyright (c) 2006-2007 CodeSourcery.
  5 + * Written by Paul Brook
  6 + *
  7 + * This code is licenced under the GPL.
  8 + */
  9 +
  10 +#include "vl.h"
  11 +
  12 +/* Bitbanded IO. Each word corresponds to a single bit. */
  13 +
  14 +/* Get the byte address of the real memory for a bitband acess. */
  15 +static inline uint32_t bitband_addr(uint32_t addr)
  16 +{
  17 + uint32_t res;
  18 +
  19 + res = addr & 0xe0000000;
  20 + res |= (addr & 0x1ffffff) >> 5;
  21 + return res;
  22 +
  23 +}
  24 +
  25 +static uint32_t bitband_readb(void *opaque, target_phys_addr_t offset)
  26 +{
  27 + uint8_t v;
  28 + cpu_physical_memory_read(bitband_addr(offset), &v, 1);
  29 + return (v & (1 << ((offset >> 2) & 7))) != 0;
  30 +}
  31 +
  32 +static void bitband_writeb(void *opaque, target_phys_addr_t offset,
  33 + uint32_t value)
  34 +{
  35 + uint32_t addr;
  36 + uint8_t mask;
  37 + uint8_t v;
  38 + addr = bitband_addr(offset);
  39 + mask = (1 << ((offset >> 2) & 7));
  40 + cpu_physical_memory_read(addr, &v, 1);
  41 + if (value & 1)
  42 + v |= mask;
  43 + else
  44 + v &= ~mask;
  45 + cpu_physical_memory_write(addr, &v, 1);
  46 +}
  47 +
  48 +static uint32_t bitband_readw(void *opaque, target_phys_addr_t offset)
  49 +{
  50 + uint32_t addr;
  51 + uint16_t mask;
  52 + uint16_t v;
  53 + addr = bitband_addr(offset) & ~1;
  54 + mask = (1 << ((offset >> 2) & 15));
  55 + mask = tswap16(mask);
  56 + cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
  57 + return (v & mask) != 0;
  58 +}
  59 +
  60 +static void bitband_writew(void *opaque, target_phys_addr_t offset,
  61 + uint32_t value)
  62 +{
  63 + uint32_t addr;
  64 + uint16_t mask;
  65 + uint16_t v;
  66 + addr = bitband_addr(offset) & ~1;
  67 + mask = (1 << ((offset >> 2) & 15));
  68 + mask = tswap16(mask);
  69 + cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
  70 + if (value & 1)
  71 + v |= mask;
  72 + else
  73 + v &= ~mask;
  74 + cpu_physical_memory_write(addr, (uint8_t *)&v, 2);
  75 +}
  76 +
  77 +static uint32_t bitband_readl(void *opaque, target_phys_addr_t offset)
  78 +{
  79 + uint32_t addr;
  80 + uint32_t mask;
  81 + uint32_t v;
  82 + addr = bitband_addr(offset) & ~3;
  83 + mask = (1 << ((offset >> 2) & 31));
  84 + mask = tswap32(mask);
  85 + cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
  86 + return (v & mask) != 0;
  87 +}
  88 +
  89 +static void bitband_writel(void *opaque, target_phys_addr_t offset,
  90 + uint32_t value)
  91 +{
  92 + uint32_t addr;
  93 + uint32_t mask;
  94 + uint32_t v;
  95 + addr = bitband_addr(offset) & ~3;
  96 + mask = (1 << ((offset >> 2) & 31));
  97 + mask = tswap32(mask);
  98 + cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
  99 + if (value & 1)
  100 + v |= mask;
  101 + else
  102 + v &= ~mask;
  103 + cpu_physical_memory_write(addr, (uint8_t *)&v, 4);
  104 +}
  105 +
  106 +static CPUReadMemoryFunc *bitband_readfn[] = {
  107 + bitband_readb,
  108 + bitband_readw,
  109 + bitband_readl
  110 +};
  111 +
  112 +static CPUWriteMemoryFunc *bitband_writefn[] = {
  113 + bitband_writeb,
  114 + bitband_writew,
  115 + bitband_writel
  116 +};
  117 +
  118 +static void armv7m_bitband_init(void)
  119 +{
  120 + int iomemtype;
  121 +
  122 + iomemtype = cpu_register_io_memory(0, bitband_readfn, bitband_writefn,
  123 + NULL);
  124 + cpu_register_physical_memory(0x22000000, 0x02000000, iomemtype);
  125 + cpu_register_physical_memory(0x42000000, 0x02000000, iomemtype);
  126 +}
  127 +
  128 +/* Board init. */
  129 +/* Init CPU and memory for a v7-M based board.
  130 + flash_size and sram_size are in kb.
  131 + Returns the NVIC array. */
  132 +
  133 +qemu_irq *armv7m_init(int flash_size, int sram_size,
  134 + const char *kernel_filename, const char *cpu_model)
  135 +{
  136 + CPUState *env;
  137 + qemu_irq *pic;
  138 + uint32_t pc;
  139 + int image_size;
  140 + uint64_t entry;
  141 + uint64_t lowaddr;
  142 +
  143 + flash_size *= 1024;
  144 + sram_size *= 1024;
  145 +
  146 + if (!cpu_model)
  147 + cpu_model = "cortex-m3";
  148 + env = cpu_init(cpu_model);
  149 + if (!env) {
  150 + fprintf(stderr, "Unable to find CPU definition\n");
  151 + exit(1);
  152 + }
  153 +
  154 +#if 0
  155 + /* > 32Mb SRAM gets complicated because it overlaps the bitband area.
  156 + We don't have proper commandline options, so allocate half of memory
  157 + as SRAM, up to a maximum of 32Mb, and the rest as code. */
  158 + if (ram_size > (512 + 32) * 1024 * 1024)
  159 + ram_size = (512 + 32) * 1024 * 1024;
  160 + sram_size = (ram_size / 2) & TARGET_PAGE_MASK;
  161 + if (sram_size > 32 * 1024 * 1024)
  162 + sram_size = 32 * 1024 * 1024;
  163 + code_size = ram_size - sram_size;
  164 +#endif
  165 +
  166 + /* Flash programming is done via the SCU, so pretend it is ROM. */
  167 + cpu_register_physical_memory(0, flash_size, IO_MEM_ROM);
  168 + cpu_register_physical_memory(0x20000000, sram_size,
  169 + flash_size + IO_MEM_RAM);
  170 + armv7m_bitband_init();
  171 +
  172 + pic = armv7m_nvic_init(env);
  173 +
  174 + image_size = load_elf(kernel_filename, 0, &entry, &lowaddr, NULL);
  175 + if (image_size < 0) {
  176 + image_size = load_image(kernel_filename, phys_ram_base);
  177 + lowaddr = 0;
  178 + }
  179 + if (image_size < 0) {
  180 + fprintf(stderr, "qemu: could not load kernel '%s'\n",
  181 + kernel_filename);
  182 + exit(1);
  183 + }
  184 +
  185 + /* If the image was loaded at address zero then assume it is a
  186 + regular ROM image and perform the normal CPU reset sequence.
  187 + Otherwise jump directly to the entry point. */
  188 + if (lowaddr == 0) {
  189 + env->regs[13] = tswap32(*(uint32_t *)phys_ram_base);
  190 + pc = tswap32(*(uint32_t *)(phys_ram_base + 4));
  191 + } else {
  192 + pc = entry;
  193 + }
  194 + env->thumb = pc & 1;
  195 + env->regs[15] = pc & ~1;
  196 +
  197 + /* Hack to map an additional page of ram at the top of the address
  198 + space. This stops qemu complaining about executing code outside RAM
  199 + when returning from an exception. */
  200 + cpu_register_physical_memory(0xfffff000, 0x1000, IO_MEM_RAM + ram_size);
  201 +
  202 + return pic;
  203 +}
  204 +
... ...
hw/armv7m_nvic.c 0 โ†’ 100644
  1 +/*
  2 + * ARM Nested Vectored Interrupt Controller
  3 + *
  4 + * Copyright (c) 2006-2007 CodeSourcery.
  5 + * Written by Paul Brook
  6 + *
  7 + * This code is licenced under the GPL.
  8 + *
  9 + * The ARMv7M System controller is fairly tightly tied in with the
  10 + * NVIC. Much of that is also implemented here.
  11 + */
  12 +
  13 +#include "vl.h"
  14 +#include "arm_pic.h"
  15 +
  16 +#define GIC_NIRQ 64
  17 +#define NCPU 1
  18 +#define NVIC 1
  19 +
  20 +/* Only a single "CPU" interface is present. */
  21 +static inline int
  22 +gic_get_current_cpu(void)
  23 +{
  24 + return 0;
  25 +}
  26 +
  27 +static uint32_t nvic_readl(void *opaque, uint32_t offset);
  28 +static void nvic_writel(void *opaque, uint32_t offset, uint32_t value);
  29 +
  30 +#include "arm_gic.c"
  31 +
  32 +typedef struct {
  33 + struct {
  34 + uint32_t control;
  35 + uint32_t reload;
  36 + int64_t tick;
  37 + QEMUTimer *timer;
  38 + } systick;
  39 + gic_state *gic;
  40 +} nvic_state;
  41 +
  42 +/* qemu timers run at 1GHz. We want something closer to 1MHz. */
  43 +#define SYSTICK_SCALE 1000ULL
  44 +
  45 +#define SYSTICK_ENABLE (1 << 0)
  46 +#define SYSTICK_TICKINT (1 << 1)
  47 +#define SYSTICK_CLKSOURCE (1 << 2)
  48 +#define SYSTICK_COUNTFLAG (1 << 16)
  49 +
  50 +/* Conversion factor from qemu timer to SysTick frequencies.
  51 + QEMU uses a base of 1GHz, so these give 20MHz and 1MHz for core and
  52 + reference frequencies. */
  53 +
  54 +static inline int64_t systick_scale(nvic_state *s)
  55 +{
  56 + if (s->systick.control & SYSTICK_CLKSOURCE)
  57 + return 50;
  58 + else
  59 + return 1000;
  60 +}
  61 +
  62 +static void systick_reload(nvic_state *s, int reset)
  63 +{
  64 + if (reset)
  65 + s->systick.tick = qemu_get_clock(vm_clock);
  66 + s->systick.tick += (s->systick.reload + 1) * systick_scale(s);
  67 + qemu_mod_timer(s->systick.timer, s->systick.tick);
  68 +}
  69 +
  70 +static void systick_timer_tick(void * opaque)
  71 +{
  72 + nvic_state *s = (nvic_state *)opaque;
  73 + s->systick.control |= SYSTICK_COUNTFLAG;
  74 + if (s->systick.control & SYSTICK_TICKINT) {
  75 + /* Trigger the interrupt. */
  76 + armv7m_nvic_set_pending(s, ARMV7M_EXCP_SYSTICK);
  77 + }
  78 + if (s->systick.reload == 0) {
  79 + s->systick.control &= ~SYSTICK_ENABLE;
  80 + } else {
  81 + systick_reload(s, 0);
  82 + }
  83 +}
  84 +
  85 +/* The external routines use the hardware vector numbering, ie. the first
  86 + IRQ is #16. The internal GIC routines use #32 as the first IRQ. */
  87 +void armv7m_nvic_set_pending(void *opaque, int irq)
  88 +{
  89 + nvic_state *s = (nvic_state *)opaque;
  90 + if (irq >= 16)
  91 + irq += 16;
  92 + gic_set_pending_private(s->gic, 0, irq);
  93 +}
  94 +
  95 +/* Make pending IRQ active. */
  96 +int armv7m_nvic_acknowledge_irq(void *opaque)
  97 +{
  98 + nvic_state *s = (nvic_state *)opaque;
  99 + uint32_t irq;
  100 +
  101 + irq = gic_acknowledge_irq(s->gic, 0);
  102 + if (irq == 1023)
  103 + cpu_abort(cpu_single_env, "Interrupt but no vector\n");
  104 + if (irq >= 32)
  105 + irq -= 16;
  106 + return irq;
  107 +}
  108 +
  109 +void armv7m_nvic_complete_irq(void *opaque, int irq)
  110 +{
  111 + nvic_state *s = (nvic_state *)opaque;
  112 + if (irq >= 16)
  113 + irq += 16;
  114 + gic_complete_irq(s->gic, 0, irq);
  115 +}
  116 +
  117 +static uint32_t nvic_readl(void *opaque, uint32_t offset)
  118 +{
  119 + nvic_state *s = (nvic_state *)opaque;
  120 + uint32_t val;
  121 + int irq;
  122 +
  123 + switch (offset) {
  124 + case 4: /* Interrupt Control Type. */
  125 + return (GIC_NIRQ / 32) - 1;
  126 + case 0x10: /* SysTick Control and Status. */
  127 + val = s->systick.control;
  128 + s->systick.control &= ~SYSTICK_COUNTFLAG;
  129 + return val;
  130 + case 0x14: /* SysTick Reload Value. */
  131 + return s->systick.reload;
  132 + case 0x18: /* SysTick Current Value. */
  133 + {
  134 + int64_t t;
  135 + if ((s->systick.control & SYSTICK_ENABLE) == 0)
  136 + return 0;
  137 + t = qemu_get_clock(vm_clock);
  138 + if (t >= s->systick.tick)
  139 + return 0;
  140 + val = ((s->systick.tick - (t + 1)) / systick_scale(s)) + 1;
  141 + /* The interrupt in triggered when the timer reaches zero.
  142 + However the counter is not reloaded until the next clock
  143 + tick. This is a hack to return zero during the first tick. */
  144 + if (val > s->systick.reload)
  145 + val = 0;
  146 + return val;
  147 + }
  148 + case 0x1c: /* SysTick Calibration Value. */
  149 + return 10000;
  150 + case 0xd00: /* CPUID Base. */
  151 + return cpu_single_env->cp15.c0_cpuid;
  152 + case 0xd04: /* Interrypt Control State. */
  153 + /* VECTACTIVE */
  154 + val = s->gic->running_irq[0];
  155 + if (val == 1023) {
  156 + val = 0;
  157 + } else if (val >= 32) {
  158 + val -= 16;
  159 + }
  160 + /* RETTOBASE */
  161 + if (s->gic->running_irq[0] == 1023
  162 + || s->gic->last_active[s->gic->running_irq[0]][0] == 1023) {
  163 + val |= (1 << 11);
  164 + }
  165 + /* VECTPENDING */
  166 + if (s->gic->current_pending[0] != 1023)
  167 + val |= (s->gic->current_pending[0] << 12);
  168 + /* ISRPENDING */
  169 + for (irq = 32; irq < GIC_NIRQ; irq++) {
  170 + if (s->gic->irq_state[irq].pending) {
  171 + val |= (1 << 22);
  172 + break;
  173 + }
  174 + }
  175 + /* PENDSTSET */
  176 + if (s->gic->irq_state[ARMV7M_EXCP_SYSTICK].pending)
  177 + val |= (1 << 26);
  178 + /* PENDSVSET */
  179 + if (s->gic->irq_state[ARMV7M_EXCP_PENDSV].pending)
  180 + val |= (1 << 28);
  181 + /* NMIPENDSET */
  182 + if (s->gic->irq_state[ARMV7M_EXCP_NMI].pending)
  183 + val |= (1 << 31);
  184 + return val;
  185 + case 0xd08: /* Vector Table Offset. */
  186 + return cpu_single_env->v7m.vecbase;
  187 + case 0xd0c: /* Application Interrupt/Reset Control. */
  188 + return 0xfa05000;
  189 + case 0xd10: /* System Control. */
  190 + /* TODO: Implement SLEEPONEXIT. */
  191 + return 0;
  192 + case 0xd14: /* Configuration Control. */
  193 + /* TODO: Implement Configuration Control bits. */
  194 + return 0;
  195 + case 0xd18: case 0xd1c: case 0xd20: /* System Handler Priority. */
  196 + irq = offset - 0xd14;
  197 + val = 0;
  198 + val = s->gic->priority1[irq++][0];
  199 + val = s->gic->priority1[irq++][0] << 8;
  200 + val = s->gic->priority1[irq++][0] << 16;
  201 + val = s->gic->priority1[irq][0] << 24;
  202 + return val;
  203 + case 0xd24: /* System Handler Status. */
  204 + val = 0;
  205 + if (s->gic->irq_state[ARMV7M_EXCP_MEM].active) val |= (1 << 0);
  206 + if (s->gic->irq_state[ARMV7M_EXCP_BUS].active) val |= (1 << 1);
  207 + if (s->gic->irq_state[ARMV7M_EXCP_USAGE].active) val |= (1 << 3);
  208 + if (s->gic->irq_state[ARMV7M_EXCP_SVC].active) val |= (1 << 7);
  209 + if (s->gic->irq_state[ARMV7M_EXCP_DEBUG].active) val |= (1 << 8);
  210 + if (s->gic->irq_state[ARMV7M_EXCP_PENDSV].active) val |= (1 << 10);
  211 + if (s->gic->irq_state[ARMV7M_EXCP_SYSTICK].active) val |= (1 << 11);
  212 + if (s->gic->irq_state[ARMV7M_EXCP_USAGE].pending) val |= (1 << 12);
  213 + if (s->gic->irq_state[ARMV7M_EXCP_MEM].pending) val |= (1 << 13);
  214 + if (s->gic->irq_state[ARMV7M_EXCP_BUS].pending) val |= (1 << 14);
  215 + if (s->gic->irq_state[ARMV7M_EXCP_SVC].pending) val |= (1 << 15);
  216 + if (s->gic->irq_state[ARMV7M_EXCP_MEM].enabled) val |= (1 << 16);
  217 + if (s->gic->irq_state[ARMV7M_EXCP_BUS].enabled) val |= (1 << 17);
  218 + if (s->gic->irq_state[ARMV7M_EXCP_USAGE].enabled) val |= (1 << 18);
  219 + return val;
  220 + case 0xd28: /* Configurable Fault Status. */
  221 + /* TODO: Implement Fault Status. */
  222 + cpu_abort(cpu_single_env,
  223 + "Not implemented: Configurable Fault Status.");
  224 + return 0;
  225 + case 0xd2c: /* Hard Fault Status. */
  226 + case 0xd30: /* Debug Fault Status. */
  227 + case 0xd34: /* Mem Manage Address. */
  228 + case 0xd38: /* Bus Fault Address. */
  229 + case 0xd3c: /* Aux Fault Status. */
  230 + /* TODO: Implement fault status registers. */
  231 + goto bad_reg;
  232 + case 0xd40: /* PFR0. */
  233 + return 0x00000030;
  234 + case 0xd44: /* PRF1. */
  235 + return 0x00000200;
  236 + case 0xd48: /* DFR0. */
  237 + return 0x00100000;
  238 + case 0xd4c: /* AFR0. */
  239 + return 0x00000000;
  240 + case 0xd50: /* MMFR0. */
  241 + return 0x00000030;
  242 + case 0xd54: /* MMFR1. */
  243 + return 0x00000000;
  244 + case 0xd58: /* MMFR2. */
  245 + return 0x00000000;
  246 + case 0xd5c: /* MMFR3. */
  247 + return 0x00000000;
  248 + case 0xd60: /* ISAR0. */
  249 + return 0x01141110;
  250 + case 0xd64: /* ISAR1. */
  251 + return 0x02111000;
  252 + case 0xd68: /* ISAR2. */
  253 + return 0x21112231;
  254 + case 0xd6c: /* ISAR3. */
  255 + return 0x01111110;
  256 + case 0xd70: /* ISAR4. */
  257 + return 0x01310102;
  258 + /* TODO: Implement debug registers. */
  259 + default:
  260 + bad_reg:
  261 + cpu_abort(cpu_single_env, "NVIC: Bad read offset 0x%x\n", offset);
  262 + }
  263 +}
  264 +
  265 +static void nvic_writel(void *opaque, uint32_t offset, uint32_t value)
  266 +{
  267 + nvic_state *s = (nvic_state *)opaque;
  268 + uint32_t oldval;
  269 + switch (offset) {
  270 + case 0x10: /* SysTick Control and Status. */
  271 + oldval = s->systick.control;
  272 + s->systick.control &= 0xfffffff8;
  273 + s->systick.control |= value & 7;
  274 + if ((oldval ^ value) & SYSTICK_ENABLE) {
  275 + int64_t now = qemu_get_clock(vm_clock);
  276 + if (value & SYSTICK_ENABLE) {
  277 + if (s->systick.tick) {
  278 + s->systick.tick += now;
  279 + qemu_mod_timer(s->systick.timer, s->systick.tick);
  280 + } else {
  281 + systick_reload(s, 1);
  282 + }
  283 + } else {
  284 + qemu_del_timer(s->systick.timer);
  285 + s->systick.tick -= now;
  286 + if (s->systick.tick < 0)
  287 + s->systick.tick = 0;
  288 + }
  289 + } else if ((oldval ^ value) & SYSTICK_CLKSOURCE) {
  290 + /* This is a hack. Force the timer to be reloaded
  291 + when the reference clock is changed. */
  292 + systick_reload(s, 1);
  293 + }
  294 + break;
  295 + case 0x14: /* SysTick Reload Value. */
  296 + s->systick.reload = value;
  297 + break;
  298 + case 0x18: /* SysTick Current Value. Writes reload the timer. */
  299 + systick_reload(s, 1);
  300 + s->systick.control &= ~SYSTICK_COUNTFLAG;
  301 + break;
  302 + case 0xd04: /* Interrupt Control State. */
  303 + if (value & (1 << 31)) {
  304 + armv7m_nvic_set_pending(s, ARMV7M_EXCP_NMI);
  305 + }
  306 + if (value & (1 << 28)) {
  307 + armv7m_nvic_set_pending(s, ARMV7M_EXCP_PENDSV);
  308 + } else if (value & (1 << 27)) {
  309 + s->gic->irq_state[ARMV7M_EXCP_PENDSV].pending = 0;
  310 + gic_update(s->gic);
  311 + }
  312 + if (value & (1 << 26)) {
  313 + armv7m_nvic_set_pending(s, ARMV7M_EXCP_SYSTICK);
  314 + } else if (value & (1 << 25)) {
  315 + s->gic->irq_state[ARMV7M_EXCP_SYSTICK].pending = 0;
  316 + gic_update(s->gic);
  317 + }
  318 + break;
  319 + case 0xd08: /* Vector Table Offset. */
  320 + cpu_single_env->v7m.vecbase = value & 0xffffff80;
  321 + break;
  322 + case 0xd0c: /* Application Interrupt/Reset Control. */
  323 + if ((value >> 16) == 0x05fa) {
  324 + if (value & 2) {
  325 + cpu_abort(cpu_single_env, "VECTCLRACTIVE not implemented");
  326 + }
  327 + if (value & 5) {
  328 + cpu_abort(cpu_single_env, "System reset");
  329 + }
  330 + }
  331 + break;
  332 + case 0xd10: /* System Control. */
  333 + case 0xd14: /* Configuration Control. */
  334 + /* TODO: Implement control registers. */
  335 + goto bad_reg;
  336 + case 0xd18: case 0xd1c: case 0xd20: /* System Handler Priority. */
  337 + {
  338 + int irq;
  339 + irq = offset - 0xd14;
  340 + s->gic->priority1[irq++][0] = value & 0xff;
  341 + s->gic->priority1[irq++][0] = (value >> 8) & 0xff;
  342 + s->gic->priority1[irq++][0] = (value >> 16) & 0xff;
  343 + s->gic->priority1[irq][0] = (value >> 24) & 0xff;
  344 + gic_update(s->gic);
  345 + }
  346 + break;
  347 + case 0xd24: /* System Handler Control. */
  348 + /* TODO: Real hardware allows you to set/clear the active bits
  349 + under some circumstances. We don't implement this. */
  350 + s->gic->irq_state[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0;
  351 + s->gic->irq_state[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0;
  352 + s->gic->irq_state[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0;
  353 + break;
  354 + case 0xd28: /* Configurable Fault Status. */
  355 + case 0xd2c: /* Hard Fault Status. */
  356 + case 0xd30: /* Debug Fault Status. */
  357 + case 0xd34: /* Mem Manage Address. */
  358 + case 0xd38: /* Bus Fault Address. */
  359 + case 0xd3c: /* Aux Fault Status. */
  360 + goto bad_reg;
  361 + default:
  362 + bad_reg:
  363 + cpu_abort(cpu_single_env, "NVIC: Bad write offset 0x%x\n", offset);
  364 + }
  365 +}
  366 +
  367 +qemu_irq *armv7m_nvic_init(CPUState *env)
  368 +{
  369 + nvic_state *s;
  370 + qemu_irq *parent;
  371 +
  372 + parent = arm_pic_init_cpu(env);
  373 + s = (nvic_state *)qemu_mallocz(sizeof(nvic_state));
  374 + s->gic = gic_init(0xe000e000, &parent[ARM_PIC_CPU_IRQ]);
  375 + s->gic->nvic = s;
  376 + s->systick.timer = qemu_new_timer(vm_clock, systick_timer_tick, s);
  377 + if (env->v7m.nvic)
  378 + cpu_abort(env, "CPU can only have one NVIC\n");
  379 + env->v7m.nvic = s;
  380 + return s->gic->in;
  381 +}
... ...
hw/integratorcp.c
... ... @@ -497,8 +497,8 @@ static void integratorcp_init(int ram_size, int vga_ram_size,
497 497 icp_pic_init(0xca000000, pic[26], NULL);
498 498 icp_pit_init(0x13000000, pic, 5);
499 499 pl031_init(0x15000000, pic[8]);
500   - pl011_init(0x16000000, pic[1], serial_hds[0]);
501   - pl011_init(0x17000000, pic[2], serial_hds[1]);
  500 + pl011_init(0x16000000, pic[1], serial_hds[0], PL011_ARM);
  501 + pl011_init(0x17000000, pic[2], serial_hds[1], PL011_ARM);
502 502 icp_control_init(0xcb000000);
503 503 pl050_init(0x18000000, pic[3], 0);
504 504 pl050_init(0x19000000, pic[4], 1);
... ...
hw/mpcore.c 0 โ†’ 100644
  1 +/*
  2 + * ARM MPCore internal peripheral emulation.
  3 + *
  4 + * Copyright (c) 2006-2007 CodeSourcery.
  5 + * Written by Paul Brook
  6 + *
  7 + * This code is licenced under the GPL.
  8 + */
  9 +
  10 +#include "vl.h"
  11 +
  12 +#define MPCORE_PRIV_BASE 0x10100000
  13 +#define NCPU 4
  14 +/* ??? The MPCore TRM says the on-chip controller has 224 external IRQ lines
  15 + (+ 32 internal). However my test chip only exposes/reports 32.
  16 + More importantly Linux falls over if more than 32 are present! */
  17 +#define GIC_NIRQ 64
  18 +
  19 +static inline int
  20 +gic_get_current_cpu(void)
  21 +{
  22 + return cpu_single_env->cpu_index;
  23 +}
  24 +
  25 +#include "arm_gic.c"
  26 +
  27 +/* MPCore private memory region. */
  28 +
  29 +typedef struct {
  30 + uint32_t count;
  31 + uint32_t load;
  32 + uint32_t control;
  33 + uint32_t status;
  34 + uint32_t old_status;
  35 + int64_t tick;
  36 + QEMUTimer *timer;
  37 + struct mpcore_priv_state *mpcore;
  38 + int id; /* Encodes both timer/watchdog and CPU. */
  39 +} mpcore_timer_state;
  40 +
  41 +typedef struct mpcore_priv_state {
  42 + gic_state *gic;
  43 + uint32_t scu_control;
  44 + mpcore_timer_state timer[8];
  45 +} mpcore_priv_state;
  46 +
  47 +/* Per-CPU Timers. */
  48 +
  49 +static inline void mpcore_timer_update_irq(mpcore_timer_state *s)
  50 +{
  51 + if (s->status & ~s->old_status) {
  52 + gic_set_pending_private(s->mpcore->gic, s->id >> 1, 29 + (s->id & 1));
  53 + }
  54 + s->old_status = s->status;
  55 +}
  56 +
  57 +/* Return conversion factor from mpcore timer ticks to qemu timer ticks. */
  58 +static inline uint32_t mpcore_timer_scale(mpcore_timer_state *s)
  59 +{
  60 + return (((s->control >> 8) & 0xff) + 1) * 10;
  61 +}
  62 +
  63 +static void mpcore_timer_reload(mpcore_timer_state *s, int restart)
  64 +{
  65 + if (s->count == 0)
  66 + return;
  67 + if (restart)
  68 + s->tick = qemu_get_clock(vm_clock);
  69 + s->tick += (int64_t)s->count * mpcore_timer_scale(s);
  70 + qemu_mod_timer(s->timer, s->tick);
  71 +}
  72 +
  73 +static void mpcore_timer_tick(void *opaque)
  74 +{
  75 + mpcore_timer_state *s = (mpcore_timer_state *)opaque;
  76 + s->status = 1;
  77 + if (s->control & 2) {
  78 + s->count = s->load;
  79 + mpcore_timer_reload(s, 0);
  80 + } else {
  81 + s->count = 0;
  82 + }
  83 + mpcore_timer_update_irq(s);
  84 +}
  85 +
  86 +static uint32_t mpcore_timer_read(mpcore_timer_state *s, int offset)
  87 +{
  88 + int64_t val;
  89 + switch (offset) {
  90 + case 0: /* Load */
  91 + return s->load;
  92 + /* Fall through. */
  93 + case 4: /* Counter. */
  94 + if (((s->control & 1) == 0) || (s->count == 0))
  95 + return 0;
  96 + /* Slow and ugly, but hopefully won't happen too often. */
  97 + val = s->tick - qemu_get_clock(vm_clock);
  98 + val /= mpcore_timer_scale(s);
  99 + if (val < 0)
  100 + val = 0;
  101 + return val;
  102 + case 8: /* Control. */
  103 + return s->control;
  104 + case 12: /* Interrupt status. */
  105 + return s->status;
  106 + }
  107 +}
  108 +
  109 +static void mpcore_timer_write(mpcore_timer_state *s, int offset,
  110 + uint32_t value)
  111 +{
  112 + int64_t old;
  113 + switch (offset) {
  114 + case 0: /* Load */
  115 + s->load = value;
  116 + /* Fall through. */
  117 + case 4: /* Counter. */
  118 + if ((s->control & 1) && s->count) {
  119 + /* Cancel the previous timer. */
  120 + qemu_del_timer(s->timer);
  121 + }
  122 + s->count = value;
  123 + if (s->control & 1) {
  124 + mpcore_timer_reload(s, 1);
  125 + }
  126 + break;
  127 + case 8: /* Control. */
  128 + old = s->control;
  129 + s->control = value;
  130 + if (((old & 1) == 0) && (value & 1)) {
  131 + if (s->count == 0 && (s->control & 2))
  132 + s->count = s->load;
  133 + mpcore_timer_reload(s, 1);
  134 + }
  135 + break;
  136 + case 12: /* Interrupt status. */
  137 + s->status &= ~value;
  138 + mpcore_timer_update_irq(s);
  139 + break;
  140 + }
  141 +}
  142 +
  143 +static void mpcore_timer_init(mpcore_priv_state *mpcore,
  144 + mpcore_timer_state *s, int id)
  145 +{
  146 + s->id = id;
  147 + s->mpcore = mpcore;
  148 + s->timer = qemu_new_timer(vm_clock, mpcore_timer_tick, s);
  149 +}
  150 +
  151 +
  152 +/* Per-CPU private memory mapped IO. */
  153 +
  154 +static uint32_t mpcore_priv_read(void *opaque, target_phys_addr_t offset)
  155 +{
  156 + mpcore_priv_state *s = (mpcore_priv_state *)opaque;
  157 + int id;
  158 + offset &= 0xfff;
  159 + if (offset < 0x100) {
  160 + /* SCU */
  161 + switch (offset) {
  162 + case 0x00: /* Control. */
  163 + return s->scu_control;
  164 + case 0x04: /* Configuration. */
  165 + return 0xf3;
  166 + case 0x08: /* CPU status. */
  167 + return 0;
  168 + case 0x0c: /* Invalidate all. */
  169 + return 0;
  170 + default:
  171 + goto bad_reg;
  172 + }
  173 + } else if (offset < 0x600) {
  174 + /* Interrupt controller. */
  175 + if (offset < 0x200) {
  176 + id = gic_get_current_cpu();
  177 + } else {
  178 + id = (offset - 0x200) >> 8;
  179 + }
  180 + return gic_cpu_read(s->gic, id, offset & 0xff);
  181 + } else if (offset < 0xb00) {
  182 + /* Timers. */
  183 + if (offset < 0x700) {
  184 + id = gic_get_current_cpu();
  185 + } else {
  186 + id = (offset - 0x700) >> 8;
  187 + }
  188 + id <<= 1;
  189 + if (offset & 0x20)
  190 + id++;
  191 + return mpcore_timer_read(&s->timer[id], offset & 0xf);
  192 + }
  193 +bad_reg:
  194 + cpu_abort(cpu_single_env, "mpcore_priv_read: Bad offset %x\n",
  195 + (int)offset);
  196 + return 0;
  197 +}
  198 +
  199 +static void mpcore_priv_write(void *opaque, target_phys_addr_t offset,
  200 + uint32_t value)
  201 +{
  202 + mpcore_priv_state *s = (mpcore_priv_state *)opaque;
  203 + int id;
  204 + offset &= 0xfff;
  205 + if (offset < 0x100) {
  206 + /* SCU */
  207 + switch (offset) {
  208 + case 0: /* Control register. */
  209 + s->scu_control = value & 1;
  210 + break;
  211 + case 0x0c: /* Invalidate all. */
  212 + /* This is a no-op as cache is not emulated. */
  213 + break;
  214 + default:
  215 + goto bad_reg;
  216 + }
  217 + } else if (offset < 0x600) {
  218 + /* Interrupt controller. */
  219 + if (offset < 0x200) {
  220 + id = gic_get_current_cpu();
  221 + } else {
  222 + id = (offset - 0x200) >> 8;
  223 + }
  224 + gic_cpu_write(s->gic, id, offset & 0xff, value);
  225 + } else if (offset < 0xb00) {
  226 + /* Timers. */
  227 + if (offset < 0x700) {
  228 + id = gic_get_current_cpu();
  229 + } else {
  230 + id = (offset - 0x700) >> 8;
  231 + }
  232 + id <<= 1;
  233 + if (offset & 0x20)
  234 + id++;
  235 + mpcore_timer_write(&s->timer[id], offset & 0xf, value);
  236 + return;
  237 + }
  238 + return;
  239 +bad_reg:
  240 + cpu_abort(cpu_single_env, "mpcore_priv_read: Bad offset %x\n",
  241 + (int)offset);
  242 +}
  243 +
  244 +static CPUReadMemoryFunc *mpcore_priv_readfn[] = {
  245 + mpcore_priv_read,
  246 + mpcore_priv_read,
  247 + mpcore_priv_read
  248 +};
  249 +
  250 +static CPUWriteMemoryFunc *mpcore_priv_writefn[] = {
  251 + mpcore_priv_write,
  252 + mpcore_priv_write,
  253 + mpcore_priv_write
  254 +};
  255 +
  256 +
  257 +static qemu_irq *mpcore_priv_init(uint32_t base, qemu_irq *pic_irq)
  258 +{
  259 + mpcore_priv_state *s;
  260 + int iomemtype;
  261 + int i;
  262 +
  263 + s = (mpcore_priv_state *)qemu_mallocz(sizeof(mpcore_priv_state));
  264 + if (!s)
  265 + return NULL;
  266 + s->gic = gic_init(base, pic_irq);
  267 + if (!s->gic)
  268 + return NULL;
  269 + iomemtype = cpu_register_io_memory(0, mpcore_priv_readfn,
  270 + mpcore_priv_writefn, s);
  271 + cpu_register_physical_memory(base, 0x00001000, iomemtype);
  272 + for (i = 0; i < 8; i++) {
  273 + mpcore_timer_init(s, &s->timer[i], i);
  274 + }
  275 + return s->gic->in;
  276 +}
  277 +
  278 +/* Dummy PIC to route IRQ lines. The baseboard has 4 independent IRQ
  279 + controllers. The output of these, plus some of the raw input lines
  280 + are fed into a single SMP-aware interrupt controller on the CPU. */
  281 +typedef struct {
  282 + qemu_irq *cpuic;
  283 + qemu_irq *rvic[4];
  284 +} mpcore_rirq_state;
  285 +
  286 +/* Map baseboard IRQs onto CPU IRQ lines. */
  287 +static const int mpcore_irq_map[32] = {
  288 + -1, -1, -1, -1, 1, 2, -1, -1,
  289 + -1, -1, 6, -1, 4, 5, -1, -1,
  290 + -1, 14, 15, 0, 7, 8, -1, -1,
  291 + -1, -1, -1, -1, 9, 3, -1, -1,
  292 +};
  293 +
  294 +static void mpcore_rirq_set_irq(void *opaque, int irq, int level)
  295 +{
  296 + mpcore_rirq_state *s = (mpcore_rirq_state *)opaque;
  297 + int i;
  298 +
  299 + for (i = 0; i < 4; i++) {
  300 + qemu_set_irq(s->rvic[i][irq], level);
  301 + }
  302 + if (irq < 32) {
  303 + irq = mpcore_irq_map[irq];
  304 + if (irq >= 0) {
  305 + qemu_set_irq(s->cpuic[irq], level);
  306 + }
  307 + }
  308 +}
  309 +
  310 +qemu_irq *mpcore_irq_init(qemu_irq *cpu_irq)
  311 +{
  312 + mpcore_rirq_state *s;
  313 + int n;
  314 +
  315 + /* ??? IRQ routing is hardcoded to "normal" mode. */
  316 + s = qemu_mallocz(sizeof(mpcore_rirq_state));
  317 + s->cpuic = mpcore_priv_init(MPCORE_PRIV_BASE, cpu_irq);
  318 + for (n = 0; n < 4; n++) {
  319 + s->rvic[n] = realview_gic_init(0x10040000 + n * 0x10000,
  320 + s->cpuic[10 + n]);
  321 + }
  322 + return qemu_allocate_irqs(mpcore_rirq_set_irq, s, 64);
  323 +}
... ...
hw/pl011.c
... ... @@ -28,6 +28,7 @@ typedef struct {
28 28 int read_trigger;
29 29 CharDriverState *chr;
30 30 qemu_irq irq;
  31 + enum pl011_type type;
31 32 } pl011_state;
32 33  
33 34 #define PL011_INT_TX 0x20
... ... @@ -38,8 +39,10 @@ typedef struct {
38 39 #define PL011_FLAG_TXFF 0x20
39 40 #define PL011_FLAG_RXFE 0x10
40 41  
41   -static const unsigned char pl011_id[] =
42   -{ 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
  42 +static const unsigned char pl011_id[2][8] = {
  43 + { 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 }, /* PL011_ARM */
  44 + { 0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 }, /* PL011_LUMINARY */
  45 +};
43 46  
44 47 static void pl011_update(pl011_state *s)
45 48 {
... ... @@ -56,7 +59,7 @@ static uint32_t pl011_read(void *opaque, target_phys_addr_t offset)
56 59  
57 60 offset -= s->base;
58 61 if (offset >= 0xfe0 && offset < 0x1000) {
59   - return pl011_id[(offset - 0xfe0) >> 2];
  62 + return pl011_id[s->type][(offset - 0xfe0) >> 2];
60 63 }
61 64 switch (offset >> 2) {
62 65 case 0: /* UARTDR */
... ... @@ -137,6 +140,9 @@ static void pl011_write(void *opaque, target_phys_addr_t offset,
137 140 case 1: /* UARTCR */
138 141 s->cr = value;
139 142 break;
  143 + case 6: /* UARTFR */
  144 + /* Writes to Flag register are ignored. */
  145 + break;
140 146 case 8: /* UARTUARTILPR */
141 147 s->ilpr = value;
142 148 break;
... ... @@ -224,7 +230,7 @@ static CPUWriteMemoryFunc *pl011_writefn[] = {
224 230 };
225 231  
226 232 void pl011_init(uint32_t base, qemu_irq irq,
227   - CharDriverState *chr)
  233 + CharDriverState *chr, enum pl011_type type)
228 234 {
229 235 int iomemtype;
230 236 pl011_state *s;
... ... @@ -235,6 +241,7 @@ void pl011_init(uint32_t base, qemu_irq irq,
235 241 cpu_register_physical_memory(base, 0x00001000, iomemtype);
236 242 s->base = base;
237 243 s->irq = irq;
  244 + s->type = type;
238 245 s->chr = chr;
239 246 s->read_trigger = 1;
240 247 s->ifl = 0x12;
... ...
hw/pl022.c 0 โ†’ 100644
  1 +/*
  2 + * Arm PrimeCell PL022 Synchronous Serial Port
  3 + *
  4 + * Copyright (c) 2007 CodeSourcery.
  5 + * Written by Paul Brook
  6 + *
  7 + * This code is licenced under the GPL.
  8 + */
  9 +
  10 +#include "vl.h"
  11 +
  12 +//#define DEBUG_PL022 1
  13 +
  14 +#ifdef DEBUG_PL022
  15 +#define DPRINTF(fmt, args...) \
  16 +do { printf("pl022: " fmt , ##args); } while (0)
  17 +#define BADF(fmt, args...) \
  18 +do { fprintf(stderr, "pl022: error: " fmt , ##args); exit(1);} while (0)
  19 +#else
  20 +#define DPRINTF(fmt, args...) do {} while(0)
  21 +#define BADF(fmt, args...) \
  22 +do { fprintf(stderr, "pl022: error: " fmt , ##args);} while (0)
  23 +#endif
  24 +
  25 +#define PL022_CR1_LBM 0x01
  26 +#define PL022_CR1_SSE 0x02
  27 +#define PL022_CR1_MS 0x04
  28 +#define PL022_CR1_SDO 0x08
  29 +
  30 +#define PL022_SR_TFE 0x01
  31 +#define PL022_SR_TNF 0x02
  32 +#define PL022_SR_RNE 0x04
  33 +#define PL022_SR_RFF 0x08
  34 +#define PL022_SR_BSY 0x10
  35 +
  36 +#define PL022_INT_ROR 0x01
  37 +#define PL022_INT_RT 0x04
  38 +#define PL022_INT_RX 0x04
  39 +#define PL022_INT_TX 0x08
  40 +
  41 +typedef struct {
  42 + uint32_t base;
  43 + uint32_t cr0;
  44 + uint32_t cr1;
  45 + uint32_t bitmask;
  46 + uint32_t sr;
  47 + uint32_t cpsr;
  48 + uint32_t is;
  49 + uint32_t im;
  50 + /* The FIFO head points to the next empty entry. */
  51 + int tx_fifo_head;
  52 + int rx_fifo_head;
  53 + int tx_fifo_len;
  54 + int rx_fifo_len;
  55 + uint16_t tx_fifo[8];
  56 + uint16_t rx_fifo[8];
  57 + qemu_irq irq;
  58 + int (*xfer_cb)(void *, int);
  59 + void *opaque;
  60 +} pl022_state;
  61 +
  62 +static const unsigned char pl022_id[8] =
  63 + { 0x22, 0x10, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
  64 +
  65 +static void pl022_update(pl022_state *s)
  66 +{
  67 + s->sr = 0;
  68 + if (s->tx_fifo_len == 0)
  69 + s->sr |= PL022_SR_TFE;
  70 + if (s->tx_fifo_len != 8)
  71 + s->sr |= PL022_SR_TNF;
  72 + if (s->rx_fifo_len != 0)
  73 + s->sr |= PL022_SR_RNE;
  74 + if (s->rx_fifo_len == 8)
  75 + s->sr |= PL022_SR_RFF;
  76 + if (s->tx_fifo_len)
  77 + s->sr |= PL022_SR_BSY;
  78 + s->is = 0;
  79 + if (s->rx_fifo_len >= 4)
  80 + s->is |= PL022_INT_RX;
  81 + if (s->tx_fifo_len <= 4)
  82 + s->is |= PL022_INT_TX;
  83 +
  84 + qemu_set_irq(s->irq, (s->is & s->im) != 0);
  85 +}
  86 +
  87 +static void pl022_xfer(pl022_state *s)
  88 +{
  89 + int i;
  90 + int o;
  91 + int val;
  92 +
  93 + if ((s->cr1 & PL022_CR1_SSE) == 0) {
  94 + pl022_update(s);
  95 + DPRINTF("Disabled\n");
  96 + return;
  97 + }
  98 +
  99 + DPRINTF("Maybe xfer %d/%d\n", s->tx_fifo_len, s->rx_fifo_len);
  100 + i = (s->tx_fifo_head - s->tx_fifo_len) & 7;
  101 + o = s->rx_fifo_head;
  102 + /* ??? We do not emulate the line speed.
  103 + This may break some applications. The are two problematic cases:
  104 + (a) A driver feeds data into the TX FIFO until it is full,
  105 + and only then drains the RX FIFO. On real hardware the CPU can
  106 + feed data fast enough that the RX fifo never gets chance to overflow.
  107 + (b) A driver transmits data, deliberately allowing the RX FIFO to
  108 + overflow because it ignores the RX data anyway.
  109 +
  110 + We choose to support (a) by stalling the transmit engine if it would
  111 + cause the RX FIFO to overflow. In practice much transmit-only code
  112 + falls into (a) because it flushes the RX FIFO to determine when
  113 + the transfer has completed. */
  114 + while (s->tx_fifo_len && s->rx_fifo_len < 8) {
  115 + DPRINTF("xfer\n");
  116 + val = s->tx_fifo[i];
  117 + if (s->cr1 & PL022_CR1_LBM) {
  118 + /* Loopback mode. */
  119 + } else if (s->xfer_cb) {
  120 + val = s->xfer_cb(s->opaque, val);
  121 + } else {
  122 + val = 0;
  123 + }
  124 + s->rx_fifo[o] = val & s->bitmask;
  125 + i = (i + 1) & 7;
  126 + o = (o + 1) & 7;
  127 + s->tx_fifo_len--;
  128 + s->rx_fifo_len++;
  129 + }
  130 + s->rx_fifo_head = o;
  131 + pl022_update(s);
  132 +}
  133 +
  134 +static uint32_t pl022_read(void *opaque, target_phys_addr_t offset)
  135 +{
  136 + pl022_state *s = (pl022_state *)opaque;
  137 + int val;
  138 +
  139 + offset -= s->base;
  140 + if (offset >= 0xfe0 && offset < 0x1000) {
  141 + return pl022_id[(offset - 0xfe0) >> 2];
  142 + }
  143 + switch (offset) {
  144 + case 0x00: /* CR0 */
  145 + return s->cr0;
  146 + case 0x04: /* CR1 */
  147 + return s->cr1;
  148 + case 0x08: /* DR */
  149 + if (s->rx_fifo_len) {
  150 + val = s->rx_fifo[(s->rx_fifo_head - s->rx_fifo_len) & 7];
  151 + DPRINTF("RX %02x\n", val);
  152 + s->rx_fifo_len--;
  153 + pl022_xfer(s);
  154 + } else {
  155 + val = 0;
  156 + }
  157 + return val;
  158 + case 0x0c: /* SR */
  159 + return s->sr;
  160 + case 0x10: /* CPSR */
  161 + return s->cpsr;
  162 + case 0x14: /* IMSC */
  163 + return s->im;
  164 + case 0x18: /* RIS */
  165 + return s->is;
  166 + case 0x1c: /* MIS */
  167 + return s->im & s->is;
  168 + case 0x20: /* DMACR */
  169 + /* Not implemented. */
  170 + return 0;
  171 + default:
  172 + cpu_abort (cpu_single_env, "pl022_read: Bad offset %x\n",
  173 + (int)offset);
  174 + return 0;
  175 + }
  176 +}
  177 +
  178 +static void pl022_write(void *opaque, target_phys_addr_t offset,
  179 + uint32_t value)
  180 +{
  181 + pl022_state *s = (pl022_state *)opaque;
  182 +
  183 + offset -= s->base;
  184 + switch (offset) {
  185 + case 0x00: /* CR0 */
  186 + s->cr0 = value;
  187 + /* Clock rate and format are ignored. */
  188 + s->bitmask = (1 << ((value & 15) + 1)) - 1;
  189 + break;
  190 + case 0x04: /* CR1 */
  191 + s->cr1 = value;
  192 + if ((s->cr1 & (PL022_CR1_MS | PL022_CR1_SSE))
  193 + == (PL022_CR1_MS | PL022_CR1_SSE)) {
  194 + BADF("SPI slave mode not implemented\n");
  195 + }
  196 + pl022_xfer(s);
  197 + break;
  198 + case 0x08: /* DR */
  199 + if (s->tx_fifo_len < 8) {
  200 + DPRINTF("TX %02x\n", value);
  201 + s->tx_fifo[s->tx_fifo_head] = value & s->bitmask;
  202 + s->tx_fifo_head = (s->tx_fifo_head + 1) & 7;
  203 + s->tx_fifo_len++;
  204 + pl022_xfer(s);
  205 + }
  206 + break;
  207 + case 0x10: /* CPSR */
  208 + /* Prescaler. Ignored. */
  209 + s->cpsr = value & 0xff;
  210 + break;
  211 + case 0x14: /* IMSC */
  212 + s->im = value;
  213 + pl022_update(s);
  214 + break;
  215 + case 0x20: /* DMACR */
  216 + if (value)
  217 + cpu_abort (cpu_single_env, "pl022: DMA not implemented\n");
  218 + break;
  219 + default:
  220 + cpu_abort (cpu_single_env, "pl022_write: Bad offset %x\n",
  221 + (int)offset);
  222 + }
  223 +}
  224 +
  225 +static void pl022_reset(pl022_state *s)
  226 +{
  227 + s->rx_fifo_len = 0;
  228 + s->tx_fifo_len = 0;
  229 + s->im = 0;
  230 + s->is = PL022_INT_TX;
  231 + s->sr = PL022_SR_TFE | PL022_SR_TNF;
  232 +}
  233 +
  234 +static CPUReadMemoryFunc *pl022_readfn[] = {
  235 + pl022_read,
  236 + pl022_read,
  237 + pl022_read
  238 +};
  239 +
  240 +static CPUWriteMemoryFunc *pl022_writefn[] = {
  241 + pl022_write,
  242 + pl022_write,
  243 + pl022_write
  244 +};
  245 +
  246 +void pl022_init(uint32_t base, qemu_irq irq, int (*xfer_cb)(void *, int),
  247 + void * opaque)
  248 +{
  249 + int iomemtype;
  250 + pl022_state *s;
  251 +
  252 + s = (pl022_state *)qemu_mallocz(sizeof(pl022_state));
  253 + iomemtype = cpu_register_io_memory(0, pl022_readfn,
  254 + pl022_writefn, s);
  255 + cpu_register_physical_memory(base, 0x00001000, iomemtype);
  256 + s->base = base;
  257 + s->irq = irq;
  258 + s->xfer_cb = xfer_cb;
  259 + s->opaque = opaque;
  260 + pl022_reset(s);
  261 + /* ??? Save/restore. */
  262 +}
  263 +
  264 +
... ...
hw/pl061.c 0 โ†’ 100644
  1 +/*
  2 + * Arm PrimeCell PL061 General Purpose IO with additional
  3 + * Luminary Micro Stellaris bits.
  4 + *
  5 + * Copyright (c) 2007 CodeSourcery.
  6 + * Written by Paul Brook
  7 + *
  8 + * This code is licenced under the GPL.
  9 + */
  10 +
  11 +#include "vl.h"
  12 +
  13 +//#define DEBUG_PL061 1
  14 +
  15 +#ifdef DEBUG_PL061
  16 +#define DPRINTF(fmt, args...) \
  17 +do { printf("pl061: " fmt , ##args); } while (0)
  18 +#define BADF(fmt, args...) \
  19 +do { fprintf(stderr, "pl061: error: " fmt , ##args); exit(1);} while (0)
  20 +#else
  21 +#define DPRINTF(fmt, args...) do {} while(0)
  22 +#define BADF(fmt, args...) \
  23 +do { fprintf(stderr, "pl061: error: " fmt , ##args);} while (0)
  24 +#endif
  25 +
  26 +static const uint8_t pl061_id[12] =
  27 + { 0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 };
  28 +
  29 +typedef struct {
  30 + uint32_t base;
  31 + int locked;
  32 + uint8_t data;
  33 + uint8_t old_data;
  34 + uint8_t dir;
  35 + uint8_t isense;
  36 + uint8_t ibe;
  37 + uint8_t iev;
  38 + uint8_t im;
  39 + uint8_t istate;
  40 + uint8_t afsel;
  41 + uint8_t dr2r;
  42 + uint8_t dr4r;
  43 + uint8_t dr8r;
  44 + uint8_t odr;
  45 + uint8_t pur;
  46 + uint8_t pdr;
  47 + uint8_t slr;
  48 + uint8_t den;
  49 + uint8_t cr;
  50 + qemu_irq irq;
  51 + qemu_irq out[8];
  52 +} pl061_state;
  53 +
  54 +static void pl061_update(pl061_state *s)
  55 +{
  56 + uint8_t changed;
  57 + uint8_t mask;
  58 + int i;
  59 +
  60 + changed = s->old_data ^ s->data;
  61 + if (!changed)
  62 + return;
  63 +
  64 + s->old_data = s->data;
  65 + for (i = 0; i < 8; i++) {
  66 + mask = 1 << i;
  67 + if ((changed & mask & s->dir) && s->out) {
  68 + DPRINTF("Set output %d = %d\n", i, (s->data & mask) != 0);
  69 + qemu_set_irq(s->out[i], (s->data & mask) != 0);
  70 + }
  71 + }
  72 +
  73 + /* FIXME: Implement input interrupts. */
  74 +}
  75 +
  76 +static uint32_t pl061_read(void *opaque, target_phys_addr_t offset)
  77 +{
  78 + pl061_state *s = (pl061_state *)opaque;
  79 +
  80 + offset -= s->base;
  81 + if (offset >= 0xfd0 && offset < 0x1000) {
  82 + return pl061_id[(offset - 0xfd0) >> 2];
  83 + }
  84 + if (offset < 0x400) {
  85 + return s->data & (offset >> 2);
  86 + }
  87 + switch (offset) {
  88 + case 0x400: /* Direction */
  89 + return s->dir;
  90 + case 0x404: /* Interrupt sense */
  91 + return s->isense;
  92 + case 0x408: /* Interrupt both edges */
  93 + return s->ibe;
  94 + case 0x40c: /* Interupt event */
  95 + return s->iev;
  96 + case 0x410: /* Interrupt mask */
  97 + return s->im;
  98 + case 0x414: /* Raw interrupt status */
  99 + return s->istate;
  100 + case 0x418: /* Masked interrupt status */
  101 + return s->istate | s->im;
  102 + case 0x420: /* Alternate function select */
  103 + return s->afsel;
  104 + case 0x500: /* 2mA drive */
  105 + return s->dr2r;
  106 + case 0x504: /* 4mA drive */
  107 + return s->dr4r;
  108 + case 0x508: /* 8mA drive */
  109 + return s->dr8r;
  110 + case 0x50c: /* Open drain */
  111 + return s->odr;
  112 + case 0x510: /* Pull-up */
  113 + return s->pur;
  114 + case 0x514: /* Pull-down */
  115 + return s->pdr;
  116 + case 0x518: /* Slew rate control */
  117 + return s->slr;
  118 + case 0x51c: /* Digital enable */
  119 + return s->den;
  120 + case 0x520: /* Lock */
  121 + return s->locked;
  122 + case 0x524: /* Commit */
  123 + return s->cr;
  124 + default:
  125 + cpu_abort (cpu_single_env, "pl061_read: Bad offset %x\n",
  126 + (int)offset);
  127 + return 0;
  128 + }
  129 +}
  130 +
  131 +static void pl061_write(void *opaque, target_phys_addr_t offset,
  132 + uint32_t value)
  133 +{
  134 + pl061_state *s = (pl061_state *)opaque;
  135 + uint8_t mask;
  136 +
  137 + offset -= s->base;
  138 + if (offset < 0x400) {
  139 + mask = (offset >> 2) & s->dir;
  140 + s->data = (s->data & ~mask) | (value & mask);
  141 + pl061_update(s);
  142 + return;
  143 + }
  144 + switch (offset) {
  145 + case 0x400: /* Direction */
  146 + s->dir = value;
  147 + break;
  148 + case 0x404: /* Interrupt sense */
  149 + s->isense = value;
  150 + break;
  151 + case 0x408: /* Interrupt both edges */
  152 + s->ibe = value;
  153 + break;
  154 + case 0x40c: /* Interupt event */
  155 + s->iev = value;
  156 + break;
  157 + case 0x410: /* Interrupt mask */
  158 + s->im = value;
  159 + break;
  160 + case 0x41c: /* Interrupt clear */
  161 + s->istate &= ~value;
  162 + break;
  163 + case 0x420: /* Alternate function select */
  164 + mask = s->cr;
  165 + s->afsel = (s->afsel & ~mask) | (value & mask);
  166 + break;
  167 + case 0x500: /* 2mA drive */
  168 + s->dr2r = value;
  169 + break;
  170 + case 0x504: /* 4mA drive */
  171 + s->dr4r = value;
  172 + break;
  173 + case 0x508: /* 8mA drive */
  174 + s->dr8r = value;
  175 + break;
  176 + case 0x50c: /* Open drain */
  177 + s->odr = value;
  178 + break;
  179 + case 0x510: /* Pull-up */
  180 + s->pur = value;
  181 + break;
  182 + case 0x514: /* Pull-down */
  183 + s->pdr = value;
  184 + break;
  185 + case 0x518: /* Slew rate control */
  186 + s->slr = value;
  187 + break;
  188 + case 0x51c: /* Digital enable */
  189 + s->den = value;
  190 + break;
  191 + case 0x520: /* Lock */
  192 + s->locked = (value != 0xacce551);
  193 + break;
  194 + case 0x524: /* Commit */
  195 + if (!s->locked)
  196 + s->cr = value;
  197 + break;
  198 + default:
  199 + cpu_abort (cpu_single_env, "pl061_write: Bad offset %x\n",
  200 + (int)offset);
  201 + }
  202 + pl061_update(s);
  203 +}
  204 +
  205 +static void pl061_reset(pl061_state *s)
  206 +{
  207 + s->locked = 1;
  208 + s->cr = 0xff;
  209 +}
  210 +
  211 +void pl061_set_irq(void * opaque, int irq, int level)
  212 +{
  213 + pl061_state *s = (pl061_state *)opaque;
  214 + uint8_t mask;
  215 +
  216 + mask = 1 << irq;
  217 + if ((s->dir & mask) == 0) {
  218 + s->data &= ~mask;
  219 + if (level)
  220 + s->data |= mask;
  221 + pl061_update(s);
  222 + }
  223 +}
  224 +
  225 +static CPUReadMemoryFunc *pl061_readfn[] = {
  226 + pl061_read,
  227 + pl061_read,
  228 + pl061_read
  229 +};
  230 +
  231 +static CPUWriteMemoryFunc *pl061_writefn[] = {
  232 + pl061_write,
  233 + pl061_write,
  234 + pl061_write
  235 +};
  236 +
  237 +/* Returns an array of inputs. */
  238 +qemu_irq *pl061_init(uint32_t base, qemu_irq irq, qemu_irq **out)
  239 +{
  240 + int iomemtype;
  241 + pl061_state *s;
  242 +
  243 + s = (pl061_state *)qemu_mallocz(sizeof(pl061_state));
  244 + iomemtype = cpu_register_io_memory(0, pl061_readfn,
  245 + pl061_writefn, s);
  246 + cpu_register_physical_memory(base, 0x00001000, iomemtype);
  247 + s->base = base;
  248 + s->irq = irq;
  249 + pl061_reset(s);
  250 + if (out)
  251 + *out = s->out;
  252 +
  253 + /* ??? Save/restore. */
  254 + return qemu_allocate_irqs(pl061_set_irq, s, 8);
  255 +}
  256 +
... ...
hw/pxa2xx.c
... ... @@ -297,7 +297,7 @@ static void pxa2xx_clkpwr_write(void *opaque, int op2, int reg, int crm,
297 297 ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
298 298 s->env->cp15.c1_sys = 0;
299 299 s->env->cp15.c1_coproc = 0;
300   - s->env->cp15.c2_base = 0;
  300 + s->env->cp15.c2_base0 = 0;
301 301 s->env->cp15.c3 = 0;
302 302 s->pm_regs[PSSR >> 2] |= 0x8; /* Set STS */
303 303 s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
... ... @@ -2031,7 +2031,8 @@ struct pxa2xx_state_s *pxa270_init(unsigned int sdram_size,
2031 2031 fprintf(stderr, "Unable to find CPU definition\n");
2032 2032 exit(1);
2033 2033 }
2034   - register_savevm("cpu", 0, 0, cpu_save, cpu_load, s->env);
  2034 + register_savevm("cpu", 0, ARM_CPU_SAVE_VERSION, cpu_save, cpu_load,
  2035 + s->env);
2035 2036  
2036 2037 /* SDRAM & Internal Memory Storage */
2037 2038 cpu_register_physical_memory(PXA2XX_SDRAM_BASE,
... ... @@ -2145,7 +2146,8 @@ struct pxa2xx_state_s *pxa255_init(unsigned int sdram_size,
2145 2146 fprintf(stderr, "Unable to find CPU definition\n");
2146 2147 exit(1);
2147 2148 }
2148   - register_savevm("cpu", 0, 0, cpu_save, cpu_load, s->env);
  2149 + register_savevm("cpu", 0, ARM_CPU_SAVE_VERSION, cpu_save, cpu_load,
  2150 + s->env);
2149 2151  
2150 2152 /* SDRAM & Internal Memory Storage */
2151 2153 cpu_register_physical_memory(PXA2XX_SDRAM_BASE, sdram_size,
... ...
hw/realview.c
... ... @@ -25,13 +25,32 @@ static void realview_init(int ram_size, int vga_ram_size,
25 25 NICInfo *nd;
26 26 int n;
27 27 int done_smc = 0;
  28 + qemu_irq cpu_irq[4];
  29 + int ncpu;
28 30  
29 31 if (!cpu_model)
30 32 cpu_model = "arm926";
31   - env = cpu_init(cpu_model);
32   - if (!env) {
33   - fprintf(stderr, "Unable to find CPU definition\n");
34   - exit(1);
  33 + /* FIXME: obey smp_cpus. */
  34 + if (strcmp(cpu_model, "arm11mpcore") == 0) {
  35 + ncpu = 4;
  36 + } else {
  37 + ncpu = 1;
  38 + }
  39 +
  40 + for (n = 0; n < ncpu; n++) {
  41 + env = cpu_init(cpu_model);
  42 + if (!env) {
  43 + fprintf(stderr, "Unable to find CPU definition\n");
  44 + exit(1);
  45 + }
  46 + pic = arm_pic_init_cpu(env);
  47 + cpu_irq[n] = pic[ARM_PIC_CPU_IRQ];
  48 + if (n > 0) {
  49 + /* Set entry point for secondary CPUs. This assumes we're using
  50 + the init code from arm_boot.c. Real hardware resets all CPUs
  51 + the same. */
  52 + env->regs[15] = 0x80000000;
  53 + }
35 54 }
36 55  
37 56 /* ??? RAM shoud repeat to fill physical memory space. */
... ... @@ -39,18 +58,23 @@ static void realview_init(int ram_size, int vga_ram_size,
39 58 cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
40 59  
41 60 arm_sysctl_init(0x10000000, 0xc1400400);
42   - pic = arm_pic_init_cpu(env);
43   - /* ??? The documentation says GIC1 is nFIQ and either GIC2 or GIC3
44   - is nIRQ (there are inconsistencies). However Linux 2.6.17 expects
45   - GIC1 to be nIRQ and ignores all the others, so do that for now. */
46   - pic = arm_gic_init(0x10040000, pic[ARM_PIC_CPU_IRQ]);
  61 +
  62 + if (ncpu == 1) {
  63 + /* ??? The documentation says GIC1 is nFIQ and either GIC2 or GIC3
  64 + is nIRQ (there are inconsistencies). However Linux 2.6.17 expects
  65 + GIC1 to be nIRQ and ignores all the others, so do that for now. */
  66 + pic = realview_gic_init(0x10040000, cpu_irq[0]);
  67 + } else {
  68 + pic = mpcore_irq_init(cpu_irq);
  69 + }
  70 +
47 71 pl050_init(0x10006000, pic[20], 0);
48 72 pl050_init(0x10007000, pic[21], 1);
49 73  
50   - pl011_init(0x10009000, pic[12], serial_hds[0]);
51   - pl011_init(0x1000a000, pic[13], serial_hds[1]);
52   - pl011_init(0x1000b000, pic[14], serial_hds[2]);
53   - pl011_init(0x1000c000, pic[15], serial_hds[3]);
  74 + pl011_init(0x10009000, pic[12], serial_hds[0], PL011_ARM);
  75 + pl011_init(0x1000a000, pic[13], serial_hds[1], PL011_ARM);
  76 + pl011_init(0x1000b000, pic[14], serial_hds[2], PL011_ARM);
  77 + pl011_init(0x1000c000, pic[15], serial_hds[3], PL011_ARM);
54 78  
55 79 /* DMA controller is optional, apparently. */
56 80 pl080_init(0x10030000, pic[24], 2);
... ... @@ -114,10 +138,10 @@ static void realview_init(int ram_size, int vga_ram_size,
114 138 /* 0x10019000 PCI controller config. */
115 139 /* 0x10020000 CLCD. */
116 140 /* 0x10030000 DMA Controller. */
117   - /* 0x10040000 GIC1 (FIQ1). */
118   - /* 0x10050000 GIC2 (IRQ1). */
119   - /* 0x10060000 GIC3 (FIQ2). */
120   - /* 0x10070000 GIC4 (IRQ2). */
  141 + /* 0x10040000 GIC1. */
  142 + /* 0x10050000 GIC2. */
  143 + /* 0x10060000 GIC3. */
  144 + /* 0x10070000 GIC4. */
121 145 /* 0x10080000 SMC. */
122 146 /* 0x40000000 NOR flash. */
123 147 /* 0x44000000 DoC flash. */
... ... @@ -137,8 +161,14 @@ static void realview_init(int ram_size, int vga_ram_size,
137 161 /* 0x68000000 PCI mem 1. */
138 162 /* 0x6c000000 PCI mem 2. */
139 163  
140   - arm_load_kernel(env, ram_size, kernel_filename, kernel_cmdline,
  164 + arm_load_kernel(first_cpu, ram_size, kernel_filename, kernel_cmdline,
141 165 initrd_filename, 0x33b, 0x0);
  166 +
  167 + /* ??? Hack to map an additional page of ram for the secondary CPU
  168 + startup code. I guess this works on real hardware because the
  169 + BootROM happens to be in ROM/flash or in memory that isn't clobbered
  170 + until after Linux boots the secondary CPUs. */
  171 + cpu_register_physical_memory(0x80000000, 0x1000, IO_MEM_RAM + ram_size);
142 172 }
143 173  
144 174 QEMUMachine realview_machine = {
... ...
hw/realview_gic.c 0 โ†’ 100644
  1 +/*
  2 + * ARM RealView Emulation Baseboard Interrupt Controller
  3 + *
  4 + * Copyright (c) 2006-2007 CodeSourcery.
  5 + * Written by Paul Brook
  6 + *
  7 + * This code is licenced under the GPL.
  8 + */
  9 +
  10 +#include "vl.h"
  11 +#include "arm_pic.h"
  12 +
  13 +#define GIC_NIRQ 96
  14 +#define NCPU 1
  15 +
  16 +/* Only a single "CPU" interface is present. */
  17 +static inline int
  18 +gic_get_current_cpu(void)
  19 +{
  20 + return 0;
  21 +}
  22 +
  23 +#include "arm_gic.c"
  24 +
  25 +static uint32_t realview_gic_cpu_read(void *opaque, target_phys_addr_t offset)
  26 +{
  27 + gic_state *s = (gic_state *)opaque;
  28 + offset -= s->base;
  29 + return gic_cpu_read(s, gic_get_current_cpu(), offset);
  30 +}
  31 +
  32 +static void realview_gic_cpu_write(void *opaque, target_phys_addr_t offset,
  33 + uint32_t value)
  34 +{
  35 + gic_state *s = (gic_state *)opaque;
  36 + offset -= s->base;
  37 + gic_cpu_write(s, gic_get_current_cpu(), offset, value);
  38 +}
  39 +
  40 +static CPUReadMemoryFunc *realview_gic_cpu_readfn[] = {
  41 + realview_gic_cpu_read,
  42 + realview_gic_cpu_read,
  43 + realview_gic_cpu_read
  44 +};
  45 +
  46 +static CPUWriteMemoryFunc *realview_gic_cpu_writefn[] = {
  47 + realview_gic_cpu_write,
  48 + realview_gic_cpu_write,
  49 + realview_gic_cpu_write
  50 +};
  51 +
  52 +qemu_irq *realview_gic_init(uint32_t base, qemu_irq parent_irq)
  53 +{
  54 + gic_state *s;
  55 + int iomemtype;
  56 +
  57 + s = gic_init(base, &parent_irq);
  58 + if (!s)
  59 + return NULL;
  60 + iomemtype = cpu_register_io_memory(0, realview_gic_cpu_readfn,
  61 + realview_gic_cpu_writefn, s);
  62 + cpu_register_physical_memory(base, 0x00001000, iomemtype);
  63 + return s->in;
  64 +}
... ...
hw/ssd0303.c 0 โ†’ 100644
  1 +/*
  2 + * SSD0303 OLED controller with OSRAM Pictiva 96x16 display.
  3 + *
  4 + * Copyright (c) 2006-2007 CodeSourcery.
  5 + * Written by Paul Brook
  6 + *
  7 + * This code is licenced under the GPL.
  8 + */
  9 +
  10 +/* The controller can support a variety of different displays, but we only
  11 + implement one. Most of the commends relating to brightness and geometry
  12 + setup are ignored. */
  13 +#include "vl.h"
  14 +
  15 +//#define DEBUG_SSD0303 1
  16 +
  17 +#ifdef DEBUG_SSD0303
  18 +#define DPRINTF(fmt, args...) \
  19 +do { printf("ssd0303: " fmt , ##args); } while (0)
  20 +#define BADF(fmt, args...) \
  21 +do { fprintf(stderr, "ssd0303: error: " fmt , ##args); exit(1);} while (0)
  22 +#else
  23 +#define DPRINTF(fmt, args...) do {} while(0)
  24 +#define BADF(fmt, args...) \
  25 +do { fprintf(stderr, "ssd0303: error: " fmt , ##args);} while (0)
  26 +#endif
  27 +
  28 +/* Scaling factor for pixels. */
  29 +#define MAGNIFY 4
  30 +
  31 +enum ssd0303_mode
  32 +{
  33 + SSD0303_IDLE,
  34 + SSD0303_DATA,
  35 + SSD0303_CMD
  36 +};
  37 +
  38 +enum ssd0303_cmd {
  39 + SSD0303_CMD_NONE,
  40 + SSD0303_CMD_SKIP1
  41 +};
  42 +
  43 +typedef struct {
  44 + i2c_slave i2c;
  45 + DisplayState *ds;
  46 + int row;
  47 + int col;
  48 + int start_line;
  49 + int mirror;
  50 + int flash;
  51 + int enabled;
  52 + int inverse;
  53 + int redraw;
  54 + enum ssd0303_mode mode;
  55 + enum ssd0303_cmd cmd_state;
  56 + uint8_t framebuffer[132*8];
  57 +} ssd0303_state;
  58 +
  59 +static int ssd0303_recv(i2c_slave *i2c)
  60 +{
  61 + BADF("Reads not implemented\n");
  62 + return -1;
  63 +}
  64 +
  65 +static int ssd0303_send(i2c_slave *i2c, uint8_t data)
  66 +{
  67 + ssd0303_state *s = (ssd0303_state *)i2c;
  68 + enum ssd0303_cmd old_cmd_state;
  69 + switch (s->mode) {
  70 + case SSD0303_IDLE:
  71 + DPRINTF("byte 0x%02x\n", data);
  72 + if (data == 0x80)
  73 + s->mode = SSD0303_CMD;
  74 + else if (data == 0x40)
  75 + s->mode = SSD0303_DATA;
  76 + else
  77 + BADF("Unexpected byte 0x%x\n", data);
  78 + break;
  79 + case SSD0303_DATA:
  80 + DPRINTF("data 0x%02x\n", data);
  81 + if (s->col < 132) {
  82 + s->framebuffer[s->col + s->row * 132] = data;
  83 + s->col++;
  84 + s->redraw = 1;
  85 + }
  86 + break;
  87 + case SSD0303_CMD:
  88 + old_cmd_state = s->cmd_state;
  89 + s->cmd_state = SSD0303_CMD_NONE;
  90 + switch (old_cmd_state) {
  91 + case SSD0303_CMD_NONE:
  92 + DPRINTF("cmd 0x%02x\n", data);
  93 + s->mode = SSD0303_IDLE;
  94 + switch (data) {
  95 + case 0x00 ... 0x0f: /* Set lower colum address. */
  96 + s->col = (s->col & 0xf0) | (data & 0xf);
  97 + break;
  98 + case 0x10 ... 0x20: /* Set higher column address. */
  99 + s->col = (s->col & 0x0f) | ((data & 0xf) << 4);
  100 + break;
  101 + case 0x40 ... 0x7f: /* Set start line. */
  102 + s->start_line = 0;
  103 + break;
  104 + case 0x81: /* Set contrast (Ignored). */
  105 + s->cmd_state = SSD0303_CMD_SKIP1;
  106 + break;
  107 + case 0xa0: /* Mirror off. */
  108 + s->mirror = 0;
  109 + break;
  110 + case 0xa1: /* Mirror off. */
  111 + s->mirror = 1;
  112 + break;
  113 + case 0xa4: /* Entire display off. */
  114 + s->flash = 0;
  115 + break;
  116 + case 0xa5: /* Entire display on. */
  117 + s->flash = 1;
  118 + break;
  119 + case 0xa6: /* Inverse off. */
  120 + s->inverse = 0;
  121 + break;
  122 + case 0xa7: /* Inverse on. */
  123 + s->inverse = 1;
  124 + break;
  125 + case 0xa8: /* Set multipled ratio (Ignored). */
  126 + s->cmd_state = SSD0303_CMD_SKIP1;
  127 + break;
  128 + case 0xad: /* DC-DC power control. */
  129 + s->cmd_state = SSD0303_CMD_SKIP1;
  130 + break;
  131 + case 0xae: /* Display off. */
  132 + s->enabled = 0;
  133 + break;
  134 + case 0xaf: /* Display on. */
  135 + s->enabled = 1;
  136 + break;
  137 + case 0xb0 ... 0xbf: /* Set Page address. */
  138 + s->row = data & 7;
  139 + break;
  140 + case 0xc0 ... 0xc8: /* Set COM output direction (Ignored). */
  141 + break;
  142 + case 0xd3: /* Set display offset (Ignored). */
  143 + s->cmd_state = SSD0303_CMD_SKIP1;
  144 + break;
  145 + case 0xd5: /* Set display clock (Ignored). */
  146 + s->cmd_state = SSD0303_CMD_SKIP1;
  147 + break;
  148 + case 0xd8: /* Set color and power mode (Ignored). */
  149 + s->cmd_state = SSD0303_CMD_SKIP1;
  150 + break;
  151 + case 0xd9: /* Set pre-charge period (Ignored). */
  152 + s->cmd_state = SSD0303_CMD_SKIP1;
  153 + break;
  154 + case 0xda: /* Set COM pin configuration (Ignored). */
  155 + s->cmd_state = SSD0303_CMD_SKIP1;
  156 + break;
  157 + case 0xdb: /* Set VCOM dselect level (Ignored). */
  158 + s->cmd_state = SSD0303_CMD_SKIP1;
  159 + break;
  160 + case 0xe3: /* no-op. */
  161 + break;
  162 + default:
  163 + BADF("Unknown command: 0x%x\n", data);
  164 + }
  165 + break;
  166 + case SSD0303_CMD_SKIP1:
  167 + DPRINTF("skip 0x%02x\n", data);
  168 + break;
  169 + }
  170 + break;
  171 + }
  172 + return 0;
  173 +}
  174 +
  175 +static void ssd0303_event(i2c_slave *i2c, enum i2c_event event)
  176 +{
  177 + ssd0303_state *s = (ssd0303_state *)i2c;
  178 + switch (event) {
  179 + case I2C_FINISH:
  180 + s->mode = SSD0303_IDLE;
  181 + break;
  182 + case I2C_START_RECV:
  183 + case I2C_START_SEND:
  184 + case I2C_NACK:
  185 + /* Nothing to do. */
  186 + break;
  187 + }
  188 +}
  189 +
  190 +static void ssd0303_update_display(void *opaque)
  191 +{
  192 + ssd0303_state *s = (ssd0303_state *)opaque;
  193 + uint8_t *dest;
  194 + uint8_t *src;
  195 + int x;
  196 + int y;
  197 + int line;
  198 + char *colors[2];
  199 + char colortab[MAGNIFY * 8];
  200 + int dest_width;
  201 + uint8_t mask;
  202 +
  203 + if (s->redraw) {
  204 + switch (s->ds->depth) {
  205 + case 0:
  206 + return;
  207 + case 15:
  208 + dest_width = 2;
  209 + break;
  210 + case 16:
  211 + dest_width = 2;
  212 + break;
  213 + case 24:
  214 + dest_width = 3;
  215 + break;
  216 + case 32:
  217 + dest_width = 4;
  218 + break;
  219 + default:
  220 + BADF("Bad color depth\n");
  221 + return;
  222 + }
  223 + dest_width *= MAGNIFY;
  224 + memset(colortab, 0xff, dest_width);
  225 + memset(colortab + dest_width, 0, dest_width);
  226 + if (s->flash) {
  227 + colors[0] = colortab;
  228 + colors[1] = colortab;
  229 + } else if (s->inverse) {
  230 + colors[0] = colortab;
  231 + colors[1] = colortab + dest_width;
  232 + } else {
  233 + colors[0] = colortab + dest_width;
  234 + colors[1] = colortab;
  235 + }
  236 + dest = s->ds->data;
  237 + for (y = 0; y < 16; y++) {
  238 + line = (y + s->start_line) & 63;
  239 + src = s->framebuffer + 132 * (line >> 3) + 36;
  240 + mask = 1 << (line & 7);
  241 + for (x = 0; x < 96; x++) {
  242 + memcpy(dest, colors[(*src & mask) != 0], dest_width);
  243 + dest += dest_width;
  244 + src++;
  245 + }
  246 + for (x = 1; x < MAGNIFY; x++) {
  247 + memcpy(dest, dest - dest_width * 96, dest_width * 96);
  248 + dest += dest_width * 96;
  249 + }
  250 + }
  251 + }
  252 + dpy_update(s->ds, 0, 0, 96 * MAGNIFY, 16 * MAGNIFY);
  253 +}
  254 +
  255 +static void ssd0303_invalidate_display(void * opaque)
  256 +{
  257 + ssd0303_state *s = (ssd0303_state *)opaque;
  258 + s->redraw = 1;
  259 +}
  260 +
  261 +void ssd0303_init(DisplayState *ds, i2c_bus *bus, int address)
  262 +{
  263 + ssd0303_state *s;
  264 +
  265 + s = (ssd0303_state *)i2c_slave_init(bus, address, sizeof(ssd0303_state));
  266 + s->ds = ds;
  267 + s->i2c.event = ssd0303_event;
  268 + s->i2c.recv = ssd0303_recv;
  269 + s->i2c.send = ssd0303_send;
  270 + graphic_console_init(ds, ssd0303_update_display, ssd0303_invalidate_display,
  271 + NULL, s);
  272 + dpy_resize(s->ds, 96 * MAGNIFY, 16 * MAGNIFY);
  273 +}
... ...
hw/ssd0323.c 0 โ†’ 100644
  1 +/*
  2 + * SSD0323 OLED controller with OSRAM Pictiva 128x64 display.
  3 + *
  4 + * Copyright (c) 2006-2007 CodeSourcery.
  5 + * Written by Paul Brook
  6 + *
  7 + * This code is licenced under the GPL.
  8 + */
  9 +
  10 +/* The controller can support a variety of different displays, but we only
  11 + implement one. Most of the commends relating to brightness and geometry
  12 + setup are ignored. */
  13 +#include "vl.h"
  14 +
  15 +//#define DEBUG_SSD0323 1
  16 +
  17 +#ifdef DEBUG_SSD0323
  18 +#define DPRINTF(fmt, args...) \
  19 +do { printf("ssd0323: " fmt , ##args); } while (0)
  20 +#define BADF(fmt, args...) \
  21 +do { fprintf(stderr, "ssd0323: error: " fmt , ##args); exit(1);} while (0)
  22 +#else
  23 +#define DPRINTF(fmt, args...) do {} while(0)
  24 +#define BADF(fmt, args...) \
  25 +do { fprintf(stderr, "ssd0323: error: " fmt , ##args);} while (0)
  26 +#endif
  27 +
  28 +/* Scaling factor for pixels. */
  29 +#define MAGNIFY 4
  30 +
  31 +enum ssd0323_mode
  32 +{
  33 + SSD0323_CMD,
  34 + SSD0323_DATA
  35 +};
  36 +
  37 +typedef struct {
  38 + DisplayState *ds;
  39 +
  40 + int cmd_len;
  41 + int cmd;
  42 + int cmd_data[8];
  43 + int row;
  44 + int row_start;
  45 + int row_end;
  46 + int col;
  47 + int col_start;
  48 + int col_end;
  49 + int redraw;
  50 + enum ssd0323_mode mode;
  51 + uint8_t framebuffer[128 * 80 / 2];
  52 +} ssd0323_state;
  53 +
  54 +int ssd0323_xfer_ssi(void *opaque, int data)
  55 +{
  56 + ssd0323_state *s = (ssd0323_state *)opaque;
  57 + switch (s->mode) {
  58 + case SSD0323_DATA:
  59 + DPRINTF("data 0x%02x\n", data);
  60 + s->framebuffer[s->col + s->row * 64] = data;
  61 + s->col++;
  62 + if (s->col > s->col_end) {
  63 + s->row++;
  64 + s->col = s->col_start;
  65 + }
  66 + if (s->row > s->row_end) {
  67 + s->row = s->row_start;
  68 + }
  69 + s->redraw = 1;
  70 + break;
  71 + case SSD0323_CMD:
  72 + DPRINTF("cmd 0x%02x\n", data);
  73 + if (s->cmd_len == 0) {
  74 + s->cmd = data;
  75 + } else {
  76 + s->cmd_data[s->cmd_len - 1] = data;
  77 + }
  78 + s->cmd_len++;
  79 + switch (s->cmd) {
  80 +#define DATA(x) if (s->cmd_len <= (x)) return 0
  81 + case 0x15: /* Set column. */
  82 + DATA(2);
  83 + s->col_start = s->cmd_data[0] % 64;
  84 + s->col_end = s->cmd_data[1] % 64;
  85 + break;
  86 + case 0x75: /* Set row. */
  87 + DATA(2);
  88 + s->row_start = s->cmd_data[0] % 80;
  89 + s->row_end = s->cmd_data[1] % 80;
  90 + break;
  91 + case 0x81: /* Set contrast */
  92 + DATA(1);
  93 + break;
  94 + case 0x84: case 0x85: case 0x86: /* Max current. */
  95 + DATA(0);
  96 + break;
  97 + case 0xa0: /* Set remapping. */
  98 + /* FIXME: Implement this. */
  99 + DATA(1);
  100 + break;
  101 + case 0xa1: /* Set display start line. */
  102 + case 0xa2: /* Set display offset. */
  103 + /* FIXME: Implement these. */
  104 + DATA(1);
  105 + break;
  106 + case 0xa4: /* Normal mode. */
  107 + case 0xa5: /* All on. */
  108 + case 0xa6: /* All off. */
  109 + case 0xa7: /* Inverse. */
  110 + /* FIXME: Implement these. */
  111 + DATA(0);
  112 + break;
  113 + case 0xa8: /* Set multiplex ratio. */
  114 + case 0xad: /* Set DC-DC converter. */
  115 + DATA(1);
  116 + /* Ignored. Don't care. */
  117 + break;
  118 + case 0xae: /* Display off. */
  119 + case 0xaf: /* Display on. */
  120 + DATA(0);
  121 + /* TODO: Implement power control. */
  122 + break;
  123 + case 0xb1: /* Set phase length. */
  124 + case 0xb2: /* Set row period. */
  125 + case 0xb3: /* Set clock rate. */
  126 + case 0xbc: /* Set precharge. */
  127 + case 0xbe: /* Set VCOMH. */
  128 + case 0xbf: /* Set segment low. */
  129 + DATA(1);
  130 + /* Ignored. Don't care. */
  131 + break;
  132 + case 0xb8: /* Set grey scale table. */
  133 + /* FIXME: Implement this. */
  134 + DATA(8);
  135 + break;
  136 + case 0xe3: /* NOP. */
  137 + DATA(0);
  138 + break;
  139 + default:
  140 + BADF("Unknown command: 0x%x\n", data);
  141 + }
  142 + s->cmd_len = 0;
  143 + return 0;
  144 + }
  145 + return 0;
  146 +}
  147 +
  148 +static void ssd0323_update_display(void *opaque)
  149 +{
  150 + ssd0323_state *s = (ssd0323_state *)opaque;
  151 + uint8_t *dest;
  152 + uint8_t *src;
  153 + int x;
  154 + int y;
  155 + int i;
  156 + int line;
  157 + char *colors[16];
  158 + char colortab[MAGNIFY * 64];
  159 + char *p;
  160 + int dest_width;
  161 +
  162 + if (s->redraw) {
  163 + switch (s->ds->depth) {
  164 + case 0:
  165 + return;
  166 + case 15:
  167 + dest_width = 2;
  168 + break;
  169 + case 16:
  170 + dest_width = 2;
  171 + break;
  172 + case 24:
  173 + dest_width = 3;
  174 + break;
  175 + case 32:
  176 + dest_width = 4;
  177 + break;
  178 + default:
  179 + BADF("Bad color depth\n");
  180 + return;
  181 + }
  182 + p = colortab;
  183 + for (i = 0; i < 16; i++) {
  184 + int n;
  185 + colors[i] = p;
  186 + switch (s->ds->depth) {
  187 + case 15:
  188 + n = i * 2 + (i >> 3);
  189 + p[0] = n | (n << 5);
  190 + p[1] = (n << 2) | (n >> 3);
  191 + break;
  192 + case 16:
  193 + n = i * 2 + (i >> 3);
  194 + p[0] = n | (n << 6) | ((n << 1) & 0x20);
  195 + p[1] = (n << 3) | (n >> 2);
  196 + break;
  197 + case 24:
  198 + case 32:
  199 + n = (i << 4) | i;
  200 + p[0] = p[1] = p[2] = n;
  201 + break;
  202 + default:
  203 + BADF("Bad color depth\n");
  204 + return;
  205 + }
  206 + p += dest_width;
  207 + }
  208 + dest = s->ds->data;
  209 + for (y = 0; y < 64; y++) {
  210 + line = y;
  211 + src = s->framebuffer + 64 * line;
  212 + for (x = 0; x < 64; x++) {
  213 + int val;
  214 + val = *src >> 4;
  215 + for (i = 0; i < MAGNIFY; i++) {
  216 + memcpy(dest, colors[val], dest_width);
  217 + dest += dest_width;
  218 + }
  219 + val = *src & 0xf;
  220 + for (i = 0; i < MAGNIFY; i++) {
  221 + memcpy(dest, colors[val], dest_width);
  222 + dest += dest_width;
  223 + }
  224 + src++;
  225 + }
  226 + for (i = 1; i < MAGNIFY; i++) {
  227 + memcpy(dest, dest - dest_width * MAGNIFY * 128,
  228 + dest_width * 128 * MAGNIFY);
  229 + dest += dest_width * 128 * MAGNIFY;
  230 + }
  231 + }
  232 + }
  233 + dpy_update(s->ds, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY);
  234 +}
  235 +
  236 +static void ssd0323_invalidate_display(void * opaque)
  237 +{
  238 + ssd0323_state *s = (ssd0323_state *)opaque;
  239 + s->redraw = 1;
  240 +}
  241 +
  242 +/* Command/data input. */
  243 +static void ssd0323_cd(void *opaque, int n, int level)
  244 +{
  245 + ssd0323_state *s = (ssd0323_state *)opaque;
  246 + DPRINTF("%s mode\n", level ? "Data" : "Command");
  247 + s->mode = level ? SSD0323_DATA : SSD0323_CMD;
  248 +}
  249 +
  250 +void *ssd0323_init(DisplayState *ds, qemu_irq *cmd_p)
  251 +{
  252 + ssd0323_state *s;
  253 + qemu_irq *cmd;
  254 +
  255 + s = (ssd0323_state *)qemu_mallocz(sizeof(ssd0323_state));
  256 + s->ds = ds;
  257 + graphic_console_init(ds, ssd0323_update_display, ssd0323_invalidate_display,
  258 + NULL, s);
  259 + dpy_resize(s->ds, 128 * MAGNIFY, 64 * MAGNIFY);
  260 + s->col_end = 63;
  261 + s->row_end = 79;
  262 +
  263 + cmd = qemu_allocate_irqs(ssd0323_cd, s, 1);
  264 + *cmd_p = *cmd;
  265 +
  266 + return s;
  267 +}
... ...
hw/stellaris.c 0 โ†’ 100644
  1 +/*
  2 + * Luminary Micro Stellaris preipherals
  3 + *
  4 + * Copyright (c) 2006 CodeSourcery.
  5 + * Written by Paul Brook
  6 + *
  7 + * This code is licenced under the GPL.
  8 + */
  9 +
  10 +#include "vl.h"
  11 +#include "arm_pic.h"
  12 +
  13 +typedef const struct {
  14 + const char *name;
  15 + uint32_t did0;
  16 + uint32_t did1;
  17 + uint32_t dc0;
  18 + uint32_t dc1;
  19 + uint32_t dc2;
  20 + uint32_t dc3;
  21 + uint32_t dc4;
  22 + enum {OLED_I2C, OLED_SSI} oled;
  23 +} stellaris_board_info;
  24 +
  25 +/* General purpose timer module. */
  26 +
  27 +/* Multiplication factor to convert from GPTM timer ticks to qemu timer
  28 + ticks. */
  29 +static int stellaris_clock_scale;
  30 +
  31 +typedef struct gptm_state {
  32 + uint32_t config;
  33 + uint32_t mode[2];
  34 + uint32_t control;
  35 + uint32_t state;
  36 + uint32_t mask;
  37 + uint32_t load[2];
  38 + uint32_t match[2];
  39 + uint32_t prescale[2];
  40 + uint32_t match_prescale[2];
  41 + uint32_t rtc;
  42 + int64_t tick[2];
  43 + struct gptm_state *opaque[2];
  44 + uint32_t base;
  45 + QEMUTimer *timer[2];
  46 + /* The timers have an alternate output used to trigger the ADC. */
  47 + qemu_irq trigger;
  48 + qemu_irq irq;
  49 +} gptm_state;
  50 +
  51 +static void gptm_update_irq(gptm_state *s)
  52 +{
  53 + int level;
  54 + level = (s->state & s->mask) != 0;
  55 + qemu_set_irq(s->irq, level);
  56 +}
  57 +
  58 +static void gptm_stop(gptm_state *s, int n)
  59 +{
  60 + qemu_del_timer(s->timer[n]);
  61 +}
  62 +
  63 +static void gptm_reload(gptm_state *s, int n, int reset)
  64 +{
  65 + int64_t tick;
  66 + if (reset)
  67 + tick = qemu_get_clock(vm_clock);
  68 + else
  69 + tick = s->tick[n];
  70 +
  71 + if (s->config == 0) {
  72 + /* 32-bit CountDown. */
  73 + uint32_t count;
  74 + count = s->load[0] | (s->load[1] << 16);
  75 + tick += (int64_t)count * stellaris_clock_scale;
  76 + } else if (s->config == 1) {
  77 + /* 32-bit RTC. 1Hz tick. */
  78 + tick += ticks_per_sec;
  79 + } else if (s->mode[n] == 0xa) {
  80 + /* PWM mode. Not implemented. */
  81 + } else {
  82 + cpu_abort(cpu_single_env, "TODO: 16-bit timer mode 0x%x\n",
  83 + s->mode[n]);
  84 + }
  85 + s->tick[n] = tick;
  86 + qemu_mod_timer(s->timer[n], tick);
  87 +}
  88 +
  89 +static void gptm_tick(void *opaque)
  90 +{
  91 + gptm_state **p = (gptm_state **)opaque;
  92 + gptm_state *s;
  93 + int n;
  94 +
  95 + s = *p;
  96 + n = p - s->opaque;
  97 + if (s->config == 0) {
  98 + s->state |= 1;
  99 + if ((s->control & 0x20)) {
  100 + /* Output trigger. */
  101 + qemu_irq_raise(s->trigger);
  102 + qemu_irq_lower(s->trigger);
  103 + }
  104 + if (s->mode[0] & 1) {
  105 + /* One-shot. */
  106 + s->control &= ~1;
  107 + } else {
  108 + /* Periodic. */
  109 + gptm_reload(s, 0, 0);
  110 + }
  111 + } else if (s->config == 1) {
  112 + /* RTC. */
  113 + uint32_t match;
  114 + s->rtc++;
  115 + match = s->match[0] | (s->match[1] << 16);
  116 + if (s->rtc > match)
  117 + s->rtc = 0;
  118 + if (s->rtc == 0) {
  119 + s->state |= 8;
  120 + }
  121 + gptm_reload(s, 0, 0);
  122 + } else if (s->mode[n] == 0xa) {
  123 + /* PWM mode. Not implemented. */
  124 + } else {
  125 + cpu_abort(cpu_single_env, "TODO: 16-bit timer mode 0x%x\n",
  126 + s->mode[n]);
  127 + }
  128 + gptm_update_irq(s);
  129 +}
  130 +
  131 +static uint32_t gptm_read(void *opaque, target_phys_addr_t offset)
  132 +{
  133 + gptm_state *s = (gptm_state *)opaque;
  134 +
  135 + offset -= s->base;
  136 + switch (offset) {
  137 + case 0x00: /* CFG */
  138 + return s->config;
  139 + case 0x04: /* TAMR */
  140 + return s->mode[0];
  141 + case 0x08: /* TBMR */
  142 + return s->mode[1];
  143 + case 0x0c: /* CTL */
  144 + return s->control;
  145 + case 0x18: /* IMR */
  146 + return s->mask;
  147 + case 0x1c: /* RIS */
  148 + return s->state;
  149 + case 0x20: /* MIS */
  150 + return s->state & s->mask;
  151 + case 0x24: /* CR */
  152 + return 0;
  153 + case 0x28: /* TAILR */
  154 + return s->load[0] | ((s->config < 4) ? (s->load[1] << 16) : 0);
  155 + case 0x2c: /* TBILR */
  156 + return s->load[1];
  157 + case 0x30: /* TAMARCHR */
  158 + return s->match[0] | ((s->config < 4) ? (s->match[1] << 16) : 0);
  159 + case 0x34: /* TBMATCHR */
  160 + return s->match[1];
  161 + case 0x38: /* TAPR */
  162 + return s->prescale[0];
  163 + case 0x3c: /* TBPR */
  164 + return s->prescale[1];
  165 + case 0x40: /* TAPMR */
  166 + return s->match_prescale[0];
  167 + case 0x44: /* TBPMR */
  168 + return s->match_prescale[1];
  169 + case 0x48: /* TAR */
  170 + if (s->control == 1)
  171 + return s->rtc;
  172 + case 0x4c: /* TBR */
  173 + cpu_abort(cpu_single_env, "TODO: Timer value read\n");
  174 + default:
  175 + cpu_abort(cpu_single_env, "gptm_read: Bad offset 0x%x\n", (int)offset);
  176 + return 0;
  177 + }
  178 +}
  179 +
  180 +static void gptm_write(void *opaque, target_phys_addr_t offset, uint32_t value)
  181 +{
  182 + gptm_state *s = (gptm_state *)opaque;
  183 + uint32_t oldval;
  184 +
  185 + offset -= s->base;
  186 + /* The timers should be disabled before changing the configuration.
  187 + We take advantage of this and defer everything until the timer
  188 + is enabled. */
  189 + switch (offset) {
  190 + case 0x00: /* CFG */
  191 + s->config = value;
  192 + break;
  193 + case 0x04: /* TAMR */
  194 + s->mode[0] = value;
  195 + break;
  196 + case 0x08: /* TBMR */
  197 + s->mode[1] = value;
  198 + break;
  199 + case 0x0c: /* CTL */
  200 + oldval = s->control;
  201 + s->control = value;
  202 + /* TODO: Implement pause. */
  203 + if ((oldval ^ value) & 1) {
  204 + if (value & 1) {
  205 + gptm_reload(s, 0, 1);
  206 + } else {
  207 + gptm_stop(s, 0);
  208 + }
  209 + }
  210 + if (((oldval ^ value) & 0x100) && s->config >= 4) {
  211 + if (value & 0x100) {
  212 + gptm_reload(s, 1, 1);
  213 + } else {
  214 + gptm_stop(s, 1);
  215 + }
  216 + }
  217 + break;
  218 + case 0x18: /* IMR */
  219 + s->mask = value & 0x77;
  220 + gptm_update_irq(s);
  221 + break;
  222 + case 0x24: /* CR */
  223 + s->state &= ~value;
  224 + break;
  225 + case 0x28: /* TAILR */
  226 + s->load[0] = value & 0xffff;
  227 + if (s->config < 4) {
  228 + s->load[1] = value >> 16;
  229 + }
  230 + break;
  231 + case 0x2c: /* TBILR */
  232 + s->load[1] = value & 0xffff;
  233 + break;
  234 + case 0x30: /* TAMARCHR */
  235 + s->match[0] = value & 0xffff;
  236 + if (s->config < 4) {
  237 + s->match[1] = value >> 16;
  238 + }
  239 + break;
  240 + case 0x34: /* TBMATCHR */
  241 + s->match[1] = value >> 16;
  242 + break;
  243 + case 0x38: /* TAPR */
  244 + s->prescale[0] = value;
  245 + break;
  246 + case 0x3c: /* TBPR */
  247 + s->prescale[1] = value;
  248 + break;
  249 + case 0x40: /* TAPMR */
  250 + s->match_prescale[0] = value;
  251 + break;
  252 + case 0x44: /* TBPMR */
  253 + s->match_prescale[0] = value;
  254 + break;
  255 + default:
  256 + cpu_abort(cpu_single_env, "gptm_write: Bad offset 0x%x\n", (int)offset);
  257 + }
  258 + gptm_update_irq(s);
  259 +}
  260 +
  261 +static CPUReadMemoryFunc *gptm_readfn[] = {
  262 + gptm_read,
  263 + gptm_read,
  264 + gptm_read
  265 +};
  266 +
  267 +static CPUWriteMemoryFunc *gptm_writefn[] = {
  268 + gptm_write,
  269 + gptm_write,
  270 + gptm_write
  271 +};
  272 +
  273 +static void stellaris_gptm_init(uint32_t base, qemu_irq irq, qemu_irq trigger)
  274 +{
  275 + int iomemtype;
  276 + gptm_state *s;
  277 +
  278 + s = (gptm_state *)qemu_mallocz(sizeof(gptm_state));
  279 + s->base = base;
  280 + s->irq = irq;
  281 + s->trigger = trigger;
  282 + s->opaque[0] = s->opaque[1] = s;
  283 +
  284 + iomemtype = cpu_register_io_memory(0, gptm_readfn,
  285 + gptm_writefn, s);
  286 + cpu_register_physical_memory(base, 0x00001000, iomemtype);
  287 + s->timer[0] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[0]);
  288 + s->timer[1] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[1]);
  289 + /* ??? Save/restore. */
  290 +}
  291 +
  292 +
  293 +/* System controller. */
  294 +
  295 +typedef struct {
  296 + uint32_t base;
  297 + uint32_t pborctl;
  298 + uint32_t ldopctl;
  299 + uint32_t int_status;
  300 + uint32_t int_mask;
  301 + uint32_t resc;
  302 + uint32_t rcc;
  303 + uint32_t rcgc[3];
  304 + uint32_t scgc[3];
  305 + uint32_t dcgc[3];
  306 + uint32_t clkvclr;
  307 + uint32_t ldoarst;
  308 + qemu_irq irq;
  309 + stellaris_board_info *board;
  310 +} ssys_state;
  311 +
  312 +static void ssys_update(ssys_state *s)
  313 +{
  314 + qemu_set_irq(s->irq, (s->int_status & s->int_mask) != 0);
  315 +}
  316 +
  317 +static uint32_t pllcfg_sandstorm[16] = {
  318 + 0x31c0, /* 1 Mhz */
  319 + 0x1ae0, /* 1.8432 Mhz */
  320 + 0x18c0, /* 2 Mhz */
  321 + 0xd573, /* 2.4576 Mhz */
  322 + 0x37a6, /* 3.57954 Mhz */
  323 + 0x1ae2, /* 3.6864 Mhz */
  324 + 0x0c40, /* 4 Mhz */
  325 + 0x98bc, /* 4.906 Mhz */
  326 + 0x935b, /* 4.9152 Mhz */
  327 + 0x09c0, /* 5 Mhz */
  328 + 0x4dee, /* 5.12 Mhz */
  329 + 0x0c41, /* 6 Mhz */
  330 + 0x75db, /* 6.144 Mhz */
  331 + 0x1ae6, /* 7.3728 Mhz */
  332 + 0x0600, /* 8 Mhz */
  333 + 0x585b /* 8.192 Mhz */
  334 +};
  335 +
  336 +static uint32_t pllcfg_fury[16] = {
  337 + 0x3200, /* 1 Mhz */
  338 + 0x1b20, /* 1.8432 Mhz */
  339 + 0x1900, /* 2 Mhz */
  340 + 0xf42b, /* 2.4576 Mhz */
  341 + 0x37e3, /* 3.57954 Mhz */
  342 + 0x1b21, /* 3.6864 Mhz */
  343 + 0x0c80, /* 4 Mhz */
  344 + 0x98ee, /* 4.906 Mhz */
  345 + 0xd5b4, /* 4.9152 Mhz */
  346 + 0x0a00, /* 5 Mhz */
  347 + 0x4e27, /* 5.12 Mhz */
  348 + 0x1902, /* 6 Mhz */
  349 + 0xec1c, /* 6.144 Mhz */
  350 + 0x1b23, /* 7.3728 Mhz */
  351 + 0x0640, /* 8 Mhz */
  352 + 0xb11c /* 8.192 Mhz */
  353 +};
  354 +
  355 +static uint32_t ssys_read(void *opaque, target_phys_addr_t offset)
  356 +{
  357 + ssys_state *s = (ssys_state *)opaque;
  358 +
  359 + offset -= s->base;
  360 + switch (offset) {
  361 + case 0x000: /* DID0 */
  362 + return s->board->did0;
  363 + case 0x004: /* DID1 */
  364 + return s->board->did1;
  365 + case 0x008: /* DC0 */
  366 + return s->board->dc0;
  367 + case 0x010: /* DC1 */
  368 + return s->board->dc1;
  369 + case 0x014: /* DC2 */
  370 + return s->board->dc2;
  371 + case 0x018: /* DC3 */
  372 + return s->board->dc3;
  373 + case 0x01c: /* DC4 */
  374 + return s->board->dc4;
  375 + case 0x030: /* PBORCTL */
  376 + return s->pborctl;
  377 + case 0x034: /* LDOPCTL */
  378 + return s->ldopctl;
  379 + case 0x040: /* SRCR0 */
  380 + return 0;
  381 + case 0x044: /* SRCR1 */
  382 + return 0;
  383 + case 0x048: /* SRCR2 */
  384 + return 0;
  385 + case 0x050: /* RIS */
  386 + return s->int_status;
  387 + case 0x054: /* IMC */
  388 + return s->int_mask;
  389 + case 0x058: /* MISC */
  390 + return s->int_status & s->int_mask;
  391 + case 0x05c: /* RESC */
  392 + return s->resc;
  393 + case 0x060: /* RCC */
  394 + return s->rcc;
  395 + case 0x064: /* PLLCFG */
  396 + {
  397 + int xtal;
  398 + xtal = (s->rcc >> 6) & 0xf;
  399 + if (s->board->did0 & (1 << 16)) {
  400 + return pllcfg_fury[xtal];
  401 + } else {
  402 + return pllcfg_sandstorm[xtal];
  403 + }
  404 + }
  405 + case 0x100: /* RCGC0 */
  406 + return s->rcgc[0];
  407 + case 0x104: /* RCGC1 */
  408 + return s->rcgc[1];
  409 + case 0x108: /* RCGC2 */
  410 + return s->rcgc[2];
  411 + case 0x110: /* SCGC0 */
  412 + return s->scgc[0];
  413 + case 0x114: /* SCGC1 */
  414 + return s->scgc[1];
  415 + case 0x118: /* SCGC2 */
  416 + return s->scgc[2];
  417 + case 0x120: /* DCGC0 */
  418 + return s->dcgc[0];
  419 + case 0x124: /* DCGC1 */
  420 + return s->dcgc[1];
  421 + case 0x128: /* DCGC2 */
  422 + return s->dcgc[2];
  423 + case 0x150: /* CLKVCLR */
  424 + return s->clkvclr;
  425 + case 0x160: /* LDOARST */
  426 + return s->ldoarst;
  427 + default:
  428 + cpu_abort(cpu_single_env, "gptm_read: Bad offset 0x%x\n", (int)offset);
  429 + return 0;
  430 + }
  431 +}
  432 +
  433 +static void ssys_write(void *opaque, target_phys_addr_t offset, uint32_t value)
  434 +{
  435 + ssys_state *s = (ssys_state *)opaque;
  436 +
  437 + offset -= s->base;
  438 + switch (offset) {
  439 + case 0x030: /* PBORCTL */
  440 + s->pborctl = value & 0xffff;
  441 + break;
  442 + case 0x034: /* LDOPCTL */
  443 + s->ldopctl = value & 0x1f;
  444 + break;
  445 + case 0x040: /* SRCR0 */
  446 + case 0x044: /* SRCR1 */
  447 + case 0x048: /* SRCR2 */
  448 + fprintf(stderr, "Peripheral reset not implemented\n");
  449 + break;
  450 + case 0x054: /* IMC */
  451 + s->int_mask = value & 0x7f;
  452 + break;
  453 + case 0x058: /* MISC */
  454 + s->int_status &= ~value;
  455 + break;
  456 + case 0x05c: /* RESC */
  457 + s->resc = value & 0x3f;
  458 + break;
  459 + case 0x060: /* RCC */
  460 + if ((s->rcc & (1 << 13)) != 0 && (value & (1 << 13)) == 0) {
  461 + /* PLL enable. */
  462 + s->int_status |= (1 << 6);
  463 + }
  464 + s->rcc = value;
  465 + stellaris_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1);
  466 + break;
  467 + case 0x100: /* RCGC0 */
  468 + s->rcgc[0] = value;
  469 + break;
  470 + case 0x104: /* RCGC1 */
  471 + s->rcgc[1] = value;
  472 + break;
  473 + case 0x108: /* RCGC2 */
  474 + s->rcgc[2] = value;
  475 + break;
  476 + case 0x110: /* SCGC0 */
  477 + s->scgc[0] = value;
  478 + break;
  479 + case 0x114: /* SCGC1 */
  480 + s->scgc[1] = value;
  481 + break;
  482 + case 0x118: /* SCGC2 */
  483 + s->scgc[2] = value;
  484 + break;
  485 + case 0x120: /* DCGC0 */
  486 + s->dcgc[0] = value;
  487 + break;
  488 + case 0x124: /* DCGC1 */
  489 + s->dcgc[1] = value;
  490 + break;
  491 + case 0x128: /* DCGC2 */
  492 + s->dcgc[2] = value;
  493 + break;
  494 + case 0x150: /* CLKVCLR */
  495 + s->clkvclr = value;
  496 + break;
  497 + case 0x160: /* LDOARST */
  498 + s->ldoarst = value;
  499 + break;
  500 + default:
  501 + cpu_abort(cpu_single_env, "gptm_write: Bad offset 0x%x\n", (int)offset);
  502 + }
  503 + ssys_update(s);
  504 +}
  505 +
  506 +static CPUReadMemoryFunc *ssys_readfn[] = {
  507 + ssys_read,
  508 + ssys_read,
  509 + ssys_read
  510 +};
  511 +
  512 +static CPUWriteMemoryFunc *ssys_writefn[] = {
  513 + ssys_write,
  514 + ssys_write,
  515 + ssys_write
  516 +};
  517 +
  518 +void ssys_reset(void *opaque)
  519 +{
  520 + ssys_state *s = (ssys_state *)opaque;
  521 +
  522 + s->pborctl = 0x7ffd;
  523 + s->rcc = 0x078e3ac0;
  524 + s->rcgc[0] = 1;
  525 + s->scgc[0] = 1;
  526 + s->dcgc[0] = 1;
  527 +}
  528 +
  529 +static void stellaris_sys_init(uint32_t base, qemu_irq irq,
  530 + stellaris_board_info * board)
  531 +{
  532 + int iomemtype;
  533 + ssys_state *s;
  534 +
  535 + s = (ssys_state *)qemu_mallocz(sizeof(ssys_state));
  536 + s->base = base;
  537 + s->irq = irq;
  538 + s->board = board;
  539 +
  540 + iomemtype = cpu_register_io_memory(0, ssys_readfn,
  541 + ssys_writefn, s);
  542 + cpu_register_physical_memory(base, 0x00001000, iomemtype);
  543 + ssys_reset(s);
  544 + /* ??? Save/restore. */
  545 +}
  546 +
  547 +
  548 +/* I2C controller. */
  549 +
  550 +typedef struct {
  551 + i2c_bus *bus;
  552 + qemu_irq irq;
  553 + uint32_t base;
  554 + uint32_t msa;
  555 + uint32_t mcs;
  556 + uint32_t mdr;
  557 + uint32_t mtpr;
  558 + uint32_t mimr;
  559 + uint32_t mris;
  560 + uint32_t mcr;
  561 +} stellaris_i2c_state;
  562 +
  563 +#define STELLARIS_I2C_MCS_BUSY 0x01
  564 +#define STELLARIS_I2C_MCS_ERROR 0x02
  565 +#define STELLARIS_I2C_MCS_ADRACK 0x04
  566 +#define STELLARIS_I2C_MCS_DATACK 0x08
  567 +#define STELLARIS_I2C_MCS_ARBLST 0x10
  568 +#define STELLARIS_I2C_MCS_IDLE 0x20
  569 +#define STELLARIS_I2C_MCS_BUSBSY 0x40
  570 +
  571 +static uint32_t stellaris_i2c_read(void *opaque, target_phys_addr_t offset)
  572 +{
  573 + stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
  574 +
  575 + offset -= s->base;
  576 + switch (offset) {
  577 + case 0x00: /* MSA */
  578 + return s->msa;
  579 + case 0x04: /* MCS */
  580 + /* We don't emulate timing, so the controller is never busy. */
  581 + return s->mcs | STELLARIS_I2C_MCS_IDLE;
  582 + case 0x08: /* MDR */
  583 + return s->mdr;
  584 + case 0x0c: /* MTPR */
  585 + return s->mtpr;
  586 + case 0x10: /* MIMR */
  587 + return s->mimr;
  588 + case 0x14: /* MRIS */
  589 + return s->mris;
  590 + case 0x18: /* MMIS */
  591 + return s->mris & s->mimr;
  592 + case 0x20: /* MCR */
  593 + return s->mcr;
  594 + default:
  595 + cpu_abort(cpu_single_env, "strllaris_i2c_read: Bad offset 0x%x\n",
  596 + (int)offset);
  597 + return 0;
  598 + }
  599 +}
  600 +
  601 +static void stellaris_i2c_update(stellaris_i2c_state *s)
  602 +{
  603 + int level;
  604 +
  605 + level = (s->mris & s->mimr) != 0;
  606 + qemu_set_irq(s->irq, level);
  607 +}
  608 +
  609 +static void stellaris_i2c_write(void *opaque, target_phys_addr_t offset,
  610 + uint32_t value)
  611 +{
  612 + stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
  613 +
  614 + offset -= s->base;
  615 + switch (offset) {
  616 + case 0x00: /* MSA */
  617 + s->msa = value & 0xff;
  618 + break;
  619 + case 0x04: /* MCS */
  620 + if ((s->mcr & 0x10) == 0) {
  621 + /* Disabled. Do nothing. */
  622 + break;
  623 + }
  624 + /* Grab the bus if this is starting a transfer. */
  625 + if ((value & 2) && (s->mcs & STELLARIS_I2C_MCS_BUSBSY) == 0) {
  626 + if (i2c_start_transfer(s->bus, s->msa >> 1, s->msa & 1)) {
  627 + s->mcs |= STELLARIS_I2C_MCS_ARBLST;
  628 + } else {
  629 + s->mcs &= ~STELLARIS_I2C_MCS_ARBLST;
  630 + s->mcs |= STELLARIS_I2C_MCS_BUSBSY;
  631 + }
  632 + }
  633 + /* If we don't have the bus then indicate an error. */
  634 + if (!i2c_bus_busy(s->bus)
  635 + || (s->mcs & STELLARIS_I2C_MCS_BUSBSY) == 0) {
  636 + s->mcs |= STELLARIS_I2C_MCS_ERROR;
  637 + break;
  638 + }
  639 + s->mcs &= ~STELLARIS_I2C_MCS_ERROR;
  640 + if (value & 1) {
  641 + /* Transfer a byte. */
  642 + /* TODO: Handle errors. */
  643 + if (s->msa & 1) {
  644 + /* Recv */
  645 + s->mdr = i2c_recv(s->bus) & 0xff;
  646 + } else {
  647 + /* Send */
  648 + i2c_send(s->bus, s->mdr);
  649 + }
  650 + /* Raise an interrupt. */
  651 + s->mris |= 1;
  652 + }
  653 + if (value & 4) {
  654 + /* Finish transfer. */
  655 + i2c_end_transfer(s->bus);
  656 + s->mcs &= ~STELLARIS_I2C_MCS_BUSBSY;
  657 + }
  658 + break;
  659 + case 0x08: /* MDR */
  660 + s->mdr = value & 0xff;
  661 + break;
  662 + case 0x0c: /* MTPR */
  663 + s->mtpr = value & 0xff;
  664 + break;
  665 + case 0x10: /* MIMR */
  666 + s->mimr = 1;
  667 + break;
  668 + case 0x1c: /* MICR */
  669 + s->mris &= ~value;
  670 + break;
  671 + case 0x20: /* MCR */
  672 + if (value & 1)
  673 + cpu_abort(cpu_single_env,
  674 + "stellaris_i2c_write: Loopback not implemented\n");
  675 + if (value & 0x20)
  676 + cpu_abort(cpu_single_env,
  677 + "stellaris_i2c_write: Slave mode not implemented\n");
  678 + s->mcr = value & 0x31;
  679 + break;
  680 + default:
  681 + cpu_abort(cpu_single_env, "stellaris_i2c_write: Bad offset 0x%x\n",
  682 + (int)offset);
  683 + }
  684 + stellaris_i2c_update(s);
  685 +}
  686 +
  687 +static void stellaris_i2c_reset(stellaris_i2c_state *s)
  688 +{
  689 + if (s->mcs & STELLARIS_I2C_MCS_BUSBSY)
  690 + i2c_end_transfer(s->bus);
  691 +
  692 + s->msa = 0;
  693 + s->mcs = 0;
  694 + s->mdr = 0;
  695 + s->mtpr = 1;
  696 + s->mimr = 0;
  697 + s->mris = 0;
  698 + s->mcr = 0;
  699 + stellaris_i2c_update(s);
  700 +}
  701 +
  702 +static CPUReadMemoryFunc *stellaris_i2c_readfn[] = {
  703 + stellaris_i2c_read,
  704 + stellaris_i2c_read,
  705 + stellaris_i2c_read
  706 +};
  707 +
  708 +static CPUWriteMemoryFunc *stellaris_i2c_writefn[] = {
  709 + stellaris_i2c_write,
  710 + stellaris_i2c_write,
  711 + stellaris_i2c_write
  712 +};
  713 +
  714 +static void stellaris_i2c_init(uint32_t base, qemu_irq irq, i2c_bus *bus)
  715 +{
  716 + stellaris_i2c_state *s;
  717 + int iomemtype;
  718 +
  719 + s = (stellaris_i2c_state *)qemu_mallocz(sizeof(stellaris_i2c_state));
  720 + s->base = base;
  721 + s->irq = irq;
  722 + s->bus = bus;
  723 +
  724 + iomemtype = cpu_register_io_memory(0, stellaris_i2c_readfn,
  725 + stellaris_i2c_writefn, s);
  726 + cpu_register_physical_memory(base, 0x00001000, iomemtype);
  727 + /* ??? For now we only implement the master interface. */
  728 + stellaris_i2c_reset(s);
  729 +}
  730 +
  731 +/* Analogue to Digital Converter. This is only partially implemented,
  732 + enough for applications that use a combined ADC and timer tick. */
  733 +
  734 +#define STELLARIS_ADC_EM_CONTROLLER 0
  735 +#define STELLARIS_ADC_EM_COMP 1
  736 +#define STELLARIS_ADC_EM_EXTERNAL 4
  737 +#define STELLARIS_ADC_EM_TIMER 5
  738 +#define STELLARIS_ADC_EM_PWM0 6
  739 +#define STELLARIS_ADC_EM_PWM1 7
  740 +#define STELLARIS_ADC_EM_PWM2 8
  741 +
  742 +#define STELLARIS_ADC_FIFO_EMPTY 0x0100
  743 +#define STELLARIS_ADC_FIFO_FULL 0x1000
  744 +
  745 +typedef struct
  746 +{
  747 + uint32_t base;
  748 + uint32_t actss;
  749 + uint32_t ris;
  750 + uint32_t im;
  751 + uint32_t emux;
  752 + uint32_t ostat;
  753 + uint32_t ustat;
  754 + uint32_t sspri;
  755 + uint32_t sac;
  756 + struct {
  757 + uint32_t state;
  758 + uint32_t data[16];
  759 + } fifo[4];
  760 + uint32_t ssmux[4];
  761 + uint32_t ssctl[4];
  762 + qemu_irq irq;
  763 +} stellaris_adc_state;
  764 +
  765 +static uint32_t stellaris_adc_fifo_read(stellaris_adc_state *s, int n)
  766 +{
  767 + int tail;
  768 +
  769 + tail = s->fifo[n].state & 0xf;
  770 + if (s->fifo[n].state & STELLARIS_ADC_FIFO_EMPTY) {
  771 + s->ustat |= 1 << n;
  772 + } else {
  773 + s->fifo[n].state = (s->fifo[n].state & ~0xf) | ((tail + 1) & 0xf);
  774 + s->fifo[n].state &= ~STELLARIS_ADC_FIFO_FULL;
  775 + if (tail + 1 == ((s->fifo[n].state >> 4) & 0xf))
  776 + s->fifo[n].state |= STELLARIS_ADC_FIFO_EMPTY;
  777 + }
  778 + return s->fifo[n].data[tail];
  779 +}
  780 +
  781 +static void stellaris_adc_fifo_write(stellaris_adc_state *s, int n,
  782 + uint32_t value)
  783 +{
  784 + int head;
  785 +
  786 + head = (s->fifo[n].state >> 4) & 0xf;
  787 + if (s->fifo[n].state & STELLARIS_ADC_FIFO_FULL) {
  788 + s->ostat |= 1 << n;
  789 + return;
  790 + }
  791 + s->fifo[n].data[head] = value;
  792 + head = (head + 1) & 0xf;
  793 + s->fifo[n].state &= ~STELLARIS_ADC_FIFO_EMPTY;
  794 + s->fifo[n].state = (s->fifo[n].state & ~0xf0) | (head << 4);
  795 + if ((s->fifo[n].state & 0xf) == head)
  796 + s->fifo[n].state |= STELLARIS_ADC_FIFO_FULL;
  797 +}
  798 +
  799 +static void stellaris_adc_update(stellaris_adc_state *s)
  800 +{
  801 + int level;
  802 +
  803 + level = (s->ris & s->im) != 0;
  804 + qemu_set_irq(s->irq, level);
  805 +}
  806 +
  807 +static void stellaris_adc_trigger(void *opaque, int irq, int level)
  808 +{
  809 + stellaris_adc_state *s = (stellaris_adc_state *)opaque;
  810 + /* Some applications use the ADC as a random number source, so introduce
  811 + some variation into the signal. */
  812 + static uint32_t noise = 0;
  813 +
  814 + if ((s->actss & 1) == 0) {
  815 + return;
  816 + }
  817 +
  818 + noise = noise * 314159 + 1;
  819 + /* ??? actual inputs not implemented. Return an arbitrary value. */
  820 + stellaris_adc_fifo_write(s, 0, 0x200 + ((noise >> 16) & 7));
  821 + s->ris |= 1;
  822 + stellaris_adc_update(s);
  823 +}
  824 +
  825 +static void stellaris_adc_reset(stellaris_adc_state *s)
  826 +{
  827 + int n;
  828 +
  829 + for (n = 0; n < 4; n++) {
  830 + s->ssmux[n] = 0;
  831 + s->ssctl[n] = 0;
  832 + s->fifo[n].state = STELLARIS_ADC_FIFO_EMPTY;
  833 + }
  834 +}
  835 +
  836 +static uint32_t stellaris_adc_read(void *opaque, target_phys_addr_t offset)
  837 +{
  838 + stellaris_adc_state *s = (stellaris_adc_state *)opaque;
  839 +
  840 + /* TODO: Implement this. */
  841 + offset -= s->base;
  842 + if (offset >= 0x40 && offset < 0xc0) {
  843 + int n;
  844 + n = (offset - 0x40) >> 5;
  845 + switch (offset & 0x1f) {
  846 + case 0x00: /* SSMUX */
  847 + return s->ssmux[n];
  848 + case 0x04: /* SSCTL */
  849 + return s->ssctl[n];
  850 + case 0x08: /* SSFIFO */
  851 + return stellaris_adc_fifo_read(s, n);
  852 + case 0x0c: /* SSFSTAT */
  853 + return s->fifo[n].state;
  854 + default:
  855 + break;
  856 + }
  857 + }
  858 + switch (offset) {
  859 + case 0x00: /* ACTSS */
  860 + return s->actss;
  861 + case 0x04: /* RIS */
  862 + return s->ris;
  863 + case 0x08: /* IM */
  864 + return s->im;
  865 + case 0x0c: /* ISC */
  866 + return s->ris & s->im;
  867 + case 0x10: /* OSTAT */
  868 + return s->ostat;
  869 + case 0x14: /* EMUX */
  870 + return s->emux;
  871 + case 0x18: /* USTAT */
  872 + return s->ustat;
  873 + case 0x20: /* SSPRI */
  874 + return s->sspri;
  875 + case 0x30: /* SAC */
  876 + return s->sac;
  877 + default:
  878 + cpu_abort(cpu_single_env, "strllaris_adc_read: Bad offset 0x%x\n",
  879 + (int)offset);
  880 + return 0;
  881 + }
  882 +}
  883 +
  884 +static void stellaris_adc_write(void *opaque, target_phys_addr_t offset,
  885 + uint32_t value)
  886 +{
  887 + stellaris_adc_state *s = (stellaris_adc_state *)opaque;
  888 +
  889 + /* TODO: Implement this. */
  890 + offset -= s->base;
  891 + if (offset >= 0x40 && offset < 0xc0) {
  892 + int n;
  893 + n = (offset - 0x40) >> 5;
  894 + switch (offset & 0x1f) {
  895 + case 0x00: /* SSMUX */
  896 + s->ssmux[n] = value & 0x33333333;
  897 + return;
  898 + case 0x04: /* SSCTL */
  899 + if (value != 6) {
  900 + cpu_abort(cpu_single_env, "ADC: Unimplemented sequence %x\n",
  901 + value);
  902 + }
  903 + s->ssctl[n] = value;
  904 + return;
  905 + default:
  906 + break;
  907 + }
  908 + }
  909 + switch (offset) {
  910 + case 0x00: /* ACTSS */
  911 + s->actss = value & 0xf;
  912 + if (value & 0xe) {
  913 + cpu_abort(cpu_single_env,
  914 + "Not implemented: ADC sequencers 1-3\n");
  915 + }
  916 + break;
  917 + case 0x08: /* IM */
  918 + s->im = value;
  919 + break;
  920 + case 0x0c: /* ISC */
  921 + s->ris &= ~value;
  922 + break;
  923 + case 0x10: /* OSTAT */
  924 + s->ostat &= ~value;
  925 + break;
  926 + case 0x14: /* EMUX */
  927 + s->emux = value;
  928 + break;
  929 + case 0x18: /* USTAT */
  930 + s->ustat &= ~value;
  931 + break;
  932 + case 0x20: /* SSPRI */
  933 + s->sspri = value;
  934 + break;
  935 + case 0x28: /* PSSI */
  936 + cpu_abort(cpu_single_env, "Not implemented: ADC sample initiate\n");
  937 + break;
  938 + case 0x30: /* SAC */
  939 + s->sac = value;
  940 + break;
  941 + default:
  942 + cpu_abort(cpu_single_env, "stellaris_adc_write: Bad offset 0x%x\n",
  943 + (int)offset);
  944 + }
  945 + stellaris_adc_update(s);
  946 +}
  947 +
  948 +static CPUReadMemoryFunc *stellaris_adc_readfn[] = {
  949 + stellaris_adc_read,
  950 + stellaris_adc_read,
  951 + stellaris_adc_read
  952 +};
  953 +
  954 +static CPUWriteMemoryFunc *stellaris_adc_writefn[] = {
  955 + stellaris_adc_write,
  956 + stellaris_adc_write,
  957 + stellaris_adc_write
  958 +};
  959 +
  960 +static qemu_irq stellaris_adc_init(uint32_t base, qemu_irq irq)
  961 +{
  962 + stellaris_adc_state *s;
  963 + int iomemtype;
  964 + qemu_irq *qi;
  965 +
  966 + s = (stellaris_adc_state *)qemu_mallocz(sizeof(stellaris_adc_state));
  967 + s->base = base;
  968 + s->irq = irq;
  969 +
  970 + iomemtype = cpu_register_io_memory(0, stellaris_adc_readfn,
  971 + stellaris_adc_writefn, s);
  972 + cpu_register_physical_memory(base, 0x00001000, iomemtype);
  973 + stellaris_adc_reset(s);
  974 + qi = qemu_allocate_irqs(stellaris_adc_trigger, s, 1);
  975 + return qi[0];
  976 +}
  977 +
  978 +/* Board init. */
  979 +static stellaris_board_info stellaris_boards[] = {
  980 + { "LM3S811EVB",
  981 + 0,
  982 + 0x0032000e,
  983 + 0x001f001f, /* dc0 */
  984 + 0x001132bf,
  985 + 0x01071013,
  986 + 0x3f0f01ff,
  987 + 0x0000001f,
  988 + OLED_I2C
  989 + },
  990 + { "LM3S6965EVB",
  991 + 0x10010002,
  992 + 0x1073402e,
  993 + 0x00ff007f, /* dc0 */
  994 + 0x001133ff,
  995 + 0x030f5317,
  996 + 0x0f0f87ff,
  997 + 0x5000007f,
  998 + OLED_SSI
  999 + }
  1000 +};
  1001 +
  1002 +static void stellaris_init(const char *kernel_filename, const char *cpu_model,
  1003 + DisplayState *ds, stellaris_board_info *board)
  1004 +{
  1005 + static const int uart_irq[] = {5, 6, 33, 34};
  1006 + static const int timer_irq[] = {19, 21, 23, 35};
  1007 + static const uint32_t gpio_addr[7] =
  1008 + { 0x40004000, 0x40005000, 0x40006000, 0x40007000,
  1009 + 0x40024000, 0x40025000, 0x40026000};
  1010 + static const int gpio_irq[7] = {0, 1, 2, 3, 4, 30, 31};
  1011 +
  1012 + qemu_irq *pic;
  1013 + qemu_irq *gpio_in[5];
  1014 + qemu_irq *gpio_out[5];
  1015 + qemu_irq adc;
  1016 + int sram_size;
  1017 + int flash_size;
  1018 + i2c_bus *i2c;
  1019 + int i;
  1020 +
  1021 + flash_size = ((board->dc0 & 0xffff) + 1) << 1;
  1022 + sram_size = (board->dc0 >> 18) + 1;
  1023 + pic = armv7m_init(flash_size, sram_size, kernel_filename, cpu_model);
  1024 +
  1025 + if (board->dc1 & (1 << 16)) {
  1026 + adc = stellaris_adc_init(0x40038000, pic[14]);
  1027 + } else {
  1028 + adc = NULL;
  1029 + }
  1030 + for (i = 0; i < 4; i++) {
  1031 + if (board->dc2 & (0x10000 << i)) {
  1032 + stellaris_gptm_init(0x40030000 + i * 0x1000,
  1033 + pic[timer_irq[i]], adc);
  1034 + }
  1035 + }
  1036 +
  1037 + stellaris_sys_init(0x400fe000, pic[28], board);
  1038 +
  1039 + for (i = 0; i < 7; i++) {
  1040 + if (board->dc4 & (1 << i)) {
  1041 + gpio_in[i] = pl061_init(gpio_addr[i], pic[gpio_irq[i]],
  1042 + &gpio_out[i]);
  1043 + }
  1044 + }
  1045 +
  1046 + if (board->dc2 & (1 << 12)) {
  1047 + i2c = i2c_init_bus();
  1048 + stellaris_i2c_init(0x40020000, pic[8], i2c);
  1049 + if (board->oled == OLED_I2C) {
  1050 + ssd0303_init(ds, i2c, 0x3d);
  1051 + }
  1052 + }
  1053 +
  1054 + for (i = 0; i < 4; i++) {
  1055 + if (board->dc2 & (1 << i)) {
  1056 + pl011_init(0x4000c000 + i * 0x1000, pic[uart_irq[i]],
  1057 + serial_hds[i], PL011_LUMINARY);
  1058 + }
  1059 + }
  1060 + if (board->dc2 & (1 << 4)) {
  1061 + if (board->oled == OLED_SSI) {
  1062 + void * oled;
  1063 + /* FIXME: Implement chip select for OLED/MMC. */
  1064 + oled = ssd0323_init(ds, &gpio_out[2][7]);
  1065 + pl022_init(0x40008000, pic[7], ssd0323_xfer_ssi, oled);
  1066 + } else {
  1067 + pl022_init(0x40008000, pic[7], NULL, NULL);
  1068 + }
  1069 + }
  1070 +}
  1071 +
  1072 +/* FIXME: Figure out how to generate these from stellaris_boards. */
  1073 +static void lm3s811evb_init(int ram_size, int vga_ram_size,
  1074 + const char *boot_device, DisplayState *ds,
  1075 + const char **fd_filename, int snapshot,
  1076 + const char *kernel_filename, const char *kernel_cmdline,
  1077 + const char *initrd_filename, const char *cpu_model)
  1078 +{
  1079 + stellaris_init(kernel_filename, cpu_model, ds, &stellaris_boards[0]);
  1080 +}
  1081 +
  1082 +static void lm3s6965evb_init(int ram_size, int vga_ram_size,
  1083 + const char *boot_device, DisplayState *ds,
  1084 + const char **fd_filename, int snapshot,
  1085 + const char *kernel_filename, const char *kernel_cmdline,
  1086 + const char *initrd_filename, const char *cpu_model)
  1087 +{
  1088 + stellaris_init(kernel_filename, cpu_model, ds, &stellaris_boards[1]);
  1089 +}
  1090 +
  1091 +QEMUMachine lm3s811evb_machine = {
  1092 + "lm3s811evb",
  1093 + "Stellaris LM3S811EVB",
  1094 + lm3s811evb_init,
  1095 +};
  1096 +
  1097 +QEMUMachine lm3s6965evb_machine = {
  1098 + "lm3s6965evb",
  1099 + "Stellaris LM3S6965EVB",
  1100 + lm3s6965evb_init,
  1101 +};
... ...
hw/versatilepb.c
... ... @@ -208,10 +208,10 @@ static void versatile_init(int ram_size, int vga_ram_size,
208 208 }
209 209 }
210 210  
211   - pl011_init(0x101f1000, pic[12], serial_hds[0]);
212   - pl011_init(0x101f2000, pic[13], serial_hds[1]);
213   - pl011_init(0x101f3000, pic[14], serial_hds[2]);
214   - pl011_init(0x10009000, sic[6], serial_hds[3]);
  211 + pl011_init(0x101f1000, pic[12], serial_hds[0], PL011_ARM);
  212 + pl011_init(0x101f2000, pic[13], serial_hds[1], PL011_ARM);
  213 + pl011_init(0x101f3000, pic[14], serial_hds[2], PL011_ARM);
  214 + pl011_init(0x10009000, sic[6], serial_hds[3], PL011_ARM);
215 215  
216 216 pl080_init(0x10130000, pic[17], 8);
217 217 sp804_init(0x101e2000, pic[4]);
... ...
qemu-doc.texi
... ... @@ -77,10 +77,12 @@ For system emulation, the following hardware targets are supported:
77 77 @item Sun4m (32-bit Sparc processor)
78 78 @item Sun4u (64-bit Sparc processor, in progress)
79 79 @item Malta board (32-bit MIPS processor)
80   -@item ARM Integrator/CP (ARM926E, 1026E or 946E processor)
81   -@item ARM Versatile baseboard (ARM926E)
82   -@item ARM RealView Emulation baseboard (ARM926EJ-S)
  80 +@item ARM Integrator/CP (ARM)
  81 +@item ARM Versatile baseboard (ARM)
  82 +@item ARM RealView Emulation baseboard (ARM)
83 83 @item Spitz, Akita, Borzoi and Terrier PDAs (PXA270 processor)
  84 +@item Luminary Micro LM3S811EVB (ARM Cortex-M3)
  85 +@item Luminary Micro LM3S6965EVB (ARM Cortex-M3)
84 86 @item Freescale MCF5208EVB (ColdFire V2).
85 87 @item Arnewsh MCF5206 evaluation board (ColdFire V2).
86 88 @item Palm Tungsten|E PDA (OMAP310 processor)
... ... @@ -2117,7 +2119,7 @@ devices:
2117 2119  
2118 2120 @itemize @minus
2119 2121 @item
2120   -ARM926E, ARM1026E or ARM946E CPU
  2122 +ARM926E, ARM1026E, ARM946E, ARM1136 or Cortex-A8 CPU
2121 2123 @item
2122 2124 Two PL011 UARTs
2123 2125 @item
... ... @@ -2134,7 +2136,7 @@ The ARM Versatile baseboard is emulated with the following devices:
2134 2136  
2135 2137 @itemize @minus
2136 2138 @item
2137   -ARM926E CPU
  2139 +ARM926E, ARM1136 or Cortex-A8 CPU
2138 2140 @item
2139 2141 PL190 Vectored Interrupt Controller
2140 2142 @item
... ... @@ -2163,7 +2165,7 @@ The ARM RealView Emulation baseboard is emulated with the following devices:
2163 2165  
2164 2166 @itemize @minus
2165 2167 @item
2166   -ARM926E CPU
  2168 +ARM926E, ARM1136, ARM11MPCORE(x4) or Cortex-A8 CPU
2167 2169 @item
2168 2170 ARM AMBA Generic/Distributed Interrupt Controller
2169 2171 @item
... ... @@ -2237,6 +2239,34 @@ Secure Digital card connected to OMAP MMC/SD host
2237 2239 Three on-chip UARTs
2238 2240 @end itemize
2239 2241  
  2242 +The Luminary Micro Stellaris LM3S811EVB emulation includes the following
  2243 +devices:
  2244 +
  2245 +@itemize @minus
  2246 +@item
  2247 +Cortex-M3 CPU core.
  2248 +@item
  2249 +64k Flash and 8k SRAM.
  2250 +@item
  2251 +Timers, UARTs, ADC and I@math{^2}C interface.
  2252 +@item
  2253 +OSRAM Pictiva 96x16 OLED with SSD0303 controller on I@math{^2}C bus.
  2254 +@end itemize
  2255 +
  2256 +The Luminary Micro Stellaris LM3S6965EVB emulation includes the following
  2257 +devices:
  2258 +
  2259 +@itemize @minus
  2260 +@item
  2261 +Cortex-M3 CPU core.
  2262 +@item
  2263 +256k Flash and 64k SRAM.
  2264 +@item
  2265 +Timers, UARTs, ADC, I@math{^2}C and SSI interfaces.
  2266 +@item
  2267 +OSRAM Pictiva 128x64 OLED with SSD0323 controller connected via SSI.
  2268 +@end itemize
  2269 +
2240 2270 A Linux 2.6 test image is available on the QEMU web site. More
2241 2271 information is available in the QEMU mailing-list archive.
2242 2272  
... ...
target-arm/cpu.h
... ... @@ -37,6 +37,18 @@
37 37 #define EXCP_IRQ 5
38 38 #define EXCP_FIQ 6
39 39 #define EXCP_BKPT 7
  40 +#define EXCP_EXCEPTION_EXIT 8 /* Return from v7M exception. */
  41 +
  42 +#define ARMV7M_EXCP_RESET 1
  43 +#define ARMV7M_EXCP_NMI 2
  44 +#define ARMV7M_EXCP_HARD 3
  45 +#define ARMV7M_EXCP_MEM 4
  46 +#define ARMV7M_EXCP_BUS 5
  47 +#define ARMV7M_EXCP_USAGE 6
  48 +#define ARMV7M_EXCP_SVC 11
  49 +#define ARMV7M_EXCP_DEBUG 12
  50 +#define ARMV7M_EXCP_PENDSV 14
  51 +#define ARMV7M_EXCP_SYSTICK 15
40 52  
41 53 typedef void ARMWriteCPFunc(void *opaque, int cp_info,
42 54 int srcreg, int operand, uint32_t value);
... ... @@ -76,17 +88,22 @@ typedef struct CPUARMState {
76 88 uint32_t VF; /* V is the bit 31. All other bits are undefined */
77 89 uint32_t NZF; /* N is bit 31. Z is computed from NZF */
78 90 uint32_t QF; /* 0 or 1 */
79   -
80   - int thumb; /* 0 = arm mode, 1 = thumb mode */
  91 + uint32_t GE; /* cpsr[19:16] */
  92 + int thumb; /* cprs[5]. 0 = arm mode, 1 = thumb mode. */
  93 + uint32_t condexec_bits; /* IT bits. cpsr[15:10,26:25]. */
81 94  
82 95 /* System control coprocessor (cp15) */
83 96 struct {
84 97 uint32_t c0_cpuid;
85 98 uint32_t c0_cachetype;
  99 + uint32_t c0_c1[8]; /* Feature registers. */
  100 + uint32_t c0_c2[8]; /* Instruction set registers. */
86 101 uint32_t c1_sys; /* System control register. */
87 102 uint32_t c1_coproc; /* Coprocessor access register. */
88 103 uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */
89   - uint32_t c2_base; /* MMU translation table base. */
  104 + uint32_t c2_base0; /* MMU translation table base 0. */
  105 + uint32_t c2_base1; /* MMU translation table base 1. */
  106 + uint32_t c2_mask; /* MMU translation table base mask. */
90 107 uint32_t c2_data; /* MPU data cachable bits. */
91 108 uint32_t c2_insn; /* MPU instruction cachable bits. */
92 109 uint32_t c3; /* MMU domain access control register
... ... @@ -100,6 +117,9 @@ typedef struct CPUARMState {
100 117 uint32_t c9_data;
101 118 uint32_t c13_fcse; /* FCSE PID. */
102 119 uint32_t c13_context; /* Context ID. */
  120 + uint32_t c13_tls1; /* User RW Thread register. */
  121 + uint32_t c13_tls2; /* User RO Thread register. */
  122 + uint32_t c13_tls3; /* Privileged Thread register. */
103 123 uint32_t c15_cpar; /* XScale Coprocessor Access Register */
104 124 uint32_t c15_ticonfig; /* TI925T configuration byte. */
105 125 uint32_t c15_i_max; /* Maximum D-cache dirty line index. */
... ... @@ -107,6 +127,17 @@ typedef struct CPUARMState {
107 127 uint32_t c15_threadid; /* TI debugger thread-ID. */
108 128 } cp15;
109 129  
  130 + struct {
  131 + uint32_t other_sp;
  132 + uint32_t vecbase;
  133 + uint32_t basepri;
  134 + uint32_t control;
  135 + int current_sp;
  136 + int exception;
  137 + int pending_exception;
  138 + void *nvic;
  139 + } v7m;
  140 +
110 141 /* Coprocessor IO used by peripherals */
111 142 struct {
112 143 ARMReadCPFunc *cp_read;
... ... @@ -117,6 +148,10 @@ typedef struct CPUARMState {
117 148 /* Internal CPU feature flags. */
118 149 uint32_t features;
119 150  
  151 + /* Callback for vectored interrupt controller. */
  152 + int (*get_irq_vector)(struct CPUARMState *);
  153 + void *irq_opaque;
  154 +
120 155 /* exception/interrupt handling */
121 156 jmp_buf jmp_env;
122 157 int exception_index;
... ... @@ -126,7 +161,7 @@ typedef struct CPUARMState {
126 161  
127 162 /* VFP coprocessor state. */
128 163 struct {
129   - float64 regs[16];
  164 + float64 regs[32];
130 165  
131 166 uint32_t xregs[16];
132 167 /* We store these fpcsr fields separately for convenience. */
... ... @@ -136,9 +171,16 @@ typedef struct CPUARMState {
136 171 /* Temporary variables if we don't have spare fp regs. */
137 172 float32 tmp0s, tmp1s;
138 173 float64 tmp0d, tmp1d;
  174 + /* scratch space when Tn are not sufficient. */
  175 + uint32_t scratch[8];
139 176  
140 177 float_status fp_status;
141 178 } vfp;
  179 +#if defined(CONFIG_USER_ONLY)
  180 + struct mmon_state *mmon_entry;
  181 +#else
  182 + uint32_t mmon_addr;
  183 +#endif
142 184  
143 185 /* iwMMXt coprocessor state. */
144 186 struct {
... ... @@ -169,6 +211,7 @@ int cpu_arm_exec(CPUARMState *s);
169 211 void cpu_arm_close(CPUARMState *s);
170 212 void do_interrupt(CPUARMState *);
171 213 void switch_mode(CPUARMState *, int);
  214 +uint32_t do_arm_semihosting(CPUARMState *env);
172 215  
173 216 /* you can call this signal handler from your SIGBUS and SIGSEGV
174 217 signal handlers to inform the virtual CPU of exceptions. non zero
... ... @@ -176,6 +219,9 @@ void switch_mode(CPUARMState *, int);
176 219 int cpu_arm_signal_handler(int host_signum, void *pinfo,
177 220 void *puc);
178 221  
  222 +void cpu_lock(void);
  223 +void cpu_unlock(void);
  224 +
179 225 #define CPSR_M (0x1f)
180 226 #define CPSR_T (1 << 5)
181 227 #define CPSR_F (1 << 6)
... ... @@ -183,13 +229,24 @@ int cpu_arm_signal_handler(int host_signum, void *pinfo,
183 229 #define CPSR_A (1 << 8)
184 230 #define CPSR_E (1 << 9)
185 231 #define CPSR_IT_2_7 (0xfc00)
186   -/* Bits 20-23 reserved. */
  232 +#define CPSR_GE (0xf << 16)
  233 +#define CPSR_RESERVED (0xf << 20)
187 234 #define CPSR_J (1 << 24)
188 235 #define CPSR_IT_0_1 (3 << 25)
189 236 #define CPSR_Q (1 << 27)
190   -#define CPSR_NZCV (0xf << 28)
  237 +#define CPSR_V (1 << 28)
  238 +#define CPSR_C (1 << 29)
  239 +#define CPSR_Z (1 << 30)
  240 +#define CPSR_N (1 << 31)
  241 +#define CPSR_NZCV (CPSR_N | CPSR_Z | CPSR_C | CPSR_V)
  242 +
  243 +#define CPSR_IT (CPSR_IT_0_1 | CPSR_IT_2_7)
  244 +#define CACHED_CPSR_BITS (CPSR_T | CPSR_GE | CPSR_IT | CPSR_Q | CPSR_NZCV)
  245 +/* Bits writable in user mode. */
  246 +#define CPSR_USER (CPSR_NZCV | CPSR_Q | CPSR_GE)
  247 +/* Execution state bits. MRS read as zero, MSR writes ignored. */
  248 +#define CPSR_EXEC (CPSR_T | CPSR_IT | CPSR_J)
191 249  
192   -#define CACHED_CPSR_BITS (CPSR_T | CPSR_Q | CPSR_NZCV)
193 250 /* Return the current CPSR value. */
194 251 static inline uint32_t cpsr_read(CPUARMState *env)
195 252 {
... ... @@ -197,7 +254,21 @@ static inline uint32_t cpsr_read(CPUARMState *env)
197 254 ZF = (env->NZF == 0);
198 255 return env->uncached_cpsr | (env->NZF & 0x80000000) | (ZF << 30) |
199 256 (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27)
200   - | (env->thumb << 5);
  257 + | (env->thumb << 5) | ((env->condexec_bits & 3) << 25)
  258 + | ((env->condexec_bits & 0xfc) << 8)
  259 + | (env->GE << 16);
  260 +}
  261 +
  262 +/* Return the current xPSR value. */
  263 +static inline uint32_t xpsr_read(CPUARMState *env)
  264 +{
  265 + int ZF;
  266 + ZF = (env->NZF == 0);
  267 + return (env->NZF & 0x80000000) | (ZF << 30)
  268 + | (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27)
  269 + | (env->thumb << 24) | ((env->condexec_bits & 3) << 25)
  270 + | ((env->condexec_bits & 0xfc) << 8)
  271 + | env->v7m.exception;
201 272 }
202 273  
203 274 /* Set the CPSR. Note that some bits of mask must be all-set or all-clear. */
... ... @@ -213,6 +284,17 @@ static inline void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
213 284 env->QF = ((val & CPSR_Q) != 0);
214 285 if (mask & CPSR_T)
215 286 env->thumb = ((val & CPSR_T) != 0);
  287 + if (mask & CPSR_IT_0_1) {
  288 + env->condexec_bits &= ~3;
  289 + env->condexec_bits |= (val >> 25) & 3;
  290 + }
  291 + if (mask & CPSR_IT_2_7) {
  292 + env->condexec_bits &= 3;
  293 + env->condexec_bits |= (val >> 8) & 0xfc;
  294 + }
  295 + if (mask & CPSR_GE) {
  296 + env->GE = (val >> 16) & 0xf;
  297 + }
216 298  
217 299 if ((env->uncached_cpsr ^ val) & mask & CPSR_M) {
218 300 switch_mode(env, val & CPSR_M);
... ... @@ -221,6 +303,32 @@ static inline void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
221 303 env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask);
222 304 }
223 305  
  306 +/* Set the xPSR. Note that some bits of mask must be all-set or all-clear. */
  307 +static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
  308 +{
  309 + /* NOTE: N = 1 and Z = 1 cannot be stored currently */
  310 + if (mask & CPSR_NZCV) {
  311 + env->NZF = (val & 0xc0000000) ^ 0x40000000;
  312 + env->CF = (val >> 29) & 1;
  313 + env->VF = (val << 3) & 0x80000000;
  314 + }
  315 + if (mask & CPSR_Q)
  316 + env->QF = ((val & CPSR_Q) != 0);
  317 + if (mask & (1 << 24))
  318 + env->thumb = ((val & (1 << 24)) != 0);
  319 + if (mask & CPSR_IT_0_1) {
  320 + env->condexec_bits &= ~3;
  321 + env->condexec_bits |= (val >> 25) & 3;
  322 + }
  323 + if (mask & CPSR_IT_2_7) {
  324 + env->condexec_bits &= 3;
  325 + env->condexec_bits |= (val >> 8) & 0xfc;
  326 + }
  327 + if (mask & 0x1ff) {
  328 + env->v7m.exception = val & 0x1ff;
  329 + }
  330 +}
  331 +
224 332 enum arm_cpu_mode {
225 333 ARM_CPU_MODE_USR = 0x10,
226 334 ARM_CPU_MODE_FIQ = 0x11,
... ... @@ -234,6 +342,8 @@ enum arm_cpu_mode {
234 342 /* VFP system registers. */
235 343 #define ARM_VFP_FPSID 0
236 344 #define ARM_VFP_FPSCR 1
  345 +#define ARM_VFP_MVFR1 6
  346 +#define ARM_VFP_MVFR0 7
237 347 #define ARM_VFP_FPEXC 8
238 348 #define ARM_VFP_FPINST 9
239 349 #define ARM_VFP_FPINST2 10
... ... @@ -253,7 +363,15 @@ enum arm_features {
253 363 ARM_FEATURE_AUXCR, /* ARM1026 Auxiliary control register. */
254 364 ARM_FEATURE_XSCALE, /* Intel XScale extensions. */
255 365 ARM_FEATURE_IWMMXT, /* Intel iwMMXt extension. */
  366 + ARM_FEATURE_V6,
  367 + ARM_FEATURE_V6K,
  368 + ARM_FEATURE_V7,
  369 + ARM_FEATURE_THUMB2,
256 370 ARM_FEATURE_MPU, /* Only has Memory Protection Unit, not full MMU. */
  371 + ARM_FEATURE_VFP3,
  372 + ARM_FEATURE_NEON,
  373 + ARM_FEATURE_DIV,
  374 + ARM_FEATURE_M, /* Microcontroller profile. */
257 375 ARM_FEATURE_OMAPCP /* OMAP specific CP15 ops handling. */
258 376 };
259 377  
... ... @@ -264,27 +382,44 @@ static inline int arm_feature(CPUARMState *env, int feature)
264 382  
265 383 void arm_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
266 384  
  385 +/* Interface between CPU and Interrupt controller. */
  386 +void armv7m_nvic_set_pending(void *opaque, int irq);
  387 +int armv7m_nvic_acknowledge_irq(void *opaque);
  388 +void armv7m_nvic_complete_irq(void *opaque, int irq);
  389 +
267 390 void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
268 391 ARMReadCPFunc *cp_read, ARMWriteCPFunc *cp_write,
269 392 void *opaque);
270 393  
271   -#define ARM_CPUID_ARM1026 0x4106a262
272   -#define ARM_CPUID_ARM926 0x41069265
273   -#define ARM_CPUID_ARM946 0x41059461
274   -#define ARM_CPUID_TI915T 0x54029152
275   -#define ARM_CPUID_TI925T 0x54029252
276   -#define ARM_CPUID_PXA250 0x69052100
277   -#define ARM_CPUID_PXA255 0x69052d00
278   -#define ARM_CPUID_PXA260 0x69052903
279   -#define ARM_CPUID_PXA261 0x69052d05
280   -#define ARM_CPUID_PXA262 0x69052d06
281   -#define ARM_CPUID_PXA270 0x69054110
282   -#define ARM_CPUID_PXA270_A0 0x69054110
283   -#define ARM_CPUID_PXA270_A1 0x69054111
284   -#define ARM_CPUID_PXA270_B0 0x69054112
285   -#define ARM_CPUID_PXA270_B1 0x69054113
286   -#define ARM_CPUID_PXA270_C0 0x69054114
287   -#define ARM_CPUID_PXA270_C5 0x69054117
  394 +/* Does the core conform to the the "MicroController" profile. e.g. Cortex-M3.
  395 + Note the M in older cores (eg. ARM7TDMI) stands for Multiply. These are
  396 + conventional cores (ie. Application or Realtime profile). */
  397 +
  398 +#define IS_M(env) arm_feature(env, ARM_FEATURE_M)
  399 +#define ARM_CPUID(env) (env->cp15.c0_cpuid)
  400 +
  401 +#define ARM_CPUID_ARM1026 0x4106a262
  402 +#define ARM_CPUID_ARM926 0x41069265
  403 +#define ARM_CPUID_ARM946 0x41059461
  404 +#define ARM_CPUID_TI915T 0x54029152
  405 +#define ARM_CPUID_TI925T 0x54029252
  406 +#define ARM_CPUID_PXA250 0x69052100
  407 +#define ARM_CPUID_PXA255 0x69052d00
  408 +#define ARM_CPUID_PXA260 0x69052903
  409 +#define ARM_CPUID_PXA261 0x69052d05
  410 +#define ARM_CPUID_PXA262 0x69052d06
  411 +#define ARM_CPUID_PXA270 0x69054110
  412 +#define ARM_CPUID_PXA270_A0 0x69054110
  413 +#define ARM_CPUID_PXA270_A1 0x69054111
  414 +#define ARM_CPUID_PXA270_B0 0x69054112
  415 +#define ARM_CPUID_PXA270_B1 0x69054113
  416 +#define ARM_CPUID_PXA270_C0 0x69054114
  417 +#define ARM_CPUID_PXA270_C5 0x69054117
  418 +#define ARM_CPUID_ARM1136 0x4117b363
  419 +#define ARM_CPUID_ARM11MPCORE 0x410fb022
  420 +#define ARM_CPUID_CORTEXA8 0x410fc080
  421 +#define ARM_CPUID_CORTEXM3 0x410fc231
  422 +#define ARM_CPUID_ANY 0xffffffff
288 423  
289 424 #if defined(CONFIG_USER_ONLY)
290 425 #define TARGET_PAGE_BITS 12
... ... @@ -302,6 +437,8 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
302 437 #define cpu_signal_handler cpu_arm_signal_handler
303 438 #define cpu_list arm_cpu_list
304 439  
  440 +#define ARM_CPU_SAVE_VERSION 1
  441 +
305 442 /* MMU modes definitions */
306 443 #define MMU_MODE0_SUFFIX _kernel
307 444 #define MMU_MODE1_SUFFIX _user
... ...
target-arm/exec.h
... ... @@ -68,12 +68,18 @@ static inline int cpu_halted(CPUState *env) {
68 68  
69 69 /* In op_helper.c */
70 70  
71   -void cpu_lock(void);
72   -void cpu_unlock(void);
73 71 void helper_set_cp(CPUState *, uint32_t, uint32_t);
74 72 uint32_t helper_get_cp(CPUState *, uint32_t);
75 73 void helper_set_cp15(CPUState *, uint32_t, uint32_t);
76 74 uint32_t helper_get_cp15(CPUState *, uint32_t);
  75 +void helper_set_r13_banked(CPUState *env, int mode, uint32_t val);
  76 +uint32_t helper_get_r13_banked(CPUState *env, int mode);
  77 +uint32_t helper_v7m_mrs(CPUState *env, int reg);
  78 +void helper_v7m_msr(CPUState *env, int reg, uint32_t val);
  79 +
  80 +void helper_mark_exclusive(CPUARMState *, uint32_t addr);
  81 +int helper_test_exclusive(CPUARMState *, uint32_t addr);
  82 +void helper_clrex(CPUARMState *env);
77 83  
78 84 void cpu_loop_exit(void);
79 85  
... ... @@ -91,4 +97,11 @@ void do_vfp_cmpes(void);
91 97 void do_vfp_cmped(void);
92 98 void do_vfp_set_fpscr(void);
93 99 void do_vfp_get_fpscr(void);
94   -
  100 +float32 helper_recps_f32(float32, float32);
  101 +float32 helper_rsqrts_f32(float32, float32);
  102 +uint32_t helper_recpe_u32(uint32_t);
  103 +uint32_t helper_rsqrte_u32(uint32_t);
  104 +float32 helper_recpe_f32(float32);
  105 +float32 helper_rsqrte_f32(float32);
  106 +void helper_neon_tbl(int rn, int maxindex);
  107 +uint32_t helper_neon_mul_p8(uint32_t op1, uint32_t op2);
... ...