xref: /OK3568_Linux_fs/kernel/drivers/pci/controller/dwc/pcie-artpec6.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * PCIe host controller driver for Axis ARTPEC-6 SoC
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Author: Niklas Cassel <niklas.cassel@axis.com>
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Based on work done by Phil Edworthy <phil@edworthys.org>
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/delay.h>
11*4882a593Smuzhiyun #include <linux/kernel.h>
12*4882a593Smuzhiyun #include <linux/init.h>
13*4882a593Smuzhiyun #include <linux/of_device.h>
14*4882a593Smuzhiyun #include <linux/pci.h>
15*4882a593Smuzhiyun #include <linux/platform_device.h>
16*4882a593Smuzhiyun #include <linux/resource.h>
17*4882a593Smuzhiyun #include <linux/signal.h>
18*4882a593Smuzhiyun #include <linux/types.h>
19*4882a593Smuzhiyun #include <linux/interrupt.h>
20*4882a593Smuzhiyun #include <linux/mfd/syscon.h>
21*4882a593Smuzhiyun #include <linux/regmap.h>
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #include "pcie-designware.h"
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #define to_artpec6_pcie(x)	dev_get_drvdata((x)->dev)
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun enum artpec_pcie_variants {
28*4882a593Smuzhiyun 	ARTPEC6,
29*4882a593Smuzhiyun 	ARTPEC7,
30*4882a593Smuzhiyun };
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun struct artpec6_pcie {
33*4882a593Smuzhiyun 	struct dw_pcie		*pci;
34*4882a593Smuzhiyun 	struct regmap		*regmap;	/* DT axis,syscon-pcie */
35*4882a593Smuzhiyun 	void __iomem		*phy_base;	/* DT phy */
36*4882a593Smuzhiyun 	enum artpec_pcie_variants variant;
37*4882a593Smuzhiyun 	enum dw_pcie_device_mode mode;
38*4882a593Smuzhiyun };
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun struct artpec_pcie_of_data {
41*4882a593Smuzhiyun 	enum artpec_pcie_variants variant;
42*4882a593Smuzhiyun 	enum dw_pcie_device_mode mode;
43*4882a593Smuzhiyun };
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun static const struct of_device_id artpec6_pcie_of_match[];
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun /* ARTPEC-6 specific registers */
48*4882a593Smuzhiyun #define PCIECFG				0x18
49*4882a593Smuzhiyun #define  PCIECFG_DBG_OEN		BIT(24)
50*4882a593Smuzhiyun #define  PCIECFG_CORE_RESET_REQ		BIT(21)
51*4882a593Smuzhiyun #define  PCIECFG_LTSSM_ENABLE		BIT(20)
52*4882a593Smuzhiyun #define  PCIECFG_DEVICE_TYPE_MASK	GENMASK(19, 16)
53*4882a593Smuzhiyun #define  PCIECFG_CLKREQ_B		BIT(11)
54*4882a593Smuzhiyun #define  PCIECFG_REFCLK_ENABLE		BIT(10)
55*4882a593Smuzhiyun #define  PCIECFG_PLL_ENABLE		BIT(9)
56*4882a593Smuzhiyun #define  PCIECFG_PCLK_ENABLE		BIT(8)
57*4882a593Smuzhiyun #define  PCIECFG_RISRCREN		BIT(4)
58*4882a593Smuzhiyun #define  PCIECFG_MODE_TX_DRV_EN		BIT(3)
59*4882a593Smuzhiyun #define  PCIECFG_CISRREN		BIT(2)
60*4882a593Smuzhiyun #define  PCIECFG_MACRO_ENABLE		BIT(0)
61*4882a593Smuzhiyun /* ARTPEC-7 specific fields */
62*4882a593Smuzhiyun #define  PCIECFG_REFCLKSEL		BIT(23)
63*4882a593Smuzhiyun #define  PCIECFG_NOC_RESET		BIT(3)
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun #define PCIESTAT			0x1c
66*4882a593Smuzhiyun /* ARTPEC-7 specific fields */
67*4882a593Smuzhiyun #define  PCIESTAT_EXTREFCLK		BIT(3)
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun #define NOCCFG				0x40
70*4882a593Smuzhiyun #define  NOCCFG_ENABLE_CLK_PCIE		BIT(4)
71*4882a593Smuzhiyun #define  NOCCFG_POWER_PCIE_IDLEACK	BIT(3)
72*4882a593Smuzhiyun #define  NOCCFG_POWER_PCIE_IDLE		BIT(2)
73*4882a593Smuzhiyun #define  NOCCFG_POWER_PCIE_IDLEREQ	BIT(1)
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun #define PHY_STATUS			0x118
76*4882a593Smuzhiyun #define  PHY_COSPLLLOCK			BIT(0)
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun #define PHY_TX_ASIC_OUT			0x4040
79*4882a593Smuzhiyun #define  PHY_TX_ASIC_OUT_TX_ACK		BIT(0)
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun #define PHY_RX_ASIC_OUT			0x405c
82*4882a593Smuzhiyun #define  PHY_RX_ASIC_OUT_ACK		BIT(0)
83*4882a593Smuzhiyun 
artpec6_pcie_readl(struct artpec6_pcie * artpec6_pcie,u32 offset)84*4882a593Smuzhiyun static u32 artpec6_pcie_readl(struct artpec6_pcie *artpec6_pcie, u32 offset)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun 	u32 val;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	regmap_read(artpec6_pcie->regmap, offset, &val);
89*4882a593Smuzhiyun 	return val;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun 
artpec6_pcie_writel(struct artpec6_pcie * artpec6_pcie,u32 offset,u32 val)92*4882a593Smuzhiyun static void artpec6_pcie_writel(struct artpec6_pcie *artpec6_pcie, u32 offset, u32 val)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun 	regmap_write(artpec6_pcie->regmap, offset, val);
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun 
artpec6_pcie_cpu_addr_fixup(struct dw_pcie * pci,u64 pci_addr)97*4882a593Smuzhiyun static u64 artpec6_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 pci_addr)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun 	struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci);
100*4882a593Smuzhiyun 	struct pcie_port *pp = &pci->pp;
101*4882a593Smuzhiyun 	struct dw_pcie_ep *ep = &pci->ep;
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	switch (artpec6_pcie->mode) {
104*4882a593Smuzhiyun 	case DW_PCIE_RC_TYPE:
105*4882a593Smuzhiyun 		return pci_addr - pp->cfg0_base;
106*4882a593Smuzhiyun 	case DW_PCIE_EP_TYPE:
107*4882a593Smuzhiyun 		return pci_addr - ep->phys_base;
108*4882a593Smuzhiyun 	default:
109*4882a593Smuzhiyun 		dev_err(pci->dev, "UNKNOWN device type\n");
110*4882a593Smuzhiyun 	}
111*4882a593Smuzhiyun 	return pci_addr;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun 
artpec6_pcie_establish_link(struct dw_pcie * pci)114*4882a593Smuzhiyun static int artpec6_pcie_establish_link(struct dw_pcie *pci)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun 	struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci);
117*4882a593Smuzhiyun 	u32 val;
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	val = artpec6_pcie_readl(artpec6_pcie, PCIECFG);
120*4882a593Smuzhiyun 	val |= PCIECFG_LTSSM_ENABLE;
121*4882a593Smuzhiyun 	artpec6_pcie_writel(artpec6_pcie, PCIECFG, val);
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	return 0;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun 
artpec6_pcie_stop_link(struct dw_pcie * pci)126*4882a593Smuzhiyun static void artpec6_pcie_stop_link(struct dw_pcie *pci)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun 	struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci);
129*4882a593Smuzhiyun 	u32 val;
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	val = artpec6_pcie_readl(artpec6_pcie, PCIECFG);
132*4882a593Smuzhiyun 	val &= ~PCIECFG_LTSSM_ENABLE;
133*4882a593Smuzhiyun 	artpec6_pcie_writel(artpec6_pcie, PCIECFG, val);
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun static const struct dw_pcie_ops dw_pcie_ops = {
137*4882a593Smuzhiyun 	.cpu_addr_fixup = artpec6_pcie_cpu_addr_fixup,
138*4882a593Smuzhiyun 	.start_link = artpec6_pcie_establish_link,
139*4882a593Smuzhiyun 	.stop_link = artpec6_pcie_stop_link,
140*4882a593Smuzhiyun };
141*4882a593Smuzhiyun 
artpec6_pcie_wait_for_phy_a6(struct artpec6_pcie * artpec6_pcie)142*4882a593Smuzhiyun static void artpec6_pcie_wait_for_phy_a6(struct artpec6_pcie *artpec6_pcie)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun 	struct dw_pcie *pci = artpec6_pcie->pci;
145*4882a593Smuzhiyun 	struct device *dev = pci->dev;
146*4882a593Smuzhiyun 	u32 val;
147*4882a593Smuzhiyun 	unsigned int retries;
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 	retries = 50;
150*4882a593Smuzhiyun 	do {
151*4882a593Smuzhiyun 		usleep_range(1000, 2000);
152*4882a593Smuzhiyun 		val = artpec6_pcie_readl(artpec6_pcie, NOCCFG);
153*4882a593Smuzhiyun 		retries--;
154*4882a593Smuzhiyun 	} while (retries &&
155*4882a593Smuzhiyun 		(val & (NOCCFG_POWER_PCIE_IDLEACK | NOCCFG_POWER_PCIE_IDLE)));
156*4882a593Smuzhiyun 	if (!retries)
157*4882a593Smuzhiyun 		dev_err(dev, "PCIe clock manager did not leave idle state\n");
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	retries = 50;
160*4882a593Smuzhiyun 	do {
161*4882a593Smuzhiyun 		usleep_range(1000, 2000);
162*4882a593Smuzhiyun 		val = readl(artpec6_pcie->phy_base + PHY_STATUS);
163*4882a593Smuzhiyun 		retries--;
164*4882a593Smuzhiyun 	} while (retries && !(val & PHY_COSPLLLOCK));
165*4882a593Smuzhiyun 	if (!retries)
166*4882a593Smuzhiyun 		dev_err(dev, "PHY PLL did not lock\n");
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun 
artpec6_pcie_wait_for_phy_a7(struct artpec6_pcie * artpec6_pcie)169*4882a593Smuzhiyun static void artpec6_pcie_wait_for_phy_a7(struct artpec6_pcie *artpec6_pcie)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun 	struct dw_pcie *pci = artpec6_pcie->pci;
172*4882a593Smuzhiyun 	struct device *dev = pci->dev;
173*4882a593Smuzhiyun 	u32 val;
174*4882a593Smuzhiyun 	u16 phy_status_tx, phy_status_rx;
175*4882a593Smuzhiyun 	unsigned int retries;
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	retries = 50;
178*4882a593Smuzhiyun 	do {
179*4882a593Smuzhiyun 		usleep_range(1000, 2000);
180*4882a593Smuzhiyun 		val = artpec6_pcie_readl(artpec6_pcie, NOCCFG);
181*4882a593Smuzhiyun 		retries--;
182*4882a593Smuzhiyun 	} while (retries &&
183*4882a593Smuzhiyun 		(val & (NOCCFG_POWER_PCIE_IDLEACK | NOCCFG_POWER_PCIE_IDLE)));
184*4882a593Smuzhiyun 	if (!retries)
185*4882a593Smuzhiyun 		dev_err(dev, "PCIe clock manager did not leave idle state\n");
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	retries = 50;
188*4882a593Smuzhiyun 	do {
189*4882a593Smuzhiyun 		usleep_range(1000, 2000);
190*4882a593Smuzhiyun 		phy_status_tx = readw(artpec6_pcie->phy_base + PHY_TX_ASIC_OUT);
191*4882a593Smuzhiyun 		phy_status_rx = readw(artpec6_pcie->phy_base + PHY_RX_ASIC_OUT);
192*4882a593Smuzhiyun 		retries--;
193*4882a593Smuzhiyun 	} while (retries && ((phy_status_tx & PHY_TX_ASIC_OUT_TX_ACK) ||
194*4882a593Smuzhiyun 				(phy_status_rx & PHY_RX_ASIC_OUT_ACK)));
195*4882a593Smuzhiyun 	if (!retries)
196*4882a593Smuzhiyun 		dev_err(dev, "PHY did not enter Pn state\n");
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun 
artpec6_pcie_wait_for_phy(struct artpec6_pcie * artpec6_pcie)199*4882a593Smuzhiyun static void artpec6_pcie_wait_for_phy(struct artpec6_pcie *artpec6_pcie)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun 	switch (artpec6_pcie->variant) {
202*4882a593Smuzhiyun 	case ARTPEC6:
203*4882a593Smuzhiyun 		artpec6_pcie_wait_for_phy_a6(artpec6_pcie);
204*4882a593Smuzhiyun 		break;
205*4882a593Smuzhiyun 	case ARTPEC7:
206*4882a593Smuzhiyun 		artpec6_pcie_wait_for_phy_a7(artpec6_pcie);
207*4882a593Smuzhiyun 		break;
208*4882a593Smuzhiyun 	}
209*4882a593Smuzhiyun }
210*4882a593Smuzhiyun 
artpec6_pcie_init_phy_a6(struct artpec6_pcie * artpec6_pcie)211*4882a593Smuzhiyun static void artpec6_pcie_init_phy_a6(struct artpec6_pcie *artpec6_pcie)
212*4882a593Smuzhiyun {
213*4882a593Smuzhiyun 	u32 val;
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	val = artpec6_pcie_readl(artpec6_pcie, PCIECFG);
216*4882a593Smuzhiyun 	val |=  PCIECFG_RISRCREN |	/* Receiver term. 50 Ohm */
217*4882a593Smuzhiyun 		PCIECFG_MODE_TX_DRV_EN |
218*4882a593Smuzhiyun 		PCIECFG_CISRREN |	/* Reference clock term. 100 Ohm */
219*4882a593Smuzhiyun 		PCIECFG_MACRO_ENABLE;
220*4882a593Smuzhiyun 	val |= PCIECFG_REFCLK_ENABLE;
221*4882a593Smuzhiyun 	val &= ~PCIECFG_DBG_OEN;
222*4882a593Smuzhiyun 	val &= ~PCIECFG_CLKREQ_B;
223*4882a593Smuzhiyun 	artpec6_pcie_writel(artpec6_pcie, PCIECFG, val);
224*4882a593Smuzhiyun 	usleep_range(5000, 6000);
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	val = artpec6_pcie_readl(artpec6_pcie, NOCCFG);
227*4882a593Smuzhiyun 	val |= NOCCFG_ENABLE_CLK_PCIE;
228*4882a593Smuzhiyun 	artpec6_pcie_writel(artpec6_pcie, NOCCFG, val);
229*4882a593Smuzhiyun 	usleep_range(20, 30);
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	val = artpec6_pcie_readl(artpec6_pcie, PCIECFG);
232*4882a593Smuzhiyun 	val |= PCIECFG_PCLK_ENABLE | PCIECFG_PLL_ENABLE;
233*4882a593Smuzhiyun 	artpec6_pcie_writel(artpec6_pcie, PCIECFG, val);
234*4882a593Smuzhiyun 	usleep_range(6000, 7000);
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	val = artpec6_pcie_readl(artpec6_pcie, NOCCFG);
237*4882a593Smuzhiyun 	val &= ~NOCCFG_POWER_PCIE_IDLEREQ;
238*4882a593Smuzhiyun 	artpec6_pcie_writel(artpec6_pcie, NOCCFG, val);
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun 
artpec6_pcie_init_phy_a7(struct artpec6_pcie * artpec6_pcie)241*4882a593Smuzhiyun static void artpec6_pcie_init_phy_a7(struct artpec6_pcie *artpec6_pcie)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun 	struct dw_pcie *pci = artpec6_pcie->pci;
244*4882a593Smuzhiyun 	u32 val;
245*4882a593Smuzhiyun 	bool extrefclk;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	/* Check if external reference clock is connected */
248*4882a593Smuzhiyun 	val = artpec6_pcie_readl(artpec6_pcie, PCIESTAT);
249*4882a593Smuzhiyun 	extrefclk = !!(val & PCIESTAT_EXTREFCLK);
250*4882a593Smuzhiyun 	dev_dbg(pci->dev, "Using reference clock: %s\n",
251*4882a593Smuzhiyun 		extrefclk ? "external" : "internal");
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	val = artpec6_pcie_readl(artpec6_pcie, PCIECFG);
254*4882a593Smuzhiyun 	val |=  PCIECFG_RISRCREN |	/* Receiver term. 50 Ohm */
255*4882a593Smuzhiyun 		PCIECFG_PCLK_ENABLE;
256*4882a593Smuzhiyun 	if (extrefclk)
257*4882a593Smuzhiyun 		val |= PCIECFG_REFCLKSEL;
258*4882a593Smuzhiyun 	else
259*4882a593Smuzhiyun 		val &= ~PCIECFG_REFCLKSEL;
260*4882a593Smuzhiyun 	artpec6_pcie_writel(artpec6_pcie, PCIECFG, val);
261*4882a593Smuzhiyun 	usleep_range(10, 20);
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	val = artpec6_pcie_readl(artpec6_pcie, NOCCFG);
264*4882a593Smuzhiyun 	val |= NOCCFG_ENABLE_CLK_PCIE;
265*4882a593Smuzhiyun 	artpec6_pcie_writel(artpec6_pcie, NOCCFG, val);
266*4882a593Smuzhiyun 	usleep_range(20, 30);
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun 	val = artpec6_pcie_readl(artpec6_pcie, NOCCFG);
269*4882a593Smuzhiyun 	val &= ~NOCCFG_POWER_PCIE_IDLEREQ;
270*4882a593Smuzhiyun 	artpec6_pcie_writel(artpec6_pcie, NOCCFG, val);
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun 
artpec6_pcie_init_phy(struct artpec6_pcie * artpec6_pcie)273*4882a593Smuzhiyun static void artpec6_pcie_init_phy(struct artpec6_pcie *artpec6_pcie)
274*4882a593Smuzhiyun {
275*4882a593Smuzhiyun 	switch (artpec6_pcie->variant) {
276*4882a593Smuzhiyun 	case ARTPEC6:
277*4882a593Smuzhiyun 		artpec6_pcie_init_phy_a6(artpec6_pcie);
278*4882a593Smuzhiyun 		break;
279*4882a593Smuzhiyun 	case ARTPEC7:
280*4882a593Smuzhiyun 		artpec6_pcie_init_phy_a7(artpec6_pcie);
281*4882a593Smuzhiyun 		break;
282*4882a593Smuzhiyun 	}
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun 
artpec6_pcie_assert_core_reset(struct artpec6_pcie * artpec6_pcie)285*4882a593Smuzhiyun static void artpec6_pcie_assert_core_reset(struct artpec6_pcie *artpec6_pcie)
286*4882a593Smuzhiyun {
287*4882a593Smuzhiyun 	u32 val;
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	val = artpec6_pcie_readl(artpec6_pcie, PCIECFG);
290*4882a593Smuzhiyun 	switch (artpec6_pcie->variant) {
291*4882a593Smuzhiyun 	case ARTPEC6:
292*4882a593Smuzhiyun 		val |= PCIECFG_CORE_RESET_REQ;
293*4882a593Smuzhiyun 		break;
294*4882a593Smuzhiyun 	case ARTPEC7:
295*4882a593Smuzhiyun 		val &= ~PCIECFG_NOC_RESET;
296*4882a593Smuzhiyun 		break;
297*4882a593Smuzhiyun 	}
298*4882a593Smuzhiyun 	artpec6_pcie_writel(artpec6_pcie, PCIECFG, val);
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun 
artpec6_pcie_deassert_core_reset(struct artpec6_pcie * artpec6_pcie)301*4882a593Smuzhiyun static void artpec6_pcie_deassert_core_reset(struct artpec6_pcie *artpec6_pcie)
302*4882a593Smuzhiyun {
303*4882a593Smuzhiyun 	u32 val;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	val = artpec6_pcie_readl(artpec6_pcie, PCIECFG);
306*4882a593Smuzhiyun 	switch (artpec6_pcie->variant) {
307*4882a593Smuzhiyun 	case ARTPEC6:
308*4882a593Smuzhiyun 		val &= ~PCIECFG_CORE_RESET_REQ;
309*4882a593Smuzhiyun 		break;
310*4882a593Smuzhiyun 	case ARTPEC7:
311*4882a593Smuzhiyun 		val |= PCIECFG_NOC_RESET;
312*4882a593Smuzhiyun 		break;
313*4882a593Smuzhiyun 	}
314*4882a593Smuzhiyun 	artpec6_pcie_writel(artpec6_pcie, PCIECFG, val);
315*4882a593Smuzhiyun 	usleep_range(100, 200);
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun 
artpec6_pcie_host_init(struct pcie_port * pp)318*4882a593Smuzhiyun static int artpec6_pcie_host_init(struct pcie_port *pp)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
321*4882a593Smuzhiyun 	struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci);
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 	if (artpec6_pcie->variant == ARTPEC7) {
324*4882a593Smuzhiyun 		pci->n_fts[0] = 180;
325*4882a593Smuzhiyun 		pci->n_fts[1] = 180;
326*4882a593Smuzhiyun 	}
327*4882a593Smuzhiyun 	artpec6_pcie_assert_core_reset(artpec6_pcie);
328*4882a593Smuzhiyun 	artpec6_pcie_init_phy(artpec6_pcie);
329*4882a593Smuzhiyun 	artpec6_pcie_deassert_core_reset(artpec6_pcie);
330*4882a593Smuzhiyun 	artpec6_pcie_wait_for_phy(artpec6_pcie);
331*4882a593Smuzhiyun 	dw_pcie_setup_rc(pp);
332*4882a593Smuzhiyun 	artpec6_pcie_establish_link(pci);
333*4882a593Smuzhiyun 	dw_pcie_wait_for_link(pci);
334*4882a593Smuzhiyun 	dw_pcie_msi_init(pp);
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	return 0;
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun static const struct dw_pcie_host_ops artpec6_pcie_host_ops = {
340*4882a593Smuzhiyun 	.host_init = artpec6_pcie_host_init,
341*4882a593Smuzhiyun };
342*4882a593Smuzhiyun 
artpec6_add_pcie_port(struct artpec6_pcie * artpec6_pcie,struct platform_device * pdev)343*4882a593Smuzhiyun static int artpec6_add_pcie_port(struct artpec6_pcie *artpec6_pcie,
344*4882a593Smuzhiyun 				 struct platform_device *pdev)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun 	struct dw_pcie *pci = artpec6_pcie->pci;
347*4882a593Smuzhiyun 	struct pcie_port *pp = &pci->pp;
348*4882a593Smuzhiyun 	struct device *dev = pci->dev;
349*4882a593Smuzhiyun 	int ret;
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	if (IS_ENABLED(CONFIG_PCI_MSI)) {
352*4882a593Smuzhiyun 		pp->msi_irq = platform_get_irq_byname(pdev, "msi");
353*4882a593Smuzhiyun 		if (pp->msi_irq < 0)
354*4882a593Smuzhiyun 			return pp->msi_irq;
355*4882a593Smuzhiyun 	}
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 	pp->ops = &artpec6_pcie_host_ops;
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	ret = dw_pcie_host_init(pp);
360*4882a593Smuzhiyun 	if (ret) {
361*4882a593Smuzhiyun 		dev_err(dev, "failed to initialize host\n");
362*4882a593Smuzhiyun 		return ret;
363*4882a593Smuzhiyun 	}
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	return 0;
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun 
artpec6_pcie_ep_init(struct dw_pcie_ep * ep)368*4882a593Smuzhiyun static void artpec6_pcie_ep_init(struct dw_pcie_ep *ep)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
371*4882a593Smuzhiyun 	struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci);
372*4882a593Smuzhiyun 	enum pci_barno bar;
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	artpec6_pcie_assert_core_reset(artpec6_pcie);
375*4882a593Smuzhiyun 	artpec6_pcie_init_phy(artpec6_pcie);
376*4882a593Smuzhiyun 	artpec6_pcie_deassert_core_reset(artpec6_pcie);
377*4882a593Smuzhiyun 	artpec6_pcie_wait_for_phy(artpec6_pcie);
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun 	for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
380*4882a593Smuzhiyun 		dw_pcie_ep_reset_bar(pci, bar);
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun 
artpec6_pcie_raise_irq(struct dw_pcie_ep * ep,u8 func_no,enum pci_epc_irq_type type,u16 interrupt_num)383*4882a593Smuzhiyun static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
384*4882a593Smuzhiyun 				  enum pci_epc_irq_type type, u16 interrupt_num)
385*4882a593Smuzhiyun {
386*4882a593Smuzhiyun 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	switch (type) {
389*4882a593Smuzhiyun 	case PCI_EPC_IRQ_LEGACY:
390*4882a593Smuzhiyun 		dev_err(pci->dev, "EP cannot trigger legacy IRQs\n");
391*4882a593Smuzhiyun 		return -EINVAL;
392*4882a593Smuzhiyun 	case PCI_EPC_IRQ_MSI:
393*4882a593Smuzhiyun 		return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num);
394*4882a593Smuzhiyun 	default:
395*4882a593Smuzhiyun 		dev_err(pci->dev, "UNKNOWN IRQ type\n");
396*4882a593Smuzhiyun 	}
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 	return 0;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun static const struct dw_pcie_ep_ops pcie_ep_ops = {
402*4882a593Smuzhiyun 	.ep_init = artpec6_pcie_ep_init,
403*4882a593Smuzhiyun 	.raise_irq = artpec6_pcie_raise_irq,
404*4882a593Smuzhiyun };
405*4882a593Smuzhiyun 
artpec6_add_pcie_ep(struct artpec6_pcie * artpec6_pcie,struct platform_device * pdev)406*4882a593Smuzhiyun static int artpec6_add_pcie_ep(struct artpec6_pcie *artpec6_pcie,
407*4882a593Smuzhiyun 			       struct platform_device *pdev)
408*4882a593Smuzhiyun {
409*4882a593Smuzhiyun 	int ret;
410*4882a593Smuzhiyun 	struct dw_pcie_ep *ep;
411*4882a593Smuzhiyun 	struct resource *res;
412*4882a593Smuzhiyun 	struct device *dev = &pdev->dev;
413*4882a593Smuzhiyun 	struct dw_pcie *pci = artpec6_pcie->pci;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 	ep = &pci->ep;
416*4882a593Smuzhiyun 	ep->ops = &pcie_ep_ops;
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 	pci->dbi_base2 = devm_platform_ioremap_resource_byname(pdev, "dbi2");
419*4882a593Smuzhiyun 	if (IS_ERR(pci->dbi_base2))
420*4882a593Smuzhiyun 		return PTR_ERR(pci->dbi_base2);
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space");
423*4882a593Smuzhiyun 	if (!res)
424*4882a593Smuzhiyun 		return -EINVAL;
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 	ep->phys_base = res->start;
427*4882a593Smuzhiyun 	ep->addr_size = resource_size(res);
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun 	ret = dw_pcie_ep_init(ep);
430*4882a593Smuzhiyun 	if (ret) {
431*4882a593Smuzhiyun 		dev_err(dev, "failed to initialize endpoint\n");
432*4882a593Smuzhiyun 		return ret;
433*4882a593Smuzhiyun 	}
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	return 0;
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun 
artpec6_pcie_probe(struct platform_device * pdev)438*4882a593Smuzhiyun static int artpec6_pcie_probe(struct platform_device *pdev)
439*4882a593Smuzhiyun {
440*4882a593Smuzhiyun 	struct device *dev = &pdev->dev;
441*4882a593Smuzhiyun 	struct dw_pcie *pci;
442*4882a593Smuzhiyun 	struct artpec6_pcie *artpec6_pcie;
443*4882a593Smuzhiyun 	int ret;
444*4882a593Smuzhiyun 	const struct of_device_id *match;
445*4882a593Smuzhiyun 	const struct artpec_pcie_of_data *data;
446*4882a593Smuzhiyun 	enum artpec_pcie_variants variant;
447*4882a593Smuzhiyun 	enum dw_pcie_device_mode mode;
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 	match = of_match_device(artpec6_pcie_of_match, dev);
450*4882a593Smuzhiyun 	if (!match)
451*4882a593Smuzhiyun 		return -EINVAL;
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 	data = (struct artpec_pcie_of_data *)match->data;
454*4882a593Smuzhiyun 	variant = (enum artpec_pcie_variants)data->variant;
455*4882a593Smuzhiyun 	mode = (enum dw_pcie_device_mode)data->mode;
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun 	artpec6_pcie = devm_kzalloc(dev, sizeof(*artpec6_pcie), GFP_KERNEL);
458*4882a593Smuzhiyun 	if (!artpec6_pcie)
459*4882a593Smuzhiyun 		return -ENOMEM;
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 	pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
462*4882a593Smuzhiyun 	if (!pci)
463*4882a593Smuzhiyun 		return -ENOMEM;
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 	pci->dev = dev;
466*4882a593Smuzhiyun 	pci->ops = &dw_pcie_ops;
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun 	artpec6_pcie->pci = pci;
469*4882a593Smuzhiyun 	artpec6_pcie->variant = variant;
470*4882a593Smuzhiyun 	artpec6_pcie->mode = mode;
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun 	pci->dbi_base = devm_platform_ioremap_resource_byname(pdev, "dbi");
473*4882a593Smuzhiyun 	if (IS_ERR(pci->dbi_base))
474*4882a593Smuzhiyun 		return PTR_ERR(pci->dbi_base);
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	artpec6_pcie->phy_base =
477*4882a593Smuzhiyun 		devm_platform_ioremap_resource_byname(pdev, "phy");
478*4882a593Smuzhiyun 	if (IS_ERR(artpec6_pcie->phy_base))
479*4882a593Smuzhiyun 		return PTR_ERR(artpec6_pcie->phy_base);
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	artpec6_pcie->regmap =
482*4882a593Smuzhiyun 		syscon_regmap_lookup_by_phandle(dev->of_node,
483*4882a593Smuzhiyun 						"axis,syscon-pcie");
484*4882a593Smuzhiyun 	if (IS_ERR(artpec6_pcie->regmap))
485*4882a593Smuzhiyun 		return PTR_ERR(artpec6_pcie->regmap);
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 	platform_set_drvdata(pdev, artpec6_pcie);
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun 	switch (artpec6_pcie->mode) {
490*4882a593Smuzhiyun 	case DW_PCIE_RC_TYPE:
491*4882a593Smuzhiyun 		if (!IS_ENABLED(CONFIG_PCIE_ARTPEC6_HOST))
492*4882a593Smuzhiyun 			return -ENODEV;
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 		ret = artpec6_add_pcie_port(artpec6_pcie, pdev);
495*4882a593Smuzhiyun 		if (ret < 0)
496*4882a593Smuzhiyun 			return ret;
497*4882a593Smuzhiyun 		break;
498*4882a593Smuzhiyun 	case DW_PCIE_EP_TYPE: {
499*4882a593Smuzhiyun 		u32 val;
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun 		if (!IS_ENABLED(CONFIG_PCIE_ARTPEC6_EP))
502*4882a593Smuzhiyun 			return -ENODEV;
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun 		val = artpec6_pcie_readl(artpec6_pcie, PCIECFG);
505*4882a593Smuzhiyun 		val &= ~PCIECFG_DEVICE_TYPE_MASK;
506*4882a593Smuzhiyun 		artpec6_pcie_writel(artpec6_pcie, PCIECFG, val);
507*4882a593Smuzhiyun 		ret = artpec6_add_pcie_ep(artpec6_pcie, pdev);
508*4882a593Smuzhiyun 		if (ret < 0)
509*4882a593Smuzhiyun 			return ret;
510*4882a593Smuzhiyun 		break;
511*4882a593Smuzhiyun 	}
512*4882a593Smuzhiyun 	default:
513*4882a593Smuzhiyun 		dev_err(dev, "INVALID device type %d\n", artpec6_pcie->mode);
514*4882a593Smuzhiyun 	}
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	return 0;
517*4882a593Smuzhiyun }
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun static const struct artpec_pcie_of_data artpec6_pcie_rc_of_data = {
520*4882a593Smuzhiyun 	.variant = ARTPEC6,
521*4882a593Smuzhiyun 	.mode = DW_PCIE_RC_TYPE,
522*4882a593Smuzhiyun };
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun static const struct artpec_pcie_of_data artpec6_pcie_ep_of_data = {
525*4882a593Smuzhiyun 	.variant = ARTPEC6,
526*4882a593Smuzhiyun 	.mode = DW_PCIE_EP_TYPE,
527*4882a593Smuzhiyun };
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun static const struct artpec_pcie_of_data artpec7_pcie_rc_of_data = {
530*4882a593Smuzhiyun 	.variant = ARTPEC7,
531*4882a593Smuzhiyun 	.mode = DW_PCIE_RC_TYPE,
532*4882a593Smuzhiyun };
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun static const struct artpec_pcie_of_data artpec7_pcie_ep_of_data = {
535*4882a593Smuzhiyun 	.variant = ARTPEC7,
536*4882a593Smuzhiyun 	.mode = DW_PCIE_EP_TYPE,
537*4882a593Smuzhiyun };
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun static const struct of_device_id artpec6_pcie_of_match[] = {
540*4882a593Smuzhiyun 	{
541*4882a593Smuzhiyun 		.compatible = "axis,artpec6-pcie",
542*4882a593Smuzhiyun 		.data = &artpec6_pcie_rc_of_data,
543*4882a593Smuzhiyun 	},
544*4882a593Smuzhiyun 	{
545*4882a593Smuzhiyun 		.compatible = "axis,artpec6-pcie-ep",
546*4882a593Smuzhiyun 		.data = &artpec6_pcie_ep_of_data,
547*4882a593Smuzhiyun 	},
548*4882a593Smuzhiyun 	{
549*4882a593Smuzhiyun 		.compatible = "axis,artpec7-pcie",
550*4882a593Smuzhiyun 		.data = &artpec7_pcie_rc_of_data,
551*4882a593Smuzhiyun 	},
552*4882a593Smuzhiyun 	{
553*4882a593Smuzhiyun 		.compatible = "axis,artpec7-pcie-ep",
554*4882a593Smuzhiyun 		.data = &artpec7_pcie_ep_of_data,
555*4882a593Smuzhiyun 	},
556*4882a593Smuzhiyun 	{},
557*4882a593Smuzhiyun };
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun static struct platform_driver artpec6_pcie_driver = {
560*4882a593Smuzhiyun 	.probe = artpec6_pcie_probe,
561*4882a593Smuzhiyun 	.driver = {
562*4882a593Smuzhiyun 		.name	= "artpec6-pcie",
563*4882a593Smuzhiyun 		.of_match_table = artpec6_pcie_of_match,
564*4882a593Smuzhiyun 		.suppress_bind_attrs = true,
565*4882a593Smuzhiyun 	},
566*4882a593Smuzhiyun };
567*4882a593Smuzhiyun builtin_platform_driver(artpec6_pcie_driver);
568