^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Handle interrupts from the SRM, assuming no additional weirdness.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "proto.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "irq_impl.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Is the palcode SMP safe? In other words: can we call cserve_ena/dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * at the same time in multiple CPUs? To be safe I added a spinlock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * but it can be removed trivially if the palcode is robust against smp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) DEFINE_SPINLOCK(srm_irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) srm_enable_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) spin_lock(&srm_irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) cserve_ena(d->irq - 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) spin_unlock(&srm_irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) srm_disable_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) spin_lock(&srm_irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) cserve_dis(d->irq - 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) spin_unlock(&srm_irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* Handle interrupts from the SRM, assuming no additional weirdness. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static struct irq_chip srm_irq_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) .name = "SRM",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) .irq_unmask = srm_enable_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .irq_mask = srm_disable_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) .irq_mask_ack = srm_disable_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) void __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) init_srm_irqs(long max, unsigned long ignore_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) long i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (NR_IRQS <= 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) for (i = 16; i < max; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (i < 64 && ((ignore_mask >> i) & 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) irq_set_chip_and_handler(i, &srm_irq_type, handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) irq_set_status_flags(i, IRQ_LEVEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) srm_device_interrupt(unsigned long vector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int irq = (vector - 0x800) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) handle_irq(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }