162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * PCIe host controller driver for Intel Gateway SoCs
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2019 Intel Corporation.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/bitfield.h>
962306a36Sopenharmony_ci#include <linux/clk.h>
1062306a36Sopenharmony_ci#include <linux/gpio/consumer.h>
1162306a36Sopenharmony_ci#include <linux/iopoll.h>
1262306a36Sopenharmony_ci#include <linux/mod_devicetable.h>
1362306a36Sopenharmony_ci#include <linux/pci_regs.h>
1462306a36Sopenharmony_ci#include <linux/phy/phy.h>
1562306a36Sopenharmony_ci#include <linux/platform_device.h>
1662306a36Sopenharmony_ci#include <linux/property.h>
1762306a36Sopenharmony_ci#include <linux/reset.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include "../../pci.h"
2062306a36Sopenharmony_ci#include "pcie-designware.h"
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#define PORT_AFR_N_FTS_GEN12_DFT	(SZ_128 - 1)
2362306a36Sopenharmony_ci#define PORT_AFR_N_FTS_GEN3		180
2462306a36Sopenharmony_ci#define PORT_AFR_N_FTS_GEN4		196
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci/* PCIe Application logic Registers */
2762306a36Sopenharmony_ci#define PCIE_APP_CCR			0x10
2862306a36Sopenharmony_ci#define PCIE_APP_CCR_LTSSM_ENABLE	BIT(0)
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#define PCIE_APP_MSG_CR			0x30
3162306a36Sopenharmony_ci#define PCIE_APP_MSG_XMT_PM_TURNOFF	BIT(0)
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#define PCIE_APP_PMC			0x44
3462306a36Sopenharmony_ci#define PCIE_APP_PMC_IN_L2		BIT(20)
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#define PCIE_APP_IRNEN			0xF4
3762306a36Sopenharmony_ci#define PCIE_APP_IRNCR			0xF8
3862306a36Sopenharmony_ci#define PCIE_APP_IRN_AER_REPORT		BIT(0)
3962306a36Sopenharmony_ci#define PCIE_APP_IRN_PME		BIT(2)
4062306a36Sopenharmony_ci#define PCIE_APP_IRN_RX_VDM_MSG		BIT(4)
4162306a36Sopenharmony_ci#define PCIE_APP_IRN_PM_TO_ACK		BIT(9)
4262306a36Sopenharmony_ci#define PCIE_APP_IRN_LINK_AUTO_BW_STAT	BIT(11)
4362306a36Sopenharmony_ci#define PCIE_APP_IRN_BW_MGT		BIT(12)
4462306a36Sopenharmony_ci#define PCIE_APP_IRN_INTA		BIT(13)
4562306a36Sopenharmony_ci#define PCIE_APP_IRN_INTB		BIT(14)
4662306a36Sopenharmony_ci#define PCIE_APP_IRN_INTC		BIT(15)
4762306a36Sopenharmony_ci#define PCIE_APP_IRN_INTD		BIT(16)
4862306a36Sopenharmony_ci#define PCIE_APP_IRN_MSG_LTR		BIT(18)
4962306a36Sopenharmony_ci#define PCIE_APP_IRN_SYS_ERR_RC		BIT(29)
5062306a36Sopenharmony_ci#define PCIE_APP_INTX_OFST		12
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#define PCIE_APP_IRN_INT \
5362306a36Sopenharmony_ci	(PCIE_APP_IRN_AER_REPORT | PCIE_APP_IRN_PME | \
5462306a36Sopenharmony_ci	PCIE_APP_IRN_RX_VDM_MSG | PCIE_APP_IRN_SYS_ERR_RC | \
5562306a36Sopenharmony_ci	PCIE_APP_IRN_PM_TO_ACK | PCIE_APP_IRN_MSG_LTR | \
5662306a36Sopenharmony_ci	PCIE_APP_IRN_BW_MGT | PCIE_APP_IRN_LINK_AUTO_BW_STAT | \
5762306a36Sopenharmony_ci	PCIE_APP_IRN_INTA | PCIE_APP_IRN_INTB | \
5862306a36Sopenharmony_ci	PCIE_APP_IRN_INTC | PCIE_APP_IRN_INTD)
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci#define BUS_IATU_OFFSET			SZ_256M
6162306a36Sopenharmony_ci#define RESET_INTERVAL_MS		100
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistruct intel_pcie {
6462306a36Sopenharmony_ci	struct dw_pcie		pci;
6562306a36Sopenharmony_ci	void __iomem		*app_base;
6662306a36Sopenharmony_ci	struct gpio_desc	*reset_gpio;
6762306a36Sopenharmony_ci	u32			rst_intrvl;
6862306a36Sopenharmony_ci	struct clk		*core_clk;
6962306a36Sopenharmony_ci	struct reset_control	*core_rst;
7062306a36Sopenharmony_ci	struct phy		*phy;
7162306a36Sopenharmony_ci};
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_cistatic void pcie_update_bits(void __iomem *base, u32 ofs, u32 mask, u32 val)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	u32 old;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	old = readl(base + ofs);
7862306a36Sopenharmony_ci	val = (old & ~mask) | (val & mask);
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	if (val != old)
8162306a36Sopenharmony_ci		writel(val, base + ofs);
8262306a36Sopenharmony_ci}
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_cistatic inline void pcie_app_wr(struct intel_pcie *pcie, u32 ofs, u32 val)
8562306a36Sopenharmony_ci{
8662306a36Sopenharmony_ci	writel(val, pcie->app_base + ofs);
8762306a36Sopenharmony_ci}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistatic void pcie_app_wr_mask(struct intel_pcie *pcie, u32 ofs,
9062306a36Sopenharmony_ci			     u32 mask, u32 val)
9162306a36Sopenharmony_ci{
9262306a36Sopenharmony_ci	pcie_update_bits(pcie->app_base, ofs, mask, val);
9362306a36Sopenharmony_ci}
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_cistatic inline u32 pcie_rc_cfg_rd(struct intel_pcie *pcie, u32 ofs)
9662306a36Sopenharmony_ci{
9762306a36Sopenharmony_ci	return dw_pcie_readl_dbi(&pcie->pci, ofs);
9862306a36Sopenharmony_ci}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_cistatic inline void pcie_rc_cfg_wr(struct intel_pcie *pcie, u32 ofs, u32 val)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	dw_pcie_writel_dbi(&pcie->pci, ofs, val);
10362306a36Sopenharmony_ci}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cistatic void pcie_rc_cfg_wr_mask(struct intel_pcie *pcie, u32 ofs,
10662306a36Sopenharmony_ci				u32 mask, u32 val)
10762306a36Sopenharmony_ci{
10862306a36Sopenharmony_ci	pcie_update_bits(pcie->pci.dbi_base, ofs, mask, val);
10962306a36Sopenharmony_ci}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic void intel_pcie_ltssm_enable(struct intel_pcie *pcie)
11262306a36Sopenharmony_ci{
11362306a36Sopenharmony_ci	pcie_app_wr_mask(pcie, PCIE_APP_CCR, PCIE_APP_CCR_LTSSM_ENABLE,
11462306a36Sopenharmony_ci			 PCIE_APP_CCR_LTSSM_ENABLE);
11562306a36Sopenharmony_ci}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistatic void intel_pcie_ltssm_disable(struct intel_pcie *pcie)
11862306a36Sopenharmony_ci{
11962306a36Sopenharmony_ci	pcie_app_wr_mask(pcie, PCIE_APP_CCR, PCIE_APP_CCR_LTSSM_ENABLE, 0);
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_cistatic void intel_pcie_link_setup(struct intel_pcie *pcie)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	u32 val;
12562306a36Sopenharmony_ci	u8 offset = dw_pcie_find_capability(&pcie->pci, PCI_CAP_ID_EXP);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	val = pcie_rc_cfg_rd(pcie, offset + PCI_EXP_LNKCTL);
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	val &= ~(PCI_EXP_LNKCTL_LD | PCI_EXP_LNKCTL_ASPMC);
13062306a36Sopenharmony_ci	pcie_rc_cfg_wr(pcie, offset + PCI_EXP_LNKCTL, val);
13162306a36Sopenharmony_ci}
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_cistatic void intel_pcie_init_n_fts(struct dw_pcie *pci)
13462306a36Sopenharmony_ci{
13562306a36Sopenharmony_ci	switch (pci->link_gen) {
13662306a36Sopenharmony_ci	case 3:
13762306a36Sopenharmony_ci		pci->n_fts[1] = PORT_AFR_N_FTS_GEN3;
13862306a36Sopenharmony_ci		break;
13962306a36Sopenharmony_ci	case 4:
14062306a36Sopenharmony_ci		pci->n_fts[1] = PORT_AFR_N_FTS_GEN4;
14162306a36Sopenharmony_ci		break;
14262306a36Sopenharmony_ci	default:
14362306a36Sopenharmony_ci		pci->n_fts[1] = PORT_AFR_N_FTS_GEN12_DFT;
14462306a36Sopenharmony_ci		break;
14562306a36Sopenharmony_ci	}
14662306a36Sopenharmony_ci	pci->n_fts[0] = PORT_AFR_N_FTS_GEN12_DFT;
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_cistatic int intel_pcie_ep_rst_init(struct intel_pcie *pcie)
15062306a36Sopenharmony_ci{
15162306a36Sopenharmony_ci	struct device *dev = pcie->pci.dev;
15262306a36Sopenharmony_ci	int ret;
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	pcie->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
15562306a36Sopenharmony_ci	if (IS_ERR(pcie->reset_gpio)) {
15662306a36Sopenharmony_ci		ret = PTR_ERR(pcie->reset_gpio);
15762306a36Sopenharmony_ci		if (ret != -EPROBE_DEFER)
15862306a36Sopenharmony_ci			dev_err(dev, "Failed to request PCIe GPIO: %d\n", ret);
15962306a36Sopenharmony_ci		return ret;
16062306a36Sopenharmony_ci	}
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	/* Make initial reset last for 100us */
16362306a36Sopenharmony_ci	usleep_range(100, 200);
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	return 0;
16662306a36Sopenharmony_ci}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_cistatic void intel_pcie_core_rst_assert(struct intel_pcie *pcie)
16962306a36Sopenharmony_ci{
17062306a36Sopenharmony_ci	reset_control_assert(pcie->core_rst);
17162306a36Sopenharmony_ci}
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_cistatic void intel_pcie_core_rst_deassert(struct intel_pcie *pcie)
17462306a36Sopenharmony_ci{
17562306a36Sopenharmony_ci	/*
17662306a36Sopenharmony_ci	 * One micro-second delay to make sure the reset pulse
17762306a36Sopenharmony_ci	 * wide enough so that core reset is clean.
17862306a36Sopenharmony_ci	 */
17962306a36Sopenharmony_ci	udelay(1);
18062306a36Sopenharmony_ci	reset_control_deassert(pcie->core_rst);
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	/*
18362306a36Sopenharmony_ci	 * Some SoC core reset also reset PHY, more delay needed
18462306a36Sopenharmony_ci	 * to make sure the reset process is done.
18562306a36Sopenharmony_ci	 */
18662306a36Sopenharmony_ci	usleep_range(1000, 2000);
18762306a36Sopenharmony_ci}
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_cistatic void intel_pcie_device_rst_assert(struct intel_pcie *pcie)
19062306a36Sopenharmony_ci{
19162306a36Sopenharmony_ci	gpiod_set_value_cansleep(pcie->reset_gpio, 1);
19262306a36Sopenharmony_ci}
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_cistatic void intel_pcie_device_rst_deassert(struct intel_pcie *pcie)
19562306a36Sopenharmony_ci{
19662306a36Sopenharmony_ci	msleep(pcie->rst_intrvl);
19762306a36Sopenharmony_ci	gpiod_set_value_cansleep(pcie->reset_gpio, 0);
19862306a36Sopenharmony_ci}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_cistatic void intel_pcie_core_irq_disable(struct intel_pcie *pcie)
20162306a36Sopenharmony_ci{
20262306a36Sopenharmony_ci	pcie_app_wr(pcie, PCIE_APP_IRNEN, 0);
20362306a36Sopenharmony_ci	pcie_app_wr(pcie, PCIE_APP_IRNCR, PCIE_APP_IRN_INT);
20462306a36Sopenharmony_ci}
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistatic int intel_pcie_get_resources(struct platform_device *pdev)
20762306a36Sopenharmony_ci{
20862306a36Sopenharmony_ci	struct intel_pcie *pcie = platform_get_drvdata(pdev);
20962306a36Sopenharmony_ci	struct dw_pcie *pci = &pcie->pci;
21062306a36Sopenharmony_ci	struct device *dev = pci->dev;
21162306a36Sopenharmony_ci	int ret;
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	pcie->core_clk = devm_clk_get(dev, NULL);
21462306a36Sopenharmony_ci	if (IS_ERR(pcie->core_clk)) {
21562306a36Sopenharmony_ci		ret = PTR_ERR(pcie->core_clk);
21662306a36Sopenharmony_ci		if (ret != -EPROBE_DEFER)
21762306a36Sopenharmony_ci			dev_err(dev, "Failed to get clks: %d\n", ret);
21862306a36Sopenharmony_ci		return ret;
21962306a36Sopenharmony_ci	}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	pcie->core_rst = devm_reset_control_get(dev, NULL);
22262306a36Sopenharmony_ci	if (IS_ERR(pcie->core_rst)) {
22362306a36Sopenharmony_ci		ret = PTR_ERR(pcie->core_rst);
22462306a36Sopenharmony_ci		if (ret != -EPROBE_DEFER)
22562306a36Sopenharmony_ci			dev_err(dev, "Failed to get resets: %d\n", ret);
22662306a36Sopenharmony_ci		return ret;
22762306a36Sopenharmony_ci	}
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	ret = device_property_read_u32(dev, "reset-assert-ms",
23062306a36Sopenharmony_ci				       &pcie->rst_intrvl);
23162306a36Sopenharmony_ci	if (ret)
23262306a36Sopenharmony_ci		pcie->rst_intrvl = RESET_INTERVAL_MS;
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	pcie->app_base = devm_platform_ioremap_resource_byname(pdev, "app");
23562306a36Sopenharmony_ci	if (IS_ERR(pcie->app_base))
23662306a36Sopenharmony_ci		return PTR_ERR(pcie->app_base);
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	pcie->phy = devm_phy_get(dev, "pcie");
23962306a36Sopenharmony_ci	if (IS_ERR(pcie->phy)) {
24062306a36Sopenharmony_ci		ret = PTR_ERR(pcie->phy);
24162306a36Sopenharmony_ci		if (ret != -EPROBE_DEFER)
24262306a36Sopenharmony_ci			dev_err(dev, "Couldn't get pcie-phy: %d\n", ret);
24362306a36Sopenharmony_ci		return ret;
24462306a36Sopenharmony_ci	}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	return 0;
24762306a36Sopenharmony_ci}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_cistatic int intel_pcie_wait_l2(struct intel_pcie *pcie)
25062306a36Sopenharmony_ci{
25162306a36Sopenharmony_ci	u32 value;
25262306a36Sopenharmony_ci	int ret;
25362306a36Sopenharmony_ci	struct dw_pcie *pci = &pcie->pci;
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	if (pci->link_gen < 3)
25662306a36Sopenharmony_ci		return 0;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	/* Send PME_TURN_OFF message */
25962306a36Sopenharmony_ci	pcie_app_wr_mask(pcie, PCIE_APP_MSG_CR, PCIE_APP_MSG_XMT_PM_TURNOFF,
26062306a36Sopenharmony_ci			 PCIE_APP_MSG_XMT_PM_TURNOFF);
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	/* Read PMC status and wait for falling into L2 link state */
26362306a36Sopenharmony_ci	ret = readl_poll_timeout(pcie->app_base + PCIE_APP_PMC, value,
26462306a36Sopenharmony_ci				 value & PCIE_APP_PMC_IN_L2, 20,
26562306a36Sopenharmony_ci				 jiffies_to_usecs(5 * HZ));
26662306a36Sopenharmony_ci	if (ret)
26762306a36Sopenharmony_ci		dev_err(pcie->pci.dev, "PCIe link enter L2 timeout!\n");
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	return ret;
27062306a36Sopenharmony_ci}
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_cistatic void intel_pcie_turn_off(struct intel_pcie *pcie)
27362306a36Sopenharmony_ci{
27462306a36Sopenharmony_ci	if (dw_pcie_link_up(&pcie->pci))
27562306a36Sopenharmony_ci		intel_pcie_wait_l2(pcie);
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	/* Put endpoint device in reset state */
27862306a36Sopenharmony_ci	intel_pcie_device_rst_assert(pcie);
27962306a36Sopenharmony_ci	pcie_rc_cfg_wr_mask(pcie, PCI_COMMAND, PCI_COMMAND_MEMORY, 0);
28062306a36Sopenharmony_ci}
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_cistatic int intel_pcie_host_setup(struct intel_pcie *pcie)
28362306a36Sopenharmony_ci{
28462306a36Sopenharmony_ci	int ret;
28562306a36Sopenharmony_ci	struct dw_pcie *pci = &pcie->pci;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	intel_pcie_core_rst_assert(pcie);
28862306a36Sopenharmony_ci	intel_pcie_device_rst_assert(pcie);
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	ret = phy_init(pcie->phy);
29162306a36Sopenharmony_ci	if (ret)
29262306a36Sopenharmony_ci		return ret;
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	intel_pcie_core_rst_deassert(pcie);
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	ret = clk_prepare_enable(pcie->core_clk);
29762306a36Sopenharmony_ci	if (ret) {
29862306a36Sopenharmony_ci		dev_err(pcie->pci.dev, "Core clock enable failed: %d\n", ret);
29962306a36Sopenharmony_ci		goto clk_err;
30062306a36Sopenharmony_ci	}
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	pci->atu_base = pci->dbi_base + 0xC0000;
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	intel_pcie_ltssm_disable(pcie);
30562306a36Sopenharmony_ci	intel_pcie_link_setup(pcie);
30662306a36Sopenharmony_ci	intel_pcie_init_n_fts(pci);
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	ret = dw_pcie_setup_rc(&pci->pp);
30962306a36Sopenharmony_ci	if (ret)
31062306a36Sopenharmony_ci		goto app_init_err;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	dw_pcie_upconfig_setup(pci);
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	intel_pcie_device_rst_deassert(pcie);
31562306a36Sopenharmony_ci	intel_pcie_ltssm_enable(pcie);
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	ret = dw_pcie_wait_for_link(pci);
31862306a36Sopenharmony_ci	if (ret)
31962306a36Sopenharmony_ci		goto app_init_err;
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	/* Enable integrated interrupts */
32262306a36Sopenharmony_ci	pcie_app_wr_mask(pcie, PCIE_APP_IRNEN, PCIE_APP_IRN_INT,
32362306a36Sopenharmony_ci			 PCIE_APP_IRN_INT);
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	return 0;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ciapp_init_err:
32862306a36Sopenharmony_ci	clk_disable_unprepare(pcie->core_clk);
32962306a36Sopenharmony_ciclk_err:
33062306a36Sopenharmony_ci	intel_pcie_core_rst_assert(pcie);
33162306a36Sopenharmony_ci	phy_exit(pcie->phy);
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	return ret;
33462306a36Sopenharmony_ci}
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_cistatic void __intel_pcie_remove(struct intel_pcie *pcie)
33762306a36Sopenharmony_ci{
33862306a36Sopenharmony_ci	intel_pcie_core_irq_disable(pcie);
33962306a36Sopenharmony_ci	intel_pcie_turn_off(pcie);
34062306a36Sopenharmony_ci	clk_disable_unprepare(pcie->core_clk);
34162306a36Sopenharmony_ci	intel_pcie_core_rst_assert(pcie);
34262306a36Sopenharmony_ci	phy_exit(pcie->phy);
34362306a36Sopenharmony_ci}
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_cistatic void intel_pcie_remove(struct platform_device *pdev)
34662306a36Sopenharmony_ci{
34762306a36Sopenharmony_ci	struct intel_pcie *pcie = platform_get_drvdata(pdev);
34862306a36Sopenharmony_ci	struct dw_pcie_rp *pp = &pcie->pci.pp;
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	dw_pcie_host_deinit(pp);
35162306a36Sopenharmony_ci	__intel_pcie_remove(pcie);
35262306a36Sopenharmony_ci}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_cistatic int intel_pcie_suspend_noirq(struct device *dev)
35562306a36Sopenharmony_ci{
35662306a36Sopenharmony_ci	struct intel_pcie *pcie = dev_get_drvdata(dev);
35762306a36Sopenharmony_ci	int ret;
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	intel_pcie_core_irq_disable(pcie);
36062306a36Sopenharmony_ci	ret = intel_pcie_wait_l2(pcie);
36162306a36Sopenharmony_ci	if (ret)
36262306a36Sopenharmony_ci		return ret;
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	phy_exit(pcie->phy);
36562306a36Sopenharmony_ci	clk_disable_unprepare(pcie->core_clk);
36662306a36Sopenharmony_ci	return ret;
36762306a36Sopenharmony_ci}
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_cistatic int intel_pcie_resume_noirq(struct device *dev)
37062306a36Sopenharmony_ci{
37162306a36Sopenharmony_ci	struct intel_pcie *pcie = dev_get_drvdata(dev);
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	return intel_pcie_host_setup(pcie);
37462306a36Sopenharmony_ci}
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_cistatic int intel_pcie_rc_init(struct dw_pcie_rp *pp)
37762306a36Sopenharmony_ci{
37862306a36Sopenharmony_ci	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
37962306a36Sopenharmony_ci	struct intel_pcie *pcie = dev_get_drvdata(pci->dev);
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	return intel_pcie_host_setup(pcie);
38262306a36Sopenharmony_ci}
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_cistatic u64 intel_pcie_cpu_addr(struct dw_pcie *pcie, u64 cpu_addr)
38562306a36Sopenharmony_ci{
38662306a36Sopenharmony_ci	return cpu_addr + BUS_IATU_OFFSET;
38762306a36Sopenharmony_ci}
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_cistatic const struct dw_pcie_ops intel_pcie_ops = {
39062306a36Sopenharmony_ci	.cpu_addr_fixup = intel_pcie_cpu_addr,
39162306a36Sopenharmony_ci};
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_cistatic const struct dw_pcie_host_ops intel_pcie_dw_ops = {
39462306a36Sopenharmony_ci	.host_init =		intel_pcie_rc_init,
39562306a36Sopenharmony_ci};
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_cistatic int intel_pcie_probe(struct platform_device *pdev)
39862306a36Sopenharmony_ci{
39962306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
40062306a36Sopenharmony_ci	struct intel_pcie *pcie;
40162306a36Sopenharmony_ci	struct dw_pcie_rp *pp;
40262306a36Sopenharmony_ci	struct dw_pcie *pci;
40362306a36Sopenharmony_ci	int ret;
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
40662306a36Sopenharmony_ci	if (!pcie)
40762306a36Sopenharmony_ci		return -ENOMEM;
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	platform_set_drvdata(pdev, pcie);
41062306a36Sopenharmony_ci	pci = &pcie->pci;
41162306a36Sopenharmony_ci	pci->dev = dev;
41262306a36Sopenharmony_ci	pp = &pci->pp;
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci	ret = intel_pcie_get_resources(pdev);
41562306a36Sopenharmony_ci	if (ret)
41662306a36Sopenharmony_ci		return ret;
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	ret = intel_pcie_ep_rst_init(pcie);
41962306a36Sopenharmony_ci	if (ret)
42062306a36Sopenharmony_ci		return ret;
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci	pci->ops = &intel_pcie_ops;
42362306a36Sopenharmony_ci	pp->ops = &intel_pcie_dw_ops;
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	ret = dw_pcie_host_init(pp);
42662306a36Sopenharmony_ci	if (ret) {
42762306a36Sopenharmony_ci		dev_err(dev, "Cannot initialize host\n");
42862306a36Sopenharmony_ci		return ret;
42962306a36Sopenharmony_ci	}
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	return 0;
43262306a36Sopenharmony_ci}
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_cistatic const struct dev_pm_ops intel_pcie_pm_ops = {
43562306a36Sopenharmony_ci	NOIRQ_SYSTEM_SLEEP_PM_OPS(intel_pcie_suspend_noirq,
43662306a36Sopenharmony_ci				  intel_pcie_resume_noirq)
43762306a36Sopenharmony_ci};
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_cistatic const struct of_device_id of_intel_pcie_match[] = {
44062306a36Sopenharmony_ci	{ .compatible = "intel,lgm-pcie" },
44162306a36Sopenharmony_ci	{}
44262306a36Sopenharmony_ci};
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_cistatic struct platform_driver intel_pcie_driver = {
44562306a36Sopenharmony_ci	.probe = intel_pcie_probe,
44662306a36Sopenharmony_ci	.remove_new = intel_pcie_remove,
44762306a36Sopenharmony_ci	.driver = {
44862306a36Sopenharmony_ci		.name = "intel-gw-pcie",
44962306a36Sopenharmony_ci		.of_match_table = of_intel_pcie_match,
45062306a36Sopenharmony_ci		.pm = &intel_pcie_pm_ops,
45162306a36Sopenharmony_ci	},
45262306a36Sopenharmony_ci};
45362306a36Sopenharmony_cibuiltin_platform_driver(intel_pcie_driver);
454