Skip to content

Commit 273ddd8

Browse files
paliLorenzo Pieralisi
authored andcommitted
PCI: aardvark: Fix support for PME requester on emulated bridge
Enable aardvark PME interrupt unconditionally by unmasking it and read PME requester ID to emulated bridge config space immediately after receiving interrupt. PME requester ID is stored in the PCIE_MSG_LOG_REG register, which contains the last inbound message. So when new inbound message is received by HW (including non-PM), the content in PCIE_MSG_LOG_REG register is replaced by a new value. PCIe specification mandates that subsequent PMEs are kept pending until the PME Status Register bit is cleared by software by writing a 1b. Support for masking/unmasking PME interrupt on emulated bridge via PCI_EXP_RTCTL_PMEIE bit is now implemented only in emulated bridge config space, to ensure that we do not miss any aardvark PME interrupt. Reading of PCI_EXP_RTCAP and PCI_EXP_RTSTA registers is simplified as final value is now always stored into emulated bridge config space by the interrupt handler, so there is no need to implement support for these registers in read_pcie callback. Clearing of W1C bit PCI_EXP_RTSTA_PME is now also simplified as it is done by pci-bridge-emul.c code for emulated bridge config space. So there is no need to implement support for clearing this bit in write_pcie callback. Link: https://lore.kernel.org/r/20220110015018.26359-18-kabel@kernel.org Signed-off-by: Pali Rohár <pali@kernel.org> Signed-off-by: Marek Behún <kabel@kernel.org> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
1 parent 0fc75d8 commit 273ddd8

1 file changed

Lines changed: 50 additions & 41 deletions

File tree

drivers/pci/controller/pci-aardvark.c

Lines changed: 50 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,11 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
590590
reg &= ~PCIE_ISR0_MSI_INT_PENDING;
591591
advk_writel(pcie, reg, PCIE_ISR0_MASK_REG);
592592

593+
/* Unmask PME interrupt for processing of PME requester */
594+
reg = advk_readl(pcie, PCIE_ISR0_MASK_REG);
595+
reg &= ~PCIE_MSG_PM_PME_MASK;
596+
advk_writel(pcie, reg, PCIE_ISR0_MASK_REG);
597+
593598
/* Enable summary interrupt for GIC SPI source */
594599
reg = PCIE_IRQ_ALL_MASK & (~PCIE_IRQ_ENABLE_INTS_MASK);
595600
advk_writel(pcie, reg, HOST_CTRL_INT_MASK_REG);
@@ -856,22 +861,11 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
856861
*value = PCI_EXP_SLTSTA_PDS << 16;
857862
return PCI_BRIDGE_EMUL_HANDLED;
858863

859-
case PCI_EXP_RTCTL: {
860-
u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG);
861-
*value = (val & PCIE_MSG_PM_PME_MASK) ? 0 : PCI_EXP_RTCTL_PMEIE;
862-
*value |= le16_to_cpu(bridge->pcie_conf.rootctl) & PCI_EXP_RTCTL_CRSSVE;
863-
*value |= PCI_EXP_RTCAP_CRSVIS << 16;
864-
return PCI_BRIDGE_EMUL_HANDLED;
865-
}
866-
867-
case PCI_EXP_RTSTA: {
868-
u32 isr0 = advk_readl(pcie, PCIE_ISR0_REG);
869-
u32 msglog = advk_readl(pcie, PCIE_MSG_LOG_REG);
870-
*value = msglog >> 16;
871-
if (isr0 & PCIE_MSG_PM_PME_MASK)
872-
*value |= PCI_EXP_RTSTA_PME;
873-
return PCI_BRIDGE_EMUL_HANDLED;
874-
}
864+
/*
865+
* PCI_EXP_RTCTL and PCI_EXP_RTSTA are also supported, but do not need
866+
* to be handled here, because their values are stored in emulated
867+
* config space buffer, and we read them from there when needed.
868+
*/
875869

876870
case PCI_EXP_LNKCAP: {
877871
u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg);
@@ -925,22 +919,19 @@ advk_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
925919
advk_pcie_wait_for_retrain(pcie);
926920
break;
927921

