All of lore.kernel.org
 help / color / mirror / Atom feed
From: Xiaojuan Yang <yangxiaojuan@loongson.cn>
To: qemu-devel@nongnu.org
Cc: peter.maydell@linaro.org, thuth@redhat.com,
	chenhuacai@loongson.cn, mst@redhat.com, philmd@redhat.com,
	richard.henderson@linaro.org, laurent@vivier.eu,
	peterx@redhat.com, f4bug@amsat.org, yangxiaojuan@loongson.cn,
	alistair.francis@wdc.com, maobibo@loongson.cn,
	gaosong@loongson.cn, pbonzini@redhat.com,
	mark.cave-ayland@ilande.co.uk, bmeng.cn@gmail.com,
	alex.bennee@linaro.org, david@gibson.dropbear.id.au
Subject: [PATCH 17/31] hw/intc: Add loongarch ls7a interrupt controller support(PCH-PIC)
Date: Tue, 19 Oct 2021 15:35:03 +0800	[thread overview]
Message-ID: <1634628917-10031-18-git-send-email-yangxiaojuan@loongson.cn> (raw)
In-Reply-To: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn>

This patch realize the PCH-PIC interrupt controller.

Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 hw/intc/Kconfig                     |   4 +
 hw/intc/loongarch_pch_pic.c         | 284 ++++++++++++++++++++++++++++
 hw/intc/meson.build                 |   1 +
 hw/loongarch/Kconfig                |   1 +
 include/hw/intc/loongarch_pch_pic.h |  50 +++++
 5 files changed, 340 insertions(+)
 create mode 100644 hw/intc/loongarch_pch_pic.c
 create mode 100644 include/hw/intc/loongarch_pch_pic.h

diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index 78aed93c45..3b7eca7b03 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -73,3 +73,7 @@ config GOLDFISH_PIC
 
 config M68K_IRQC
     bool
