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,6 +17,7 @@
17 - MIPS mipssim pequdo machine (Thiemo Seufer) 17 - MIPS mipssim pequdo machine (Thiemo Seufer)
18 - Strace for Linux userland emulation (Stuart Anderson, Thayne Harbaugh) 18 - Strace for Linux userland emulation (Stuart Anderson, Thayne Harbaugh)
19 - OMAP310 MPU emulation plus Palm T|E machine (Andrzej Zaborowski) 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 version 0.9.0: 22 version 0.9.0:
22 23
Makefile.target
@@ -493,7 +493,9 @@ ifeq ($(TARGET_BASE_ARCH), arm) @@ -493,7 +493,9 @@ ifeq ($(TARGET_BASE_ARCH), arm)
493 VL_OBJS+= integratorcp.o versatilepb.o ps2.o smc91c111.o arm_pic.o arm_timer.o 493 VL_OBJS+= integratorcp.o versatilepb.o ps2.o smc91c111.o arm_pic.o arm_timer.o
494 VL_OBJS+= arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o 494 VL_OBJS+= arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
495 VL_OBJS+= versatile_pci.o sd.o ptimer.o 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 VL_OBJS+= arm-semi.o 499 VL_OBJS+= arm-semi.o
498 VL_OBJS+= pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o 500 VL_OBJS+= pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
499 VL_OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o max111x.o max7310.o 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,6 +173,7 @@ static inline TranslationBlock *tb_find_fast(void)
173 flags |= (1 << 6); 173 flags |= (1 << 6);
174 if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) 174 if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
175 flags |= (1 << 7); 175 flags |= (1 << 7);
  176 + flags |= (env->condexec_bits << 8);
