1
0
Files
kernel-49/arch/mips/tc3262/irq-gic.c
2021-03-11 18:33:13 +03:00

212 lines
8.9 KiB
C

#include <linux/init.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <asm/setup.h>
#include <asm/mips-cm.h>
#include <asm/gic.h>
#include <asm/tc3162/tc3162.h>
#include <asm/tc3162/rt_mmap.h>
#include <asm/tc3162/surfboardint.h>
#include "irq.h"
#define X GIC_UNUSED
static const struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
/* cpu, irqNum - 1, polarity, triggerType, flags, Src Name */
{ 0, CPU_CM_ERR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 0 CPU Coherence Manager Error */
{ 0, CPU_CM_PCINT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 1 CPU CM Perf Cnt overflow */
{ 0, UART_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 2 uart */
{ X, DRAM_PROTECTION - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 3 dram illegal access */
{ 0, TIMER0_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 4 timer 0 */
{ 0, TIMER1_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 5 timer 1 */
{ 0, TIMER2_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 6 timer 2 */
{ 0, IPI_RESCHED_INT0 - 1, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, /* 7 ipi resched 0 */
{ 1, IPI_RESCHED_INT1 - 1, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, /* 8 ipi resched 1 */
{ 0, TIMER5_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 9 timer 3 for wdog */
{ 0, GPIO_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 10 GPIO */
{ 0, PCM1_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 11 PCM 1 */
{ 2, IPI_RESCHED_INT2 - 1, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, /* 12 ipi resched 2 */
{ 3, IPI_RESCHED_INT3 - 1, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, /* 13 ipi resched 3 */
{ 0, GDMA_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 14 GDMA */
{ 0, MAC1_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 15 LAN Giga Switch */
{ 0, UART2_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 16 uart 2 */
{ 0, IRQ_RT3XXX_USB - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 17 USB host */
{ 0, DYINGGASP_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 18 Dying gasp */
{ 0, DMT_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 19 xDSL DMT */
{ 0, GIC_EDGE_NMI - 1, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, /* 20 gic edge NMI */
{ 0, QDMA_LAN0_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 21 QDMA LAN 0 */
{ 0, QDMA_WAN0_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 22 QDMA WAN 0 */
{ 0, PCIE_0_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 23 PCIE port 0 */
{ 0, PCIE_A_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 24 PCIE port 1 */
{ 0, PCIE_SERR_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 25 PCIE error */
{ 0, XPON_MAC_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 26 XPON MAC */
{ 0, XPON_PHY_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 27 XPON PHY */
{ 0, CRYPTO_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 28 Crypto engine */
{ 1, SI_TIMER_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_PERCPU }, /* 29 external CPU timer 1 when bfbf0400[1]=1 */
{ 0, SI_TIMER_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_PERCPU }, /* 30 external CPU timer 0 when bfbf0400[0]=1 */
{ 0, BUS_TOUT_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 31 Pbus timeout */
{ 0, PCM2_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 32 PCM 2 */
{ 0, FE_ERR_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 33 Frame Engine Error */
{ 0, IPI_CALL_INT0 - 1, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, /* 34 ipi call 0 */
{ 0, AUTO_MANUAL_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 35 SPI */
{ 3, SI_TIMER_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_PERCPU }, /* 36 external CPU timer 3 when bfbe0000[1]=1 */
{ 2, SI_TIMER_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_PERCPU }, /* 37 external CPU timer 2 when bfbe0000[1]=1 */
{ 0, UART3_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 38 UART3 */
{ 0, QDMA_LAN1_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 39 QDMA LAN 1 */
{ 0, QDMA_LAN2_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 40 QDMA LAN 2 */
{ 0, QDMA_LAN3_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 41 QDMA LAN 3 */
{ 0, QDMA_WAN1_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 42 QDMA WAN 1 */
{ 0, QDMA_WAN2_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 43 QDMA WAN 2 */
{ 0, QDMA_WAN3_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 44 QDMA WAN 3 */
{ 0, UART4_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 45 UART 4 */
{ 0, UART5_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 46 UART 5 */
{ 0, HSDMA_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 47 High Speed DMA */
{ 0, USB_HOST_2 - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 48 USB host 2 (port1) */
{ 0, XSI_MAC_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 49 XFI/HGSMII MAC interface */
{ 0, XSI_PHY_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 50 XFI/HGSMII PHY interface */
{ 0, WOE0_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 51 WIFI Offload Engine 0 */
{ 0, WOE1_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 52 WIFI Offload Engine 1 */
{ 0, WDMA0_P0_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 53 WIFI DMA 0 port 0 */
{ 0, WDMA0_P1_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 54 WIFI DMA 0 port 1 */
{ 0, WDMA0_WOE_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 55 WIFI DMA 0 for WOE */
{ 0, WDMA1_P0_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 56 WIFI DMA 1 port 0 */
{ 0, WDMA1_P1_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 56 WIFI DMA 1 port 1 */
{ 0, WDMA1_WOE_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 58 WIFI DMA 1 for WOE */
#ifdef CONFIG_ECONET_EN7528
{ 2, RBUS_TOUT_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 59 rbus timeout interrupt */
#else
{ 0, EFUSE_ERR0_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 59 efuse error for not setting key */
#endif
{ 0, EFUSE_ERR1_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 60 efuse error for prev action not finished */
{ 1, IPI_CALL_INT1 - 1, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, /* 61 ipi call 1 */
{ 2, IPI_CALL_INT2 - 1, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, /* 62 ipi call 2 */
{ 3, IPI_CALL_INT3 - 1, GIC_POL_POS, GIC_TRIG_EDGE, 0 } /* 63 ipi call 3 */
};
#undef X
static int get_gic_shared_intr(unsigned int irqNum)
{
int intSrc;
for (intSrc = 0; intSrc < GIC_NUM_INTRS; intSrc++) {
if ((gic_intr_map[intSrc].pin + 1) == irqNum)
return intSrc;
}
return -1;
}
void tc_disable_irq_all(void)
{
unsigned long flags;
if (!gic_present)
return;
local_irq_save(flags);
GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_RMASK_OFS + 0x00), 0xffffffff);
GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_RMASK_OFS + 0x04), 0xffffffff);
local_irq_restore(flags);
}
static irqreturn_t cpu_cm_err_interrupt(int irq, void *dev_id)
{
/* clear CM2 error cause */
VPint(KSEG1ADDR(RALINK_GCMP_BASE) + 0x0048) = 0;
return IRQ_HANDLED;
}
static irqreturn_t cpu_cm_pcint_interrupt(int irq, void *dev_id)
{
/* clear CM2 Performance Counter Overflow Status Register */
VPint(KSEG1ADDR(RALINK_GCMP_BASE) + 0x6120) = 0x7;
return IRQ_HANDLED;
}
static struct irqaction cpu_cm_err_irqaction = {
.handler = cpu_cm_err_interrupt,
.flags = IRQF_NO_THREAD,
.name = "cpu_cm_err",
};
static struct irqaction cpu_cm_pcint_irqaction = {
.handler = cpu_cm_pcint_interrupt,
.flags = IRQF_NO_THREAD,
.name = "cpu_cm_pcint",
};
void __init gic_platform_init(int irqs, struct irq_chip *irq_controller)
{
int i, intSrc;
/* irqVec starts from 1 and ends at 63 */
for (i = 1; i < INTR_SOURCES_NUM; i++)
irq_set_chip(gic_irq_base + i, irq_controller);
/* Initialize IRQ action handlers */
for (i = 1; i < INTR_SOURCES_NUM; i++) {
unsigned int irq;
if (i >= IPI_RESCHED_INT0)
break;
irq = gic_irq_base + i;
if (i == SI_TIMER_INT)
irq_set_handler(irq, handle_percpu_devid_irq);
else if (i == GIC_EDGE_NMI)
irq_set_handler(irq, handle_edge_irq);
else
irq_set_handler(irq, handle_level_irq);
}
/* bind watchdog Intr to CPU1 */
intSrc = get_gic_shared_intr(TIMER5_INT);
if (intSrc >= 0)
GIC_SH_MAP_TO_VPE_SMASK(intSrc, 1);
#ifdef CONFIG_ECONET_EN7528
/* set rbus timeout intr as NMI */
intSrc = get_gic_shared_intr(RBUS_TOUT_INTR);
if (intSrc >= 0)
GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intSrc)), GIC_MAP_TO_NMI_MSK);
#endif
}
void __init arch_init_irq(void)
{
phys_addr_t gic_base = RALINK_GIC_BASE;
/* Disable all hardware interrupts */
clear_c0_status(ST0_IM);
clear_c0_cause(CAUSEF_IP);
if (mips_cm_present()) {
gic_base = read_gcr_gic_base() & ~CM_GCR_GIC_BASE_GICEN_MSK;
write_gcr_gic_base(gic_base | CM_GCR_GIC_BASE_GICEN_MSK);
__sync();
}
gic_present = true;
gic_init(gic_base, RALINK_GIC_ADDRSPACE_SZ, gic_intr_map,
ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
setup_irq(CPU_CM_ERR, &cpu_cm_err_irqaction);
setup_irq(CPU_CM_PCINT, &cpu_cm_pcint_irqaction);
}
asmlinkage void plat_irq_dispatch(void)
{
unsigned int irq = (read_c0_cause() & ST0_IM) >> 10;
do_IRQ(irq);
}