928-
case PCI_EXP_RTCTL:
929-
/* Only mask/unmask PME interrupt */
930-
if (mask & PCI_EXP_RTCTL_PMEIE) {
931-
u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG);
932-
if (new & PCI_EXP_RTCTL_PMEIE)
933-
val &= ~PCIE_MSG_PM_PME_MASK;
934-
else
935-
val |= PCIE_MSG_PM_PME_MASK;
936-
advk_writel(pcie, val, PCIE_ISR0_MASK_REG);
937-
}
922+
case PCI_EXP_RTCTL: {
923+
u16 rootctl = le16_to_cpu(bridge->pcie_conf.rootctl);
924+
/* Only emulation of PMEIE and CRSSVE bits is provided */
925+
rootctl &= PCI_EXP_RTCTL_PMEIE | PCI_EXP_RTCTL_CRSSVE;
926+
bridge->pcie_conf.rootctl = cpu_to_le16(rootctl);
938927
break;
928+
}
939929

940-
case PCI_EXP_RTSTA:
941-
if (new & PCI_EXP_RTSTA_PME)
942-
advk_writel(pcie, PCIE_MSG_PM_PME_MASK, PCIE_ISR0_REG);
943-
break;
930+
/*
931+
* PCI_EXP_RTSTA is also supported, but does not need to be handled
932+
* here, because its value is stored in emulated config space buffer,
933+
* and we write it there when needed.
934+
*/
944935

945936
case PCI_EXP_DEVCTL:
946937
case PCI_EXP_DEVCTL2:
@@ -1443,6 +1434,32 @@ static void advk_pcie_remove_irq_domain(struct advk_pcie *pcie)
14431434
irq_domain_remove(pcie->irq_domain);
14441435
}
14451436

1437+
static void advk_pcie_handle_pme(struct advk_pcie *pcie)
1438+
{
1439+
u32 requester = advk_readl(pcie, PCIE_MSG_LOG_REG) >> 16;
1440+
1441+
advk_writel(pcie, PCIE_MSG_PM_PME_MASK, PCIE_ISR0_REG);
1442+
1443+
/*
1444+
* PCIE_MSG_LOG_REG contains the last inbound message, so store
1445+
* the requester ID only when PME was not asserted yet.
1446+
* Also do not trigger PME interrupt when PME is still asserted.
1447+
*/
1448+
if (!(le32_to_cpu(pcie->bridge.pcie_conf.rootsta) & PCI_EXP_RTSTA_PME)) {
1449+
pcie->bridge.pcie_conf.rootsta = cpu_to_le32(requester | PCI_EXP_RTSTA_PME);
1450+
1451+
/*
1452+
* Trigger PME interrupt only if PMEIE bit in Root Control is set.
1453+
* Aardvark HW returns zero for PCI_EXP_FLAGS_IRQ, so use PCIe interrupt 0.
1454+
*/
1455+
if (!(le16_to_cpu(pcie->bridge.pcie_conf.rootctl) & PCI_EXP_RTCTL_PMEIE))
1456+
return;
1457+
1458+
if (generic_handle_domain_irq(pcie->irq_domain, 0) == -EINVAL)
1459+
dev_err_ratelimited(&pcie->pdev->dev, "unhandled PME IRQ\n");
1460+
}
1461+
}
1462+
14461463
static void advk_pcie_handle_msi(struct advk_pcie *pcie)
14471464
{
14481465
u32 msi_val, msi_mask, msi_status, msi_idx;
@@ -1478,17 +1495,9 @@ static void advk_pcie_handle_int(struct advk_pcie *pcie)
14781495
isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
14791496
isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK);
14801497

1481-
/* Process PME interrupt */
1482-
if (isr0_status & PCIE_MSG_PM_PME_MASK) {
1483-
/*
1484-
* Do not clear PME interrupt bit in ISR0, it is cleared by IRQ
1485-
* receiver by writing to the PCI_EXP_RTSTA register of emulated
1486-
* root bridge. Aardvark HW returns zero for PCI_EXP_FLAGS_IRQ,
1487-
* so use PCIe interrupt 0.
1488-
*/
1489-
if (generic_handle_domain_irq(pcie->irq_domain, 0) == -EINVAL)
1490-
dev_err_ratelimited(&pcie->pdev->dev, "unhandled PME IRQ\n");
1491-
}
1498+
/* Process PME interrupt as the first one to do not miss PME requester id */
1499+
if (isr0_status & PCIE_MSG_PM_PME_MASK)
1500+
advk_pcie_handle_pme(pcie);
14921501

14931502
/* Process ERR interrupt */
14941503
if (isr0_status & PCIE_ISR0_ERR_MASK) {

0 commit comments

Comments
 (0)