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 */ | ... | ... |