xref: /OK3568_Linux_fs/kernel/drivers/pci/controller/dwc/pcie-intel-gw.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * PCIe host controller driver for Intel Gateway SoCs
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (c) 2019 Intel Corporation.
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/bitfield.h>
9*4882a593Smuzhiyun #include <linux/clk.h>
10*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
11*4882a593Smuzhiyun #include <linux/iopoll.h>
12*4882a593Smuzhiyun #include <linux/pci_regs.h>
13*4882a593Smuzhiyun #include <linux/phy/phy.h>
14*4882a593Smuzhiyun #include <linux/platform_device.h>
15*4882a593Smuzhiyun #include <linux/reset.h>
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #include "../../pci.h"
18*4882a593Smuzhiyun #include "pcie-designware.h"
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #define PORT_AFR_N_FTS_GEN12_DFT	(SZ_128 - 1)
21*4882a593Smuzhiyun #define PORT_AFR_N_FTS_GEN3		180
22*4882a593Smuzhiyun #define PORT_AFR_N_FTS_GEN4		196
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun /* PCIe Application logic Registers */
25*4882a593Smuzhiyun #define PCIE_APP_CCR			0x10
26*4882a593Smuzhiyun #define PCIE_APP_CCR_LTSSM_ENABLE	BIT(0)
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #define PCIE_APP_MSG_CR			0x30
29*4882a593Smuzhiyun #define PCIE_APP_MSG_XMT_PM_TURNOFF	BIT(0)
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #define PCIE_APP_PMC			0x44
32*4882a593Smuzhiyun #define PCIE_APP_PMC_IN_L2		BIT(20)
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #define PCIE_APP_IRNEN			0xF4
35*4882a593Smuzhiyun #define PCIE_APP_IRNCR			0xF8
36*4882a593Smuzhiyun #define PCIE_APP_IRN_AER_REPORT		BIT(0)
37*4882a593Smuzhiyun #define PCIE_APP_IRN_PME		BIT(2)
38*4882a593Smuzhiyun #define PCIE_APP_IRN_RX_VDM_MSG		BIT(4)
39*4882a593Smuzhiyun #define PCIE_APP_IRN_PM_TO_ACK		BIT(9)
40*4882a593Smuzhiyun #define PCIE_APP_IRN_LINK_AUTO_BW_STAT	BIT(11)
41*4882a593Smuzhiyun #define PCIE_APP_IRN_BW_MGT		BIT(12)
42*4882a593Smuzhiyun #define PCIE_APP_IRN_INTA		BIT(13)
43*4882a593Smuzhiyun #define PCIE_APP_IRN_INTB		BIT(14)
44*4882a593Smuzhiyun #define PCIE_APP_IRN_INTC		BIT(15)
45*4882a593Smuzhiyun #define PCIE_APP_IRN_INTD		BIT(16)
46*4882a593Smuzhiyun #define PCIE_APP_IRN_MSG_LTR		BIT(18)
47*4882a593Smuzhiyun #define PCIE_APP_IRN_SYS_ERR_RC		BIT(29)
48*4882a593Smuzhiyun #define PCIE_APP_INTX_OFST		12
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun #define PCIE_APP_IRN_INT \
51*4882a593Smuzhiyun 	(PCIE_APP_IRN_AER_REPORT | PCIE_APP_IRN_PME | \
52*4882a593Smuzhiyun 	PCIE_APP_IRN_RX_VDM_MSG | PCIE_APP_IRN_SYS_ERR_RC | \
53*4882a593Smuzhiyun 	PCIE_APP_IRN_PM_TO_ACK | PCIE_APP_IRN_MSG_LTR | \
54*4882a593Smuzhiyun 	PCIE_APP_IRN_BW_MGT | PCIE_APP_IRN_LINK_AUTO_BW_STAT | \
55*4882a593Smuzhiyun 	PCIE_APP_IRN_INTA | PCIE_APP_IRN_INTB | \
56*4882a593Smuzhiyun 	PCIE_APP_IRN_INTC | PCIE_APP_IRN_INTD)
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun #define BUS_IATU_OFFSET			SZ_256M
59*4882a593Smuzhiyun #define RESET_INTERVAL_MS		100
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun struct intel_pcie_soc {
62*4882a593Smuzhiyun 	unsigned int	pcie_ver;
63*4882a593Smuzhiyun 	unsigned int	pcie_atu_offset;
64*4882a593Smuzhiyun 	u32		num_viewport;
65*4882a593Smuzhiyun };
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun struct intel_pcie_port {
68*4882a593Smuzhiyun 	struct dw_pcie		pci;
69*4882a593Smuzhiyun 	void __iomem		*app_base;
70*4882a593Smuzhiyun 	struct gpio_desc	*reset_gpio;
71*4882a593Smuzhiyun 	u32			rst_intrvl;
72*4882a593Smuzhiyun 	struct clk		*core_clk;
73*4882a593Smuzhiyun 	struct reset_control	*core_rst;
74*4882a593Smuzhiyun 	struct phy		*phy;
75*4882a593Smuzhiyun };
76*4882a593Smuzhiyun 
pcie_update_bits(void __iomem * base,u32 ofs,u32 mask,u32 val)77*4882a593Smuzhiyun static void pcie_update_bits(void __iomem *base, u32 ofs, u32 mask, u32 val)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun 	u32 old;
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	old = readl(base + ofs);
82*4882a593Smuzhiyun 	val = (old & ~mask) | (val & mask);
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	if (val != old)
85*4882a593Smuzhiyun 		writel(val, base + ofs);
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun 
pcie_app_rd(struct intel_pcie_port * lpp,u32 ofs)88*4882a593Smuzhiyun static inline u32 pcie_app_rd(struct intel_pcie_port *lpp, u32 ofs)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun 	return readl(lpp->app_base + ofs);
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun 
pcie_app_wr(struct intel_pcie_port * lpp,u32 ofs,u32 val)93*4882a593Smuzhiyun static inline void pcie_app_wr(struct intel_pcie_port *lpp, u32 ofs, u32 val)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun 	writel(val, lpp->app_base + ofs);
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun 
pcie_app_wr_mask(struct intel_pcie_port * lpp,u32 ofs,u32 mask,u32 val)98*4882a593Smuzhiyun static void pcie_app_wr_mask(struct intel_pcie_port *lpp, u32 ofs,
99*4882a593Smuzhiyun 			     u32 mask, u32 val)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun 	pcie_update_bits(lpp->app_base, ofs, mask, val);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun 
pcie_rc_cfg_rd(struct intel_pcie_port * lpp,u32 ofs)104*4882a593Smuzhiyun static inline u32 pcie_rc_cfg_rd(struct intel_pcie_port *lpp, u32 ofs)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun 	return dw_pcie_readl_dbi(&lpp->pci, ofs);
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun 
pcie_rc_cfg_wr(struct intel_pcie_port * lpp,u32 ofs,u32 val)109*4882a593Smuzhiyun static inline void pcie_rc_cfg_wr(struct intel_pcie_port *lpp, u32 ofs, u32 val)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun 	dw_pcie_writel_dbi(&lpp->pci, ofs, val);
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun 
pcie_rc_cfg_wr_mask(struct intel_pcie_port * lpp,u32 ofs,u32 mask,u32 val)114*4882a593Smuzhiyun static void pcie_rc_cfg_wr_mask(struct intel_pcie_port *lpp, u32 ofs,
115*4882a593Smuzhiyun 				u32 mask, u32 val)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun 	pcie_update_bits(lpp->pci.dbi_base, ofs, mask, val);
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun 
intel_pcie_ltssm_enable(struct intel_pcie_port * lpp)120*4882a593Smuzhiyun static void intel_pcie_ltssm_enable(struct intel_pcie_port *lpp)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun 	pcie_app_wr_mask(lpp, PCIE_APP_CCR, PCIE_APP_CCR_LTSSM_ENABLE,
123*4882a593Smuzhiyun 			 PCIE_APP_CCR_LTSSM_ENABLE);
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun 
intel_pcie_ltssm_disable(struct intel_pcie_port * lpp)126*4882a593Smuzhiyun static void intel_pcie_ltssm_disable(struct intel_pcie_port *lpp)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun 	pcie_app_wr_mask(lpp, PCIE_APP_CCR, PCIE_APP_CCR_LTSSM_ENABLE, 0);
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun 
intel_pcie_link_setup(struct intel_pcie_port * lpp)131*4882a593Smuzhiyun static void intel_pcie_link_setup(struct intel_pcie_port *lpp)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun 	u32 val;
134*4882a593Smuzhiyun 	u8 offset = dw_pcie_find_capability(&lpp->pci, PCI_CAP_ID_EXP);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	val = pcie_rc_cfg_rd(lpp, offset + PCI_EXP_LNKCTL);
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	val &= ~(PCI_EXP_LNKCTL_LD | PCI_EXP_LNKCTL_ASPMC);
139*4882a593Smuzhiyun 	pcie_rc_cfg_wr(lpp, offset + PCI_EXP_LNKCTL, val);
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun 
intel_pcie_init_n_fts(struct dw_pcie * pci)142*4882a593Smuzhiyun static void intel_pcie_init_n_fts(struct dw_pcie *pci)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun 	switch (pci->link_gen) {
145*4882a593Smuzhiyun 	case 3:
146*4882a593Smuzhiyun 		pci->n_fts[1] = PORT_AFR_N_FTS_GEN3;
147*4882a593Smuzhiyun 		break;
148*4882a593Smuzhiyun 	case 4:
149*4882a593Smuzhiyun 		pci->n_fts[1] = PORT_AFR_N_FTS_GEN4;
150*4882a593Smuzhiyun 		break;
151*4882a593Smuzhiyun 	default:
152*4882a593Smuzhiyun 		pci->n_fts[1] = PORT_AFR_N_FTS_GEN12_DFT;
153*4882a593Smuzhiyun 		break;
154*4882a593Smuzhiyun 	}
155*4882a593Smuzhiyun 	pci->n_fts[0] = PORT_AFR_N_FTS_GEN12_DFT;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun 
intel_pcie_rc_setup(struct intel_pcie_port * lpp)158*4882a593Smuzhiyun static void intel_pcie_rc_setup(struct intel_pcie_port *lpp)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun 	intel_pcie_ltssm_disable(lpp);
161*4882a593Smuzhiyun 	intel_pcie_link_setup(lpp);
162*4882a593Smuzhiyun 	intel_pcie_init_n_fts(&lpp->pci);
163*4882a593Smuzhiyun 	dw_pcie_setup_rc(&lpp->pci.pp);
164*4882a593Smuzhiyun 	dw_pcie_upconfig_setup(&lpp->pci);
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun 
intel_pcie_ep_rst_init(struct intel_pcie_port * lpp)167*4882a593Smuzhiyun static int intel_pcie_ep_rst_init(struct intel_pcie_port *lpp)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun 	struct device *dev = lpp->pci.dev;
170*4882a593Smuzhiyun 	int ret;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	lpp->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
173*4882a593Smuzhiyun 	if (IS_ERR(lpp->reset_gpio)) {
174*4882a593Smuzhiyun 		ret = PTR_ERR(lpp->reset_gpio);
175*4882a593Smuzhiyun 		if (ret != -EPROBE_DEFER)
176*4882a593Smuzhiyun 			dev_err(dev, "Failed to request PCIe GPIO: %d\n", ret);
177*4882a593Smuzhiyun 		return ret;
178*4882a593Smuzhiyun 	}
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	/* Make initial reset last for 100us */
181*4882a593Smuzhiyun 	usleep_range(100, 200);
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	return 0;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun 
intel_pcie_core_rst_assert(struct intel_pcie_port * lpp)186*4882a593Smuzhiyun static void intel_pcie_core_rst_assert(struct intel_pcie_port *lpp)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun 	reset_control_assert(lpp->core_rst);
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun 
intel_pcie_core_rst_deassert(struct intel_pcie_port * lpp)191*4882a593Smuzhiyun static void intel_pcie_core_rst_deassert(struct intel_pcie_port *lpp)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun 	/*
194*4882a593Smuzhiyun 	 * One micro-second delay to make sure the reset pulse
195*4882a593Smuzhiyun 	 * wide enough so that core reset is clean.
196*4882a593Smuzhiyun 	 */
197*4882a593Smuzhiyun 	udelay(1);
198*4882a593Smuzhiyun 	reset_control_deassert(lpp->core_rst);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	/*
201*4882a593Smuzhiyun 	 * Some SoC core reset also reset PHY, more delay needed
202*4882a593Smuzhiyun 	 * to make sure the reset process is done.
203*4882a593Smuzhiyun 	 */
204*4882a593Smuzhiyun 	usleep_range(1000, 2000);
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun 
intel_pcie_device_rst_assert(struct intel_pcie_port * lpp)207*4882a593Smuzhiyun static void intel_pcie_device_rst_assert(struct intel_pcie_port *lpp)
208*4882a593Smuzhiyun {
209*4882a593Smuzhiyun 	gpiod_set_value_cansleep(lpp->reset_gpio, 1);
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun 
intel_pcie_device_rst_deassert(struct intel_pcie_port * lpp)212*4882a593Smuzhiyun static void intel_pcie_device_rst_deassert(struct intel_pcie_port *lpp)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun 	msleep(lpp->rst_intrvl);
215*4882a593Smuzhiyun 	gpiod_set_value_cansleep(lpp->reset_gpio, 0);
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun 
intel_pcie_app_logic_setup(struct intel_pcie_port * lpp)218*4882a593Smuzhiyun static int intel_pcie_app_logic_setup(struct intel_pcie_port *lpp)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun 	intel_pcie_device_rst_deassert(lpp);
221*4882a593Smuzhiyun 	intel_pcie_ltssm_enable(lpp);
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	return dw_pcie_wait_for_link(&lpp->pci);
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun 
intel_pcie_core_irq_disable(struct intel_pcie_port * lpp)226*4882a593Smuzhiyun static void intel_pcie_core_irq_disable(struct intel_pcie_port *lpp)
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun 	pcie_app_wr(lpp, PCIE_APP_IRNEN, 0);
229*4882a593Smuzhiyun 	pcie_app_wr(lpp, PCIE_APP_IRNCR, PCIE_APP_IRN_INT);
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun 
intel_pcie_get_resources(struct platform_device * pdev)232*4882a593Smuzhiyun static int intel_pcie_get_resources(struct platform_device *pdev)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun 	struct intel_pcie_port *lpp = platform_get_drvdata(pdev);
235*4882a593Smuzhiyun 	struct dw_pcie *pci = &lpp->pci;
236*4882a593Smuzhiyun 	struct device *dev = pci->dev;
237*4882a593Smuzhiyun 	int ret;
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	pci->dbi_base = devm_platform_ioremap_resource_byname(pdev, "dbi");
240*4882a593Smuzhiyun 	if (IS_ERR(pci->dbi_base))
241*4882a593Smuzhiyun 		return PTR_ERR(pci->dbi_base);
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	lpp->core_clk = devm_clk_get(dev, NULL);
244*4882a593Smuzhiyun 	if (IS_ERR(lpp->core_clk)) {
245*4882a593Smuzhiyun 		ret = PTR_ERR(lpp->core_clk);
246*4882a593Smuzhiyun 		if (ret != -EPROBE_DEFER)
247*4882a593Smuzhiyun 			dev_err(dev, "Failed to get clks: %d\n", ret);
248*4882a593Smuzhiyun 		return ret;
249*4882a593Smuzhiyun 	}
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	lpp->core_rst = devm_reset_control_get(dev, NULL);
252*4882a593Smuzhiyun 	if (IS_ERR(lpp->core_rst)) {
253*4882a593Smuzhiyun 		ret = PTR_ERR(lpp->core_rst);
254*4882a593Smuzhiyun 		if (ret != -EPROBE_DEFER)
255*4882a593Smuzhiyun 			dev_err(dev, "Failed to get resets: %d\n", ret);
256*4882a593Smuzhiyun 		return ret;
257*4882a593Smuzhiyun 	}
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	ret = device_property_read_u32(dev, "reset-assert-ms",
260*4882a593Smuzhiyun 				       &lpp->rst_intrvl);
261*4882a593Smuzhiyun 	if (ret)
262*4882a593Smuzhiyun 		lpp->rst_intrvl = RESET_INTERVAL_MS;
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	lpp->app_base = devm_platform_ioremap_resource_byname(pdev, "app");
265*4882a593Smuzhiyun 	if (IS_ERR(lpp->app_base))
266*4882a593Smuzhiyun 		return PTR_ERR(lpp->app_base);
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun 	lpp->phy = devm_phy_get(dev, "pcie");
269*4882a593Smuzhiyun 	if (IS_ERR(lpp->phy)) {
270*4882a593Smuzhiyun 		ret = PTR_ERR(lpp->phy);
271*4882a593Smuzhiyun 		if (ret != -EPROBE_DEFER)
272*4882a593Smuzhiyun 			dev_err(dev, "Couldn't get pcie-phy: %d\n", ret);
273*4882a593Smuzhiyun 		return ret;
274*4882a593Smuzhiyun 	}
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	return 0;
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun 
intel_pcie_deinit_phy(struct intel_pcie_port * lpp)279*4882a593Smuzhiyun static void intel_pcie_deinit_phy(struct intel_pcie_port *lpp)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun 	phy_exit(lpp->phy);
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun 
intel_pcie_wait_l2(struct intel_pcie_port * lpp)284*4882a593Smuzhiyun static int intel_pcie_wait_l2(struct intel_pcie_port *lpp)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun 	u32 value;
287*4882a593Smuzhiyun 	int ret;
288*4882a593Smuzhiyun 	struct dw_pcie *pci = &lpp->pci;
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 	if (pci->link_gen < 3)
291*4882a593Smuzhiyun 		return 0;
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	/* Send PME_TURN_OFF message */
294*4882a593Smuzhiyun 	pcie_app_wr_mask(lpp, PCIE_APP_MSG_CR, PCIE_APP_MSG_XMT_PM_TURNOFF,
295*4882a593Smuzhiyun 			 PCIE_APP_MSG_XMT_PM_TURNOFF);
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	/* Read PMC status and wait for falling into L2 link state */
298*4882a593Smuzhiyun 	ret = readl_poll_timeout(lpp->app_base + PCIE_APP_PMC, value,
299*4882a593Smuzhiyun 				 value & PCIE_APP_PMC_IN_L2, 20,
300*4882a593Smuzhiyun 				 jiffies_to_usecs(5 * HZ));
301*4882a593Smuzhiyun 	if (ret)
302*4882a593Smuzhiyun 		dev_err(lpp->pci.dev, "PCIe link enter L2 timeout!\n");
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	return ret;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun 
intel_pcie_turn_off(struct intel_pcie_port * lpp)307*4882a593Smuzhiyun static void intel_pcie_turn_off(struct intel_pcie_port *lpp)
308*4882a593Smuzhiyun {
309*4882a593Smuzhiyun 	if (dw_pcie_link_up(&lpp->pci))
310*4882a593Smuzhiyun 		intel_pcie_wait_l2(lpp);
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	/* Put endpoint device in reset state */
313*4882a593Smuzhiyun 	intel_pcie_device_rst_assert(lpp);
314*4882a593Smuzhiyun 	pcie_rc_cfg_wr_mask(lpp, PCI_COMMAND, PCI_COMMAND_MEMORY, 0);
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun 
intel_pcie_host_setup(struct intel_pcie_port * lpp)317*4882a593Smuzhiyun static int intel_pcie_host_setup(struct intel_pcie_port *lpp)
318*4882a593Smuzhiyun {
319*4882a593Smuzhiyun 	int ret;
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 	intel_pcie_core_rst_assert(lpp);
322*4882a593Smuzhiyun 	intel_pcie_device_rst_assert(lpp);
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	ret = phy_init(lpp->phy);
325*4882a593Smuzhiyun 	if (ret)
326*4882a593Smuzhiyun 		return ret;
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	intel_pcie_core_rst_deassert(lpp);
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	ret = clk_prepare_enable(lpp->core_clk);
331*4882a593Smuzhiyun 	if (ret) {
332*4882a593Smuzhiyun 		dev_err(lpp->pci.dev, "Core clock enable failed: %d\n", ret);
333*4882a593Smuzhiyun 		goto clk_err;
334*4882a593Smuzhiyun 	}
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	intel_pcie_rc_setup(lpp);
337*4882a593Smuzhiyun 	ret = intel_pcie_app_logic_setup(lpp);
338*4882a593Smuzhiyun 	if (ret)
339*4882a593Smuzhiyun 		goto app_init_err;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	/* Enable integrated interrupts */
342*4882a593Smuzhiyun 	pcie_app_wr_mask(lpp, PCIE_APP_IRNEN, PCIE_APP_IRN_INT,
343*4882a593Smuzhiyun 			 PCIE_APP_IRN_INT);
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	return 0;
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun app_init_err:
348*4882a593Smuzhiyun 	clk_disable_unprepare(lpp->core_clk);
349*4882a593Smuzhiyun clk_err:
350*4882a593Smuzhiyun 	intel_pcie_core_rst_assert(lpp);
351*4882a593Smuzhiyun 	intel_pcie_deinit_phy(lpp);
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 	return ret;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun 
__intel_pcie_remove(struct intel_pcie_port * lpp)356*4882a593Smuzhiyun static void __intel_pcie_remove(struct intel_pcie_port *lpp)
357*4882a593Smuzhiyun {
358*4882a593Smuzhiyun 	intel_pcie_core_irq_disable(lpp);
359*4882a593Smuzhiyun 	intel_pcie_turn_off(lpp);
360*4882a593Smuzhiyun 	clk_disable_unprepare(lpp->core_clk);
361*4882a593Smuzhiyun 	intel_pcie_core_rst_assert(lpp);
362*4882a593Smuzhiyun 	intel_pcie_deinit_phy(lpp);
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun 
intel_pcie_remove(struct platform_device * pdev)365*4882a593Smuzhiyun static int intel_pcie_remove(struct platform_device *pdev)
366*4882a593Smuzhiyun {
367*4882a593Smuzhiyun 	struct intel_pcie_port *lpp = platform_get_drvdata(pdev);
368*4882a593Smuzhiyun 	struct pcie_port *pp = &lpp->pci.pp;
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 	dw_pcie_host_deinit(pp);
371*4882a593Smuzhiyun 	__intel_pcie_remove(lpp);
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun 	return 0;
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun 
intel_pcie_suspend_noirq(struct device * dev)376*4882a593Smuzhiyun static int __maybe_unused intel_pcie_suspend_noirq(struct device *dev)
377*4882a593Smuzhiyun {
378*4882a593Smuzhiyun 	struct intel_pcie_port *lpp = dev_get_drvdata(dev);
379*4882a593Smuzhiyun 	int ret;
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun 	intel_pcie_core_irq_disable(lpp);
382*4882a593Smuzhiyun 	ret = intel_pcie_wait_l2(lpp);
383*4882a593Smuzhiyun 	if (ret)
384*4882a593Smuzhiyun 		return ret;
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 	intel_pcie_deinit_phy(lpp);
387*4882a593Smuzhiyun 	clk_disable_unprepare(lpp->core_clk);
388*4882a593Smuzhiyun 	return ret;
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun 
intel_pcie_resume_noirq(struct device * dev)391*4882a593Smuzhiyun static int __maybe_unused intel_pcie_resume_noirq(struct device *dev)
392*4882a593Smuzhiyun {
393*4882a593Smuzhiyun 	struct intel_pcie_port *lpp = dev_get_drvdata(dev);
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun 	return intel_pcie_host_setup(lpp);
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun 
intel_pcie_rc_init(struct pcie_port * pp)398*4882a593Smuzhiyun static int intel_pcie_rc_init(struct pcie_port *pp)
399*4882a593Smuzhiyun {
400*4882a593Smuzhiyun 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
401*4882a593Smuzhiyun 	struct intel_pcie_port *lpp = dev_get_drvdata(pci->dev);
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 	return intel_pcie_host_setup(lpp);
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun /*
407*4882a593Smuzhiyun  * Dummy function so that DW core doesn't configure MSI
408*4882a593Smuzhiyun  */
intel_pcie_msi_init(struct pcie_port * pp)409*4882a593Smuzhiyun static int intel_pcie_msi_init(struct pcie_port *pp)
410*4882a593Smuzhiyun {
411*4882a593Smuzhiyun 	return 0;
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun 
intel_pcie_cpu_addr(struct dw_pcie * pcie,u64 cpu_addr)414*4882a593Smuzhiyun static u64 intel_pcie_cpu_addr(struct dw_pcie *pcie, u64 cpu_addr)
415*4882a593Smuzhiyun {
416*4882a593Smuzhiyun 	return cpu_addr + BUS_IATU_OFFSET;
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun static const struct dw_pcie_ops intel_pcie_ops = {
420*4882a593Smuzhiyun 	.cpu_addr_fixup = intel_pcie_cpu_addr,
421*4882a593Smuzhiyun };
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun static const struct dw_pcie_host_ops intel_pcie_dw_ops = {
424*4882a593Smuzhiyun 	.host_init =		intel_pcie_rc_init,
425*4882a593Smuzhiyun 	.msi_host_init =	intel_pcie_msi_init,
426*4882a593Smuzhiyun };
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun static const struct intel_pcie_soc pcie_data = {
429*4882a593Smuzhiyun 	.pcie_ver =		0x520A,
430*4882a593Smuzhiyun 	.pcie_atu_offset =	0xC0000,
431*4882a593Smuzhiyun 	.num_viewport =		3,
432*4882a593Smuzhiyun };
433*4882a593Smuzhiyun 
intel_pcie_probe(struct platform_device * pdev)434*4882a593Smuzhiyun static int intel_pcie_probe(struct platform_device *pdev)
435*4882a593Smuzhiyun {
436*4882a593Smuzhiyun 	const struct intel_pcie_soc *data;
437*4882a593Smuzhiyun 	struct device *dev = &pdev->dev;
438*4882a593Smuzhiyun 	struct intel_pcie_port *lpp;
439*4882a593Smuzhiyun 	struct pcie_port *pp;
440*4882a593Smuzhiyun 	struct dw_pcie *pci;
441*4882a593Smuzhiyun 	int ret;
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	lpp = devm_kzalloc(dev, sizeof(*lpp), GFP_KERNEL);
444*4882a593Smuzhiyun 	if (!lpp)
445*4882a593Smuzhiyun 		return -ENOMEM;
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	platform_set_drvdata(pdev, lpp);
448*4882a593Smuzhiyun 	pci = &lpp->pci;
449*4882a593Smuzhiyun 	pci->dev = dev;
450*4882a593Smuzhiyun 	pp = &pci->pp;
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	ret = intel_pcie_get_resources(pdev);
453*4882a593Smuzhiyun 	if (ret)
454*4882a593Smuzhiyun 		return ret;
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun 	ret = intel_pcie_ep_rst_init(lpp);
457*4882a593Smuzhiyun 	if (ret)
458*4882a593Smuzhiyun 		return ret;
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 	data = device_get_match_data(dev);
461*4882a593Smuzhiyun 	if (!data)
462*4882a593Smuzhiyun 		return -ENODEV;
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	pci->ops = &intel_pcie_ops;
465*4882a593Smuzhiyun 	pci->version = data->pcie_ver;
466*4882a593Smuzhiyun 	pci->atu_base = pci->dbi_base + data->pcie_atu_offset;
467*4882a593Smuzhiyun 	pp->ops = &intel_pcie_dw_ops;
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 	ret = dw_pcie_host_init(pp);
470*4882a593Smuzhiyun 	if (ret) {
471*4882a593Smuzhiyun 		dev_err(dev, "Cannot initialize host\n");
472*4882a593Smuzhiyun 		return ret;
473*4882a593Smuzhiyun 	}
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	/*
476*4882a593Smuzhiyun 	 * Intel PCIe doesn't configure IO region, so set viewport
477*4882a593Smuzhiyun 	 * to not perform IO region access.
478*4882a593Smuzhiyun 	 */
479*4882a593Smuzhiyun 	pci->num_viewport = data->num_viewport;
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	return 0;
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun static const struct dev_pm_ops intel_pcie_pm_ops = {
485*4882a593Smuzhiyun 	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(intel_pcie_suspend_noirq,
486*4882a593Smuzhiyun 				      intel_pcie_resume_noirq)
487*4882a593Smuzhiyun };
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun static const struct of_device_id of_intel_pcie_match[] = {
490*4882a593Smuzhiyun 	{ .compatible = "intel,lgm-pcie", .data = &pcie_data },
491*4882a593Smuzhiyun 	{}
492*4882a593Smuzhiyun };
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun static struct platform_driver intel_pcie_driver = {
495*4882a593Smuzhiyun 	.probe = intel_pcie_probe,
496*4882a593Smuzhiyun 	.remove = intel_pcie_remove,
497*4882a593Smuzhiyun 	.driver = {
498*4882a593Smuzhiyun 		.name = "intel-gw-pcie",
499*4882a593Smuzhiyun 		.of_match_table = of_intel_pcie_match,
500*4882a593Smuzhiyun 		.pm = &intel_pcie_pm_ops,
501*4882a593Smuzhiyun 	},
502*4882a593Smuzhiyun };
503*4882a593Smuzhiyun builtin_platform_driver(intel_pcie_driver);
504