525-PCI-aardvark-use-isr1-instead-of-isr0-interrupt-in-legacy-irq-mode.patch 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. From patchwork Thu Sep 28 12:58:35 2017
  2. Content-Type: text/plain; charset="utf-8"
  3. MIME-Version: 1.0
  4. Content-Transfer-Encoding: 7bit
  5. Subject: [v2,
  6. 4/7] PCI: aardvark: use isr1 instead of isr0 interrupt in legacy irq
  7. mode
  8. X-Patchwork-Submitter: Thomas Petazzoni <[email protected]>
  9. X-Patchwork-Id: 819592
  10. Message-Id: <[email protected]>
  11. To: Bjorn Helgaas <[email protected]>, [email protected]
  12. Cc: Jason Cooper <[email protected]>, Andrew Lunn <[email protected]>,
  13. Sebastian Hesselbarth <[email protected]>, Gregory Clement
  14. <[email protected]>,
  15. Nadav Haklai <[email protected]>, Hanna Hawa <[email protected]>,
  16. Yehuda Yitschak <[email protected]>,
  17. [email protected], Antoine Tenart
  18. <[email protected]>, =?utf-8?q?Miqu=C3=A8l_Raynal?=
  19. <[email protected]>, Victor Gu <[email protected]>,
  20. Thomas Petazzoni <[email protected]>
  21. Date: Thu, 28 Sep 2017 14:58:35 +0200
  22. From: Thomas Petazzoni <[email protected]>
  23. List-Id: <linux-pci.vger.kernel.org>
  24. From: Victor Gu <[email protected]>
  25. The Aardvark has two interrupts sets:
  26. - first set is bit[23:16] of PCIe ISR 0 register(RD0074840h)
  27. - second set is bit[11:8] of PCIe ISR 1 register(RD0074848h)
  28. Only one set should be used, while another set should be masked.
  29. The second set, ISR1, is more advanced, the Legacy INT_X status bit is
  30. asserted once Assert_INTX message is received, and de-asserted after
  31. Deassert_INTX message is received. Therefore, it matches what the
  32. driver is currently doing in the ->irq_mask() and ->irq_unmask()
  33. functions. The ISR0 requires additional work to deassert the
  34. interrupt, which the driver doesn't do currently.
  35. This commit resolves a number of issues with legacy interrupts.
  36. This is part of fixing bug
  37. https://bugzilla.kernel.org/show_bug.cgi?id=196339, this commit was
  38. reported as the user to be important to get a Intel 7260 mini-PCIe
  39. WiFi card working.
  40. Fixes: 8c39d710363c1 ("PCI: aardvark: Add Aardvark PCI host controller driver")
  41. Signed-off-by: Victor Gu <[email protected]>
  42. Reviewed-by: Evan Wang <[email protected]>
  43. Reviewed-by: Nadav Haklai <[email protected]>
  44. [Thomas: tweak commit log.]
  45. Signed-off-by: Thomas Petazzoni <[email protected]>
  46. ---
  47. drivers/pci/host/pci-aardvark.c | 41 ++++++++++++++++++++++++-----------------
  48. 1 file changed, 24 insertions(+), 17 deletions(-)
  49. --- a/drivers/pci/host/pci-aardvark.c
  50. +++ b/drivers/pci/host/pci-aardvark.c
  51. @@ -105,7 +105,8 @@
  52. #define PCIE_ISR1_MASK_REG (CONTROL_BASE_ADDR + 0x4C)
  53. #define PCIE_ISR1_POWER_STATE_CHANGE BIT(4)
  54. #define PCIE_ISR1_FLUSH BIT(5)
  55. -#define PCIE_ISR1_ALL_MASK GENMASK(5, 4)
  56. +#define PCIE_ISR1_INTX_ASSERT(val) BIT(8 + (val))
  57. +#define PCIE_ISR1_ALL_MASK GENMASK(11, 4)
  58. #define PCIE_MSI_ADDR_LOW_REG (CONTROL_BASE_ADDR + 0x50)
  59. #define PCIE_MSI_ADDR_HIGH_REG (CONTROL_BASE_ADDR + 0x54)
  60. #define PCIE_MSI_STATUS_REG (CONTROL_BASE_ADDR + 0x58)
  61. @@ -615,9 +616,9 @@ static void advk_pcie_irq_mask(struct ir
  62. irq_hw_number_t hwirq = irqd_to_hwirq(d);
  63. u32 mask;
  64. - mask = advk_readl(pcie, PCIE_ISR0_MASK_REG);
  65. - mask |= PCIE_ISR0_INTX_ASSERT(hwirq);
  66. - advk_writel(pcie, mask, PCIE_ISR0_MASK_REG);
  67. + mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
  68. + mask |= PCIE_ISR1_INTX_ASSERT(hwirq);
  69. + advk_writel(pcie, mask, PCIE_ISR1_MASK_REG);
  70. }
  71. static void advk_pcie_irq_unmask(struct irq_data *d)
  72. @@ -626,9 +627,9 @@ static void advk_pcie_irq_unmask(struct
  73. irq_hw_number_t hwirq = irqd_to_hwirq(d);
  74. u32 mask;
  75. - mask = advk_readl(pcie, PCIE_ISR0_MASK_REG);
  76. - mask &= ~PCIE_ISR0_INTX_ASSERT(hwirq);
  77. - advk_writel(pcie, mask, PCIE_ISR0_MASK_REG);
  78. + mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
  79. + mask &= ~PCIE_ISR1_INTX_ASSERT(hwirq);
  80. + advk_writel(pcie, mask, PCIE_ISR1_MASK_REG);
  81. }
  82. static int advk_pcie_irq_map(struct irq_domain *h,
  83. @@ -771,29 +772,35 @@ static void advk_pcie_handle_msi(struct
  84. static void advk_pcie_handle_int(struct advk_pcie *pcie)
  85. {
  86. - u32 val, mask, status;
  87. + u32 isr0_val, isr0_mask, isr0_status;
  88. + u32 isr1_val, isr1_mask, isr1_status;
  89. int i, virq;
  90. - val = advk_readl(pcie, PCIE_ISR0_REG);
  91. - mask = advk_readl(pcie, PCIE_ISR0_MASK_REG);
  92. - status = val & ((~mask) & PCIE_ISR0_ALL_MASK);
  93. -
  94. - if (!status) {
  95. - advk_writel(pcie, val, PCIE_ISR0_REG);
  96. + isr0_val = advk_readl(pcie, PCIE_ISR0_REG);
  97. + isr0_mask = advk_readl(pcie, PCIE_ISR0_MASK_REG);
  98. + isr0_status = isr0_val & ((~isr0_mask) & PCIE_ISR0_ALL_MASK);
  99. +
  100. + isr1_val = advk_readl(pcie, PCIE_ISR1_REG);
  101. + isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
  102. + isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK);
  103. +
  104. + if (!isr0_status && !isr1_status) {
  105. + advk_writel(pcie, isr0_val, PCIE_ISR0_REG);
  106. + advk_writel(pcie, isr1_val, PCIE_ISR1_REG);
  107. return;
  108. }
  109. /* Process MSI interrupts */
  110. - if (status & PCIE_ISR0_MSI_INT_PENDING)
  111. + if (isr0_status & PCIE_ISR0_MSI_INT_PENDING)
  112. advk_pcie_handle_msi(pcie);
  113. /* Process legacy interrupts */
  114. for (i = 0; i < PCI_NUM_INTX; i++) {
  115. - if (!(status & PCIE_ISR0_INTX_ASSERT(i)))
  116. + if (!(isr1_status & PCIE_ISR1_INTX_ASSERT(i)))
  117. continue;
  118. - advk_writel(pcie, PCIE_ISR0_INTX_ASSERT(i),
  119. - PCIE_ISR0_REG);
  120. + advk_writel(pcie, PCIE_ISR1_INTX_ASSERT(i),
  121. + PCIE_ISR1_REG);
  122. virq = irq_find_mapping(pcie->irq_domain, i);
  123. generic_handle_irq(virq);