Skip to content

Commit

Permalink
MIPS: Netlogic: Add MSI support for XLP
Browse files Browse the repository at this point in the history
Add MSI chip and MSIX chip definitions.

For MSI, we map the link interrupt to a MSI link IRQ which will
do a second level of dispatch based on the MSI status register.

The MSI chip definitions use the MSI enable register to enable
and disable the MSI irqs.

For MSI-X, we split the 32 available MSI-X vectors across the
four PCIe links (8 each). These PIC interrupts generate an IRQ
per link which uses a second level dispatch as well.

The MSI-X chip definition uses the standard functions to enable
and disable interrupts.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
Signed-off-by: John Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/6270/
  • Loading branch information
Jayachandran C authored and Ralf Baechle committed Jan 24, 2014
1 parent 27547ab commit c24a8a7
Show file tree
Hide file tree
Showing 11 changed files with 586 additions and 37 deletions.
1 change: 1 addition & 0 deletions arch/mips/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,7 @@ config NLM_XLP_BOARD
select CEVT_R4K
select CSRC_R4K
select IRQ_CPU
select ARCH_SUPPORTS_MSI
select ZONE_DMA32 if 64BIT
select SYNC_R4K
select SYS_HAS_EARLY_PRINTK
Expand Down
3 changes: 2 additions & 1 deletion arch/mips/include/asm/mach-netlogic/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
#define __ASM_NETLOGIC_IRQ_H

#include <asm/mach-netlogic/multi-node.h>
#define NR_IRQS (64 * NLM_NR_NODES)
#define NLM_IRQS_PER_NODE 1024
#define NR_IRQS (NLM_IRQS_PER_NODE * NLM_NR_NODES)

#define MIPS_CPU_IRQ_BASE 0

Expand Down
6 changes: 6 additions & 0 deletions arch/mips/include/asm/netlogic/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,14 @@ struct nlm_soc_info {

struct irq_data;
uint64_t nlm_pci_irqmask(int node);
void nlm_setup_pic_irq(int node, int picirq, int irq, int irt);
void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *));

#ifdef CONFIG_PCI_MSI
void nlm_dispatch_msi(int node, int lirq);
void nlm_dispatch_msix(int node, int msixirq);
#endif

/*
* The NR_IRQs is divided between nodes, each of them has a separate irq space
*/
Expand Down
33 changes: 25 additions & 8 deletions arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,25 +52,42 @@
#define PCIE_BYTE_SWAP_MEM_LIM 0x248
#define PCIE_BYTE_SWAP_IO_BASE 0x249
#define PCIE_BYTE_SWAP_IO_LIM 0x24A

#define PCIE_BRIDGE_MSIX_ADDR_BASE 0x24F
#define PCIE_BRIDGE_MSIX_ADDR_LIMIT 0x250
#define PCIE_MSI_STATUS 0x25A
#define PCIE_MSI_EN 0x25B
#define PCIE_MSIX_STATUS 0x25D
#define PCIE_INT_STATUS0 0x25F
#define PCIE_INT_STATUS1 0x260
#define PCIE_INT_EN0 0x261
#define PCIE_INT_EN1 0x262

/* PCIE_MSI_EN */
#define PCIE_MSI_VECTOR_INT_EN 0xFFFFFFFF

/* PCIE_INT_EN0 */
#define PCIE_MSI_INT_EN (1 << 9)
/* other */
#define PCIE_NLINKS 4

/* MSI addresses */
#define MSI_ADDR_BASE 0xfffee00000ULL
#define MSI_ADDR_SZ 0x10000
#define MSI_LINK_ADDR(n, l) (MSI_ADDR_BASE + \
(PCIE_NLINKS * (n) + (l)) * MSI_ADDR_SZ)
#define MSIX_ADDR_BASE 0xfffef00000ULL
#define MSIX_LINK_ADDR(n, l) (MSIX_ADDR_BASE + \
(PCIE_NLINKS * (n) + (l)) * MSI_ADDR_SZ)
#ifndef __ASSEMBLY__

#define nlm_read_pcie_reg(b, r) nlm_read_reg(b, r)
#define nlm_write_pcie_reg(b, r, v) nlm_write_reg(b, r, v)
#define nlm_get_pcie_base(node, inst) \
nlm_pcicfg_base(XLP_IO_PCIE_OFFSET(node, inst))
#define nlm_get_pcie_regbase(node, inst) \
(nlm_get_pcie_base(node, inst) + XLP_IO_PCI_HDRSZ)

int xlp_pcie_link_irt(int link);
#ifdef CONFIG_PCI_MSI
void xlp_init_node_msi_irqs(int node, int link);
#else
static inline void xlp_init_node_msi_irqs(int node, int link) {}
#endif

struct pci_dev *xlp_get_pcie_link(const struct pci_dev *dev);

#endif
#endif /* __NLM_HAL_PCIBUS_H__ */
5 changes: 0 additions & 5 deletions arch/mips/include/asm/netlogic/xlp-hal/pic.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,14 +193,9 @@
#define PIC_IRT_PCIE_LINK_INDEX(num) ((num) + PIC_IRT_PCIE_LINK_0_INDEX)

#define PIC_CLOCK_TIMER 7
#define PIC_IRQ_BASE 8

#if !defined(LOCORE) && !defined(__ASSEMBLY__)

#define PIC_IRT_FIRST_IRQ (PIC_IRQ_BASE)
#define PIC_IRT_LAST_IRQ 63
#define PIC_IRQ_IS_IRT(irq) ((irq) >= PIC_IRT_FIRST_IRQ)

/*
* Misc
*/
Expand Down
24 changes: 20 additions & 4 deletions arch/mips/include/asm/netlogic/xlp-hal/xlp.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,9 @@

