Skip to content

Commit 986b6ad

Browse files
paliKAGA-KOKO
authored andcommitted
irqchip/armada-370-xp: Add support for 32 MSI interrupts on non-IPI platforms
The doorbell interrupts have the following layout on IPI vs no-IPI platforms: | 0...7 | 8...15 | 16...31 | ------------------+---------+----------+---------------------+ IPI platform | IPI | n/a | MSI | ------------------+---------+----------+---------------------+ non-IPI platform | MSI | ------------------+------------------------------------------+ Currently the driver only allows for the upper 16...31 interrupts for MSI domain (i.e. the MSI domain has only 16 interrupts). On platforms where IPI is not available, we can use whole 32 MSI interrupts. Implement support also for the lower 16 MSI interrupts on non-IPI platforms. [ Marek: refactored, changed commit message ] Signed-off-by: Pali Rohár <[email protected]> Signed-off-by: Marek Behún <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Andrew Lunn <[email protected]>
1 parent 9d80f6b commit 986b6ad

File tree

1 file changed

+63
-14
lines changed

1 file changed

+63
-14
lines changed

drivers/irqchip/irq-armada-370-xp.c

Lines changed: 63 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* warranty of any kind, whether express or implied.
1414
*/
1515

16+
#include <linux/bits.h>
1617
#include <linux/kernel.h>
1718
#include <linux/module.h>
1819
#include <linux/init.h>
@@ -136,6 +137,7 @@
136137

137138
#define ARMADA_370_XP_MAX_PER_CPU_IRQS (28)
138139

140+
/* IPI and MSI interrupt definitions for IPI platforms */
139141
#define IPI_DOORBELL_START (0)
140142
#define IPI_DOORBELL_END (8)
141143
#define IPI_DOORBELL_MASK 0xFF
@@ -144,6 +146,14 @@
144146
#define PCI_MSI_DOORBELL_END (32)
145147
#define PCI_MSI_DOORBELL_MASK 0xFFFF0000
146148

149+
/* MSI interrupt definitions for non-IPI platforms */
150+
#define PCI_MSI_FULL_DOORBELL_START 0
151+
#define PCI_MSI_FULL_DOORBELL_NR 32
152+
#define PCI_MSI_FULL_DOORBELL_END 32
153+
#define PCI_MSI_FULL_DOORBELL_MASK GENMASK(31, 0)
154+
#define PCI_MSI_FULL_DOORBELL_SRC0_MASK GENMASK(15, 0)
155+
#define PCI_MSI_FULL_DOORBELL_SRC1_MASK GENMASK(31, 16)
156+
147157
static void __iomem *per_cpu_int_base;
148158
static void __iomem *main_int_base;
149159
static struct irq_domain *armada_370_xp_mpic_domain;
@@ -152,7 +162,7 @@ static int parent_irq;
152162
#ifdef CONFIG_PCI_MSI
153163
static struct irq_domain *armada_370_xp_msi_domain;
154164
static struct irq_domain *armada_370_xp_msi_inner_domain;
155-
static DECLARE_BITMAP(msi_used, PCI_MSI_DOORBELL_NR);
165+
static DECLARE_BITMAP(msi_used, PCI_MSI_FULL_DOORBELL_NR);
156166
static DEFINE_MUTEX(msi_used_lock);
157167
static phys_addr_t msi_doorbell_addr;
158168
#endif
@@ -168,6 +178,30 @@ static inline bool is_ipi_available(void)
168178
return parent_irq <= 0;
169179
}
170180

