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