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