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