Message ID | 20240108110612.19048-15-minda.chen@starfivetech.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | Refactoring Microchip PCIe driver and add StarFive PCIe | expand |
> 主题: [PATCH v14 14/22] PCI: microchip: Add get_events() callback and add > PLDA get_event() > > As PLDA dts binding doc(Documentation/devicetree/bindings/pci/ > plda,xpressrich3-axi-common.yaml) showes, PLDA PCIe contains an interrupt > controller. > > PolarFire implements its own PCIe interrupts, additional to the regular PCIe > interrupts, due to lack of an MSI controller, so the interrupt to event number > mapping is different to the PLDA regular interrupts, necessitating a custom > get_events() implementation. > > Microchip Polarfire PCIe additional intrerrupts: > EVENT_PCIE_L2_EXIT > EVENT_PCIE_HOTRST_EXIT > EVENT_PCIE_DLUP_EXIT > EVENT_SEC_TX_RAM_SEC_ERR > EVENT_SEC_RX_RAM_SEC_ERR > .... > > plda_get_events() adds interrupt register to PLDA local event num mapping > codes. All The PLDA interrupts can be seen in new added graph. > > Signed-off-by: Minda Chen <minda.chen@starfivetech.com> > Acked-by: Conor Dooley <conor.dooley@microchip.com> > --- > .../pci/controller/plda/pcie-microchip-host.c | 35 ++++++++++++++++++- > drivers/pci/controller/plda/pcie-plda.h | 32 +++++++++++++++++ > 2 files changed, 66 insertions(+), 1 deletion(-) > > diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c > b/drivers/pci/controller/plda/pcie-microchip-host.c > index 8a51d3aa7e88..b3df373a2141 100644 > --- a/drivers/pci/controller/plda/pcie-microchip-host.c > +++ b/drivers/pci/controller/plda/pcie-microchip-host.c > @@ -626,6 +626,26 @@ static u32 mc_get_events(struct plda_pcie_rp *port) > return events; > } > > +static u32 plda_get_events(struct plda_pcie_rp *port) { > + u32 events, val, origin; > + > + origin = readl_relaxed(port->bridge_addr + ISTATUS_LOCAL); > + > + /* MSI event and sys events */ > + val = (origin & SYS_AND_MSI_MASK) >> PM_MSI_INT_MSI_SHIFT; > + events = val << (PM_MSI_INT_MSI_SHIFT - PCI_NUM_INTX + 1); > + > + /* INTx events */ > + if (origin & PM_MSI_INT_INTX_MASK) > + events |= BIT(PM_MSI_INT_INTX_SHIFT); > + > + /* remains are same with register */ > + events |= origin & GENMASK(P_ATR_EVT_DOORBELL_SHIFT, 0); > + > + return events; > +} > + > static irqreturn_t mc_event_handler(int irq, void *dev_id) { > struct plda_pcie_rp *port = dev_id; > @@ -656,7 +676,7 @@ static void plda_handle_event(struct irq_desc *desc) > > chained_irq_enter(chip, desc); > > - events = mc_get_events(port); > + events = port->event_ops->get_events(port); > > for_each_set_bit(bit, &events, port->num_events) > generic_handle_domain_irq(port->event_domain, bit); @@ -750,6 > +770,10 @@ static struct irq_chip mc_event_irq_chip = { > .irq_unmask = mc_unmask_event_irq, > }; > > +static const struct plda_event_ops plda_event_ops = { > + .get_events = plda_get_events, > +}; > + > static int plda_pcie_event_map(struct irq_domain *domain, unsigned int irq, > irq_hw_number_t hwirq) > { > @@ -815,6 +839,10 @@ static int mc_request_event_irq(struct plda_pcie_rp > *plda, int event_irq, > 0, event_cause[event].sym, plda); > } > > +static const struct plda_event_ops mc_event_ops = { > + .get_events = mc_get_events, > +}; > + > static const struct plda_event mc_event = { > .request_event_irq = mc_request_event_irq, > .intx_event = EVENT_LOCAL_PM_MSI_INT_INTX, > @@ -931,6 +959,9 @@ static int plda_init_interrupts(struct platform_device > *pdev, > int i, intx_irq, msi_irq, event_irq; > int ret; > > + if (!port->event_ops) > + port->event_ops = &plda_event_ops; > + > ret = plda_pcie_init_irq_domains(port); > if (ret) { > dev_err(dev, "failed creating IRQ domains\n"); @@ -1007,6 +1038,8 > @@ static int mc_platform_init(struct pci_config_window *cfg) > if (ret) > return ret; > > + port->plda.event_ops = &mc_event_ops; > + > /* Address translation is up; safe to enable interrupts */ > ret = plda_init_interrupts(pdev, &port->plda, &mc_event); > if (ret) > diff --git a/drivers/pci/controller/plda/pcie-plda.h > b/drivers/pci/controller/plda/pcie-plda.h > index 0efe64d5f688..9db92ccf286c 100644 > --- a/drivers/pci/controller/plda/pcie-plda.h > +++ b/drivers/pci/controller/plda/pcie-plda.h > @@ -58,6 +58,7 @@ > #define PM_MSI_INT_EVENTS_SHIFT 30 > #define PM_MSI_INT_SYS_ERR_MASK 0x80000000u > #define PM_MSI_INT_SYS_ERR_SHIFT 31 > +#define SYS_AND_MSI_MASK GENMASK(31, 28) > #define NUM_LOCAL_EVENTS 15 > #define ISTATUS_LOCAL 0x184 > #define IMASK_HOST 0x188 > @@ -108,6 +109,36 @@ enum plda_int_event { > > #define PLDA_MAX_INT_NUM (PLDA_NUM_DMA_EVENTS + > PLDA_INT_EVENT_NUM) > > +/* > + * PLDA interrupt register > + * > + * 31 27 23 15 7 0 > + * +--+--+--+-+------+-+-+-+-+-+-+-+-+-----------+-----------+ > + * |12|11|10|9| intx |7|6|5|4|3|2|1|0| DMA error | DMA end | > + * +--+--+--+-+------+-+-+-+-+-+-+-+-+-----------+-----------+ > + * bit 0-7 DMA interrupt end : reserved for vendor implement > + * bit 8-15 DMA error : reserved for vendor implement > + * 0: AXI post error (PLDA_AXI_POST_ERR) > + * 1: AXI fetch error (PLDA_AXI_FETCH_ERR) > + * 2: AXI discard error (PLDA_AXI_DISCARD_ERR) > + * 3: AXI doorbell (PLDA_PCIE_DOORBELL) > + * 4: PCIe post error (PLDA_PCIE_POST_ERR) > + * 5: PCIe fetch error (PLDA_PCIE_FETCH_ERR) > + * 6: PCIe discard error (PLDA_PCIE_DISCARD_ERR) > + * 7: PCIe doorbell (PLDA_PCIE_DOORBELL) > + * 8: 4 INTx interruts (PLDA_INTX) > + * 9: MSI interrupt (PLDA_MSI) > + * 10: AER event (PLDA_AER_EVENT) > + * 11: PM/LTR/Hotplug (PLDA_MISC_EVENTS) > + * 12: System error (PLDA_SYS_ERR) > + */ > + Hi Tomas The PLDA interrupt register is showed aboved. plda_get_events() is register to event mapping. The relationship is list below. register bit event 0 0 | | | | 23 23 24 ----> 24 (intx) | | 27 --+ 28 25 | | 31 28 > +struct plda_pcie_rp; > + > +struct plda_event_ops { > + u32 (*get_events)(struct plda_pcie_rp *pcie); }; > + > struct plda_msi { > struct mutex lock; /* Protect used bitmap */ > struct irq_domain *msi_domain; > @@ -123,6 +154,7 @@ struct plda_pcie_rp { > struct irq_domain *event_domain; > raw_spinlock_t lock; > struct plda_msi msi; > + const struct plda_event_ops *event_ops; > void __iomem *bridge_addr; > int num_events; > }; > -- > 2.17.1
diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c index 8a51d3aa7e88..b3df373a2141 100644 --- a/drivers/pci/controller/plda/pcie-microchip-host.c +++ b/drivers/pci/controller/plda/pcie-microchip-host.c @@ -626,6 +626,26 @@ static u32 mc_get_events(struct plda_pcie_rp *port) return events; } +static u32 plda_get_events(struct plda_pcie_rp *port) +{ + u32 events, val, origin; + + origin = readl_relaxed(port->bridge_addr + ISTATUS_LOCAL); + + /* MSI event and sys events */ + val = (origin & SYS_AND_MSI_MASK) >> PM_MSI_INT_MSI_SHIFT; + events = val << (PM_MSI_INT_MSI_SHIFT - PCI_NUM_INTX + 1); + + /* INTx events */ + if (origin & PM_MSI_INT_INTX_MASK) + events |= BIT(PM_MSI_INT_INTX_SHIFT); + + /* remains are same with register */ + events |= origin & GENMASK(P_ATR_EVT_DOORBELL_SHIFT, 0); + + return events; +} + static irqreturn_t mc_event_handler(int irq, void *dev_id) { struct plda_pcie_rp *port = dev_id; @@ -656,7 +676,7 @@ static void plda_handle_event(struct irq_desc *desc) chained_irq_enter(chip, desc); - events = mc_get_events(port); + events = port->event_ops->get_events(port); for_each_set_bit(bit, &events, port->num_events) generic_handle_domain_irq(port->event_domain, bit); @@ -750,6 +770,10 @@ static struct irq_chip mc_event_irq_chip = { .irq_unmask = mc_unmask_event_irq, }; +static const struct plda_event_ops plda_event_ops = { + .get_events = plda_get_events, +}; + static int plda_pcie_event_map(struct irq_domain *domain, unsigned int irq, irq_hw_number_t hwirq) { @@ -815,6 +839,10 @@ static int mc_request_event_irq(struct plda_pcie_rp *plda, int event_irq, 0, event_cause[event].sym, plda); } +static const struct plda_event_ops mc_event_ops = { + .get_events = mc_get_events, +}; + static const struct plda_event mc_event = { .request_event_irq = mc_request_event_irq, .intx_event = EVENT_LOCAL_PM_MSI_INT_INTX, @@ -931,6 +959,9 @@ static int plda_init_interrupts(struct platform_device *pdev, int i, intx_irq, msi_irq, event_irq; int ret; + if (!port->event_ops) + port->event_ops = &plda_event_ops; + ret = plda_pcie_init_irq_domains(port); if (ret) { dev_err(dev, "failed creating IRQ domains\n"); @@ -1007,6 +1038,8 @@ static int mc_platform_init(struct pci_config_window *cfg) if (ret) return ret; + port->plda.event_ops = &mc_event_ops; + /* Address translation is up; safe to enable interrupts */ ret = plda_init_interrupts(pdev, &port->plda, &mc_event); if (ret) diff --git a/drivers/pci/controller/plda/pcie-plda.h b/drivers/pci/controller/plda/pcie-plda.h index 0efe64d5f688..9db92ccf286c 100644 --- a/drivers/pci/controller/plda/pcie-plda.h +++ b/drivers/pci/controller/plda/pcie-plda.h @@ -58,6 +58,7 @@ #define PM_MSI_INT_EVENTS_SHIFT 30 #define PM_MSI_INT_SYS_ERR_MASK 0x80000000u #define PM_MSI_INT_SYS_ERR_SHIFT 31 +#define SYS_AND_MSI_MASK GENMASK(31, 28) #define NUM_LOCAL_EVENTS 15 #define ISTATUS_LOCAL 0x184 #define IMASK_HOST 0x188 @@ -108,6 +109,36 @@ enum plda_int_event { #define PLDA_MAX_INT_NUM (PLDA_NUM_DMA_EVENTS + PLDA_INT_EVENT_NUM) +/* + * PLDA interrupt register + * + * 31 27 23 15 7 0 + * +--+--+--+-+------+-+-+-+-+-+-+-+-+-----------+-----------+ + * |12|11|10|9| intx |7|6|5|4|3|2|1|0| DMA error | DMA end | + * +--+--+--+-+------+-+-+-+-+-+-+-+-+-----------+-----------+ + * bit 0-7 DMA interrupt end : reserved for vendor implement + * bit 8-15 DMA error : reserved for vendor implement + * 0: AXI post error (PLDA_AXI_POST_ERR) + * 1: AXI fetch error (PLDA_AXI_FETCH_ERR) + * 2: AXI discard error (PLDA_AXI_DISCARD_ERR) + * 3: AXI doorbell (PLDA_PCIE_DOORBELL) + * 4: PCIe post error (PLDA_PCIE_POST_ERR) + * 5: PCIe fetch error (PLDA_PCIE_FETCH_ERR) + * 6: PCIe discard error (PLDA_PCIE_DISCARD_ERR) + * 7: PCIe doorbell (PLDA_PCIE_DOORBELL) + * 8: 4 INTx interruts (PLDA_INTX) + * 9: MSI interrupt (PLDA_MSI) + * 10: AER event (PLDA_AER_EVENT) + * 11: PM/LTR/Hotplug (PLDA_MISC_EVENTS) + * 12: System error (PLDA_SYS_ERR) + */ + +struct plda_pcie_rp; + +struct plda_event_ops { + u32 (*get_events)(struct plda_pcie_rp *pcie); +}; + struct plda_msi { struct mutex lock; /* Protect used bitmap */ struct irq_domain *msi_domain; @@ -123,6 +154,7 @@ struct plda_pcie_rp { struct irq_domain *event_domain; raw_spinlock_t lock; struct plda_msi msi; + const struct plda_event_ops *event_ops; void __iomem *bridge_addr; int num_events; };