linux/drivers/irqchip/irq-sa11x0.c
<<
>>
Prefs
   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                handle_domain_irq(sa1100_normal_irqdomain,
 144                                ffs(mask) - 1, regs);
 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}
 172