18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Handle interrupts from the SRM, assuming no additional weirdness. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/init.h> 78c2ecf20Sopenharmony_ci#include <linux/sched.h> 88c2ecf20Sopenharmony_ci#include <linux/irq.h> 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include "proto.h" 118c2ecf20Sopenharmony_ci#include "irq_impl.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci/* 158c2ecf20Sopenharmony_ci * Is the palcode SMP safe? In other words: can we call cserve_ena/dis 168c2ecf20Sopenharmony_ci * at the same time in multiple CPUs? To be safe I added a spinlock 178c2ecf20Sopenharmony_ci * but it can be removed trivially if the palcode is robust against smp. 188c2ecf20Sopenharmony_ci */ 198c2ecf20Sopenharmony_ciDEFINE_SPINLOCK(srm_irq_lock); 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistatic inline void 228c2ecf20Sopenharmony_cisrm_enable_irq(struct irq_data *d) 238c2ecf20Sopenharmony_ci{ 248c2ecf20Sopenharmony_ci spin_lock(&srm_irq_lock); 258c2ecf20Sopenharmony_ci cserve_ena(d->irq - 16); 268c2ecf20Sopenharmony_ci spin_unlock(&srm_irq_lock); 278c2ecf20Sopenharmony_ci} 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic void 308c2ecf20Sopenharmony_cisrm_disable_irq(struct irq_data *d) 318c2ecf20Sopenharmony_ci{ 328c2ecf20Sopenharmony_ci spin_lock(&srm_irq_lock); 338c2ecf20Sopenharmony_ci cserve_dis(d->irq - 16); 348c2ecf20Sopenharmony_ci spin_unlock(&srm_irq_lock); 358c2ecf20Sopenharmony_ci} 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci/* Handle interrupts from the SRM, assuming no additional weirdness. */ 388c2ecf20Sopenharmony_cistatic struct irq_chip srm_irq_type = { 398c2ecf20Sopenharmony_ci .name = "SRM", 408c2ecf20Sopenharmony_ci .irq_unmask = srm_enable_irq, 418c2ecf20Sopenharmony_ci .irq_mask = srm_disable_irq, 428c2ecf20Sopenharmony_ci .irq_mask_ack = srm_disable_irq, 438c2ecf20Sopenharmony_ci}; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_civoid __init 468c2ecf20Sopenharmony_ciinit_srm_irqs(long max, unsigned long ignore_mask) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci long i; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci if (NR_IRQS <= 16) 518c2ecf20Sopenharmony_ci return; 528c2ecf20Sopenharmony_ci for (i = 16; i < max; ++i) { 538c2ecf20Sopenharmony_ci if (i < 64 && ((ignore_mask >> i) & 1)) 548c2ecf20Sopenharmony_ci continue; 558c2ecf20Sopenharmony_ci irq_set_chip_and_handler(i, &srm_irq_type, handle_level_irq); 568c2ecf20Sopenharmony_ci irq_set_status_flags(i, IRQ_LEVEL); 578c2ecf20Sopenharmony_ci } 588c2ecf20Sopenharmony_ci} 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_civoid 618c2ecf20Sopenharmony_cisrm_device_interrupt(unsigned long vector) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci int irq = (vector - 0x800) >> 4; 648c2ecf20Sopenharmony_ci handle_irq(irq); 658c2ecf20Sopenharmony_ci} 66