176 cs_base = 0; 177 cs_base = 0;
177 pc = env->regs[15]; 178 pc = env->regs[15];
178 #elif defined(TARGET_SPARC) 179 #elif defined(TARGET_SPARC)
@@ -511,8 +512,18 @@ int cpu_exec(CPUState *env1) @@ -511,8 +512,18 @@ int cpu_exec(CPUState *env1)
511 env->exception_index = EXCP_FIQ; 512 env->exception_index = EXCP_FIQ;
512 do_interrupt(env); 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 if (interrupt_request & CPU_INTERRUPT_HARD 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 env->exception_index = EXCP_IRQ; 527 env->exception_index = EXCP_IRQ;
517 do_interrupt(env); 528 do_interrupt(env);
518 } 529 }
fpu/softfloat-native.h
@@ -224,6 +224,11 @@ INLINE float32 float32_chs(float32 a) @@ -224,6 +224,11 @@ INLINE float32 float32_chs(float32 a)
224 return -a; 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 | Software IEC/IEEE double-precision conversion routines. 233 | Software IEC/IEEE double-precision conversion routines.
229 *----------------------------------------------------------------------------*/ 234 *----------------------------------------------------------------------------*/
@@ -311,6 +316,11 @@ INLINE float64 float64_chs(float64 a) @@ -311,6 +316,11 @@ INLINE float64 float64_chs(float64 a)
311 return -a; 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 #ifdef FLOATX80 324 #ifdef FLOATX80
315 325
316 /*---------------------------------------------------------------------------- 326 /*----------------------------------------------------------------------------
@@ -391,4 +401,10 @@ INLINE floatx80 floatx80_chs(floatx80 a) @@ -391,4 +401,10 @@ INLINE floatx80 floatx80_chs(floatx80 a)
391 { 401 {
392 return -a; 402 return -a;
393 } 403 }
  404 +
  405 +INLINE floatx80 floatx80_scalbn(floatx80 a, int n)
  406 +{
  407 + return scalbnl(a, n);
  408 +}
  409 +
394 #endif 410 #endif
fpu/softfloat.c
@@ -5377,3 +5377,78 @@ int float ## s ## _compare_quiet( float ## s a, float ## s b STATUS_PARAM ) \ @@ -5377,3 +5377,78 @@ int float ## s ## _compare_quiet( float ## s a, float ## s b STATUS_PARAM ) \
5377 5377
5378 COMPARE(32, 0xff) 5378 COMPARE(32, 0xff)
5379 COMPARE(64, 0x7ff) 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,6 +244,7 @@ int float32_compare( float32, float32 STATUS_PARAM );
244 int float32_compare_quiet( float32, float32 STATUS_PARAM ); 244 int float32_compare_quiet( float32, float32 STATUS_PARAM );
245 int float32_is_nan( float32 ); 245 int float32_is_nan( float32 );
246 int float32_is_signaling_nan( float32 ); 246 int float32_is_signaling_nan( float32 );
  247 +float32 float32_scalbn( float32, int STATUS_PARAM );
247 248
248 INLINE float32 float32_abs(float32 a) 249 INLINE float32 float32_abs(float32 a)
249 { 250 {
@@ -295,6 +296,7 @@ int float64_compare( float64, float64 STATUS_PARAM ); @@ -295,6 +296,7 @@ int float64_compare( float64, float64 STATUS_PARAM );
295 int float64_compare_quiet( float64, float64 STATUS_PARAM ); 296 int float64_compare_quiet( float64, float64 STATUS_PARAM );
296 int float64_is_nan( float64 a ); 297 int float64_is_nan( float64 a );
297 int float64_is_signaling_nan( float64 ); 298 int float64_is_signaling_nan( float64 );
  299 +float64 float64_scalbn( float64, int STATUS_PARAM );
298 300
299 INLINE float64 float64_abs(float64 a) 301 INLINE float64 float64_abs(float64 a)
300 { 302 {
@@ -339,6 +341,7 @@ int floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM ); @@ -339,6 +341,7 @@ int floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM );
339 int floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM ); 341 int floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM );
340 int floatx80_is_nan( floatx80 ); 342 int floatx80_is_nan( floatx80 );
341 int floatx80_is_signaling_nan( floatx80 ); 343 int floatx80_is_signaling_nan( floatx80 );
  344 +floatx80 floatx80_scalbn( floatx80, int STATUS_PARAM );
342 345
343 INLINE floatx80 floatx80_abs(floatx80 a) 346 INLINE floatx80 floatx80_abs(floatx80 a)
344 { 347 {
@@ -387,6 +390,7 @@ int float128_le_quiet( float128, float128 STATUS_PARAM ); @@ -387,6 +390,7 @@ int float128_le_quiet( float128, float128 STATUS_PARAM );
387 int float128_lt_quiet( float128, float128 STATUS_PARAM ); 390 int float128_lt_quiet( float128, float128 STATUS_PARAM );
388 int float128_is_nan( float128 ); 391 int float128_is_nan( float128 );
389 int float128_is_signaling_nan( float128 ); 392 int float128_is_signaling_nan( float128 );
  393 +float128 float128_scalbn( float128, int STATUS_PARAM );
390 394
391 INLINE float128 float128_abs(float128 a) 395 INLINE float128 float128_abs(float128 a)
392 { 396 {
hw/arm_boot.c
1 /* 1 /*
2 * ARM kernel loader. 2 * ARM kernel loader.
3 * 3 *
4 - * Copyright (c) 2006 CodeSourcery. 4 + * Copyright (c) 2006-2007 CodeSourcery.
5 * Written by Paul Brook 5 * Written by Paul Brook
6 * 6 *
7 * This code is licenced under the GPL. 7 * This code is licenced under the GPL.
@@ -24,6 +24,22 @@ static uint32_t bootloader[] = { @@ -24,6 +24,22 @@ static uint32_t bootloader[] = {
24 0 /* Kernel entry point. Set by integratorcp_init. */ 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 static void main_cpu_reset(void *opaque) 43 static void main_cpu_reset(void *opaque)
28 { 44 {
29 CPUState *env = opaque; 45 CPUState *env = opaque;
@@ -33,6 +49,8 @@ static void main_cpu_reset(void *opaque) @@ -33,6 +49,8 @@ static void main_cpu_reset(void *opaque)
33 arm_load_kernel(env, env->ram_size, env->kernel_filename, 49 arm_load_kernel(env, env->ram_size, env->kernel_filename,
34 env->kernel_cmdline, env->initrd_filename, 50 env->kernel_cmdline, env->initrd_filename,
35 env->board_id, env->loader_start); 51 env->board_id, env->loader_start);
  52 +
  53 + /* TODO: Reset secondary CPUs. */
36 } 54 }
37 55
38 static void set_kernel_args(uint32_t ram_size, int initrd_size, 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,6 +229,8 @@ void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename,
211 bootloader[6] = entry; 229 bootloader[6] = entry;
212 for (n = 0; n < sizeof(bootloader) / 4; n++) 230 for (n = 0; n < sizeof(bootloader) / 4; n++)
213 stl_raw(phys_ram_base + (n * 4), bootloader[n]); 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 if (old_param) 234 if (old_param)
215 set_kernel_args_old(ram_size, initrd_size, 235 set_kernel_args_old(ram_size, initrd_size,
216 kernel_cmdline, loader_start); 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 * Written by Paul Brook 5 * Written by Paul Brook
6 * 6 *
7 * This code is licenced under the GPL. 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 //#define DEBUG_GIC 14 //#define DEBUG_GIC
17 15
@@ -22,58 +20,84 @@ do { printf(&quot;arm_gic: &quot; fmt , ##args); } while (0) @@ -22,58 +20,84 @@ do { printf(&quot;arm_gic: &quot; fmt , ##args); } while (0)
22 #define DPRINTF(fmt, args...) do {} while(0) 20 #define DPRINTF(fmt, args...) do {} while(0)
23 #endif 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 static const uint8_t gic_id[] = 31 static const uint8_t gic_id[] =
28 { 0x90, 0x13, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 }; 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 typedef struct gic_irq_state 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 unsigned enabled:1; 41 unsigned enabled:1;
35 - unsigned pending:1;  
36 - unsigned active:1; 42 + unsigned pending:NCPU;
  43 + unsigned active:NCPU;
37 unsigned level:1; 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 unsigned trigger:1; /* nonzero = edge triggered. */ 46 unsigned trigger:1; /* nonzero = edge triggered. */
40 } gic_irq_state; 47 } gic_irq_state;
41 48
  49 +#define ALL_CPU_MASK ((1 << NCPU) - 1)
  50 +
42 #define GIC_SET_ENABLED(irq) s->irq_state[irq].enabled = 1 51 #define GIC_SET_ENABLED(irq) s->irq_state[irq].enabled = 1
43 #define GIC_CLEAR_ENABLED(irq) s->irq_state[irq].enabled = 0 52 #define GIC_CLEAR_ENABLED(irq) s->irq_state[irq].enabled = 0
44 #define GIC_TEST_ENABLED(irq) s->irq_state[irq].enabled 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 #define GIC_SET_MODEL(irq) s->irq_state[irq].model = 1 60 #define GIC_SET_MODEL(irq) s->irq_state[irq].model = 1
52 #define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = 0 61 #define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = 0
53 #define GIC_TEST_MODEL(irq) s->irq_state[irq].model 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 #define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = 1 66 #define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = 1
58 #define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0 67 #define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0
59 #define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger 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 typedef struct gic_state 77 typedef struct gic_state
62 { 78 {
63 uint32_t base; 79 uint32_t base;
64 - qemu_irq parent_irq; 80 + qemu_irq parent_irq[NCPU];
65 int enabled; 81 int enabled;
66 - int cpu_enabled; 82 + int cpu_enabled[NCPU];
67 83
68 gic_irq_state irq_state[GIC_NIRQ]; 84 gic_irq_state irq_state[GIC_NIRQ];
  85 +#ifndef NVIC
69 int irq_target[GIC_NIRQ]; 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 } gic_state; 101 } gic_state;
78 102
79 /* TODO: Many places that call this routine could be optimized. */ 103 /* TODO: Many places that call this routine could be optimized. */
@@ -83,112 +107,136 @@ static void gic_update(gic_state *s) @@ -83,112 +107,136 @@ static void gic_update(gic_state *s)
83 int best_irq; 107 int best_irq;
84 int best_prio; 108 int best_prio;
85 int irq; 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 static void gic_set_irq(void *opaque, int irq, int level) 157 static void gic_set_irq(void *opaque, int irq, int level)
114 { 158 {
115 gic_state *s = (gic_state *)opaque; 159 gic_state *s = (gic_state *)opaque;
116 /* The first external input line is internal interrupt 32. */ 160 /* The first external input line is internal interrupt 32. */
117 irq += 32; 161 irq += 32;
118 - if (level == GIC_TEST_LEVEL(irq)) 162 + if (level == GIC_TEST_LEVEL(irq, ALL_CPU_MASK))
119 return; 163 return;
120 164
121 if (level) { 165 if (level) {
122 - GIC_SET_LEVEL(irq); 166 + GIC_SET_LEVEL(irq, ALL_CPU_MASK);
123 if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq)) { 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 } else { 171 } else {
128 - GIC_CLEAR_LEVEL(irq); 172 + GIC_CLEAR_LEVEL(irq, ALL_CPU_MASK);
129 } 173 }
130 gic_update(s); 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 gic_update(s); 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 int new_irq; 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 DPRINTF("ACK no pending IRQ\n"); 195 DPRINTF("ACK no pending IRQ\n");
149 return 1023; 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 DPRINTF("ACK %d\n", new_irq); 203 DPRINTF("ACK %d\n", new_irq);
158 return new_irq; 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 int update = 0; 209 int update = 0;
  210 + int cm = 1 << cpu;
164 DPRINTF("EOI %d\n", irq); 211 DPRINTF("EOI %d\n", irq);
165 - if (s->running_irq == 1023) 212 + if (s->running_irq[cpu] == 1023)
166 return; /* No active IRQ. */ 213 return; /* No active IRQ. */
167 if (irq != 1023) { 214 if (irq != 1023) {
168 /* Mark level triggered interrupts as pending if they are still 215 /* Mark level triggered interrupts as pending if they are still
169 raised. */ 216 raised. */
170 if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq) 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 update = 1; 221 update = 1;
174 } 222 }
175 } 223 }
176 - if (irq != s->running_irq) { 224 + if (irq != s->running_irq[cpu]) {
177 /* Complete an IRQ that is not currently running. */ 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 break; 230 break;
183 } 231 }
184 - tmp = s->last_active[tmp]; 232 + tmp = s->last_active[tmp][cpu];
185 } 233 }
186 if (update) { 234 if (update) {
187 gic_update(s); 235 gic_update(s);
188 } 236 }
189 } else { 237 } else {
190 /* Complete the current running IRQ. */ 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,15 +246,22 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
198 uint32_t res; 246 uint32_t res;
199 int irq; 247 int irq;
200 int i; 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 if (offset < 0x100) { 256 if (offset < 0x100) {
  257 +#ifndef NVIC
204 if (offset == 0) 258 if (offset == 0)
205 return s->enabled; 259 return s->enabled;
206 if (offset == 4) 260 if (offset == 4)
207 - return (GIC_NIRQ / 32) - 1; 261 + return ((GIC_NIRQ / 32) - 1) | ((NCPU - 1) << 5);
208 if (offset < 0x08) 262 if (offset < 0x08)
209 return 0; 263 return 0;
  264 +#endif
210 goto bad_reg; 265 goto bad_reg;
211 } else if (offset < 0x200) { 266 } else if (offset < 0x200) {
212 /* Interrupt Set/Clear Enable. */ 267 /* Interrupt Set/Clear Enable. */
@@ -214,6 +269,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset) @@ -214,6 +269,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
214 irq = (offset - 0x100) * 8; 269 irq = (offset - 0x100) * 8;
215 else 270 else
216 irq = (offset - 0x180) * 8; 271 irq = (offset - 0x180) * 8;
  272 + irq += GIC_BASE_IRQ;
217 if (irq >= GIC_NIRQ) 273 if (irq >= GIC_NIRQ)
218 goto bad_reg; 274 goto bad_reg;
219 res = 0; 275 res = 0;
@@ -228,40 +284,48 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset) @@ -228,40 +284,48 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
228 irq = (offset - 0x200) * 8; 284 irq = (offset - 0x200) * 8;
229 else 285 else
230 irq = (offset - 0x280) * 8; 286 irq = (offset - 0x280) * 8;
  287 + irq += GIC_BASE_IRQ;
231 if (irq >= GIC_NIRQ) 288 if (irq >= GIC_NIRQ)
232 goto bad_reg; 289 goto bad_reg;
233 res = 0; 290 res = 0;
  291 + mask = (irq < 32) ? cm : ALL_CPU_MASK;
234 for (i = 0; i < 8; i++) { 292 for (i = 0; i < 8; i++) {
235 - if (GIC_TEST_PENDING(irq + i)) { 293 + if (GIC_TEST_PENDING(irq + i, mask)) {
236 res |= (1 << i); 294 res |= (1 << i);
237 } 295 }
238 } 296 }
239 } else if (offset < 0x400) { 297 } else if (offset < 0x400) {
240 /* Interrupt Active. */ 298 /* Interrupt Active. */
241 - irq = (offset - 0x300) * 8; 299 + irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
242 if (irq >= GIC_NIRQ) 300 if (irq >= GIC_NIRQ)
243 goto bad_reg; 301 goto bad_reg;
244 res = 0; 302 res = 0;
  303 + mask = (irq < 32) ? cm : ALL_CPU_MASK;
245 for (i = 0; i < 8; i++) { 304 for (i = 0; i < 8; i++) {
246 - if (GIC_TEST_ACTIVE(irq + i)) { 305 + if (GIC_TEST_ACTIVE(irq + i, mask)) {
247 res |= (1 << i); 306 res |= (1 << i);
248 } 307 }
249 } 308 }
250 } else if (offset < 0x800) { 309 } else if (offset < 0x800) {
251 /* Interrupt Priority. */ 310 /* Interrupt Priority. */
252 - irq = offset - 0x400; 311 + irq = (offset - 0x400) + GIC_BASE_IRQ;
253 if (irq >= GIC_NIRQ) 312 if (irq >= GIC_NIRQ)
254 goto bad_reg; 313 goto bad_reg;
255 - res = s->priority[irq]; 314 + res = GIC_GET_PRIORITY(irq, cpu);
  315 +#ifndef NVIC
256 } else if (offset < 0xc00) { 316 } else if (offset < 0xc00) {
257 /* Interrupt CPU Target. */ 317 /* Interrupt CPU Target. */
258 - irq = offset - 0x800; 318 + irq = (offset - 0x800) + GIC_BASE_IRQ;
259 if (irq >= GIC_NIRQ) 319 if (irq >= GIC_NIRQ)
260 goto bad_reg; 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 } else if (offset < 0xf00) { 326 } else if (offset < 0xf00) {
263 /* Interrupt Configuration. */ 327 /* Interrupt Configuration. */
264 - irq = (offset - 0xc00) * 2; 328 + irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ;
265 if (irq >= GIC_NIRQ) 329 if (irq >= GIC_NIRQ)
266 goto bad_reg; 330 goto bad_reg;
267 res = 0; 331 res = 0;
@@ -271,6 +335,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset) @@ -271,6 +335,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
271 if (GIC_TEST_TRIGGER(irq + i)) 335 if (GIC_TEST_TRIGGER(irq + i))
272 res |= (2 << (i * 2)); 336 res |= (2 << (i * 2));
273 } 337 }
  338 +#endif
