Commit 83d82352 authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'pci/host/al'

  - Add Amazon Annapurna Labs PCIe host controller driver (Jonathan
    Chocron)

* pci/host/al:
  PCI: al: Add Amazon Annapurna Labs PCIe host controller driver
parents c711a84a 4166bfe5
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -12015,6 +12015,12 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/pci.git/
S:	Supported
F:	drivers/pci/controller/

PCIE DRIVER FOR ANNAPURNA LABS
M:	Jonathan Chocron <jonnyc@amazon.com>
L:	linux-pci@vger.kernel.org
S:	Maintained
F:	drivers/pci/controller/dwc/pcie-al.c

PCIE DRIVER FOR AMLOGIC MESON
M:	Yue Wang <yue.wang@Amlogic.com>
L:	linux-pci@vger.kernel.org
+12 −0
Original line number Diff line number Diff line
@@ -52,6 +52,18 @@ struct mcfg_fixup {
static struct mcfg_fixup mcfg_quirks[] = {
/*	{ OEM_ID, OEM_TABLE_ID, REV, SEGMENT, BUS_RANGE, ops, cfgres }, */

#define AL_ECAM(table_id, rev, seg, ops) \
	{ "AMAZON", table_id, rev, seg, MCFG_BUS_ANY, ops }

	AL_ECAM("GRAVITON", 0, 0, &al_pcie_ops),
	AL_ECAM("GRAVITON", 0, 1, &al_pcie_ops),
	AL_ECAM("GRAVITON", 0, 2, &al_pcie_ops),
	AL_ECAM("GRAVITON", 0, 3, &al_pcie_ops),
	AL_ECAM("GRAVITON", 0, 4, &al_pcie_ops),
	AL_ECAM("GRAVITON", 0, 5, &al_pcie_ops),
	AL_ECAM("GRAVITON", 0, 6, &al_pcie_ops),
	AL_ECAM("GRAVITON", 0, 7, &al_pcie_ops),

#define QCOM_ECAM32(seg) \
	{ "QCOM  ", "QDF2432 ", 1, seg, MCFG_BUS_ANY, &pci_32b_ops }

+1 −0
Original line number Diff line number Diff line
@@ -28,5 +28,6 @@ obj-$(CONFIG_PCIE_UNIPHIER) += pcie-uniphier.o
# depending on whether ACPI, the DT driver, or both are enabled.

ifdef CONFIG_PCI
obj-$(CONFIG_ARM64) += pcie-al.o
obj-$(CONFIG_ARM64) += pcie-hisi.o
endif
+93 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 * PCIe host controller driver for Amazon's Annapurna Labs IP (used in chips
 * such as Graviton and Alpine)
 *
 * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Author: Jonathan Chocron <jonnyc@amazon.com>
 */

#include <linux/pci.h>
#include <linux/pci-ecam.h>
#include <linux/pci-acpi.h>
#include "../../pci.h"

#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)

struct al_pcie_acpi  {
	void __iomem *dbi_base;
};

static void __iomem *al_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
				     int where)
{
	struct pci_config_window *cfg = bus->sysdata;
	struct al_pcie_acpi *pcie = cfg->priv;
	void __iomem *dbi_base = pcie->dbi_base;

	if (bus->number == cfg->busr.start) {
		/*
		 * The DW PCIe core doesn't filter out transactions to other
		 * devices/functions on the root bus num, so we do this here.
		 */
		if (PCI_SLOT(devfn) > 0)
			return NULL;
		else
			return dbi_base + where;
	}

	return pci_ecam_map_bus(bus, devfn, where);
}

static int al_pcie_init(struct pci_config_window *cfg)
{
	struct device *dev = cfg->parent;
	struct acpi_device *adev = to_acpi_device(dev);
	struct acpi_pci_root *root = acpi_driver_data(adev);
	struct al_pcie_acpi *al_pcie;
	struct resource *res;
	int ret;

	al_pcie = devm_kzalloc(dev, sizeof(*al_pcie), GFP_KERNEL);
	if (!al_pcie)
		return -ENOMEM;

	res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
	if (!res)
		return -ENOMEM;

	ret = acpi_get_rc_resources(dev, "AMZN0001", root->segment, res);
	if (ret) {
		dev_err(dev, "can't get rc dbi base address for SEG %d\n",
			root->segment);
		return ret;
	}

	dev_dbg(dev, "Root port dbi res: %pR\n", res);

	al_pcie->dbi_base = devm_pci_remap_cfg_resource(dev, res);
	if (IS_ERR(al_pcie->dbi_base)) {
		long err = PTR_ERR(al_pcie->dbi_base);

		dev_err(dev, "couldn't remap dbi base %pR (err:%ld)\n",
			res, err);
		return err;
	}

	cfg->priv = al_pcie;

	return 0;
}

struct pci_ecam_ops al_pcie_ops = {
	.bus_shift    = 20,
	.init         =  al_pcie_init,
	.pci_ops      = {
		.map_bus    = al_pcie_map_bus,
		.read       = pci_generic_config_read,
		.write      = pci_generic_config_write,
	}
};

#endif /* defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS) */
+1 −0
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ extern struct pci_ecam_ops thunder_pem_ecam_ops; /* Cavium ThunderX 1.x & 2.x */
extern struct pci_ecam_ops pci_thunder_ecam_ops; /* Cavium ThunderX 1.x */
extern struct pci_ecam_ops xgene_v1_pcie_ecam_ops; /* APM X-Gene PCIe v1 */
extern struct pci_ecam_ops xgene_v2_pcie_ecam_ops; /* APM X-Gene PCIe v2.x */
extern struct pci_ecam_ops al_pcie_ops; /* Amazon Annapurna Labs PCIe */
#endif

#ifdef CONFIG_PCI_HOST_COMMON