aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Gu <xigu@marvell.com>2018-04-06 10:55:33 -0400
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>2018-04-16 06:48:32 -0400
commit3430f924a62905891c8fa9a3b97ea52007795bc3 (patch)
tree345ca464dfea4098798883dd4c96194e7963c6aa
parent4fa3999ee672c54a5498ce98e20fe3fdf9c1cbb4 (diff)
PCI: aardvark: Use ISR1 instead of ISR0 interrupt in legacy irq mode
The Aardvark has two interrupts sets: - first set is bit[23:16] of PCIe ISR 0 register(RD0074840h) - second set is bit[11:8] of PCIe ISR 1 register(RD0074848h) Only one set should be used, while another set should be masked. The second set, ISR1, is more advanced, the Legacy INT_X status bit is asserted once Assert_INTX message is received, and de-asserted after Deassert_INTX message is received which matches what the driver is currently doing in the ->irq_mask() and ->irq_unmask() functions. The ISR0 requires additional work to deassert the interrupt, which the driver does not currently implement, therefore it needs fixing. Update the driver to use ISR1 register set, fixing current implementation. Fixes: 8c39d710363c1 ("PCI: aardvark: Add Aardvark PCI host controller driver") Link: https://bugzilla.kernel.org/show_bug.cgi?id=196339 Signed-off-by: Victor Gu <xigu@marvell.com> [Thomas: tweak commit log.] Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com> [lorenzo.pieralisi@arm.com: updated the commit log] Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Reviewed-by: Evan Wang <xswang@marvell.com> Reviewed-by: Nadav Haklai <nadavh@marvell.com> Cc: <stable@vger.kernel.org>
-rw-r--r--drivers/pci/host/pci-aardvark.c41
1 files changed, 24 insertions, 17 deletions
diff --git a/drivers/pci/host/pci-aardvark.c b/drivers/pci/host/pci-aardvark.c
index 5b8201aaf34d..7a0ddb709052 100644
--- a/drivers/pci/host/pci-aardvark.c
+++ b/drivers/pci/host/pci-aardvark.c
@@ -100,7 +100,8 @@
100#define PCIE_ISR1_MASK_REG (CONTROL_BASE_ADDR + 0x4C) 100#define PCIE_ISR1_MASK_REG (CONTROL_BASE_ADDR + 0x4C)
101#define PCIE_ISR1_POWER_STATE_CHANGE BIT(4) 101#define PCIE_ISR1_POWER_STATE_CHANGE BIT(4)
102#define PCIE_ISR1_FLUSH BIT(5) 102#define PCIE_ISR1_FLUSH BIT(5)
103#define PCIE_ISR1_ALL_MASK GENMASK(5, 4) 103#define PCIE_ISR1_INTX_ASSERT(val) BIT(8 + (val))
104#define PCIE_ISR1_ALL_MASK GENMASK(11, 4)
104#define PCIE_MSI_ADDR_LOW_REG (CONTROL_BASE_ADDR + 0x50) 105#define PCIE_MSI_ADDR_LOW_REG (CONTROL_BASE_ADDR + 0x50)
105#define PCIE_MSI_ADDR_HIGH_REG (CONTROL_BASE_ADDR + 0x54) 106#define PCIE_MSI_ADDR_HIGH_REG (CONTROL_BASE_ADDR + 0x54)
106#define PCIE_MSI_STATUS_REG (CONTROL_BASE_ADDR + 0x58) 107#define PCIE_MSI_STATUS_REG (CONTROL_BASE_ADDR + 0x58)
@@ -607,9 +608,9 @@ static void advk_pcie_irq_mask(struct irq_data *d)
607 irq_hw_number_t hwirq = irqd_to_hwirq(d); 608 irq_hw_number_t hwirq = irqd_to_hwirq(d);
608 u32 mask; 609 u32 mask;
609 610
610 mask = advk_readl(pcie, PCIE_ISR0_MASK_REG); 611 mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
611 mask |= PCIE_ISR0_INTX_ASSERT(hwirq); 612 mask |= PCIE_ISR1_INTX_ASSERT(hwirq);
612 advk_writel(pcie, mask, PCIE_ISR0_MASK_REG); 613 advk_writel(pcie, mask, PCIE_ISR1_MASK_REG);
613} 614}
614 615
615static void advk_pcie_irq_unmask(struct irq_data *d) 616static void advk_pcie_irq_unmask(struct irq_data *d)
@@ -618,9 +619,9 @@ static void advk_pcie_irq_unmask(struct irq_data *d)
618 irq_hw_number_t hwirq = irqd_to_hwirq(d); 619 irq_hw_number_t hwirq = irqd_to_hwirq(d);
619 u32 mask; 620 u32 mask;
620 621
621 mask = advk_readl(pcie, PCIE_ISR0_MASK_REG); 622 mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
622 mask &= ~PCIE_ISR0_INTX_ASSERT(hwirq); 623 mask &= ~PCIE_ISR1_INTX_ASSERT(hwirq);
623 advk_writel(pcie, mask, PCIE_ISR0_MASK_REG); 624 advk_writel(pcie, mask, PCIE_ISR1_MASK_REG);
624} 625}
625 626
626static int advk_pcie_irq_map(struct irq_domain *h, 627static int advk_pcie_irq_map(struct irq_domain *h,
@@ -763,29 +764,35 @@ static void advk_pcie_handle_msi(struct advk_pcie *pcie)
763 764
764static void advk_pcie_handle_int(struct advk_pcie *pcie) 765static void advk_pcie_handle_int(struct advk_pcie *pcie)
765{ 766{
766 u32 val, mask, status; 767 u32 isr0_val, isr0_mask, isr0_status;
768 u32 isr1_val, isr1_mask, isr1_status;
767 int i, virq; 769 int i, virq;
768 770
769 val = advk_readl(pcie, PCIE_ISR0_REG); 771 isr0_val = advk_readl(pcie, PCIE_ISR0_REG);
770 mask = advk_readl(pcie, PCIE_ISR0_MASK_REG); 772 isr0_mask = advk_readl(pcie, PCIE_ISR0_MASK_REG);
771 status = val & ((~mask) & PCIE_ISR0_ALL_MASK); 773 isr0_status = isr0_val & ((~isr0_mask) & PCIE_ISR0_ALL_MASK);
772 774
773 if (!status) { 775 isr1_val = advk_readl(pcie, PCIE_ISR1_REG);
774 advk_writel(pcie, val, PCIE_ISR0_REG); 776 isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
777 isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK);
778
779 if (!isr0_status && !isr1_status) {
780 advk_writel(pcie, isr0_val, PCIE_ISR0_REG);
781 advk_writel(pcie, isr1_val, PCIE_ISR1_REG);
775 return; 782 return;
776 } 783 }
777 784
778 /* Process MSI interrupts */ 785 /* Process MSI interrupts */
779 if (status & PCIE_ISR0_MSI_INT_PENDING) 786 if (isr0_status & PCIE_ISR0_MSI_INT_PENDING)
780 advk_pcie_handle_msi(pcie); 787 advk_pcie_handle_msi(pcie);
781 788
782 /* Process legacy interrupts */ 789 /* Process legacy interrupts */
783 for (i = 0; i < PCI_NUM_INTX; i++) { 790 for (i = 0; i < PCI_NUM_INTX; i++) {
784 if (!(status & PCIE_ISR0_INTX_ASSERT(i))) 791 if (!(isr1_status & PCIE_ISR1_INTX_ASSERT(i)))
785 continue; 792 continue;
786 793
787 advk_writel(pcie, PCIE_ISR0_INTX_ASSERT(i), 794 advk_writel(pcie, PCIE_ISR1_INTX_ASSERT(i),
788 PCIE_ISR0_REG); 795 PCIE_ISR1_REG);
789 796
790 virq = irq_find_mapping(pcie->irq_domain, i); 797 virq = irq_find_mapping(pcie->irq_domain, i);
791 generic_handle_irq(virq); 798 generic_handle_irq(virq);