274 } else if (offset < 0xfe0) { 339 } else if (offset < 0xfe0) {
275 goto bad_reg; 340 goto bad_reg;
276 } else /* offset >= 0xfe0 */ { 341 } else /* offset >= 0xfe0 */ {
@@ -282,7 +347,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset) @@ -282,7 +347,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
282 } 347 }
283 return res; 348 return res;
284 bad_reg: 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 return 0; 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,6 +362,13 @@ static uint32_t gic_dist_readw(void *opaque, target_phys_addr_t offset)
297 static uint32_t gic_dist_readl(void *opaque, target_phys_addr_t offset) 362 static uint32_t gic_dist_readl(void *opaque, target_phys_addr_t offset)
298 { 363 {
299 uint32_t val; 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 val = gic_dist_readw(opaque, offset); 372 val = gic_dist_readw(opaque, offset);
301 val |= gic_dist_readw(opaque, offset + 2) << 16; 373 val |= gic_dist_readw(opaque, offset + 2) << 16;
302 return val; 374 return val;
@@ -308,9 +380,14 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset, @@ -308,9 +380,14 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
308 gic_state *s = (gic_state *)opaque; 380 gic_state *s = (gic_state *)opaque;
309 int irq; 381 int irq;
310 int i; 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 if (offset < 0x100) { 387 if (offset < 0x100) {
  388 +#ifdef NVIC
  389 + goto bad_reg;
  390 +#else
314 if (offset == 0) { 391 if (offset == 0) {
315 s->enabled = (value & 1); 392 s->enabled = (value & 1);
316 DPRINTF("Distribution %sabled\n", s->enabled ? "En" : "Dis"); 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,27 +396,36 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
319 } else { 396 } else {
320 goto bad_reg; 397 goto bad_reg;
321 } 398 }
  399 +#endif
322 } else if (offset < 0x180) { 400 } else if (offset < 0x180) {
323 /* Interrupt Set Enable. */ 401 /* Interrupt Set Enable. */
324 - irq = (offset - 0x100) * 8; 402 + irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
325 if (irq >= GIC_NIRQ) 403 if (irq >= GIC_NIRQ)
326 goto bad_reg; 404 goto bad_reg;
  405 + if (irq < 16)
  406 + value = 0xff;
327 for (i = 0; i < 8; i++) { 407 for (i = 0; i < 8; i++) {
328 if (value & (1 << i)) { 408 if (value & (1 << i)) {
  409 + int mask = (irq < 32) ? (1 << cpu) : GIC_TARGET(irq);
329 if (!GIC_TEST_ENABLED(irq + i)) 410 if (!GIC_TEST_ENABLED(irq + i))
330 DPRINTF("Enabled IRQ %d\n", irq + i); 411 DPRINTF("Enabled IRQ %d\n", irq + i);
331 GIC_SET_ENABLED(irq + i); 412 GIC_SET_ENABLED(irq + i);
332 /* If a raised level triggered IRQ enabled then mark 413 /* If a raised level triggered IRQ enabled then mark
333 is as pending. */ 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 } else if (offset < 0x200) { 422 } else if (offset < 0x200) {
339 /* Interrupt Clear Enable. */ 423 /* Interrupt Clear Enable. */
340 - irq = (offset - 0x180) * 8; 424 + irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
341 if (irq >= GIC_NIRQ) 425 if (irq >= GIC_NIRQ)
342 goto bad_reg; 426 goto bad_reg;
  427 + if (irq < 16)
  428 + value = 0;
343 for (i = 0; i < 8; i++) { 429 for (i = 0; i < 8; i++) {
344 if (value & (1 << i)) { 430 if (value & (1 << i)) {
345 if (GIC_TEST_ENABLED(irq + i)) 431 if (GIC_TEST_ENABLED(irq + i))
@@ -349,22 +435,28 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset, @@ -349,22 +435,28 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
349 } 435 }
350 } else if (offset < 0x280) { 436 } else if (offset < 0x280) {
351 /* Interrupt Set Pending. */ 437 /* Interrupt Set Pending. */
352 - irq = (offset - 0x200) * 8; 438 + irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
353 if (irq >= GIC_NIRQ) 439 if (irq >= GIC_NIRQ)
354 goto bad_reg; 440 goto bad_reg;
  441 + if (irq < 16)
  442 + irq = 0;
  443 +
355 for (i = 0; i < 8; i++) { 444 for (i = 0; i < 8; i++) {
356 if (value & (1 << i)) { 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 } else if (offset < 0x300) { 449 } else if (offset < 0x300) {
361 /* Interrupt Clear Pending. */ 450 /* Interrupt Clear Pending. */
362 - irq = (offset - 0x280) * 8; 451 + irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
363 if (irq >= GIC_NIRQ) 452 if (irq >= GIC_NIRQ)
364 goto bad_reg; 453 goto bad_reg;
365 for (i = 0; i < 8; i++) { 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 if (value & (1 << i)) { 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 } else if (offset < 0x400) { 462 } else if (offset < 0x400) {
@@ -372,21 +464,32 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset, @@ -372,21 +464,32 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
372 goto bad_reg; 464 goto bad_reg;
373 } else if (offset < 0x800) { 465 } else if (offset < 0x800) {
374 /* Interrupt Priority. */ 466 /* Interrupt Priority. */
375 - irq = offset - 0x400; 467 + irq = (offset - 0x400) + GIC_BASE_IRQ;
376 if (irq >= GIC_NIRQ) 468 if (irq >= GIC_NIRQ)
377 goto bad_reg; 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 } else if (offset < 0xc00) { 476 } else if (offset < 0xc00) {
380 /* Interrupt CPU Target. */ 477 /* Interrupt CPU Target. */
381 - irq = offset - 0x800; 478 + irq = (offset - 0x800) + GIC_BASE_IRQ;
382 if (irq >= GIC_NIRQ) 479 if (irq >= GIC_NIRQ)
383 goto bad_reg; 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 } else if (offset < 0xf00) { 486 } else if (offset < 0xf00) {
386 /* Interrupt Configuration. */ 487 /* Interrupt Configuration. */
387 - irq = (offset - 0xc00) * 4; 488 + irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
388 if (irq >= GIC_NIRQ) 489 if (irq >= GIC_NIRQ)
389 goto bad_reg; 490 goto bad_reg;
  491 + if (irq < 32)
  492 + value |= 0xaa;
390 for (i = 0; i < 4; i++) { 493 for (i = 0; i < 4; i++) {
391 if (value & (1 << (i * 2))) { 494 if (value & (1 << (i * 2))) {
392 GIC_SET_MODEL(irq + i); 495 GIC_SET_MODEL(irq + i);
@@ -399,25 +502,20 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset, @@ -399,25 +502,20 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
399 GIC_CLEAR_TRIGGER(irq + i); 502 GIC_CLEAR_TRIGGER(irq + i);
400 } 503 }
401 } 504 }
  505 +#endif
402 } else { 506 } else {
403 - /* 0xf00 is only handled for word writes. */ 507 + /* 0xf00 is only handled for 32-bit writes. */
404 goto bad_reg; 508 goto bad_reg;
405 } 509 }
406 gic_update(s); 510 gic_update(s);
407 return; 511 return;
408 bad_reg: 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 static void gic_dist_writew(void *opaque, target_phys_addr_t offset, 516 static void gic_dist_writew(void *opaque, target_phys_addr_t offset,
413 uint32_t value) 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 gic_dist_writeb(opaque, offset, value & 0xff); 519 gic_dist_writeb(opaque, offset, value & 0xff);
422 gic_dist_writeb(opaque, offset + 1, value >> 8); 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,6 +523,41 @@ static void gic_dist_writew(void *opaque, target_phys_addr_t offset,
425 static void gic_dist_writel(void *opaque, target_phys_addr_t offset, 523 static void gic_dist_writel(void *opaque, target_phys_addr_t offset,
426 uint32_t value) 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 gic_dist_writew(opaque, offset, value & 0xffff); 561 gic_dist_writew(opaque, offset, value & 0xffff);
429 gic_dist_writew(opaque, offset + 2, value >> 16); 562 gic_dist_writew(opaque, offset + 2, value >> 16);
430 } 563 }
@@ -441,105 +574,100 @@ static CPUWriteMemoryFunc *gic_dist_writefn[] = { @@ -441,105 +574,100 @@ static CPUWriteMemoryFunc *gic_dist_writefn[] = {
441 gic_dist_writel 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 switch (offset) { 580 switch (offset) {
449 case 0x00: /* Control */ 581 case 0x00: /* Control */
450 - return s->cpu_enabled; 582 + return s->cpu_enabled[cpu];
451 case 0x04: /* Priority mask */ 583 case 0x04: /* Priority mask */
452 - return s->priority_mask; 584 + return s->priority_mask[cpu];
453 case 0x08: /* Binary Point */ 585 case 0x08: /* Binary Point */
454 /* ??? Not implemented. */ 586 /* ??? Not implemented. */
455 return 0; 587 return 0;
456 case 0x0c: /* Acknowledge */ 588 case 0x0c: /* Acknowledge */
457 - return gic_acknowledge_irq(s); 589 + return gic_acknowledge_irq(s, cpu);
458 case 0x14: /* Runing Priority */ 590 case 0x14: /* Runing Priority */
459 - return s->running_priority; 591 + return s->running_priority[cpu];
460 case 0x18: /* Highest Pending Interrupt */ 592 case 0x18: /* Highest Pending Interrupt */
461 - return s->current_pending; 593 + return s->current_pending[cpu];
462 default: 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 return 0; 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 switch (offset) { 603 switch (offset) {
474 case 0x00: /* Control */ 604 case 0x00: /* Control */
475 - s->cpu_enabled = (value & 1); 605 + s->cpu_enabled[cpu] = (value & 1);
476 DPRINTF("CPU %sabled\n", s->cpu_enabled ? "En" : "Dis"); 606 DPRINTF("CPU %sabled\n", s->cpu_enabled ? "En" : "Dis");
477 break; 607 break;
478 case 0x04: /* Priority mask */ 608 case 0x04: /* Priority mask */
479 - s->priority_mask = (value & 0x3ff); 609 + s->priority_mask[cpu] = (value & 0xff);
480 break; 610 break;
481 case 0x08: /* Binary Point */ 611 case 0x08: /* Binary Point */
482 /* ??? Not implemented. */ 612 /* ??? Not implemented. */
483 break; 613 break;
484 case 0x10: /* End Of Interrupt */ 614 case 0x10: /* End Of Interrupt */
485 - return gic_complete_irq(s, value & 0x3ff); 615 + return gic_complete_irq(s, cpu, value & 0x3ff);
486 default: 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 return; 619 return;
489 } 620 }
490 gic_update(s); 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 static void gic_reset(gic_state *s) 625 static void gic_reset(gic_state *s)
506 { 626 {
507 int i; 627 int i;
508 memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state)); 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 for (i = 0; i < 15; i++) { 641 for (i = 0; i < 15; i++) {
514 GIC_SET_ENABLED(i); 642 GIC_SET_ENABLED(i);
515 GIC_SET_TRIGGER(i); 643 GIC_SET_TRIGGER(i);
516 } 644 }
  645 +#ifdef NVIC
  646 + /* The NVIC is always enabled. */
  647 + s->enabled = 1;
  648 +#else
517 s->enabled = 0; 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 gic_state *s; 655 gic_state *s;
524 - qemu_irq *qi;  
525 int iomemtype; 656 int iomemtype;
  657 + int i;
526 658
527 s = (gic_state *)qemu_mallocz(sizeof(gic_state)); 659 s = (gic_state *)qemu_mallocz(sizeof(gic_state));
528 if (!s) 660 if (!s)
529 return NULL; 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 gic_reset(s); 671 gic_reset(s);
544 - return qi; 672 + return s;
545 } 673 }
hw/arm_sysctl.c
1 /* 1 /*
2 * Status and system control registers for ARM RealView/Versatile boards. 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 * Written by Paul Brook 5 * Written by Paul Brook
6 * 6 *
7 * This code is licenced under the GPL. 7 * This code is licenced under the GPL.
@@ -200,6 +200,9 @@ void arm_sysctl_init(uint32_t base, uint32_t sys_id) @@ -200,6 +200,9 @@ void arm_sysctl_init(uint32_t base, uint32_t sys_id)
200 return; 200 return;
201 s->base = base; 201 s->base = base;
202 s->sys_id = sys_id; 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 iomemtype = cpu_register_io_memory(0, arm_sysctl_readfn, 206 iomemtype = cpu_register_io_memory(0, arm_sysctl_readfn,
204 arm_sysctl_writefn, s); 207 arm_sysctl_writefn, s);
205 cpu_register_physical_memory(base, 0x00001000, iomemtype); 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,8 +497,8 @@ static void integratorcp_init(int ram_size, int vga_ram_size,
497 icp_pic_init(0xca000000, pic[26], NULL); 497 icp_pic_init(0xca000000, pic[26], NULL);
498 icp_pit_init(0x13000000, pic, 5); 498 icp_pit_init(0x13000000, pic, 5);
499 pl031_init(0x15000000, pic[8]); 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 icp_control_init(0xcb000000); 502 icp_control_init(0xcb000000);
503 pl050_init(0x18000000, pic[3], 0); 503 pl050_init(0x18000000, pic[3], 0);
504 pl050_init(0x19000000, pic[4], 1); 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,6 +28,7 @@ typedef struct {
28 int read_trigger; 28 int read_trigger;
29 CharDriverState *chr; 29 CharDriverState *chr;
30 qemu_irq irq; 30 qemu_irq irq;
  31 + enum pl011_type type;
31 } pl011_state; 32 } pl011_state;
32 33
33 #define PL011_INT_TX 0x20 34 #define PL011_INT_TX 0x20
@@ -38,8 +39,10 @@ typedef struct { @@ -38,8 +39,10 @@ typedef struct {
38 #define PL011_FLAG_TXFF 0x20 39 #define PL011_FLAG_TXFF 0x20
39 #define PL011_FLAG_RXFE 0x10 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 static void pl011_update(pl011_state *s) 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,7 +59,7 @@ static uint32_t pl011_read(void *opaque, target_phys_addr_t offset)
56 59
57 offset -= s->base; 60 offset -= s->base;
58 if (offset >= 0xfe0 && offset < 0x1000) { 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 switch (offset >> 2) { 64 switch (offset >> 2) {
62 case 0: /* UARTDR */ 65 case 0: /* UARTDR */
@@ -137,6 +140,9 @@ static void pl011_write(void *opaque, target_phys_addr_t offset, @@ -137,6 +140,9 @@ static void pl011_write(void *opaque, target_phys_addr_t offset,
137 case 1: /* UARTCR */ 140 case 1: /* UARTCR */
138 s->cr = value; 141 s->cr = value;
139 break; 142 break;
  143 + case 6: /* UARTFR */
  144 + /* Writes to Flag register are ignored. */
  145 + break;
140 case 8: /* UARTUARTILPR */ 146 case 8: /* UARTUARTILPR */
141 s->ilpr = value; 147 s->ilpr = value;
142 break; 148 break;
@@ -224,7 +230,7 @@ static CPUWriteMemoryFunc *pl011_writefn[] = { @@ -224,7 +230,7 @@ static CPUWriteMemoryFunc *pl011_writefn[] = {
224 }; 230 };
225 231
226 void pl011_init(uint32_t base, qemu_irq irq, 232 void pl011_init(uint32_t base, qemu_irq irq,
227 - CharDriverState *chr) 233 + CharDriverState *chr, enum pl011_type type)
228 { 234 {
229 int iomemtype; 235 int iomemtype;
230 pl011_state *s; 236 pl011_state *s;
@@ -235,6 +241,7 @@ void pl011_init(uint32_t base, qemu_irq irq, @@ -235,6 +241,7 @@ void pl011_init(uint32_t base, qemu_irq irq,
235 cpu_register_physical_memory(base, 0x00001000, iomemtype); 241 cpu_register_physical_memory(base, 0x00001000, iomemtype);
236 s->base = base; 242 s->base = base;
237 s->irq = irq; 243 s->irq = irq;
  244 + s->type = type;
238 s->chr = chr; 245 s->chr = chr;
239 s->read_trigger = 1; 246 s->read_trigger = 1;
240 s->ifl = 0x12; 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,7 +297,7 @@ static void pxa2xx_clkpwr_write(void *opaque, int op2, int reg, int crm,
297 ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I; 297 ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
298 s->env->cp15.c1_sys = 0; 298 s->env->cp15.c1_sys = 0;
299 s->env->cp15.c1_coproc = 0; 299 s->env->cp15.c1_coproc = 0;
300 - s->env->cp15.c2_base = 0; 300 + s->env->cp15.c2_base0 = 0;
301 s->env->cp15.c3 = 0; 301 s->env->cp15.c3 = 0;
302 s->pm_regs[PSSR >> 2] |= 0x8; /* Set STS */ 302 s->pm_regs[PSSR >> 2] |= 0x8; /* Set STS */
303 s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */ 303 s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
@@ -2031,7 +2031,8 @@ struct pxa2xx_state_s *pxa270_init(unsigned int sdram_size, @@ -2031,7 +2031,8 @@ struct pxa2xx_state_s *pxa270_init(unsigned int sdram_size,
2031 fprintf(stderr, "Unable to find CPU definition\n"); 2031 fprintf(stderr, "Unable to find CPU definition\n");
2032 exit(1); 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 /* SDRAM & Internal Memory Storage */ 2037 /* SDRAM & Internal Memory Storage */
2037 cpu_register_physical_memory(PXA2XX_SDRAM_BASE, 2038 cpu_register_physical_memory(PXA2XX_SDRAM_BASE,
@@ -2145,7 +2146,8 @@ struct pxa2xx_state_s *pxa255_init(unsigned int sdram_size, @@ -2145,7 +2146,8 @@ struct pxa2xx_state_s *pxa255_init(unsigned int sdram_size,
2145 fprintf(stderr, "Unable to find CPU definition\n"); 2146 fprintf(stderr, "Unable to find CPU definition\n");
2146 exit(1); 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 /* SDRAM & Internal Memory Storage */ 2152 /* SDRAM & Internal Memory Storage */
2151 cpu_register_physical_memory(PXA2XX_SDRAM_BASE, sdram_size, 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,13 +25,32 @@ static void realview_init(int ram_size, int vga_ram_size,
25 NICInfo *nd; 25 NICInfo *nd;
26 int n; 26 int n;
27 int done_smc = 0; 27 int done_smc = 0;
  28 + qemu_irq cpu_irq[4];
  29 + int ncpu;
28 30
29 if (!cpu_model) 31 if (!cpu_model)
30 cpu_model = "arm926"; 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 /* ??? RAM shoud repeat to fill physical memory space. */ 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,18 +58,23 @@ static void realview_init(int ram_size, int vga_ram_size,
39 cpu_register_physical_memory(0, ram_size, IO_MEM_RAM); 58 cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
40 59
41 arm_sysctl_init(0x10000000, 0xc1400400); 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 pl050_init(0x10006000, pic[20], 0); 71 pl050_init(0x10006000, pic[20], 0);
48 pl050_init(0x10007000, pic[21], 1); 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 /* DMA controller is optional, apparently. */ 79 /* DMA controller is optional, apparently. */
56 pl080_init(0x10030000, pic[24], 2); 80 pl080_init(0x10030000, pic[24], 2);
@@ -114,10 +138,10 @@ static void realview_init(int ram_size, int vga_ram_size, @@ -114,10 +138,10 @@ static void realview_init(int ram_size, int vga_ram_size,
114 /* 0x10019000 PCI controller config. */ 138 /* 0x10019000 PCI controller config. */
115 /* 0x10020000 CLCD. */ 139 /* 0x10020000 CLCD. */
116 /* 0x10030000 DMA Controller. */ 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 /* 0x10080000 SMC. */ 145 /* 0x10080000 SMC. */
122 /* 0x40000000 NOR flash. */ 146 /* 0x40000000 NOR flash. */
123 /* 0x44000000 DoC flash. */ 147 /* 0x44000000 DoC flash. */
@@ -137,8 +161,14 @@ static void realview_init(int ram_size, int vga_ram_size, @@ -137,8 +161,14 @@ static void realview_init(int ram_size, int vga_ram_size,
137 /* 0x68000000 PCI mem 1. */ 161 /* 0x68000000 PCI mem 1. */
138 /* 0x6c000000 PCI mem 2. */ 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 initrd_filename, 0x33b, 0x0); 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 QEMUMachine realview_machine = { 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,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 pl080_init(0x10130000, pic[17], 8); 216 pl080_init(0x10130000, pic[17], 8);
217 sp804_init(0x101e2000, pic[4]); 217 sp804_init(0x101e2000, pic[4]);
qemu-doc.texi
@@ -77,10 +77,12 @@ For system emulation, the following hardware targets are supported: @@ -77,10 +77,12 @@ For system emulation, the following hardware targets are supported:
77 @item Sun4m (32-bit Sparc processor) 77 @item Sun4m (32-bit Sparc processor)
78 @item Sun4u (64-bit Sparc processor, in progress) 78 @item Sun4u (64-bit Sparc processor, in progress)
79 @item Malta board (32-bit MIPS processor) 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 @item Spitz, Akita, Borzoi and Terrier PDAs (PXA270 processor) 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 @item Freescale MCF5208EVB (ColdFire V2). 86 @item Freescale MCF5208EVB (ColdFire V2).
85 @item Arnewsh MCF5206 evaluation board (ColdFire V2). 87 @item Arnewsh MCF5206 evaluation board (ColdFire V2).
86 @item Palm Tungsten|E PDA (OMAP310 processor) 88 @item Palm Tungsten|E PDA (OMAP310 processor)
@@ -2117,7 +2119,7 @@ devices: @@ -2117,7 +2119,7 @@ devices:
2117 2119
2118 @itemize @minus 2120 @itemize @minus
2119 @item 2121 @item
2120 -ARM926E, ARM1026E or ARM946E CPU 2122 +ARM926E, ARM1026E, ARM946E, ARM1136 or Cortex-A8 CPU
2121 @item 2123 @item
2122 Two PL011 UARTs 2124 Two PL011 UARTs
2123 @item 2125 @item
@@ -2134,7 +2136,7 @@ The ARM Versatile baseboard is emulated with the following devices: @@ -2134,7 +2136,7 @@ The ARM Versatile baseboard is emulated with the following devices:
2134 2136
2135 @itemize @minus 2137 @itemize @minus
2136 @item 2138 @item
2137 -ARM926E CPU 2139 +ARM926E, ARM1136 or Cortex-A8 CPU
2138 @item 2140 @item
2139 PL190 Vectored Interrupt Controller 2141 PL190 Vectored Interrupt Controller
2140 @item 2142 @item
@@ -2163,7 +2165,7 @@ The ARM RealView Emulation baseboard is emulated with the following devices: @@ -2163,7 +2165,7 @@ The ARM RealView Emulation baseboard is emulated with the following devices:
2163 2165
2164 @itemize @minus 2166 @itemize @minus
2165 @item 2167 @item
2166 -ARM926E CPU 2168 +ARM926E, ARM1136, ARM11MPCORE(x4) or Cortex-A8 CPU
2167 @item 2169 @item
2168 ARM AMBA Generic/Distributed Interrupt Controller 2170 ARM AMBA Generic/Distributed Interrupt Controller
2169 @item 2171 @item
@@ -2237,6 +2239,34 @@ Secure Digital card connected to OMAP MMC/SD host @@ -2237,6 +2239,34 @@ Secure Digital card connected to OMAP MMC/SD host
2237 Three on-chip UARTs 2239 Three on-chip UARTs
2238 @end itemize 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 A Linux 2.6 test image is available on the QEMU web site. More 2270 A Linux 2.6 test image is available on the QEMU web site. More
2241 information is available in the QEMU mailing-list archive. 2271 information is available in the QEMU mailing-list archive.
2242 2272
target-arm/cpu.h
@@ -37,6 +37,18 @@ @@ -37,6 +37,18 @@
37 #define EXCP_IRQ 5 37 #define EXCP_IRQ 5
38 #define EXCP_FIQ 6 38 #define EXCP_FIQ 6
39 #define EXCP_BKPT 7 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 typedef void ARMWriteCPFunc(void *opaque, int cp_info, 53 typedef void ARMWriteCPFunc(void *opaque, int cp_info,
42 int srcreg, int operand, uint32_t value); 54 int srcreg, int operand, uint32_t value);
@@ -76,17 +88,22 @@ typedef struct CPUARMState { @@ -76,17 +88,22 @@ typedef struct CPUARMState {
76 uint32_t VF; /* V is the bit 31. All other bits are undefined */ 88 uint32_t VF; /* V is the bit 31. All other bits are undefined */
77 uint32_t NZF; /* N is bit 31. Z is computed from NZF */ 89 uint32_t NZF; /* N is bit 31. Z is computed from NZF */
78 uint32_t QF; /* 0 or 1 */ 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 /* System control coprocessor (cp15) */ 95 /* System control coprocessor (cp15) */
83 struct { 96 struct {
84 uint32_t c0_cpuid; 97 uint32_t c0_cpuid;
85 uint32_t c0_cachetype; 98 uint32_t c0_cachetype;
  99 + uint32_t c0_c1[8]; /* Feature registers. */
  100 + uint32_t c0_c2[8]; /* Instruction set registers. */
86 uint32_t c1_sys; /* System control register. */ 101 uint32_t c1_sys; /* System control register. */
87 uint32_t c1_coproc; /* Coprocessor access register. */ 102 uint32_t c1_coproc; /* Coprocessor access register. */
88 uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */ 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 uint32_t c2_data; /* MPU data cachable bits. */ 107 uint32_t c2_data; /* MPU data cachable bits. */
91 uint32_t c2_insn; /* MPU instruction cachable bits. */ 108 uint32_t c2_insn; /* MPU instruction cachable bits. */
92 uint32_t c3; /* MMU domain access control register 109 uint32_t c3; /* MMU domain access control register
@@ -100,6 +117,9 @@ typedef struct CPUARMState { @@ -100,6 +117,9 @@ typedef struct CPUARMState {
100 uint32_t c9_data; 117 uint32_t c9_data;
101 uint32_t c13_fcse; /* FCSE PID. */ 118 uint32_t c13_fcse; /* FCSE PID. */
102 uint32_t c13_context; /* Context ID. */ 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 uint32_t c15_cpar; /* XScale Coprocessor Access Register */ 123 uint32_t c15_cpar; /* XScale Coprocessor Access Register */
104 uint32_t c15_ticonfig; /* TI925T configuration byte. */ 124 uint32_t c15_ticonfig; /* TI925T configuration byte. */
105 uint32_t c15_i_max; /* Maximum D-cache dirty line index. */ 125 uint32_t c15_i_max; /* Maximum D-cache dirty line index. */
@@ -107,6 +127,17 @@ typedef struct CPUARMState { @@ -107,6 +127,17 @@ typedef struct CPUARMState {
107 uint32_t c15_threadid; /* TI debugger thread-ID. */ 127 uint32_t c15_threadid; /* TI debugger thread-ID. */
108 } cp15; 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 /* Coprocessor IO used by peripherals */ 141 /* Coprocessor IO used by peripherals */
111 struct { 142 struct {
112 ARMReadCPFunc *cp_read; 143 ARMReadCPFunc *cp_read;
@@ -117,6 +148,10 @@ typedef struct CPUARMState { @@ -117,6 +148,10 @@ typedef struct CPUARMState {
117 /* Internal CPU feature flags. */ 148 /* Internal CPU feature flags. */
118 uint32_t features; 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 /* exception/interrupt handling */ 155 /* exception/interrupt handling */
121 jmp_buf jmp_env; 156 jmp_buf jmp_env;
122 int exception_index; 157 int exception_index;
@@ -126,7 +161,7 @@ typedef struct CPUARMState { @@ -126,7 +161,7 @@ typedef struct CPUARMState {
126 161
127 /* VFP coprocessor state. */ 162 /* VFP coprocessor state. */
128 struct { 163 struct {
129 - float64 regs[16]; 164 + float64 regs[32];
130 165
131 uint32_t xregs[16]; 166 uint32_t xregs[16];
132 /* We store these fpcsr fields separately for convenience. */ 167 /* We store these fpcsr fields separately for convenience. */
@@ -136,9 +171,16 @@ typedef struct CPUARMState { @@ -136,9 +171,16 @@ typedef struct CPUARMState {
136 /* Temporary variables if we don't have spare fp regs. */ 171 /* Temporary variables if we don't have spare fp regs. */
137 float32 tmp0s, tmp1s; 172 float32 tmp0s, tmp1s;
138 float64 tmp0d, tmp1d; 173 float64 tmp0d, tmp1d;
  174 + /* scratch space when Tn are not sufficient. */
  175 + uint32_t scratch[8];
139 176
140 float_status fp_status; 177 float_status fp_status;
141 } vfp; 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 /* iwMMXt coprocessor state. */ 185 /* iwMMXt coprocessor state. */
144 struct { 186 struct {
@@ -169,6 +211,7 @@ int cpu_arm_exec(CPUARMState *s); @@ -169,6 +211,7 @@ int cpu_arm_exec(CPUARMState *s);
169 void cpu_arm_close(CPUARMState *s); 211 void cpu_arm_close(CPUARMState *s);
170 void do_interrupt(CPUARMState *); 212 void do_interrupt(CPUARMState *);
171 void switch_mode(CPUARMState *, int); 213 void switch_mode(CPUARMState *, int);
  214 +uint32_t do_arm_semihosting(CPUARMState *env);
172 215
173 /* you can call this signal handler from your SIGBUS and SIGSEGV 216 /* you can call this signal handler from your SIGBUS and SIGSEGV
174 signal handlers to inform the virtual CPU of exceptions. non zero 217 signal handlers to inform the virtual CPU of exceptions. non zero
@@ -176,6 +219,9 @@ void switch_mode(CPUARMState *, int); @@ -176,6 +219,9 @@ void switch_mode(CPUARMState *, int);
176 int cpu_arm_signal_handler(int host_signum, void *pinfo, 219 int cpu_arm_signal_handler(int host_signum, void *pinfo,
177 void *puc); 220 void *puc);
178 221
  222 +void cpu_lock(void);
  223 +void cpu_unlock(void);
  224 +
179 #define CPSR_M (0x1f) 225 #define CPSR_M (0x1f)
180 #define CPSR_T (1 << 5) 226 #define CPSR_T (1 << 5)
181 #define CPSR_F (1 << 6) 227 #define CPSR_F (1 << 6)
@@ -183,13 +229,24 @@ int cpu_arm_signal_handler(int host_signum, void *pinfo, @@ -183,13 +229,24 @@ int cpu_arm_signal_handler(int host_signum, void *pinfo,
183 #define CPSR_A (1 << 8) 229 #define CPSR_A (1 << 8)
184 #define CPSR_E (1 << 9) 230 #define CPSR_E (1 << 9)
185 #define CPSR_IT_2_7 (0xfc00) 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 #define CPSR_J (1 << 24) 234 #define CPSR_J (1 << 24)
188 #define CPSR_IT_0_1 (3 << 25) 235 #define CPSR_IT_0_1 (3 << 25)
189 #define CPSR_Q (1 << 27) 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 /* Return the current CPSR value. */ 250 /* Return the current CPSR value. */
194 static inline uint32_t cpsr_read(CPUARMState *env) 251 static inline uint32_t cpsr_read(CPUARMState *env)
195 { 252 {
@@ -197,7 +254,21 @@ static inline uint32_t cpsr_read(CPUARMState *env) @@ -197,7 +254,21 @@ static inline uint32_t cpsr_read(CPUARMState *env)
197 ZF = (env->NZF == 0); 254 ZF = (env->NZF == 0);
198 return env->uncached_cpsr | (env->NZF & 0x80000000) | (ZF << 30) | 255 return env->uncached_cpsr | (env->NZF & 0x80000000) | (ZF << 30) |
199 (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27) 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 /* Set the CPSR. Note that some bits of mask must be all-set or all-clear. */ 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,6 +284,17 @@ static inline void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
213 env->QF = ((val & CPSR_Q) != 0); 284 env->QF = ((val & CPSR_Q) != 0);
214 if (mask & CPSR_T) 285 if (mask & CPSR_T)
215 env->thumb = ((val & CPSR_T) != 0); 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 if ((env->uncached_cpsr ^ val) & mask & CPSR_M) { 299 if ((env->uncached_cpsr ^ val) & mask & CPSR_M) {
218 switch_mode(env, val & CPSR_M); 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,6 +303,32 @@ static inline void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
221 env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask); 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 enum arm_cpu_mode { 332 enum arm_cpu_mode {
225 ARM_CPU_MODE_USR = 0x10, 333 ARM_CPU_MODE_USR = 0x10,
226 ARM_CPU_MODE_FIQ = 0x11, 334 ARM_CPU_MODE_FIQ = 0x11,
@@ -234,6 +342,8 @@ enum arm_cpu_mode { @@ -234,6 +342,8 @@ enum arm_cpu_mode {
234 /* VFP system registers. */ 342 /* VFP system registers. */
235 #define ARM_VFP_FPSID 0 343 #define ARM_VFP_FPSID 0
236 #define ARM_VFP_FPSCR 1 344 #define ARM_VFP_FPSCR 1
  345 +#define ARM_VFP_MVFR1 6
  346 +#define ARM_VFP_MVFR0 7
237 #define ARM_VFP_FPEXC 8 347 #define ARM_VFP_FPEXC 8
238 #define ARM_VFP_FPINST 9 348 #define ARM_VFP_FPINST 9
239 #define ARM_VFP_FPINST2 10 349 #define ARM_VFP_FPINST2 10
@@ -253,7 +363,15 @@ enum arm_features { @@ -253,7 +363,15 @@ enum arm_features {
253 ARM_FEATURE_AUXCR, /* ARM1026 Auxiliary control register. */ 363 ARM_FEATURE_AUXCR, /* ARM1026 Auxiliary control register. */
254 ARM_FEATURE_XSCALE, /* Intel XScale extensions. */ 364 ARM_FEATURE_XSCALE, /* Intel XScale extensions. */
255 ARM_FEATURE_IWMMXT, /* Intel iwMMXt extension. */ 365 ARM_FEATURE_IWMMXT, /* Intel iwMMXt extension. */
  366 + ARM_FEATURE_V6,
  367 + ARM_FEATURE_V6K,
  368 + ARM_FEATURE_V7,
  369 + ARM_FEATURE_THUMB2,
256 ARM_FEATURE_MPU, /* Only has Memory Protection Unit, not full MMU. */ 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 ARM_FEATURE_OMAPCP /* OMAP specific CP15 ops handling. */ 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,27 +382,44 @@ static inline int arm_feature(CPUARMState *env, int feature)
264 382
265 void arm_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)); 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 void cpu_arm_set_cp_io(CPUARMState *env, int cpnum, 390 void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
268 ARMReadCPFunc *cp_read, ARMWriteCPFunc *cp_write, 391 ARMReadCPFunc *cp_read, ARMWriteCPFunc *cp_write,
269 void *opaque); 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 #if defined(CONFIG_USER_ONLY) 424 #if defined(CONFIG_USER_ONLY)
290 #define TARGET_PAGE_BITS 12 425 #define TARGET_PAGE_BITS 12
@@ -302,6 +437,8 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum, @@ -302,6 +437,8 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
302 #define cpu_signal_handler cpu_arm_signal_handler 437 #define cpu_signal_handler cpu_arm_signal_handler
303 #define cpu_list arm_cpu_list 438 #define cpu_list arm_cpu_list
304 439
  440 +#define ARM_CPU_SAVE_VERSION 1
  441 +
305 /* MMU modes definitions */ 442 /* MMU modes definitions */
306 #define MMU_MODE0_SUFFIX _kernel 443 #define MMU_MODE0_SUFFIX _kernel
307 #define MMU_MODE1_SUFFIX _user 444 #define MMU_MODE1_SUFFIX _user
target-arm/exec.h
@@ -68,12 +68,18 @@ static inline int cpu_halted(CPUState *env) { @@ -68,12 +68,18 @@ static inline int cpu_halted(CPUState *env) {
68 68
69 /* In op_helper.c */ 69 /* In op_helper.c */
70 70
71 -void cpu_lock(void);  
72 -void cpu_unlock(void);  
73 void helper_set_cp(CPUState *, uint32_t, uint32_t); 71 void helper_set_cp(CPUState *, uint32_t, uint32_t);
74 uint32_t helper_get_cp(CPUState *, uint32_t); 72 uint32_t helper_get_cp(CPUState *, uint32_t);
75 void helper_set_cp15(CPUState *, uint32_t, uint32_t); 73 void helper_set_cp15(CPUState *, uint32_t, uint32_t);
76 uint32_t helper_get_cp15(CPUState *, uint32_t); 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 void cpu_loop_exit(void); 84 void cpu_loop_exit(void);
79 85
@@ -91,4 +97,11 @@ void do_vfp_cmpes(void); @@ -91,4 +97,11 @@ void do_vfp_cmpes(void);
91 void do_vfp_cmped(void); 97 void do_vfp_cmped(void);
92 void do_vfp_set_fpscr(void); 98 void do_vfp_set_fpscr(void);
93 void do_vfp_get_fpscr(void); 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);