linux/arch/alpha/kernel/irq_pyxis.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *      linux/arch/alpha/kernel/irq_pyxis.c
   4 *
   5 * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com).
   6 *
   7 * IRQ Code common to all PYXIS core logic chips.
   8 */
   9
  10#include <linux/init.h>
  11#include <linux/sched.h>
  12#include <linux/irq.h>
  13
  14#include <asm/io.h>
  15#include <asm/core_cia.h>
  16
  17#include "proto.h"
  18#include "irq_impl.h"
  19
  20
  21/* Note mask bit is true for ENABLED irqs.  */
  22static unsigned long cached_irq_mask;
  23
  24static inline void
  25pyxis_update_irq_hw(unsigned long mask)
  26{
  27        *(vulp)PYXIS_INT_MASK = mask;
  28        mb();
  29        *(vulp)PYXIS_INT_MASK;
  30}
  31
  32static inline void
  33pyxis_enable_irq(struct irq_data *d)
  34{
  35        pyxis_update_irq_hw(cached_irq_mask |= 1UL << (d->irq - 16));
  36}
  37
  38static void
  39pyxis_disable_irq(struct irq_data *d)
  40{
  41        pyxis_update_irq_hw(cached_irq_mask &= ~(1UL << (d->irq - 16)));
  42}
  43
  44static void
  45pyxis_mask_and_ack_irq(struct irq_data *d)
  46{
  47        unsigned long bit = 1UL << (d->irq - 16);
  48        unsigned long mask = cached_irq_mask &= ~bit;
  49
  50        /* Disable the interrupt.  */
  51        *(vulp)PYXIS_INT_MASK = mask;
  52        wmb();
  53        /* Ack PYXIS PCI interrupt.  */
  54        *(vulp)PYXIS_INT_REQ = bit;
  55        mb();
  56        /* Re-read to force both writes.  */
  57        *(vulp)PYXIS_INT_MASK;
  58}
  59
  60static struct irq_chip pyxis_irq_type = {
  61        .name           = "PYXIS",
  62        .irq_mask_ack   = pyxis_mask_and_ack_irq,
  63        .irq_mask       = pyxis_disable_irq,
  64        .irq_unmask     = pyxis_enable_irq,
  65};
  66
  67void 
  68pyxis_device_interrupt(unsigned long vector)
  69{
  70        unsigned long pld;
  71        unsigned int i;
  72
  73        /* Read the interrupt summary register of PYXIS */
  74        pld = *(vulp)PYXIS_INT_REQ;
  75        pld &= cached_irq_mask;
  76
  77        /*
  78         * Now for every possible bit set, work through them and call
  79         * the appropriate interrupt handler.
  80         */
  81        while (pld) {
  82                i = ffz(~pld);
  83                pld &= pld - 1; /* clear least bit set */
  84                if (i == 7)
  85                        isa_device_interrupt(vector);
  86                else
  87                        handle_irq(16+i);
  88        }
  89}
  90
  91void __init
  92init_pyxis_irqs(unsigned long ignore_mask)
  93{
  94        long i;
  95
  96        *(vulp)PYXIS_INT_MASK = 0;              /* disable all */
  97        *(vulp)PYXIS_INT_REQ  = -1;             /* flush all */
  98        mb();
  99
 100        /* Send -INTA pulses to clear any pending interrupts ...*/
 101        *(vuip) CIA_IACK_SC;
 102
 103        for (i = 16; i < 48; ++i) {
 104                if ((ignore_mask >> i) & 1)
 105                        continue;
 106                irq_set_chip_and_handler(i, &pyxis_irq_type, handle_level_irq);
 107                irq_set_status_flags(i, IRQ_LEVEL);
 108        }
 109
 110        setup_irq(16+7, &isa_cascade_irqaction);
 111}
 112