#define PIC_UART_0_IRQ 17
#define PIC_UART_1_IRQ 18
#define PIC_PCIE_LINK_0_IRQ 19
#define PIC_PCIE_LINK_1_IRQ 20
#define PIC_PCIE_LINK_2_IRQ 21
#define PIC_PCIE_LINK_3_IRQ 22

#define PIC_PCIE_LINK_LEGACY_IRQ_BASE 19
#define PIC_PCIE_LINK_LEGACY_IRQ(i) (19 + (i))

#define PIC_EHCI_0_IRQ 23
#define PIC_EHCI_1_IRQ 24
Expand All @@ -58,6 +57,23 @@
#define PIC_I2C_2_IRQ 32
#define PIC_I2C_3_IRQ 33

#define PIC_PCIE_LINK_MSI_IRQ_BASE 44 /* 44 - 47 MSI IRQ */
#define PIC_PCIE_LINK_MSI_IRQ(i) (44 + (i))

/* MSI-X with second link-level dispatch */
#define PIC_PCIE_MSIX_IRQ_BASE 48 /* 48 - 51 MSI-X IRQ */
#define PIC_PCIE_MSIX_IRQ(i) (48 + (i))

#define NLM_MSIX_VEC_BASE 96 /* 96 - 127 - MSIX mapped */
#define NLM_MSI_VEC_BASE 128 /* 128 -255 - MSI mapped */

#define NLM_PIC_INDIRECT_VEC_BASE 512
#define NLM_GPIO_VEC_BASE 768

#define PIC_IRQ_BASE 8
#define PIC_IRT_FIRST_IRQ PIC_IRQ_BASE
#define PIC_IRT_LAST_IRQ 63

#ifndef __ASSEMBLY__

/* SMP support functions */
Expand Down
29 changes: 21 additions & 8 deletions arch/mips/netlogic/common/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ static void __init nlm_init_percpu_irqs(void)
#endif
}


void nlm_setup_pic_irq(int node, int picirq, int irq, int irt)
{
struct nlm_pic_irq *pic_data;
Expand Down Expand Up @@ -207,24 +208,24 @@ void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *))

static void nlm_init_node_irqs(int node)
{
int i, irt;
uint64_t irqmask;
struct nlm_soc_info *nodep;
int i, irt;

pr_info("Init IRQ for node %d\n", node);
nodep = nlm_get_node(node);
irqmask = PERCPU_IRQ_MASK;
nodep->irqmask = PERCPU_IRQ_MASK;
for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ; i++) {
irt = nlm_irq_to_irt(i);
if (irt == -1)
if (irt == -1) /* unused irq */
continue;
nlm_setup_pic_irq(node, i, i, irt);
/* set interrupts to first cpu in node */
nodep->irqmask |= 1ull << i;
if (irt == -2) /* not a direct PIC irq */
continue;

nlm_pic_init_irt(nodep->picbase, irt, i,
node * NLM_CPUS_PER_NODE, 0);
irqmask |= (1ull << i);
nlm_setup_pic_irq(node, i, i, irt);
}
nodep->irqmask = irqmask;
}

void nlm_smp_irq_init(int hwcpuid)
Expand Down Expand Up @@ -256,6 +257,18 @@ asmlinkage void plat_irq_dispatch(void)
return;
}

#if defined(CONFIG_PCI_MSI) && defined(CONFIG_CPU_XLP)
/* PCI interrupts need a second level dispatch for MSI bits */
if (i >= PIC_PCIE_LINK_MSI_IRQ(0) && i <= PIC_PCIE_LINK_MSI_IRQ(3)) {
nlm_dispatch_msi(node, i);
return;
}
if (i >= PIC_PCIE_MSIX_IRQ(0) && i <= PIC_PCIE_MSIX_IRQ(3)) {
nlm_dispatch_msix(node, i);
return;
}

#endif
/* top level irq handling */
do_IRQ(nlm_irq_to_xirq(node, i));
}
Expand Down
12 changes: 10 additions & 2 deletions arch/mips/netlogic/xlp/nlm_hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,17 @@ int nlm_irq_to_irt(int irq)
case PIC_I2C_3_IRQ:
irt = irt + 3; break;
}
} else if (irq >= PIC_PCIE_LINK_0_IRQ && irq <= PIC_PCIE_LINK_3_IRQ) {
} else if (irq >= PIC_PCIE_LINK_LEGACY_IRQ(0) &&
irq <= PIC_PCIE_LINK_LEGACY_IRQ(3)) {
/* HW bug, PCI IRT entries are bad on early silicon, fix */
irt = PIC_IRT_PCIE_LINK_INDEX(irq - PIC_PCIE_LINK_0_IRQ);
irt = PIC_IRT_PCIE_LINK_INDEX(irq -
PIC_PCIE_LINK_LEGACY_IRQ_BASE);
} else if (irq >= PIC_PCIE_LINK_MSI_IRQ(0) &&
irq <= PIC_PCIE_LINK_MSI_IRQ(3)) {
irt = -2;
} else if (irq >= PIC_PCIE_MSIX_IRQ(0) &&
irq <= PIC_PCIE_MSIX_IRQ(3)) {
irt = -2;
} else {
irt = -1;
}
Expand Down
1 change: 1 addition & 0 deletions arch/mips/pci/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,5 @@ obj-$(CONFIG_CPU_XLP) += pci-xlp.o

ifdef CONFIG_PCI_MSI
obj-$(CONFIG_CAVIUM_OCTEON_SOC) += msi-octeon.o
obj-$(CONFIG_CPU_XLP) += msi-xlp.o
endif
Loading

0 comments on commit c24a8a7

Please sign in to comment.