18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * ip30-irq.c: Highlevel interrupt handling for IP30 architecture. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci#include <linux/errno.h> 68c2ecf20Sopenharmony_ci#include <linux/init.h> 78c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 88c2ecf20Sopenharmony_ci#include <linux/irq.h> 98c2ecf20Sopenharmony_ci#include <linux/percpu.h> 108c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 118c2ecf20Sopenharmony_ci#include <linux/tick.h> 128c2ecf20Sopenharmony_ci#include <linux/types.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <asm/irq_cpu.h> 158c2ecf20Sopenharmony_ci#include <asm/sgi/heart.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include "ip30-common.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistruct heart_irq_data { 208c2ecf20Sopenharmony_ci u64 *irq_mask; 218c2ecf20Sopenharmony_ci int cpu; 228c2ecf20Sopenharmony_ci}; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistatic DECLARE_BITMAP(heart_irq_map, HEART_NUM_IRQS); 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic DEFINE_PER_CPU(unsigned long, irq_enable_mask); 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic inline int heart_alloc_int(void) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci int bit; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ciagain: 338c2ecf20Sopenharmony_ci bit = find_first_zero_bit(heart_irq_map, HEART_NUM_IRQS); 348c2ecf20Sopenharmony_ci if (bit >= HEART_NUM_IRQS) 358c2ecf20Sopenharmony_ci return -ENOSPC; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci if (test_and_set_bit(bit, heart_irq_map)) 388c2ecf20Sopenharmony_ci goto again; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci return bit; 418c2ecf20Sopenharmony_ci} 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cistatic void ip30_error_irq(struct irq_desc *desc) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci u64 pending, mask, cause, error_irqs, err_reg; 468c2ecf20Sopenharmony_ci int cpu = smp_processor_id(); 478c2ecf20Sopenharmony_ci int i; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci pending = heart_read(&heart_regs->isr); 508c2ecf20Sopenharmony_ci mask = heart_read(&heart_regs->imr[cpu]); 518c2ecf20Sopenharmony_ci cause = heart_read(&heart_regs->cause); 528c2ecf20Sopenharmony_ci error_irqs = (pending & HEART_L4_INT_MASK & mask); 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci /* Bail if there's nothing to process (how did we get here, then?) */ 558c2ecf20Sopenharmony_ci if (unlikely(!error_irqs)) 568c2ecf20Sopenharmony_ci return; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci /* Prevent any of the error IRQs from firing again. */ 598c2ecf20Sopenharmony_ci heart_write(mask & ~(pending), &heart_regs->imr[cpu]); 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci /* Ack all error IRQs. */ 628c2ecf20Sopenharmony_ci heart_write(HEART_L4_INT_MASK, &heart_regs->clear_isr); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci /* 658c2ecf20Sopenharmony_ci * If we also have a cause value, then something happened, so loop 668c2ecf20Sopenharmony_ci * through the error IRQs and report a "heart attack" for each one 678c2ecf20Sopenharmony_ci * and print the value of the HEART cause register. This is really 688c2ecf20Sopenharmony_ci * primitive right now, but it should hopefully work until a more 698c2ecf20Sopenharmony_ci * robust error handling routine can be put together. 708c2ecf20Sopenharmony_ci * 718c2ecf20Sopenharmony_ci * Refer to heart.h for the HC_* macros to work out the cause 728c2ecf20Sopenharmony_ci * that got us here. 738c2ecf20Sopenharmony_ci */ 748c2ecf20Sopenharmony_ci if (cause) { 758c2ecf20Sopenharmony_ci pr_alert("IP30: CPU%d: HEART ATTACK! ISR = 0x%.16llx, IMR = 0x%.16llx, CAUSE = 0x%.16llx\n", 768c2ecf20Sopenharmony_ci cpu, pending, mask, cause); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci if (cause & HC_COR_MEM_ERR) { 798c2ecf20Sopenharmony_ci err_reg = heart_read(&heart_regs->mem_err_addr); 808c2ecf20Sopenharmony_ci pr_alert(" HEART_MEMERR_ADDR = 0x%.16llx\n", err_reg); 818c2ecf20Sopenharmony_ci } 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci /* i = 63; i >= 51; i-- */ 848c2ecf20Sopenharmony_ci for (i = HEART_ERR_MASK_END; i >= HEART_ERR_MASK_START; i--) 858c2ecf20Sopenharmony_ci if ((pending >> i) & 1) 868c2ecf20Sopenharmony_ci pr_alert(" HEART Error IRQ #%d\n", i); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci /* XXX: Seems possible to loop forever here, so panic(). */ 898c2ecf20Sopenharmony_ci panic("IP30: Fatal Error !\n"); 908c2ecf20Sopenharmony_ci } 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci /* Unmask the error IRQs. */ 938c2ecf20Sopenharmony_ci heart_write(mask, &heart_regs->imr[cpu]); 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic void ip30_normal_irq(struct irq_desc *desc) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci int cpu = smp_processor_id(); 998c2ecf20Sopenharmony_ci struct irq_domain *domain; 1008c2ecf20Sopenharmony_ci u64 pend, mask; 1018c2ecf20Sopenharmony_ci int irq; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci pend = heart_read(&heart_regs->isr); 1048c2ecf20Sopenharmony_ci mask = (heart_read(&heart_regs->imr[cpu]) & 1058c2ecf20Sopenharmony_ci (HEART_L0_INT_MASK | HEART_L1_INT_MASK | HEART_L2_INT_MASK)); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci pend &= mask; 1088c2ecf20Sopenharmony_ci if (unlikely(!pend)) 1098c2ecf20Sopenharmony_ci return; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 1128c2ecf20Sopenharmony_ci if (pend & BIT_ULL(HEART_L2_INT_RESCHED_CPU_0)) { 1138c2ecf20Sopenharmony_ci heart_write(BIT_ULL(HEART_L2_INT_RESCHED_CPU_0), 1148c2ecf20Sopenharmony_ci &heart_regs->clear_isr); 1158c2ecf20Sopenharmony_ci scheduler_ipi(); 1168c2ecf20Sopenharmony_ci } else if (pend & BIT_ULL(HEART_L2_INT_RESCHED_CPU_1)) { 1178c2ecf20Sopenharmony_ci heart_write(BIT_ULL(HEART_L2_INT_RESCHED_CPU_1), 1188c2ecf20Sopenharmony_ci &heart_regs->clear_isr); 1198c2ecf20Sopenharmony_ci scheduler_ipi(); 1208c2ecf20Sopenharmony_ci } else if (pend & BIT_ULL(HEART_L2_INT_CALL_CPU_0)) { 1218c2ecf20Sopenharmony_ci heart_write(BIT_ULL(HEART_L2_INT_CALL_CPU_0), 1228c2ecf20Sopenharmony_ci &heart_regs->clear_isr); 1238c2ecf20Sopenharmony_ci generic_smp_call_function_interrupt(); 1248c2ecf20Sopenharmony_ci } else if (pend & BIT_ULL(HEART_L2_INT_CALL_CPU_1)) { 1258c2ecf20Sopenharmony_ci heart_write(BIT_ULL(HEART_L2_INT_CALL_CPU_1), 1268c2ecf20Sopenharmony_ci &heart_regs->clear_isr); 1278c2ecf20Sopenharmony_ci generic_smp_call_function_interrupt(); 1288c2ecf20Sopenharmony_ci } else 1298c2ecf20Sopenharmony_ci#endif 1308c2ecf20Sopenharmony_ci { 1318c2ecf20Sopenharmony_ci domain = irq_desc_get_handler_data(desc); 1328c2ecf20Sopenharmony_ci irq = irq_linear_revmap(domain, __ffs(pend)); 1338c2ecf20Sopenharmony_ci if (irq) 1348c2ecf20Sopenharmony_ci generic_handle_irq(irq); 1358c2ecf20Sopenharmony_ci else 1368c2ecf20Sopenharmony_ci spurious_interrupt(); 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistatic void ip30_ack_heart_irq(struct irq_data *d) 1418c2ecf20Sopenharmony_ci{ 1428c2ecf20Sopenharmony_ci heart_write(BIT_ULL(d->hwirq), &heart_regs->clear_isr); 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cistatic void ip30_mask_heart_irq(struct irq_data *d) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci struct heart_irq_data *hd = irq_data_get_irq_chip_data(d); 1488c2ecf20Sopenharmony_ci unsigned long *mask = &per_cpu(irq_enable_mask, hd->cpu); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci clear_bit(d->hwirq, mask); 1518c2ecf20Sopenharmony_ci heart_write(*mask, &heart_regs->imr[hd->cpu]); 1528c2ecf20Sopenharmony_ci} 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_cistatic void ip30_mask_and_ack_heart_irq(struct irq_data *d) 1558c2ecf20Sopenharmony_ci{ 1568c2ecf20Sopenharmony_ci struct heart_irq_data *hd = irq_data_get_irq_chip_data(d); 1578c2ecf20Sopenharmony_ci unsigned long *mask = &per_cpu(irq_enable_mask, hd->cpu); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci clear_bit(d->hwirq, mask); 1608c2ecf20Sopenharmony_ci heart_write(*mask, &heart_regs->imr[hd->cpu]); 1618c2ecf20Sopenharmony_ci heart_write(BIT_ULL(d->hwirq), &heart_regs->clear_isr); 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistatic void ip30_unmask_heart_irq(struct irq_data *d) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci struct heart_irq_data *hd = irq_data_get_irq_chip_data(d); 1678c2ecf20Sopenharmony_ci unsigned long *mask = &per_cpu(irq_enable_mask, hd->cpu); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci set_bit(d->hwirq, mask); 1708c2ecf20Sopenharmony_ci heart_write(*mask, &heart_regs->imr[hd->cpu]); 1718c2ecf20Sopenharmony_ci} 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_cistatic int ip30_set_heart_irq_affinity(struct irq_data *d, 1748c2ecf20Sopenharmony_ci const struct cpumask *mask, bool force) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci struct heart_irq_data *hd = irq_data_get_irq_chip_data(d); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci if (!hd) 1798c2ecf20Sopenharmony_ci return -EINVAL; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci if (irqd_is_started(d)) 1828c2ecf20Sopenharmony_ci ip30_mask_and_ack_heart_irq(d); 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci hd->cpu = cpumask_first_and(mask, cpu_online_mask); 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci if (irqd_is_started(d)) 1878c2ecf20Sopenharmony_ci ip30_unmask_heart_irq(d); 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci irq_data_update_effective_affinity(d, cpumask_of(hd->cpu)); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci return 0; 1928c2ecf20Sopenharmony_ci} 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_cistatic struct irq_chip heart_irq_chip = { 1958c2ecf20Sopenharmony_ci .name = "HEART", 1968c2ecf20Sopenharmony_ci .irq_ack = ip30_ack_heart_irq, 1978c2ecf20Sopenharmony_ci .irq_mask = ip30_mask_heart_irq, 1988c2ecf20Sopenharmony_ci .irq_mask_ack = ip30_mask_and_ack_heart_irq, 1998c2ecf20Sopenharmony_ci .irq_unmask = ip30_unmask_heart_irq, 2008c2ecf20Sopenharmony_ci .irq_set_affinity = ip30_set_heart_irq_affinity, 2018c2ecf20Sopenharmony_ci}; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cistatic int heart_domain_alloc(struct irq_domain *domain, unsigned int virq, 2048c2ecf20Sopenharmony_ci unsigned int nr_irqs, void *arg) 2058c2ecf20Sopenharmony_ci{ 2068c2ecf20Sopenharmony_ci struct irq_alloc_info *info = arg; 2078c2ecf20Sopenharmony_ci struct heart_irq_data *hd; 2088c2ecf20Sopenharmony_ci int hwirq; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci if (nr_irqs > 1 || !info) 2118c2ecf20Sopenharmony_ci return -EINVAL; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci hd = kzalloc(sizeof(*hd), GFP_KERNEL); 2148c2ecf20Sopenharmony_ci if (!hd) 2158c2ecf20Sopenharmony_ci return -ENOMEM; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci hwirq = heart_alloc_int(); 2188c2ecf20Sopenharmony_ci if (hwirq < 0) { 2198c2ecf20Sopenharmony_ci kfree(hd); 2208c2ecf20Sopenharmony_ci return -EAGAIN; 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci irq_domain_set_info(domain, virq, hwirq, &heart_irq_chip, hd, 2238c2ecf20Sopenharmony_ci handle_level_irq, NULL, NULL); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci return 0; 2268c2ecf20Sopenharmony_ci} 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_cistatic void heart_domain_free(struct irq_domain *domain, 2298c2ecf20Sopenharmony_ci unsigned int virq, unsigned int nr_irqs) 2308c2ecf20Sopenharmony_ci{ 2318c2ecf20Sopenharmony_ci struct irq_data *irqd; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci if (nr_irqs > 1) 2348c2ecf20Sopenharmony_ci return; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci irqd = irq_domain_get_irq_data(domain, virq); 2378c2ecf20Sopenharmony_ci if (irqd) { 2388c2ecf20Sopenharmony_ci clear_bit(irqd->hwirq, heart_irq_map); 2398c2ecf20Sopenharmony_ci kfree(irqd->chip_data); 2408c2ecf20Sopenharmony_ci } 2418c2ecf20Sopenharmony_ci} 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_cistatic const struct irq_domain_ops heart_domain_ops = { 2448c2ecf20Sopenharmony_ci .alloc = heart_domain_alloc, 2458c2ecf20Sopenharmony_ci .free = heart_domain_free, 2468c2ecf20Sopenharmony_ci}; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_civoid __init ip30_install_ipi(void) 2498c2ecf20Sopenharmony_ci{ 2508c2ecf20Sopenharmony_ci int cpu = smp_processor_id(); 2518c2ecf20Sopenharmony_ci unsigned long *mask = &per_cpu(irq_enable_mask, cpu); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci set_bit(HEART_L2_INT_RESCHED_CPU_0 + cpu, mask); 2548c2ecf20Sopenharmony_ci heart_write(BIT_ULL(HEART_L2_INT_RESCHED_CPU_0 + cpu), 2558c2ecf20Sopenharmony_ci &heart_regs->clear_isr); 2568c2ecf20Sopenharmony_ci set_bit(HEART_L2_INT_CALL_CPU_0 + cpu, mask); 2578c2ecf20Sopenharmony_ci heart_write(BIT_ULL(HEART_L2_INT_CALL_CPU_0 + cpu), 2588c2ecf20Sopenharmony_ci &heart_regs->clear_isr); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci heart_write(*mask, &heart_regs->imr[cpu]); 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_civoid __init arch_init_irq(void) 2648c2ecf20Sopenharmony_ci{ 2658c2ecf20Sopenharmony_ci struct irq_domain *domain; 2668c2ecf20Sopenharmony_ci struct fwnode_handle *fn; 2678c2ecf20Sopenharmony_ci unsigned long *mask; 2688c2ecf20Sopenharmony_ci int i; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci mips_cpu_irq_init(); 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci /* Mask all IRQs. */ 2738c2ecf20Sopenharmony_ci heart_write(HEART_CLR_ALL_MASK, &heart_regs->imr[0]); 2748c2ecf20Sopenharmony_ci heart_write(HEART_CLR_ALL_MASK, &heart_regs->imr[1]); 2758c2ecf20Sopenharmony_ci heart_write(HEART_CLR_ALL_MASK, &heart_regs->imr[2]); 2768c2ecf20Sopenharmony_ci heart_write(HEART_CLR_ALL_MASK, &heart_regs->imr[3]); 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci /* Ack everything. */ 2798c2ecf20Sopenharmony_ci heart_write(HEART_ACK_ALL_MASK, &heart_regs->clear_isr); 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci /* Enable specific HEART error IRQs for each CPU. */ 2828c2ecf20Sopenharmony_ci mask = &per_cpu(irq_enable_mask, 0); 2838c2ecf20Sopenharmony_ci *mask |= HEART_CPU0_ERR_MASK; 2848c2ecf20Sopenharmony_ci heart_write(*mask, &heart_regs->imr[0]); 2858c2ecf20Sopenharmony_ci mask = &per_cpu(irq_enable_mask, 1); 2868c2ecf20Sopenharmony_ci *mask |= HEART_CPU1_ERR_MASK; 2878c2ecf20Sopenharmony_ci heart_write(*mask, &heart_regs->imr[1]); 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci /* 2908c2ecf20Sopenharmony_ci * Some HEART bits are reserved by hardware or by software convention. 2918c2ecf20Sopenharmony_ci * Mark these as reserved right away so they won't be accidentally 2928c2ecf20Sopenharmony_ci * used later. 2938c2ecf20Sopenharmony_ci */ 2948c2ecf20Sopenharmony_ci set_bit(HEART_L0_INT_GENERIC, heart_irq_map); 2958c2ecf20Sopenharmony_ci set_bit(HEART_L0_INT_FLOW_CTRL_HWTR_0, heart_irq_map); 2968c2ecf20Sopenharmony_ci set_bit(HEART_L0_INT_FLOW_CTRL_HWTR_1, heart_irq_map); 2978c2ecf20Sopenharmony_ci set_bit(HEART_L2_INT_RESCHED_CPU_0, heart_irq_map); 2988c2ecf20Sopenharmony_ci set_bit(HEART_L2_INT_RESCHED_CPU_1, heart_irq_map); 2998c2ecf20Sopenharmony_ci set_bit(HEART_L2_INT_CALL_CPU_0, heart_irq_map); 3008c2ecf20Sopenharmony_ci set_bit(HEART_L2_INT_CALL_CPU_1, heart_irq_map); 3018c2ecf20Sopenharmony_ci set_bit(HEART_L3_INT_TIMER, heart_irq_map); 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci /* Reserve the error interrupts (#51 to #63). */ 3048c2ecf20Sopenharmony_ci for (i = HEART_L4_INT_XWID_ERR_9; i <= HEART_L4_INT_HEART_EXCP; i++) 3058c2ecf20Sopenharmony_ci set_bit(i, heart_irq_map); 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci fn = irq_domain_alloc_named_fwnode("HEART"); 3088c2ecf20Sopenharmony_ci WARN_ON(fn == NULL); 3098c2ecf20Sopenharmony_ci if (!fn) 3108c2ecf20Sopenharmony_ci return; 3118c2ecf20Sopenharmony_ci domain = irq_domain_create_linear(fn, HEART_NUM_IRQS, 3128c2ecf20Sopenharmony_ci &heart_domain_ops, NULL); 3138c2ecf20Sopenharmony_ci WARN_ON(domain == NULL); 3148c2ecf20Sopenharmony_ci if (!domain) 3158c2ecf20Sopenharmony_ci return; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci irq_set_default_host(domain); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci irq_set_percpu_devid(IP30_HEART_L0_IRQ); 3208c2ecf20Sopenharmony_ci irq_set_chained_handler_and_data(IP30_HEART_L0_IRQ, ip30_normal_irq, 3218c2ecf20Sopenharmony_ci domain); 3228c2ecf20Sopenharmony_ci irq_set_percpu_devid(IP30_HEART_L1_IRQ); 3238c2ecf20Sopenharmony_ci irq_set_chained_handler_and_data(IP30_HEART_L1_IRQ, ip30_normal_irq, 3248c2ecf20Sopenharmony_ci domain); 3258c2ecf20Sopenharmony_ci irq_set_percpu_devid(IP30_HEART_L2_IRQ); 3268c2ecf20Sopenharmony_ci irq_set_chained_handler_and_data(IP30_HEART_L2_IRQ, ip30_normal_irq, 3278c2ecf20Sopenharmony_ci domain); 3288c2ecf20Sopenharmony_ci irq_set_percpu_devid(IP30_HEART_ERR_IRQ); 3298c2ecf20Sopenharmony_ci irq_set_chained_handler_and_data(IP30_HEART_ERR_IRQ, ip30_error_irq, 3308c2ecf20Sopenharmony_ci domain); 3318c2ecf20Sopenharmony_ci} 332