162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Actions Semi Owl SoCs SIRQ interrupt controller driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2014 Actions Semi Inc. 662306a36Sopenharmony_ci * David Liu <liuwei@actions-semi.com> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Author: Parthiban Nallathambi <pn@denx.de> 962306a36Sopenharmony_ci * Author: Saravanan Sekar <sravanhome@gmail.com> 1062306a36Sopenharmony_ci * Author: Cristian Ciocaltea <cristian.ciocaltea@gmail.com> 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/bitfield.h> 1462306a36Sopenharmony_ci#include <linux/interrupt.h> 1562306a36Sopenharmony_ci#include <linux/irqchip.h> 1662306a36Sopenharmony_ci#include <linux/of_address.h> 1762306a36Sopenharmony_ci#include <linux/of_irq.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include <dt-bindings/interrupt-controller/arm-gic.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define NUM_SIRQ 3 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define INTC_EXTCTL_PENDING BIT(0) 2462306a36Sopenharmony_ci#define INTC_EXTCTL_CLK_SEL BIT(4) 2562306a36Sopenharmony_ci#define INTC_EXTCTL_EN BIT(5) 2662306a36Sopenharmony_ci#define INTC_EXTCTL_TYPE_MASK GENMASK(7, 6) 2762306a36Sopenharmony_ci#define INTC_EXTCTL_TYPE_HIGH 0 2862306a36Sopenharmony_ci#define INTC_EXTCTL_TYPE_LOW BIT(6) 2962306a36Sopenharmony_ci#define INTC_EXTCTL_TYPE_RISING BIT(7) 3062306a36Sopenharmony_ci#define INTC_EXTCTL_TYPE_FALLING (BIT(6) | BIT(7)) 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* S500 & S700 SIRQ control register masks */ 3362306a36Sopenharmony_ci#define INTC_EXTCTL_SIRQ0_MASK GENMASK(23, 16) 3462306a36Sopenharmony_ci#define INTC_EXTCTL_SIRQ1_MASK GENMASK(15, 8) 3562306a36Sopenharmony_ci#define INTC_EXTCTL_SIRQ2_MASK GENMASK(7, 0) 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* S900 SIRQ control register offsets, relative to controller base address */ 3862306a36Sopenharmony_ci#define INTC_EXTCTL0 0x0000 3962306a36Sopenharmony_ci#define INTC_EXTCTL1 0x0328 4062306a36Sopenharmony_ci#define INTC_EXTCTL2 0x032c 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistruct owl_sirq_params { 4362306a36Sopenharmony_ci /* INTC_EXTCTL reg shared for all three SIRQ lines */ 4462306a36Sopenharmony_ci bool reg_shared; 4562306a36Sopenharmony_ci /* INTC_EXTCTL reg offsets relative to controller base address */ 4662306a36Sopenharmony_ci u16 reg_offset[NUM_SIRQ]; 4762306a36Sopenharmony_ci}; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistruct owl_sirq_chip_data { 5062306a36Sopenharmony_ci const struct owl_sirq_params *params; 5162306a36Sopenharmony_ci void __iomem *base; 5262306a36Sopenharmony_ci raw_spinlock_t lock; 5362306a36Sopenharmony_ci u32 ext_irqs[NUM_SIRQ]; 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* S500 & S700 SoCs */ 5762306a36Sopenharmony_cistatic const struct owl_sirq_params owl_sirq_s500_params = { 5862306a36Sopenharmony_ci .reg_shared = true, 5962306a36Sopenharmony_ci .reg_offset = { 0, 0, 0 }, 6062306a36Sopenharmony_ci}; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci/* S900 SoC */ 6362306a36Sopenharmony_cistatic const struct owl_sirq_params owl_sirq_s900_params = { 6462306a36Sopenharmony_ci .reg_shared = false, 6562306a36Sopenharmony_ci .reg_offset = { INTC_EXTCTL0, INTC_EXTCTL1, INTC_EXTCTL2 }, 6662306a36Sopenharmony_ci}; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic u32 owl_field_get(u32 val, u32 index) 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci switch (index) { 7162306a36Sopenharmony_ci case 0: 7262306a36Sopenharmony_ci return FIELD_GET(INTC_EXTCTL_SIRQ0_MASK, val); 7362306a36Sopenharmony_ci case 1: 7462306a36Sopenharmony_ci return FIELD_GET(INTC_EXTCTL_SIRQ1_MASK, val); 7562306a36Sopenharmony_ci case 2: 7662306a36Sopenharmony_ci default: 7762306a36Sopenharmony_ci return FIELD_GET(INTC_EXTCTL_SIRQ2_MASK, val); 7862306a36Sopenharmony_ci } 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistatic u32 owl_field_prep(u32 val, u32 index) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci switch (index) { 8462306a36Sopenharmony_ci case 0: 8562306a36Sopenharmony_ci return FIELD_PREP(INTC_EXTCTL_SIRQ0_MASK, val); 8662306a36Sopenharmony_ci case 1: 8762306a36Sopenharmony_ci return FIELD_PREP(INTC_EXTCTL_SIRQ1_MASK, val); 8862306a36Sopenharmony_ci case 2: 8962306a36Sopenharmony_ci default: 9062306a36Sopenharmony_ci return FIELD_PREP(INTC_EXTCTL_SIRQ2_MASK, val); 9162306a36Sopenharmony_ci } 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistatic u32 owl_sirq_read_extctl(struct owl_sirq_chip_data *data, u32 index) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci u32 val; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci val = readl_relaxed(data->base + data->params->reg_offset[index]); 9962306a36Sopenharmony_ci if (data->params->reg_shared) 10062306a36Sopenharmony_ci val = owl_field_get(val, index); 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci return val; 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic void owl_sirq_write_extctl(struct owl_sirq_chip_data *data, 10662306a36Sopenharmony_ci u32 extctl, u32 index) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci u32 val; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci if (data->params->reg_shared) { 11162306a36Sopenharmony_ci val = readl_relaxed(data->base + data->params->reg_offset[index]); 11262306a36Sopenharmony_ci val &= ~owl_field_prep(0xff, index); 11362306a36Sopenharmony_ci extctl = owl_field_prep(extctl, index) | val; 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci writel_relaxed(extctl, data->base + data->params->reg_offset[index]); 11762306a36Sopenharmony_ci} 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistatic void owl_sirq_clear_set_extctl(struct owl_sirq_chip_data *d, 12062306a36Sopenharmony_ci u32 clear, u32 set, u32 index) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci unsigned long flags; 12362306a36Sopenharmony_ci u32 val; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci raw_spin_lock_irqsave(&d->lock, flags); 12662306a36Sopenharmony_ci val = owl_sirq_read_extctl(d, index); 12762306a36Sopenharmony_ci val &= ~clear; 12862306a36Sopenharmony_ci val |= set; 12962306a36Sopenharmony_ci owl_sirq_write_extctl(d, val, index); 13062306a36Sopenharmony_ci raw_spin_unlock_irqrestore(&d->lock, flags); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic void owl_sirq_eoi(struct irq_data *data) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci struct owl_sirq_chip_data *chip_data = irq_data_get_irq_chip_data(data); 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci /* 13862306a36Sopenharmony_ci * Software must clear external interrupt pending, when interrupt type 13962306a36Sopenharmony_ci * is edge triggered, so we need per SIRQ based clearing. 14062306a36Sopenharmony_ci */ 14162306a36Sopenharmony_ci if (!irqd_is_level_type(data)) 14262306a36Sopenharmony_ci owl_sirq_clear_set_extctl(chip_data, 0, INTC_EXTCTL_PENDING, 14362306a36Sopenharmony_ci data->hwirq); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci irq_chip_eoi_parent(data); 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_cistatic void owl_sirq_mask(struct irq_data *data) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci struct owl_sirq_chip_data *chip_data = irq_data_get_irq_chip_data(data); 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci owl_sirq_clear_set_extctl(chip_data, INTC_EXTCTL_EN, 0, data->hwirq); 15362306a36Sopenharmony_ci irq_chip_mask_parent(data); 15462306a36Sopenharmony_ci} 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_cistatic void owl_sirq_unmask(struct irq_data *data) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci struct owl_sirq_chip_data *chip_data = irq_data_get_irq_chip_data(data); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci owl_sirq_clear_set_extctl(chip_data, 0, INTC_EXTCTL_EN, data->hwirq); 16162306a36Sopenharmony_ci irq_chip_unmask_parent(data); 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci/* 16562306a36Sopenharmony_ci * GIC does not handle falling edge or active low, hence SIRQ shall be 16662306a36Sopenharmony_ci * programmed to convert falling edge to rising edge signal and active 16762306a36Sopenharmony_ci * low to active high signal. 16862306a36Sopenharmony_ci */ 16962306a36Sopenharmony_cistatic int owl_sirq_set_type(struct irq_data *data, unsigned int type) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci struct owl_sirq_chip_data *chip_data = irq_data_get_irq_chip_data(data); 17262306a36Sopenharmony_ci u32 sirq_type; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci switch (type) { 17562306a36Sopenharmony_ci case IRQ_TYPE_LEVEL_LOW: 17662306a36Sopenharmony_ci sirq_type = INTC_EXTCTL_TYPE_LOW; 17762306a36Sopenharmony_ci type = IRQ_TYPE_LEVEL_HIGH; 17862306a36Sopenharmony_ci break; 17962306a36Sopenharmony_ci case IRQ_TYPE_LEVEL_HIGH: 18062306a36Sopenharmony_ci sirq_type = INTC_EXTCTL_TYPE_HIGH; 18162306a36Sopenharmony_ci break; 18262306a36Sopenharmony_ci case IRQ_TYPE_EDGE_FALLING: 18362306a36Sopenharmony_ci sirq_type = INTC_EXTCTL_TYPE_FALLING; 18462306a36Sopenharmony_ci type = IRQ_TYPE_EDGE_RISING; 18562306a36Sopenharmony_ci break; 18662306a36Sopenharmony_ci case IRQ_TYPE_EDGE_RISING: 18762306a36Sopenharmony_ci sirq_type = INTC_EXTCTL_TYPE_RISING; 18862306a36Sopenharmony_ci break; 18962306a36Sopenharmony_ci default: 19062306a36Sopenharmony_ci return -EINVAL; 19162306a36Sopenharmony_ci } 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci owl_sirq_clear_set_extctl(chip_data, INTC_EXTCTL_TYPE_MASK, sirq_type, 19462306a36Sopenharmony_ci data->hwirq); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci return irq_chip_set_type_parent(data, type); 19762306a36Sopenharmony_ci} 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_cistatic struct irq_chip owl_sirq_chip = { 20062306a36Sopenharmony_ci .name = "owl-sirq", 20162306a36Sopenharmony_ci .irq_mask = owl_sirq_mask, 20262306a36Sopenharmony_ci .irq_unmask = owl_sirq_unmask, 20362306a36Sopenharmony_ci .irq_eoi = owl_sirq_eoi, 20462306a36Sopenharmony_ci .irq_set_type = owl_sirq_set_type, 20562306a36Sopenharmony_ci .irq_retrigger = irq_chip_retrigger_hierarchy, 20662306a36Sopenharmony_ci#ifdef CONFIG_SMP 20762306a36Sopenharmony_ci .irq_set_affinity = irq_chip_set_affinity_parent, 20862306a36Sopenharmony_ci#endif 20962306a36Sopenharmony_ci}; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cistatic int owl_sirq_domain_translate(struct irq_domain *d, 21262306a36Sopenharmony_ci struct irq_fwspec *fwspec, 21362306a36Sopenharmony_ci unsigned long *hwirq, 21462306a36Sopenharmony_ci unsigned int *type) 21562306a36Sopenharmony_ci{ 21662306a36Sopenharmony_ci if (!is_of_node(fwspec->fwnode)) 21762306a36Sopenharmony_ci return -EINVAL; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci if (fwspec->param_count != 2 || fwspec->param[0] >= NUM_SIRQ) 22062306a36Sopenharmony_ci return -EINVAL; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci *hwirq = fwspec->param[0]; 22362306a36Sopenharmony_ci *type = fwspec->param[1]; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci return 0; 22662306a36Sopenharmony_ci} 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_cistatic int owl_sirq_domain_alloc(struct irq_domain *domain, unsigned int virq, 22962306a36Sopenharmony_ci unsigned int nr_irqs, void *data) 23062306a36Sopenharmony_ci{ 23162306a36Sopenharmony_ci struct owl_sirq_chip_data *chip_data = domain->host_data; 23262306a36Sopenharmony_ci struct irq_fwspec *fwspec = data; 23362306a36Sopenharmony_ci struct irq_fwspec parent_fwspec; 23462306a36Sopenharmony_ci irq_hw_number_t hwirq; 23562306a36Sopenharmony_ci unsigned int type; 23662306a36Sopenharmony_ci int ret; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci if (WARN_ON(nr_irqs != 1)) 23962306a36Sopenharmony_ci return -EINVAL; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci ret = owl_sirq_domain_translate(domain, fwspec, &hwirq, &type); 24262306a36Sopenharmony_ci if (ret) 24362306a36Sopenharmony_ci return ret; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci switch (type) { 24662306a36Sopenharmony_ci case IRQ_TYPE_EDGE_RISING: 24762306a36Sopenharmony_ci case IRQ_TYPE_LEVEL_HIGH: 24862306a36Sopenharmony_ci break; 24962306a36Sopenharmony_ci case IRQ_TYPE_EDGE_FALLING: 25062306a36Sopenharmony_ci type = IRQ_TYPE_EDGE_RISING; 25162306a36Sopenharmony_ci break; 25262306a36Sopenharmony_ci case IRQ_TYPE_LEVEL_LOW: 25362306a36Sopenharmony_ci type = IRQ_TYPE_LEVEL_HIGH; 25462306a36Sopenharmony_ci break; 25562306a36Sopenharmony_ci default: 25662306a36Sopenharmony_ci return -EINVAL; 25762306a36Sopenharmony_ci } 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci irq_domain_set_hwirq_and_chip(domain, virq, hwirq, &owl_sirq_chip, 26062306a36Sopenharmony_ci chip_data); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci parent_fwspec.fwnode = domain->parent->fwnode; 26362306a36Sopenharmony_ci parent_fwspec.param_count = 3; 26462306a36Sopenharmony_ci parent_fwspec.param[0] = GIC_SPI; 26562306a36Sopenharmony_ci parent_fwspec.param[1] = chip_data->ext_irqs[hwirq]; 26662306a36Sopenharmony_ci parent_fwspec.param[2] = type; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci return irq_domain_alloc_irqs_parent(domain, virq, 1, &parent_fwspec); 26962306a36Sopenharmony_ci} 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_cistatic const struct irq_domain_ops owl_sirq_domain_ops = { 27262306a36Sopenharmony_ci .translate = owl_sirq_domain_translate, 27362306a36Sopenharmony_ci .alloc = owl_sirq_domain_alloc, 27462306a36Sopenharmony_ci .free = irq_domain_free_irqs_common, 27562306a36Sopenharmony_ci}; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_cistatic int __init owl_sirq_init(const struct owl_sirq_params *params, 27862306a36Sopenharmony_ci struct device_node *node, 27962306a36Sopenharmony_ci struct device_node *parent) 28062306a36Sopenharmony_ci{ 28162306a36Sopenharmony_ci struct irq_domain *domain, *parent_domain; 28262306a36Sopenharmony_ci struct owl_sirq_chip_data *chip_data; 28362306a36Sopenharmony_ci int ret, i; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci parent_domain = irq_find_host(parent); 28662306a36Sopenharmony_ci if (!parent_domain) { 28762306a36Sopenharmony_ci pr_err("%pOF: failed to find sirq parent domain\n", node); 28862306a36Sopenharmony_ci return -ENXIO; 28962306a36Sopenharmony_ci } 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci chip_data = kzalloc(sizeof(*chip_data), GFP_KERNEL); 29262306a36Sopenharmony_ci if (!chip_data) 29362306a36Sopenharmony_ci return -ENOMEM; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci raw_spin_lock_init(&chip_data->lock); 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci chip_data->params = params; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci chip_data->base = of_iomap(node, 0); 30062306a36Sopenharmony_ci if (!chip_data->base) { 30162306a36Sopenharmony_ci pr_err("%pOF: failed to map sirq registers\n", node); 30262306a36Sopenharmony_ci ret = -ENXIO; 30362306a36Sopenharmony_ci goto out_free; 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci for (i = 0; i < NUM_SIRQ; i++) { 30762306a36Sopenharmony_ci struct of_phandle_args irq; 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci ret = of_irq_parse_one(node, i, &irq); 31062306a36Sopenharmony_ci if (ret) { 31162306a36Sopenharmony_ci pr_err("%pOF: failed to parse interrupt %d\n", node, i); 31262306a36Sopenharmony_ci goto out_unmap; 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci if (WARN_ON(irq.args_count != 3)) { 31662306a36Sopenharmony_ci ret = -EINVAL; 31762306a36Sopenharmony_ci goto out_unmap; 31862306a36Sopenharmony_ci } 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci chip_data->ext_irqs[i] = irq.args[1]; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci /* Set 24MHz external interrupt clock freq */ 32362306a36Sopenharmony_ci owl_sirq_clear_set_extctl(chip_data, 0, INTC_EXTCTL_CLK_SEL, i); 32462306a36Sopenharmony_ci } 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci domain = irq_domain_add_hierarchy(parent_domain, 0, NUM_SIRQ, node, 32762306a36Sopenharmony_ci &owl_sirq_domain_ops, chip_data); 32862306a36Sopenharmony_ci if (!domain) { 32962306a36Sopenharmony_ci pr_err("%pOF: failed to add domain\n", node); 33062306a36Sopenharmony_ci ret = -ENOMEM; 33162306a36Sopenharmony_ci goto out_unmap; 33262306a36Sopenharmony_ci } 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci return 0; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ciout_unmap: 33762306a36Sopenharmony_ci iounmap(chip_data->base); 33862306a36Sopenharmony_ciout_free: 33962306a36Sopenharmony_ci kfree(chip_data); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci return ret; 34262306a36Sopenharmony_ci} 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_cistatic int __init owl_sirq_s500_of_init(struct device_node *node, 34562306a36Sopenharmony_ci struct device_node *parent) 34662306a36Sopenharmony_ci{ 34762306a36Sopenharmony_ci return owl_sirq_init(&owl_sirq_s500_params, node, parent); 34862306a36Sopenharmony_ci} 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ciIRQCHIP_DECLARE(owl_sirq_s500, "actions,s500-sirq", owl_sirq_s500_of_init); 35162306a36Sopenharmony_ciIRQCHIP_DECLARE(owl_sirq_s700, "actions,s700-sirq", owl_sirq_s500_of_init); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_cistatic int __init owl_sirq_s900_of_init(struct device_node *node, 35462306a36Sopenharmony_ci struct device_node *parent) 35562306a36Sopenharmony_ci{ 35662306a36Sopenharmony_ci return owl_sirq_init(&owl_sirq_s900_params, node, parent); 35762306a36Sopenharmony_ci} 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ciIRQCHIP_DECLARE(owl_sirq_s900, "actions,s900-sirq", owl_sirq_s900_of_init); 360