xref: /OK3568_Linux_fs/kernel/drivers/pci/controller/cadence/pcie-cadence-host.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun // Copyright (c) 2017 Cadence
3*4882a593Smuzhiyun // Cadence PCIe host controller driver.
4*4882a593Smuzhiyun // Author: Cyrille Pitchen <cyrille.pitchen@free-electrons.com>
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #include <linux/delay.h>
7*4882a593Smuzhiyun #include <linux/kernel.h>
8*4882a593Smuzhiyun #include <linux/list_sort.h>
9*4882a593Smuzhiyun #include <linux/of_address.h>
10*4882a593Smuzhiyun #include <linux/of_pci.h>
11*4882a593Smuzhiyun #include <linux/platform_device.h>
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include "pcie-cadence.h"
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun static u64 bar_max_size[] = {
16*4882a593Smuzhiyun 	[RP_BAR0] = _ULL(128 * SZ_2G),
17*4882a593Smuzhiyun 	[RP_BAR1] = SZ_2G,
18*4882a593Smuzhiyun 	[RP_NO_BAR] = _BITULL(63),
19*4882a593Smuzhiyun };
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun static u8 bar_aperture_mask[] = {
22*4882a593Smuzhiyun 	[RP_BAR0] = 0x1F,
23*4882a593Smuzhiyun 	[RP_BAR1] = 0xF,
24*4882a593Smuzhiyun };
25*4882a593Smuzhiyun 
cdns_pci_map_bus(struct pci_bus * bus,unsigned int devfn,int where)26*4882a593Smuzhiyun void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
27*4882a593Smuzhiyun 			       int where)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun 	struct pci_host_bridge *bridge = pci_find_host_bridge(bus);
30*4882a593Smuzhiyun 	struct cdns_pcie_rc *rc = pci_host_bridge_priv(bridge);
31*4882a593Smuzhiyun 	struct cdns_pcie *pcie = &rc->pcie;
32*4882a593Smuzhiyun 	unsigned int busn = bus->number;
33*4882a593Smuzhiyun 	u32 addr0, desc0;
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun 	if (pci_is_root_bus(bus)) {
36*4882a593Smuzhiyun 		/*
37*4882a593Smuzhiyun 		 * Only the root port (devfn == 0) is connected to this bus.
38*4882a593Smuzhiyun 		 * All other PCI devices are behind some bridge hence on another
39*4882a593Smuzhiyun 		 * bus.
40*4882a593Smuzhiyun 		 */
41*4882a593Smuzhiyun 		if (devfn)
42*4882a593Smuzhiyun 			return NULL;
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 		return pcie->reg_base + (where & 0xfff);
45*4882a593Smuzhiyun 	}
46*4882a593Smuzhiyun 	/* Check that the link is up */
47*4882a593Smuzhiyun 	if (!(cdns_pcie_readl(pcie, CDNS_PCIE_LM_BASE) & 0x1))
48*4882a593Smuzhiyun 		return NULL;
49*4882a593Smuzhiyun 	/* Clear AXI link-down status */
50*4882a593Smuzhiyun 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_LINKDOWN, 0x0);
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	/* Update Output registers for AXI region 0. */
53*4882a593Smuzhiyun 	addr0 = CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_NBITS(12) |
54*4882a593Smuzhiyun 		CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN(devfn) |
55*4882a593Smuzhiyun 		CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_BUS(busn);
56*4882a593Smuzhiyun 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_PCI_ADDR0(0), addr0);
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	/* Configuration Type 0 or Type 1 access. */
59*4882a593Smuzhiyun 	desc0 = CDNS_PCIE_AT_OB_REGION_DESC0_HARDCODED_RID |
60*4882a593Smuzhiyun 		CDNS_PCIE_AT_OB_REGION_DESC0_DEVFN(0);
61*4882a593Smuzhiyun 	/*
62*4882a593Smuzhiyun 	 * The bus number was already set once for all in desc1 by
63*4882a593Smuzhiyun 	 * cdns_pcie_host_init_address_translation().
64*4882a593Smuzhiyun 	 */
65*4882a593Smuzhiyun 	if (busn == bridge->busnr + 1)
66*4882a593Smuzhiyun 		desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_CONF_TYPE0;
67*4882a593Smuzhiyun 	else
68*4882a593Smuzhiyun 		desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_CONF_TYPE1;
69*4882a593Smuzhiyun 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC0(0), desc0);
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 	return rc->cfg_base + (where & 0xfff);
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun static struct pci_ops cdns_pcie_host_ops = {
75*4882a593Smuzhiyun 	.map_bus	= cdns_pci_map_bus,
76*4882a593Smuzhiyun 	.read		= pci_generic_config_read,
77*4882a593Smuzhiyun 	.write		= pci_generic_config_write,
78*4882a593Smuzhiyun };
79*4882a593Smuzhiyun 
cdns_pcie_host_wait_for_link(struct cdns_pcie * pcie)80*4882a593Smuzhiyun static int cdns_pcie_host_wait_for_link(struct cdns_pcie *pcie)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun 	struct device *dev = pcie->dev;
83*4882a593Smuzhiyun 	int retries;
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	/* Check if the link is up or not */
86*4882a593Smuzhiyun 	for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
87*4882a593Smuzhiyun 		if (cdns_pcie_link_up(pcie)) {
88*4882a593Smuzhiyun 			dev_info(dev, "Link up\n");
89*4882a593Smuzhiyun 			return 0;
90*4882a593Smuzhiyun 		}
91*4882a593Smuzhiyun 		usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
92*4882a593Smuzhiyun 	}
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	return -ETIMEDOUT;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun 
cdns_pcie_retrain(struct cdns_pcie * pcie)97*4882a593Smuzhiyun static int cdns_pcie_retrain(struct cdns_pcie *pcie)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun 	u32 lnk_cap_sls, pcie_cap_off = CDNS_PCIE_RP_CAP_OFFSET;
100*4882a593Smuzhiyun 	u16 lnk_stat, lnk_ctl;
101*4882a593Smuzhiyun 	int ret = 0;
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	/*
104*4882a593Smuzhiyun 	 * Set retrain bit if current speed is 2.5 GB/s,
105*4882a593Smuzhiyun 	 * but the PCIe root port support is > 2.5 GB/s.
106*4882a593Smuzhiyun 	 */
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	lnk_cap_sls = cdns_pcie_readl(pcie, (CDNS_PCIE_RP_BASE + pcie_cap_off +
109*4882a593Smuzhiyun 					     PCI_EXP_LNKCAP));
110*4882a593Smuzhiyun 	if ((lnk_cap_sls & PCI_EXP_LNKCAP_SLS) <= PCI_EXP_LNKCAP_SLS_2_5GB)
111*4882a593Smuzhiyun 		return ret;
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	lnk_stat = cdns_pcie_rp_readw(pcie, pcie_cap_off + PCI_EXP_LNKSTA);
114*4882a593Smuzhiyun 	if ((lnk_stat & PCI_EXP_LNKSTA_CLS) == PCI_EXP_LNKSTA_CLS_2_5GB) {
115*4882a593Smuzhiyun 		lnk_ctl = cdns_pcie_rp_readw(pcie,
116*4882a593Smuzhiyun 					     pcie_cap_off + PCI_EXP_LNKCTL);
117*4882a593Smuzhiyun 		lnk_ctl |= PCI_EXP_LNKCTL_RL;
118*4882a593Smuzhiyun 		cdns_pcie_rp_writew(pcie, pcie_cap_off + PCI_EXP_LNKCTL,
119*4882a593Smuzhiyun 				    lnk_ctl);
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 		ret = cdns_pcie_host_wait_for_link(pcie);
122*4882a593Smuzhiyun 	}
123*4882a593Smuzhiyun 	return ret;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun 
cdns_pcie_host_start_link(struct cdns_pcie_rc * rc)126*4882a593Smuzhiyun static int cdns_pcie_host_start_link(struct cdns_pcie_rc *rc)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun 	struct cdns_pcie *pcie = &rc->pcie;
129*4882a593Smuzhiyun 	int ret;
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	ret = cdns_pcie_host_wait_for_link(pcie);
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	/*
134*4882a593Smuzhiyun 	 * Retrain link for Gen2 training defect
135*4882a593Smuzhiyun 	 * if quirk flag is set.
136*4882a593Smuzhiyun 	 */
137*4882a593Smuzhiyun 	if (!ret && rc->quirk_retrain_flag)
138*4882a593Smuzhiyun 		ret = cdns_pcie_retrain(pcie);
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 	return ret;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun 
cdns_pcie_host_init_root_port(struct cdns_pcie_rc * rc)143*4882a593Smuzhiyun static int cdns_pcie_host_init_root_port(struct cdns_pcie_rc *rc)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun 	struct cdns_pcie *pcie = &rc->pcie;
146*4882a593Smuzhiyun 	u32 value, ctrl;
147*4882a593Smuzhiyun 	u32 id;
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 	/*
150*4882a593Smuzhiyun 	 * Set the root complex BAR configuration register:
151*4882a593Smuzhiyun 	 * - disable both BAR0 and BAR1.
152*4882a593Smuzhiyun 	 * - enable Prefetchable Memory Base and Limit registers in type 1
153*4882a593Smuzhiyun 	 *   config space (64 bits).
154*4882a593Smuzhiyun 	 * - enable IO Base and Limit registers in type 1 config
155*4882a593Smuzhiyun 	 *   space (32 bits).
156*4882a593Smuzhiyun 	 */
157*4882a593Smuzhiyun 	ctrl = CDNS_PCIE_LM_BAR_CFG_CTRL_DISABLED;
158*4882a593Smuzhiyun 	value = CDNS_PCIE_LM_RC_BAR_CFG_BAR0_CTRL(ctrl) |
159*4882a593Smuzhiyun 		CDNS_PCIE_LM_RC_BAR_CFG_BAR1_CTRL(ctrl) |
160*4882a593Smuzhiyun 		CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_ENABLE |
161*4882a593Smuzhiyun 		CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_64BITS |
162*4882a593Smuzhiyun 		CDNS_PCIE_LM_RC_BAR_CFG_IO_ENABLE |
163*4882a593Smuzhiyun 		CDNS_PCIE_LM_RC_BAR_CFG_IO_32BITS;
164*4882a593Smuzhiyun 	cdns_pcie_writel(pcie, CDNS_PCIE_LM_RC_BAR_CFG, value);
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	/* Set root port configuration space */
167*4882a593Smuzhiyun 	if (rc->vendor_id != 0xffff) {
168*4882a593Smuzhiyun 		id = CDNS_PCIE_LM_ID_VENDOR(rc->vendor_id) |
169*4882a593Smuzhiyun 			CDNS_PCIE_LM_ID_SUBSYS(rc->vendor_id);
170*4882a593Smuzhiyun 		cdns_pcie_writel(pcie, CDNS_PCIE_LM_ID, id);
171*4882a593Smuzhiyun 	}
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	if (rc->device_id != 0xffff)
174*4882a593Smuzhiyun 		cdns_pcie_rp_writew(pcie, PCI_DEVICE_ID, rc->device_id);
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	cdns_pcie_rp_writeb(pcie, PCI_CLASS_REVISION, 0);
177*4882a593Smuzhiyun 	cdns_pcie_rp_writeb(pcie, PCI_CLASS_PROG, 0);
178*4882a593Smuzhiyun 	cdns_pcie_rp_writew(pcie, PCI_CLASS_DEVICE, PCI_CLASS_BRIDGE_PCI);
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	return 0;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun 
cdns_pcie_host_bar_ib_config(struct cdns_pcie_rc * rc,enum cdns_pcie_rp_bar bar,u64 cpu_addr,u64 size,unsigned long flags)183*4882a593Smuzhiyun static int cdns_pcie_host_bar_ib_config(struct cdns_pcie_rc *rc,
184*4882a593Smuzhiyun 					enum cdns_pcie_rp_bar bar,
185*4882a593Smuzhiyun 					u64 cpu_addr, u64 size,
186*4882a593Smuzhiyun 					unsigned long flags)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun 	struct cdns_pcie *pcie = &rc->pcie;
189*4882a593Smuzhiyun 	u32 addr0, addr1, aperture, value;
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	if (!rc->avail_ib_bar[bar])
192*4882a593Smuzhiyun 		return -EBUSY;
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	rc->avail_ib_bar[bar] = false;
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	aperture = ilog2(size);
197*4882a593Smuzhiyun 	addr0 = CDNS_PCIE_AT_IB_RP_BAR_ADDR0_NBITS(aperture) |
198*4882a593Smuzhiyun 		(lower_32_bits(cpu_addr) & GENMASK(31, 8));
199*4882a593Smuzhiyun 	addr1 = upper_32_bits(cpu_addr);
200*4882a593Smuzhiyun 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_RP_BAR_ADDR0(bar), addr0);
201*4882a593Smuzhiyun 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_RP_BAR_ADDR1(bar), addr1);
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	if (bar == RP_NO_BAR)
204*4882a593Smuzhiyun 		return 0;
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	value = cdns_pcie_readl(pcie, CDNS_PCIE_LM_RC_BAR_CFG);
207*4882a593Smuzhiyun 	value &= ~(LM_RC_BAR_CFG_CTRL_MEM_64BITS(bar) |
208*4882a593Smuzhiyun 		   LM_RC_BAR_CFG_CTRL_PREF_MEM_64BITS(bar) |
209*4882a593Smuzhiyun 		   LM_RC_BAR_CFG_CTRL_MEM_32BITS(bar) |
210*4882a593Smuzhiyun 		   LM_RC_BAR_CFG_CTRL_PREF_MEM_32BITS(bar) |
211*4882a593Smuzhiyun 		   LM_RC_BAR_CFG_APERTURE(bar, bar_aperture_mask[bar] + 2));
212*4882a593Smuzhiyun 	if (size + cpu_addr >= SZ_4G) {
213*4882a593Smuzhiyun 		if (!(flags & IORESOURCE_PREFETCH))
214*4882a593Smuzhiyun 			value |= LM_RC_BAR_CFG_CTRL_MEM_64BITS(bar);
215*4882a593Smuzhiyun 		value |= LM_RC_BAR_CFG_CTRL_PREF_MEM_64BITS(bar);
216*4882a593Smuzhiyun 	} else {
217*4882a593Smuzhiyun 		if (!(flags & IORESOURCE_PREFETCH))
218*4882a593Smuzhiyun 			value |= LM_RC_BAR_CFG_CTRL_MEM_32BITS(bar);
219*4882a593Smuzhiyun 		value |= LM_RC_BAR_CFG_CTRL_PREF_MEM_32BITS(bar);
220*4882a593Smuzhiyun 	}
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	value |= LM_RC_BAR_CFG_APERTURE(bar, aperture);
223*4882a593Smuzhiyun 	cdns_pcie_writel(pcie, CDNS_PCIE_LM_RC_BAR_CFG, value);
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	return 0;
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun static enum cdns_pcie_rp_bar
cdns_pcie_host_find_min_bar(struct cdns_pcie_rc * rc,u64 size)229*4882a593Smuzhiyun cdns_pcie_host_find_min_bar(struct cdns_pcie_rc *rc, u64 size)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun 	enum cdns_pcie_rp_bar bar, sel_bar;
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	sel_bar = RP_BAR_UNDEFINED;
234*4882a593Smuzhiyun 	for (bar = RP_BAR0; bar <= RP_NO_BAR; bar++) {
235*4882a593Smuzhiyun 		if (!rc->avail_ib_bar[bar])
236*4882a593Smuzhiyun 			continue;
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 		if (size <= bar_max_size[bar]) {
239*4882a593Smuzhiyun 			if (sel_bar == RP_BAR_UNDEFINED) {
240*4882a593Smuzhiyun 				sel_bar = bar;
241*4882a593Smuzhiyun 				continue;
242*4882a593Smuzhiyun 			}
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 			if (bar_max_size[bar] < bar_max_size[sel_bar])
245*4882a593Smuzhiyun 				sel_bar = bar;
246*4882a593Smuzhiyun 		}
247*4882a593Smuzhiyun 	}
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 	return sel_bar;
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun static enum cdns_pcie_rp_bar
cdns_pcie_host_find_max_bar(struct cdns_pcie_rc * rc,u64 size)253*4882a593Smuzhiyun cdns_pcie_host_find_max_bar(struct cdns_pcie_rc *rc, u64 size)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun 	enum cdns_pcie_rp_bar bar, sel_bar;
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	sel_bar = RP_BAR_UNDEFINED;
258*4882a593Smuzhiyun 	for (bar = RP_BAR0; bar <= RP_NO_BAR; bar++) {
259*4882a593Smuzhiyun 		if (!rc->avail_ib_bar[bar])
260*4882a593Smuzhiyun 			continue;
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 		if (size >= bar_max_size[bar]) {
263*4882a593Smuzhiyun 			if (sel_bar == RP_BAR_UNDEFINED) {
264*4882a593Smuzhiyun 				sel_bar = bar;
265*4882a593Smuzhiyun 				continue;
266*4882a593Smuzhiyun 			}
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun 			if (bar_max_size[bar] > bar_max_size[sel_bar])
269*4882a593Smuzhiyun 				sel_bar = bar;
270*4882a593Smuzhiyun 		}
271*4882a593Smuzhiyun 	}
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	return sel_bar;
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun 
cdns_pcie_host_bar_config(struct cdns_pcie_rc * rc,struct resource_entry * entry)276*4882a593Smuzhiyun static int cdns_pcie_host_bar_config(struct cdns_pcie_rc *rc,
277*4882a593Smuzhiyun 				     struct resource_entry *entry)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun 	u64 cpu_addr, pci_addr, size, winsize;
280*4882a593Smuzhiyun 	struct cdns_pcie *pcie = &rc->pcie;
281*4882a593Smuzhiyun 	struct device *dev = pcie->dev;
282*4882a593Smuzhiyun 	enum cdns_pcie_rp_bar bar;
283*4882a593Smuzhiyun 	unsigned long flags;
284*4882a593Smuzhiyun 	int ret;
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	cpu_addr = entry->res->start;
287*4882a593Smuzhiyun 	pci_addr = entry->res->start - entry->offset;
288*4882a593Smuzhiyun 	flags = entry->res->flags;
289*4882a593Smuzhiyun 	size = resource_size(entry->res);
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	if (entry->offset) {
292*4882a593Smuzhiyun 		dev_err(dev, "PCI addr: %llx must be equal to CPU addr: %llx\n",
293*4882a593Smuzhiyun 			pci_addr, cpu_addr);
294*4882a593Smuzhiyun 		return -EINVAL;
295*4882a593Smuzhiyun 	}
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	while (size > 0) {
298*4882a593Smuzhiyun 		/*
299*4882a593Smuzhiyun 		 * Try to find a minimum BAR whose size is greater than
300*4882a593Smuzhiyun 		 * or equal to the remaining resource_entry size. This will
301*4882a593Smuzhiyun 		 * fail if the size of each of the available BARs is less than
302*4882a593Smuzhiyun 		 * the remaining resource_entry size.
303*4882a593Smuzhiyun 		 * If a minimum BAR is found, IB ATU will be configured and
304*4882a593Smuzhiyun 		 * exited.
305*4882a593Smuzhiyun 		 */
306*4882a593Smuzhiyun 		bar = cdns_pcie_host_find_min_bar(rc, size);
307*4882a593Smuzhiyun 		if (bar != RP_BAR_UNDEFINED) {
308*4882a593Smuzhiyun 			ret = cdns_pcie_host_bar_ib_config(rc, bar, cpu_addr,
309*4882a593Smuzhiyun 							   size, flags);
310*4882a593Smuzhiyun 			if (ret)
311*4882a593Smuzhiyun 				dev_err(dev, "IB BAR: %d config failed\n", bar);
312*4882a593Smuzhiyun 			return ret;
313*4882a593Smuzhiyun 		}
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 		/*
316*4882a593Smuzhiyun 		 * If the control reaches here, it would mean the remaining
317*4882a593Smuzhiyun 		 * resource_entry size cannot be fitted in a single BAR. So we
318*4882a593Smuzhiyun 		 * find a maximum BAR whose size is less than or equal to the
319*4882a593Smuzhiyun 		 * remaining resource_entry size and split the resource entry
320*4882a593Smuzhiyun 		 * so that part of resource entry is fitted inside the maximum
321*4882a593Smuzhiyun 		 * BAR. The remaining size would be fitted during the next
322*4882a593Smuzhiyun 		 * iteration of the loop.
323*4882a593Smuzhiyun 		 * If a maximum BAR is not found, there is no way we can fit
324*4882a593Smuzhiyun 		 * this resource_entry, so we error out.
325*4882a593Smuzhiyun 		 */
326*4882a593Smuzhiyun 		bar = cdns_pcie_host_find_max_bar(rc, size);
327*4882a593Smuzhiyun 		if (bar == RP_BAR_UNDEFINED) {
328*4882a593Smuzhiyun 			dev_err(dev, "No free BAR to map cpu_addr %llx\n",
329*4882a593Smuzhiyun 				cpu_addr);
330*4882a593Smuzhiyun 			return -EINVAL;
331*4882a593Smuzhiyun 		}
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 		winsize = bar_max_size[bar];
334*4882a593Smuzhiyun 		ret = cdns_pcie_host_bar_ib_config(rc, bar, cpu_addr, winsize,
335*4882a593Smuzhiyun 						   flags);
336*4882a593Smuzhiyun 		if (ret) {
337*4882a593Smuzhiyun 			dev_err(dev, "IB BAR: %d config failed\n", bar);
338*4882a593Smuzhiyun 			return ret;
339*4882a593Smuzhiyun 		}
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 		size -= winsize;
342*4882a593Smuzhiyun 		cpu_addr += winsize;
343*4882a593Smuzhiyun 	}
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	return 0;
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun 
cdns_pcie_host_dma_ranges_cmp(void * priv,struct list_head * a,struct list_head * b)348*4882a593Smuzhiyun static int cdns_pcie_host_dma_ranges_cmp(void *priv, struct list_head *a, struct list_head *b)
349*4882a593Smuzhiyun {
350*4882a593Smuzhiyun 	struct resource_entry *entry1, *entry2;
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun         entry1 = container_of(a, struct resource_entry, node);
353*4882a593Smuzhiyun         entry2 = container_of(b, struct resource_entry, node);
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun         return resource_size(entry2->res) - resource_size(entry1->res);
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun 
cdns_pcie_host_map_dma_ranges(struct cdns_pcie_rc * rc)358*4882a593Smuzhiyun static int cdns_pcie_host_map_dma_ranges(struct cdns_pcie_rc *rc)
359*4882a593Smuzhiyun {
360*4882a593Smuzhiyun 	struct cdns_pcie *pcie = &rc->pcie;
361*4882a593Smuzhiyun 	struct device *dev = pcie->dev;
362*4882a593Smuzhiyun 	struct device_node *np = dev->of_node;
363*4882a593Smuzhiyun 	struct pci_host_bridge *bridge;
364*4882a593Smuzhiyun 	struct resource_entry *entry;
365*4882a593Smuzhiyun 	u32 no_bar_nbits = 32;
366*4882a593Smuzhiyun 	int err;
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	bridge = pci_host_bridge_from_priv(rc);
369*4882a593Smuzhiyun 	if (!bridge)
370*4882a593Smuzhiyun 		return -ENOMEM;
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	if (list_empty(&bridge->dma_ranges)) {
373*4882a593Smuzhiyun 		of_property_read_u32(np, "cdns,no-bar-match-nbits",
374*4882a593Smuzhiyun 				     &no_bar_nbits);
375*4882a593Smuzhiyun 		err = cdns_pcie_host_bar_ib_config(rc, RP_NO_BAR, 0x0,
376*4882a593Smuzhiyun 						   (u64)1 << no_bar_nbits, 0);
377*4882a593Smuzhiyun 		if (err)
378*4882a593Smuzhiyun 			dev_err(dev, "IB BAR: %d config failed\n", RP_NO_BAR);
379*4882a593Smuzhiyun 		return err;
380*4882a593Smuzhiyun 	}
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	list_sort(NULL, &bridge->dma_ranges, cdns_pcie_host_dma_ranges_cmp);
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 	resource_list_for_each_entry(entry, &bridge->dma_ranges) {
385*4882a593Smuzhiyun 		err = cdns_pcie_host_bar_config(rc, entry);
386*4882a593Smuzhiyun 		if (err) {
387*4882a593Smuzhiyun 			dev_err(dev, "Fail to configure IB using dma-ranges\n");
388*4882a593Smuzhiyun 			return err;
389*4882a593Smuzhiyun 		}
390*4882a593Smuzhiyun 	}
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	return 0;
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun 
cdns_pcie_host_init_address_translation(struct cdns_pcie_rc * rc)395*4882a593Smuzhiyun static int cdns_pcie_host_init_address_translation(struct cdns_pcie_rc *rc)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun 	struct cdns_pcie *pcie = &rc->pcie;
398*4882a593Smuzhiyun 	struct pci_host_bridge *bridge = pci_host_bridge_from_priv(rc);
399*4882a593Smuzhiyun 	struct resource *cfg_res = rc->cfg_res;
400*4882a593Smuzhiyun 	struct resource_entry *entry;
401*4882a593Smuzhiyun 	u64 cpu_addr = cfg_res->start;
402*4882a593Smuzhiyun 	u32 addr0, addr1, desc1;
403*4882a593Smuzhiyun 	int r, busnr = 0;
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	entry = resource_list_first_type(&bridge->windows, IORESOURCE_BUS);
406*4882a593Smuzhiyun 	if (entry)
407*4882a593Smuzhiyun 		busnr = entry->res->start;
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 	/*
410*4882a593Smuzhiyun 	 * Reserve region 0 for PCI configure space accesses:
411*4882a593Smuzhiyun 	 * OB_REGION_PCI_ADDR0 and OB_REGION_DESC0 are updated dynamically by
412*4882a593Smuzhiyun 	 * cdns_pci_map_bus(), other region registers are set here once for all.
413*4882a593Smuzhiyun 	 */
414*4882a593Smuzhiyun 	addr1 = 0; /* Should be programmed to zero. */
415*4882a593Smuzhiyun 	desc1 = CDNS_PCIE_AT_OB_REGION_DESC1_BUS(busnr);
416*4882a593Smuzhiyun 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_PCI_ADDR1(0), addr1);
417*4882a593Smuzhiyun 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC1(0), desc1);
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	if (pcie->ops->cpu_addr_fixup)
420*4882a593Smuzhiyun 		cpu_addr = pcie->ops->cpu_addr_fixup(pcie, cpu_addr);
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 	addr0 = CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS(12) |
423*4882a593Smuzhiyun 		(lower_32_bits(cpu_addr) & GENMASK(31, 8));
424*4882a593Smuzhiyun 	addr1 = upper_32_bits(cpu_addr);
425*4882a593Smuzhiyun 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(0), addr0);
426*4882a593Smuzhiyun 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(0), addr1);
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	r = 1;
429*4882a593Smuzhiyun 	resource_list_for_each_entry(entry, &bridge->windows) {
430*4882a593Smuzhiyun 		struct resource *res = entry->res;
431*4882a593Smuzhiyun 		u64 pci_addr = res->start - entry->offset;
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 		if (resource_type(res) == IORESOURCE_IO)
434*4882a593Smuzhiyun 			cdns_pcie_set_outbound_region(pcie, busnr, 0, r,
435*4882a593Smuzhiyun 						      true,
436*4882a593Smuzhiyun 						      pci_pio_to_address(res->start),
437*4882a593Smuzhiyun 						      pci_addr,
438*4882a593Smuzhiyun 						      resource_size(res));
439*4882a593Smuzhiyun 		else
440*4882a593Smuzhiyun 			cdns_pcie_set_outbound_region(pcie, busnr, 0, r,
441*4882a593Smuzhiyun 						      false,
442*4882a593Smuzhiyun 						      res->start,
443*4882a593Smuzhiyun 						      pci_addr,
444*4882a593Smuzhiyun 						      resource_size(res));
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 		r++;
447*4882a593Smuzhiyun 	}
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 	return cdns_pcie_host_map_dma_ranges(rc);
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun 
cdns_pcie_host_init(struct device * dev,struct cdns_pcie_rc * rc)452*4882a593Smuzhiyun static int cdns_pcie_host_init(struct device *dev,
453*4882a593Smuzhiyun 			       struct cdns_pcie_rc *rc)
454*4882a593Smuzhiyun {
455*4882a593Smuzhiyun 	int err;
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun 	err = cdns_pcie_host_init_root_port(rc);
458*4882a593Smuzhiyun 	if (err)
459*4882a593Smuzhiyun 		return err;
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 	return cdns_pcie_host_init_address_translation(rc);
462*4882a593Smuzhiyun }
463*4882a593Smuzhiyun 
cdns_pcie_host_setup(struct cdns_pcie_rc * rc)464*4882a593Smuzhiyun int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
465*4882a593Smuzhiyun {
466*4882a593Smuzhiyun 	struct device *dev = rc->pcie.dev;
467*4882a593Smuzhiyun 	struct platform_device *pdev = to_platform_device(dev);
468*4882a593Smuzhiyun 	struct device_node *np = dev->of_node;
469*4882a593Smuzhiyun 	struct pci_host_bridge *bridge;
470*4882a593Smuzhiyun 	enum cdns_pcie_rp_bar bar;
471*4882a593Smuzhiyun 	struct cdns_pcie *pcie;
472*4882a593Smuzhiyun 	struct resource *res;
473*4882a593Smuzhiyun 	int ret;
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	bridge = pci_host_bridge_from_priv(rc);
476*4882a593Smuzhiyun 	if (!bridge)
477*4882a593Smuzhiyun 		return -ENOMEM;
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 	pcie = &rc->pcie;
480*4882a593Smuzhiyun 	pcie->is_rc = true;
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 	rc->vendor_id = 0xffff;
483*4882a593Smuzhiyun 	of_property_read_u32(np, "vendor-id", &rc->vendor_id);
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 	rc->device_id = 0xffff;
486*4882a593Smuzhiyun 	of_property_read_u32(np, "device-id", &rc->device_id);
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	pcie->reg_base = devm_platform_ioremap_resource_byname(pdev, "reg");
489*4882a593Smuzhiyun 	if (IS_ERR(pcie->reg_base)) {
490*4882a593Smuzhiyun 		dev_err(dev, "missing \"reg\"\n");
491*4882a593Smuzhiyun 		return PTR_ERR(pcie->reg_base);
492*4882a593Smuzhiyun 	}
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
495*4882a593Smuzhiyun 	rc->cfg_base = devm_pci_remap_cfg_resource(dev, res);
496*4882a593Smuzhiyun 	if (IS_ERR(rc->cfg_base))
497*4882a593Smuzhiyun 		return PTR_ERR(rc->cfg_base);
498*4882a593Smuzhiyun 	rc->cfg_res = res;
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun 	if (rc->quirk_detect_quiet_flag)
501*4882a593Smuzhiyun 		cdns_pcie_detect_quiet_min_delay_set(&rc->pcie);
502*4882a593Smuzhiyun 
503*4882a593Smuzhiyun 	ret = cdns_pcie_start_link(pcie);
504*4882a593Smuzhiyun 	if (ret) {
505*4882a593Smuzhiyun 		dev_err(dev, "Failed to start link\n");
506*4882a593Smuzhiyun 		return ret;
507*4882a593Smuzhiyun 	}
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun 	ret = cdns_pcie_host_start_link(rc);
510*4882a593Smuzhiyun 	if (ret)
511*4882a593Smuzhiyun 		dev_dbg(dev, "PCIe link never came up\n");
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun 	for (bar = RP_BAR0; bar <= RP_NO_BAR; bar++)
514*4882a593Smuzhiyun 		rc->avail_ib_bar[bar] = true;
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	ret = cdns_pcie_host_init(dev, rc);
517*4882a593Smuzhiyun 	if (ret)
518*4882a593Smuzhiyun 		return ret;
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun 	if (!bridge->ops)
521*4882a593Smuzhiyun 		bridge->ops = &cdns_pcie_host_ops;
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 	ret = pci_host_probe(bridge);
524*4882a593Smuzhiyun 	if (ret < 0)
525*4882a593Smuzhiyun 		goto err_init;
526*4882a593Smuzhiyun 
527*4882a593Smuzhiyun 	return 0;
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun  err_init:
530*4882a593Smuzhiyun 	pm_runtime_put_sync(dev);
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 	return ret;
533*4882a593Smuzhiyun }
534