From patchwork Mon Jan 13 14:58:07 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrea della Porta X-Patchwork-Id: 13937726 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 888ABC02184 for ; Mon, 13 Jan 2025 16:18:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:To:From:Reply-To: Cc:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=j5Syod//Rmt7/HH9hv4977njkIkORPgD/HA+7eqXGnc=; b=aA78kezfzkCtSrrgHxOZIoX9NL 4/cXxO4C0d+Fo14rFqRnhF74pr+dqd6roeTIp7F0G+guFK8UKJ3HLR4x1lYXIG92IddCeZ7MDXJYm o3W5bpydWBFXQDfFzqg7lpn86h8CD5/9bP9N0ExduvZErJMb8KtyAFDZs5IyR5BXPEhLtAFszpoPq fyaxsNB6FaaC+YJQrSLho4OU2GOeyX+Kzm5sSwigh8pYg3gk64Jrfg+fPWmsjENVjQHop3ymOYNmP TyjEYf+MRkk5ic+lYLMzZ+TAT3NC/9rH8CS52G7J6p4Lt7LGci6Cq8z5+6e54B/l+DTkYzoLrPjTV 2zRJNfJw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tXN8N-00000005oSN-1dTP; Mon, 13 Jan 2025 16:17:47 +0000 Received: from mail-ej1-x642.google.com ([2a00:1450:4864:20::642]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tXLsj-00000005VwE-1GUp for linux-arm-kernel@lists.infradead.org; Mon, 13 Jan 2025 14:57:35 +0000 Received: by mail-ej1-x642.google.com with SMTP id a640c23a62f3a-aaedd529ba1so625677266b.1 for ; Mon, 13 Jan 2025 06:57:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=google; t=1736780251; x=1737385051; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=j5Syod//Rmt7/HH9hv4977njkIkORPgD/HA+7eqXGnc=; b=GRl45/SXB0l50hAp8g+655B3CEx02ELRDTWz780l0QmqXtjIXgQpJECYwxxgPO8yG2 7oHudNoDrIWRvKAbRGTRdS3Ycx37Woae2Io0S7wNrkSs8A6z0r0lpFF8lRhG8husvt4N Szi6MkydF0iwriabpE5h3RLRboorIeO3uZSmp1NwCwo9F+HjyStOhHZG26IkZB/btuNu fs1YDuptCNsSjWH3nTTVpwJhFuOLcxxiwl+pbu8XSCGUq81erXaD6cR0WfUKkS1oNbOp TCkIPEgaF56avx7Ju9xAqWkgDXF8BL5v0mazFSgT0GfOSEXJZoQpxAl5Jhcn7RgGJnBV HDkg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736780252; x=1737385052; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=j5Syod//Rmt7/HH9hv4977njkIkORPgD/HA+7eqXGnc=; b=GHu4GAztf+3GGOyIbW27KiHghVkS4TRyV+bJUJ4V0crJDfpLP7+4cWvLWuBO6BgD6R K8s5BR2RJ9/qk4+nE0IGL3E8iJeNazMGPYwyp8iNTcDTgiGjBmLjEQs7eEgV8pSGunoR spzPzHRvtwwW58HHcCxEXc8tf0/2VRhe25WgXH6LGHumlDpblXsk1c/iwu+/Gv7KRAog dp1svMAIC7S+LNIQIeJPasZ4EGQ4AklmUuYkO36KOler3tf8FyrCZEb1cKnSk94JeScc qOUP5MN6Qd8uLjEAbM8EbsJjO1UKgtv2iB9mzpylnqPiCnUXU10sQ3705iPv48ZMByu9 siiA== X-Forwarded-Encrypted: i=1; AJvYcCWrcTiVTrDJwaYDlBviltJuaVlI5XJ9ZcqudWZrB1jDhAtFxSYiEz9gtW+/qHsndwMubOcFaQYQeHGvTSwKCKDB@lists.infradead.org X-Gm-Message-State: AOJu0YypnyhKeK5VKfjfDtm7LKqK+OUoeG0D+XUXHYX/X7Ecx9rKZ9Gu e8Q67Tjan07N2KlrafSwqV+CZd3JxRuKvG5j6D0JTMSse3olbhDi4Wo/3yFQPDQ= X-Gm-Gg: ASbGncsTcmUjeF7MkhPiQym0XxzZ1MdKbLMopzAtPCO/rDbw21yDsFbGLhSCWdHJgBl 0qtkwr2+ZgtsxE1uRPwi8voIn/ZEzpo3rJ0jO64Iu+ubGA83nRRD34Fvd7flXaWsPf8jVXZyjT7 FwRWKEdEO5Sse0yuxSAAt49UDNK8vrxiR7u1+dwJao/GvFR5wJQmZ0tg9jYdtu6IuJoSR5jgkFx sK7dsoX/AnPeld449tqsLqFhx7iENc3SP9S1BhzdfeOBWhJCX8f+iWDQcKzumVtcMcUu4XxHP4H 7INv+MP1Z5hh3IlnNJqHRHkYEhk= X-Google-Smtp-Source: AGHT+IG9zHWW91Jvy8EOROMgeJXoJxwcxspVbw0esNKFLtYtGz+4WJASTxBZhYi2YeNvBeV6CgyO0w== X-Received: by 2002:a05:6402:5251:b0:5d0:bf5e:eb8 with SMTP id 4fb4d7f45d1cf-5d972e63ddfmr45448297a12.23.1736780251496; Mon, 13 Jan 2025 06:57:31 -0800 (PST) Received: from localhost (host-87-14-236-197.retail.telecomitalia.it. [87.14.236.197]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ab2c905e2ebsm521106966b.10.2025.01.13.06.57.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2025 06:57:31 -0800 (PST) From: Andrea della Porta To: Andrea della Porta , Michael Turquette , Stephen Boyd , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Florian Fainelli , Broadcom internal kernel review list , Lorenzo Pieralisi , Krzysztof Wilczynski , Manivannan Sadhasivam , Bjorn Helgaas , Linus Walleij , Catalin Marinas , Will Deacon , Bartosz Golaszewski , Derek Kiernan , Dragan Cvetic , Arnd Bergmann , Greg Kroah-Hartman , Saravana Kannan , linux-clk@vger.kernel.org, devicetree@vger.kernel.org, linux-rpi-kernel@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-gpio@vger.kernel.org, Masahiro Yamada , Stefan Wahren , Herve Codina , Luca Ceresoli , Thomas Petazzoni , Andrew Lunn Subject: [PATCH v6 08/10] misc: rp1: RaspberryPi RP1 misc driver Date: Mon, 13 Jan 2025 15:58:07 +0100 Message-ID: <550590a5a0b80dd8a0c655921ec0aa41a67c8148.1736776658.git.andrea.porta@suse.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250113_065733_388272_B5411AA9 X-CRM114-Status: GOOD ( 32.94 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The RaspberryPi RP1 is a PCI multi function device containing peripherals ranging from Ethernet to USB controller, I2C, SPI and others. Implement a bare minimum driver to operate the RP1, leveraging actual OF based driver implementations for the on-board peripherals by loading a devicetree overlay during driver probe. The peripherals are accessed by mapping MMIO registers starting from PCI BAR1 region. With the overlay approach we can achieve more generic and agnostic approach to managing this chipset, being that it is a PCI endpoint and could possibly be reused in other hw implementations. The presented approach is also used by Bootlin's Microchip LAN966x patchset (see link) as well, for a similar chipset. For reasons why this driver is contained in drivers/misc, please check the links. This driver is heavily based on downstream code from RaspberryPi Foundation, and the original author is Phil Elwell. Link: https://datasheets.raspberrypi.com/rp1/rp1-peripherals.pdf Link: https://lore.kernel.org/all/20240612140208.GC1504919@google.com/ Link: https://lore.kernel.org/all/83f7fa09-d0e6-4f36-a27d-cee08979be2a@app.fastmail.com/ Link: https://lore.kernel.org/all/2024081356-mutable-everyday-6f9d@gregkh/ Link: https://lore.kernel.org/all/20240808154658.247873-1-herve.codina@bootlin.com/ Signed-off-by: Andrea della Porta --- MAINTAINERS | 1 + drivers/misc/Kconfig | 1 + drivers/misc/Makefile | 1 + drivers/misc/rp1/Kconfig | 21 +++ drivers/misc/rp1/Makefile | 3 + drivers/misc/rp1/rp1-pci.dtso | 8 + drivers/misc/rp1/rp1_pci.c | 305 ++++++++++++++++++++++++++++++++++ drivers/misc/rp1/rp1_pci.h | 14 ++ drivers/pci/quirks.c | 1 + include/linux/pci_ids.h | 3 + 10 files changed, 358 insertions(+) create mode 100644 drivers/misc/rp1/Kconfig create mode 100644 drivers/misc/rp1/Makefile create mode 100644 drivers/misc/rp1/rp1-pci.dtso create mode 100644 drivers/misc/rp1/rp1_pci.c create mode 100644 drivers/misc/rp1/rp1_pci.h diff --git a/MAINTAINERS b/MAINTAINERS index fbdd8594aa7e..d67ba6d10aa8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -19583,6 +19583,7 @@ F: Documentation/devicetree/bindings/misc/pci1de4,1.yaml F: Documentation/devicetree/bindings/pci/pci-ep-bus.yaml F: Documentation/devicetree/bindings/pinctrl/raspberrypi,rp1-gpio.yaml F: drivers/clk/clk-rp1.c +F: drivers/misc/rp1/ F: drivers/pinctrl/pinctrl-rp1.c F: include/dt-bindings/clock/rp1.h F: include/dt-bindings/misc/rp1.h diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 09cbe3f0ab1e..ffa4d8315c35 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -651,4 +651,5 @@ source "drivers/misc/uacce/Kconfig" source "drivers/misc/pvpanic/Kconfig" source "drivers/misc/mchp_pci1xxxx/Kconfig" source "drivers/misc/keba/Kconfig" +source "drivers/misc/rp1/Kconfig" endmenu diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 40bf953185c7..3b6b07a23aac 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -74,3 +74,4 @@ lan966x-pci-objs := lan966x_pci.o lan966x-pci-objs += lan966x_pci.dtbo.o obj-$(CONFIG_MCHP_LAN966X_PCI) += lan966x-pci.o obj-y += keba/ +obj-$(CONFIG_MISC_RP1) += rp1/ diff --git a/drivers/misc/rp1/Kconfig b/drivers/misc/rp1/Kconfig new file mode 100644 index 000000000000..15c443e13389 --- /dev/null +++ b/drivers/misc/rp1/Kconfig @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# RaspberryPi RP1 misc device +# + +config MISC_RP1 + tristate "RaspberryPi RP1 PCIe support" + depends on OF_IRQ && PCI_MSI && PCI_QUIRKS + select OF_OVERLAY + select PCI_DYNAMIC_OF_NODES + help + Support the RP1 peripheral chip found on Raspberry Pi 5 board. + + This device supports several sub-devices including e.g. Ethernet + controller, USB controller, I2C, SPI and UART. + + The driver is responsible for enabling the DT node once the PCIe + endpoint has been configured, and handling interrupts. + + This driver uses an overlay to load other drivers to support for + RP1 internal sub-devices. diff --git a/drivers/misc/rp1/Makefile b/drivers/misc/rp1/Makefile new file mode 100644 index 000000000000..508b4cb05627 --- /dev/null +++ b/drivers/misc/rp1/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_MISC_RP1) += rp1-pci.o +rp1-pci-objs := rp1_pci.o rp1-pci.dtbo.o diff --git a/drivers/misc/rp1/rp1-pci.dtso b/drivers/misc/rp1/rp1-pci.dtso new file mode 100644 index 000000000000..0bf2f4bb18e6 --- /dev/null +++ b/drivers/misc/rp1/rp1-pci.dtso @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +/* the dts overlay is included from the dts directory so + * it can be possible to check it with CHECK_DTBS while + * also compile it from the driver source directory. + */ + +#include "arm64/broadcom/rp1.dtso" diff --git a/drivers/misc/rp1/rp1_pci.c b/drivers/misc/rp1/rp1_pci.c new file mode 100644 index 000000000000..3e8ba3fa7fd5 --- /dev/null +++ b/drivers/misc/rp1/rp1_pci.c @@ -0,0 +1,305 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018-24 Raspberry Pi Ltd. + * All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rp1_pci.h" + +#define RP1_DRIVER_NAME "rp1" + +#define RP1_HW_IRQ_MASK GENMASK(5, 0) + +#define REG_SET 0x800 +#define REG_CLR 0xc00 + +/* MSI-X CFG registers start at 0x8 */ +#define MSIX_CFG(x) (0x8 + (4 * (x))) + +#define MSIX_CFG_IACK_EN BIT(3) +#define MSIX_CFG_IACK BIT(2) +#define MSIX_CFG_ENABLE BIT(0) + +/* Address map */ +#define RP1_PCIE_APBS_BASE 0x108000 + +/* Interrupts */ +#define RP1_INT_END 61 + +struct rp1_dev { + struct pci_dev *pdev; + struct irq_domain *domain; + struct irq_data *pcie_irqds[64]; + void __iomem *bar1; + int ovcs_id; /* overlay changeset id */ + bool level_triggered_irq[RP1_INT_END]; +}; + +static void msix_cfg_set(struct rp1_dev *rp1, unsigned int hwirq, u32 value) +{ + iowrite32(value, rp1->bar1 + RP1_PCIE_APBS_BASE + REG_SET + MSIX_CFG(hwirq)); +} + +static void msix_cfg_clr(struct rp1_dev *rp1, unsigned int hwirq, u32 value) +{ + iowrite32(value, rp1->bar1 + RP1_PCIE_APBS_BASE + REG_CLR + MSIX_CFG(hwirq)); +} + +static void rp1_mask_irq(struct irq_data *irqd) +{ + struct rp1_dev *rp1 = irqd->domain->host_data; + struct irq_data *pcie_irqd = rp1->pcie_irqds[irqd->hwirq]; + + pci_msi_mask_irq(pcie_irqd); +} + +static void rp1_unmask_irq(struct irq_data *irqd) +{ + struct rp1_dev *rp1 = irqd->domain->host_data; + struct irq_data *pcie_irqd = rp1->pcie_irqds[irqd->hwirq]; + + pci_msi_unmask_irq(pcie_irqd); +} + +static int rp1_irq_set_type(struct irq_data *irqd, unsigned int type) +{ + struct rp1_dev *rp1 = irqd->domain->host_data; + unsigned int hwirq = (unsigned int)irqd->hwirq; + + switch (type) { + case IRQ_TYPE_LEVEL_HIGH: + dev_dbg(&rp1->pdev->dev, "MSIX IACK EN for irq %d\n", hwirq); + msix_cfg_set(rp1, hwirq, MSIX_CFG_IACK_EN); + rp1->level_triggered_irq[hwirq] = true; + break; + case IRQ_TYPE_EDGE_RISING: + msix_cfg_clr(rp1, hwirq, MSIX_CFG_IACK_EN); + rp1->level_triggered_irq[hwirq] = false; + break; + default: + return -EINVAL; + } + + return 0; +} + +static struct irq_chip rp1_irq_chip = { + .name = "rp1_irq_chip", + .irq_mask = rp1_mask_irq, + .irq_unmask = rp1_unmask_irq, + .irq_set_type = rp1_irq_set_type, +}; + +static void rp1_chained_handle_irq(struct irq_desc *desc) +{ + unsigned int hwirq = desc->irq_data.hwirq & RP1_HW_IRQ_MASK; + struct rp1_dev *rp1 = irq_desc_get_handler_data(desc); + struct irq_chip *chip = irq_desc_get_chip(desc); + unsigned int virq; + + chained_irq_enter(chip, desc); + + virq = irq_find_mapping(rp1->domain, hwirq); + generic_handle_irq(virq); + if (rp1->level_triggered_irq[hwirq]) + msix_cfg_set(rp1, hwirq, MSIX_CFG_IACK); + + chained_irq_exit(chip, desc); +} + +static int rp1_irq_xlate(struct irq_domain *d, struct device_node *node, + const u32 *intspec, unsigned int intsize, + unsigned long *out_hwirq, unsigned int *out_type) +{ + struct rp1_dev *rp1 = d->host_data; + struct irq_data *pcie_irqd; + unsigned long hwirq; + int pcie_irq; + int ret; + + ret = irq_domain_xlate_twocell(d, node, intspec, intsize, + &hwirq, out_type); + if (ret) + return ret; + + pcie_irq = pci_irq_vector(rp1->pdev, hwirq); + pcie_irqd = irq_get_irq_data(pcie_irq); + rp1->pcie_irqds[hwirq] = pcie_irqd; + *out_hwirq = hwirq; + + return 0; +} + +static int rp1_irq_activate(struct irq_domain *d, struct irq_data *irqd, + bool reserve) +{ + struct rp1_dev *rp1 = d->host_data; + + msix_cfg_set(rp1, (unsigned int)irqd->hwirq, MSIX_CFG_ENABLE); + + return 0; +} + +static void rp1_irq_deactivate(struct irq_domain *d, struct irq_data *irqd) +{ + struct rp1_dev *rp1 = d->host_data; + + msix_cfg_clr(rp1, (unsigned int)irqd->hwirq, MSIX_CFG_ENABLE); +} + +static const struct irq_domain_ops rp1_domain_ops = { + .xlate = rp1_irq_xlate, + .activate = rp1_irq_activate, + .deactivate = rp1_irq_deactivate, +}; + +static void rp1_unregister_interrupts(struct pci_dev *pdev) +{ + struct rp1_dev *rp1 = pci_get_drvdata(pdev); + int irq, i; + + if (rp1->domain) { + for (i = 0; i < RP1_INT_END; i++) { + irq = irq_find_mapping(rp1->domain, i); + irq_dispose_mapping(irq); + } + + irq_domain_remove(rp1->domain); + } + + pci_free_irq_vectors(pdev); +} + +static int rp1_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + u32 dtbo_size = __dtbo_rp1_pci_end - __dtbo_rp1_pci_begin; + void *dtbo_start = __dtbo_rp1_pci_begin; + struct device *dev = &pdev->dev; + struct device_node *rp1_node; + struct rp1_dev *rp1; + int err = 0; + int i; + + rp1_node = dev_of_node(dev); + if (!rp1_node) { + dev_err(dev, "Missing of_node for device\n"); + return -EINVAL; + } + + rp1 = devm_kzalloc(&pdev->dev, sizeof(*rp1), GFP_KERNEL); + if (!rp1) + return -ENOMEM; + + rp1->pdev = pdev; + + if (pci_resource_len(pdev, 1) <= 0x10000) { + dev_err(&pdev->dev, + "Not initialised - is the firmware running?\n"); + return -EINVAL; + } + + err = pcim_enable_device(pdev); + if (err < 0) + return dev_err_probe(&pdev->dev, err, + "Enabling PCI device has failed"); + + rp1->bar1 = pcim_iomap(pdev, 1, 0); + if (!rp1->bar1) { + dev_err(&pdev->dev, "Cannot map PCI BAR\n"); + return -EIO; + } + + pci_set_master(pdev); + + err = pci_alloc_irq_vectors(pdev, RP1_INT_END, RP1_INT_END, + PCI_IRQ_MSIX); + if (err < 0) { + return dev_err_probe(&pdev->dev, err, + "pci_alloc_irq_vectors failed"); + } else if (err != RP1_INT_END) { + dev_err(&pdev->dev, "Cannot allocate enough interrupts\n"); + return -EINVAL; + } + + pci_set_drvdata(pdev, rp1); + rp1->domain = irq_domain_add_linear(rp1_node, RP1_INT_END, + &rp1_domain_ops, rp1); + if (!rp1->domain) { + dev_err(&pdev->dev, "Error creating IRQ domain\n"); + err = -ENOMEM; + goto err_unregister_interrupts; + } + + for (i = 0; i < RP1_INT_END; i++) { + unsigned int irq = irq_create_mapping(rp1->domain, i); + + if (!irq) { + dev_err(&pdev->dev, "failed to create irq mapping\n"); + err = -EINVAL; + goto err_unregister_interrupts; + } + + irq_set_chip_and_handler(irq, &rp1_irq_chip, handle_level_irq); + irq_set_probe(irq); + irq_set_chained_handler_and_data(pci_irq_vector(pdev, i), + rp1_chained_handle_irq, rp1); + } + + err = of_overlay_fdt_apply(dtbo_start, dtbo_size, &rp1->ovcs_id, rp1_node); + if (err) + goto err_unregister_interrupts; + + err = of_platform_default_populate(rp1_node, NULL, dev); + if (err) + goto err_unload_overlay; + + return 0; + +err_unload_overlay: + of_overlay_remove(&rp1->ovcs_id); +err_unregister_interrupts: + rp1_unregister_interrupts(pdev); + + return err; +} + +static void rp1_remove(struct pci_dev *pdev) +{ + struct rp1_dev *rp1 = pci_get_drvdata(pdev); + struct device *dev = &pdev->dev; + + of_platform_depopulate(dev); + of_overlay_remove(&rp1->ovcs_id); + rp1_unregister_interrupts(pdev); +} + +static const struct pci_device_id dev_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_RPI, PCI_DEVICE_ID_RPI_RP1_C0), }, + { 0, } +}; +MODULE_DEVICE_TABLE(pci, dev_id_table); + +static struct pci_driver rp1_driver = { + .name = RP1_DRIVER_NAME, + .id_table = dev_id_table, + .probe = rp1_probe, + .remove = rp1_remove, +}; + +module_pci_driver(rp1_driver); + +MODULE_AUTHOR("Phil Elwell "); +MODULE_AUTHOR("Andrea della Porta "); +MODULE_DESCRIPTION("RP1 wrapper"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/rp1/rp1_pci.h b/drivers/misc/rp1/rp1_pci.h new file mode 100644 index 000000000000..7982f13bad9b --- /dev/null +++ b/drivers/misc/rp1/rp1_pci.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Copyright (c) 2018-24 Raspberry Pi Ltd. + * All rights reserved. + */ + +#ifndef _RP1_EXTERN_H_ +#define _RP1_EXTERN_H_ + +extern char __dtbo_rp1_pci_begin[]; +extern char __dtbo_rp1_pci_end[]; + +#endif diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 76f4df75b08a..e9a0fb707a4a 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -6269,6 +6269,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_XILINX, 0x5020, of_pci_make_dev_node); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_XILINX, 0x5021, of_pci_make_dev_node); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_REDHAT, 0x0005, of_pci_make_dev_node); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_EFAR, 0x9660, of_pci_make_dev_node); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_RPI, PCI_DEVICE_ID_RPI_RP1_C0, of_pci_make_dev_node); /* * Devices known to require a longer delay before first config space access diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index d2402bf4aea2..9232b131a41e 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2615,6 +2615,9 @@ #define PCI_VENDOR_ID_TEKRAM 0x1de1 #define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29 +#define PCI_VENDOR_ID_RPI 0x1de4 +#define PCI_DEVICE_ID_RPI_RP1_C0 0x0001 + #define PCI_VENDOR_ID_ALIBABA 0x1ded #define PCI_VENDOR_ID_CXL 0x1e98