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


      1// SPDX-License-Identifier: GPL-2.0
      2#include <linux/init.h>
      3#include <linux/list.h>
      4#include <linux/io.h>
      5
      6#include <asm/mach/irq.h>
      7#include <asm/hardware/iomd.h>
      8#include <asm/irq.h>
      9#include <asm/fiq.h>
     10
     11// These are offsets from the stat register for each IRQ bank
     12#define STAT	0x00
     13#define REQ	0x04
     14#define CLR	0x04
     15#define MASK	0x08
     16
     17static const u8 irq_prio_h[256] = {
     18	 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10,
     19	12, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10,
     20	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
     21	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
     22	14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10,
     23	14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10,
     24	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
     25	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
     26	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10,
     27	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10,
     28	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
     29	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
     30	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10,
     31	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10,
     32	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
     33	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
     34};
     35
     36static const u8 irq_prio_d[256] = {
     37	 0,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
     38	20,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
     39	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
     40	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
     41	22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
     42	22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
     43	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
     44	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
     45	23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
     46	23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
     47	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
     48	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
     49	22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
     50	22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
     51	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
     52	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
     53};
     54
     55static const u8 irq_prio_l[256] = {
     56	 0, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
     57	 4, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
     58	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
     59	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
     60	 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3,
     61	 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3,
     62	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
     63	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
     64	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
     65	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
     66	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
     67	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
     68	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
     69	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
     70	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
     71	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
     72};
     73
     74static int iomd_get_irq_nr(void)
     75{
     76	int irq;
     77	u8 reg;
     78
     79	/* get highest priority first */
     80	reg = readb(IOC_BASE + IOMD_IRQREQB);
     81	irq = irq_prio_h[reg];
     82	if (irq)
     83		return irq;
     84
     85	/* get DMA  */
     86	reg = readb(IOC_BASE + IOMD_DMAREQ);
     87	irq = irq_prio_d[reg];
     88	if (irq)
     89		return irq;
     90
     91	/* get low priority */
     92	reg = readb(IOC_BASE + IOMD_IRQREQA);
     93	irq = irq_prio_l[reg];
     94	if (irq)
     95		return irq;
     96	return 0;
     97}
     98
     99static void iomd_handle_irq(struct pt_regs *regs)
    100{
    101	int irq;
    102
    103	do {
    104		irq = iomd_get_irq_nr();
    105		if (irq)
    106			generic_handle_irq(irq);
    107	} while (irq);
    108}
    109
    110static void __iomem *iomd_get_base(struct irq_data *d)
    111{
    112	void *cd = irq_data_get_irq_chip_data(d);
    113
    114	return (void __iomem *)(unsigned long)cd;
    115}
    116
    117static void iomd_set_base_mask(unsigned int irq, void __iomem *base, u32 mask)
    118{
    119	struct irq_data *d = irq_get_irq_data(irq);
    120
    121	d->mask = mask;
    122	irq_set_chip_data(irq, (void *)(unsigned long)base);
    123}
    124
    125static void iomd_irq_mask_ack(struct irq_data *d)
    126{
    127	void __iomem *base = iomd_get_base(d);
    128	unsigned int val, mask = d->mask;
    129
    130	val = readb(base + MASK);
    131	writeb(val & ~mask, base + MASK);
    132	writeb(mask, base + CLR);
    133}
    134
    135static void iomd_irq_mask(struct irq_data *d)
    136{
    137	void __iomem *base = iomd_get_base(d);
    138	unsigned int val, mask = d->mask;
    139
    140	val = readb(base + MASK);
    141	writeb(val & ~mask, base + MASK);
    142}
    143
    144static void iomd_irq_unmask(struct irq_data *d)
    145{
    146	void __iomem *base = iomd_get_base(d);
    147	unsigned int val, mask = d->mask;
    148
    149	val = readb(base + MASK);
    150	writeb(val | mask, base + MASK);
    151}
    152
    153static struct irq_chip iomd_chip_clr = {
    154	.irq_mask_ack	= iomd_irq_mask_ack,
    155	.irq_mask	= iomd_irq_mask,
    156	.irq_unmask	= iomd_irq_unmask,
    157};
    158
    159static struct irq_chip iomd_chip_noclr = {
    160	.irq_mask	= iomd_irq_mask,
    161	.irq_unmask	= iomd_irq_unmask,
    162};
    163
    164extern unsigned char rpc_default_fiq_start, rpc_default_fiq_end;
    165
    166void __init rpc_init_irq(void)
    167{
    168	unsigned int irq, clr, set;
    169
    170	iomd_writeb(0, IOMD_IRQMASKA);
    171	iomd_writeb(0, IOMD_IRQMASKB);
    172	iomd_writeb(0, IOMD_FIQMASK);
    173	iomd_writeb(0, IOMD_DMAMASK);
    174
    175	set_fiq_handler(&rpc_default_fiq_start,
    176		&rpc_default_fiq_end - &rpc_default_fiq_start);
    177
    178	set_handle_irq(iomd_handle_irq);
    179
    180	for (irq = 0; irq < NR_IRQS; irq++) {
    181		clr = IRQ_NOREQUEST;
    182		set = 0;
    183
    184		if (irq <= 6 || (irq >= 9 && irq <= 15))
    185			clr |= IRQ_NOPROBE;
    186
    187		if (irq == 21 || (irq >= 16 && irq <= 19) ||
    188		    irq == IRQ_KEYBOARDTX)
    189			set |= IRQ_NOAUTOEN;
    190
    191		switch (irq) {
    192		case 0 ... 7:
    193			irq_set_chip_and_handler(irq, &iomd_chip_clr,
    194						 handle_level_irq);
    195			irq_modify_status(irq, clr, set);
    196			iomd_set_base_mask(irq, IOMD_BASE + IOMD_IRQSTATA,
    197					   BIT(irq));
    198			break;
    199
    200		case 8 ... 15:
    201			irq_set_chip_and_handler(irq, &iomd_chip_noclr,
    202						 handle_level_irq);
    203			irq_modify_status(irq, clr, set);
    204			iomd_set_base_mask(irq, IOMD_BASE + IOMD_IRQSTATB,
    205					   BIT(irq - 8));
    206			break;
    207
    208		case 16 ... 21:
    209			irq_set_chip_and_handler(irq, &iomd_chip_noclr,
    210						 handle_level_irq);
    211			irq_modify_status(irq, clr, set);
    212			iomd_set_base_mask(irq, IOMD_BASE + IOMD_DMASTAT,
    213					   BIT(irq - 16));
    214			break;
    215
    216		case 64 ... 71:
    217			irq_set_chip(irq, &iomd_chip_noclr);
    218			irq_modify_status(irq, clr, set);
    219			iomd_set_base_mask(irq, IOMD_BASE + IOMD_FIQSTAT,
    220					   BIT(irq - 64));
    221			break;
    222		}
    223	}
    224
    225	init_FIQ(FIQ_START);
    226}