From nobody Wed Nov 27 02:39:56 2024 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1702002798; cv=none; d=zohomail.com; s=zohoarc; b=KI8auJmXn1JX4pVeYR6VYuJh4zGL4Gp8Rq2m9JUVSDUuHPQiqha2sN1HuNCXmzsb+DX+e6AVPjovEiWYsn/N74cm/U+VBW0tZ5L5+IDSmhsgl3GIw9cftIse0b00JZvjw55jwrWjINRJ9E0JoMcbjSG1wVz8Myg/7LX4awDgEOc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1702002798; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=IA89nY8jxlWQU5cEQQofnym1Upjf0MuK6dyCKlAlClw=; b=SrbDOzduDJGvIuzzScfzZXzt5lTEn9VuWytZoHgtLQS6yaaeJlRWg5XbMHMzidf/u+Kq6FZ68TvrZ+ekYEhAeT7RMINOJZw1cemzOT6zvp+vab0NMDoTEwXE63pbC9azHYT6zmhoUol036q77f6FYe7ZX2kZpHgSRkVxFw7Wr14= 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 1702002798714190.46547927104825; Thu, 7 Dec 2023 18:33:18 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rBQff-0004M0-2z; Thu, 07 Dec 2023 21:32:55 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBQfY-0004F4-JG; Thu, 07 Dec 2023 21:32:48 -0500 Received: from mail-lf1-x133.google.com ([2a00:1450:4864:20::133]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rBQfW-0002Vn-G7; Thu, 07 Dec 2023 21:32:48 -0500 Received: by mail-lf1-x133.google.com with SMTP id 2adb3069b0e04-50bf82f4409so1470501e87.0; Thu, 07 Dec 2023 18:32:45 -0800 (PST) Received: from localhost.localdomain ([185.200.240.39]) by smtp.gmail.com with ESMTPSA id r1-20020a2e94c1000000b002c9e6cbf78esm99062ljh.19.2023.12.07.18.32.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Dec 2023 18:32:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702002764; x=1702607564; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=IA89nY8jxlWQU5cEQQofnym1Upjf0MuK6dyCKlAlClw=; b=W+RzKDt7PkkHANjdpH8fOL4TxK/aNN51WrJjjXDucG8BHkL74ohMVXVpD4gVqChxfs 9Bhk7A20rPx9SfVqMQj2n0AlRlctZ3gVyt38Sy8+F2GK/E+3XPzOfGGfd/MX82a710ks UCfjvsBE4R6Y7+TgvmptGG4ENBA96DaVHTNshai3T9MVw8wduX+nR0v2S/a33G/0NYWW GDipEUNEcI2MmGKmUip/p8V0DunuQllhEr6f6BEhwpJDC8bpBLJlHoYXG9xkINWBgTR4 hN9xS5lPGnaqMrAD7SN+DdPHWk+M19Wv9ZiHB7/hpA41lwC6qlu/iv1503OvI9TGzp2U FQkw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702002764; x=1702607564; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=IA89nY8jxlWQU5cEQQofnym1Upjf0MuK6dyCKlAlClw=; b=sphMyzn6/XpTNRcCDtg9ajxWlv+45GhgF4BWmjVmhQ696Hg6fQZbpmiLX3WAl1+xeu ooZ1HKT5QV/OatYyuKTuaF+5vHLiI7z7DdGOi6TQOoO2AHnPeAkxAHM0eGcP5HuIEp4G 6bNdEtNqqnDr++IAYqQanCkRiFuLWpETKce7LMM/eZfukjlH9mdkrbhKeuVStN18yCsA kNbM6xxpRSexQdDsfa+RSzhwihbMOmz0TbtgmGIgbJsUT4EuYxocBjh+0k5yJtUxfuN/ GFOmYGN9TeAbH+mGowGTfvtm9GlMijnKGYWJi9Dk9AYcRmDHHNCxYHk1zqXm8ST/B7Hu 25dQ== X-Gm-Message-State: AOJu0YzgRnFZP/dkF6nH5UMRHb7s/yWox42oPCf82QByORjG2tlky0RC Vbgq6c1yUkcWxlNVjLzKBfNUs4iPtd2UAw== X-Google-Smtp-Source: AGHT+IFOiLxFZTexe9sfbEQ9Wlg6dXo53NEbJtttKyEiAFqqjoXEM9q2nuYo74KDE5/vpAj0Bc8Low== X-Received: by 2002:ac2:5966:0:b0:50b:c476:2f2d with SMTP id h6-20020ac25966000000b0050bc4762f2dmr76525lfp.16.1702002764124; Thu, 07 Dec 2023 18:32:44 -0800 (PST) From: Sergey Kambalin X-Google-Original-From: Sergey Kambalin To: qemu-arm@nongnu.org Cc: qemu-devel@nongnu.org, Sergey Kambalin Subject: [PATCH v4 15/45] Add BCM2838 PCIE host Date: Thu, 7 Dec 2023 20:31:15 -0600 Message-Id: <20231208023145.1385775-16-sergey.kambalin@auriga.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231208023145.1385775-1-sergey.kambalin@auriga.com> References: <20231208023145.1385775-1-sergey.kambalin@auriga.com> 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=2a00:1450:4864:20::133; envelope-from=serg.oker@gmail.com; helo=mail-lf1-x133.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, FREEMAIL_FROM=0.001, 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-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1702002799979100001 Content-Type: text/plain; charset="utf-8" Signed-off-by: Sergey Kambalin --- hw/arm/bcm2838_pcie.c | 216 +++++++++++++++++++++++++++++++++- include/hw/arm/bcm2838_pcie.h | 22 ++++ 2 files changed, 236 insertions(+), 2 deletions(-) diff --git a/hw/arm/bcm2838_pcie.c b/hw/arm/bcm2838_pcie.c index 3b4373c6a6..75146d6c2e 100644 --- a/hw/arm/bcm2838_pcie.c +++ b/hw/arm/bcm2838_pcie.c @@ -12,11 +12,222 @@ #include "hw/irq.h" #include "hw/pci-host/gpex.h" #include "hw/qdev-properties.h" -#include "migration/vmstate.h" -#include "qemu/module.h" #include "hw/arm/bcm2838_pcie.h" #include "trace.h" =20 +/* + * RC host part + */ + +static uint64_t bcm2838_pcie_host_read(void *opaque, hwaddr offset, + unsigned size) { + hwaddr mmcfg_addr; + uint64_t value =3D ~0; + BCM2838PcieHostState *s =3D opaque; + PCIExpressHost *pcie_hb =3D PCIE_HOST_BRIDGE(s); + PCIDevice *root_pci_dev =3D PCI_DEVICE(&s->root_port); + uint8_t *root_regs =3D s->root_port.regs; + uint32_t *cfg_idx =3D (uint32_t *)(root_regs + BCM2838_PCIE_EXT_CFG_IN= DEX + - PCIE_CONFIG_SPACE_SIZE); + + if (offset < PCIE_CONFIG_SPACE_SIZE) { + value =3D pci_host_config_read_common(root_pci_dev, offset, + PCIE_CONFIG_SPACE_SIZE, size); + } else if (offset - PCIE_CONFIG_SPACE_SIZE + size + <=3D sizeof(s->root_port.regs)) { + switch (offset) { + case BCM2838_PCIE_EXT_CFG_DATA + ... BCM2838_PCIE_EXT_CFG_DATA + PCIE_CONFIG_SPACE_SIZE - 1: + mmcfg_addr =3D *cfg_idx + | PCIE_MMCFG_CONFOFFSET(offset - BCM2838_PCIE_EXT_CFG_DATA= ); + value =3D pcie_hb->mmio.ops->read(opaque, mmcfg_addr, size); + break; + default: + memcpy(&value, root_regs + offset - PCIE_CONFIG_SPACE_SIZE, si= ze); + } + } else { + qemu_log_mask( + LOG_GUEST_ERROR, + "%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n", + __func__, size, offset); + } + + trace_bcm2838_pcie_host_read(size, offset, value); + return value; +} + +static void bcm2838_pcie_host_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) { + hwaddr mmcfg_addr; + BCM2838PcieHostState *s =3D opaque; + PCIExpressHost *pcie_hb =3D PCIE_HOST_BRIDGE(s); + PCIDevice *root_pci_dev =3D PCI_DEVICE(&s->root_port); + uint8_t *root_regs =3D s->root_port.regs; + uint32_t *cfg_idx =3D (uint32_t *)(root_regs + BCM2838_PCIE_EXT_CFG_IN= DEX + - PCIE_CONFIG_SPACE_SIZE); + + trace_bcm2838_pcie_host_write(size, offset, value); + + if (offset < PCIE_CONFIG_SPACE_SIZE) { + pci_host_config_write_common(root_pci_dev, offset, + PCIE_CONFIG_SPACE_SIZE, value, size); + } else if (offset - PCIE_CONFIG_SPACE_SIZE + size + <=3D sizeof(s->root_port.regs)) { + switch (offset) { + case BCM2838_PCIE_EXT_CFG_DATA + ... BCM2838_PCIE_EXT_CFG_DATA + PCIE_CONFIG_SPACE_SIZE - 1: + mmcfg_addr =3D *cfg_idx + | PCIE_MMCFG_CONFOFFSET(offset - BCM2838_PCIE_EXT_CFG_DATA= ); + pcie_hb->mmio.ops->write(opaque, mmcfg_addr, value, size); + break; + default: + memcpy(root_regs + offset - PCIE_CONFIG_SPACE_SIZE, &value, si= ze); + } + } else { + qemu_log_mask( + LOG_GUEST_ERROR, + "%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n", + __func__, size, offset); + } +} + +static const MemoryRegionOps bcm2838_pcie_host_ops =3D { + .read =3D bcm2838_pcie_host_read, + .write =3D bcm2838_pcie_host_write, + .endianness =3D DEVICE_NATIVE_ENDIAN, + .impl =3D {.max_access_size =3D sizeof(uint64_t)}, +}; + +int bcm2838_pcie_host_set_irq_num(BCM2838PcieHostState *s, int index, int = spi) +{ + if (index >=3D BCM2838_PCIE_NUM_IRQS) { + return -EINVAL; + } + + s->irq_num[index] =3D spi; + return 0; +} + +static void bcm2838_pcie_host_set_irq(void *opaque, int irq_num, int level) +{ + BCM2838PcieHostState *s =3D opaque; + + qemu_set_irq(s->irq[irq_num], level); +} + +static PCIINTxRoute bcm2838_pcie_host_route_intx_pin_to_irq(void *opaque, + int pin) +{ + PCIINTxRoute route; + BCM2838PcieHostState *s =3D opaque; + + route.irq =3D s->irq_num[pin]; + route.mode =3D route.irq < 0 ? PCI_INTX_DISABLED : PCI_INTX_ENABLED; + + return route; +} + +static int bcm2838_pcie_host_map_irq(PCIDevice *pci_dev, int pin) +{ + return pin; +} + +static void bcm2838_pcie_host_realize(DeviceState *dev, Error **errp) +{ + PCIHostState *pci =3D PCI_HOST_BRIDGE(dev); + BCM2838PcieHostState *s =3D BCM2838_PCIE_HOST(dev); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(dev); + + int i; + + memory_region_init_io(&s->cfg_regs, OBJECT(s), &bcm2838_pcie_host_ops,= s, + "bcm2838_pcie_cfg_regs", BCM2838_PCIE_REGS_SIZE); + sysbus_init_mmio(sbd, &s->cfg_regs); + + /* + * The MemoryRegions io_mmio and io_ioport that we pass to + * pci_register_root_bus() are not the same as the MemoryRegions + * io_mmio_window and io_ioport_window that we expose as SysBus MRs. + * The difference is in the behavior of accesses to addresses where no= PCI + * device has been mapped. + * + * io_mmio and io_ioport are the underlying PCI view of the PCI address + * space, and when a PCI device does a bus master access to a bad addr= ess + * this is reported back to it as a transaction failure. + * + * io_mmio_window and io_ioport_window implement "unmapped addresses r= ead as + * -1 and ignore writes"; this is a traditional x86 PC behavior, which= is + * not mandated properly by the PCI spec but expected by the majority = of + * PCI-using guest software, including Linux. + * + * We implement it in the PCIe host controller, by providing the *_win= dow + * MRs, which are containers with io ops that implement the 'backgroun= d' + * behavior and which hold the real PCI MRs as sub-regions. + */ + memory_region_init(&s->io_mmio, OBJECT(s), "bcm2838_pcie_mmio", UINT64= _MAX); + memory_region_init(&s->io_ioport, OBJECT(s), "bcm2838_pcie_ioport", + 64 * 1024); + + memory_region_init_io(&s->io_mmio_window, OBJECT(s), + &unassigned_io_ops, OBJECT(s), + "bcm2838_pcie_mmio_window", UINT64_MAX); + memory_region_init_io(&s->io_ioport_window, OBJECT(s), + &unassigned_io_ops, OBJECT(s), + "bcm2838_pcie_ioport_window", 64 * 1024); + + memory_region_add_subregion(&s->io_mmio_window, 0, &s->io_mmio); + memory_region_add_subregion(&s->io_ioport_window, 0, &s->io_ioport); + sysbus_init_mmio(sbd, &s->io_mmio_window); + sysbus_init_mmio(sbd, &s->io_ioport_window); + + for (i =3D 0; i < BCM2838_PCIE_NUM_IRQS; i++) { + sysbus_init_irq(sbd, &s->irq[i]); + s->irq_num[i] =3D -1; + } + + pci->bus =3D pci_register_root_bus(dev, "pcie.0", bcm2838_pcie_host_se= t_irq, + bcm2838_pcie_host_map_irq, s, &s->io_= mmio, + &s->io_ioport, 0, BCM2838_PCIE_NUM_IR= QS, + TYPE_PCIE_BUS); + pci_bus_set_route_irq_fn(pci->bus, bcm2838_pcie_host_route_intx_pin_to= _irq); + qdev_realize(DEVICE(&s->root_port), BUS(pci->bus), &error_fatal); +} + +static const char *bcm2838_pcie_host_root_bus_path(PCIHostState *host_brid= ge, + PCIBus *rootbus) +{ + return "0000:00"; +} + +static void bcm2838_pcie_host_class_init(ObjectClass *class, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(class); + PCIHostBridgeClass *hc =3D PCI_HOST_BRIDGE_CLASS(class); + + hc->root_bus_path =3D bcm2838_pcie_host_root_bus_path; + dc->realize =3D bcm2838_pcie_host_realize; + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->fw_name =3D "pci"; +} + +static void bcm2838_pcie_host_initfn(Object *obj) +{ + BCM2838PcieHostState *s =3D BCM2838_PCIE_HOST(obj); + BCM2838PcieRootState *root =3D &s->root_port; + + object_initialize_child(obj, "root_port", root, TYPE_BCM2838_PCIE_ROOT= ); + qdev_prop_set_int32(DEVICE(root), "addr", PCI_DEVFN(0, 0)); + qdev_prop_set_bit(DEVICE(root), "multifunction", false); +} + +static const TypeInfo bcm2838_pcie_host_info =3D { + .name =3D TYPE_BCM2838_PCIE_HOST, + .parent =3D TYPE_PCIE_HOST_BRIDGE, + .instance_size =3D sizeof(BCM2838PcieHostState), + .instance_init =3D bcm2838_pcie_host_initfn, + .class_init =3D bcm2838_pcie_host_class_init, +}; + /* * RC root part (D0:F0) */ @@ -69,6 +280,7 @@ static const TypeInfo bcm2838_pcie_root_info =3D { static void bcm2838_pcie_register(void) { type_register_static(&bcm2838_pcie_root_info); + type_register_static(&bcm2838_pcie_host_info); } =20 type_init(bcm2838_pcie_register) diff --git a/include/hw/arm/bcm2838_pcie.h b/include/hw/arm/bcm2838_pcie.h index 39828f817f..58c3a0efe7 100644 --- a/include/hw/arm/bcm2838_pcie.h +++ b/include/hw/arm/bcm2838_pcie.h @@ -16,6 +16,9 @@ #include "hw/pci/pcie_port.h" #include "qom/object.h" =20 +#define TYPE_BCM2838_PCIE_HOST "bcm2838-pcie-host" +OBJECT_DECLARE_SIMPLE_TYPE(BCM2838PcieHostState, BCM2838_PCIE_HOST) + #define TYPE_BCM2838_PCIE_ROOT "bcm2838-pcie-root" OBJECT_DECLARE_TYPE(BCM2838PcieRootState, BCM2838PcieRootClass, BCM2838_PCIE_ROOT) @@ -50,4 +53,23 @@ struct BCM2838PcieRootClass { }; =20 =20 +struct BCM2838PcieHostState { + /*< private >*/ + PCIExpressHost parent_obj; + + /*< public >*/ + BCM2838PcieRootState root_port; + + MemoryRegion cfg_regs; + MemoryRegion io_ioport; + MemoryRegion io_mmio; + MemoryRegion io_ioport_window; + MemoryRegion io_mmio_window; + + qemu_irq irq[BCM2838_PCIE_NUM_IRQS]; + int irq_num[BCM2838_PCIE_NUM_IRQS]; +}; + +int bcm2838_pcie_host_set_irq_num(BCM2838PcieHostState *s, int index, int = spi); + #endif /* BCM2838_PCIE_H */ --=20 2.34.1