linux/arch/arm/mach-rpc/irq.c
<<
>>
Prefs
   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}
 227