Commit 9fdc60bf55fc291d734735ddfb5629f8e8ced32b
1 parent
74c62ba8
kvm/powerpc: Add irq support for E500 core
Signed-off-by: Liu Yu <yu.liu@freescale.com> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6662 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
74 additions
and
2 deletions
hw/ppc.c
... | ... | @@ -314,6 +314,66 @@ void ppc40x_irq_init (CPUState *env) |
314 | 314 | env, PPC40x_INPUT_NB); |
315 | 315 | } |
316 | 316 | |
317 | +/* PowerPC E500 internal IRQ controller */ | |
318 | +static void ppce500_set_irq (void *opaque, int pin, int level) | |
319 | +{ | |
320 | + CPUState *env = opaque; | |
321 | + int cur_level; | |
322 | + | |
323 | + LOG_IRQ("%s: env %p pin %d level %d\n", __func__, | |
324 | + env, pin, level); | |
325 | + cur_level = (env->irq_input_state >> pin) & 1; | |
326 | + /* Don't generate spurious events */ | |
327 | + if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) { | |
328 | + switch (pin) { | |
329 | + case PPCE500_INPUT_MCK: | |
330 | + if (level) { | |
331 | + LOG_IRQ("%s: reset the PowerPC system\n", | |
332 | + __func__); | |
333 | + qemu_system_reset_request(); | |
334 | + } | |
335 | + break; | |
336 | + case PPCE500_INPUT_RESET_CORE: | |
337 | + if (level) { | |
338 | + LOG_IRQ("%s: reset the PowerPC core\n", __func__); | |
339 | + ppc_set_irq(env, PPC_INTERRUPT_MCK, level); | |
340 | + } | |
341 | + break; | |
342 | + case PPCE500_INPUT_CINT: | |
343 | + /* Level sensitive - active high */ | |
344 | + LOG_IRQ("%s: set the critical IRQ state to %d\n", | |
345 | + __func__, level); | |
346 | + ppc_set_irq(env, PPC_INTERRUPT_CEXT, level); | |
347 | + break; | |
348 | + case PPCE500_INPUT_INT: | |
349 | + /* Level sensitive - active high */ | |
350 | + LOG_IRQ("%s: set the core IRQ state to %d\n", | |
351 | + __func__, level); | |
352 | + ppc_set_irq(env, PPC_INTERRUPT_EXT, level); | |
353 | + break; | |
354 | + case PPCE500_INPUT_DEBUG: | |
355 | + /* Level sensitive - active high */ | |
356 | + LOG_IRQ("%s: set the debug pin state to %d\n", | |
357 | + __func__, level); | |
358 | + ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level); | |
359 | + break; | |
360 | + default: | |
361 | + /* Unknown pin - do nothing */ | |
362 | + LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin); | |
363 | + return; | |
364 | + } | |
365 | + if (level) | |
366 | + env->irq_input_state |= 1 << pin; | |
367 | + else | |
368 | + env->irq_input_state &= ~(1 << pin); | |
369 | + } | |
370 | +} | |
371 | + | |
372 | +void ppce500_irq_init (CPUState *env) | |
373 | +{ | |
374 | + env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq, | |
375 | + env, PPCE500_INPUT_NB); | |
376 | +} | |
317 | 377 | /*****************************************************************************/ |
318 | 378 | /* PowerPC time base and decrementer emulation */ |
319 | 379 | struct ppc_tb_t { | ... | ... |
hw/ppc.h
... | ... | @@ -31,6 +31,7 @@ extern CPUReadMemoryFunc *PPC_io_read[]; |
31 | 31 | void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val); |
32 | 32 | |
33 | 33 | void ppc40x_irq_init (CPUState *env); |
34 | +void ppce500_irq_init (CPUState *env); | |
34 | 35 | void ppc6xx_irq_init (CPUState *env); |
35 | 36 | void ppc970_irq_init (CPUState *env); |
36 | 37 | ... | ... |
target-ppc/cpu.h
... | ... | @@ -1356,6 +1356,16 @@ enum { |
1356 | 1356 | }; |
1357 | 1357 | |
1358 | 1358 | enum { |
1359 | + /* PowerPC E500 input pins */ | |
1360 | + PPCE500_INPUT_RESET_CORE = 0, | |
1361 | + PPCE500_INPUT_MCK = 1, | |
1362 | + PPCE500_INPUT_CINT = 3, | |
1363 | + PPCE500_INPUT_INT = 4, | |
1364 | + PPCE500_INPUT_DEBUG = 6, | |
1365 | + PPCE500_INPUT_NB, | |
1366 | +}; | |
1367 | + | |
1368 | +enum { | |
1359 | 1369 | /* PowerPC 40x input pins */ |
1360 | 1370 | PPC40x_INPUT_RESET_CORE = 0, |
1361 | 1371 | PPC40x_INPUT_RESET_CHIP = 1, | ... | ... |
target-ppc/translate_init.c
... | ... | @@ -63,6 +63,7 @@ void glue(glue(ppc, name),_irq_init) (CPUPPCState *env); |
63 | 63 | PPC_IRQ_INIT_FN(40x); |
64 | 64 | PPC_IRQ_INIT_FN(6xx); |
65 | 65 | PPC_IRQ_INIT_FN(970); |
66 | +PPC_IRQ_INIT_FN(e500); | |
66 | 67 | |
67 | 68 | /* Generic callbacks: |
68 | 69 | * do nothing but store/retrieve spr value |
... | ... | @@ -4198,7 +4199,6 @@ static void init_proc_e300 (CPUPPCState *env) |
4198 | 4199 | #define check_pow_e500v2 check_pow_hid0 |
4199 | 4200 | #define init_proc_e500v2 init_proc_e500 |
4200 | 4201 | |
4201 | -__attribute__ (( unused )) | |
4202 | 4202 | static void init_proc_e500 (CPUPPCState *env) |
4203 | 4203 | { |
4204 | 4204 | /* Time base */ |
... | ... | @@ -4300,7 +4300,8 @@ static void init_proc_e500 (CPUPPCState *env) |
4300 | 4300 | init_excp_e200(env); |
4301 | 4301 | env->dcache_line_size = 32; |
4302 | 4302 | env->icache_line_size = 32; |
4303 | - /* XXX: TODO: allocate internal IRQ controller */ | |
4303 | + /* Allocate hardware IRQ controller */ | |
4304 | + ppce500_irq_init(env); | |
4304 | 4305 | } |
4305 | 4306 | |
4306 | 4307 | /* Non-embedded PowerPC */ | ... | ... |