linux/arch/mips/lasat/interrupt.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Carsten Langgaard, carstenl@mips.com
   4 * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
   5 *
   6 * Routines for generic manipulation of the interrupts found on the
   7 * Lasat boards.
   8 */
   9#include <linux/init.h>
  10#include <linux/interrupt.h>
  11#include <linux/irq.h>
  12
  13#include <asm/irq_cpu.h>
  14#include <asm/lasat/lasat.h>
  15#include <asm/lasat/lasatint.h>
  16
  17#include <irq.h>
  18
  19static volatile int *lasat_int_status;
  20static volatile int *lasat_int_mask;
  21static volatile int lasat_int_mask_shift;
  22
  23void disable_lasat_irq(struct irq_data *d)
  24{
  25        unsigned int irq_nr = d->irq - LASAT_IRQ_BASE;
  26
  27        *lasat_int_mask &= ~(1 << irq_nr) << lasat_int_mask_shift;
  28}
  29
  30void enable_lasat_irq(struct irq_data *d)
  31{
  32        unsigned int irq_nr = d->irq - LASAT_IRQ_BASE;
  33
  34        *lasat_int_mask |= (1 << irq_nr) << lasat_int_mask_shift;
  35}
  36
  37static struct irq_chip lasat_irq_type = {
  38        .name = "Lasat",
  39        .irq_mask = disable_lasat_irq,
  40        .irq_unmask = enable_lasat_irq,
  41};
  42
  43static inline int ls1bit32(unsigned int x)
  44{
  45        int b = 31, s;
  46
  47        s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
  48        s =  8; if (x <<  8 == 0) s = 0; b -= s; x <<= s;
  49        s =  4; if (x <<  4 == 0) s = 0; b -= s; x <<= s;
  50        s =  2; if (x <<  2 == 0) s = 0; b -= s; x <<= s;
  51        s =  1; if (x <<  1 == 0) s = 0; b -= s;
  52
  53        return b;
  54}
  55
  56static unsigned long (*get_int_status)(void);
  57
  58static unsigned long get_int_status_100(void)
  59{
  60        return *lasat_int_status & *lasat_int_mask;
  61}
  62
  63static unsigned long get_int_status_200(void)
  64{
  65        unsigned long int_status;
  66
  67        int_status = *lasat_int_status;
  68        int_status &= (int_status >> LASATINT_MASK_SHIFT_200) & 0xffff;
  69        return int_status;
  70}
  71
  72asmlinkage void plat_irq_dispatch(void)
  73{
  74        unsigned long int_status;
  75        unsigned int cause = read_c0_cause();
  76        int irq;
  77
  78        if (cause & CAUSEF_IP7) {       /* R4000 count / compare IRQ */
  79                do_IRQ(7);
  80                return;
  81        }
  82
  83        int_status = get_int_status();
  84
  85        /* if int_status == 0, then the interrupt has already been cleared */
  86        if (int_status) {
  87                irq = LASAT_IRQ_BASE + ls1bit32(int_status);
  88
  89                do_IRQ(irq);
  90        }
  91}
  92
  93static struct irqaction cascade = {
  94        .handler        = no_action,
  95        .name           = "cascade",
  96        .flags          = IRQF_NO_THREAD,
  97};
  98
  99void __init arch_init_irq(void)
 100{
 101        int i;
 102
 103        if (IS_LASAT_200()) {
 104                lasat_int_status = (void *)LASAT_INT_STATUS_REG_200;
 105                lasat_int_mask = (void *)LASAT_INT_MASK_REG_200;
 106                lasat_int_mask_shift = LASATINT_MASK_SHIFT_200;
 107                get_int_status = get_int_status_200;
 108                *lasat_int_mask &= 0xffff;
 109        } else {
 110                lasat_int_status = (void *)LASAT_INT_STATUS_REG_100;
 111                lasat_int_mask = (void *)LASAT_INT_MASK_REG_100;
 112                lasat_int_mask_shift = LASATINT_MASK_SHIFT_100;
 113                get_int_status = get_int_status_100;
 114                *lasat_int_mask = 0;
 115        }
 116
 117        mips_cpu_irq_init();
 118
 119        for (i = LASAT_IRQ_BASE; i <= LASAT_IRQ_END; i++)
 120                irq_set_chip_and_handler(i, &lasat_irq_type, handle_level_irq);
 121
 122        setup_irq(LASAT_CASCADE_IRQ, &cascade);
 123}
 124