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
  93void __init arch_init_irq(void)
  94{
  95        int irq = LASAT_CASCADE_IRQ;
  96        int i;
  97
  98        if (IS_LASAT_200()) {
  99                lasat_int_status = (void *)LASAT_INT_STATUS_REG_200;
 100                lasat_int_mask = (void *)LASAT_INT_MASK_REG_200;
 101                lasat_int_mask_shift = LASATINT_MASK_SHIFT_200;
 102                get_int_status = get_int_status_200;
 103                *lasat_int_mask &= 0xffff;
 104        } else {
 105                lasat_int_status = (void *)LASAT_INT_STATUS_REG_100;
 106                lasat_int_mask = (void *)LASAT_INT_MASK_REG_100;
 107                lasat_int_mask_shift = LASATINT_MASK_SHIFT_100;
 108                get_int_status = get_int_status_100;
 109                *lasat_int_mask = 0;
 110        }
 111
 112        mips_cpu_irq_init();
 113
 114        for (i = LASAT_IRQ_BASE; i <= LASAT_IRQ_END; i++)
 115                irq_set_chip_and_handler(i, &lasat_irq_type, handle_level_irq);
 116
 117        if (request_irq(irq, no_action, IRQF_NO_THREAD, "cascade", NULL))
 118                pr_err("Failed to request irq %d (cascade)\n", irq);
 119}
 120