diff mbox

[08/15] Openrisc: add programmable interrupt controller support

Message ID 1337243758-11802-9-git-send-email-proljc@gmail.com
State New
Headers show

Commit Message

Jia Liu May 17, 2012, 8:35 a.m. UTC
add the openrisc programmable interrupt controller support.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 cpu-exec.c        |   17 +++++++++++++++++
 hw/openrisc_pic.c |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+)

Comments

Blue Swirl May 19, 2012, 8:33 a.m. UTC | #1
On Thu, May 17, 2012 at 8:35 AM, Jia Liu <proljc@gmail.com> wrote:
> add the openrisc programmable interrupt controller support.
>
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  cpu-exec.c        |   17 +++++++++++++++++
>  hw/openrisc_pic.c |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 65 insertions(+)
>
> diff --git a/cpu-exec.c b/cpu-exec.c
> index ba10db1..845b2ae 100644
> --- a/cpu-exec.c
> +++ b/cpu-exec.c
> @@ -375,6 +375,23 @@ int cpu_exec(CPUArchState *env)
>                         do_interrupt(env);
>                         next_tb = 0;
>                     }
> +#elif defined(TARGET_OPENRISC)
> +                    {
> +                        int idx = -1;
> +                        if ((interrupt_request & CPU_INTERRUPT_HARD)
> +                            && (env->sr & SR_IEE)) {
> +                            idx = EXCP_INT;
> +                        }
> +                        if ((interrupt_request & CPU_INTERRUPT_TIMER)
> +                            && (env->sr & SR_TEE)) {
> +                            idx = EXCP_TICK;
> +                        }
> +                        if (idx >= 0) {
> +                            env->exception_index = idx;
> +                            do_interrupt(env);
> +                            next_tb = 0;
> +                        }
> +                    }
>  #elif defined(TARGET_SPARC)
>                     if (interrupt_request & CPU_INTERRUPT_HARD) {
>                         if (cpu_interrupts_enabled(env) &&
> diff --git a/hw/openrisc_pic.c b/hw/openrisc_pic.c
> index 0abdd50..52e48ec 100644
> --- a/hw/openrisc_pic.c
> +++ b/hw/openrisc_pic.c
> @@ -29,3 +29,51 @@ void cpu_openrisc_pic_reset(CPUOPENRISCState *env)
>     env->picmr = 0x00000000;
>     env->picsr = 0x00000000;
>  }
> +
> +/* openrisc pic handler */
> +static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
> +{
> +    CPUOPENRISCState *env = (CPUOPENRISCState *)opaque;
> +    int i;
> +    uint32_t irq_bit = 1 << irq;
> +
> +    if (irq > 31 || irq < 0) {
> +        return;
> +    }
> +
> +    if (level) {
> +        env->picsr |= irq_bit;
> +    } else {
> +        env->picsr &= ~irq_bit;
> +    }
> +
> +    for (i = 0; i < 32; i++) {
> +        if ((env->picsr && (1 << i)) && (env->picmr && (1 << i))) {
> +            cpu_interrupt(env, CPU_INTERRUPT_HARD);

The CPU could have one IRQ line input (set up at board or CPU level),
which the device toggles. That way the PIC does not need to be coupled
so tightly with the CPU (no need to access CPUState).

> +        } else {
> +            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
> +            env->picsr &= ~(1 << i);
> +        }
> +    }
> +}
> +
> +void cpu_openrisc_pic_init(CPUOPENRISCState *env)
> +{
> +    int i;
> +    qemu_irq *qi;
> +    qi = qemu_allocate_irqs(openrisc_pic_cpu_handler, env, NR_IRQS);
> +
> +    for (i = 0; i < NR_IRQS; i++) {
> +        env->irq[i] = qi[i];
> +    }
> +}
> +
> +void cpu_openrisc_store_picmr(CPUOPENRISCState *env, uint32_t value)
> +{
> +    env->picmr |= value;
> +}
> +
> +void cpu_openrisc_store_picsr(CPUOPENRISCState *env, uint32_t value)
> +{
> +    env->picsr &= ~value;
> +}
> --
> 1.7.9.5
>
>
diff mbox

Patch

diff --git a/cpu-exec.c b/cpu-exec.c
index ba10db1..845b2ae 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -375,6 +375,23 @@  int cpu_exec(CPUArchState *env)
                         do_interrupt(env);
                         next_tb = 0;
                     }
+#elif defined(TARGET_OPENRISC)
+                    {
+                        int idx = -1;
+                        if ((interrupt_request & CPU_INTERRUPT_HARD)
+                            && (env->sr & SR_IEE)) {
+                            idx = EXCP_INT;
+                        }
+                        if ((interrupt_request & CPU_INTERRUPT_TIMER)
+                            && (env->sr & SR_TEE)) {
+                            idx = EXCP_TICK;
+                        }
+                        if (idx >= 0) {
+                            env->exception_index = idx;
+                            do_interrupt(env);
+                            next_tb = 0;
+                        }
+                    }
 #elif defined(TARGET_SPARC)
                     if (interrupt_request & CPU_INTERRUPT_HARD) {
                         if (cpu_interrupts_enabled(env) &&
diff --git a/hw/openrisc_pic.c b/hw/openrisc_pic.c
index 0abdd50..52e48ec 100644
--- a/hw/openrisc_pic.c
+++ b/hw/openrisc_pic.c
@@ -29,3 +29,51 @@  void cpu_openrisc_pic_reset(CPUOPENRISCState *env)
     env->picmr = 0x00000000;
     env->picsr = 0x00000000;
 }
+
+/* openrisc pic handler */
+static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
+{
+    CPUOPENRISCState *env = (CPUOPENRISCState *)opaque;
+    int i;
+    uint32_t irq_bit = 1 << irq;
+
+    if (irq > 31 || irq < 0) {
+        return;
+    }
+
+    if (level) {
+        env->picsr |= irq_bit;
+    } else {
+        env->picsr &= ~irq_bit;
+    }
+
+    for (i = 0; i < 32; i++) {
+        if ((env->picsr && (1 << i)) && (env->picmr && (1 << i))) {
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        } else {
+            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+            env->picsr &= ~(1 << i);
+        }
+    }
+}
+
+void cpu_openrisc_pic_init(CPUOPENRISCState *env)
+{
+    int i;
+    qemu_irq *qi;
+    qi = qemu_allocate_irqs(openrisc_pic_cpu_handler, env, NR_IRQS);
+
+    for (i = 0; i < NR_IRQS; i++) {
+        env->irq[i] = qi[i];
+    }
+}
+
+void cpu_openrisc_store_picmr(CPUOPENRISCState *env, uint32_t value)
+{
+    env->picmr |= value;
+}
+
+void cpu_openrisc_store_picsr(CPUOPENRISCState *env, uint32_t value)
+{
+    env->picsr &= ~value;
+}