162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * PCIe host controller driver for Amazon's Annapurna Labs IP (used in chips
462306a36Sopenharmony_ci * such as Graviton and Alpine)
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Author: Jonathan Chocron <jonnyc@amazon.com>
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/pci.h>
1262306a36Sopenharmony_ci#include <linux/pci-ecam.h>
1362306a36Sopenharmony_ci#include <linux/pci-acpi.h>
1462306a36Sopenharmony_ci#include "../../pci.h"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cistruct al_pcie_acpi  {
1962306a36Sopenharmony_ci	void __iomem *dbi_base;
2062306a36Sopenharmony_ci};
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cistatic void __iomem *al_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
2362306a36Sopenharmony_ci				     int where)
2462306a36Sopenharmony_ci{
2562306a36Sopenharmony_ci	struct pci_config_window *cfg = bus->sysdata;
2662306a36Sopenharmony_ci	struct al_pcie_acpi *pcie = cfg->priv;
2762306a36Sopenharmony_ci	void __iomem *dbi_base = pcie->dbi_base;
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	if (bus->number == cfg->busr.start) {
3062306a36Sopenharmony_ci		/*
3162306a36Sopenharmony_ci		 * The DW PCIe core doesn't filter out transactions to other
3262306a36Sopenharmony_ci		 * devices/functions on the root bus num, so we do this here.
3362306a36Sopenharmony_ci		 */
3462306a36Sopenharmony_ci		if (PCI_SLOT(devfn) > 0)
3562306a36Sopenharmony_ci			return NULL;
3662306a36Sopenharmony_ci		else
3762306a36Sopenharmony_ci			return dbi_base + where;
3862306a36Sopenharmony_ci	}
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	return pci_ecam_map_bus(bus, devfn, where);
4162306a36Sopenharmony_ci}
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cistatic int al_pcie_init(struct pci_config_window *cfg)
4462306a36Sopenharmony_ci{
4562306a36Sopenharmony_ci	struct device *dev = cfg->parent;
4662306a36Sopenharmony_ci	struct acpi_device *adev = to_acpi_device(dev);
4762306a36Sopenharmony_ci	struct acpi_pci_root *root = acpi_driver_data(adev);
4862306a36Sopenharmony_ci	struct al_pcie_acpi *al_pcie;
4962306a36Sopenharmony_ci	struct resource *res;
5062306a36Sopenharmony_ci	int ret;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	al_pcie = devm_kzalloc(dev, sizeof(*al_pcie), GFP_KERNEL);
5362306a36Sopenharmony_ci	if (!al_pcie)
5462306a36Sopenharmony_ci		return -ENOMEM;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
5762306a36Sopenharmony_ci	if (!res)
5862306a36Sopenharmony_ci		return -ENOMEM;
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	ret = acpi_get_rc_resources(dev, "AMZN0001", root->segment, res);
6162306a36Sopenharmony_ci	if (ret) {
6262306a36Sopenharmony_ci		dev_err(dev, "can't get rc dbi base address for SEG %d\n",
6362306a36Sopenharmony_ci			root->segment);
6462306a36Sopenharmony_ci		return ret;
6562306a36Sopenharmony_ci	}
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	dev_dbg(dev, "Root port dbi res: %pR\n", res);
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	al_pcie->dbi_base = devm_pci_remap_cfg_resource(dev, res);
7062306a36Sopenharmony_ci	if (IS_ERR(al_pcie->dbi_base))
7162306a36Sopenharmony_ci		return PTR_ERR(al_pcie->dbi_base);
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	cfg->priv = al_pcie;
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	return 0;
7662306a36Sopenharmony_ci}
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ciconst struct pci_ecam_ops al_pcie_ops = {
7962306a36Sopenharmony_ci	.init         =  al_pcie_init,
8062306a36Sopenharmony_ci	.pci_ops      = {
8162306a36Sopenharmony_ci		.map_bus    = al_pcie_map_bus,
8262306a36Sopenharmony_ci		.read       = pci_generic_config_read,
8362306a36Sopenharmony_ci		.write      = pci_generic_config_write,
8462306a36Sopenharmony_ci	}
8562306a36Sopenharmony_ci};
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci#endif /* defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS) */
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci#ifdef CONFIG_PCIE_AL
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci#include <linux/of_pci.h>
9262306a36Sopenharmony_ci#include "pcie-designware.h"
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci#define AL_PCIE_REV_ID_2	2
9562306a36Sopenharmony_ci#define AL_PCIE_REV_ID_3	3
9662306a36Sopenharmony_ci#define AL_PCIE_REV_ID_4	4
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci#define AXI_BASE_OFFSET		0x0
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci#define DEVICE_ID_OFFSET	0x16c
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci#define DEVICE_REV_ID			0x0
10362306a36Sopenharmony_ci#define DEVICE_REV_ID_DEV_ID_MASK	GENMASK(31, 16)
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci#define DEVICE_REV_ID_DEV_ID_X4		0
10662306a36Sopenharmony_ci#define DEVICE_REV_ID_DEV_ID_X8		2
10762306a36Sopenharmony_ci#define DEVICE_REV_ID_DEV_ID_X16	4
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci#define OB_CTRL_REV1_2_OFFSET	0x0040
11062306a36Sopenharmony_ci#define OB_CTRL_REV3_5_OFFSET	0x0030
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci#define CFG_TARGET_BUS			0x0
11362306a36Sopenharmony_ci#define CFG_TARGET_BUS_MASK_MASK	GENMASK(7, 0)
11462306a36Sopenharmony_ci#define CFG_TARGET_BUS_BUSNUM_MASK	GENMASK(15, 8)
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci#define CFG_CONTROL			0x4
11762306a36Sopenharmony_ci#define CFG_CONTROL_SUBBUS_MASK		GENMASK(15, 8)
11862306a36Sopenharmony_ci#define CFG_CONTROL_SEC_BUS_MASK	GENMASK(23, 16)
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_cistruct al_pcie_reg_offsets {
12162306a36Sopenharmony_ci	unsigned int ob_ctrl;
12262306a36Sopenharmony_ci};
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_cistruct al_pcie_target_bus_cfg {
12562306a36Sopenharmony_ci	u8 reg_val;
12662306a36Sopenharmony_ci	u8 reg_mask;
12762306a36Sopenharmony_ci	u8 ecam_mask;
12862306a36Sopenharmony_ci};
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_cistruct al_pcie {
13162306a36Sopenharmony_ci	struct dw_pcie *pci;
13262306a36Sopenharmony_ci	void __iomem *controller_base; /* base of PCIe unit (not DW core) */
13362306a36Sopenharmony_ci	struct device *dev;
13462306a36Sopenharmony_ci	resource_size_t ecam_size;
13562306a36Sopenharmony_ci	unsigned int controller_rev_id;
13662306a36Sopenharmony_ci	struct al_pcie_reg_offsets reg_offsets;
13762306a36Sopenharmony_ci	struct al_pcie_target_bus_cfg target_bus_cfg;
13862306a36Sopenharmony_ci};
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci#define to_al_pcie(x)		dev_get_drvdata((x)->dev)
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cistatic inline u32 al_pcie_controller_readl(struct al_pcie *pcie, u32 offset)
14362306a36Sopenharmony_ci{
14462306a36Sopenharmony_ci	return readl_relaxed(pcie->controller_base + offset);
14562306a36Sopenharmony_ci}
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_cistatic inline void al_pcie_controller_writel(struct al_pcie *pcie, u32 offset,
14862306a36Sopenharmony_ci					     u32 val)
14962306a36Sopenharmony_ci{
15062306a36Sopenharmony_ci	writel_relaxed(val, pcie->controller_base + offset);
15162306a36Sopenharmony_ci}
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_cistatic int al_pcie_rev_id_get(struct al_pcie *pcie, unsigned int *rev_id)
15462306a36Sopenharmony_ci{
15562306a36Sopenharmony_ci	u32 dev_rev_id_val;
15662306a36Sopenharmony_ci	u32 dev_id_val;
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	dev_rev_id_val = al_pcie_controller_readl(pcie, AXI_BASE_OFFSET +
15962306a36Sopenharmony_ci						  DEVICE_ID_OFFSET +
16062306a36Sopenharmony_ci						  DEVICE_REV_ID);
16162306a36Sopenharmony_ci	dev_id_val = FIELD_GET(DEVICE_REV_ID_DEV_ID_MASK, dev_rev_id_val);
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	switch (dev_id_val) {
16462306a36Sopenharmony_ci	case DEVICE_REV_ID_DEV_ID_X4:
16562306a36Sopenharmony_ci		*rev_id = AL_PCIE_REV_ID_2;
16662306a36Sopenharmony_ci		break;
16762306a36Sopenharmony_ci	case DEVICE_REV_ID_DEV_ID_X8:
16862306a36Sopenharmony_ci		*rev_id = AL_PCIE_REV_ID_3;
16962306a36Sopenharmony_ci		break;
17062306a36Sopenharmony_ci	case DEVICE_REV_ID_DEV_ID_X16:
17162306a36Sopenharmony_ci		*rev_id = AL_PCIE_REV_ID_4;
17262306a36Sopenharmony_ci		break;
17362306a36Sopenharmony_ci	default:
17462306a36Sopenharmony_ci		dev_err(pcie->dev, "Unsupported dev_id_val (0x%x)\n",
17562306a36Sopenharmony_ci			dev_id_val);
17662306a36Sopenharmony_ci		return -EINVAL;
17762306a36Sopenharmony_ci	}
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	dev_dbg(pcie->dev, "dev_id_val: 0x%x\n", dev_id_val);
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	return 0;
18262306a36Sopenharmony_ci}
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_cistatic int al_pcie_reg_offsets_set(struct al_pcie *pcie)
18562306a36Sopenharmony_ci{
18662306a36Sopenharmony_ci	switch (pcie->controller_rev_id) {
18762306a36Sopenharmony_ci	case AL_PCIE_REV_ID_2:
18862306a36Sopenharmony_ci		pcie->reg_offsets.ob_ctrl = OB_CTRL_REV1_2_OFFSET;
18962306a36Sopenharmony_ci		break;
19062306a36Sopenharmony_ci	case AL_PCIE_REV_ID_3:
19162306a36Sopenharmony_ci	case AL_PCIE_REV_ID_4:
19262306a36Sopenharmony_ci		pcie->reg_offsets.ob_ctrl = OB_CTRL_REV3_5_OFFSET;
19362306a36Sopenharmony_ci		break;
19462306a36Sopenharmony_ci	default:
19562306a36Sopenharmony_ci		dev_err(pcie->dev, "Unsupported controller rev_id: 0x%x\n",
19662306a36Sopenharmony_ci			pcie->controller_rev_id);
19762306a36Sopenharmony_ci		return -EINVAL;
19862306a36Sopenharmony_ci	}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	return 0;
20162306a36Sopenharmony_ci}
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_cistatic inline void al_pcie_target_bus_set(struct al_pcie *pcie,
20462306a36Sopenharmony_ci					  u8 target_bus,
20562306a36Sopenharmony_ci					  u8 mask_target_bus)
20662306a36Sopenharmony_ci{
20762306a36Sopenharmony_ci	u32 reg;
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	reg = FIELD_PREP(CFG_TARGET_BUS_MASK_MASK, mask_target_bus) |
21062306a36Sopenharmony_ci	      FIELD_PREP(CFG_TARGET_BUS_BUSNUM_MASK, target_bus);
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	al_pcie_controller_writel(pcie, AXI_BASE_OFFSET +
21362306a36Sopenharmony_ci				  pcie->reg_offsets.ob_ctrl + CFG_TARGET_BUS,
21462306a36Sopenharmony_ci				  reg);
21562306a36Sopenharmony_ci}
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_cistatic void __iomem *al_pcie_conf_addr_map_bus(struct pci_bus *bus,
21862306a36Sopenharmony_ci					       unsigned int devfn, int where)
21962306a36Sopenharmony_ci{
22062306a36Sopenharmony_ci	struct dw_pcie_rp *pp = bus->sysdata;
22162306a36Sopenharmony_ci	struct al_pcie *pcie = to_al_pcie(to_dw_pcie_from_pp(pp));
22262306a36Sopenharmony_ci	unsigned int busnr = bus->number;
22362306a36Sopenharmony_ci	struct al_pcie_target_bus_cfg *target_bus_cfg = &pcie->target_bus_cfg;
22462306a36Sopenharmony_ci	unsigned int busnr_ecam = busnr & target_bus_cfg->ecam_mask;
22562306a36Sopenharmony_ci	unsigned int busnr_reg = busnr & target_bus_cfg->reg_mask;
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	if (busnr_reg != target_bus_cfg->reg_val) {
22862306a36Sopenharmony_ci		dev_dbg(pcie->pci->dev, "Changing target bus busnum val from 0x%x to 0x%x\n",
22962306a36Sopenharmony_ci			target_bus_cfg->reg_val, busnr_reg);
23062306a36Sopenharmony_ci		target_bus_cfg->reg_val = busnr_reg;
23162306a36Sopenharmony_ci		al_pcie_target_bus_set(pcie,
23262306a36Sopenharmony_ci				       target_bus_cfg->reg_val,
23362306a36Sopenharmony_ci				       target_bus_cfg->reg_mask);
23462306a36Sopenharmony_ci	}
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	return pp->va_cfg0_base + PCIE_ECAM_OFFSET(busnr_ecam, devfn, where);
23762306a36Sopenharmony_ci}
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_cistatic struct pci_ops al_child_pci_ops = {
24062306a36Sopenharmony_ci	.map_bus = al_pcie_conf_addr_map_bus,
24162306a36Sopenharmony_ci	.read = pci_generic_config_read,
24262306a36Sopenharmony_ci	.write = pci_generic_config_write,
24362306a36Sopenharmony_ci};
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_cistatic void al_pcie_config_prepare(struct al_pcie *pcie)
24662306a36Sopenharmony_ci{
24762306a36Sopenharmony_ci	struct al_pcie_target_bus_cfg *target_bus_cfg;
24862306a36Sopenharmony_ci	struct dw_pcie_rp *pp = &pcie->pci->pp;
24962306a36Sopenharmony_ci	unsigned int ecam_bus_mask;
25062306a36Sopenharmony_ci	u32 cfg_control_offset;
25162306a36Sopenharmony_ci	u8 subordinate_bus;
25262306a36Sopenharmony_ci	u8 secondary_bus;
25362306a36Sopenharmony_ci	u32 cfg_control;
25462306a36Sopenharmony_ci	u32 reg;
25562306a36Sopenharmony_ci	struct resource *bus = resource_list_first_type(&pp->bridge->windows, IORESOURCE_BUS)->res;
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	target_bus_cfg = &pcie->target_bus_cfg;
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	ecam_bus_mask = (pcie->ecam_size >> PCIE_ECAM_BUS_SHIFT) - 1;
26062306a36Sopenharmony_ci	if (ecam_bus_mask > 255) {
26162306a36Sopenharmony_ci		dev_warn(pcie->dev, "ECAM window size is larger than 256MB. Cutting off at 256\n");
26262306a36Sopenharmony_ci		ecam_bus_mask = 255;
26362306a36Sopenharmony_ci	}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	/* This portion is taken from the transaction address */
26662306a36Sopenharmony_ci	target_bus_cfg->ecam_mask = ecam_bus_mask;
26762306a36Sopenharmony_ci	/* This portion is taken from the cfg_target_bus reg */
26862306a36Sopenharmony_ci	target_bus_cfg->reg_mask = ~target_bus_cfg->ecam_mask;
26962306a36Sopenharmony_ci	target_bus_cfg->reg_val = bus->start & target_bus_cfg->reg_mask;
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	al_pcie_target_bus_set(pcie, target_bus_cfg->reg_val,
27262306a36Sopenharmony_ci			       target_bus_cfg->reg_mask);
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	secondary_bus = bus->start + 1;
27562306a36Sopenharmony_ci	subordinate_bus = bus->end;
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	/* Set the valid values of secondary and subordinate buses */
27862306a36Sopenharmony_ci	cfg_control_offset = AXI_BASE_OFFSET + pcie->reg_offsets.ob_ctrl +
27962306a36Sopenharmony_ci			     CFG_CONTROL;
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	cfg_control = al_pcie_controller_readl(pcie, cfg_control_offset);
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	reg = cfg_control &
28462306a36Sopenharmony_ci	      ~(CFG_CONTROL_SEC_BUS_MASK | CFG_CONTROL_SUBBUS_MASK);
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	reg |= FIELD_PREP(CFG_CONTROL_SUBBUS_MASK, subordinate_bus) |
28762306a36Sopenharmony_ci	       FIELD_PREP(CFG_CONTROL_SEC_BUS_MASK, secondary_bus);
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	al_pcie_controller_writel(pcie, cfg_control_offset, reg);
29062306a36Sopenharmony_ci}
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_cistatic int al_pcie_host_init(struct dw_pcie_rp *pp)
29362306a36Sopenharmony_ci{
29462306a36Sopenharmony_ci	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
29562306a36Sopenharmony_ci	struct al_pcie *pcie = to_al_pcie(pci);
29662306a36Sopenharmony_ci	int rc;
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	pp->bridge->child_ops = &al_child_pci_ops;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	rc = al_pcie_rev_id_get(pcie, &pcie->controller_rev_id);
30162306a36Sopenharmony_ci	if (rc)
30262306a36Sopenharmony_ci		return rc;
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	rc = al_pcie_reg_offsets_set(pcie);
30562306a36Sopenharmony_ci	if (rc)
30662306a36Sopenharmony_ci		return rc;
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	al_pcie_config_prepare(pcie);
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	return 0;
31162306a36Sopenharmony_ci}
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_cistatic const struct dw_pcie_host_ops al_pcie_host_ops = {
31462306a36Sopenharmony_ci	.host_init = al_pcie_host_init,
31562306a36Sopenharmony_ci};
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_cistatic int al_pcie_probe(struct platform_device *pdev)
31862306a36Sopenharmony_ci{
31962306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
32062306a36Sopenharmony_ci	struct resource *controller_res;
32162306a36Sopenharmony_ci	struct resource *ecam_res;
32262306a36Sopenharmony_ci	struct al_pcie *al_pcie;
32362306a36Sopenharmony_ci	struct dw_pcie *pci;
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	al_pcie = devm_kzalloc(dev, sizeof(*al_pcie), GFP_KERNEL);
32662306a36Sopenharmony_ci	if (!al_pcie)
32762306a36Sopenharmony_ci		return -ENOMEM;
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
33062306a36Sopenharmony_ci	if (!pci)
33162306a36Sopenharmony_ci		return -ENOMEM;
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	pci->dev = dev;
33462306a36Sopenharmony_ci	pci->pp.ops = &al_pcie_host_ops;
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	al_pcie->pci = pci;
33762306a36Sopenharmony_ci	al_pcie->dev = dev;
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	ecam_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
34062306a36Sopenharmony_ci	if (!ecam_res) {
34162306a36Sopenharmony_ci		dev_err(dev, "couldn't find 'config' reg in DT\n");
34262306a36Sopenharmony_ci		return -ENOENT;
34362306a36Sopenharmony_ci	}
34462306a36Sopenharmony_ci	al_pcie->ecam_size = resource_size(ecam_res);
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	controller_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
34762306a36Sopenharmony_ci						      "controller");
34862306a36Sopenharmony_ci	al_pcie->controller_base = devm_ioremap_resource(dev, controller_res);
34962306a36Sopenharmony_ci	if (IS_ERR(al_pcie->controller_base)) {
35062306a36Sopenharmony_ci		dev_err(dev, "couldn't remap controller base %pR\n",
35162306a36Sopenharmony_ci			controller_res);
35262306a36Sopenharmony_ci		return PTR_ERR(al_pcie->controller_base);
35362306a36Sopenharmony_ci	}
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	dev_dbg(dev, "From DT: controller_base: %pR\n", controller_res);
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	platform_set_drvdata(pdev, al_pcie);
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	return dw_pcie_host_init(&pci->pp);
36062306a36Sopenharmony_ci}
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_cistatic const struct of_device_id al_pcie_of_match[] = {
36362306a36Sopenharmony_ci	{ .compatible = "amazon,al-alpine-v2-pcie",
36462306a36Sopenharmony_ci	},
36562306a36Sopenharmony_ci	{ .compatible = "amazon,al-alpine-v3-pcie",
36662306a36Sopenharmony_ci	},
36762306a36Sopenharmony_ci	{},
36862306a36Sopenharmony_ci};
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_cistatic struct platform_driver al_pcie_driver = {
37162306a36Sopenharmony_ci	.driver = {
37262306a36Sopenharmony_ci		.name	= "al-pcie",
37362306a36Sopenharmony_ci		.of_match_table = al_pcie_of_match,
37462306a36Sopenharmony_ci		.suppress_bind_attrs = true,
37562306a36Sopenharmony_ci	},
37662306a36Sopenharmony_ci	.probe = al_pcie_probe,
37762306a36Sopenharmony_ci};
37862306a36Sopenharmony_cibuiltin_platform_driver(al_pcie_driver);
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci#endif /* CONFIG_PCIE_AL*/
381