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