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-msc01.c (3707B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *
      4 * Copyright (c) 2004 MIPS Inc
      5 * Author: chris@mips.com
      6 *
      7 * Copyright (C) 2004, 06 Ralf Baechle <ralf@linux-mips.org>
      8 */
      9#include <linux/interrupt.h>
     10#include <linux/kernel.h>
     11#include <linux/sched.h>
     12#include <linux/kernel_stat.h>
     13#include <asm/io.h>
     14#include <asm/irq.h>
     15#include <asm/msc01_ic.h>
     16#include <asm/traps.h>
     17
     18static unsigned long _icctrl_msc;
     19#define MSC01_IC_REG_BASE	_icctrl_msc
     20
     21#define MSCIC_WRITE(reg, data)	do { *(volatile u32 *)(reg) = data; } while (0)
     22#define MSCIC_READ(reg, data)	do { data = *(volatile u32 *)(reg); } while (0)
     23
     24static unsigned int irq_base;
     25
     26/* mask off an interrupt */
     27static inline void mask_msc_irq(struct irq_data *d)
     28{
     29	unsigned int irq = d->irq;
     30
     31	if (irq < (irq_base + 32))
     32		MSCIC_WRITE(MSC01_IC_DISL, 1<<(irq - irq_base));
     33	else
     34		MSCIC_WRITE(MSC01_IC_DISH, 1<<(irq - irq_base - 32));
     35}
     36
     37/* unmask an interrupt */
     38static inline void unmask_msc_irq(struct irq_data *d)
     39{
     40	unsigned int irq = d->irq;
     41
     42	if (irq < (irq_base + 32))
     43		MSCIC_WRITE(MSC01_IC_ENAL, 1<<(irq - irq_base));
     44	else
     45		MSCIC_WRITE(MSC01_IC_ENAH, 1<<(irq - irq_base - 32));
     46}
     47
     48/*
     49 * Masks and ACKs an IRQ
     50 */
     51static void level_mask_and_ack_msc_irq(struct irq_data *d)
     52{
     53	mask_msc_irq(d);
     54	if (!cpu_has_veic)
     55		MSCIC_WRITE(MSC01_IC_EOI, 0);
     56}
     57
     58/*
     59 * Masks and ACKs an IRQ
     60 */
     61static void edge_mask_and_ack_msc_irq(struct irq_data *d)
     62{
     63	unsigned int irq = d->irq;
     64
     65	mask_msc_irq(d);
     66	if (!cpu_has_veic)
     67		MSCIC_WRITE(MSC01_IC_EOI, 0);
     68	else {
     69		u32 r;
     70		MSCIC_READ(MSC01_IC_SUP+irq*8, r);
     71		MSCIC_WRITE(MSC01_IC_SUP+irq*8, r | ~MSC01_IC_SUP_EDGE_BIT);
     72		MSCIC_WRITE(MSC01_IC_SUP+irq*8, r);
     73	}
     74}
     75
     76/*
     77 * Interrupt handler for interrupts coming from SOC-it.
     78 */
     79void ll_msc_irq(void)
     80{
     81	unsigned int irq;
     82
     83	/* read the interrupt vector register */
     84	MSCIC_READ(MSC01_IC_VEC, irq);
     85	if (irq < 64)
     86		do_IRQ(irq + irq_base);
     87	else {
     88		/* Ignore spurious interrupt */
     89	}
     90}
     91
     92static void msc_bind_eic_interrupt(int irq, int set)
     93{
     94	MSCIC_WRITE(MSC01_IC_RAMW,
     95		    (irq<<MSC01_IC_RAMW_ADDR_SHF) | (set<<MSC01_IC_RAMW_DATA_SHF));
     96}
     97
     98static struct irq_chip msc_levelirq_type = {
     99	.name = "SOC-it-Level",
    100	.irq_ack = level_mask_and_ack_msc_irq,
    101	.irq_mask = mask_msc_irq,
    102	.irq_mask_ack = level_mask_and_ack_msc_irq,
    103	.irq_unmask = unmask_msc_irq,
    104	.irq_eoi = unmask_msc_irq,
    105};
    106
    107static struct irq_chip msc_edgeirq_type = {
    108	.name = "SOC-it-Edge",
    109	.irq_ack = edge_mask_and_ack_msc_irq,
    110	.irq_mask = mask_msc_irq,
    111	.irq_mask_ack = edge_mask_and_ack_msc_irq,
    112	.irq_unmask = unmask_msc_irq,
    113	.irq_eoi = unmask_msc_irq,
    114};
    115
    116
    117void __init init_msc_irqs(unsigned long icubase, unsigned int irqbase, msc_irqmap_t *imp, int nirq)
    118{
    119	_icctrl_msc = (unsigned long) ioremap(icubase, 0x40000);
    120
    121	/* Reset interrupt controller - initialises all registers to 0 */
    122	MSCIC_WRITE(MSC01_IC_RST, MSC01_IC_RST_RST_BIT);
    123
    124	board_bind_eic_interrupt = &msc_bind_eic_interrupt;
    125
    126	for (; nirq > 0; nirq--, imp++) {
    127		int n = imp->im_irq;
    128
    129		switch (imp->im_type) {
    130		case MSC01_IRQ_EDGE:
    131			irq_set_chip_and_handler_name(irqbase + n,
    132						      &msc_edgeirq_type,
    133						      handle_edge_irq,
    134						      "edge");
    135			if (cpu_has_veic)
    136				MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT);
    137			else
    138				MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT | imp->im_lvl);
    139			break;
    140		case MSC01_IRQ_LEVEL:
    141			irq_set_chip_and_handler_name(irqbase + n,
    142						      &msc_levelirq_type,
    143						      handle_level_irq,
    144						      "level");
    145			if (cpu_has_veic)
    146				MSCIC_WRITE(MSC01_IC_SUP+n*8, 0);
    147			else
    148				MSCIC_WRITE(MSC01_IC_SUP+n*8, imp->im_lvl);
    149		}
    150	}
    151
    152	irq_base = irqbase;
    153
    154	MSCIC_WRITE(MSC01_IC_GENA, MSC01_IC_GENA_GENA_BIT);	/* Enable interrupt generation */
    155
    156}