181+
static inline u32 msi_doorbell_mask(void)
182+
{
183+
return is_ipi_available() ? PCI_MSI_DOORBELL_MASK :
184+
PCI_MSI_FULL_DOORBELL_MASK;
185+
}
186+
187+
static inline unsigned int msi_doorbell_start(void)
188+
{
189+
return is_ipi_available() ? PCI_MSI_DOORBELL_START :
190+
PCI_MSI_FULL_DOORBELL_START;
191+
}
192+
193+
static inline unsigned int msi_doorbell_size(void)
194+
{
195+
return is_ipi_available() ? PCI_MSI_DOORBELL_NR :
196+
PCI_MSI_FULL_DOORBELL_NR;
197+
}
198+
199+
static inline unsigned int msi_doorbell_end(void)
200+
{
201+
return is_ipi_available() ? PCI_MSI_DOORBELL_END :
202+
PCI_MSI_FULL_DOORBELL_END;
203+
}
204+
171205
static inline bool is_percpu_irq(irq_hw_number_t irq)
172206
{
173207
if (irq <= ARMADA_370_XP_MAX_PER_CPU_IRQS)
@@ -225,7 +259,7 @@ static void armada_370_xp_compose_msi_msg(struct irq_data *data, struct msi_msg
225259

226260
msg->address_lo = lower_32_bits(msi_doorbell_addr);
227261
msg->address_hi = upper_32_bits(msi_doorbell_addr);
228-
msg->data = BIT(cpu + 8) | (data->hwirq + PCI_MSI_DOORBELL_START);
262+
msg->data = BIT(cpu + 8) | (data->hwirq + msi_doorbell_start());
229263
}
230264

231265
static int armada_370_xp_msi_set_affinity(struct irq_data *irq_data,
@@ -258,7 +292,7 @@ static int armada_370_xp_msi_alloc(struct irq_domain *domain, unsigned int virq,
258292
int hwirq, i;
259293

260294
mutex_lock(&msi_used_lock);
261-
hwirq = bitmap_find_free_region(msi_used, PCI_MSI_DOORBELL_NR,
295+
hwirq = bitmap_find_free_region(msi_used, msi_doorbell_size(),
262296
order_base_2(nr_irqs));
263297
mutex_unlock(&msi_used_lock);
264298

@@ -295,9 +329,10 @@ static void armada_370_xp_msi_reenable_percpu(void)
295329
u32 reg;
296330

297331
/* Enable MSI doorbell mask and combined cpu local interrupt */
298-
reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS)
299-
| PCI_MSI_DOORBELL_MASK;
332+
reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
333+
reg |= msi_doorbell_mask();
300334
writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
335+
301336
/* Unmask local doorbell interrupt */
302337
writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
303338
}
@@ -309,7 +344,7 @@ static int armada_370_xp_msi_init(struct device_node *node,
309344
ARMADA_370_XP_SW_TRIG_INT_OFFS;
310345

311346
armada_370_xp_msi_inner_domain =
312-
irq_domain_add_linear(NULL, PCI_MSI_DOORBELL_NR,
347+
irq_domain_add_linear(NULL, msi_doorbell_size(),
313348
&armada_370_xp_msi_domain_ops, NULL);
314349
if (!armada_370_xp_msi_inner_domain)
315350
return -ENOMEM;
@@ -325,6 +360,10 @@ static int armada_370_xp_msi_init(struct device_node *node,
325360

326361
armada_370_xp_msi_reenable_percpu();
327362

363+
/* Unmask low 16 MSI irqs on non-IPI platforms */
364+
if (!is_ipi_available())
365+
writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
366+
328367
return 0;
329368
}
330369
#else
@@ -613,20 +652,20 @@ static void armada_370_xp_handle_msi_irq(struct pt_regs *regs, bool is_chained)
613652
u32 msimask, msinr;
614653

615654
msimask = readl_relaxed(per_cpu_int_base +
616-
ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
617-
& PCI_MSI_DOORBELL_MASK;
655+
ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
656+
msimask &= msi_doorbell_mask();
618657

619658
writel(~msimask, per_cpu_int_base +
620659
ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
621660

622-
for (msinr = PCI_MSI_DOORBELL_START;
623-
msinr < PCI_MSI_DOORBELL_END; msinr++) {
661+
for (msinr = msi_doorbell_start();
662+
msinr < msi_doorbell_end(); msinr++) {
624663
unsigned int irq;
625664

626665
if (!(msimask & BIT(msinr)))
627666
continue;
628667

629-
irq = msinr - PCI_MSI_DOORBELL_START;
668+
irq = msinr - msi_doorbell_start();
630669

631670
generic_handle_domain_irq(armada_370_xp_msi_inner_domain, irq);
632671
}
@@ -655,7 +694,7 @@ static void armada_370_xp_mpic_handle_cascade_irq(struct irq_desc *desc)
655694
if (!(irqsrc & ARMADA_370_XP_INT_IRQ_FIQ_MASK(cpuid)))
656695
continue;
657696

658-
if (irqn == 1) {
697+
if (irqn == 0 || irqn == 1) {
659698
armada_370_xp_handle_msi_irq(NULL, true);
660699
continue;
661700
}
@@ -716,6 +755,7 @@ static int armada_370_xp_mpic_suspend(void)
716755

717756
static void armada_370_xp_mpic_resume(void)
718757
{
758+
bool src0, src1;
719759
int nirqs;
720760
irq_hw_number_t irq;
721761

@@ -755,9 +795,18 @@ static void armada_370_xp_mpic_resume(void)
755795
/* Reconfigure doorbells for IPIs and MSIs */
756796
writel(doorbell_mask_reg,
757797
per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
758-
if (is_ipi_available() && (doorbell_mask_reg & IPI_DOORBELL_MASK))
798+
799+
if (is_ipi_available()) {
800+
src0 = doorbell_mask_reg & IPI_DOORBELL_MASK;
801+
src1 = doorbell_mask_reg & PCI_MSI_DOORBELL_MASK;
802+
} else {
803+
src0 = doorbell_mask_reg & PCI_MSI_FULL_DOORBELL_SRC0_MASK;
804+
src1 = doorbell_mask_reg & PCI_MSI_FULL_DOORBELL_SRC1_MASK;
805+
}
806+
807+
if (src0)
759808
writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
760-
if (doorbell_mask_reg & PCI_MSI_DOORBELL_MASK)
809+
if (src1)
761810
writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
762811

763812
if (is_ipi_available())

0 commit comments

Comments
 (0)