From nobody Wed Nov 27 04:52:37 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=1701650030; cv=none; d=zohomail.com; s=zohoarc; b=jrOm583xLU4MZT3WUbz9VNIQBlT+WDpYokDBcbNTLBYvn62z4TJcyQgb8Krvl2DozXFeb8/WMKC6nt8LAECRoE6+A6syEKvA/RXSsYIMDOdpfihsr/TrGpncyLTjsqK+EmvKwEzVQhcYjZBVuaN6+0uqfUFnoAkraMZEW0ZJK1Y= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1701650030; 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=PPtNg5WT6oraJWVWtdllWJuG6N+ShuQN11PE3aaLSrzGqhbzk0cfPtcSugOvWOn0G0aOPgwzUmyo1VHKe4F5ZhDHnVOXnjhx6wd0E/FcgFbQJXvAzXmheqveAUnBzK1GrL3FkSJmcYRJBnBD8WcOI4G9i44LzUT2Tcm/PccCPj8= 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 1701650030679767.1004953609416; Sun, 3 Dec 2023 16:33:50 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r9wno-0004oF-IR; Sun, 03 Dec 2023 19:27:12 -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 1r9wnT-0004YG-79; Sun, 03 Dec 2023 19:26:56 -0500 Received: from mail-yw1-x112a.google.com ([2607:f8b0:4864:20::112a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1r9wnN-00009i-Bi; Sun, 03 Dec 2023 19:26:50 -0500 Received: by mail-yw1-x112a.google.com with SMTP id 00721157ae682-5d719a2004fso5254567b3.3; Sun, 03 Dec 2023 16:26:43 -0800 (PST) Received: from localhost.localdomain ([201.206.180.22]) by smtp.gmail.com with ESMTPSA id l63-20020a0de242000000b005d3e6ce07e7sm2443187ywe.6.2023.12.03.16.26.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 03 Dec 2023 16:26:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1701649602; x=1702254402; 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=ACxL6UbmbhO4lzmtVMYzpldFEh2B48EREC6rB689d5xlPWPw+aRXklUm/mdh9wre7T 54yAbRHWPwam4PeXmcdUyhEgKGwW29Iy1fT21ii0lus4zdmv2kPav1SJ+I1bw8LQwGym Kp3xbsEmOa+updlY5KubP0nPItUqPWdVNvHhNaPAJjA7hhbjBFx756eEWc6boM9+uK79 FJ3Kneh/Q4z5Ha86JhQiGEvoe7FOHK0JBNFPawl7sD7+rBYdiPQry3CVIXgWRzdpXtJy +str8068kteuZ24RnWOxBfYchj2+R0QODw5FFD52Ls+51eqYcetwL26bUf1VSIOc46Tf BuIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701649602; x=1702254402; 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=eV0xrwksHLJUgVsB4Zgwd1aqhxkTWs8TVRjmtIsnCM82RmAGnTLy85rKFhffXeRarh BNHzABQurc8CB0Lc9ttfTO1ojAJqEMcpyDQ/IjS+ARsYgXiYL3c3LKwF2RjCP4gXXA7w HW9wfMuydxd/qAtRW42rP7AQnsPSY/IVFluMJun2Vsn8SLoBnF31ztSZOxr0C7d/FPJl 0cmcUajYiGl24pkdn2imBNzHDyNoLV8JMf+cAt08AWq2hV81+L4c+rImbGtHAMv+yINX AImeCmlcOObHb8gghlYUcnVXd4ocmUQLhfo7N5sJfltAuIkA1/kZpVBoOD8uvFV9Ph0+ wnlg== X-Gm-Message-State: AOJu0YyMdZQ121Fn5ww7xMaRCkfGFCTKQFfjPcZXz4fexcME+VSRMxMd MNdnbNDSithszq4548dGZ7OuqGEp6dGD9Q== X-Google-Smtp-Source: AGHT+IHvE11cLCJHE1TY4ug+w33H/AnltHMcZLZw3/0TiuXdgszegyGSgxJfGQYYrOhvmsNrHsyR2w== X-Received: by 2002:a81:b049:0:b0:5d2:913a:640d with SMTP id x9-20020a81b049000000b005d2913a640dmr822205ywk.47.1701649602626; Sun, 03 Dec 2023 16:26:42 -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 v3 15/45] Add BCM2838 PCIE host Date: Sun, 3 Dec 2023 18:25:49 -0600 Message-Id: <20231204002619.1367044-16-sergey.kambalin@auriga.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231204002619.1367044-1-sergey.kambalin@auriga.com> References: <20231204002619.1367044-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=2607:f8b0:4864:20::112a; envelope-from=serg.oker@gmail.com; helo=mail-yw1-x112a.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: 1701650933291100003 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