Skip to content

Commit 1abb722

Browse files
Daire McNamaraLorenzo Pieralisi
authored andcommitted
PCI: microchip: Gather MSI information from hardware config registers
The PCIe Root Complex on PolarFire SoC is configured at bitstream creation time using Libero. Key MSI-related parameters include the number of MSIs (1/2/4/8/16/32) and the MSI address. In the device driver, extract this information from hardware registers at init time, and use it to configure MSI system, including configuring MSI capability structure correctly in configuration space. Link: https://lore.kernel.org/r/20230728131401.1615724-7-daire.mcnamara@microchip.com Signed-off-by: Daire McNamara <daire.mcnamara@microchip.com> Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org> Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
1 parent 4f0b912 commit 1abb722

File tree

1 file changed

+37
-28
lines changed

1 file changed

+37
-28
lines changed

drivers/pci/controller/pcie-microchip-host.c

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* Author: Daire McNamara <daire.mcnamara@microchip.com>
88
*/
99

10+
#include <linux/bitfield.h>
1011
#include <linux/clk.h>
1112
#include <linux/irqchip/chained_irq.h>
1213
#include <linux/irqdomain.h>
@@ -20,8 +21,7 @@
2021
#include "../pci.h"
2122

2223
/* 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
2525

2626
/* PCIe Bridge Phy and Controller Phy offsets */
2727
#define MC_PCIE1_BRIDGE_ADDR 0x00008000u
@@ -31,6 +31,11 @@
3131
#define MC_PCIE_CTRL_ADDR (MC_PCIE1_CTRL_ADDR)
3232

3333
/* 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+
3439
#define IMASK_LOCAL 0x180
3540
#define DMA_END_ENGINE_0_MASK 0x00000000u
3641
#define DMA_END_ENGINE_0_SHIFT 0
@@ -79,7 +84,6 @@
7984
#define IMASK_HOST 0x188
8085
#define ISTATUS_HOST 0x18c
8186
#define IMSI_ADDR 0x190
82-
#define MSI_ADDR 0x190
8387
#define ISTATUS_MSI 0x194
8488

8589
/* PCIe Master table init defines */
@@ -158,8 +162,6 @@
158162

159163
/* PCIe Config space MSI capability structure */
160164
#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)
163165

164166
/* Events */
165167
#define EVENT_PCIE_L2_EXIT 0
@@ -259,7 +261,7 @@ struct mc_msi {
259261
struct irq_domain *dev_domain;
260262
u32 num_vectors;
261263
u64 vector_phy;
262-
DECLARE_BITMAP(used, MC_NUM_MSI_IRQS);
264+
DECLARE_BITMAP(used, MC_MAX_NUM_MSI_IRQS);
263265
};
264266

265267
struct mc_pcie {
@@ -382,25 +384,27 @@ static struct {
382384

383385
static char poss_clks[][5] = { "fic0", "fic1", "fic2", "fic3" };
384386

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)
386388
{
387389
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;
390392

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);
397397

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);
399402

403+
/* Fixup MSI addr fields */
400404
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);
402406
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);
404408
}
405409

406410
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,
473477
{
474478
struct mc_pcie *port = domain->host_data;
475479
struct mc_msi *msi = &port->msi;
476-
void __iomem *bridge_base_addr =
477-
port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
478480
unsigned long bit;
479-
u32 val;
480481

481482
mutex_lock(&msi->lock);
482483
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,
490491
irq_domain_set_info(domain, virq, bit, &mc_msi_bottom_irq_chip,
491492
domain->host_data, handle_edge_irq, NULL, NULL);
492493

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-
498494
mutex_unlock(&msi->lock);
499495

500496
return 0;
@@ -1111,6 +1107,7 @@ static int mc_platform_init(struct pci_config_window *cfg)
11111107
struct mc_pcie *port;
11121108
void __iomem *bridge_base_addr;
11131109
int ret;
1110+
u32 val;
11141111

11151112
port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
11161113
if (!port)
@@ -1131,12 +1128,24 @@ static int mc_platform_init(struct pci_config_window *cfg)
11311128

11321129
bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
11331130

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);
11361135

11371136
/* Hardware doesn't setup MSI by default */
11381137
mc_pcie_enable_msi(port, cfg->win);
11391138

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+
11401149
/* Configure Address Translation Table 0 for PCIe config space */
11411150
mc_pcie_setup_window(bridge_base_addr, 0, cfg->res.start & 0xffffffff,
11421151
cfg->res.start, resource_size(&cfg->res));

0 commit comments

Comments
 (0)