cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

irq.c (5403B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
      4 */
      5
      6#include <linux/interrupt.h>
      7#include <linux/irq.h>
      8#include <asm/irq_cpu.h>
      9
     10#include <loongson1.h>
     11#include <irq.h>
     12
     13#define LS1X_INTC_REG(n, x) \
     14		((void __iomem *)KSEG1ADDR(LS1X_INTC_BASE + (n * 0x18) + (x)))
     15
     16#define LS1X_INTC_INTISR(n)		LS1X_INTC_REG(n, 0x0)
     17#define LS1X_INTC_INTIEN(n)		LS1X_INTC_REG(n, 0x4)
     18#define LS1X_INTC_INTSET(n)		LS1X_INTC_REG(n, 0x8)
     19#define LS1X_INTC_INTCLR(n)		LS1X_INTC_REG(n, 0xc)
     20#define LS1X_INTC_INTPOL(n)		LS1X_INTC_REG(n, 0x10)
     21#define LS1X_INTC_INTEDGE(n)		LS1X_INTC_REG(n, 0x14)
     22
     23static void ls1x_irq_ack(struct irq_data *d)
     24{
     25	unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
     26	unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
     27
     28	__raw_writel(__raw_readl(LS1X_INTC_INTCLR(n))
     29			| (1 << bit), LS1X_INTC_INTCLR(n));
     30}
     31
     32static void ls1x_irq_mask(struct irq_data *d)
     33{
     34	unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
     35	unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
     36
     37	__raw_writel(__raw_readl(LS1X_INTC_INTIEN(n))
     38			& ~(1 << bit), LS1X_INTC_INTIEN(n));
     39}
     40
     41static void ls1x_irq_mask_ack(struct irq_data *d)
     42{
     43	unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
     44	unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
     45
     46	__raw_writel(__raw_readl(LS1X_INTC_INTIEN(n))
     47			& ~(1 << bit), LS1X_INTC_INTIEN(n));
     48	__raw_writel(__raw_readl(LS1X_INTC_INTCLR(n))
     49			| (1 << bit), LS1X_INTC_INTCLR(n));
     50}
     51
     52static void ls1x_irq_unmask(struct irq_data *d)
     53{
     54	unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
     55	unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
     56
     57	__raw_writel(__raw_readl(LS1X_INTC_INTIEN(n))
     58			| (1 << bit), LS1X_INTC_INTIEN(n));
     59}
     60
     61static int ls1x_irq_settype(struct irq_data *d, unsigned int type)
     62{
     63	unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
     64	unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
     65
     66	switch (type) {
     67	case IRQ_TYPE_LEVEL_HIGH:
     68		__raw_writel(__raw_readl(LS1X_INTC_INTPOL(n))
     69			| (1 << bit), LS1X_INTC_INTPOL(n));
     70		__raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n))
     71			& ~(1 << bit), LS1X_INTC_INTEDGE(n));
     72		break;
     73	case IRQ_TYPE_LEVEL_LOW:
     74		__raw_writel(__raw_readl(LS1X_INTC_INTPOL(n))
     75			& ~(1 << bit), LS1X_INTC_INTPOL(n));
     76		__raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n))
     77			& ~(1 << bit), LS1X_INTC_INTEDGE(n));
     78		break;
     79	case IRQ_TYPE_EDGE_RISING:
     80		__raw_writel(__raw_readl(LS1X_INTC_INTPOL(n))
     81			| (1 << bit), LS1X_INTC_INTPOL(n));
     82		__raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n))
     83			| (1 << bit), LS1X_INTC_INTEDGE(n));
     84		break;
     85	case IRQ_TYPE_EDGE_FALLING:
     86		__raw_writel(__raw_readl(LS1X_INTC_INTPOL(n))
     87			& ~(1 << bit), LS1X_INTC_INTPOL(n));
     88		__raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n))
     89			| (1 << bit), LS1X_INTC_INTEDGE(n));
     90		break;
     91	case IRQ_TYPE_EDGE_BOTH:
     92		__raw_writel(__raw_readl(LS1X_INTC_INTPOL(n))
     93			& ~(1 << bit), LS1X_INTC_INTPOL(n));
     94		__raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n))
     95			| (1 << bit), LS1X_INTC_INTEDGE(n));
     96		break;
     97	case IRQ_TYPE_NONE:
     98		break;
     99	default:
    100		return -EINVAL;
    101	}
    102
    103	return 0;
    104}
    105
    106static struct irq_chip ls1x_irq_chip = {
    107	.name		= "LS1X-INTC",
    108	.irq_ack	= ls1x_irq_ack,
    109	.irq_mask	= ls1x_irq_mask,
    110	.irq_mask_ack	= ls1x_irq_mask_ack,
    111	.irq_unmask	= ls1x_irq_unmask,
    112	.irq_set_type   = ls1x_irq_settype,
    113};
    114
    115static void ls1x_irq_dispatch(int n)
    116{
    117	u32 int_status, irq;
    118
    119	/* Get pending sources, masked by current enables */
    120	int_status = __raw_readl(LS1X_INTC_INTISR(n)) &
    121			__raw_readl(LS1X_INTC_INTIEN(n));
    122
    123	if (int_status) {
    124		irq = LS1X_IRQ(n, __ffs(int_status));
    125		do_IRQ(irq);
    126	}
    127}
    128
    129asmlinkage void plat_irq_dispatch(void)
    130{
    131	unsigned int pending;
    132
    133	pending = read_c0_cause() & read_c0_status() & ST0_IM;
    134
    135	if (pending & CAUSEF_IP7)
    136		do_IRQ(TIMER_IRQ);
    137	else if (pending & CAUSEF_IP2)
    138		ls1x_irq_dispatch(0); /* INT0 */
    139	else if (pending & CAUSEF_IP3)
    140		ls1x_irq_dispatch(1); /* INT1 */
    141	else if (pending & CAUSEF_IP4)
    142		ls1x_irq_dispatch(2); /* INT2 */
    143	else if (pending & CAUSEF_IP5)
    144		ls1x_irq_dispatch(3); /* INT3 */
    145	else if (pending & CAUSEF_IP6)
    146		ls1x_irq_dispatch(4); /* INT4 */
    147	else
    148		spurious_interrupt();
    149
    150}
    151
    152static void __init ls1x_irq_init(int base)
    153{
    154	int n;
    155
    156	/* Disable interrupts and clear pending,
    157	 * setup all IRQs as high level triggered
    158	 */
    159	for (n = 0; n < INTN; n++) {
    160		__raw_writel(0x0, LS1X_INTC_INTIEN(n));
    161		__raw_writel(0xffffffff, LS1X_INTC_INTCLR(n));
    162		__raw_writel(0xffffffff, LS1X_INTC_INTPOL(n));
    163		/* set DMA0, DMA1 and DMA2 to edge trigger */
    164		__raw_writel(n ? 0x0 : 0xe000, LS1X_INTC_INTEDGE(n));
    165	}
    166
    167
    168	for (n = base; n < NR_IRQS; n++) {
    169		irq_set_chip_and_handler(n, &ls1x_irq_chip,
    170					 handle_level_irq);
    171	}
    172
    173	if (request_irq(INT0_IRQ, no_action, IRQF_NO_THREAD, "cascade", NULL))
    174		pr_err("Failed to request irq %d (cascade)\n", INT0_IRQ);
    175	if (request_irq(INT1_IRQ, no_action, IRQF_NO_THREAD, "cascade", NULL))
    176		pr_err("Failed to request irq %d (cascade)\n", INT1_IRQ);
    177	if (request_irq(INT2_IRQ, no_action, IRQF_NO_THREAD, "cascade", NULL))
    178		pr_err("Failed to request irq %d (cascade)\n", INT2_IRQ);
    179	if (request_irq(INT3_IRQ, no_action, IRQF_NO_THREAD, "cascade", NULL))
    180		pr_err("Failed to request irq %d (cascade)\n", INT3_IRQ);
    181#if defined(CONFIG_LOONGSON1_LS1C)
    182	if (request_irq(INT4_IRQ, no_action, IRQF_NO_THREAD, "cascade", NULL))
    183		pr_err("Failed to request irq %d (cascade)\n", INT4_IRQ);
    184#endif
    185}
    186
    187void __init arch_init_irq(void)
    188{
    189	mips_cpu_irq_init();
    190	ls1x_irq_init(LS1X_IRQ_BASE);
    191}