From: Vincent Sanders <vince@kyllikki.org>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 4/16] S3C irq controller
Date: Thu, 23 Apr 2009 18:52:46 +0100 [thread overview]
Message-ID: <20090423175246.GG4629@derik> (raw)
In-Reply-To: <20090423171503.GC4629@derik>
S3C IRQ controller
Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
s3c24xx_irq.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 200 insertions(+)
diff -urN qemusvnclean/hw/s3c24xx_irq.c qemusvnpatches/hw/s3c24xx_irq.c
--- qemusvnclean/hw/s3c24xx_irq.c 1970-01-01 01:00:00.000000000 +0100
+++ qemusvnpatches/hw/s3c24xx_irq.c 2009-04-23 16:00:07.000000000 +0100
@@ -0,0 +1,200 @@
+/* hw/s3c24xx_irq.c
+ *
+ * Samsung S3C24XX IRQ controller emulation
+ *
+ * Copyright 2006, 2007, 2008 Daniel Silverstone and Vincent Sanders
+ *
+ * This file is under the terms of the GNU General Public
+ * License Version 2
+ */
+
+#include "hw.h"
+
+#include "s3c24xx.h"
+
+/* IRQ request status RW WORD */
+#define S3C_IRQ_SRCPND 0
+/* Interrupt mode control WR WORD */
+#define S3C_IRQ_INTMOD 1
+/* Interrupt mask control RW WORD */
+#define S3C_IRQ_INTMSK 2
+/* IRQ priority control WR WORD */
+#define S3C_IRQ_PRIORITY 3
+/* Interrupt request status RW WORD */
+#define S3C_IRQ_INTPND 4
+/* Interrupt request source offset RO WORD */
+#define S3C_IRQ_OFFSET 5
+/* Sub-source pending RW WORD */
+#define S3C_IRQ_SUBSRCPND 6
+/* Interrupt sub-mask RW WORD */
+#define S3C_IRQ_INTSUBMSK 7
+
+
+static void
+s3c24xx_percolate_interrupt(S3CState *soc)
+{
+ /* Take the status of the srcpnd register, percolate it through, raise to
+ * CPU if necessary */
+ uint32_t ints = (soc->irq_reg[S3C_IRQ_SRCPND] &
+ ~soc->irq_reg[S3C_IRQ_INTMSK]);
+ int fsb = ffs(ints);
+
+ /* TODO: Priority encoder could go here */
+ if (ints & soc->irq_reg[S3C_IRQ_INTMOD]) {
+ /* Detected a FIQ */
+ cpu_interrupt(soc->cpu_env, CPU_INTERRUPT_FIQ);
+ return;
+ } else {
+ /* No FIQ here today */
+ cpu_reset_interrupt(soc->cpu_env, CPU_INTERRUPT_FIQ);
+ }
+
+ /* No FIQ, check for a normal IRQ */
+ if (fsb) {
+ if ((soc->irq_reg[S3C_IRQ_INTPND] == 0) ||
+ (soc->irq_reg[S3C_IRQ_INTPND] > 1<<(fsb-1))) {
+ /* Current INTPND is lower priority than fsb of ints (or empty) */
+ soc->irq_reg[S3C_IRQ_INTPND] = 1<<(fsb-1);
+ soc->irq_reg[S3C_IRQ_OFFSET] = fsb-1;
+ }
+ } else {
+ /* No FSB, thus no IRQ, thus nothing to do yet */
+ }
+
+ if (soc->irq_reg[S3C_IRQ_INTPND] != 0) {
+ cpu_interrupt(soc->cpu_env, CPU_INTERRUPT_HARD);
+ } else {
+ cpu_reset_interrupt(soc->cpu_env, CPU_INTERRUPT_HARD);
+ }
+}
+
+static void
+s3c24xx_percolate_subsrc_interrupt(S3CState *soc)
+{
+ uint32_t ints;
+
+ soc->irq_reg[S3C_IRQ_SRCPND] |= soc->irq_main_level;
+ soc->irq_reg[S3C_IRQ_SUBSRCPND] |= soc->irq_subsrc_level;
+
+ ints = (soc->irq_reg[S3C_IRQ_SUBSRCPND] &
+ ~soc->irq_reg[S3C_IRQ_INTSUBMSK]);
+
+ /* If UART0 has asserted, raise that */
+ if( ints & 0x7 ) {
+ soc->irq_reg[S3C_IRQ_SRCPND] |= (1<<28);
+ }
+
+ /* Ditto UART1 */
+ if( ints & 0x7<<3 ) soc->irq_reg[S3C_IRQ_SRCPND] |= (1<<23);
+
+ /* Ditto UART2 */
+ if( ints & 0x7<<6 ) soc->irq_reg[S3C_IRQ_SRCPND] |= (1<<15);
+
+ /* And percolate it through */
+ s3c24xx_percolate_interrupt(soc);
+}
+
+static void
+s3c24xx_irq_write_f(void *opaque, target_phys_addr_t addr_, uint32_t value)
+{
+ S3CState *soc = (S3CState *)opaque;
+ int addr = (addr_ >> 2) & 7;
+
+ if (addr == S3C_IRQ_SRCPND ||
+ addr == S3C_IRQ_INTPND ||
+ addr == S3C_IRQ_SUBSRCPND) {
+ soc->irq_reg[addr] &= ~value;
+ } else {
+ soc->irq_reg[addr] = value;
+ }
+
+ /* Start at the subsrc irqs and percolate from there */
+ s3c24xx_percolate_subsrc_interrupt(soc);
+}
+
+static uint32_t
+s3c24xx_irq_read_f(void *opaque, target_phys_addr_t addr_)
+{
+ S3CState *soc = (S3CState *)opaque;
+ int addr = (addr_ >> 2) & 0x7;
+
+ return soc->irq_reg[addr];
+}
+
+
+static CPUReadMemoryFunc *s3c24xx_irq_read[] = {
+ &s3c24xx_irq_read_f,
+ &s3c24xx_irq_read_f,
+ &s3c24xx_irq_read_f,
+};
+
+static CPUWriteMemoryFunc *s3c24xx_irq_write[] = {
+ &s3c24xx_irq_write_f,
+ &s3c24xx_irq_write_f,
+ &s3c24xx_irq_write_f,
+};
+
+static void
+s3c24xx_irq_set_interrupt_level(S3CState *soc, int irq_num, int level, int set_level)
+{
+ if (level) {
+ if (set_level) soc->irq_main_level |= 1<<irq_num;
+ soc->irq_reg[S3C_IRQ_SRCPND] |= 1<<irq_num;
+ } else {
+ soc->irq_main_level &= ~(1<<irq_num);
+ soc->irq_reg[S3C_IRQ_SRCPND] &= ~(1<<irq_num);
+ }
+ s3c24xx_percolate_subsrc_interrupt(soc);
+}
+
+static void
+s3c24xx_irq_set_subsrc_interrupt_level(S3CState *soc, int irq_num, int level, int set_level)
+{
+
+ if (level) {
+ if (set_level) soc->irq_subsrc_level |= 1<<irq_num;
+ soc->irq_reg[S3C_IRQ_SUBSRCPND] |= 1<<irq_num;
+ } else {
+ soc->irq_subsrc_level &= ~(1<<irq_num);
+ soc->irq_reg[S3C_IRQ_SUBSRCPND] &= ~(1<<irq_num);
+ }
+ s3c24xx_percolate_subsrc_interrupt(soc);
+}
+
+static void
+s3c24xx_irq_handler(void *opaque, int _n, int level)
+{
+ S3CState *soc = (S3CState *)opaque;
+ int irq_num = _n % 32;
+ int is_subsrc = (_n & 32)?1:0;
+ int is_level = (_n & 64)?1:0;
+
+ if (is_subsrc == 0)
+ s3c24xx_irq_set_interrupt_level(soc, irq_num, level, is_level);
+ else
+ s3c24xx_irq_set_subsrc_interrupt_level(soc, irq_num, level, is_level);
+}
+
+qemu_irq *
+s3c24xx_irq_init(S3CState *soc, target_phys_addr_t base_addr)
+{
+ /* Samsung S3C2410X IRQ registration. */
+ int tag = cpu_register_io_memory(0, s3c24xx_irq_read, s3c24xx_irq_write, soc);
+ cpu_register_physical_memory(base_addr, 8 * 4, tag);
+
+ /* Set up registers to power on values */
+ soc->irq_reg[S3C_IRQ_SRCPND] = 0x00;
+ soc->irq_reg[S3C_IRQ_INTMOD] = 0x00;
+ soc->irq_reg[S3C_IRQ_INTMSK] = 0xFFFFFFFF;
+ soc->irq_reg[S3C_IRQ_PRIORITY] = 0x7F;
+ soc->irq_reg[S3C_IRQ_INTPND] = 0x00;
+ soc->irq_reg[S3C_IRQ_OFFSET] = 0x00;
+ soc->irq_reg[S3C_IRQ_SUBSRCPND] = 0x00;
+ soc->irq_reg[S3C_IRQ_INTSUBMSK] = 0x7FF;
+
+ /* Allocate the interrupts and return them. All 64 potential ones.
+ * We return them doubled up because the latter half are level where
+ * the former half are edge.
+ */
+ return qemu_allocate_irqs(s3c24xx_irq_handler, soc, 128);
+}
--
Regards Vincent
http://www.kyllikki.org/
next prev parent reply other threads:[~2009-04-23 17:52 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-04-23 17:15 [Qemu-devel] [PATCH 0/16] ARM Add S3C SOC core, drivers and boards Vincent Sanders
2009-04-23 17:45 ` [Qemu-devel] [PATCH 1/16] ARM Add ARM 920T identifiers Vincent Sanders
2009-04-30 16:08 ` Paul Brook
2009-05-23 16:50 ` Vincent Sanders
2009-05-24 18:31 ` Paul Brook
2009-05-26 9:39 ` Vincent Sanders
2009-05-26 9:42 ` Laurent Desnogues
2009-05-26 9:56 ` Jamie Lokier
2009-05-26 10:08 ` Laurent Desnogues
2009-05-26 11:29 ` Jamie Lokier
2009-05-26 11:46 ` Laurent Desnogues
2009-05-26 10:16 ` Paul Brook
2009-05-26 11:18 ` Vincent Sanders
2009-04-23 17:48 ` [Qemu-devel] [PATCH 2/16] Add s3c SOC header Vincent Sanders
2009-04-23 17:50 ` [Qemu-devel] [PATCH 3/16] S3C SDRAM memory controller Peripheral Vincent Sanders
2009-04-23 17:52 ` Vincent Sanders [this message]
2009-04-23 17:58 ` [Qemu-devel] [PATCH 05/16] S3C Clock controller peripheral Vincent Sanders
2009-04-23 18:00 ` [Qemu-devel] [PATCH 7/16] S3C serial peripheral Vincent Sanders
2009-04-23 18:02 ` [Qemu-devel] [PATCH 6/16] S3C Timers Vincent Sanders
2009-04-23 18:04 ` [Qemu-devel] [PATCH 8/16] S3C Real Time Clock Vincent Sanders
2009-04-23 18:05 ` [Qemu-devel] [PATCH 9/16] S3C General Purpose IO Vincent Sanders
2009-04-23 18:07 ` [Qemu-devel] [PATCH 10/16] S3C I2C peripheral Vincent Sanders
2009-04-23 18:08 ` [Qemu-devel] [PATCH 11/16] S3C LCD display Vincent Sanders
2009-04-23 18:09 ` [Qemu-devel] [PATCH 12/16] S3C NAND controller Vincent Sanders
2009-04-23 18:11 ` [Qemu-devel] [PATCH 13/16] S3C2410 SOC implementation Vincent Sanders
2009-04-23 18:14 ` [Qemu-devel] [PATCH 14/16] S3C2440 SOC impementation Vincent Sanders
2009-04-23 18:15 ` [Qemu-devel] [PATCH 15/16] Add S3C SOC files to Makefile Vincent Sanders
2009-04-23 18:17 ` [Qemu-devel] [PATCH 16/16] Add two boards which use S3C2410 SOC Vincent Sanders
2009-04-25 12:44 ` Jean-Christophe PLAGNIOL-VILLARD
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090423175246.GG4629@derik \
--to=vince@kyllikki.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.