1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Synopsys DesignWare PCIe Endpoint controller driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2017 Texas Instruments
6*4882a593Smuzhiyun * Author: Kishon Vijay Abraham I <kishon@ti.com>
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <linux/of.h>
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include "pcie-designware.h"
12*4882a593Smuzhiyun #include <linux/pci-epc.h>
13*4882a593Smuzhiyun #include <linux/pci-epf.h>
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #include "../../pci.h"
16*4882a593Smuzhiyun
dw_pcie_ep_linkup(struct dw_pcie_ep * ep)17*4882a593Smuzhiyun void dw_pcie_ep_linkup(struct dw_pcie_ep *ep)
18*4882a593Smuzhiyun {
19*4882a593Smuzhiyun struct pci_epc *epc = ep->epc;
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun pci_epc_linkup(epc);
22*4882a593Smuzhiyun }
23*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(dw_pcie_ep_linkup);
24*4882a593Smuzhiyun
dw_pcie_ep_init_notify(struct dw_pcie_ep * ep)25*4882a593Smuzhiyun void dw_pcie_ep_init_notify(struct dw_pcie_ep *ep)
26*4882a593Smuzhiyun {
27*4882a593Smuzhiyun struct pci_epc *epc = ep->epc;
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun pci_epc_init_notify(epc);
30*4882a593Smuzhiyun }
31*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(dw_pcie_ep_init_notify);
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun struct dw_pcie_ep_func *
dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep * ep,u8 func_no)34*4882a593Smuzhiyun dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep *ep, u8 func_no)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun struct dw_pcie_ep_func *ep_func;
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun list_for_each_entry(ep_func, &ep->func_list, list) {
39*4882a593Smuzhiyun if (ep_func->func_no == func_no)
40*4882a593Smuzhiyun return ep_func;
41*4882a593Smuzhiyun }
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun return NULL;
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun
dw_pcie_ep_func_select(struct dw_pcie_ep * ep,u8 func_no)46*4882a593Smuzhiyun static unsigned int dw_pcie_ep_func_select(struct dw_pcie_ep *ep, u8 func_no)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun unsigned int func_offset = 0;
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun if (ep->ops->func_conf_select)
51*4882a593Smuzhiyun func_offset = ep->ops->func_conf_select(ep, func_no);
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun return func_offset;
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun
__dw_pcie_ep_reset_bar(struct dw_pcie * pci,u8 func_no,enum pci_barno bar,int flags)56*4882a593Smuzhiyun static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, u8 func_no,
57*4882a593Smuzhiyun enum pci_barno bar, int flags)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun u32 reg;
60*4882a593Smuzhiyun unsigned int func_offset = 0;
61*4882a593Smuzhiyun struct dw_pcie_ep *ep = &pci->ep;
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun func_offset = dw_pcie_ep_func_select(ep, func_no);
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun reg = func_offset + PCI_BASE_ADDRESS_0 + (4 * bar);
66*4882a593Smuzhiyun dw_pcie_dbi_ro_wr_en(pci);
67*4882a593Smuzhiyun dw_pcie_writel_dbi2(pci, reg, 0x0);
68*4882a593Smuzhiyun dw_pcie_writel_dbi(pci, reg, 0x0);
69*4882a593Smuzhiyun if (flags & PCI_BASE_ADDRESS_MEM_TYPE_64) {
70*4882a593Smuzhiyun dw_pcie_writel_dbi2(pci, reg + 4, 0x0);
71*4882a593Smuzhiyun dw_pcie_writel_dbi(pci, reg + 4, 0x0);
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun dw_pcie_dbi_ro_wr_dis(pci);
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
dw_pcie_ep_reset_bar(struct dw_pcie * pci,enum pci_barno bar)76*4882a593Smuzhiyun void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun u8 func_no, funcs;
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun funcs = pci->ep.epc->max_functions;
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun for (func_no = 0; func_no < funcs; func_no++)
83*4882a593Smuzhiyun __dw_pcie_ep_reset_bar(pci, func_no, bar, 0);
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun
__dw_pcie_ep_find_next_cap(struct dw_pcie_ep * ep,u8 func_no,u8 cap_ptr,u8 cap)86*4882a593Smuzhiyun static u8 __dw_pcie_ep_find_next_cap(struct dw_pcie_ep *ep, u8 func_no,
87*4882a593Smuzhiyun u8 cap_ptr, u8 cap)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
90*4882a593Smuzhiyun unsigned int func_offset = 0;
91*4882a593Smuzhiyun u8 cap_id, next_cap_ptr;
92*4882a593Smuzhiyun u16 reg;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun if (!cap_ptr)
95*4882a593Smuzhiyun return 0;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun func_offset = dw_pcie_ep_func_select(ep, func_no);
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun reg = dw_pcie_readw_dbi(pci, func_offset + cap_ptr);
100*4882a593Smuzhiyun cap_id = (reg & 0x00ff);
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun if (cap_id > PCI_CAP_ID_MAX)
103*4882a593Smuzhiyun return 0;
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun if (cap_id == cap)
106*4882a593Smuzhiyun return cap_ptr;
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun next_cap_ptr = (reg & 0xff00) >> 8;
109*4882a593Smuzhiyun return __dw_pcie_ep_find_next_cap(ep, func_no, next_cap_ptr, cap);
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun
dw_pcie_ep_find_capability(struct dw_pcie_ep * ep,u8 func_no,u8 cap)112*4882a593Smuzhiyun static u8 dw_pcie_ep_find_capability(struct dw_pcie_ep *ep, u8 func_no, u8 cap)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
115*4882a593Smuzhiyun unsigned int func_offset = 0;
116*4882a593Smuzhiyun u8 next_cap_ptr;
117*4882a593Smuzhiyun u16 reg;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun func_offset = dw_pcie_ep_func_select(ep, func_no);
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun reg = dw_pcie_readw_dbi(pci, func_offset + PCI_CAPABILITY_LIST);
122*4882a593Smuzhiyun next_cap_ptr = (reg & 0x00ff);
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun return __dw_pcie_ep_find_next_cap(ep, func_no, next_cap_ptr, cap);
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(dw_pcie_ep_reset_bar);
127*4882a593Smuzhiyun
dw_pcie_ep_write_header(struct pci_epc * epc,u8 func_no,struct pci_epf_header * hdr)128*4882a593Smuzhiyun static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no,
129*4882a593Smuzhiyun struct pci_epf_header *hdr)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun struct dw_pcie_ep *ep = epc_get_drvdata(epc);
132*4882a593Smuzhiyun struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
133*4882a593Smuzhiyun unsigned int func_offset = 0;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun func_offset = dw_pcie_ep_func_select(ep, func_no);
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun dw_pcie_dbi_ro_wr_en(pci);
138*4882a593Smuzhiyun dw_pcie_writew_dbi(pci, func_offset + PCI_VENDOR_ID, hdr->vendorid);
139*4882a593Smuzhiyun dw_pcie_writew_dbi(pci, func_offset + PCI_DEVICE_ID, hdr->deviceid);
140*4882a593Smuzhiyun dw_pcie_writeb_dbi(pci, func_offset + PCI_REVISION_ID, hdr->revid);
141*4882a593Smuzhiyun dw_pcie_writeb_dbi(pci, func_offset + PCI_CLASS_PROG, hdr->progif_code);
142*4882a593Smuzhiyun dw_pcie_writew_dbi(pci, func_offset + PCI_CLASS_DEVICE,
143*4882a593Smuzhiyun hdr->subclass_code | hdr->baseclass_code << 8);
144*4882a593Smuzhiyun dw_pcie_writeb_dbi(pci, func_offset + PCI_CACHE_LINE_SIZE,
145*4882a593Smuzhiyun hdr->cache_line_size);
146*4882a593Smuzhiyun dw_pcie_writew_dbi(pci, func_offset + PCI_SUBSYSTEM_VENDOR_ID,
147*4882a593Smuzhiyun hdr->subsys_vendor_id);
148*4882a593Smuzhiyun dw_pcie_writew_dbi(pci, func_offset + PCI_SUBSYSTEM_ID, hdr->subsys_id);
149*4882a593Smuzhiyun dw_pcie_writeb_dbi(pci, func_offset + PCI_INTERRUPT_PIN,
150*4882a593Smuzhiyun hdr->interrupt_pin);
151*4882a593Smuzhiyun dw_pcie_dbi_ro_wr_dis(pci);
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun return 0;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun
dw_pcie_ep_inbound_atu(struct dw_pcie_ep * ep,u8 func_no,enum pci_barno bar,dma_addr_t cpu_addr,enum dw_pcie_as_type as_type)156*4882a593Smuzhiyun static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no,
157*4882a593Smuzhiyun enum pci_barno bar, dma_addr_t cpu_addr,
158*4882a593Smuzhiyun enum dw_pcie_as_type as_type)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun int ret;
161*4882a593Smuzhiyun u32 free_win;
162*4882a593Smuzhiyun struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun free_win = find_first_zero_bit(ep->ib_window_map, ep->num_ib_windows);
165*4882a593Smuzhiyun if (free_win >= ep->num_ib_windows) {
166*4882a593Smuzhiyun dev_err(pci->dev, "No free inbound window\n");
167*4882a593Smuzhiyun return -EINVAL;
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun ret = dw_pcie_prog_inbound_atu(pci, func_no, free_win, bar, cpu_addr,
171*4882a593Smuzhiyun as_type);
172*4882a593Smuzhiyun if (ret < 0) {
173*4882a593Smuzhiyun dev_err(pci->dev, "Failed to program IB window\n");
174*4882a593Smuzhiyun return ret;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun ep->bar_to_atu[bar] = free_win;
178*4882a593Smuzhiyun set_bit(free_win, ep->ib_window_map);
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun return 0;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun
dw_pcie_ep_outbound_atu(struct dw_pcie_ep * ep,u8 func_no,phys_addr_t phys_addr,u64 pci_addr,size_t size)183*4882a593Smuzhiyun static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, u8 func_no,
184*4882a593Smuzhiyun phys_addr_t phys_addr,
185*4882a593Smuzhiyun u64 pci_addr, size_t size)
186*4882a593Smuzhiyun {
187*4882a593Smuzhiyun u32 free_win;
188*4882a593Smuzhiyun struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun free_win = find_first_zero_bit(ep->ob_window_map, ep->num_ob_windows);
191*4882a593Smuzhiyun if (free_win >= ep->num_ob_windows) {
192*4882a593Smuzhiyun dev_err(pci->dev, "No free outbound window\n");
193*4882a593Smuzhiyun return -EINVAL;
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun dw_pcie_prog_ep_outbound_atu(pci, func_no, free_win, PCIE_ATU_TYPE_MEM,
197*4882a593Smuzhiyun phys_addr, pci_addr, size);
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun set_bit(free_win, ep->ob_window_map);
200*4882a593Smuzhiyun ep->outbound_addr[free_win] = phys_addr;
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun return 0;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun
dw_pcie_ep_clear_bar(struct pci_epc * epc,u8 func_no,struct pci_epf_bar * epf_bar)205*4882a593Smuzhiyun static void dw_pcie_ep_clear_bar(struct pci_epc *epc, u8 func_no,
206*4882a593Smuzhiyun struct pci_epf_bar *epf_bar)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun struct dw_pcie_ep *ep = epc_get_drvdata(epc);
209*4882a593Smuzhiyun struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
210*4882a593Smuzhiyun enum pci_barno bar = epf_bar->barno;
211*4882a593Smuzhiyun u32 atu_index = ep->bar_to_atu[bar];
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun __dw_pcie_ep_reset_bar(pci, func_no, bar, epf_bar->flags);
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun dw_pcie_disable_atu(pci, atu_index, DW_PCIE_REGION_INBOUND);
216*4882a593Smuzhiyun clear_bit(atu_index, ep->ib_window_map);
217*4882a593Smuzhiyun ep->epf_bar[bar] = NULL;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
dw_pcie_ep_set_bar(struct pci_epc * epc,u8 func_no,struct pci_epf_bar * epf_bar)220*4882a593Smuzhiyun static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no,
221*4882a593Smuzhiyun struct pci_epf_bar *epf_bar)
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun int ret;
224*4882a593Smuzhiyun struct dw_pcie_ep *ep = epc_get_drvdata(epc);
225*4882a593Smuzhiyun struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
226*4882a593Smuzhiyun enum pci_barno bar = epf_bar->barno;
227*4882a593Smuzhiyun size_t size = epf_bar->size;
228*4882a593Smuzhiyun int flags = epf_bar->flags;
229*4882a593Smuzhiyun enum dw_pcie_as_type as_type;
230*4882a593Smuzhiyun u32 reg;
231*4882a593Smuzhiyun unsigned int func_offset = 0;
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun func_offset = dw_pcie_ep_func_select(ep, func_no);
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun reg = PCI_BASE_ADDRESS_0 + (4 * bar) + func_offset;
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun if (!(flags & PCI_BASE_ADDRESS_SPACE))
238*4882a593Smuzhiyun as_type = DW_PCIE_AS_MEM;
239*4882a593Smuzhiyun else
240*4882a593Smuzhiyun as_type = DW_PCIE_AS_IO;
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun ret = dw_pcie_ep_inbound_atu(ep, func_no, bar,
243*4882a593Smuzhiyun epf_bar->phys_addr, as_type);
244*4882a593Smuzhiyun if (ret)
245*4882a593Smuzhiyun return ret;
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun dw_pcie_dbi_ro_wr_en(pci);
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun dw_pcie_writel_dbi2(pci, reg, lower_32_bits(size - 1));
250*4882a593Smuzhiyun dw_pcie_writel_dbi(pci, reg, flags);
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun if (flags & PCI_BASE_ADDRESS_MEM_TYPE_64) {
253*4882a593Smuzhiyun dw_pcie_writel_dbi2(pci, reg + 4, upper_32_bits(size - 1));
254*4882a593Smuzhiyun dw_pcie_writel_dbi(pci, reg + 4, 0);
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun ep->epf_bar[bar] = epf_bar;
258*4882a593Smuzhiyun dw_pcie_dbi_ro_wr_dis(pci);
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun return 0;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun
dw_pcie_find_index(struct dw_pcie_ep * ep,phys_addr_t addr,u32 * atu_index)263*4882a593Smuzhiyun static int dw_pcie_find_index(struct dw_pcie_ep *ep, phys_addr_t addr,
264*4882a593Smuzhiyun u32 *atu_index)
265*4882a593Smuzhiyun {
266*4882a593Smuzhiyun u32 index;
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun for (index = 0; index < ep->num_ob_windows; index++) {
269*4882a593Smuzhiyun if (ep->outbound_addr[index] != addr)
270*4882a593Smuzhiyun continue;
271*4882a593Smuzhiyun *atu_index = index;
272*4882a593Smuzhiyun return 0;
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun return -EINVAL;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
dw_pcie_ep_unmap_addr(struct pci_epc * epc,u8 func_no,phys_addr_t addr)278*4882a593Smuzhiyun static void dw_pcie_ep_unmap_addr(struct pci_epc *epc, u8 func_no,
279*4882a593Smuzhiyun phys_addr_t addr)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun int ret;
282*4882a593Smuzhiyun u32 atu_index;
283*4882a593Smuzhiyun struct dw_pcie_ep *ep = epc_get_drvdata(epc);
284*4882a593Smuzhiyun struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun ret = dw_pcie_find_index(ep, addr, &atu_index);
287*4882a593Smuzhiyun if (ret < 0)
288*4882a593Smuzhiyun return;
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun dw_pcie_disable_atu(pci, atu_index, DW_PCIE_REGION_OUTBOUND);
291*4882a593Smuzhiyun clear_bit(atu_index, ep->ob_window_map);
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun
dw_pcie_ep_map_addr(struct pci_epc * epc,u8 func_no,phys_addr_t addr,u64 pci_addr,size_t size)294*4882a593Smuzhiyun static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no,
295*4882a593Smuzhiyun phys_addr_t addr,
296*4882a593Smuzhiyun u64 pci_addr, size_t size)
297*4882a593Smuzhiyun {
298*4882a593Smuzhiyun int ret;
299*4882a593Smuzhiyun struct dw_pcie_ep *ep = epc_get_drvdata(epc);
300*4882a593Smuzhiyun struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun ret = dw_pcie_ep_outbound_atu(ep, func_no, addr, pci_addr, size);
303*4882a593Smuzhiyun if (ret) {
304*4882a593Smuzhiyun dev_err(pci->dev, "Failed to enable address\n");
305*4882a593Smuzhiyun return ret;
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun return 0;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun
dw_pcie_ep_get_msi(struct pci_epc * epc,u8 func_no)311*4882a593Smuzhiyun static int dw_pcie_ep_get_msi(struct pci_epc *epc, u8 func_no)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun struct dw_pcie_ep *ep = epc_get_drvdata(epc);
314*4882a593Smuzhiyun struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
315*4882a593Smuzhiyun u32 val, reg;
316*4882a593Smuzhiyun unsigned int func_offset = 0;
317*4882a593Smuzhiyun struct dw_pcie_ep_func *ep_func;
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
320*4882a593Smuzhiyun if (!ep_func || !ep_func->msi_cap)
321*4882a593Smuzhiyun return -EINVAL;
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun func_offset = dw_pcie_ep_func_select(ep, func_no);
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun reg = ep_func->msi_cap + func_offset + PCI_MSI_FLAGS;
326*4882a593Smuzhiyun val = dw_pcie_readw_dbi(pci, reg);
327*4882a593Smuzhiyun if (!(val & PCI_MSI_FLAGS_ENABLE))
328*4882a593Smuzhiyun return -EINVAL;
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun val = (val & PCI_MSI_FLAGS_QSIZE) >> 4;
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun return val;
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun
dw_pcie_ep_set_msi(struct pci_epc * epc,u8 func_no,u8 interrupts)335*4882a593Smuzhiyun static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts)
336*4882a593Smuzhiyun {
337*4882a593Smuzhiyun struct dw_pcie_ep *ep = epc_get_drvdata(epc);
338*4882a593Smuzhiyun struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
339*4882a593Smuzhiyun u32 val, reg;
340*4882a593Smuzhiyun unsigned int func_offset = 0;
341*4882a593Smuzhiyun struct dw_pcie_ep_func *ep_func;
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
344*4882a593Smuzhiyun if (!ep_func || !ep_func->msi_cap)
345*4882a593Smuzhiyun return -EINVAL;
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun func_offset = dw_pcie_ep_func_select(ep, func_no);
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun reg = ep_func->msi_cap + func_offset + PCI_MSI_FLAGS;
350*4882a593Smuzhiyun val = dw_pcie_readw_dbi(pci, reg);
351*4882a593Smuzhiyun val &= ~PCI_MSI_FLAGS_QMASK;
352*4882a593Smuzhiyun val |= (interrupts << 1) & PCI_MSI_FLAGS_QMASK;
353*4882a593Smuzhiyun dw_pcie_dbi_ro_wr_en(pci);
354*4882a593Smuzhiyun dw_pcie_writew_dbi(pci, reg, val);
355*4882a593Smuzhiyun dw_pcie_dbi_ro_wr_dis(pci);
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun return 0;
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun
dw_pcie_ep_get_msix(struct pci_epc * epc,u8 func_no)360*4882a593Smuzhiyun static int dw_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun struct dw_pcie_ep *ep = epc_get_drvdata(epc);
363*4882a593Smuzhiyun struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
364*4882a593Smuzhiyun u32 val, reg;
365*4882a593Smuzhiyun unsigned int func_offset = 0;
366*4882a593Smuzhiyun struct dw_pcie_ep_func *ep_func;
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
369*4882a593Smuzhiyun if (!ep_func || !ep_func->msix_cap)
370*4882a593Smuzhiyun return -EINVAL;
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun func_offset = dw_pcie_ep_func_select(ep, func_no);
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun reg = ep_func->msix_cap + func_offset + PCI_MSIX_FLAGS;
375*4882a593Smuzhiyun val = dw_pcie_readw_dbi(pci, reg);
376*4882a593Smuzhiyun if (!(val & PCI_MSIX_FLAGS_ENABLE))
377*4882a593Smuzhiyun return -EINVAL;
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun val &= PCI_MSIX_FLAGS_QSIZE;
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun return val;
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun
dw_pcie_ep_set_msix(struct pci_epc * epc,u8 func_no,u16 interrupts,enum pci_barno bir,u32 offset)384*4882a593Smuzhiyun static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts,
385*4882a593Smuzhiyun enum pci_barno bir, u32 offset)
386*4882a593Smuzhiyun {
387*4882a593Smuzhiyun struct dw_pcie_ep *ep = epc_get_drvdata(epc);
388*4882a593Smuzhiyun struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
389*4882a593Smuzhiyun u32 val, reg;
390*4882a593Smuzhiyun unsigned int func_offset = 0;
391*4882a593Smuzhiyun struct dw_pcie_ep_func *ep_func;
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
394*4882a593Smuzhiyun if (!ep_func || !ep_func->msix_cap)
395*4882a593Smuzhiyun return -EINVAL;
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun dw_pcie_dbi_ro_wr_en(pci);
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun func_offset = dw_pcie_ep_func_select(ep, func_no);
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun reg = ep_func->msix_cap + func_offset + PCI_MSIX_FLAGS;
402*4882a593Smuzhiyun val = dw_pcie_readw_dbi(pci, reg);
403*4882a593Smuzhiyun val &= ~PCI_MSIX_FLAGS_QSIZE;
404*4882a593Smuzhiyun val |= interrupts;
405*4882a593Smuzhiyun dw_pcie_writew_dbi(pci, reg, val);
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun reg = ep_func->msix_cap + func_offset + PCI_MSIX_TABLE;
408*4882a593Smuzhiyun val = offset | bir;
409*4882a593Smuzhiyun dw_pcie_writel_dbi(pci, reg, val);
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun reg = ep_func->msix_cap + func_offset + PCI_MSIX_PBA;
412*4882a593Smuzhiyun val = (offset + (interrupts * PCI_MSIX_ENTRY_SIZE)) | bir;
413*4882a593Smuzhiyun dw_pcie_writel_dbi(pci, reg, val);
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun dw_pcie_dbi_ro_wr_dis(pci);
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun return 0;
418*4882a593Smuzhiyun }
419*4882a593Smuzhiyun
dw_pcie_ep_raise_irq(struct pci_epc * epc,u8 func_no,enum pci_epc_irq_type type,u16 interrupt_num)420*4882a593Smuzhiyun static int dw_pcie_ep_raise_irq(struct pci_epc *epc, u8 func_no,
421*4882a593Smuzhiyun enum pci_epc_irq_type type, u16 interrupt_num)
422*4882a593Smuzhiyun {
423*4882a593Smuzhiyun struct dw_pcie_ep *ep = epc_get_drvdata(epc);
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun if (!ep->ops->raise_irq)
426*4882a593Smuzhiyun return -EINVAL;
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun return ep->ops->raise_irq(ep, func_no, type, interrupt_num);
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun
dw_pcie_ep_stop(struct pci_epc * epc)431*4882a593Smuzhiyun static void dw_pcie_ep_stop(struct pci_epc *epc)
432*4882a593Smuzhiyun {
433*4882a593Smuzhiyun struct dw_pcie_ep *ep = epc_get_drvdata(epc);
434*4882a593Smuzhiyun struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun if (!pci->ops->stop_link)
437*4882a593Smuzhiyun return;
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun pci->ops->stop_link(pci);
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun
dw_pcie_ep_start(struct pci_epc * epc)442*4882a593Smuzhiyun static int dw_pcie_ep_start(struct pci_epc *epc)
443*4882a593Smuzhiyun {
444*4882a593Smuzhiyun struct dw_pcie_ep *ep = epc_get_drvdata(epc);
445*4882a593Smuzhiyun struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun if (!pci->ops->start_link)
448*4882a593Smuzhiyun return -EINVAL;
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun return pci->ops->start_link(pci);
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun static const struct pci_epc_features*
dw_pcie_ep_get_features(struct pci_epc * epc,u8 func_no)454*4882a593Smuzhiyun dw_pcie_ep_get_features(struct pci_epc *epc, u8 func_no)
455*4882a593Smuzhiyun {
456*4882a593Smuzhiyun struct dw_pcie_ep *ep = epc_get_drvdata(epc);
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun if (!ep->ops->get_features)
459*4882a593Smuzhiyun return NULL;
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun return ep->ops->get_features(ep);
462*4882a593Smuzhiyun }
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun static const struct pci_epc_ops epc_ops = {
465*4882a593Smuzhiyun .write_header = dw_pcie_ep_write_header,
466*4882a593Smuzhiyun .set_bar = dw_pcie_ep_set_bar,
467*4882a593Smuzhiyun .clear_bar = dw_pcie_ep_clear_bar,
468*4882a593Smuzhiyun .map_addr = dw_pcie_ep_map_addr,
469*4882a593Smuzhiyun .unmap_addr = dw_pcie_ep_unmap_addr,
470*4882a593Smuzhiyun .set_msi = dw_pcie_ep_set_msi,
471*4882a593Smuzhiyun .get_msi = dw_pcie_ep_get_msi,
472*4882a593Smuzhiyun .set_msix = dw_pcie_ep_set_msix,
473*4882a593Smuzhiyun .get_msix = dw_pcie_ep_get_msix,
474*4882a593Smuzhiyun .raise_irq = dw_pcie_ep_raise_irq,
475*4882a593Smuzhiyun .start = dw_pcie_ep_start,
476*4882a593Smuzhiyun .stop = dw_pcie_ep_stop,
477*4882a593Smuzhiyun .get_features = dw_pcie_ep_get_features,
478*4882a593Smuzhiyun };
479*4882a593Smuzhiyun
dw_pcie_ep_raise_legacy_irq(struct dw_pcie_ep * ep,u8 func_no)480*4882a593Smuzhiyun int dw_pcie_ep_raise_legacy_irq(struct dw_pcie_ep *ep, u8 func_no)
481*4882a593Smuzhiyun {
482*4882a593Smuzhiyun struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
483*4882a593Smuzhiyun struct device *dev = pci->dev;
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun dev_err(dev, "EP cannot trigger legacy IRQs\n");
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun return -EINVAL;
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(dw_pcie_ep_raise_legacy_irq);
490*4882a593Smuzhiyun
dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep * ep,u8 func_no,u8 interrupt_num)491*4882a593Smuzhiyun int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
492*4882a593Smuzhiyun u8 interrupt_num)
493*4882a593Smuzhiyun {
494*4882a593Smuzhiyun struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
495*4882a593Smuzhiyun struct dw_pcie_ep_func *ep_func;
496*4882a593Smuzhiyun struct pci_epc *epc = ep->epc;
497*4882a593Smuzhiyun unsigned int aligned_offset;
498*4882a593Smuzhiyun unsigned int func_offset = 0;
499*4882a593Smuzhiyun u16 msg_ctrl, msg_data;
500*4882a593Smuzhiyun u32 msg_addr_lower, msg_addr_upper, reg;
501*4882a593Smuzhiyun u64 msg_addr;
502*4882a593Smuzhiyun bool has_upper;
503*4882a593Smuzhiyun int ret;
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
506*4882a593Smuzhiyun if (!ep_func || !ep_func->msi_cap)
507*4882a593Smuzhiyun return -EINVAL;
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun func_offset = dw_pcie_ep_func_select(ep, func_no);
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun /* Raise MSI per the PCI Local Bus Specification Revision 3.0, 6.8.1. */
512*4882a593Smuzhiyun reg = ep_func->msi_cap + func_offset + PCI_MSI_FLAGS;
513*4882a593Smuzhiyun msg_ctrl = dw_pcie_readw_dbi(pci, reg);
514*4882a593Smuzhiyun has_upper = !!(msg_ctrl & PCI_MSI_FLAGS_64BIT);
515*4882a593Smuzhiyun reg = ep_func->msi_cap + func_offset + PCI_MSI_ADDRESS_LO;
516*4882a593Smuzhiyun msg_addr_lower = dw_pcie_readl_dbi(pci, reg);
517*4882a593Smuzhiyun if (has_upper) {
518*4882a593Smuzhiyun reg = ep_func->msi_cap + func_offset + PCI_MSI_ADDRESS_HI;
519*4882a593Smuzhiyun msg_addr_upper = dw_pcie_readl_dbi(pci, reg);
520*4882a593Smuzhiyun reg = ep_func->msi_cap + func_offset + PCI_MSI_DATA_64;
521*4882a593Smuzhiyun msg_data = dw_pcie_readw_dbi(pci, reg);
522*4882a593Smuzhiyun } else {
523*4882a593Smuzhiyun msg_addr_upper = 0;
524*4882a593Smuzhiyun reg = ep_func->msi_cap + func_offset + PCI_MSI_DATA_32;
525*4882a593Smuzhiyun msg_data = dw_pcie_readw_dbi(pci, reg);
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun aligned_offset = msg_addr_lower & (epc->mem->window.page_size - 1);
528*4882a593Smuzhiyun msg_addr = ((u64)msg_addr_upper) << 32 |
529*4882a593Smuzhiyun (msg_addr_lower & ~aligned_offset);
530*4882a593Smuzhiyun ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys, msg_addr,
531*4882a593Smuzhiyun epc->mem->window.page_size);
532*4882a593Smuzhiyun if (ret)
533*4882a593Smuzhiyun return ret;
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun writel(msg_data | (interrupt_num - 1), ep->msi_mem + aligned_offset);
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun dw_pcie_ep_unmap_addr(epc, func_no, ep->msi_mem_phys);
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun return 0;
540*4882a593Smuzhiyun }
541*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(dw_pcie_ep_raise_msi_irq);
542*4882a593Smuzhiyun
dw_pcie_ep_raise_msix_irq_doorbell(struct dw_pcie_ep * ep,u8 func_no,u16 interrupt_num)543*4882a593Smuzhiyun int dw_pcie_ep_raise_msix_irq_doorbell(struct dw_pcie_ep *ep, u8 func_no,
544*4882a593Smuzhiyun u16 interrupt_num)
545*4882a593Smuzhiyun {
546*4882a593Smuzhiyun struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
547*4882a593Smuzhiyun struct dw_pcie_ep_func *ep_func;
548*4882a593Smuzhiyun u32 msg_data;
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
551*4882a593Smuzhiyun if (!ep_func || !ep_func->msix_cap)
552*4882a593Smuzhiyun return -EINVAL;
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun msg_data = (func_no << PCIE_MSIX_DOORBELL_PF_SHIFT) |
555*4882a593Smuzhiyun (interrupt_num - 1);
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun dw_pcie_writel_dbi(pci, PCIE_MSIX_DOORBELL, msg_data);
558*4882a593Smuzhiyun
559*4882a593Smuzhiyun return 0;
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun
dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep * ep,u8 func_no,u16 interrupt_num)562*4882a593Smuzhiyun int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
563*4882a593Smuzhiyun u16 interrupt_num)
564*4882a593Smuzhiyun {
565*4882a593Smuzhiyun struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
566*4882a593Smuzhiyun struct dw_pcie_ep_func *ep_func;
567*4882a593Smuzhiyun struct pci_epf_msix_tbl *msix_tbl;
568*4882a593Smuzhiyun struct pci_epc *epc = ep->epc;
569*4882a593Smuzhiyun unsigned int func_offset = 0;
570*4882a593Smuzhiyun u32 reg, msg_data, vec_ctrl;
571*4882a593Smuzhiyun unsigned int aligned_offset;
572*4882a593Smuzhiyun u32 tbl_offset;
573*4882a593Smuzhiyun u64 msg_addr;
574*4882a593Smuzhiyun int ret;
575*4882a593Smuzhiyun u8 bir;
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
578*4882a593Smuzhiyun if (!ep_func || !ep_func->msix_cap)
579*4882a593Smuzhiyun return -EINVAL;
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun func_offset = dw_pcie_ep_func_select(ep, func_no);
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun reg = ep_func->msix_cap + func_offset + PCI_MSIX_TABLE;
584*4882a593Smuzhiyun tbl_offset = dw_pcie_readl_dbi(pci, reg);
585*4882a593Smuzhiyun bir = (tbl_offset & PCI_MSIX_TABLE_BIR);
586*4882a593Smuzhiyun tbl_offset &= PCI_MSIX_TABLE_OFFSET;
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun msix_tbl = ep->epf_bar[bir]->addr + tbl_offset;
589*4882a593Smuzhiyun msg_addr = msix_tbl[(interrupt_num - 1)].msg_addr;
590*4882a593Smuzhiyun msg_data = msix_tbl[(interrupt_num - 1)].msg_data;
591*4882a593Smuzhiyun vec_ctrl = msix_tbl[(interrupt_num - 1)].vector_ctrl;
592*4882a593Smuzhiyun
593*4882a593Smuzhiyun if (vec_ctrl & PCI_MSIX_ENTRY_CTRL_MASKBIT) {
594*4882a593Smuzhiyun dev_dbg(pci->dev, "MSI-X entry ctrl set\n");
595*4882a593Smuzhiyun return -EPERM;
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun aligned_offset = msg_addr & (epc->mem->window.page_size - 1);
599*4882a593Smuzhiyun ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys, msg_addr,
600*4882a593Smuzhiyun epc->mem->window.page_size);
601*4882a593Smuzhiyun if (ret)
602*4882a593Smuzhiyun return ret;
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun writel(msg_data, ep->msi_mem + aligned_offset);
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun dw_pcie_ep_unmap_addr(epc, func_no, ep->msi_mem_phys);
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun return 0;
609*4882a593Smuzhiyun }
610*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(dw_pcie_ep_raise_msix_irq);
611*4882a593Smuzhiyun
dw_pcie_ep_exit(struct dw_pcie_ep * ep)612*4882a593Smuzhiyun void dw_pcie_ep_exit(struct dw_pcie_ep *ep)
613*4882a593Smuzhiyun {
614*4882a593Smuzhiyun struct pci_epc *epc = ep->epc;
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun pci_epc_mem_free_addr(epc, ep->msi_mem_phys, ep->msi_mem,
617*4882a593Smuzhiyun epc->mem->window.page_size);
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun pci_epc_mem_exit(epc);
620*4882a593Smuzhiyun }
621*4882a593Smuzhiyun
dw_pcie_ep_find_ext_capability(struct dw_pcie * pci,int cap)622*4882a593Smuzhiyun static unsigned int dw_pcie_ep_find_ext_capability(struct dw_pcie *pci, int cap)
623*4882a593Smuzhiyun {
624*4882a593Smuzhiyun u32 header;
625*4882a593Smuzhiyun int pos = PCI_CFG_SPACE_SIZE;
626*4882a593Smuzhiyun
627*4882a593Smuzhiyun while (pos) {
628*4882a593Smuzhiyun header = dw_pcie_readl_dbi(pci, pos);
629*4882a593Smuzhiyun if (PCI_EXT_CAP_ID(header) == cap)
630*4882a593Smuzhiyun return pos;
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun pos = PCI_EXT_CAP_NEXT(header);
633*4882a593Smuzhiyun if (!pos)
634*4882a593Smuzhiyun break;
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun return 0;
638*4882a593Smuzhiyun }
639*4882a593Smuzhiyun
dw_pcie_ep_init_complete(struct dw_pcie_ep * ep)640*4882a593Smuzhiyun int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep)
641*4882a593Smuzhiyun {
642*4882a593Smuzhiyun struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
643*4882a593Smuzhiyun unsigned int offset;
644*4882a593Smuzhiyun unsigned int nbars;
645*4882a593Smuzhiyun u8 hdr_type;
646*4882a593Smuzhiyun u32 reg;
647*4882a593Smuzhiyun int i;
648*4882a593Smuzhiyun
649*4882a593Smuzhiyun hdr_type = dw_pcie_readb_dbi(pci, PCI_HEADER_TYPE) &
650*4882a593Smuzhiyun PCI_HEADER_TYPE_MASK;
651*4882a593Smuzhiyun if (hdr_type != PCI_HEADER_TYPE_NORMAL) {
652*4882a593Smuzhiyun dev_err(pci->dev,
653*4882a593Smuzhiyun "PCIe controller is not set to EP mode (hdr_type:0x%x)!\n",
654*4882a593Smuzhiyun hdr_type);
655*4882a593Smuzhiyun return -EIO;
656*4882a593Smuzhiyun }
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun offset = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR);
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun dw_pcie_dbi_ro_wr_en(pci);
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun if (offset) {
663*4882a593Smuzhiyun reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL);
664*4882a593Smuzhiyun nbars = (reg & PCI_REBAR_CTRL_NBAR_MASK) >>
665*4882a593Smuzhiyun PCI_REBAR_CTRL_NBAR_SHIFT;
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL)
668*4882a593Smuzhiyun dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, 0x0);
669*4882a593Smuzhiyun }
670*4882a593Smuzhiyun
671*4882a593Smuzhiyun dw_pcie_setup(pci);
672*4882a593Smuzhiyun dw_pcie_dbi_ro_wr_dis(pci);
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun return 0;
675*4882a593Smuzhiyun }
676*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(dw_pcie_ep_init_complete);
677*4882a593Smuzhiyun
dw_pcie_ep_init(struct dw_pcie_ep * ep)678*4882a593Smuzhiyun int dw_pcie_ep_init(struct dw_pcie_ep *ep)
679*4882a593Smuzhiyun {
680*4882a593Smuzhiyun int ret;
681*4882a593Smuzhiyun void *addr;
682*4882a593Smuzhiyun u8 func_no;
683*4882a593Smuzhiyun struct pci_epc *epc;
684*4882a593Smuzhiyun struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
685*4882a593Smuzhiyun struct device *dev = pci->dev;
686*4882a593Smuzhiyun struct device_node *np = dev->of_node;
687*4882a593Smuzhiyun const struct pci_epc_features *epc_features;
688*4882a593Smuzhiyun struct dw_pcie_ep_func *ep_func;
689*4882a593Smuzhiyun
690*4882a593Smuzhiyun INIT_LIST_HEAD(&ep->func_list);
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun if (!pci->dbi_base || !pci->dbi_base2) {
693*4882a593Smuzhiyun dev_err(dev, "dbi_base/dbi_base2 is not populated\n");
694*4882a593Smuzhiyun return -EINVAL;
695*4882a593Smuzhiyun }
696*4882a593Smuzhiyun
697*4882a593Smuzhiyun ret = of_property_read_u32(np, "num-ib-windows", &ep->num_ib_windows);
698*4882a593Smuzhiyun if (ret < 0) {
699*4882a593Smuzhiyun dev_err(dev, "Unable to read *num-ib-windows* property\n");
700*4882a593Smuzhiyun return ret;
701*4882a593Smuzhiyun }
702*4882a593Smuzhiyun if (ep->num_ib_windows > MAX_IATU_IN) {
703*4882a593Smuzhiyun dev_err(dev, "Invalid *num-ib-windows*\n");
704*4882a593Smuzhiyun return -EINVAL;
705*4882a593Smuzhiyun }
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun ret = of_property_read_u32(np, "num-ob-windows", &ep->num_ob_windows);
708*4882a593Smuzhiyun if (ret < 0) {
709*4882a593Smuzhiyun dev_err(dev, "Unable to read *num-ob-windows* property\n");
710*4882a593Smuzhiyun return ret;
711*4882a593Smuzhiyun }
712*4882a593Smuzhiyun if (ep->num_ob_windows > MAX_IATU_OUT) {
713*4882a593Smuzhiyun dev_err(dev, "Invalid *num-ob-windows*\n");
714*4882a593Smuzhiyun return -EINVAL;
715*4882a593Smuzhiyun }
716*4882a593Smuzhiyun
717*4882a593Smuzhiyun ep->ib_window_map = devm_kcalloc(dev,
718*4882a593Smuzhiyun BITS_TO_LONGS(ep->num_ib_windows),
719*4882a593Smuzhiyun sizeof(long),
720*4882a593Smuzhiyun GFP_KERNEL);
721*4882a593Smuzhiyun if (!ep->ib_window_map)
722*4882a593Smuzhiyun return -ENOMEM;
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun ep->ob_window_map = devm_kcalloc(dev,
725*4882a593Smuzhiyun BITS_TO_LONGS(ep->num_ob_windows),
726*4882a593Smuzhiyun sizeof(long),
727*4882a593Smuzhiyun GFP_KERNEL);
728*4882a593Smuzhiyun if (!ep->ob_window_map)
729*4882a593Smuzhiyun return -ENOMEM;
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun addr = devm_kcalloc(dev, ep->num_ob_windows, sizeof(phys_addr_t),
732*4882a593Smuzhiyun GFP_KERNEL);
733*4882a593Smuzhiyun if (!addr)
734*4882a593Smuzhiyun return -ENOMEM;
735*4882a593Smuzhiyun ep->outbound_addr = addr;
736*4882a593Smuzhiyun
737*4882a593Smuzhiyun if (pci->link_gen < 1)
738*4882a593Smuzhiyun pci->link_gen = of_pci_get_max_link_speed(np);
739*4882a593Smuzhiyun
740*4882a593Smuzhiyun epc = devm_pci_epc_create(dev, &epc_ops);
741*4882a593Smuzhiyun if (IS_ERR(epc)) {
742*4882a593Smuzhiyun dev_err(dev, "Failed to create epc device\n");
743*4882a593Smuzhiyun return PTR_ERR(epc);
744*4882a593Smuzhiyun }
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun ep->epc = epc;
747*4882a593Smuzhiyun epc_set_drvdata(epc, ep);
748*4882a593Smuzhiyun
749*4882a593Smuzhiyun ret = of_property_read_u8(np, "max-functions", &epc->max_functions);
750*4882a593Smuzhiyun if (ret < 0)
751*4882a593Smuzhiyun epc->max_functions = 1;
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun for (func_no = 0; func_no < epc->max_functions; func_no++) {
754*4882a593Smuzhiyun ep_func = devm_kzalloc(dev, sizeof(*ep_func), GFP_KERNEL);
755*4882a593Smuzhiyun if (!ep_func)
756*4882a593Smuzhiyun return -ENOMEM;
757*4882a593Smuzhiyun
758*4882a593Smuzhiyun ep_func->func_no = func_no;
759*4882a593Smuzhiyun ep_func->msi_cap = dw_pcie_ep_find_capability(ep, func_no,
760*4882a593Smuzhiyun PCI_CAP_ID_MSI);
761*4882a593Smuzhiyun ep_func->msix_cap = dw_pcie_ep_find_capability(ep, func_no,
762*4882a593Smuzhiyun PCI_CAP_ID_MSIX);
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun list_add_tail(&ep_func->list, &ep->func_list);
765*4882a593Smuzhiyun }
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun if (ep->ops->ep_init)
768*4882a593Smuzhiyun ep->ops->ep_init(ep);
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun ret = pci_epc_mem_init(epc, ep->phys_base, ep->addr_size,
771*4882a593Smuzhiyun ep->page_size);
772*4882a593Smuzhiyun if (ret < 0) {
773*4882a593Smuzhiyun dev_err(dev, "Failed to initialize address space\n");
774*4882a593Smuzhiyun return ret;
775*4882a593Smuzhiyun }
776*4882a593Smuzhiyun
777*4882a593Smuzhiyun ep->msi_mem = pci_epc_mem_alloc_addr(epc, &ep->msi_mem_phys,
778*4882a593Smuzhiyun epc->mem->window.page_size);
779*4882a593Smuzhiyun if (!ep->msi_mem) {
780*4882a593Smuzhiyun ret = -ENOMEM;
781*4882a593Smuzhiyun dev_err(dev, "Failed to reserve memory for MSI/MSI-X\n");
782*4882a593Smuzhiyun goto err_exit_epc_mem;
783*4882a593Smuzhiyun }
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun if (ep->ops->get_features) {
786*4882a593Smuzhiyun epc_features = ep->ops->get_features(ep);
787*4882a593Smuzhiyun if (epc_features->core_init_notifier)
788*4882a593Smuzhiyun return 0;
789*4882a593Smuzhiyun }
790*4882a593Smuzhiyun
791*4882a593Smuzhiyun ret = dw_pcie_ep_init_complete(ep);
792*4882a593Smuzhiyun if (ret)
793*4882a593Smuzhiyun goto err_free_epc_mem;
794*4882a593Smuzhiyun
795*4882a593Smuzhiyun return 0;
796*4882a593Smuzhiyun
797*4882a593Smuzhiyun err_free_epc_mem:
798*4882a593Smuzhiyun pci_epc_mem_free_addr(epc, ep->msi_mem_phys, ep->msi_mem,
799*4882a593Smuzhiyun epc->mem->window.page_size);
800*4882a593Smuzhiyun
801*4882a593Smuzhiyun err_exit_epc_mem:
802*4882a593Smuzhiyun pci_epc_mem_exit(epc);
803*4882a593Smuzhiyun
804*4882a593Smuzhiyun return ret;
805*4882a593Smuzhiyun }
806*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(dw_pcie_ep_init);
807