7
7
* Author: Daire McNamara <daire.mcnamara@microchip.com>
8
8
*/
9
9
10
+ #include <linux/bitfield.h>
10
11
#include <linux/clk.h>
11
12
#include <linux/irqchip/chained_irq.h>
12
13
#include <linux/irqdomain.h>
20
21
#include "../pci.h"
21
22
22
23
/* Number of MSI IRQs */
23
- #define MC_NUM_MSI_IRQS 32
24
- #define MC_NUM_MSI_IRQS_CODED 5
24
+ #define MC_MAX_NUM_MSI_IRQS 32
25
25
26
26
/* PCIe Bridge Phy and Controller Phy offsets */
27
27
#define MC_PCIE1_BRIDGE_ADDR 0x00008000u
31
31
#define MC_PCIE_CTRL_ADDR (MC_PCIE1_CTRL_ADDR)
32
32
33
33
/* PCIe Bridge Phy Regs */
34
+ #define PCIE_PCI_IRQ_DW0 0xa8
35
+ #define MSIX_CAP_MASK BIT(31)
36
+ #define NUM_MSI_MSGS_MASK GENMASK(6, 4)
37
+ #define NUM_MSI_MSGS_SHIFT 4
38
+
34
39
#define IMASK_LOCAL 0x180
35
40
#define DMA_END_ENGINE_0_MASK 0x00000000u
36
41
#define DMA_END_ENGINE_0_SHIFT 0
79
84
#define IMASK_HOST 0x188
80
85
#define ISTATUS_HOST 0x18c
81
86
#define IMSI_ADDR 0x190
82
- #define MSI_ADDR 0x190
83
87
#define ISTATUS_MSI 0x194
84
88
85
89
/* PCIe Master table init defines */
158
162
159
163
/* PCIe Config space MSI capability structure */
160
164
#define MC_MSI_CAP_CTRL_OFFSET 0xe0u
161
- #define MC_MSI_MAX_Q_AVAIL (MC_NUM_MSI_IRQS_CODED << 1)
162
- #define MC_MSI_Q_SIZE (MC_NUM_MSI_IRQS_CODED << 4)
163
165
164
166
/* Events */
165
167
#define EVENT_PCIE_L2_EXIT 0
@@ -259,7 +261,7 @@ struct mc_msi {
259
261
struct irq_domain * dev_domain ;
260
262
u32 num_vectors ;
261
263
u64 vector_phy ;
262
- DECLARE_BITMAP (used , MC_NUM_MSI_IRQS );
264
+ DECLARE_BITMAP (used , MC_MAX_NUM_MSI_IRQS );
263
265
};
264
266
265
267
struct mc_pcie {
@@ -382,25 +384,27 @@ static struct {
382
384
383
385
static char poss_clks [][5 ] = { "fic0" , "fic1" , "fic2" , "fic3" };
384
386
385
- static void mc_pcie_enable_msi (struct mc_pcie * port , void __iomem * base )
387
+ static void mc_pcie_enable_msi (struct mc_pcie * port , void __iomem * ecam )
386
388
{
387
389
struct mc_msi * msi = & port -> msi ;
388
- u32 cap_offset = MC_MSI_CAP_CTRL_OFFSET ;
389
- u16 msg_ctrl = readw_relaxed ( base + cap_offset + PCI_MSI_FLAGS ) ;
390
+ u16 reg ;
391
+ u8 queue_size ;
390
392
391
- msg_ctrl |= PCI_MSI_FLAGS_ENABLE ;
392
- msg_ctrl &= ~PCI_MSI_FLAGS_QMASK ;
393
- msg_ctrl |= MC_MSI_MAX_Q_AVAIL ;
394
- msg_ctrl &= ~PCI_MSI_FLAGS_QSIZE ;
395
- msg_ctrl |= MC_MSI_Q_SIZE ;
396
- msg_ctrl |= PCI_MSI_FLAGS_64BIT ;
393
+ /* Fixup MSI enable flag */
394
+ reg = readw_relaxed (ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_FLAGS );
395
+ reg |= PCI_MSI_FLAGS_ENABLE ;
396
+ writew_relaxed (reg , ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_FLAGS );
397
397
398
- writew_relaxed (msg_ctrl , base + cap_offset + PCI_MSI_FLAGS );
398
+ /* Fixup PCI MSI queue flags */
399
+ queue_size = FIELD_GET (PCI_MSI_FLAGS_QMASK , reg );
400
+ reg |= FIELD_PREP (PCI_MSI_FLAGS_QSIZE , queue_size );
401
+ writew_relaxed (reg , ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_FLAGS );
399
402
403
+ /* Fixup MSI addr fields */
400
404
writel_relaxed (lower_32_bits (msi -> vector_phy ),
401
- base + cap_offset + PCI_MSI_ADDRESS_LO );
405
+ ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_ADDRESS_LO );
402
406
writel_relaxed (upper_32_bits (msi -> vector_phy ),
403
- base + cap_offset + PCI_MSI_ADDRESS_HI );
407
+ ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_ADDRESS_HI );
404
408
}
405
409
406
410
static void mc_handle_msi (struct irq_desc * desc )
@@ -473,10 +477,7 @@ static int mc_irq_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
473
477
{
474
478
struct mc_pcie * port = domain -> host_data ;
475
479
struct mc_msi * msi = & port -> msi ;
476
- void __iomem * bridge_base_addr =
477
- port -> axi_base_addr + MC_PCIE_BRIDGE_ADDR ;
478
480
unsigned long bit ;
479
- u32 val ;
480
481
481
482
mutex_lock (& msi -> lock );
482
483
bit = find_first_zero_bit (msi -> used , msi -> num_vectors );
@@ -490,11 +491,6 @@ static int mc_irq_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
490
491
irq_domain_set_info (domain , virq , bit , & mc_msi_bottom_irq_chip ,
491
492
domain -> host_data , handle_edge_irq , NULL , NULL );
492
493
493
- /* Enable MSI interrupts */
494
- val = readl_relaxed (bridge_base_addr + IMASK_LOCAL );
495
- val |= PM_MSI_INT_MSI_MASK ;
496
- writel_relaxed (val , bridge_base_addr + IMASK_LOCAL );
497
-
498
494
mutex_unlock (& msi -> lock );
499
495
500
496
return 0 ;
@@ -1111,6 +1107,7 @@ static int mc_platform_init(struct pci_config_window *cfg)
1111
1107
struct mc_pcie * port ;
1112
1108
void __iomem * bridge_base_addr ;
1113
1109
int ret ;
1110
+ u32 val ;
1114
1111
1115
1112
port = devm_kzalloc (dev , sizeof (* port ), GFP_KERNEL );
1116
1113
if (!port )
@@ -1131,12 +1128,24 @@ static int mc_platform_init(struct pci_config_window *cfg)
1131
1128
1132
1129
bridge_base_addr = port -> axi_base_addr + MC_PCIE_BRIDGE_ADDR ;
1133
1130
1134
- port -> msi .vector_phy = MSI_ADDR ;
1135
- port -> msi .num_vectors = MC_NUM_MSI_IRQS ;
1131
+ /* Allow enabling MSI by disabling MSI-X */
1132
+ val = readl (bridge_base_addr + PCIE_PCI_IRQ_DW0 );
1133
+ val &= ~MSIX_CAP_MASK ;
1134
+ writel (val , bridge_base_addr + PCIE_PCI_IRQ_DW0 );
1136
1135
1137
1136
/* Hardware doesn't setup MSI by default */
1138
1137
mc_pcie_enable_msi (port , cfg -> win );
1139
1138
1139
+ /* Pick num vectors from bitfile programmed onto FPGA fabric */
1140
+ val = readl (bridge_base_addr + PCIE_PCI_IRQ_DW0 );
1141
+ val &= NUM_MSI_MSGS_MASK ;
1142
+ val >>= NUM_MSI_MSGS_SHIFT ;
1143
+
1144
+ port -> msi .num_vectors = 1 << val ;
1145
+
1146
+ /* Pick vector address from design */
1147
+ port -> msi .vector_phy = readl_relaxed (bridge_base_addr + IMSI_ADDR );
1148
+
1140
1149
/* Configure Address Translation Table 0 for PCIe config space */
1141
1150
mc_pcie_setup_window (bridge_base_addr , 0 , cfg -> res .start & 0xffffffff ,
1142
1151
cfg -> res .start , resource_size (& cfg -> res ));
0 commit comments