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-sa11x0.c (3844B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2015 Dmitry Eremin-Solenikov
      4 * Copyright (C) 1999-2001 Nicolas Pitre
      5 *
      6 * Generic IRQ handling for the SA11x0.
      7 */
      8#include <linux/init.h>
      9#include <linux/module.h>
     10#include <linux/interrupt.h>
     11#include <linux/io.h>
     12#include <linux/irq.h>
     13#include <linux/irqdomain.h>
     14#include <linux/syscore_ops.h>
     15#include <linux/irqchip/irq-sa11x0.h>
     16
     17#include <soc/sa1100/pwer.h>
     18
     19#include <asm/exception.h>
     20
     21#define ICIP	0x00  /* IC IRQ Pending reg. */
     22#define ICMR	0x04  /* IC Mask Reg.        */
     23#define ICLR	0x08  /* IC Level Reg.       */
     24#define ICCR	0x0C  /* IC Control Reg.     */
     25#define ICFP	0x10  /* IC FIQ Pending reg. */
     26#define ICPR	0x20  /* IC Pending Reg.     */
     27
     28static void __iomem *iobase;
     29
     30/*
     31 * We don't need to ACK IRQs on the SA1100 unless they're GPIOs
     32 * this is for internal IRQs i.e. from IRQ LCD to RTCAlrm.
     33 */
     34static void sa1100_mask_irq(struct irq_data *d)
     35{
     36	u32 reg;
     37
     38	reg = readl_relaxed(iobase + ICMR);
     39	reg &= ~BIT(d->hwirq);
     40	writel_relaxed(reg, iobase + ICMR);
     41}
     42
     43static void sa1100_unmask_irq(struct irq_data *d)
     44{
     45	u32 reg;
     46
     47	reg = readl_relaxed(iobase + ICMR);
     48	reg |= BIT(d->hwirq);
     49	writel_relaxed(reg, iobase + ICMR);
     50}
     51
     52static int sa1100_set_wake(struct irq_data *d, unsigned int on)
     53{
     54	return sa11x0_sc_set_wake(d->hwirq, on);
     55}
     56
     57static struct irq_chip sa1100_normal_chip = {
     58	.name		= "SC",
     59	.irq_ack	= sa1100_mask_irq,
     60	.irq_mask	= sa1100_mask_irq,
     61	.irq_unmask	= sa1100_unmask_irq,
     62	.irq_set_wake	= sa1100_set_wake,
     63};
     64
     65static int sa1100_normal_irqdomain_map(struct irq_domain *d,
     66		unsigned int irq, irq_hw_number_t hwirq)
     67{
     68	irq_set_chip_and_handler(irq, &sa1100_normal_chip,
     69				 handle_level_irq);
     70
     71	return 0;
     72}
     73
     74static const struct irq_domain_ops sa1100_normal_irqdomain_ops = {
     75	.map = sa1100_normal_irqdomain_map,
     76	.xlate = irq_domain_xlate_onetwocell,
     77};
     78
     79static struct irq_domain *sa1100_normal_irqdomain;
     80
     81static struct sa1100irq_state {
     82	unsigned int	saved;
     83	unsigned int	icmr;
     84	unsigned int	iclr;
     85	unsigned int	iccr;
     86} sa1100irq_state;
     87
     88static int sa1100irq_suspend(void)
     89{
     90	struct sa1100irq_state *st = &sa1100irq_state;
     91
     92	st->saved = 1;
     93	st->icmr = readl_relaxed(iobase + ICMR);
     94	st->iclr = readl_relaxed(iobase + ICLR);
     95	st->iccr = readl_relaxed(iobase + ICCR);
     96
     97	/*
     98	 * Disable all GPIO-based interrupts.
     99	 */
    100	writel_relaxed(st->icmr & 0xfffff000, iobase + ICMR);
    101
    102	return 0;
    103}
    104
    105static void sa1100irq_resume(void)
    106{
    107	struct sa1100irq_state *st = &sa1100irq_state;
    108
    109	if (st->saved) {
    110		writel_relaxed(st->iccr, iobase + ICCR);
    111		writel_relaxed(st->iclr, iobase + ICLR);
    112
    113		writel_relaxed(st->icmr, iobase + ICMR);
    114	}
    115}
    116
    117static struct syscore_ops sa1100irq_syscore_ops = {
    118	.suspend	= sa1100irq_suspend,
    119	.resume		= sa1100irq_resume,
    120};
    121
    122static int __init sa1100irq_init_devicefs(void)
    123{
    124	register_syscore_ops(&sa1100irq_syscore_ops);
    125	return 0;
    126}
    127
    128device_initcall(sa1100irq_init_devicefs);
    129
    130static asmlinkage void __exception_irq_entry
    131sa1100_handle_irq(struct pt_regs *regs)
    132{
    133	uint32_t icip, icmr, mask;
    134
    135	do {
    136		icip = readl_relaxed(iobase + ICIP);
    137		icmr = readl_relaxed(iobase + ICMR);
    138		mask = icip & icmr;
    139
    140		if (mask == 0)
    141			break;
    142
    143		generic_handle_domain_irq(sa1100_normal_irqdomain,
    144					  ffs(mask) - 1);
    145	} while (1);
    146}
    147
    148void __init sa11x0_init_irq_nodt(int irq_start, resource_size_t io_start)
    149{
    150	iobase = ioremap(io_start, SZ_64K);
    151	if (WARN_ON(!iobase))
    152		return;
    153
    154	/* disable all IRQs */
    155	writel_relaxed(0, iobase + ICMR);
    156
    157	/* all IRQs are IRQ, not FIQ */
    158	writel_relaxed(0, iobase + ICLR);
    159
    160	/*
    161	 * Whatever the doc says, this has to be set for the wait-on-irq
    162	 * instruction to work... on a SA1100 rev 9 at least.
    163	 */
    164	writel_relaxed(1, iobase + ICCR);
    165
    166	sa1100_normal_irqdomain = irq_domain_add_simple(NULL,
    167			32, irq_start,
    168			&sa1100_normal_irqdomain_ops, NULL);
    169
    170	set_handle_irq(sa1100_handle_irq);
    171}