From nobody Thu Nov 14 17:42:06 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=1708905922; cv=none; d=zohomail.com; s=zohoarc; b=ZBQsBXWnDIcxXDjK0P4CgKoq3p2H4OoHICZzAY+BOJCYiUPvIJy67jgw6s1A8L6C68Nl5L5r+ZTe92HRDrqt8o9uFGOdqWLuMdP4Bkjne18P8ERv3YLNyXauAEKbf4Xa236ouVHxGN74185rEubVDSAGdqxSfvzmVDcifNIfXm8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1708905922; 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=gLCgNe8tzKgwcvsw5l260FdcvaTVAG0BWiHATsCjss4=; b=k/2LeWgw/FBsD0l4ueajivwDTcCw63wKW/iCdVg8fBuPva0PAa8jc0BpXufLvbzqa9qhZjcWQYm0TyrSmfqU3Pox2I/siGw2eqZhmuFGKUzds0gbB93GJdjpyHoaXE6EwKGkaZ2rszp0RD9Diqw4V3K1yjJoLUEmVdP87V6gd9c= 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 1708905922809586.3236468534145; Sun, 25 Feb 2024 16:05:22 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1reOT1-0006mK-J3; Sun, 25 Feb 2024 19:03:35 -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 1reOSq-0006cY-2U; Sun, 25 Feb 2024 19:03:24 -0500 Received: from mail-yw1-x112c.google.com ([2607:f8b0:4864:20::112c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1reOSn-0000MH-NZ; Sun, 25 Feb 2024 19:03:23 -0500 Received: by mail-yw1-x112c.google.com with SMTP id 00721157ae682-60822b444c9so15150207b3.2; Sun, 25 Feb 2024 16:03:20 -0800 (PST) Received: from localhost.localdomain ([201.203.117.224]) by smtp.gmail.com with ESMTPSA id t18-20020a818312000000b00607bfa1913csm938171ywf.114.2024.02.25.16.03.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 25 Feb 2024 16:03:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1708905800; x=1709510600; 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=gLCgNe8tzKgwcvsw5l260FdcvaTVAG0BWiHATsCjss4=; b=inKUZIO2Ep7HuiqtxGxgebWee3wKp2H5wR1LfKK9m1wvsO8D5PmgZrGevhNIMIyCcA IfX8/jddCc7RlwyYYmyOTcaxdfh18XM5Xirea7r56y1e/2nT086GCTEhi+EKFgV8RzFw JX1buxOOOflu5LnvyXERtDwLI8c2a79DhhenBKn7/dg4WdE5OCMrZFz17olvxsN/0CpG DM8GMoYzEYr9/TCwBwFlTTBBCUK2o/MPseAybvu9kFyApW19unk7Wrd7yXMZ2GpyYkC7 J5R+432/aTV3JvGm/4bX1bey/xPWrhIYXl69qEmG9UaT+OipzenHnghq1PCi3aPax4d2 ddQw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708905800; x=1709510600; 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=gLCgNe8tzKgwcvsw5l260FdcvaTVAG0BWiHATsCjss4=; b=C2RkdmT+nyT9X0DahxQlh+Q925QdaLA11PZnvynutqP67j+xus7CQyIg3fPNafT8GB fuxhS8buI8m9FEhhBU5KS9Fv4xV8NaYtfpjUu278iL5RKYcKCVEt5U8duALYmO4FD/T8 9qExnVXiHTut7svZdGpH+hJ70a0gydmAkKfwmZCwNUrlqn/Wlgu2H6yHR/+zZ5U0m69x IaBVFRrgd1MQzQJPaoYIZEqi1vllAf30Pr3yzuGGhcf2u7lCY3zgRrHaXTk6PC79JWRt WEIovqvB91GpmeruTcg0s4X4FYk52CavaMWtvU9EcChe75P4NDou2S+kJ56i0qp/w7Ld zAyA== X-Gm-Message-State: AOJu0YxJbBKOjGDzdXjdpeXDO0K1tznB6y1OCQmpcWoJH5mG3ffu+pia KcUhE4nbdtzHHdO2SZndkJvjJa5WaHijHGddj8/K0Zbf2ruBvASzBQyEg9jJYaV+gQ== X-Google-Smtp-Source: AGHT+IH+MAA9ELOisKERWH1kYxlQGlNCLEjz9mGe0vYUfEFtJjVia3XyuvqFkqdm8Cde+Ex9tbeq+w== X-Received: by 2002:a81:a143:0:b0:607:f09a:d298 with SMTP id y64-20020a81a143000000b00607f09ad298mr5536436ywg.42.1708905799874; Sun, 25 Feb 2024 16:03:19 -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 v6 14/41] Add BCM2838 PCIE host Date: Sun, 25 Feb 2024 18:02:32 -0600 Message-Id: <20240226000259.2752893-15-sergey.kambalin@auriga.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240226000259.2752893-1-sergey.kambalin@auriga.com> References: <20240226000259.2752893-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::112c; envelope-from=serg.oker@gmail.com; helo=mail-yw1-x112c.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: 1708905924917100003 Content-Type: text/plain; charset="utf-8" Signed-off-by: Sergey Kambalin --- hw/arm/bcm2838_pcie.c | 217 +++++++++++++++++++++++++++++++++- hw/arm/trace-events | 4 + include/hw/arm/bcm2838_pcie.h | 22 ++++ 3 files changed, 241 insertions(+), 2 deletions(-) diff --git a/hw/arm/bcm2838_pcie.c b/hw/arm/bcm2838_pcie.c index cb1370433e..348263d9fb 100644 --- a/hw/arm/bcm2838_pcie.c +++ b/hw/arm/bcm2838_pcie.c @@ -12,11 +12,220 @@ #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 +static uint32_t bcm2838_pcie_config_read(PCIDevice *d, + uint32_t address, int len) +{ + return pci_default_read_config(d, address, len); +} + +static void bcm2838_pcie_config_write(PCIDevice *d, uint32_t addr, uint32_= t val, + int len) +{ + return pci_default_write_config(d, addr, val, len); +} + +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); + 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 + size <=3D sizeof(s->root_port.re= gs)) { + 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); + 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 + size <=3D sizeof(s->root_port.re= gs)) { + 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) */ @@ -62,6 +271,9 @@ static void bcm2838_pcie_root_class_init(ObjectClass *cl= ass, void *data) k->device_id =3D BCM2838_PCIE_DEVICE_ID; k->revision =3D BCM2838_PCIE_REVISION; =20 + k->config_read =3D bcm2838_pcie_config_read; + k->config_write =3D bcm2838_pcie_config_write; + rpc->exp_offset =3D BCM2838_PCIE_EXP_CAP_OFFSET; rpc->aer_offset =3D BCM2838_PCIE_AER_CAP_OFFSET; } @@ -77,6 +289,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/hw/arm/trace-events b/hw/arm/trace-events index f1a54a02df..2f24d9528d 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -73,3 +73,7 @@ xen_enable_tpm(uint64_t addr) "Connected tpmdev at addres= s 0x%"PRIx64 =20 # bcm2838.c bcm2838_gic_set_irq(int irq, int level) "gic irq:%d lvl:%d" + +# bcm2838_pcie.c +bcm2838_pcie_host_read(unsigned int size, uint64_t offset, uint64_t value)= "%u bytes @ 0x%04"PRIx64": 0x%016"PRIx64 +bcm2838_pcie_host_write(unsigned int size, uint64_t offset, uint64_t value= ) "%u bytes @ 0x%04"PRIx64": 0x%016"PRIx64 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