1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2023-09-23     GuEe-GUI     first version
9  */
10 
11 #define DBG_TAG "pcie.dw-ep"
12 #define DBG_LVL DBG_INFO
13 #include <rtdbg.h>
14 
15 #include "pcie-dw.h"
16 
dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep * ep,rt_uint8_t func_no)17 struct dw_pcie_ep_func *dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep *ep, rt_uint8_t func_no)
18 {
19     struct dw_pcie_ep_func *ep_func;
20 
21     rt_list_for_each_entry(ep_func, &ep->func_nodes, list)
22     {
23         if (ep_func->func_no == func_no)
24         {
25             return ep_func;
26         }
27     }
28 
29     return RT_NULL;
30 }
31 
dw_pcie_ep_func_select(struct dw_pcie_ep * ep,rt_uint8_t func_no)32 static rt_uint8_t dw_pcie_ep_func_select(struct dw_pcie_ep *ep, rt_uint8_t func_no)
33 {
34     rt_uint8_t func_offset = 0;
35 
36     if (ep->ops->func_select)
37     {
38         func_offset = ep->ops->func_select(ep, func_no);
39     }
40 
41     return func_offset;
42 }
43 
__dw_pcie_ep_reset_bar(struct dw_pcie * pci,rt_uint8_t func_no,int bar_idx,int flags)44 static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, rt_uint8_t func_no,
45         int bar_idx, int flags)
46 {
47     rt_uint32_t reg;
48     rt_uint8_t func_offset = 0;
49     struct dw_pcie_ep *ep = &pci->endpoint;
50 
51     func_offset = dw_pcie_ep_func_select(ep, func_no);
52     reg = func_offset + PCIR_BAR(bar_idx);
53 
54     dw_pcie_dbi_ro_writable_enable(pci, RT_TRUE);
55 
56     dw_pcie_writel_dbi2(pci, reg, 0x0);
57     dw_pcie_writel_dbi(pci, reg, 0x0);
58 
59     if (flags & PCIM_BAR_MEM_TYPE_64)
60     {
61         dw_pcie_writel_dbi2(pci, reg + 4, 0x0);
62         dw_pcie_writel_dbi(pci, reg + 4, 0x0);
63     }
64 
65     dw_pcie_dbi_ro_writable_enable(pci, RT_FALSE);
66 }
67 
dw_pcie_ep_reset_bar(struct dw_pcie * pci,int bar_idx)68 void dw_pcie_ep_reset_bar(struct dw_pcie *pci, int bar_idx)
69 {
70     rt_uint8_t func_no, funcs = pci->endpoint.epc->max_functions;
71 
72     for (func_no = 0; func_no < funcs; ++func_no)
73     {
74         __dw_pcie_ep_reset_bar(pci, func_no, bar_idx, 0);
75     }
76 }
77 
__dw_pcie_ep_find_next_cap(struct dw_pcie_ep * ep,rt_uint8_t func_no,rt_uint8_t cap_ptr,rt_uint8_t cap)78 static rt_uint8_t __dw_pcie_ep_find_next_cap(struct dw_pcie_ep *ep, rt_uint8_t func_no,
79         rt_uint8_t cap_ptr, rt_uint8_t cap)
80 {
81     rt_uint16_t reg;
82     rt_uint8_t func_offset = 0, cap_id, next_cap_ptr;
83     struct dw_pcie *pci = to_dw_pcie_from_endpoint(ep);
84 
85     if (!cap_ptr)
86     {
87         return 0;
88     }
89 
90     func_offset = dw_pcie_ep_func_select(ep, func_no);
91     reg = dw_pcie_readw_dbi(pci, func_offset + cap_ptr);
92     cap_id = (reg & 0x00ff);
93 
94     if (cap_id > PCIY_MAX)
95     {
96         return 0;
97     }
98 
99     if (cap_id == cap)
100     {
101         return cap_ptr;
102     }
103 
104     next_cap_ptr = (reg & 0xff00) >> 8;
105     return __dw_pcie_ep_find_next_cap(ep, func_no, next_cap_ptr, cap);
106 }
107 
dw_pcie_ep_find_capability(struct dw_pcie_ep * ep,rt_uint8_t func_no,rt_uint8_t cap)108 static rt_uint8_t dw_pcie_ep_find_capability(struct dw_pcie_ep *ep, rt_uint8_t func_no,
109         rt_uint8_t cap)
110 {
111     rt_uint16_t reg;
112     rt_uint8_t func_offset = 0, next_cap_ptr;
113     struct dw_pcie *pci = to_dw_pcie_from_endpoint(ep);
114 
115     func_offset = dw_pcie_ep_func_select(ep, func_no);
116     reg = dw_pcie_readw_dbi(pci, func_offset + PCIR_CAP_PTR);
117     next_cap_ptr = reg & 0x00ff;
118 
119     return __dw_pcie_ep_find_next_cap(ep, func_no, next_cap_ptr, cap);
120 }
121 
dw_pcie_ep_inbound_atu(struct dw_pcie_ep * ep,rt_uint8_t func_no,int bar_idx,rt_ubase_t cpu_addr,enum dw_pcie_aspace_type aspace_type)122 rt_err_t dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, rt_uint8_t func_no,
123         int bar_idx, rt_ubase_t cpu_addr, enum dw_pcie_aspace_type aspace_type)
124 {
125     rt_err_t err;
126     rt_uint32_t free_win;
127     struct dw_pcie *pci = to_dw_pcie_from_endpoint(ep);
128 
129     free_win = rt_bitmap_next_clear_bit(ep->ib_window_map, 0, ep->num_ib_windows);
130     if (free_win >= ep->num_ib_windows)
131     {
132         LOG_E("No free inbound window");
133         return -RT_EEMPTY;
134     }
135 
136     err = dw_pcie_prog_inbound_atu(pci, func_no, free_win, bar_idx, cpu_addr, aspace_type);
137     if (err)
138     {
139         LOG_E("Failed to program IB window error = %s", rt_strerror(err));
140         return err;
141     }
142 
143     ep->bar_to_atu[bar_idx] = free_win;
144     rt_bitmap_set_bit(ep->ib_window_map, free_win);
145 
146     return RT_EOK;
147 }
148 
dw_pcie_ep_outbound_atu(struct dw_pcie_ep * ep,rt_uint8_t func_no,rt_ubase_t phys_addr,rt_uint64_t pci_addr,rt_size_t size)149 rt_err_t dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, rt_uint8_t func_no,
150         rt_ubase_t phys_addr, rt_uint64_t pci_addr, rt_size_t size)
151 {
152     rt_uint32_t free_win;
153     struct dw_pcie *pci = to_dw_pcie_from_endpoint(ep);
154 
155     free_win = rt_bitmap_next_clear_bit(ep->ob_window_map, 0, ep->num_ob_windows);
156     if (free_win >= ep->num_ob_windows)
157     {
158         LOG_E("No free outbound window");
159         return -RT_EEMPTY;
160     }
161 
162     dw_pcie_prog_ep_outbound_atu(pci, func_no, free_win, PCIE_ATU_TYPE_MEM,
163             phys_addr, pci_addr, size);
164 
165     ep->outbound_addr[free_win] = phys_addr;
166     rt_bitmap_set_bit(ep->ob_window_map, free_win);
167 
168     return RT_EOK;
169 }
170 
dw_pcie_ep_write_header(struct rt_pci_ep * epc,rt_uint8_t func_no,struct rt_pci_ep_header * hdr)171 static rt_err_t dw_pcie_ep_write_header(struct rt_pci_ep *epc, rt_uint8_t func_no,
172         struct rt_pci_ep_header *hdr)
173 {
174     rt_uint8_t func_offset = 0;
175     struct dw_pcie_ep *ep = epc->priv;
176     struct dw_pcie *pci = to_dw_pcie_from_endpoint(ep);
177 
178     func_offset = dw_pcie_ep_func_select(ep, func_no);
179 
180     dw_pcie_dbi_ro_writable_enable(pci, RT_TRUE);
181 
182     dw_pcie_writew_dbi(pci, func_offset + PCIR_VENDOR, hdr->vendor);
183     dw_pcie_writew_dbi(pci, func_offset + PCIR_DEVICE, hdr->device);
184     dw_pcie_writeb_dbi(pci, func_offset + PCIR_REVID, hdr->revision);
185     dw_pcie_writeb_dbi(pci, func_offset + PCIR_PROGIF, hdr->progif);
186     dw_pcie_writew_dbi(pci, func_offset + PCIR_SUBCLASS, hdr->subclass | hdr->class_code << 8);
187     dw_pcie_writeb_dbi(pci, func_offset + PCIR_CACHELNSZ, hdr->cache_line_size);
188     dw_pcie_writew_dbi(pci, func_offset + PCIR_SUBVEND_0, hdr->subsystem_vendor);
189     dw_pcie_writew_dbi(pci, func_offset + PCIR_SUBDEV_0, hdr->subsystem_device);
190     dw_pcie_writeb_dbi(pci, func_offset + PCIR_INTPIN, hdr->intx);
191 
192     dw_pcie_dbi_ro_writable_enable(pci, RT_FALSE);
193 
194     return 0;
195 }
196 
dw_pcie_ep_clear_bar(struct rt_pci_ep * epc,rt_uint8_t func_no,struct rt_pci_ep_bar * bar,int bar_idx)197 static rt_err_t dw_pcie_ep_clear_bar(struct rt_pci_ep *epc, rt_uint8_t func_no,
198         struct rt_pci_ep_bar *bar, int bar_idx)
199 {
200     rt_uint32_t atu_index;
201     struct dw_pcie_ep *ep = epc->priv;
202     struct dw_pcie *pci = to_dw_pcie_from_endpoint(ep);
203 
204     atu_index = ep->bar_to_atu[bar_idx];
205     __dw_pcie_ep_reset_bar(pci, func_no, bar_idx, ep->epc_bar[bar_idx]->bus.flags);
206 
207     dw_pcie_disable_atu(pci, atu_index, DW_PCIE_REGION_INBOUND);
208     rt_bitmap_clear_bit(ep->ib_window_map, atu_index);
209     ep->epc_bar[bar_idx] = RT_NULL;
210 
211     return RT_EOK;
212 }
213 
dw_pcie_ep_set_bar(struct rt_pci_ep * epc,rt_uint8_t func_no,struct rt_pci_ep_bar * bar,int bar_idx)214 static rt_err_t dw_pcie_ep_set_bar(struct rt_pci_ep *epc, rt_uint8_t func_no,
215         struct rt_pci_ep_bar *bar, int bar_idx)
216 {
217     rt_err_t err;
218     rt_uint32_t reg;
219     rt_uint8_t func_offset = 0;
220     rt_size_t size = bar->bus.size;
221     rt_ubase_t flags = bar->bus.flags;
222     enum dw_pcie_aspace_type aspace_type;
223     struct dw_pcie_ep *ep = epc->priv;
224     struct dw_pcie *pci = to_dw_pcie_from_endpoint(ep);
225 
226     func_offset = dw_pcie_ep_func_select(ep, func_no);
227     reg = PCIR_BAR(bar_idx) + func_offset;
228 
229     if (!(flags & PCIM_BAR_SPACE))
230     {
231         aspace_type = DW_PCIE_ASPACE_MEM;
232     }
233     else
234     {
235         aspace_type = DW_PCIE_ASPACE_IO;
236     }
237 
238     err = dw_pcie_ep_inbound_atu(ep, func_no, bar_idx, bar->bus.base, aspace_type);
239     if (err)
240     {
241         return err;
242     }
243 
244     dw_pcie_dbi_ro_writable_enable(pci, RT_TRUE);
245 
246     dw_pcie_writel_dbi2(pci, reg, rt_lower_32_bits(size - 1));
247     dw_pcie_writel_dbi(pci, reg, flags);
248 
249     if (flags & PCIM_BAR_MEM_TYPE_64)
250     {
251         dw_pcie_writel_dbi2(pci, reg + 4, rt_upper_32_bits(size - 1));
252         dw_pcie_writel_dbi(pci, reg + 4, 0);
253     }
254 
255     ep->epc_bar[bar_idx] = bar;
256     dw_pcie_dbi_ro_writable_enable(pci, RT_FALSE);
257 
258     return 0;
259 }
260 
dw_pcie_find_index(struct dw_pcie_ep * ep,rt_ubase_t addr,rt_uint32_t * atu_index)261 static rt_err_t dw_pcie_find_index(struct dw_pcie_ep *ep,
262         rt_ubase_t addr, rt_uint32_t *atu_index)
263 {
264     for (rt_uint32_t index = 0; index < ep->num_ob_windows; ++index)
265     {
266         if (ep->outbound_addr[index] != addr)
267         {
268             continue;
269         }
270 
271         *atu_index = index;
272 
273         return RT_EOK;
274     }
275 
276     return -RT_EINVAL;
277 }
278 
dw_pcie_ep_unmap_addr(struct rt_pci_ep * epc,rt_uint8_t func_no,rt_ubase_t addr)279 static rt_err_t dw_pcie_ep_unmap_addr(struct rt_pci_ep *epc, rt_uint8_t func_no,
280         rt_ubase_t addr)
281 {
282     rt_err_t err;
283     rt_uint32_t atu_index;
284     struct dw_pcie_ep *ep = epc->priv;
285     struct dw_pcie *pci = to_dw_pcie_from_endpoint(ep);
286 
287     if ((err = dw_pcie_find_index(ep, addr, &atu_index)))
288     {
289         return err;
290     }
291 
292     dw_pcie_disable_atu(pci, atu_index, DW_PCIE_REGION_OUTBOUND);
293     rt_bitmap_clear_bit(ep->ob_window_map, atu_index);
294 
295     return RT_EOK;
296 }
297 
dw_pcie_ep_map_addr(struct rt_pci_ep * epc,rt_uint8_t func_no,rt_ubase_t addr,rt_uint64_t pci_addr,rt_size_t size)298 static rt_err_t dw_pcie_ep_map_addr(struct rt_pci_ep *epc, rt_uint8_t func_no,
299         rt_ubase_t addr, rt_uint64_t pci_addr, rt_size_t size)
300 {
301     rt_err_t err;
302     struct dw_pcie_ep *ep = epc->priv;
303 
304     err = dw_pcie_ep_outbound_atu(ep, func_no, addr, pci_addr, size);
305     if (err)
306     {
307         LOG_E("Failed to enable address error = %s", rt_strerror(err));
308         return err;
309     }
310 
311     return RT_EOK;
312 }
313 
dw_pcie_ep_set_msi(struct rt_pci_ep * epc,rt_uint8_t func_no,unsigned irq_nr)314 static rt_err_t dw_pcie_ep_set_msi(struct rt_pci_ep *epc, rt_uint8_t func_no,
315         unsigned irq_nr)
316 {
317     rt_uint32_t val, reg;
318     rt_uint8_t func_offset = 0;
319     struct dw_pcie_ep_func *ep_func;
320     struct dw_pcie_ep *ep = epc->priv;
321     struct dw_pcie *pci = to_dw_pcie_from_endpoint(ep);
322 
323     ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
324     if (!ep_func || !ep_func->msi_cap)
325     {
326         return -RT_EINVAL;
327     }
328 
329     func_offset = dw_pcie_ep_func_select(ep, func_no);
330     reg = ep_func->msi_cap + func_offset + PCIR_MSI_CTRL;
331 
332     val = dw_pcie_readw_dbi(pci, reg);
333     val &= ~PCIM_MSICTRL_MMC_MASK;
334     val |= (irq_nr << 1) & PCIM_MSICTRL_MMC_MASK;
335 
336     dw_pcie_dbi_ro_writable_enable(pci, RT_TRUE);
337     dw_pcie_writew_dbi(pci, reg, val);
338     dw_pcie_dbi_ro_writable_enable(pci, RT_FALSE);
339 
340     return RT_EOK;
341 }
342 
dw_pcie_ep_get_msi(struct rt_pci_ep * epc,rt_uint8_t func_no,unsigned * out_irq_nr)343 static rt_err_t dw_pcie_ep_get_msi(struct rt_pci_ep *epc, rt_uint8_t func_no,
344         unsigned *out_irq_nr)
345 {
346     rt_uint32_t val, reg;
347     rt_uint8_t func_offset = 0;
348     struct dw_pcie_ep *ep = epc->priv;
349     struct dw_pcie_ep_func *ep_func;
350     struct dw_pcie *pci = to_dw_pcie_from_endpoint(ep);
351 
352     ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
353     if (!ep_func || !ep_func->msi_cap)
354     {
355         return -RT_EINVAL;
356     }
357 
358     func_offset = dw_pcie_ep_func_select(ep, func_no);
359     reg = ep_func->msi_cap + func_offset + PCIR_MSI_CTRL;
360 
361     val = dw_pcie_readw_dbi(pci, reg);
362     if (!(val & PCIM_MSICTRL_MSI_ENABLE))
363     {
364         return -RT_EINVAL;
365     }
366 
367     *out_irq_nr = (val & PCIM_MSICTRL_MME_MASK) >> 4;
368 
369     return RT_EOK;
370 }
371 
dw_pcie_ep_set_msix(struct rt_pci_ep * epc,rt_uint8_t func_no,unsigned irq_nr,int bar_idx,rt_off_t offset)372 static rt_err_t dw_pcie_ep_set_msix(struct rt_pci_ep *epc, rt_uint8_t func_no,
373         unsigned irq_nr, int bar_idx, rt_off_t offset)
374 {
375     rt_uint32_t val, reg;
376     rt_uint8_t func_offset = 0;
377     struct dw_pcie_ep_func *ep_func;
378     struct dw_pcie_ep *ep = epc->priv;
379     struct dw_pcie *pci = to_dw_pcie_from_endpoint(ep);
380 
381     ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
382     if (!ep_func || !ep_func->msix_cap)
383     {
384         return -RT_EINVAL;
385     }
386 
387     dw_pcie_dbi_ro_writable_enable(pci, RT_TRUE);
388 
389     func_offset = dw_pcie_ep_func_select(ep, func_no);
390     reg = ep_func->msix_cap + func_offset + PCIR_MSIX_CTRL;
391 
392     val = dw_pcie_readw_dbi(pci, reg);
393     val &= ~PCIM_MSIXCTRL_TABLE_SIZE;
394     val |= irq_nr;
395     dw_pcie_writew_dbi(pci, reg, val);
396 
397     reg = ep_func->msix_cap + func_offset + PCIR_MSIX_TABLE;
398     val = offset | bar_idx;
399     dw_pcie_writel_dbi(pci, reg, val);
400 
401     reg = ep_func->msix_cap + func_offset + PCIR_MSIX_PBA;
402     val = (offset + (irq_nr * PCIM_MSIX_ENTRY_SIZE)) | bar_idx;
403     dw_pcie_writel_dbi(pci, reg, val);
404 
405     dw_pcie_dbi_ro_writable_enable(pci, RT_FALSE);
406 
407     return RT_EOK;
408 }
409 
dw_pcie_ep_get_msix(struct rt_pci_ep * epc,rt_uint8_t func_no,unsigned * out_irq_nr)410 static rt_err_t dw_pcie_ep_get_msix(struct rt_pci_ep *epc, rt_uint8_t func_no,
411         unsigned *out_irq_nr)
412 {
413     rt_uint32_t val, reg;
414     rt_uint8_t func_offset = 0;
415     struct dw_pcie_ep_func *ep_func;
416     struct dw_pcie_ep *ep = epc->priv;
417     struct dw_pcie *pci = to_dw_pcie_from_endpoint(ep);
418 
419     ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
420     if (!ep_func || !ep_func->msix_cap)
421     {
422         return -RT_EINVAL;
423     }
424 
425     func_offset = dw_pcie_ep_func_select(ep, func_no);
426     reg = ep_func->msix_cap + func_offset + PCIR_MSIX_CTRL;
427 
428     val = dw_pcie_readw_dbi(pci, reg);
429     if (!(val & PCIM_MSIXCTRL_MSIX_ENABLE))
430     {
431         return -RT_EINVAL;
432     }
433 
434     *out_irq_nr = val & PCIM_MSIXCTRL_TABLE_SIZE;
435 
436     return RT_EOK;
437 }
438 
dw_pcie_ep_raise_irq(struct rt_pci_ep * epc,rt_uint8_t func_no,enum rt_pci_ep_irq type,unsigned irq)439 static rt_err_t dw_pcie_ep_raise_irq(struct rt_pci_ep *epc, rt_uint8_t func_no,
440         enum rt_pci_ep_irq type, unsigned irq)
441 {
442     struct dw_pcie_ep *ep = epc->priv;
443 
444     if (!ep->ops->raise_irq)
445     {
446         return -RT_ENOSYS;
447     }
448 
449     return ep->ops->raise_irq(ep, func_no, type, irq);
450 }
451 
dw_pcie_ep_stop(struct rt_pci_ep * epc)452 static rt_err_t dw_pcie_ep_stop(struct rt_pci_ep *epc)
453 {
454     struct dw_pcie_ep *ep = epc->priv;
455     struct dw_pcie *pci = to_dw_pcie_from_endpoint(ep);
456 
457     if (pci->ops->stop_link)
458     {
459         pci->ops->stop_link(pci);
460     }
461 
462     return RT_EOK;
463 }
464 
dw_pcie_ep_start(struct rt_pci_ep * epc)465 static rt_err_t dw_pcie_ep_start(struct rt_pci_ep *epc)
466 {
467     struct dw_pcie_ep *ep = epc->priv;
468     struct dw_pcie *pci = to_dw_pcie_from_endpoint(ep);
469 
470     if (pci->ops->start_link)
471     {
472         return pci->ops->start_link(pci);
473     }
474 
475     return RT_EOK;
476 }
477 
478 static const struct rt_pci_ep_ops dw_pcie_ep_ops =
479 {
480     .write_header   = dw_pcie_ep_write_header,
481     .set_bar        = dw_pcie_ep_set_bar,
482     .clear_bar      = dw_pcie_ep_clear_bar,
483     .map_addr       = dw_pcie_ep_map_addr,
484     .unmap_addr     = dw_pcie_ep_unmap_addr,
485     .set_msi        = dw_pcie_ep_set_msi,
486     .get_msi        = dw_pcie_ep_get_msi,
487     .set_msix       = dw_pcie_ep_set_msix,
488     .get_msix       = dw_pcie_ep_get_msix,
489     .raise_irq      = dw_pcie_ep_raise_irq,
490     .start          = dw_pcie_ep_start,
491     .stop           = dw_pcie_ep_stop,
492 };
493 
dw_pcie_ep_raise_legacy_irq(struct dw_pcie_ep * ep,rt_uint8_t func_no)494 rt_err_t dw_pcie_ep_raise_legacy_irq(struct dw_pcie_ep *ep, rt_uint8_t func_no)
495 {
496     LOG_E("EP cannot trigger legacy IRQs");
497 
498     return -RT_EINVAL;
499 }
500 
dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep * ep,rt_uint8_t func_no,unsigned irq)501 rt_err_t dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, rt_uint8_t func_no,
502         unsigned irq)
503 {
504     rt_err_t err;
505     rt_off_t aligned_offset;
506     rt_uint8_t func_offset = 0;
507     rt_uint64_t msg_addr;
508     rt_uint16_t msg_ctrl, msg_data;
509     rt_uint32_t msg_addr_lower, msg_addr_upper, reg;
510     struct rt_pci_ep *epc = ep->epc;
511     struct dw_pcie_ep_func *ep_func;
512     struct dw_pcie *pci = to_dw_pcie_from_endpoint(ep);
513 
514     ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
515     if (!ep_func || !ep_func->msi_cap)
516     {
517         return -RT_EINVAL;
518     }
519 
520     func_offset = dw_pcie_ep_func_select(ep, func_no);
521 
522     /* Raise MSI per the PCI Local Bus Specification Revision 3.0, 6.8.1. */
523     reg = ep_func->msi_cap + func_offset + PCIR_MSI_CTRL;
524     msg_ctrl = dw_pcie_readw_dbi(pci, reg);
525     reg = ep_func->msi_cap + func_offset + PCIR_MSI_ADDR;
526     msg_addr_lower = dw_pcie_readl_dbi(pci, reg);
527 
528     if (!!(msg_ctrl & PCIM_MSICTRL_64BIT))
529     {
530         reg = ep_func->msi_cap + func_offset + PCIR_MSI_ADDR_HIGH;
531         msg_addr_upper = dw_pcie_readl_dbi(pci, reg);
532         reg = ep_func->msi_cap + func_offset + PCIR_MSI_DATA_64BIT;
533         msg_data = dw_pcie_readw_dbi(pci, reg);
534     }
535     else
536     {
537         msg_addr_upper = 0;
538         reg = ep_func->msi_cap + func_offset + PCIR_MSI_DATA;
539         msg_data = dw_pcie_readw_dbi(pci, reg);
540     }
541 
542     aligned_offset = msg_addr_lower & (ep->page_size - 1);
543     msg_addr = ((rt_uint64_t)msg_addr_upper << 32) | (msg_addr_lower & ~aligned_offset);
544 
545     if ((err = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phy, msg_addr, ep->page_size)))
546     {
547         return err;
548     }
549 
550     HWREG32(ep->msi_mem + aligned_offset) = msg_data | (irq - 1);
551     dw_pcie_ep_unmap_addr(epc, func_no, ep->msi_mem_phy);
552 
553     return RT_EOK;
554 }
555 
dw_pcie_ep_raise_msix_irq_doorbell(struct dw_pcie_ep * ep,rt_uint8_t func_no,unsigned irq)556 rt_err_t dw_pcie_ep_raise_msix_irq_doorbell(struct dw_pcie_ep *ep, rt_uint8_t func_no,
557         unsigned irq)
558 {
559     rt_uint32_t msg_data;
560     struct dw_pcie_ep_func *ep_func;
561     struct dw_pcie *pci = to_dw_pcie_from_endpoint(ep);
562 
563     ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
564     if (!ep_func || !ep_func->msix_cap)
565     {
566         return -RT_EINVAL;
567     }
568 
569     msg_data = (func_no << PCIE_MSIX_DOORBELL_PF_SHIFT) | (irq - 1);
570     dw_pcie_writel_dbi(pci, PCIE_MSIX_DOORBELL, msg_data);
571 
572     return RT_EOK;
573 }
574 
dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep * ep,rt_uint8_t func_no,unsigned irq)575 rt_err_t dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, rt_uint8_t func_no,
576         unsigned irq)
577 {
578     rt_err_t err;
579     int bar_idx;
580     rt_uint64_t msg_addr;
581     rt_uint32_t tbl_offset;
582     rt_off_t aligned_offset;
583     rt_uint8_t func_offset = 0;
584     rt_uint32_t reg, msg_data, vec_ctrl;
585     struct rt_pci_ep *epc = ep->epc;
586     struct rt_pci_ep_msix_tbl *msix_tbl;
587     struct dw_pcie_ep_func *ep_func;
588     struct dw_pcie *pci = to_dw_pcie_from_endpoint(ep);
589 
590     ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
591     if (!ep_func || !ep_func->msix_cap)
592     {
593         return -RT_EINVAL;
594     }
595 
596     func_offset = dw_pcie_ep_func_select(ep, func_no);
597     reg = ep_func->msix_cap + func_offset + PCIR_MSIX_TABLE;
598 
599     tbl_offset = dw_pcie_readl_dbi(pci, reg);
600     bar_idx = (tbl_offset & PCIM_MSIX_BIR_MASK);
601     tbl_offset &= PCIM_MSIX_TABLE_OFFSET;
602 
603     msix_tbl = (void *)ep->epc_bar[bar_idx]->cpu_addr + tbl_offset;
604     msg_addr = msix_tbl[(irq - 1)].msg_addr;
605     msg_data = msix_tbl[(irq - 1)].msg_data;
606     vec_ctrl = msix_tbl[(irq - 1)].vector_ctrl;
607 
608     if (vec_ctrl & PCIM_MSIX_ENTRYVECTOR_CTRL_MASK)
609     {
610         return -RT_EINVAL;
611     }
612 
613     aligned_offset = msg_addr & (ep->page_size - 1);
614 
615     if ((err = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phy, msg_addr, ep->page_size)))
616     {
617         return err;
618     }
619 
620     HWREG32(ep->msi_mem + aligned_offset) = msg_data;
621     dw_pcie_ep_unmap_addr(epc, func_no, ep->msi_mem_phy);
622 
623     return RT_EOK;
624 }
625 
dw_pcie_ep_exit(struct dw_pcie_ep * ep)626 void dw_pcie_ep_exit(struct dw_pcie_ep *ep)
627 {
628     struct rt_pci_ep *epc = ep->epc;
629 
630     if (ep->msi_mem)
631     {
632         rt_pci_ep_mem_free(epc, ep->msi_mem, ep->msi_mem_phy, ep->page_size);
633     }
634 
635     if (!rt_list_isempty(&ep->func_nodes))
636     {
637         struct dw_pcie_ep_func *ep_func, *ep_func_next;
638 
639         rt_list_for_each_entry_safe(ep_func, ep_func_next, &ep->func_nodes, list)
640         {
641             rt_list_remove(&ep_func->list);
642             rt_free(ep_func);
643         }
644     }
645 
646     if (ep->ib_window_map)
647     {
648         rt_free(ep->ib_window_map);
649     }
650 
651     if (ep->ob_window_map)
652     {
653         rt_free(ep->ob_window_map);
654     }
655 
656     if (ep->outbound_addr)
657     {
658         rt_free(ep->outbound_addr);
659     }
660 
661     if (epc)
662     {
663         rt_free(epc);
664     }
665 }
666 
dw_pcie_ep_find_ext_capability(struct dw_pcie * pci,int cap)667 static rt_uint32_t dw_pcie_ep_find_ext_capability(struct dw_pcie *pci, int cap)
668 {
669     rt_uint32_t header;
670     int pos = (PCI_REGMAX + 1);
671 
672     while (pos)
673     {
674         header = dw_pcie_readl_dbi(pci, pos);
675 
676         if (PCI_EXTCAP_ID(header) == cap)
677         {
678             return pos;
679         }
680 
681         if (!(pos = PCI_EXTCAP_NEXTPTR(header)))
682         {
683             break;
684         }
685     }
686 
687     return 0;
688 }
689 
dw_pcie_ep_init_complete(struct dw_pcie_ep * ep)690 rt_err_t dw_pcie_ep_init_complete(struct dw_pcie_ep *ep)
691 {
692     rt_off_t offset;
693     rt_size_t bar_nr;
694     rt_uint32_t reg;
695     rt_uint8_t hdr_type;
696     struct dw_pcie *pci = to_dw_pcie_from_endpoint(ep);
697 
698     hdr_type = dw_pcie_readb_dbi(pci, PCIR_HDRTYPE) & PCIM_HDRTYPE;
699     if (hdr_type != PCIM_HDRTYPE_NORMAL)
700     {
701         LOG_E("PCIe controller is not set to EP mode hdr_type = %x", hdr_type);
702         return -RT_EIO;
703     }
704 
705     offset = dw_pcie_ep_find_ext_capability(pci, PCIZ_RESIZE_BAR);
706 
707     dw_pcie_dbi_ro_writable_enable(pci, RT_TRUE);
708 
709     if (offset)
710     {
711         reg = dw_pcie_readl_dbi(pci, offset + PCIM_REBAR_CTRL);
712         bar_nr = (reg & PCIM_REBAR_CTRL_NBAR_MASK) >> PCIM_REBAR_CTRL_NBAR_SHIFT;
713 
714         for (int i = 0; i < bar_nr; ++i, offset += PCIM_REBAR_CTRL)
715         {
716             dw_pcie_writel_dbi(pci, offset + PCIM_REBAR_CAP, 0x0);
717         }
718     }
719 
720     dw_pcie_setup(pci);
721     dw_pcie_dbi_ro_writable_enable(pci, RT_FALSE);
722 
723     return RT_EOK;
724 }
725 
dw_pcie_ep_init(struct dw_pcie_ep * ep)726 rt_err_t dw_pcie_ep_init(struct dw_pcie_ep *ep)
727 {
728     rt_err_t err;
729     struct rt_pci_ep *epc = RT_NULL;
730     struct dw_pcie_ep_func *ep_func;
731     struct dw_pcie *pci = to_dw_pcie_from_endpoint(ep);
732     struct rt_device *dev = pci->dev;
733 
734     rt_list_init(&ep->func_nodes);
735 
736     if (!pci->dbi_base || !pci->dbi_base2)
737     {
738         LOG_E("dbi_base/dbi_base2 is not populated");
739         return -RT_EINVAL;
740     }
741 
742     if ((err = rt_dm_dev_prop_read_u32(dev, "num-ib-windows", &ep->num_ib_windows)))
743     {
744         LOG_E("Unable to read 'num-ib-windows' property");
745         return err;
746     }
747 
748     if (ep->num_ib_windows > MAX_IATU_IN)
749     {
750         LOG_E("Invalid 'num-ib-windows'");
751         return -RT_EINVAL;
752     }
753 
754     if ((err = rt_dm_dev_prop_read_u32(dev, "num-ob-windows", &ep->num_ob_windows)))
755     {
756         LOG_E("Unable to read 'num-ob-windows' property");
757         return err;
758     }
759 
760     if (ep->num_ob_windows > MAX_IATU_OUT)
761     {
762         LOG_E("Invalid 'num-ob-windows'");
763         return -RT_EINVAL;
764     }
765 
766     ep->ib_window_map = rt_calloc(RT_BITMAP_LEN(ep->num_ib_windows), sizeof(rt_bitmap_t));
767     if (!ep->ib_window_map)
768     {
769         return -RT_ENOMEM;
770     }
771 
772     ep->ob_window_map = rt_calloc(RT_BITMAP_LEN(ep->num_ob_windows), sizeof(rt_bitmap_t));
773     if (!ep->ob_window_map)
774     {
775         err = -RT_ENOMEM;
776         goto _fail;
777     }
778 
779     ep->outbound_addr = rt_calloc(ep->num_ob_windows, sizeof(rt_ubase_t));
780     if (!ep->outbound_addr)
781     {
782         err = -RT_ENOMEM;
783         goto _fail;
784     }
785 
786     if (pci->link_gen < 1)
787     {
788         pci->link_gen = -1;
789         rt_dm_dev_prop_read_u32(dev, "max-link-speed", &pci->link_gen);
790     }
791 
792     epc = rt_calloc(1, sizeof(*epc));
793     if (!epc)
794     {
795         err = -RT_ENOMEM;
796         goto _fail;
797     }
798 
799     epc->name = rt_dm_dev_get_name(dev);
800     epc->rc_dev = dev;
801     epc->ops = &dw_pcie_ep_ops;
802     epc->priv = ep;
803 
804     if ((err = rt_pci_ep_register(epc)))
805     {
806         goto _fail;
807     }
808     ep->epc = epc;
809 
810     if (rt_dm_dev_prop_read_u8(dev, "max-functions", &epc->max_functions))
811     {
812         epc->max_functions = 1;
813     }
814 
815     for (rt_uint8_t func_no = 0; func_no < epc->max_functions; ++func_no)
816     {
817         ep_func = rt_calloc(1, sizeof(*ep_func));
818 
819         if (!ep_func)
820         {
821             err = -RT_ENOMEM;
822             goto _fail;
823         }
824 
825         ep_func->func_no = func_no;
826         ep_func->msi_cap = dw_pcie_ep_find_capability(ep, func_no, PCIY_MSI);
827         ep_func->msix_cap = dw_pcie_ep_find_capability(ep, func_no, PCIY_MSIX);
828 
829         rt_list_init(&ep_func->list);
830         rt_list_insert_after(&ep->func_nodes, &ep_func->list);
831     }
832 
833     if (ep->ops->ep_init)
834     {
835         ep->ops->ep_init(ep);
836     }
837 
838     if ((err = rt_pci_ep_mem_init(epc, ep->aspace, ep->aspace_size, ep->page_size)))
839     {
840         goto _fail;
841     }
842 
843     ep->msi_mem = rt_pci_ep_mem_alloc(epc, &ep->msi_mem_phy, ep->page_size);
844 
845     if (!ep->msi_mem)
846     {
847         LOG_E("Failed to reserve memory for MSI/MSI-X");
848         err = -RT_ENOMEM;
849         goto _fail;
850     }
851 
852     if ((err = dw_pcie_ep_init_complete(ep)))
853     {
854         goto _fail;
855     }
856 
857     return RT_EOK;
858 
859 _fail:
860     dw_pcie_ep_exit(ep);
861 
862     return err;
863 }
864