162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * PCIe host controller driver for Marvell Armada-8K SoCs 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Armada-8K PCIe Glue Layer Source Code 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 2016 Marvell Technology Group Ltd. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Author: Yehuda Yitshak <yehuday@marvell.com> 1062306a36Sopenharmony_ci * Author: Shadi Ammouri <shadi@marvell.com> 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/clk.h> 1462306a36Sopenharmony_ci#include <linux/delay.h> 1562306a36Sopenharmony_ci#include <linux/interrupt.h> 1662306a36Sopenharmony_ci#include <linux/kernel.h> 1762306a36Sopenharmony_ci#include <linux/init.h> 1862306a36Sopenharmony_ci#include <linux/of.h> 1962306a36Sopenharmony_ci#include <linux/pci.h> 2062306a36Sopenharmony_ci#include <linux/phy/phy.h> 2162306a36Sopenharmony_ci#include <linux/platform_device.h> 2262306a36Sopenharmony_ci#include <linux/resource.h> 2362306a36Sopenharmony_ci#include <linux/of_pci.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include "pcie-designware.h" 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#define ARMADA8K_PCIE_MAX_LANES PCIE_LNK_X4 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistruct armada8k_pcie { 3062306a36Sopenharmony_ci struct dw_pcie *pci; 3162306a36Sopenharmony_ci struct clk *clk; 3262306a36Sopenharmony_ci struct clk *clk_reg; 3362306a36Sopenharmony_ci struct phy *phy[ARMADA8K_PCIE_MAX_LANES]; 3462306a36Sopenharmony_ci unsigned int phy_count; 3562306a36Sopenharmony_ci}; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define PCIE_VENDOR_REGS_OFFSET 0x8000 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#define PCIE_GLOBAL_CONTROL_REG (PCIE_VENDOR_REGS_OFFSET + 0x0) 4062306a36Sopenharmony_ci#define PCIE_APP_LTSSM_EN BIT(2) 4162306a36Sopenharmony_ci#define PCIE_DEVICE_TYPE_SHIFT 4 4262306a36Sopenharmony_ci#define PCIE_DEVICE_TYPE_MASK 0xF 4362306a36Sopenharmony_ci#define PCIE_DEVICE_TYPE_RC 0x4 /* Root complex */ 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#define PCIE_GLOBAL_STATUS_REG (PCIE_VENDOR_REGS_OFFSET + 0x8) 4662306a36Sopenharmony_ci#define PCIE_GLB_STS_RDLH_LINK_UP BIT(1) 4762306a36Sopenharmony_ci#define PCIE_GLB_STS_PHY_LINK_UP BIT(9) 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#define PCIE_GLOBAL_INT_CAUSE1_REG (PCIE_VENDOR_REGS_OFFSET + 0x1C) 5062306a36Sopenharmony_ci#define PCIE_GLOBAL_INT_MASK1_REG (PCIE_VENDOR_REGS_OFFSET + 0x20) 5162306a36Sopenharmony_ci#define PCIE_INT_A_ASSERT_MASK BIT(9) 5262306a36Sopenharmony_ci#define PCIE_INT_B_ASSERT_MASK BIT(10) 5362306a36Sopenharmony_ci#define PCIE_INT_C_ASSERT_MASK BIT(11) 5462306a36Sopenharmony_ci#define PCIE_INT_D_ASSERT_MASK BIT(12) 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci#define PCIE_ARCACHE_TRC_REG (PCIE_VENDOR_REGS_OFFSET + 0x50) 5762306a36Sopenharmony_ci#define PCIE_AWCACHE_TRC_REG (PCIE_VENDOR_REGS_OFFSET + 0x54) 5862306a36Sopenharmony_ci#define PCIE_ARUSER_REG (PCIE_VENDOR_REGS_OFFSET + 0x5C) 5962306a36Sopenharmony_ci#define PCIE_AWUSER_REG (PCIE_VENDOR_REGS_OFFSET + 0x60) 6062306a36Sopenharmony_ci/* 6162306a36Sopenharmony_ci * AR/AW Cache defaults: Normal memory, Write-Back, Read / Write 6262306a36Sopenharmony_ci * allocate 6362306a36Sopenharmony_ci */ 6462306a36Sopenharmony_ci#define ARCACHE_DEFAULT_VALUE 0x3511 6562306a36Sopenharmony_ci#define AWCACHE_DEFAULT_VALUE 0x5311 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci#define DOMAIN_OUTER_SHAREABLE 0x2 6862306a36Sopenharmony_ci#define AX_USER_DOMAIN_MASK 0x3 6962306a36Sopenharmony_ci#define AX_USER_DOMAIN_SHIFT 4 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci#define to_armada8k_pcie(x) dev_get_drvdata((x)->dev) 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistatic void armada8k_pcie_disable_phys(struct armada8k_pcie *pcie) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci int i; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci for (i = 0; i < ARMADA8K_PCIE_MAX_LANES; i++) { 7862306a36Sopenharmony_ci phy_power_off(pcie->phy[i]); 7962306a36Sopenharmony_ci phy_exit(pcie->phy[i]); 8062306a36Sopenharmony_ci } 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic int armada8k_pcie_enable_phys(struct armada8k_pcie *pcie) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci int ret; 8662306a36Sopenharmony_ci int i; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci for (i = 0; i < ARMADA8K_PCIE_MAX_LANES; i++) { 8962306a36Sopenharmony_ci ret = phy_init(pcie->phy[i]); 9062306a36Sopenharmony_ci if (ret) 9162306a36Sopenharmony_ci return ret; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci ret = phy_set_mode_ext(pcie->phy[i], PHY_MODE_PCIE, 9462306a36Sopenharmony_ci pcie->phy_count); 9562306a36Sopenharmony_ci if (ret) { 9662306a36Sopenharmony_ci phy_exit(pcie->phy[i]); 9762306a36Sopenharmony_ci return ret; 9862306a36Sopenharmony_ci } 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci ret = phy_power_on(pcie->phy[i]); 10162306a36Sopenharmony_ci if (ret) { 10262306a36Sopenharmony_ci phy_exit(pcie->phy[i]); 10362306a36Sopenharmony_ci return ret; 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci } 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci return 0; 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic int armada8k_pcie_setup_phys(struct armada8k_pcie *pcie) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci struct dw_pcie *pci = pcie->pci; 11362306a36Sopenharmony_ci struct device *dev = pci->dev; 11462306a36Sopenharmony_ci struct device_node *node = dev->of_node; 11562306a36Sopenharmony_ci int ret = 0; 11662306a36Sopenharmony_ci int i; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci for (i = 0; i < ARMADA8K_PCIE_MAX_LANES; i++) { 11962306a36Sopenharmony_ci pcie->phy[i] = devm_of_phy_get_by_index(dev, node, i); 12062306a36Sopenharmony_ci if (IS_ERR(pcie->phy[i])) { 12162306a36Sopenharmony_ci if (PTR_ERR(pcie->phy[i]) != -ENODEV) 12262306a36Sopenharmony_ci return PTR_ERR(pcie->phy[i]); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci pcie->phy[i] = NULL; 12562306a36Sopenharmony_ci continue; 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci pcie->phy_count++; 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci /* Old bindings miss the PHY handle, so just warn if there is no PHY */ 13262306a36Sopenharmony_ci if (!pcie->phy_count) 13362306a36Sopenharmony_ci dev_warn(dev, "No available PHY\n"); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci ret = armada8k_pcie_enable_phys(pcie); 13662306a36Sopenharmony_ci if (ret) 13762306a36Sopenharmony_ci dev_err(dev, "Failed to initialize PHY(s) (%d)\n", ret); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci return ret; 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic int armada8k_pcie_link_up(struct dw_pcie *pci) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci u32 reg; 14562306a36Sopenharmony_ci u32 mask = PCIE_GLB_STS_RDLH_LINK_UP | PCIE_GLB_STS_PHY_LINK_UP; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_STATUS_REG); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci if ((reg & mask) == mask) 15062306a36Sopenharmony_ci return 1; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci dev_dbg(pci->dev, "No link detected (Global-Status: 0x%08x).\n", reg); 15362306a36Sopenharmony_ci return 0; 15462306a36Sopenharmony_ci} 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_cistatic int armada8k_pcie_start_link(struct dw_pcie *pci) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci u32 reg; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci /* Start LTSSM */ 16162306a36Sopenharmony_ci reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_CONTROL_REG); 16262306a36Sopenharmony_ci reg |= PCIE_APP_LTSSM_EN; 16362306a36Sopenharmony_ci dw_pcie_writel_dbi(pci, PCIE_GLOBAL_CONTROL_REG, reg); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci return 0; 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic int armada8k_pcie_host_init(struct dw_pcie_rp *pp) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci u32 reg; 17162306a36Sopenharmony_ci struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci if (!dw_pcie_link_up(pci)) { 17462306a36Sopenharmony_ci /* Disable LTSSM state machine to enable configuration */ 17562306a36Sopenharmony_ci reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_CONTROL_REG); 17662306a36Sopenharmony_ci reg &= ~(PCIE_APP_LTSSM_EN); 17762306a36Sopenharmony_ci dw_pcie_writel_dbi(pci, PCIE_GLOBAL_CONTROL_REG, reg); 17862306a36Sopenharmony_ci } 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci /* Set the device to root complex mode */ 18162306a36Sopenharmony_ci reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_CONTROL_REG); 18262306a36Sopenharmony_ci reg &= ~(PCIE_DEVICE_TYPE_MASK << PCIE_DEVICE_TYPE_SHIFT); 18362306a36Sopenharmony_ci reg |= PCIE_DEVICE_TYPE_RC << PCIE_DEVICE_TYPE_SHIFT; 18462306a36Sopenharmony_ci dw_pcie_writel_dbi(pci, PCIE_GLOBAL_CONTROL_REG, reg); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci /* Set the PCIe master AxCache attributes */ 18762306a36Sopenharmony_ci dw_pcie_writel_dbi(pci, PCIE_ARCACHE_TRC_REG, ARCACHE_DEFAULT_VALUE); 18862306a36Sopenharmony_ci dw_pcie_writel_dbi(pci, PCIE_AWCACHE_TRC_REG, AWCACHE_DEFAULT_VALUE); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci /* Set the PCIe master AxDomain attributes */ 19162306a36Sopenharmony_ci reg = dw_pcie_readl_dbi(pci, PCIE_ARUSER_REG); 19262306a36Sopenharmony_ci reg &= ~(AX_USER_DOMAIN_MASK << AX_USER_DOMAIN_SHIFT); 19362306a36Sopenharmony_ci reg |= DOMAIN_OUTER_SHAREABLE << AX_USER_DOMAIN_SHIFT; 19462306a36Sopenharmony_ci dw_pcie_writel_dbi(pci, PCIE_ARUSER_REG, reg); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci reg = dw_pcie_readl_dbi(pci, PCIE_AWUSER_REG); 19762306a36Sopenharmony_ci reg &= ~(AX_USER_DOMAIN_MASK << AX_USER_DOMAIN_SHIFT); 19862306a36Sopenharmony_ci reg |= DOMAIN_OUTER_SHAREABLE << AX_USER_DOMAIN_SHIFT; 19962306a36Sopenharmony_ci dw_pcie_writel_dbi(pci, PCIE_AWUSER_REG, reg); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci /* Enable INT A-D interrupts */ 20262306a36Sopenharmony_ci reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_INT_MASK1_REG); 20362306a36Sopenharmony_ci reg |= PCIE_INT_A_ASSERT_MASK | PCIE_INT_B_ASSERT_MASK | 20462306a36Sopenharmony_ci PCIE_INT_C_ASSERT_MASK | PCIE_INT_D_ASSERT_MASK; 20562306a36Sopenharmony_ci dw_pcie_writel_dbi(pci, PCIE_GLOBAL_INT_MASK1_REG, reg); 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci return 0; 20862306a36Sopenharmony_ci} 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_cistatic irqreturn_t armada8k_pcie_irq_handler(int irq, void *arg) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci struct armada8k_pcie *pcie = arg; 21362306a36Sopenharmony_ci struct dw_pcie *pci = pcie->pci; 21462306a36Sopenharmony_ci u32 val; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci /* 21762306a36Sopenharmony_ci * Interrupts are directly handled by the device driver of the 21862306a36Sopenharmony_ci * PCI device. However, they are also latched into the PCIe 21962306a36Sopenharmony_ci * controller, so we simply discard them. 22062306a36Sopenharmony_ci */ 22162306a36Sopenharmony_ci val = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_INT_CAUSE1_REG); 22262306a36Sopenharmony_ci dw_pcie_writel_dbi(pci, PCIE_GLOBAL_INT_CAUSE1_REG, val); 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci return IRQ_HANDLED; 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cistatic const struct dw_pcie_host_ops armada8k_pcie_host_ops = { 22862306a36Sopenharmony_ci .host_init = armada8k_pcie_host_init, 22962306a36Sopenharmony_ci}; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cistatic int armada8k_add_pcie_port(struct armada8k_pcie *pcie, 23262306a36Sopenharmony_ci struct platform_device *pdev) 23362306a36Sopenharmony_ci{ 23462306a36Sopenharmony_ci struct dw_pcie *pci = pcie->pci; 23562306a36Sopenharmony_ci struct dw_pcie_rp *pp = &pci->pp; 23662306a36Sopenharmony_ci struct device *dev = &pdev->dev; 23762306a36Sopenharmony_ci int ret; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci pp->ops = &armada8k_pcie_host_ops; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci pp->irq = platform_get_irq(pdev, 0); 24262306a36Sopenharmony_ci if (pp->irq < 0) 24362306a36Sopenharmony_ci return pp->irq; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci ret = devm_request_irq(dev, pp->irq, armada8k_pcie_irq_handler, 24662306a36Sopenharmony_ci IRQF_SHARED, "armada8k-pcie", pcie); 24762306a36Sopenharmony_ci if (ret) { 24862306a36Sopenharmony_ci dev_err(dev, "failed to request irq %d\n", pp->irq); 24962306a36Sopenharmony_ci return ret; 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci ret = dw_pcie_host_init(pp); 25362306a36Sopenharmony_ci if (ret) { 25462306a36Sopenharmony_ci dev_err(dev, "failed to initialize host: %d\n", ret); 25562306a36Sopenharmony_ci return ret; 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci return 0; 25962306a36Sopenharmony_ci} 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cistatic const struct dw_pcie_ops dw_pcie_ops = { 26262306a36Sopenharmony_ci .link_up = armada8k_pcie_link_up, 26362306a36Sopenharmony_ci .start_link = armada8k_pcie_start_link, 26462306a36Sopenharmony_ci}; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_cistatic int armada8k_pcie_probe(struct platform_device *pdev) 26762306a36Sopenharmony_ci{ 26862306a36Sopenharmony_ci struct dw_pcie *pci; 26962306a36Sopenharmony_ci struct armada8k_pcie *pcie; 27062306a36Sopenharmony_ci struct device *dev = &pdev->dev; 27162306a36Sopenharmony_ci struct resource *base; 27262306a36Sopenharmony_ci int ret; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); 27562306a36Sopenharmony_ci if (!pcie) 27662306a36Sopenharmony_ci return -ENOMEM; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); 27962306a36Sopenharmony_ci if (!pci) 28062306a36Sopenharmony_ci return -ENOMEM; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci pci->dev = dev; 28362306a36Sopenharmony_ci pci->ops = &dw_pcie_ops; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci pcie->pci = pci; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci pcie->clk = devm_clk_get(dev, NULL); 28862306a36Sopenharmony_ci if (IS_ERR(pcie->clk)) 28962306a36Sopenharmony_ci return PTR_ERR(pcie->clk); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci ret = clk_prepare_enable(pcie->clk); 29262306a36Sopenharmony_ci if (ret) 29362306a36Sopenharmony_ci return ret; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci pcie->clk_reg = devm_clk_get(dev, "reg"); 29662306a36Sopenharmony_ci if (pcie->clk_reg == ERR_PTR(-EPROBE_DEFER)) { 29762306a36Sopenharmony_ci ret = -EPROBE_DEFER; 29862306a36Sopenharmony_ci goto fail; 29962306a36Sopenharmony_ci } 30062306a36Sopenharmony_ci if (!IS_ERR(pcie->clk_reg)) { 30162306a36Sopenharmony_ci ret = clk_prepare_enable(pcie->clk_reg); 30262306a36Sopenharmony_ci if (ret) 30362306a36Sopenharmony_ci goto fail_clkreg; 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci /* Get the dw-pcie unit configuration/control registers base. */ 30762306a36Sopenharmony_ci base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl"); 30862306a36Sopenharmony_ci pci->dbi_base = devm_pci_remap_cfg_resource(dev, base); 30962306a36Sopenharmony_ci if (IS_ERR(pci->dbi_base)) { 31062306a36Sopenharmony_ci ret = PTR_ERR(pci->dbi_base); 31162306a36Sopenharmony_ci goto fail_clkreg; 31262306a36Sopenharmony_ci } 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci ret = armada8k_pcie_setup_phys(pcie); 31562306a36Sopenharmony_ci if (ret) 31662306a36Sopenharmony_ci goto fail_clkreg; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci platform_set_drvdata(pdev, pcie); 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci ret = armada8k_add_pcie_port(pcie, pdev); 32162306a36Sopenharmony_ci if (ret) 32262306a36Sopenharmony_ci goto disable_phy; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci return 0; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_cidisable_phy: 32762306a36Sopenharmony_ci armada8k_pcie_disable_phys(pcie); 32862306a36Sopenharmony_cifail_clkreg: 32962306a36Sopenharmony_ci clk_disable_unprepare(pcie->clk_reg); 33062306a36Sopenharmony_cifail: 33162306a36Sopenharmony_ci clk_disable_unprepare(pcie->clk); 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci return ret; 33462306a36Sopenharmony_ci} 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_cistatic const struct of_device_id armada8k_pcie_of_match[] = { 33762306a36Sopenharmony_ci { .compatible = "marvell,armada8k-pcie", }, 33862306a36Sopenharmony_ci {}, 33962306a36Sopenharmony_ci}; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_cistatic struct platform_driver armada8k_pcie_driver = { 34262306a36Sopenharmony_ci .probe = armada8k_pcie_probe, 34362306a36Sopenharmony_ci .driver = { 34462306a36Sopenharmony_ci .name = "armada8k-pcie", 34562306a36Sopenharmony_ci .of_match_table = armada8k_pcie_of_match, 34662306a36Sopenharmony_ci .suppress_bind_attrs = true, 34762306a36Sopenharmony_ci }, 34862306a36Sopenharmony_ci}; 34962306a36Sopenharmony_cibuiltin_platform_driver(armada8k_pcie_driver); 350