+
+config LOONGARCH_PCH_PIC
+    bool
+    select UNIMP
diff --git a/hw/intc/loongarch_pch_pic.c b/hw/intc/loongarch_pch_pic.c
new file mode 100644
index 0000000000..9d0673b98a
--- /dev/null
+++ b/hw/intc/loongarch_pch_pic.c
@@ -0,0 +1,284 @@
+/*
+ * QEMU Loongson 7A1000 I/O interrupt controller.
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "hw/intc/loongarch_pch_pic.h"
+#include "migration/vmstate.h"
+
+#define DEBUG_LOONGARCH_PCH_PIC 0
+
+#define DPRINTF(fmt, ...) \
+do { \
+    if (DEBUG_LOONGARCH_PCH_PIC) { \
+        fprintf(stderr, "LOONGARCH_PCH_PIC: " fmt , ## __VA_ARGS__); \
+    } \
+} while (0)
+
+ #define for_each_set_bit(bit, addr, size) \
+         for ((bit) = find_first_bit((addr), (size));            \
+              (bit) < (size);                                    \
+              (bit) = find_next_bit((addr), (size), (bit) + 1))
+
+static void update_irq(loongarch_pch_pic *s, int mask, int level)
+{
+    int i;
+    uint64_t val;
+    val = mask & s->intirr & (~s->int_mask);
+
+    for_each_set_bit(i, &val, 32) {
+        if (level == 1) {
+            if ((s->intisr & (0x1ULL << i)) == 0) {
+                s->intisr |= 1ULL << i;
+                qemu_set_irq(s->parent_irq[s->htmsi_vector[i]], 1);
+            }
+        } else if (level == 0) {
+            if (s->intisr & (0x1ULL << i)) {
+                s->intisr &= ~(0x1ULL << i);
+                qemu_set_irq(s->parent_irq[s->htmsi_vector[i]], 0);
+            }
+        }
+    }
+}
+
+static void irq_handler(void *opaque, int irq, int level)
+{
+    loongarch_pch_pic *s = opaque;
+
+    assert(irq < 32);
+    uint32_t mask = 1ULL << irq;
+    DPRINTF("------ %s irq %d %d\n", __func__, irq, level);
+
+    if (s->intedge & mask) {
+        /* edge triggered */
+        if (level) {
+            if ((s->last_intirr & mask) == 0) {
+                s->intirr |= mask;
+            }
+            s->last_intirr |= mask;
+        } else {
+            s->last_intirr &= ~mask;
+        }
+    } else {
+        /* level triggered */
+        if (level) {
+            s->intirr |= mask;
+            s->last_intirr |= mask;
+        } else {
+            s->intirr &= ~mask;
+            s->last_intirr &= ~mask;
+        }
+
+    }
+    update_irq(s, mask, level);
+}
+
+static uint64_t loongarch_pch_pic_reg_read(void *opaque, hwaddr addr,
+                                           unsigned size)
+{
+    loongarch_pch_pic *s = opaque;
+    uint32_t val = 0;
+    uint32_t offset;
+    int32_t offset_tmp;
+    offset = addr & 0xfff;
+    if (4 == size) {
+        switch (offset) {
+        case PCH_PIC_INT_ID_OFFSET:
+            val = PCH_PIC_INT_ID_VAL;
+            break;
+        case PCH_PIC_INT_MASK_OFFSET:
+            val = s->int_mask;
+            break;
+        case PCH_PIC_INT_STATUS_OFFSET:
+            val = s->intisr & (~s->int_mask);
+            break;
+        case PCH_PIC_INT_EDGE_OFFSET:
+            val = s->intedge;
+            break;
+        case PCH_PIC_INT_POL_OFFSET:
+            val = s->int_polarity;
+            break;
+        case PCH_PIC_HTMSI_EN_OFFSET:
+            val = s->htmsi_en;
+            break;
+        case PCH_PIC_AUTO_CTRL0_OFFSET:
+        case PCH_PIC_AUTO_CTRL1_OFFSET:
+            break;
+        default:
+            break;
+        }
+    } else if (1 == size) {
+        if (offset >= PCH_PIC_HTMSI_VEC_OFFSET) {
+            offset_tmp = offset - PCH_PIC_HTMSI_VEC_OFFSET;
+            if (offset_tmp >= 0 && offset_tmp < 32) {
+                val = s->htmsi_vector[offset_tmp];
+            }
+        } else if (offset >=  PCH_PIC_ROUTE_ENTRY_OFFSET) {
+            offset_tmp = offset - PCH_PIC_ROUTE_ENTRY_OFFSET;
+            if (offset_tmp >= 0 && offset_tmp < 32) {
+                val = s->route_entry[offset_tmp];
+            }
+        }
+    }
+
+    return val;
+}
+
+static void loongarch_pch_pic_reg_write(void *opaque, hwaddr addr,
+                                        uint64_t data, unsigned size)
+{
+    loongarch_pch_pic *s = opaque;
+    int32_t offset_tmp;
+    uint32_t offset, old;
+    offset = addr & 0xfff;
+
+    if (4 == size) {
+        switch (offset) {
+        case PCH_PIC_INT_MASK_OFFSET:
+            old = s->int_mask;
+            s->int_mask = data;
+            if (old & ~data) {
+                update_irq(s, (old & ~data), 1);
+            } else if (~old & data) {
+                update_irq(s, (~old & data), 0);
+            }
+            break;
+        case PCH_PIC_INT_STATUS_OFFSET:
+            s->intisr = data;
+            break;
+        case PCH_PIC_INT_EDGE_OFFSET:
+            s->intedge = data;
+            break;
+        case PCH_PIC_INT_CLEAR_OFFSET:
+            s->intirr &= (~(data & s->intedge));
+            update_irq(s, data, 0);
+            s->intisr &= (~data);
+            break;
+        case PCH_PIC_INT_POL_OFFSET:
+            s->int_polarity = data;
+            break;
+        case PCH_PIC_HTMSI_EN_OFFSET:
+            s->htmsi_en = data;
+            break;
+        case PCH_PIC_AUTO_CTRL0_OFFSET:
+        case PCH_PIC_AUTO_CTRL1_OFFSET:
+            break;
+        default:
+            break;
+        }
+    } else if (1 == size) {
+        if (offset >= PCH_PIC_HTMSI_VEC_OFFSET) {
+            offset_tmp = offset - PCH_PIC_HTMSI_VEC_OFFSET;
+            if (offset_tmp >= 0 && offset_tmp < 32) {
+                s->htmsi_vector[offset_tmp] = (uint8_t)(data & 0xff);
+            }
+        } else if (offset >=  PCH_PIC_ROUTE_ENTRY_OFFSET) {
+            offset_tmp = offset - PCH_PIC_ROUTE_ENTRY_OFFSET;
+            if (offset_tmp >= 0 && offset_tmp < 32) {
+                s->route_entry[offset_tmp] = (uint8_t)(data & 0xff);
+            }
+        }
+    }
+}
+
+static const MemoryRegionOps loongarch_pch_pic_ops = {
+    .read = loongarch_pch_pic_reg_read,
+    .write = loongarch_pch_pic_reg_write,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 8,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void loongarch_pch_pic_reset(DeviceState *d)
+{
+    loongarch_pch_pic *s = LOONGARCH_PCH_PIC(d);
+    int i;
+
+    s->int_id   = 0x0;
+    s->int_mask = 0xffffffff;
+    s->htmsi_en = 0x0;
+    s->intedge  = 0x0;
+    s->intclr   = 0x0;
+    s->auto_crtl0 = 0x0;
+    s->auto_crtl1 = 0x0;
+    for (i = 0; i < 32; i++) {
+        s->route_entry[i] = 0x1;
+        s->htmsi_vector[i] = 0x0;
+    }
+    s->intirr = 0x0;
+    s->intisr = 0x0;
+    s->last_intirr = 0x0;
+    s->int_polarity = 0x0;
+}
+
+static void loongarch_pch_pic_init(Object *obj)
+{
+    loongarch_pch_pic *s = LOONGARCH_PCH_PIC(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    int tmp;
+
+    memory_region_init_io(&s->iomem, obj, &loongarch_pch_pic_ops,
+                          s, TYPE_LOONGARCH_PCH_PIC, 0x1000);
+    sysbus_init_mmio(sbd, &s->iomem);
+
+    for (tmp = 0; tmp < 32; tmp++) {
+        sysbus_init_irq(sbd, &s->parent_irq[tmp]);
+    }
+    qdev_init_gpio_in(DEVICE(obj), irq_handler, 32);
+}
+
+static const VMStateDescription vmstate_loongarch_pch_pic = {
+    .name = TYPE_LOONGARCH_PCH_PIC,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(int_mask, loongarch_pch_pic),
+        VMSTATE_UINT32(htmsi_en, loongarch_pch_pic),
+        VMSTATE_UINT32(intedge, loongarch_pch_pic),
+        VMSTATE_UINT32(intclr, loongarch_pch_pic),
+        VMSTATE_UINT32(auto_crtl0, loongarch_pch_pic),
+        VMSTATE_UINT32(auto_crtl1, loongarch_pch_pic),
+        VMSTATE_UINT8_ARRAY(route_entry, loongarch_pch_pic, 32),
+        VMSTATE_UINT8_ARRAY(htmsi_vector, loongarch_pch_pic, 32),
+        VMSTATE_UINT32(last_intirr, loongarch_pch_pic),
+        VMSTATE_UINT32(intirr, loongarch_pch_pic),
+        VMSTATE_UINT32(intisr, loongarch_pch_pic),
+        VMSTATE_UINT32(int_polarity, loongarch_pch_pic),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void loongarch_pch_pic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->reset = loongarch_pch_pic_reset;
+    dc->vmsd = &vmstate_loongarch_pch_pic;
+}
+
+static const TypeInfo loongarch_pch_pic_info = {
+    .name          = TYPE_LOONGARCH_PCH_PIC,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(loongarch_pch_pic),
+    .instance_init = loongarch_pch_pic_init,
+    .class_init    = loongarch_pch_pic_class_init,
+};
+
+static void loongarch_pch_pic_register_types(void)
+{
+    type_register_static(&loongarch_pch_pic_info);
+}
+
+type_init(loongarch_pch_pic_register_types)
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index a1d00aa48d..c61f171d5c 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -58,3 +58,4 @@ specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XIVE'],
 		if_true: files('spapr_xive_kvm.c'))
 specific_ss.add(when: 'CONFIG_GOLDFISH_PIC', if_true: files('goldfish_pic.c'))
 specific_ss.add(when: 'CONFIG_M68K_IRQC', if_true: files('m68k_irqc.c'))
+specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC', if_true: files('loongarch_pch_pic.c'))
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index 720822f32c..c6d7ebcd5b 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -1,3 +1,4 @@
 config LOONGSON_3A5000
     bool
     select PCI_EXPRESS_7A
+    select LOONGARCH_PCH_PIC
diff --git a/include/hw/intc/loongarch_pch_pic.h b/include/hw/intc/loongarch_pch_pic.h
new file mode 100644
index 0000000000..f85606de78
--- /dev/null
+++ b/include/hw/intc/loongarch_pch_pic.h
@@ -0,0 +1,50 @@
+/*
+ * Loongarch 7A1000 I/O interrupt controller definitions
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#define TYPE_LOONGARCH_PCH_PIC "loongarch_pch_pic"
+DECLARE_INSTANCE_CHECKER(struct loongarch_pch_pic, LOONGARCH_PCH_PIC,
+                         TYPE_LOONGARCH_PCH_PIC)
+
+#define PCH_PIC_ROUTE_ENTRY_OFFSET      0x100
+#define PCH_PIC_INT_ID_OFFSET           0x00
+#define PCH_PIC_INT_ID_VAL              0x7000000UL
+#define PCH_PIC_INT_ID_VER              0x1f0001UL
+#define PCH_PIC_INT_MASK_OFFSET         0x20
+#define PCH_PIC_INT_EDGE_OFFSET         0x60
+#define PCH_PIC_INT_CLEAR_OFFSET        0x80
+#define PCH_PIC_INT_STATUS_OFFSET       0x3a0
+#define PCH_PIC_INT_POL_OFFSET          0x3e0
+#define PCH_PIC_HTMSI_EN_OFFSET         0x40
+#define PCH_PIC_HTMSI_VEC_OFFSET        0x200
+#define PCH_PIC_AUTO_CTRL0_OFFSET       0xc0
+#define PCH_PIC_AUTO_CTRL1_OFFSET       0xe0
+
+typedef struct loongarch_pch_pic {
+    SysBusDevice parent_obj;
+    qemu_irq parent_irq[32];
+    uint32_t int_id;
+    uint32_t int_mask; /*0x020 interrupt mask register*/
+    uint32_t htmsi_en;/*0x040 1=msi*/
+    uint32_t intedge; /*0x060 edge=1 level  =0*/
+    uint32_t intclr; /*0x080 for clean edge int,set 1 clean,set 0 is noused*/
+    uint32_t auto_crtl0; /*0x0c0*/
+    uint32_t auto_crtl1; /*0x0e0*/
+    uint8_t route_entry[32]; /*0x100 - 0x120*/
+    uint8_t htmsi_vector[32]; /*0x200 - 0x220*/
+    uint32_t last_intirr;    /* edge detection */
+    uint32_t intirr; /* 0x380 interrupt request register */
+    uint32_t intisr; /* 0x3a0 interrupt service register */
+    /*
+     * 0x3e0 interrupt level polarity selection
+     * register 0 for high level trigger
+     */
+    uint32_t int_polarity;
+    MemoryRegion iomem;
+} loongarch_pch_pic;
+
+
-- 
2.27.0



  parent reply	other threads:[~2021-10-19  7:43 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-19  7:34 [PATCH 00/31] Add Loongarch softmmu support Xiaojuan Yang
2021-10-19  7:34 ` [PATCH 02/31] target/loongarch: Add CSR registers definition Xiaojuan Yang
2021-10-19 19:10   ` Richard Henderson
2021-10-19  7:34 ` [PATCH 03/31] target/loongarch: Set default csr values Xiaojuan Yang
2021-10-19 19:18   ` Richard Henderson
2021-10-19  7:34 ` [PATCH 04/31] target/loongarch: Add basic vmstate description of CPU Xiaojuan Yang
2021-10-19 19:35   ` Richard Henderson
2021-10-19  7:34 ` [PATCH 05/31] target/loongarch: Implement qmp_query_cpu_definitions() Xiaojuan Yang
2021-10-19 20:25   ` Richard Henderson
2021-10-19  7:34 ` [PATCH 08/31] target/loongarch: Add tlb instruction support Xiaojuan Yang
2021-10-20  4:19   ` Richard Henderson
2021-10-29  7:01     ` yangxiaojuan
2021-10-29 17:48       ` Richard Henderson
2021-10-19  7:34 ` [PATCH 09/31] target/loongarch: Add other core instructions support Xiaojuan Yang
2021-10-20  4:45   ` Richard Henderson
2021-10-19  7:34 ` [PATCH 10/31] target/loongarch: Add loongarch interrupt and exception handle Xiaojuan Yang
2021-10-20  4:59   ` Richard Henderson
2021-10-19  7:34 ` [PATCH 11/31] target/loongarch: Add stabletimer support Xiaojuan Yang
2021-10-19  7:34 ` [PATCH 12/31] target/loongarch: Add timer related instructions support Xiaojuan Yang
2021-10-20  5:17   ` Richard Henderson
2021-10-19  7:34 ` [PATCH 13/31] hw/pci-host: Add ls7a1000 PCIe Host bridge support for Loongson Platform Xiaojuan Yang
2021-10-19  7:35 ` [PATCH 14/31] hw/loongarch: Add a virt loongarch 3A5000 board support Xiaojuan Yang
2021-10-19  7:35 ` [PATCH 15/31] hw/loongarch: Add loongarch cpu interrupt support(CPUINTC) Xiaojuan Yang
2021-10-19  7:35 ` [PATCH 16/31] hw/loongarch: Add loongarch ipi interrupt support(IPI) Xiaojuan Yang
2021-10-19  7:35 ` Xiaojuan Yang [this message]
2021-10-19  7:35 ` [PATCH 18/31] hw/intc: Add loongarch ls7a msi interrupt controller support(PCH-MSI) Xiaojuan Yang
2021-10-19  7:35 ` [PATCH 19/31] hw/intc: Add loongarch extioi interrupt controller(EIOINTC) Xiaojuan Yang
2021-10-19  7:35 ` [PATCH 20/31] hw/loongarch: Add irq hierarchy for the system Xiaojuan Yang
2021-10-19 14:52 ` [PATCH 00/31] Add Loongarch softmmu support WANG Xuerui
     [not found]   ` <7d933f8d.228e.17c9b556e98.Coremail.yangxiaojuan@loongson.cn>
2021-10-20  5:11     ` WANG Xuerui
     [not found] ` <1634628917-10031-24-git-send-email-yangxiaojuan@loongson.cn>
2021-10-19 16:19   ` [PATCH 23/31] hw/loongarch: Add default bios startup support Michael S. Tsirkin
     [not found] ` <1634628917-10031-2-git-send-email-yangxiaojuan@loongson.cn>
2021-10-19 18:56   ` [PATCH 01/31] target/loongarch: Upate the README for the softmmu Richard Henderson
2021-10-22  2:25     ` yangxiaojuan
     [not found] ` <1634628917-10031-7-git-send-email-yangxiaojuan@loongson.cn>
2021-10-19 21:11   ` [PATCH 06/31] target/loongarch: Add mmu support for Loongarch CPU Richard Henderson
     [not found] ` <1634628917-10031-8-git-send-email-yangxiaojuan@loongson.cn>
2021-10-20  1:36   ` [PATCH 07/31] target/loongarch: Add loongarch csr/iocsr instruction support Richard Henderson
2021-10-29  6:26     ` yangxiaojuan
2021-10-29 17:38       ` Richard Henderson

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=1634628917-10031-18-git-send-email-yangxiaojuan@loongson.cn \
    --to=yangxiaojuan@loongson.cn \
    --cc=alex.bennee@linaro.org \
    --cc=alistair.francis@wdc.com \
    --cc=bmeng.cn@gmail.com \
    --cc=chenhuacai@loongson.cn \
    --cc=david@gibson.dropbear.id.au \
    --cc=f4bug@amsat.org \
    --cc=gaosong@loongson.cn \
    --cc=laurent@vivier.eu \
    --cc=maobibo@loongson.cn \
    --cc=mark.cave-ayland@ilande.co.uk \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=peterx@redhat.com \
    --cc=philmd@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=richard.henderson@linaro.org \
    --cc=thuth@redhat.com \
    /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.