1*27e9e554SCristian Ciocaltea // SPDX-License-Identifier: GPL-2.0+ 2*27e9e554SCristian Ciocaltea /* 3*27e9e554SCristian Ciocaltea * Actions Semi Owl SoCs SIRQ interrupt controller driver 4*27e9e554SCristian Ciocaltea * 5*27e9e554SCristian Ciocaltea * Copyright (C) 2014 Actions Semi Inc. 6*27e9e554SCristian Ciocaltea * David Liu <liuwei@actions-semi.com> 7*27e9e554SCristian Ciocaltea * 8*27e9e554SCristian Ciocaltea * Author: Parthiban Nallathambi <pn@denx.de> 9*27e9e554SCristian Ciocaltea * Author: Saravanan Sekar <sravanhome@gmail.com> 10*27e9e554SCristian Ciocaltea * Author: Cristian Ciocaltea <cristian.ciocaltea@gmail.com> 11*27e9e554SCristian Ciocaltea */ 12*27e9e554SCristian Ciocaltea 13*27e9e554SCristian Ciocaltea #include <linux/bitfield.h> 14*27e9e554SCristian Ciocaltea #include <linux/interrupt.h> 15*27e9e554SCristian Ciocaltea #include <linux/irqchip.h> 16*27e9e554SCristian Ciocaltea #include <linux/of_address.h> 17*27e9e554SCristian Ciocaltea #include <linux/of_irq.h> 18*27e9e554SCristian Ciocaltea 19*27e9e554SCristian Ciocaltea #include <dt-bindings/interrupt-controller/arm-gic.h> 20*27e9e554SCristian Ciocaltea 21*27e9e554SCristian Ciocaltea #define NUM_SIRQ 3 22*27e9e554SCristian Ciocaltea 23*27e9e554SCristian Ciocaltea #define INTC_EXTCTL_PENDING BIT(0) 24*27e9e554SCristian Ciocaltea #define INTC_EXTCTL_CLK_SEL BIT(4) 25*27e9e554SCristian Ciocaltea #define INTC_EXTCTL_EN BIT(5) 26*27e9e554SCristian Ciocaltea #define INTC_EXTCTL_TYPE_MASK GENMASK(7, 6) 27*27e9e554SCristian Ciocaltea #define INTC_EXTCTL_TYPE_HIGH 0 28*27e9e554SCristian Ciocaltea #define INTC_EXTCTL_TYPE_LOW BIT(6) 29*27e9e554SCristian Ciocaltea #define INTC_EXTCTL_TYPE_RISING BIT(7) 30*27e9e554SCristian Ciocaltea #define INTC_EXTCTL_TYPE_FALLING (BIT(6) | BIT(7)) 31*27e9e554SCristian Ciocaltea 32*27e9e554SCristian Ciocaltea /* S500 & S700 SIRQ control register masks */ 33*27e9e554SCristian Ciocaltea #define INTC_EXTCTL_SIRQ0_MASK GENMASK(23, 16) 34*27e9e554SCristian Ciocaltea #define INTC_EXTCTL_SIRQ1_MASK GENMASK(15, 8) 35*27e9e554SCristian Ciocaltea #define INTC_EXTCTL_SIRQ2_MASK GENMASK(7, 0) 36*27e9e554SCristian Ciocaltea 37*27e9e554SCristian Ciocaltea /* S900 SIRQ control register offsets, relative to controller base address */ 38*27e9e554SCristian Ciocaltea #define INTC_EXTCTL0 0x0000 39*27e9e554SCristian Ciocaltea #define INTC_EXTCTL1 0x0328 40*27e9e554SCristian Ciocaltea #define INTC_EXTCTL2 0x032c 41*27e9e554SCristian Ciocaltea 42*27e9e554SCristian Ciocaltea struct owl_sirq_params { 43*27e9e554SCristian Ciocaltea /* INTC_EXTCTL reg shared for all three SIRQ lines */ 44*27e9e554SCristian Ciocaltea bool reg_shared; 45*27e9e554SCristian Ciocaltea /* INTC_EXTCTL reg offsets relative to controller base address */ 46*27e9e554SCristian Ciocaltea u16 reg_offset[NUM_SIRQ]; 47*27e9e554SCristian Ciocaltea }; 48*27e9e554SCristian Ciocaltea 49*27e9e554SCristian Ciocaltea struct owl_sirq_chip_data { 50*27e9e554SCristian Ciocaltea const struct owl_sirq_params *params; 51*27e9e554SCristian Ciocaltea void __iomem *base; 52*27e9e554SCristian Ciocaltea raw_spinlock_t lock; 53*27e9e554SCristian Ciocaltea u32 ext_irqs[NUM_SIRQ]; 54*27e9e554SCristian Ciocaltea }; 55*27e9e554SCristian Ciocaltea 56*27e9e554SCristian Ciocaltea /* S500 & S700 SoCs */ 57*27e9e554SCristian Ciocaltea static const struct owl_sirq_params owl_sirq_s500_params = { 58*27e9e554SCristian Ciocaltea .reg_shared = true, 59*27e9e554SCristian Ciocaltea .reg_offset = { 0, 0, 0 }, 60*27e9e554SCristian Ciocaltea }; 61*27e9e554SCristian Ciocaltea 62*27e9e554SCristian Ciocaltea /* S900 SoC */ 63*27e9e554SCristian Ciocaltea static const struct owl_sirq_params owl_sirq_s900_params = { 64*27e9e554SCristian Ciocaltea .reg_shared = false, 65*27e9e554SCristian Ciocaltea .reg_offset = { INTC_EXTCTL0, INTC_EXTCTL1, INTC_EXTCTL2 }, 66*27e9e554SCristian Ciocaltea }; 67*27e9e554SCristian Ciocaltea 68*27e9e554SCristian Ciocaltea static u32 owl_field_get(u32 val, u32 index) 69*27e9e554SCristian Ciocaltea { 70*27e9e554SCristian Ciocaltea switch (index) { 71*27e9e554SCristian Ciocaltea case 0: 72*27e9e554SCristian Ciocaltea return FIELD_GET(INTC_EXTCTL_SIRQ0_MASK, val); 73*27e9e554SCristian Ciocaltea case 1: 74*27e9e554SCristian Ciocaltea return FIELD_GET(INTC_EXTCTL_SIRQ1_MASK, val); 75*27e9e554SCristian Ciocaltea case 2: 76*27e9e554SCristian Ciocaltea default: 77*27e9e554SCristian Ciocaltea return FIELD_GET(INTC_EXTCTL_SIRQ2_MASK, val); 78*27e9e554SCristian Ciocaltea } 79*27e9e554SCristian Ciocaltea } 80*27e9e554SCristian Ciocaltea 81*27e9e554SCristian Ciocaltea static u32 owl_field_prep(u32 val, u32 index) 82*27e9e554SCristian Ciocaltea { 83*27e9e554SCristian Ciocaltea switch (index) { 84*27e9e554SCristian Ciocaltea case 0: 85*27e9e554SCristian Ciocaltea return FIELD_PREP(INTC_EXTCTL_SIRQ0_MASK, val); 86*27e9e554SCristian Ciocaltea case 1: 87*27e9e554SCristian Ciocaltea return FIELD_PREP(INTC_EXTCTL_SIRQ1_MASK, val); 88*27e9e554SCristian Ciocaltea case 2: 89*27e9e554SCristian Ciocaltea default: 90*27e9e554SCristian Ciocaltea return FIELD_PREP(INTC_EXTCTL_SIRQ2_MASK, val); 91*27e9e554SCristian Ciocaltea } 92*27e9e554SCristian Ciocaltea } 93*27e9e554SCristian Ciocaltea 94*27e9e554SCristian Ciocaltea static u32 owl_sirq_read_extctl(struct owl_sirq_chip_data *data, u32 index) 95*27e9e554SCristian Ciocaltea { 96*27e9e554SCristian Ciocaltea u32 val; 97*27e9e554SCristian Ciocaltea 98*27e9e554SCristian Ciocaltea val = readl_relaxed(data->base + data->params->reg_offset[index]); 99*27e9e554SCristian Ciocaltea if (data->params->reg_shared) 100*27e9e554SCristian Ciocaltea val = owl_field_get(val, index); 101*27e9e554SCristian Ciocaltea 102*27e9e554SCristian Ciocaltea return val; 103*27e9e554SCristian Ciocaltea } 104*27e9e554SCristian Ciocaltea 105*27e9e554SCristian Ciocaltea static void owl_sirq_write_extctl(struct owl_sirq_chip_data *data, 106*27e9e554SCristian Ciocaltea u32 extctl, u32 index) 107*27e9e554SCristian Ciocaltea { 108*27e9e554SCristian Ciocaltea u32 val; 109*27e9e554SCristian Ciocaltea 110*27e9e554SCristian Ciocaltea if (data->params->reg_shared) { 111*27e9e554SCristian Ciocaltea val = readl_relaxed(data->base + data->params->reg_offset[index]); 112*27e9e554SCristian Ciocaltea val &= ~owl_field_prep(0xff, index); 113*27e9e554SCristian Ciocaltea extctl = owl_field_prep(extctl, index) | val; 114*27e9e554SCristian Ciocaltea } 115*27e9e554SCristian Ciocaltea 116*27e9e554SCristian Ciocaltea writel_relaxed(extctl, data->base + data->params->reg_offset[index]); 117*27e9e554SCristian Ciocaltea } 118*27e9e554SCristian Ciocaltea 119*27e9e554SCristian Ciocaltea static void owl_sirq_clear_set_extctl(struct owl_sirq_chip_data *d, 120*27e9e554SCristian Ciocaltea u32 clear, u32 set, u32 index) 121*27e9e554SCristian Ciocaltea { 122*27e9e554SCristian Ciocaltea unsigned long flags; 123*27e9e554SCristian Ciocaltea u32 val; 124*27e9e554SCristian Ciocaltea 125*27e9e554SCristian Ciocaltea raw_spin_lock_irqsave(&d->lock, flags); 126*27e9e554SCristian Ciocaltea val = owl_sirq_read_extctl(d, index); 127*27e9e554SCristian Ciocaltea val &= ~clear; 128*27e9e554SCristian Ciocaltea val |= set; 129*27e9e554SCristian Ciocaltea owl_sirq_write_extctl(d, val, index); 130*27e9e554SCristian Ciocaltea raw_spin_unlock_irqrestore(&d->lock, flags); 131*27e9e554SCristian Ciocaltea } 132*27e9e554SCristian Ciocaltea 133*27e9e554SCristian Ciocaltea static void owl_sirq_eoi(struct irq_data *data) 134*27e9e554SCristian Ciocaltea { 135*27e9e554SCristian Ciocaltea struct owl_sirq_chip_data *chip_data = irq_data_get_irq_chip_data(data); 136*27e9e554SCristian Ciocaltea 137*27e9e554SCristian Ciocaltea /* 138*27e9e554SCristian Ciocaltea * Software must clear external interrupt pending, when interrupt type 139*27e9e554SCristian Ciocaltea * is edge triggered, so we need per SIRQ based clearing. 140*27e9e554SCristian Ciocaltea */ 141*27e9e554SCristian Ciocaltea if (!irqd_is_level_type(data)) 142*27e9e554SCristian Ciocaltea owl_sirq_clear_set_extctl(chip_data, 0, INTC_EXTCTL_PENDING, 143*27e9e554SCristian Ciocaltea data->hwirq); 144*27e9e554SCristian Ciocaltea 145*27e9e554SCristian Ciocaltea irq_chip_eoi_parent(data); 146*27e9e554SCristian Ciocaltea } 147*27e9e554SCristian Ciocaltea 148*27e9e554SCristian Ciocaltea static void owl_sirq_mask(struct irq_data *data) 149*27e9e554SCristian Ciocaltea { 150*27e9e554SCristian Ciocaltea struct owl_sirq_chip_data *chip_data = irq_data_get_irq_chip_data(data); 151*27e9e554SCristian Ciocaltea 152*27e9e554SCristian Ciocaltea owl_sirq_clear_set_extctl(chip_data, INTC_EXTCTL_EN, 0, data->hwirq); 153*27e9e554SCristian Ciocaltea irq_chip_mask_parent(data); 154*27e9e554SCristian Ciocaltea } 155*27e9e554SCristian Ciocaltea 156*27e9e554SCristian Ciocaltea static void owl_sirq_unmask(struct irq_data *data) 157*27e9e554SCristian Ciocaltea { 158*27e9e554SCristian Ciocaltea struct owl_sirq_chip_data *chip_data = irq_data_get_irq_chip_data(data); 159*27e9e554SCristian Ciocaltea 160*27e9e554SCristian Ciocaltea owl_sirq_clear_set_extctl(chip_data, 0, INTC_EXTCTL_EN, data->hwirq); 161*27e9e554SCristian Ciocaltea irq_chip_unmask_parent(data); 162*27e9e554SCristian Ciocaltea } 163*27e9e554SCristian Ciocaltea 164*27e9e554SCristian Ciocaltea /* 165*27e9e554SCristian Ciocaltea * GIC does not handle falling edge or active low, hence SIRQ shall be 166*27e9e554SCristian Ciocaltea * programmed to convert falling edge to rising edge signal and active 167*27e9e554SCristian Ciocaltea * low to active high signal. 168*27e9e554SCristian Ciocaltea */ 169*27e9e554SCristian Ciocaltea static int owl_sirq_set_type(struct irq_data *data, unsigned int type) 170*27e9e554SCristian Ciocaltea { 171*27e9e554SCristian Ciocaltea struct owl_sirq_chip_data *chip_data = irq_data_get_irq_chip_data(data); 172*27e9e554SCristian Ciocaltea u32 sirq_type; 173*27e9e554SCristian Ciocaltea 174*27e9e554SCristian Ciocaltea switch (type) { 175*27e9e554SCristian Ciocaltea case IRQ_TYPE_LEVEL_LOW: 176*27e9e554SCristian Ciocaltea sirq_type = INTC_EXTCTL_TYPE_LOW; 177*27e9e554SCristian Ciocaltea type = IRQ_TYPE_LEVEL_HIGH; 178*27e9e554SCristian Ciocaltea break; 179*27e9e554SCristian Ciocaltea case IRQ_TYPE_LEVEL_HIGH: 180*27e9e554SCristian Ciocaltea sirq_type = INTC_EXTCTL_TYPE_HIGH; 181*27e9e554SCristian Ciocaltea break; 182*27e9e554SCristian Ciocaltea case IRQ_TYPE_EDGE_FALLING: 183*27e9e554SCristian Ciocaltea sirq_type = INTC_EXTCTL_TYPE_FALLING; 184*27e9e554SCristian Ciocaltea type = IRQ_TYPE_EDGE_RISING; 185*27e9e554SCristian Ciocaltea break; 186*27e9e554SCristian Ciocaltea case IRQ_TYPE_EDGE_RISING: 187*27e9e554SCristian Ciocaltea sirq_type = INTC_EXTCTL_TYPE_RISING; 188*27e9e554SCristian Ciocaltea break; 189*27e9e554SCristian Ciocaltea default: 190*27e9e554SCristian Ciocaltea return -EINVAL; 191*27e9e554SCristian Ciocaltea } 192*27e9e554SCristian Ciocaltea 193*27e9e554SCristian Ciocaltea owl_sirq_clear_set_extctl(chip_data, INTC_EXTCTL_TYPE_MASK, sirq_type, 194*27e9e554SCristian Ciocaltea data->hwirq); 195*27e9e554SCristian Ciocaltea 196*27e9e554SCristian Ciocaltea return irq_chip_set_type_parent(data, type); 197*27e9e554SCristian Ciocaltea } 198*27e9e554SCristian Ciocaltea 199*27e9e554SCristian Ciocaltea static struct irq_chip owl_sirq_chip = { 200*27e9e554SCristian Ciocaltea .name = "owl-sirq", 201*27e9e554SCristian Ciocaltea .irq_mask = owl_sirq_mask, 202*27e9e554SCristian Ciocaltea .irq_unmask = owl_sirq_unmask, 203*27e9e554SCristian Ciocaltea .irq_eoi = owl_sirq_eoi, 204*27e9e554SCristian Ciocaltea .irq_set_type = owl_sirq_set_type, 205*27e9e554SCristian Ciocaltea .irq_retrigger = irq_chip_retrigger_hierarchy, 206*27e9e554SCristian Ciocaltea #ifdef CONFIG_SMP 207*27e9e554SCristian Ciocaltea .irq_set_affinity = irq_chip_set_affinity_parent, 208*27e9e554SCristian Ciocaltea #endif 209*27e9e554SCristian Ciocaltea }; 210*27e9e554SCristian Ciocaltea 211*27e9e554SCristian Ciocaltea static int owl_sirq_domain_translate(struct irq_domain *d, 212*27e9e554SCristian Ciocaltea struct irq_fwspec *fwspec, 213*27e9e554SCristian Ciocaltea unsigned long *hwirq, 214*27e9e554SCristian Ciocaltea unsigned int *type) 215*27e9e554SCristian Ciocaltea { 216*27e9e554SCristian Ciocaltea if (!is_of_node(fwspec->fwnode)) 217*27e9e554SCristian Ciocaltea return -EINVAL; 218*27e9e554SCristian Ciocaltea 219*27e9e554SCristian Ciocaltea if (fwspec->param_count != 2 || fwspec->param[0] >= NUM_SIRQ) 220*27e9e554SCristian Ciocaltea return -EINVAL; 221*27e9e554SCristian Ciocaltea 222*27e9e554SCristian Ciocaltea *hwirq = fwspec->param[0]; 223*27e9e554SCristian Ciocaltea *type = fwspec->param[1]; 224*27e9e554SCristian Ciocaltea 225*27e9e554SCristian Ciocaltea return 0; 226*27e9e554SCristian Ciocaltea } 227*27e9e554SCristian Ciocaltea 228*27e9e554SCristian Ciocaltea static int owl_sirq_domain_alloc(struct irq_domain *domain, unsigned int virq, 229*27e9e554SCristian Ciocaltea unsigned int nr_irqs, void *data) 230*27e9e554SCristian Ciocaltea { 231*27e9e554SCristian Ciocaltea struct owl_sirq_chip_data *chip_data = domain->host_data; 232*27e9e554SCristian Ciocaltea struct irq_fwspec *fwspec = data; 233*27e9e554SCristian Ciocaltea struct irq_fwspec parent_fwspec; 234*27e9e554SCristian Ciocaltea irq_hw_number_t hwirq; 235*27e9e554SCristian Ciocaltea unsigned int type; 236*27e9e554SCristian Ciocaltea int ret; 237*27e9e554SCristian Ciocaltea 238*27e9e554SCristian Ciocaltea if (WARN_ON(nr_irqs != 1)) 239*27e9e554SCristian Ciocaltea return -EINVAL; 240*27e9e554SCristian Ciocaltea 241*27e9e554SCristian Ciocaltea ret = owl_sirq_domain_translate(domain, fwspec, &hwirq, &type); 242*27e9e554SCristian Ciocaltea if (ret) 243*27e9e554SCristian Ciocaltea return ret; 244*27e9e554SCristian Ciocaltea 245*27e9e554SCristian Ciocaltea switch (type) { 246*27e9e554SCristian Ciocaltea case IRQ_TYPE_EDGE_RISING: 247*27e9e554SCristian Ciocaltea case IRQ_TYPE_LEVEL_HIGH: 248*27e9e554SCristian Ciocaltea break; 249*27e9e554SCristian Ciocaltea case IRQ_TYPE_EDGE_FALLING: 250*27e9e554SCristian Ciocaltea type = IRQ_TYPE_EDGE_RISING; 251*27e9e554SCristian Ciocaltea break; 252*27e9e554SCristian Ciocaltea case IRQ_TYPE_LEVEL_LOW: 253*27e9e554SCristian Ciocaltea type = IRQ_TYPE_LEVEL_HIGH; 254*27e9e554SCristian Ciocaltea break; 255*27e9e554SCristian Ciocaltea default: 256*27e9e554SCristian Ciocaltea return -EINVAL; 257*27e9e554SCristian Ciocaltea } 258*27e9e554SCristian Ciocaltea 259*27e9e554SCristian Ciocaltea irq_domain_set_hwirq_and_chip(domain, virq, hwirq, &owl_sirq_chip, 260*27e9e554SCristian Ciocaltea chip_data); 261*27e9e554SCristian Ciocaltea 262*27e9e554SCristian Ciocaltea parent_fwspec.fwnode = domain->parent->fwnode; 263*27e9e554SCristian Ciocaltea parent_fwspec.param_count = 3; 264*27e9e554SCristian Ciocaltea parent_fwspec.param[0] = GIC_SPI; 265*27e9e554SCristian Ciocaltea parent_fwspec.param[1] = chip_data->ext_irqs[hwirq]; 266*27e9e554SCristian Ciocaltea parent_fwspec.param[2] = type; 267*27e9e554SCristian Ciocaltea 268*27e9e554SCristian Ciocaltea return irq_domain_alloc_irqs_parent(domain, virq, 1, &parent_fwspec); 269*27e9e554SCristian Ciocaltea } 270*27e9e554SCristian Ciocaltea 271*27e9e554SCristian Ciocaltea static const struct irq_domain_ops owl_sirq_domain_ops = { 272*27e9e554SCristian Ciocaltea .translate = owl_sirq_domain_translate, 273*27e9e554SCristian Ciocaltea .alloc = owl_sirq_domain_alloc, 274*27e9e554SCristian Ciocaltea .free = irq_domain_free_irqs_common, 275*27e9e554SCristian Ciocaltea }; 276*27e9e554SCristian Ciocaltea 277*27e9e554SCristian Ciocaltea static int __init owl_sirq_init(const struct owl_sirq_params *params, 278*27e9e554SCristian Ciocaltea struct device_node *node, 279*27e9e554SCristian Ciocaltea struct device_node *parent) 280*27e9e554SCristian Ciocaltea { 281*27e9e554SCristian Ciocaltea struct irq_domain *domain, *parent_domain; 282*27e9e554SCristian Ciocaltea struct owl_sirq_chip_data *chip_data; 283*27e9e554SCristian Ciocaltea int ret, i; 284*27e9e554SCristian Ciocaltea 285*27e9e554SCristian Ciocaltea parent_domain = irq_find_host(parent); 286*27e9e554SCristian Ciocaltea if (!parent_domain) { 287*27e9e554SCristian Ciocaltea pr_err("%pOF: failed to find sirq parent domain\n", node); 288*27e9e554SCristian Ciocaltea return -ENXIO; 289*27e9e554SCristian Ciocaltea } 290*27e9e554SCristian Ciocaltea 291*27e9e554SCristian Ciocaltea chip_data = kzalloc(sizeof(*chip_data), GFP_KERNEL); 292*27e9e554SCristian Ciocaltea if (!chip_data) 293*27e9e554SCristian Ciocaltea return -ENOMEM; 294*27e9e554SCristian Ciocaltea 295*27e9e554SCristian Ciocaltea raw_spin_lock_init(&chip_data->lock); 296*27e9e554SCristian Ciocaltea 297*27e9e554SCristian Ciocaltea chip_data->params = params; 298*27e9e554SCristian Ciocaltea 299*27e9e554SCristian Ciocaltea chip_data->base = of_iomap(node, 0); 300*27e9e554SCristian Ciocaltea if (!chip_data->base) { 301*27e9e554SCristian Ciocaltea pr_err("%pOF: failed to map sirq registers\n", node); 302*27e9e554SCristian Ciocaltea ret = -ENXIO; 303*27e9e554SCristian Ciocaltea goto out_free; 304*27e9e554SCristian Ciocaltea } 305*27e9e554SCristian Ciocaltea 306*27e9e554SCristian Ciocaltea for (i = 0; i < NUM_SIRQ; i++) { 307*27e9e554SCristian Ciocaltea struct of_phandle_args irq; 308*27e9e554SCristian Ciocaltea 309*27e9e554SCristian Ciocaltea ret = of_irq_parse_one(node, i, &irq); 310*27e9e554SCristian Ciocaltea if (ret) { 311*27e9e554SCristian Ciocaltea pr_err("%pOF: failed to parse interrupt %d\n", node, i); 312*27e9e554SCristian Ciocaltea goto out_unmap; 313*27e9e554SCristian Ciocaltea } 314*27e9e554SCristian Ciocaltea 315*27e9e554SCristian Ciocaltea if (WARN_ON(irq.args_count != 3)) { 316*27e9e554SCristian Ciocaltea ret = -EINVAL; 317*27e9e554SCristian Ciocaltea goto out_unmap; 318*27e9e554SCristian Ciocaltea } 319*27e9e554SCristian Ciocaltea 320*27e9e554SCristian Ciocaltea chip_data->ext_irqs[i] = irq.args[1]; 321*27e9e554SCristian Ciocaltea 322*27e9e554SCristian Ciocaltea /* Set 24MHz external interrupt clock freq */ 323*27e9e554SCristian Ciocaltea owl_sirq_clear_set_extctl(chip_data, 0, INTC_EXTCTL_CLK_SEL, i); 324*27e9e554SCristian Ciocaltea } 325*27e9e554SCristian Ciocaltea 326*27e9e554SCristian Ciocaltea domain = irq_domain_add_hierarchy(parent_domain, 0, NUM_SIRQ, node, 327*27e9e554SCristian Ciocaltea &owl_sirq_domain_ops, chip_data); 328*27e9e554SCristian Ciocaltea if (!domain) { 329*27e9e554SCristian Ciocaltea pr_err("%pOF: failed to add domain\n", node); 330*27e9e554SCristian Ciocaltea ret = -ENOMEM; 331*27e9e554SCristian Ciocaltea goto out_unmap; 332*27e9e554SCristian Ciocaltea } 333*27e9e554SCristian Ciocaltea 334*27e9e554SCristian Ciocaltea return 0; 335*27e9e554SCristian Ciocaltea 336*27e9e554SCristian Ciocaltea out_unmap: 337*27e9e554SCristian Ciocaltea iounmap(chip_data->base); 338*27e9e554SCristian Ciocaltea out_free: 339*27e9e554SCristian Ciocaltea kfree(chip_data); 340*27e9e554SCristian Ciocaltea 341*27e9e554SCristian Ciocaltea return ret; 342*27e9e554SCristian Ciocaltea } 343*27e9e554SCristian Ciocaltea 344*27e9e554SCristian Ciocaltea static int __init owl_sirq_s500_of_init(struct device_node *node, 345*27e9e554SCristian Ciocaltea struct device_node *parent) 346*27e9e554SCristian Ciocaltea { 347*27e9e554SCristian Ciocaltea return owl_sirq_init(&owl_sirq_s500_params, node, parent); 348*27e9e554SCristian Ciocaltea } 349*27e9e554SCristian Ciocaltea 350*27e9e554SCristian Ciocaltea IRQCHIP_DECLARE(owl_sirq_s500, "actions,s500-sirq", owl_sirq_s500_of_init); 351*27e9e554SCristian Ciocaltea IRQCHIP_DECLARE(owl_sirq_s700, "actions,s700-sirq", owl_sirq_s500_of_init); 352*27e9e554SCristian Ciocaltea 353*27e9e554SCristian Ciocaltea static int __init owl_sirq_s900_of_init(struct device_node *node, 354*27e9e554SCristian Ciocaltea struct device_node *parent) 355*27e9e554SCristian Ciocaltea { 356*27e9e554SCristian Ciocaltea return owl_sirq_init(&owl_sirq_s900_params, node, parent); 357*27e9e554SCristian Ciocaltea } 358*27e9e554SCristian Ciocaltea 359*27e9e554SCristian Ciocaltea IRQCHIP_DECLARE(owl_sirq_s900, "actions,s900-sirq", owl_sirq_s900_of_init); 360