@@ -40,6 +40,39 @@ void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar)
40
40
__dw_pcie_ep_reset_bar (pci , bar , 0 );
41
41
}
42
42
43
+ static u8 __dw_pcie_ep_find_next_cap (struct dw_pcie * pci , u8 cap_ptr ,
44
+ u8 cap )
45
+ {
46
+ u8 cap_id , next_cap_ptr ;
47
+ u16 reg ;
48
+
49
+ reg = dw_pcie_readw_dbi (pci , cap_ptr );
50
+ next_cap_ptr = (reg & 0xff00 ) >> 8 ;
51
+ cap_id = (reg & 0x00ff );
52
+
53
+ if (!next_cap_ptr || cap_id > PCI_CAP_ID_MAX )
54
+ return 0 ;
55
+
56
+ if (cap_id == cap )
57
+ return cap_ptr ;
58
+
59
+ return __dw_pcie_ep_find_next_cap (pci , next_cap_ptr , cap );
60
+ }
61
+
62
+ static u8 dw_pcie_ep_find_capability (struct dw_pcie * pci , u8 cap )
63
+ {
64
+ u8 next_cap_ptr ;
65
+ u16 reg ;
66
+
67
+ reg = dw_pcie_readw_dbi (pci , PCI_CAPABILITY_LIST );
68
+ next_cap_ptr = (reg & 0x00ff );
69
+
70
+ if (!next_cap_ptr )
71
+ return 0 ;
72
+
73
+ return __dw_pcie_ep_find_next_cap (pci , next_cap_ptr , cap );
74
+ }
75
+
43
76
static int dw_pcie_ep_write_header (struct pci_epc * epc , u8 func_no ,
44
77
struct pci_epf_header * hdr )
45
78
{
@@ -241,6 +274,45 @@ static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 encode_int)
241
274
return 0 ;
242
275
}
243
276
277
+ static int dw_pcie_ep_get_msix (struct pci_epc * epc , u8 func_no )
278
+ {
279
+ struct dw_pcie_ep * ep = epc_get_drvdata (epc );
280
+ struct dw_pcie * pci = to_dw_pcie_from_ep (ep );
281
+ u32 val , reg ;
282
+
283
+ if (!ep -> msix_cap )
284
+ return - EINVAL ;
285
+
286
+ reg = ep -> msix_cap + PCI_MSIX_FLAGS ;
287
+ val = dw_pcie_readw_dbi (pci , reg );
288
+ if (!(val & PCI_MSIX_FLAGS_ENABLE ))
289
+ return - EINVAL ;
290
+
291
+ val &= PCI_MSIX_FLAGS_QSIZE ;
292
+
293
+ return val ;
294
+ }
295
+
296
+ static int dw_pcie_ep_set_msix (struct pci_epc * epc , u8 func_no , u16 interrupts )
297
+ {
298
+ struct dw_pcie_ep * ep = epc_get_drvdata (epc );
299
+ struct dw_pcie * pci = to_dw_pcie_from_ep (ep );
300
+ u32 val , reg ;
301
+
302
+ if (!ep -> msix_cap )
303
+ return - EINVAL ;
304
+
305
+ reg = ep -> msix_cap + PCI_MSIX_FLAGS ;
306
+ val = dw_pcie_readw_dbi (pci , reg );
307
+ val &= ~PCI_MSIX_FLAGS_QSIZE ;
308
+ val |= interrupts ;
309
+ dw_pcie_dbi_ro_wr_en (pci );
310
+ dw_pcie_writew_dbi (pci , reg , val );
311
+ dw_pcie_dbi_ro_wr_dis (pci );
312
+
313
+ return 0 ;
314
+ }
315
+
244
316
static int dw_pcie_ep_raise_irq (struct pci_epc * epc , u8 func_no ,
245
317
enum pci_epc_irq_type type , u16 interrupt_num )
246
318
{
@@ -282,6 +354,8 @@ static const struct pci_epc_ops epc_ops = {
282
354
.unmap_addr = dw_pcie_ep_unmap_addr ,
283
355
.set_msi = dw_pcie_ep_set_msi ,
284
356
.get_msi = dw_pcie_ep_get_msi ,
357
+ .set_msix = dw_pcie_ep_set_msix ,
358
+ .get_msix = dw_pcie_ep_get_msix ,
285
359
.raise_irq = dw_pcie_ep_raise_irq ,
286
360
.start = dw_pcie_ep_start ,
287
361
.stop = dw_pcie_ep_stop ,
@@ -322,6 +396,64 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
322
396
return 0 ;
323
397
}
324
398
399
+ int dw_pcie_ep_raise_msix_irq (struct dw_pcie_ep * ep , u8 func_no ,
400
+ u16 interrupt_num )
401
+ {
402
+ struct dw_pcie * pci = to_dw_pcie_from_ep (ep );
403
+ struct pci_epc * epc = ep -> epc ;
404
+ u16 tbl_offset , bir ;
405
+ u32 bar_addr_upper , bar_addr_lower ;
406
+ u32 msg_addr_upper , msg_addr_lower ;
407
+ u32 reg , msg_data , vec_ctrl ;
408
+ u64 tbl_addr , msg_addr , reg_u64 ;
409
+ void __iomem * msix_tbl ;
410
+ int ret ;
411
+
412
+ reg = ep -> msix_cap + PCI_MSIX_TABLE ;
413
+ tbl_offset = dw_pcie_readl_dbi (pci , reg );
414
+ bir = (tbl_offset & PCI_MSIX_TABLE_BIR );
415
+ tbl_offset &= PCI_MSIX_TABLE_OFFSET ;
416
+ tbl_offset >>= 3 ;
417
+
418
+ reg = PCI_BASE_ADDRESS_0 + (4 * bir );
419
+ bar_addr_upper = 0 ;
420
+ bar_addr_lower = dw_pcie_readl_dbi (pci , reg );
421
+ reg_u64 = (bar_addr_lower & PCI_BASE_ADDRESS_MEM_TYPE_MASK );
422
+ if (reg_u64 == PCI_BASE_ADDRESS_MEM_TYPE_64 )
423
+ bar_addr_upper = dw_pcie_readl_dbi (pci , reg + 4 );
424
+
425
+ tbl_addr = ((u64 ) bar_addr_upper ) << 32 | bar_addr_lower ;
426
+ tbl_addr += (tbl_offset + ((interrupt_num - 1 ) * PCI_MSIX_ENTRY_SIZE ));
427
+ tbl_addr &= PCI_BASE_ADDRESS_MEM_MASK ;
428
+
429
+ msix_tbl = ioremap_nocache (ep -> phys_base + tbl_addr ,
430
+ PCI_MSIX_ENTRY_SIZE );
431
+ if (!msix_tbl )
432
+ return - EINVAL ;
433
+
434
+ msg_addr_lower = readl (msix_tbl + PCI_MSIX_ENTRY_LOWER_ADDR );
435
+ msg_addr_upper = readl (msix_tbl + PCI_MSIX_ENTRY_UPPER_ADDR );
436
+ msg_addr = ((u64 ) msg_addr_upper ) << 32 | msg_addr_lower ;
437
+ msg_data = readl (msix_tbl + PCI_MSIX_ENTRY_DATA );
438
+ vec_ctrl = readl (msix_tbl + PCI_MSIX_ENTRY_VECTOR_CTRL );
439
+
440
+ iounmap (msix_tbl );
441
+
442
+ if (vec_ctrl & PCI_MSIX_ENTRY_CTRL_MASKBIT )
443
+ return - EPERM ;
444
+
445
+ ret = dw_pcie_ep_map_addr (epc , func_no , ep -> msi_mem_phys , msg_addr ,
446
+ epc -> mem -> page_size );
447
+ if (ret )
448
+ return ret ;
449
+
450
+ writel (msg_data , ep -> msi_mem );
451
+
452
+ dw_pcie_ep_unmap_addr (epc , func_no , ep -> msi_mem_phys );
453
+
454
+ return 0 ;
455
+ }
456
+
325
457
void dw_pcie_ep_exit (struct dw_pcie_ep * ep )
326
458
{
327
459
struct pci_epc * epc = ep -> epc ;
@@ -412,9 +544,12 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
412
544
ep -> msi_mem = pci_epc_mem_alloc_addr (epc , & ep -> msi_mem_phys ,
413
545
epc -> mem -> page_size );
414
546
if (!ep -> msi_mem ) {
415
- dev_err (dev , "Failed to reserve memory for MSI\n" );
547
+ dev_err (dev , "Failed to reserve memory for MSI/MSI-X \n" );
416
548
return - ENOMEM ;
417
549
}
550
+ ep -> msi_cap = dw_pcie_ep_find_capability (pci , PCI_CAP_ID_MSI );
551
+
552
+ ep -> msix_cap = dw_pcie_ep_find_capability (pci , PCI_CAP_ID_MSIX );
418
553
419
554
dw_pcie_setup (pci );
420
555
0 commit comments