From nobody Tue Feb 10 10:20:44 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1654559561; cv=none; d=zohomail.com; s=zohoarc; b=gXp7uTV2fHhE5JQ2RdarImfqZB37mTVilFhy1Hj+M2Tq/RAWaYw3J6BAqrymuZUdO9HYRjQjhr/OTW2esffaj10+M4tkhuQDwC/iueqpBm/tDYQ7GPZ5emylONtd49d4C3VtUbEw4kHTlmsHRYrZ8KUacpnIqv0lY08j9X7IK54= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1654559561; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=b5V5pYO+6MUJ7L6aoacvRRREv3hSsylQIq3DfoufEcA=; b=O0LnKyYNROwerdjojosjluctUC3rzzBDUvqtwMsZYS+3pxKhoeE3sqEixrQLF+Cu0sprhlo0C+7OeL+L2nmirNaNscTpyP2uXaIkC+zV711rYOSJVaBrKma2xQ9J1v0ECi3uu/qz9tKYa6nUaX4hMjS9cdNNbaSut7IHpUc6qxc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1654559561950495.96501264531753; Mon, 6 Jun 2022 16:52:41 -0700 (PDT) Received: from localhost ([::1]:44844 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nyMWW-0003MG-SO for importer@patchew.org; Mon, 06 Jun 2022 19:52:40 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35254) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nyLwV-0001lY-PM for qemu-devel@nongnu.org; Mon, 06 Jun 2022 19:15:33 -0400 Received: from mail-pj1-x102a.google.com ([2607:f8b0:4864:20::102a]:35530) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1nyLwR-0003jU-KZ for qemu-devel@nongnu.org; Mon, 06 Jun 2022 19:15:27 -0400 Received: by mail-pj1-x102a.google.com with SMTP id o6-20020a17090a0a0600b001e2c6566046so19216767pjo.0 for ; Mon, 06 Jun 2022 16:15:22 -0700 (PDT) Received: from stoup.. ([2602:ae:1547:e101:dd1c:9738:3e40:ffe0]) by smtp.gmail.com with ESMTPSA id 2-20020a170902c24200b00162523fdb8fsm10954623plg.252.2022.06.06.16.15.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Jun 2022 16:15:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=b5V5pYO+6MUJ7L6aoacvRRREv3hSsylQIq3DfoufEcA=; b=XHjZsyaRgvDSKead0O/4GUqJ7MRrpYQk/7fyCrq0k4EIhM4Yuxq32mR349d8o6v55n F8r9SD+mR39fK2AkVUhVKu7YUa5KCjsGNyyxlI1UW786DGHCmOHxUj5XU/Cq4zUUN0KA 21EhGzv+W4Rlx3jQJbOIR0PJiqOpwcnZHMfhdoLSChIVy6tlFmW5oIwMNOI1T5MuPraK s4L8N552EJbMht8czjPjhJ4+AZIPvxxbiAt3b3lFldX0rItq/qxs/Ld7mcArr0z+OC0T oGt0wbjzjYQyqA+s8yE+VMsmhNrLzNT1V6PptBH+8I6OoSGJMXXnlqySiO3Dbi+amBtw KSHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=b5V5pYO+6MUJ7L6aoacvRRREv3hSsylQIq3DfoufEcA=; b=QDUNn9E8wgcm1b8NlzRn+s26vUrGu3d/PovpbNJlqfMPWuALSVpl2njtOuSrJJ9gdA 75ICO02dF58KMYVGlhcdfYvhG6GHVQ8GLhHsNYsT4nVVbxUoU9yvY7m2nvsKZItikGzg dT/4LR8+QIarPi0GkJaynGAVG/tOCdfH8oFueWaPA+GcunDMdGKyQUR3v1EWhOn/SEov TnfdF43Jsv1YHidQfVUUEgC6nYJLMu/Txv5mtT7mqW1mjyiB6r5STRRcwnlrZcRNRTpk RGa2s4dKWDke2lRvNZYo+q2BggZ0HIxpdTn+vvD+ahF+Zhy61pj1n9j3qvtVxn4FIJZp JFnw== X-Gm-Message-State: AOAM533Aaqhq3VJ+pBZA6hAkwJ4GNKZLadsDRsev8zuSz7Xk7bY9Trqn BQIqJ2H770c7VAOP7fEPw7Q/6NMMu/Rr6g== X-Google-Smtp-Source: ABdhPJw6JPVxKeMteebK6BcwikUXuRmfduBnYRy0SWmO1WjKPGJPt5s/b9aapaqm18NcgbGlQ9DiWg== X-Received: by 2002:a17:902:724a:b0:167:9222:2755 with SMTP id c10-20020a170902724a00b0016792222755mr1162616pll.98.1654557322118; Mon, 06 Jun 2022 16:15:22 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Cc: =gaosong@loongson.cn, yangxiaojuan@loongson.cn, Song Gao Subject: [PULL 32/43] hw/intc: Add LoongArch ls7a interrupt controller support(PCH-PIC) Date: Mon, 6 Jun 2022 16:14:39 -0700 Message-Id: <20220606231450.448443-33-richard.henderson@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220606231450.448443-1-richard.henderson@linaro.org> References: <20220606231450.448443-1-richard.henderson@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::102a; envelope-from=richard.henderson@linaro.org; helo=mail-pj1-x102a.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1654559563774100001 Content-Type: text/plain; charset="utf-8" From: Xiaojuan Yang This patch realize the PCH-PIC interrupt controller. Signed-off-by: Xiaojuan Yang Signed-off-by: Song Gao Reviewed-by: Richard Henderson Message-Id: <20220606124333.2060567-33-yangxiaojuan@loongson.cn> Signed-off-by: Richard Henderson --- include/hw/intc/loongarch_pch_pic.h | 69 +++++ include/hw/pci-host/ls7a.h | 30 ++ hw/intc/loongarch_pch_pic.c | 431 ++++++++++++++++++++++++++++ MAINTAINERS | 1 + hw/intc/Kconfig | 4 + hw/intc/meson.build | 1 + hw/intc/trace-events | 9 + hw/loongarch/Kconfig | 1 + 8 files changed, 546 insertions(+) create mode 100644 include/hw/intc/loongarch_pch_pic.h create mode 100644 include/hw/pci-host/ls7a.h create mode 100644 hw/intc/loongarch_pch_pic.c diff --git a/include/hw/intc/loongarch_pch_pic.h b/include/hw/intc/loongarc= h_pch_pic.h new file mode 100644 index 0000000000..2d4aa9ed6f --- /dev/null +++ b/include/hw/intc/loongarch_pch_pic.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * LoongArch 7A1000 I/O interrupt controller definitions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + */ + +#define TYPE_LOONGARCH_PCH_PIC "loongarch_pch_pic" +#define PCH_PIC_NAME(name) TYPE_LOONGARCH_PCH_PIC#name +OBJECT_DECLARE_SIMPLE_TYPE(LoongArchPCHPIC, LOONGARCH_PCH_PIC) + +#define PCH_PIC_IRQ_START 0 +#define PCH_PIC_IRQ_END 63 +#define PCH_PIC_IRQ_NUM 64 +#define PCH_PIC_INT_ID_VAL 0x7000000UL +#define PCH_PIC_INT_ID_NUM 0x3f0001UL + +#define PCH_PIC_INT_ID_LO 0x00 +#define PCH_PIC_INT_ID_HI 0x04 +#define PCH_PIC_INT_MASK_LO 0x20 +#define PCH_PIC_INT_MASK_HI 0x24 +#define PCH_PIC_HTMSI_EN_LO 0x40 +#define PCH_PIC_HTMSI_EN_HI 0x44 +#define PCH_PIC_INT_EDGE_LO 0x60 +#define PCH_PIC_INT_EDGE_HI 0x64 +#define PCH_PIC_INT_CLEAR_LO 0x80 +#define PCH_PIC_INT_CLEAR_HI 0x84 +#define PCH_PIC_AUTO_CTRL0_LO 0xc0 +#define PCH_PIC_AUTO_CTRL0_HI 0xc4 +#define PCH_PIC_AUTO_CTRL1_LO 0xe0 +#define PCH_PIC_AUTO_CTRL1_HI 0xe4 +#define PCH_PIC_ROUTE_ENTRY_OFFSET 0x100 +#define PCH_PIC_ROUTE_ENTRY_END 0x13f +#define PCH_PIC_HTMSI_VEC_OFFSET 0x200 +#define PCH_PIC_HTMSI_VEC_END 0x23f +#define PCH_PIC_INT_STATUS_LO 0x3a0 +#define PCH_PIC_INT_STATUS_HI 0x3a4 +#define PCH_PIC_INT_POL_LO 0x3e0 +#define PCH_PIC_INT_POL_HI 0x3e4 + +#define STATUS_LO_START 0 +#define STATUS_HI_START 0x4 +#define POL_LO_START 0x40 +#define POL_HI_START 0x44 +struct LoongArchPCHPIC { + SysBusDevice parent_obj; + qemu_irq parent_irq[64]; + uint64_t int_mask; /*0x020 interrupt mask register*/ + uint64_t htmsi_en; /*0x040 1=3Dmsi*/ + uint64_t intedge; /*0x060 edge=3D1 level =3D0*/ + uint64_t intclr; /*0x080 for clean edge int,set 1 clean,set 0 is nouse= d*/ + uint64_t auto_crtl0; /*0x0c0*/ + uint64_t auto_crtl1; /*0x0e0*/ + uint64_t last_intirr; /* edge detection */ + uint64_t intirr; /* 0x380 interrupt request register */ + uint64_t intisr; /* 0x3a0 interrupt service register */ + /* + * 0x3e0 interrupt level polarity selection + * register 0 for high level trigger + */ + uint64_t int_polarity; + + uint8_t route_entry[64]; /*0x100 - 0x138*/ + uint8_t htmsi_vector[64]; /*0x200 - 0x238*/ + + MemoryRegion iomem32_low; + MemoryRegion iomem32_high; + MemoryRegion iomem8; +}; diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h new file mode 100644 index 0000000000..bf80e99ce1 --- /dev/null +++ b/include/hw/pci-host/ls7a.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * QEMU LoongArch CPU + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + */ + +#ifndef HW_LS7A_H +#define HW_LS7A_H + +#include "hw/pci/pci.h" +#include "hw/pci/pcie_host.h" +#include "hw/pci-host/pam.h" +#include "qemu/units.h" +#include "qemu/range.h" +#include "qom/object.h" + +#define LS7A_PCH_REG_BASE 0x10000000UL +#define LS7A_IOAPIC_REG_BASE (LS7A_PCH_REG_BASE) +#define LS7A_PCH_MSI_ADDR_LOW 0x2FF00000UL + +/* + * According to the kernel pch irq start from 64 offset + * 0 ~ 16 irqs used for non-pci device while 16 ~ 64 irqs + * used for pci device. + */ +#define PCH_PIC_IRQ_OFFSET 64 +#define LS7A_DEVICE_IRQS 16 +#define LS7A_PCI_IRQS 48 +#endif diff --git a/hw/intc/loongarch_pch_pic.c b/hw/intc/loongarch_pch_pic.c new file mode 100644 index 0000000000..3c9814a3b4 --- /dev/null +++ b/hw/intc/loongarch_pch_pic.c @@ -0,0 +1,431 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * QEMU Loongson 7A1000 I/O interrupt controller. + * + * Copyright (C) 2021 Loongson Technology Corporation Limited + */ + +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "hw/loongarch/virt.h" +#include "hw/irq.h" +#include "hw/intc/loongarch_pch_pic.h" +#include "migration/vmstate.h" +#include "trace.h" + +static void pch_pic_update_irq(LoongArchPCHPIC *s, uint64_t mask, int leve= l) +{ + unsigned long val; + int irq; + + if (level) { + val =3D mask & s->intirr & ~s->int_mask; + if (val) { + irq =3D find_first_bit(&val, 64); + s->intisr |=3D 0x1ULL << irq; + qemu_set_irq(s->parent_irq[s->htmsi_vector[irq]], 1); + } + } else { + val =3D mask & s->intisr; + if (val) { + irq =3D find_first_bit(&val, 64); + s->intisr &=3D ~(0x1ULL << irq); + qemu_set_irq(s->parent_irq[s->htmsi_vector[irq]], 0); + } + } +} + +static void pch_pic_irq_handler(void *opaque, int irq, int level) +{ + LoongArchPCHPIC *s =3D LOONGARCH_PCH_PIC(opaque); + uint64_t mask =3D 1ULL << irq; + + assert(irq < PCH_PIC_IRQ_NUM); + trace_loongarch_pch_pic_irq_handler(irq, level); + + if (s->intedge & mask) { + /* Edge triggered */ + if (level) { + if ((s->last_intirr & mask) =3D=3D 0) { + s->intirr |=3D mask; + } + s->last_intirr |=3D mask; + } else { + s->last_intirr &=3D ~mask; + } + } else { + /* Level triggered */ + if (level) { + s->intirr |=3D mask; + s->last_intirr |=3D mask; + } else { + s->intirr &=3D ~mask; + s->last_intirr &=3D ~mask; + } + } + pch_pic_update_irq(s, mask, level); +} + +static uint64_t loongarch_pch_pic_low_readw(void *opaque, hwaddr addr, + unsigned size) +{ + LoongArchPCHPIC *s =3D LOONGARCH_PCH_PIC(opaque); + uint64_t val =3D 0; + uint32_t offset =3D addr & 0xfff; + + switch (offset) { + case PCH_PIC_INT_ID_LO: + val =3D PCH_PIC_INT_ID_VAL; + break; + case PCH_PIC_INT_ID_HI: + val =3D PCH_PIC_INT_ID_NUM; + break; + case PCH_PIC_INT_MASK_LO: + val =3D (uint32_t)s->int_mask; + break; + case PCH_PIC_INT_MASK_HI: + val =3D s->int_mask >> 32; + break; + case PCH_PIC_INT_EDGE_LO: + val =3D (uint32_t)s->intedge; + break; + case PCH_PIC_INT_EDGE_HI: + val =3D s->intedge >> 32; + break; + case PCH_PIC_HTMSI_EN_LO: + val =3D (uint32_t)s->htmsi_en; + break; + case PCH_PIC_HTMSI_EN_HI: + val =3D s->htmsi_en >> 32; + break; + case PCH_PIC_AUTO_CTRL0_LO: + case PCH_PIC_AUTO_CTRL0_HI: + case PCH_PIC_AUTO_CTRL1_LO: + case PCH_PIC_AUTO_CTRL1_HI: + break; + default: + break; + } + + trace_loongarch_pch_pic_low_readw(size, addr, val); + return val; +} + +static uint64_t get_writew_val(uint64_t value, uint32_t target, bool hi) +{ + uint64_t mask =3D 0xffffffff00000000; + uint64_t data =3D target; + + return hi ? (value & ~mask) | (data << 32) : (value & mask) | data; +} + +static void loongarch_pch_pic_low_writew(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + LoongArchPCHPIC *s =3D LOONGARCH_PCH_PIC(opaque); + uint32_t offset, old_valid, data =3D (uint32_t)value; + uint64_t old, int_mask; + offset =3D addr & 0xfff; + + trace_loongarch_pch_pic_low_writew(size, addr, data); + + switch (offset) { + case PCH_PIC_INT_MASK_LO: + old =3D s->int_mask; + s->int_mask =3D get_writew_val(old, data, 0); + old_valid =3D (uint32_t)old; + if (old_valid & ~data) { + pch_pic_update_irq(s, (old_valid & ~data), 1); + } + if (~old_valid & data) { + pch_pic_update_irq(s, (~old_valid & data), 0); + } + break; + case PCH_PIC_INT_MASK_HI: + old =3D s->int_mask; + s->int_mask =3D get_writew_val(old, data, 1); + old_valid =3D (uint32_t)(old >> 32); + int_mask =3D old_valid & ~data; + if (int_mask) { + pch_pic_update_irq(s, int_mask << 32, 1); + } + int_mask =3D ~old_valid & data; + if (int_mask) { + pch_pic_update_irq(s, int_mask << 32, 0); + } + break; + case PCH_PIC_INT_EDGE_LO: + s->intedge =3D get_writew_val(s->intedge, data, 0); + break; + case PCH_PIC_INT_EDGE_HI: + s->intedge =3D get_writew_val(s->intedge, data, 1); + break; + case PCH_PIC_INT_CLEAR_LO: + if (s->intedge & data) { + s->intirr &=3D (~data); + pch_pic_update_irq(s, data, 0); + s->intisr &=3D (~data); + } + break; + case PCH_PIC_INT_CLEAR_HI: + value <<=3D 32; + if (s->intedge & value) { + s->intirr &=3D (~value); + pch_pic_update_irq(s, value, 0); + s->intisr &=3D (~value); + } + break; + case PCH_PIC_HTMSI_EN_LO: + s->htmsi_en =3D get_writew_val(s->htmsi_en, data, 0); + break; + case PCH_PIC_HTMSI_EN_HI: + s->htmsi_en =3D get_writew_val(s->htmsi_en, data, 1); + break; + case PCH_PIC_AUTO_CTRL0_LO: + case PCH_PIC_AUTO_CTRL0_HI: + case PCH_PIC_AUTO_CTRL1_LO: + case PCH_PIC_AUTO_CTRL1_HI: + break; + default: + break; + } +} + +static uint64_t loongarch_pch_pic_high_readw(void *opaque, hwaddr addr, + unsigned size) +{ + LoongArchPCHPIC *s =3D LOONGARCH_PCH_PIC(opaque); + uint64_t val =3D 0; + uint32_t offset =3D addr & 0xfff; + + switch (offset) { + case STATUS_LO_START: + val =3D (uint32_t)(s->intisr & (~s->int_mask)); + break; + case STATUS_HI_START: + val =3D (s->intisr & (~s->int_mask)) >> 32; + break; + case POL_LO_START: + val =3D (uint32_t)s->int_polarity; + break; + case POL_HI_START: + val =3D s->int_polarity >> 32; + break; + default: + break; + } + + trace_loongarch_pch_pic_high_readw(size, addr, val); + return val; +} + +static void loongarch_pch_pic_high_writew(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + LoongArchPCHPIC *s =3D LOONGARCH_PCH_PIC(opaque); + uint32_t offset, data =3D (uint32_t)value; + offset =3D addr & 0xfff; + + trace_loongarch_pch_pic_high_writew(size, addr, data); + + switch (offset) { + case STATUS_LO_START: + s->intisr =3D get_writew_val(s->intisr, data, 0); + break; + case STATUS_HI_START: + s->intisr =3D get_writew_val(s->intisr, data, 1); + break; + case POL_LO_START: + s->int_polarity =3D get_writew_val(s->int_polarity, data, 0); + break; + case POL_HI_START: + s->int_polarity =3D get_writew_val(s->int_polarity, data, 1); + break; + default: + break; + } +} + +static uint64_t loongarch_pch_pic_readb(void *opaque, hwaddr addr, + unsigned size) +{ + LoongArchPCHPIC *s =3D LOONGARCH_PCH_PIC(opaque); + uint64_t val =3D 0; + uint32_t offset =3D (addr & 0xfff) + PCH_PIC_ROUTE_ENTRY_OFFSET; + int64_t offset_tmp; + + switch (offset) { + case PCH_PIC_HTMSI_VEC_OFFSET ... PCH_PIC_HTMSI_VEC_END: + offset_tmp =3D offset - PCH_PIC_HTMSI_VEC_OFFSET; + if (offset_tmp >=3D 0 && offset_tmp < 64) { + val =3D s->htmsi_vector[offset_tmp]; + } + break; + case PCH_PIC_ROUTE_ENTRY_OFFSET ... PCH_PIC_ROUTE_ENTRY_END: + offset_tmp =3D offset - PCH_PIC_ROUTE_ENTRY_OFFSET; + if (offset_tmp >=3D 0 && offset_tmp < 64) { + val =3D s->route_entry[offset_tmp]; + } + break; + default: + break; + } + + trace_loongarch_pch_pic_readb(size, addr, val); + return val; +} + +static void loongarch_pch_pic_writeb(void *opaque, hwaddr addr, + uint64_t data, unsigned size) +{ + LoongArchPCHPIC *s =3D LOONGARCH_PCH_PIC(opaque); + int32_t offset_tmp; + uint32_t offset =3D (addr & 0xfff) + PCH_PIC_ROUTE_ENTRY_OFFSET; + + trace_loongarch_pch_pic_writeb(size, addr, data); + + switch (offset) { + case PCH_PIC_HTMSI_VEC_OFFSET ... PCH_PIC_HTMSI_VEC_END: + offset_tmp =3D offset - PCH_PIC_HTMSI_VEC_OFFSET; + if (offset_tmp >=3D 0 && offset_tmp < 64) { + s->htmsi_vector[offset_tmp] =3D (uint8_t)(data & 0xff); + } + break; + case PCH_PIC_ROUTE_ENTRY_OFFSET ... PCH_PIC_ROUTE_ENTRY_END: + offset_tmp =3D offset - PCH_PIC_ROUTE_ENTRY_OFFSET; + if (offset_tmp >=3D 0 && offset_tmp < 64) { + s->route_entry[offset_tmp] =3D (uint8_t)(data & 0xff); + } + break; + default: + break; + } +} + +static const MemoryRegionOps loongarch_pch_pic_reg32_low_ops =3D { + .read =3D loongarch_pch_pic_low_readw, + .write =3D loongarch_pch_pic_low_writew, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 8, + }, + .impl =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + }, + .endianness =3D DEVICE_LITTLE_ENDIAN, +}; + +static const MemoryRegionOps loongarch_pch_pic_reg32_high_ops =3D { + .read =3D loongarch_pch_pic_high_readw, + .write =3D loongarch_pch_pic_high_writew, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 8, + }, + .impl =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + }, + .endianness =3D DEVICE_LITTLE_ENDIAN, +}; + +static const MemoryRegionOps loongarch_pch_pic_reg8_ops =3D { + .read =3D loongarch_pch_pic_readb, + .write =3D loongarch_pch_pic_writeb, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 1, + }, + .impl =3D { + .min_access_size =3D 1, + .max_access_size =3D 1, + }, + .endianness =3D DEVICE_LITTLE_ENDIAN, +}; + +static void loongarch_pch_pic_reset(DeviceState *d) +{ + LoongArchPCHPIC *s =3D LOONGARCH_PCH_PIC(d); + int i; + + s->int_mask =3D -1; + s->htmsi_en =3D 0x0; + s->intedge =3D 0x0; + s->intclr =3D 0x0; + s->auto_crtl0 =3D 0x0; + s->auto_crtl1 =3D 0x0; + for (i =3D 0; i < 64; i++) { + s->route_entry[i] =3D 0x1; + s->htmsi_vector[i] =3D 0x0; + } + s->intirr =3D 0x0; + s->intisr =3D 0x0; + s->last_intirr =3D 0x0; + s->int_polarity =3D 0x0; +} + +static void loongarch_pch_pic_init(Object *obj) +{ + LoongArchPCHPIC *s =3D LOONGARCH_PCH_PIC(obj); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem32_low, obj, + &loongarch_pch_pic_reg32_low_ops, + s, PCH_PIC_NAME(.reg32_part1), 0x100); + memory_region_init_io(&s->iomem8, obj, &loongarch_pch_pic_reg8_ops, + s, PCH_PIC_NAME(.reg8), 0x2a0); + memory_region_init_io(&s->iomem32_high, obj, + &loongarch_pch_pic_reg32_high_ops, + s, PCH_PIC_NAME(.reg32_part2), 0xc60); + sysbus_init_mmio(sbd, &s->iomem32_low); + sysbus_init_mmio(sbd, &s->iomem8); + sysbus_init_mmio(sbd, &s->iomem32_high); + + qdev_init_gpio_out(DEVICE(obj), s->parent_irq, PCH_PIC_IRQ_NUM); + qdev_init_gpio_in(DEVICE(obj), pch_pic_irq_handler, PCH_PIC_IRQ_NUM); +} + +static const VMStateDescription vmstate_loongarch_pch_pic =3D { + .name =3D TYPE_LOONGARCH_PCH_PIC, + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_UINT64(int_mask, LoongArchPCHPIC), + VMSTATE_UINT64(htmsi_en, LoongArchPCHPIC), + VMSTATE_UINT64(intedge, LoongArchPCHPIC), + VMSTATE_UINT64(intclr, LoongArchPCHPIC), + VMSTATE_UINT64(auto_crtl0, LoongArchPCHPIC), + VMSTATE_UINT64(auto_crtl1, LoongArchPCHPIC), + VMSTATE_UINT8_ARRAY(route_entry, LoongArchPCHPIC, 64), + VMSTATE_UINT8_ARRAY(htmsi_vector, LoongArchPCHPIC, 64), + VMSTATE_UINT64(last_intirr, LoongArchPCHPIC), + VMSTATE_UINT64(intirr, LoongArchPCHPIC), + VMSTATE_UINT64(intisr, LoongArchPCHPIC), + VMSTATE_UINT64(int_polarity, LoongArchPCHPIC), + VMSTATE_END_OF_LIST() + } +}; + +static void loongarch_pch_pic_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->reset =3D loongarch_pch_pic_reset; + dc->vmsd =3D &vmstate_loongarch_pch_pic; +} + +static const TypeInfo loongarch_pch_pic_info =3D { + .name =3D TYPE_LOONGARCH_PCH_PIC, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(LoongArchPCHPIC), + .instance_init =3D loongarch_pch_pic_init, + .class_init =3D 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/MAINTAINERS b/MAINTAINERS index 271eb89e2a..3ce5674da5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1135,6 +1135,7 @@ F: hw/loongarch/ F: include/hw/loongarch/virt.h F: include/hw/intc/loongarch_*.h F: hw/intc/loongarch_*.c +F: include/hw/pci-host/ls7a.h =20 M68K Machines ------------- diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig index 1122c33cec..362980ca8c 100644 --- a/hw/intc/Kconfig +++ b/hw/intc/Kconfig @@ -90,3 +90,7 @@ config NIOS2_VIC =20 config LOONGARCH_IPI bool + +config LOONGARCH_PCH_PIC + bool + select UNIMP diff --git a/hw/intc/meson.build b/hw/intc/meson.build index 57af7fb33f..03f13f1c49 100644 --- a/hw/intc/meson.build +++ b/hw/intc/meson.build @@ -64,3 +64,4 @@ specific_ss.add(when: 'CONFIG_GOLDFISH_PIC', if_true: fil= es('goldfish_pic.c')) specific_ss.add(when: 'CONFIG_M68K_IRQC', if_true: files('m68k_irqc.c')) specific_ss.add(when: 'CONFIG_NIOS2_VIC', if_true: files('nios2_vic.c')) specific_ss.add(when: 'CONFIG_LOONGARCH_IPI', if_true: files('loongarch_ip= i.c')) +specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC', if_true: files('loongarc= h_pch_pic.c')) diff --git a/hw/intc/trace-events b/hw/intc/trace-events index 36774662af..4cdbc01a07 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -291,3 +291,12 @@ sh_intc_set(int id, int enable) "setting interrupt gro= up %d to %d" # loongarch_ipi.c loongarch_ipi_read(unsigned size, uint64_t addr, uint64_t val) "size: %u a= ddr: 0x%"PRIx64 "val: 0x%"PRIx64 loongarch_ipi_write(unsigned size, uint64_t addr, uint64_t val) "size: %u = addr: 0x%"PRIx64 "val: 0x%"PRIx64 + +# loongarch_pch_pic.c +loongarch_pch_pic_irq_handler(int irq, int level) "irq %d level %d" +loongarch_pch_pic_low_readw(unsigned size, uint64_t addr, uint64_t val) "s= ize: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64 +loongarch_pch_pic_low_writew(unsigned size, uint64_t addr, uint64_t val) "= size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64 +loongarch_pch_pic_high_readw(unsigned size, uint64_t addr, uint64_t val) "= size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64 +loongarch_pch_pic_high_writew(unsigned size, uint64_t addr, uint64_t val) = "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64 +loongarch_pch_pic_readb(unsigned size, uint64_t addr, uint64_t val) "size:= %u addr: 0x%"PRIx64 "val: 0x%" PRIx64 +loongarch_pch_pic_writeb(unsigned size, uint64_t addr, uint64_t val) "size= : %u addr: 0x%"PRIx64 "val: 0x%" PRIx64 diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig index f0dad3329a..2df45f7e8f 100644 --- a/hw/loongarch/Kconfig +++ b/hw/loongarch/Kconfig @@ -3,3 +3,4 @@ config LOONGARCH_VIRT select PCI select PCI_EXPRESS_GENERIC_BRIDGE select LOONGARCH_IPI + select LOONGARCH_PCH_PIC --=20 2.34.1