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

intc.c (3514B)


      1/*
      2 * intc.c  -- support for the old ColdFire interrupt controller
      3 *
      4 * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
      5 *
      6 * This file is subject to the terms and conditions of the GNU General Public
      7 * License.  See the file COPYING in the main directory of this archive
      8 * for more details.
      9 */
     10
     11#include <linux/types.h>
     12#include <linux/init.h>
     13#include <linux/kernel.h>
     14#include <linux/interrupt.h>
     15#include <linux/irq.h>
     16#include <linux/io.h>
     17#include <asm/traps.h>
     18#include <asm/coldfire.h>
     19#include <asm/mcfsim.h>
     20
     21/*
     22 * The mapping of irq number to a mask register bit is not one-to-one.
     23 * The irq numbers are either based on "level" of interrupt or fixed
     24 * for an autovector-able interrupt. So we keep a local data structure
     25 * that maps from irq to mask register. Not all interrupts will have
     26 * an IMR bit.
     27 */
     28unsigned char mcf_irq2imr[NR_IRQS];
     29
     30/*
     31 * Define the minimum and maximum external interrupt numbers.
     32 * This is also used as the "level" interrupt numbers.
     33 */
     34#define	EIRQ1	25
     35#define	EIRQ7	31
     36
     37/*
     38 * In the early version 2 core ColdFire parts the IMR register was 16 bits
     39 * in size. Version 3 (and later version 2) core parts have a 32 bit
     40 * sized IMR register. Provide some size independent methods to access the
     41 * IMR register.
     42 */
     43#ifdef MCFSIM_IMR_IS_16BITS
     44
     45void mcf_setimr(int index)
     46{
     47	u16 imr;
     48	imr = __raw_readw(MCFSIM_IMR);
     49	__raw_writew(imr | (0x1 << index), MCFSIM_IMR);
     50}
     51
     52void mcf_clrimr(int index)
     53{
     54	u16 imr;
     55	imr = __raw_readw(MCFSIM_IMR);
     56	__raw_writew(imr & ~(0x1 << index), MCFSIM_IMR);
     57}
     58
     59void mcf_maskimr(unsigned int mask)
     60{
     61	u16 imr;
     62	imr = __raw_readw(MCFSIM_IMR);
     63	imr |= mask;
     64	__raw_writew(imr, MCFSIM_IMR);
     65}
     66
     67#else
     68
     69void mcf_setimr(int index)
     70{
     71	u32 imr;
     72	imr = __raw_readl(MCFSIM_IMR);
     73	__raw_writel(imr | (0x1 << index), MCFSIM_IMR);
     74}
     75
     76void mcf_clrimr(int index)
     77{
     78	u32 imr;
     79	imr = __raw_readl(MCFSIM_IMR);
     80	__raw_writel(imr & ~(0x1 << index), MCFSIM_IMR);
     81}
     82
     83void mcf_maskimr(unsigned int mask)
     84{
     85	u32 imr;
     86	imr = __raw_readl(MCFSIM_IMR);
     87	imr |= mask;
     88	__raw_writel(imr, MCFSIM_IMR);
     89}
     90
     91#endif
     92
     93/*
     94 * Interrupts can be "vectored" on the ColdFire cores that support this old
     95 * interrupt controller. That is, the device raising the interrupt can also
     96 * supply the vector number to interrupt through. The AVR register of the
     97 * interrupt controller enables or disables this for each external interrupt,
     98 * so provide generic support for this. Setting this up is out-of-band for
     99 * the interrupt system API's, and needs to be done by the driver that
    100 * supports this device. Very few devices actually use this.
    101 */
    102void mcf_autovector(int irq)
    103{
    104#ifdef MCFSIM_AVR
    105	if ((irq >= EIRQ1) && (irq <= EIRQ7)) {
    106		u8 avec;
    107		avec = __raw_readb(MCFSIM_AVR);
    108		avec |= (0x1 << (irq - EIRQ1 + 1));
    109		__raw_writeb(avec, MCFSIM_AVR);
    110	}
    111#endif
    112}
    113
    114static void intc_irq_mask(struct irq_data *d)
    115{
    116	if (mcf_irq2imr[d->irq])
    117		mcf_setimr(mcf_irq2imr[d->irq]);
    118}
    119
    120static void intc_irq_unmask(struct irq_data *d)
    121{
    122	if (mcf_irq2imr[d->irq])
    123		mcf_clrimr(mcf_irq2imr[d->irq]);
    124}
    125
    126static int intc_irq_set_type(struct irq_data *d, unsigned int type)
    127{
    128	return 0;
    129}
    130
    131static struct irq_chip intc_irq_chip = {
    132	.name		= "CF-INTC",
    133	.irq_mask	= intc_irq_mask,
    134	.irq_unmask	= intc_irq_unmask,
    135	.irq_set_type	= intc_irq_set_type,
    136};
    137
    138void __init init_IRQ(void)
    139{
    140	int irq;
    141
    142	mcf_maskimr(0xffffffff);
    143
    144	for (irq = 0; (irq < NR_IRQS); irq++) {
    145		irq_set_chip(irq, &intc_irq_chip);
    146		irq_set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
    147		irq_set_handler(irq, handle_level_irq);
    148	}
    149}
    150