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 (4042B)


      1/*
      2 * This file is subject to the terms and conditions of the GNU General Public
      3 * License.  See the file "COPYING" in the main directory of this archive
      4 * for more details.
      5 *
      6 * Copyright (C) 1992 Linus Torvalds
      7 * Copyright (C) 1994 - 2001, 2003, 07 Ralf Baechle
      8 */
      9#include <linux/clockchips.h>
     10#include <linux/i8253.h>
     11#include <linux/init.h>
     12#include <linux/interrupt.h>
     13#include <linux/kernel.h>
     14#include <linux/smp.h>
     15#include <linux/spinlock.h>
     16#include <linux/irq.h>
     17#include <linux/pgtable.h>
     18
     19#include <asm/irq_cpu.h>
     20#include <asm/i8259.h>
     21#include <asm/io.h>
     22#include <asm/jazz.h>
     23#include <asm/tlbmisc.h>
     24
     25static DEFINE_RAW_SPINLOCK(r4030_lock);
     26
     27static void enable_r4030_irq(struct irq_data *d)
     28{
     29	unsigned int mask = 1 << (d->irq - JAZZ_IRQ_START);
     30	unsigned long flags;
     31
     32	raw_spin_lock_irqsave(&r4030_lock, flags);
     33	mask |= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE);
     34	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask);
     35	raw_spin_unlock_irqrestore(&r4030_lock, flags);
     36}
     37
     38void disable_r4030_irq(struct irq_data *d)
     39{
     40	unsigned int mask = ~(1 << (d->irq - JAZZ_IRQ_START));
     41	unsigned long flags;
     42
     43	raw_spin_lock_irqsave(&r4030_lock, flags);
     44	mask &= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE);
     45	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask);
     46	raw_spin_unlock_irqrestore(&r4030_lock, flags);
     47}
     48
     49static struct irq_chip r4030_irq_type = {
     50	.name = "R4030",
     51	.irq_mask = disable_r4030_irq,
     52	.irq_unmask = enable_r4030_irq,
     53};
     54
     55void __init init_r4030_ints(void)
     56{
     57	int i;
     58
     59	for (i = JAZZ_IRQ_START; i <= JAZZ_IRQ_END; i++)
     60		irq_set_chip_and_handler(i, &r4030_irq_type, handle_level_irq);
     61
     62	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 0);
     63	r4030_read_reg16(JAZZ_IO_IRQ_SOURCE);		/* clear pending IRQs */
     64	r4030_read_reg32(JAZZ_R4030_INVAL_ADDR);	/* clear error bits */
     65}
     66
     67/*
     68 * On systems with i8259-style interrupt controllers we assume for
     69 * driver compatibility reasons interrupts 0 - 15 to be the i8259
     70 * interrupts even if the hardware uses a different interrupt numbering.
     71 */
     72void __init arch_init_irq(void)
     73{
     74	/*
     75	 * this is a hack to get back the still needed wired mapping
     76	 * killed by init_mm()
     77	 */
     78
     79	/* Map 0xe0000000 -> 0x0:800005C0, 0xe0010000 -> 0x1:30000580 */
     80	add_wired_entry(0x02000017, 0x03c00017, 0xe0000000, PM_64K);
     81	/* Map 0xe2000000 -> 0x0:900005C0, 0xe3010000 -> 0x0:910005C0 */
     82	add_wired_entry(0x02400017, 0x02440017, 0xe2000000, PM_16M);
     83	/* Map 0xe4000000 -> 0x0:600005C0, 0xe4100000 -> 400005C0 */
     84	add_wired_entry(0x01800017, 0x01000017, 0xe4000000, PM_4M);
     85
     86	init_i8259_irqs();			/* Integrated i8259  */
     87	mips_cpu_irq_init();
     88	init_r4030_ints();
     89
     90	change_c0_status(ST0_IM, IE_IRQ2 | IE_IRQ1);
     91}
     92
     93asmlinkage void plat_irq_dispatch(void)
     94{
     95	unsigned int pending = read_c0_cause() & read_c0_status();
     96	unsigned int irq;
     97
     98	if (pending & IE_IRQ4) {
     99		r4030_read_reg32(JAZZ_TIMER_REGISTER);
    100		do_IRQ(JAZZ_TIMER_IRQ);
    101	} else if (pending & IE_IRQ2) {
    102		irq = *(volatile u8 *)JAZZ_EISA_IRQ_ACK;
    103		do_IRQ(irq);
    104	} else if (pending & IE_IRQ1) {
    105		irq = *(volatile u8 *)JAZZ_IO_IRQ_SOURCE >> 2;
    106		if (likely(irq > 0))
    107			do_IRQ(irq + JAZZ_IRQ_START - 1);
    108		else
    109			panic("Unimplemented loc_no_irq handler");
    110	}
    111}
    112
    113struct clock_event_device r4030_clockevent = {
    114	.name		= "r4030",
    115	.features	= CLOCK_EVT_FEAT_PERIODIC,
    116	.rating		= 300,
    117	.irq		= JAZZ_TIMER_IRQ,
    118};
    119
    120static irqreturn_t r4030_timer_interrupt(int irq, void *dev_id)
    121{
    122	struct clock_event_device *cd = dev_id;
    123
    124	cd->event_handler(cd);
    125	return IRQ_HANDLED;
    126}
    127
    128void __init plat_time_init(void)
    129{
    130	struct clock_event_device *cd = &r4030_clockevent;
    131	unsigned int cpu = smp_processor_id();
    132
    133	BUG_ON(HZ != 100);
    134
    135	cd->cpumask		= cpumask_of(cpu);
    136	clockevents_register_device(cd);
    137	if (request_irq(JAZZ_TIMER_IRQ, r4030_timer_interrupt, IRQF_TIMER,
    138			"R4030 timer", cd))
    139		pr_err("Failed to register R4030 timer interrupt\n");
    140
    141	/*
    142	 * Set clock to 100Hz.
    143	 *
    144	 * The R4030 timer receives an input clock of 1kHz which is divided by
    145	 * a programmable 4-bit divider.  This makes it fairly inflexible.
    146	 */
    147	r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9);
    148	setup_pit_timer();
    149}