14e346146SSamuel Holland // SPDX-License-Identifier: GPL-2.0-only 24e346146SSamuel Holland /* 34e346146SSamuel Holland * The R_INTC in Allwinner A31 and newer SoCs manages several types of 44e346146SSamuel Holland * interrupts, as shown below: 54e346146SSamuel Holland * 64e346146SSamuel Holland * NMI IRQ DIRECT IRQs MUXED IRQs 74e346146SSamuel Holland * bit 0 bits 1-15^ bits 19-31 84e346146SSamuel Holland * 94e346146SSamuel Holland * +---------+ +---------+ +---------+ +---------+ 104e346146SSamuel Holland * | NMI Pad | | IRQ d | | IRQ m | | IRQ m+7 | 114e346146SSamuel Holland * +---------+ +---------+ +---------+ +---------+ 124e346146SSamuel Holland * | | | | | | | 134e346146SSamuel Holland * | | | | |......| | 144e346146SSamuel Holland * +------V------+ +------------+ | | | +--V------V--+ | 154e346146SSamuel Holland * | Invert/ | | Write 1 to | | | | | AND with | | 164e346146SSamuel Holland * | Edge Detect | | PENDING[0] | | | | | MUX[m/8] | | 174e346146SSamuel Holland * +-------------+ +------------+ | | | +------------+ | 184e346146SSamuel Holland * | | | | | | | 194e346146SSamuel Holland * +--V-------V--+ +--V--+ | +--V--+ | +--V--+ 204e346146SSamuel Holland * | Set Reset| | GIC | | | GIC | | | GIC | 214e346146SSamuel Holland * | Latch | | SPI | | | SPI |... | ...| SPI | 224e346146SSamuel Holland * +-------------+ | N+d | | | m | | | m+7 | 234e346146SSamuel Holland * | | +-----+ | +-----+ | +-----+ 244e346146SSamuel Holland * | | | | 254e346146SSamuel Holland * +-------V-+ +-V----------+ +---------V--+ +--------V--------+ 264e346146SSamuel Holland * | GIC SPI | | AND with | | AND with | | AND with | 274e346146SSamuel Holland * | N (=32) | | ENABLE[0] | | ENABLE[d] | | ENABLE[19+m/8] | 284e346146SSamuel Holland * +---------+ +------------+ +------------+ +-----------------+ 294e346146SSamuel Holland * | | | 304e346146SSamuel Holland * +------V-----+ +------V-----+ +--------V--------+ 314e346146SSamuel Holland * | Read | | Read | | Read | 324e346146SSamuel Holland * | PENDING[0] | | PENDING[d] | | PENDING[19+m/8] | 334e346146SSamuel Holland * +------------+ +------------+ +-----------------+ 344e346146SSamuel Holland * 354e346146SSamuel Holland * ^ bits 16-18 are direct IRQs for peripherals with banked interrupts, such as 364e346146SSamuel Holland * the MSGBOX. These IRQs do not map to any GIC SPI. 374e346146SSamuel Holland * 384e346146SSamuel Holland * The H6 variant adds two more (banked) direct IRQs and implements the full 394e346146SSamuel Holland * set of 128 mux bits. This requires a second set of top-level registers. 404e346146SSamuel Holland */ 414e346146SSamuel Holland 42*7ab365f6SSamuel Holland #include <linux/bitmap.h> 434e346146SSamuel Holland #include <linux/interrupt.h> 444e346146SSamuel Holland #include <linux/irq.h> 454e346146SSamuel Holland #include <linux/irqchip.h> 464e346146SSamuel Holland #include <linux/irqdomain.h> 474e346146SSamuel Holland #include <linux/of.h> 484e346146SSamuel Holland #include <linux/of_address.h> 494e346146SSamuel Holland #include <linux/of_irq.h> 50*7ab365f6SSamuel Holland #include <linux/syscore_ops.h> 514e346146SSamuel Holland 524e346146SSamuel Holland #include <dt-bindings/interrupt-controller/arm-gic.h> 534e346146SSamuel Holland 544e346146SSamuel Holland #define SUN6I_NMI_CTRL (0x0c) 554e346146SSamuel Holland #define SUN6I_IRQ_PENDING(n) (0x10 + 4 * (n)) 564e346146SSamuel Holland #define SUN6I_IRQ_ENABLE(n) (0x40 + 4 * (n)) 574e346146SSamuel Holland #define SUN6I_MUX_ENABLE(n) (0xc0 + 4 * (n)) 584e346146SSamuel Holland 594e346146SSamuel Holland #define SUN6I_NMI_SRC_TYPE_LEVEL_LOW 0 604e346146SSamuel Holland #define SUN6I_NMI_SRC_TYPE_EDGE_FALLING 1 614e346146SSamuel Holland #define SUN6I_NMI_SRC_TYPE_LEVEL_HIGH 2 624e346146SSamuel Holland #define SUN6I_NMI_SRC_TYPE_EDGE_RISING 3 634e346146SSamuel Holland 644e346146SSamuel Holland #define SUN6I_NMI_BIT BIT(0) 654e346146SSamuel Holland 664e346146SSamuel Holland #define SUN6I_NMI_NEEDS_ACK ((void *)1) 674e346146SSamuel Holland 684e346146SSamuel Holland #define SUN6I_NR_TOP_LEVEL_IRQS 64 694e346146SSamuel Holland #define SUN6I_NR_DIRECT_IRQS 16 704e346146SSamuel Holland #define SUN6I_NR_MUX_BITS 128 714e346146SSamuel Holland 72*7ab365f6SSamuel Holland struct sun6i_r_intc_variant { 73*7ab365f6SSamuel Holland u32 first_mux_irq; 74*7ab365f6SSamuel Holland u32 nr_mux_irqs; 75*7ab365f6SSamuel Holland u32 mux_valid[BITS_TO_U32(SUN6I_NR_MUX_BITS)]; 76*7ab365f6SSamuel Holland }; 77*7ab365f6SSamuel Holland 784e346146SSamuel Holland static void __iomem *base; 794e346146SSamuel Holland static irq_hw_number_t nmi_hwirq; 80*7ab365f6SSamuel Holland static DECLARE_BITMAP(wake_irq_enabled, SUN6I_NR_TOP_LEVEL_IRQS); 81*7ab365f6SSamuel Holland static DECLARE_BITMAP(wake_mux_enabled, SUN6I_NR_MUX_BITS); 82*7ab365f6SSamuel Holland static DECLARE_BITMAP(wake_mux_valid, SUN6I_NR_MUX_BITS); 834e346146SSamuel Holland 844e346146SSamuel Holland static void sun6i_r_intc_ack_nmi(void) 854e346146SSamuel Holland { 864e346146SSamuel Holland writel_relaxed(SUN6I_NMI_BIT, base + SUN6I_IRQ_PENDING(0)); 874e346146SSamuel Holland } 884e346146SSamuel Holland 894e346146SSamuel Holland static void sun6i_r_intc_nmi_ack(struct irq_data *data) 904e346146SSamuel Holland { 914e346146SSamuel Holland if (irqd_get_trigger_type(data) & IRQ_TYPE_EDGE_BOTH) 924e346146SSamuel Holland sun6i_r_intc_ack_nmi(); 934e346146SSamuel Holland else 944e346146SSamuel Holland data->chip_data = SUN6I_NMI_NEEDS_ACK; 954e346146SSamuel Holland } 964e346146SSamuel Holland 974e346146SSamuel Holland static void sun6i_r_intc_nmi_eoi(struct irq_data *data) 984e346146SSamuel Holland { 994e346146SSamuel Holland /* For oneshot IRQs, delay the ack until the IRQ is unmasked. */ 1004e346146SSamuel Holland if (data->chip_data == SUN6I_NMI_NEEDS_ACK && !irqd_irq_masked(data)) { 1014e346146SSamuel Holland data->chip_data = NULL; 1024e346146SSamuel Holland sun6i_r_intc_ack_nmi(); 1034e346146SSamuel Holland } 1044e346146SSamuel Holland 1054e346146SSamuel Holland irq_chip_eoi_parent(data); 1064e346146SSamuel Holland } 1074e346146SSamuel Holland 1084e346146SSamuel Holland static void sun6i_r_intc_nmi_unmask(struct irq_data *data) 1094e346146SSamuel Holland { 1104e346146SSamuel Holland if (data->chip_data == SUN6I_NMI_NEEDS_ACK) { 1114e346146SSamuel Holland data->chip_data = NULL; 1124e346146SSamuel Holland sun6i_r_intc_ack_nmi(); 1134e346146SSamuel Holland } 1144e346146SSamuel Holland 1154e346146SSamuel Holland irq_chip_unmask_parent(data); 1164e346146SSamuel Holland } 1174e346146SSamuel Holland 1184e346146SSamuel Holland static int sun6i_r_intc_nmi_set_type(struct irq_data *data, unsigned int type) 1194e346146SSamuel Holland { 1204e346146SSamuel Holland u32 nmi_src_type; 1214e346146SSamuel Holland 1224e346146SSamuel Holland switch (type) { 1234e346146SSamuel Holland case IRQ_TYPE_EDGE_RISING: 1244e346146SSamuel Holland nmi_src_type = SUN6I_NMI_SRC_TYPE_EDGE_RISING; 1254e346146SSamuel Holland break; 1264e346146SSamuel Holland case IRQ_TYPE_EDGE_FALLING: 1274e346146SSamuel Holland nmi_src_type = SUN6I_NMI_SRC_TYPE_EDGE_FALLING; 1284e346146SSamuel Holland break; 1294e346146SSamuel Holland case IRQ_TYPE_LEVEL_HIGH: 1304e346146SSamuel Holland nmi_src_type = SUN6I_NMI_SRC_TYPE_LEVEL_HIGH; 1314e346146SSamuel Holland break; 1324e346146SSamuel Holland case IRQ_TYPE_LEVEL_LOW: 1334e346146SSamuel Holland nmi_src_type = SUN6I_NMI_SRC_TYPE_LEVEL_LOW; 1344e346146SSamuel Holland break; 1354e346146SSamuel Holland default: 1364e346146SSamuel Holland return -EINVAL; 1374e346146SSamuel Holland } 1384e346146SSamuel Holland 1394e346146SSamuel Holland writel_relaxed(nmi_src_type, base + SUN6I_NMI_CTRL); 1404e346146SSamuel Holland 1414e346146SSamuel Holland /* 1424e346146SSamuel Holland * The "External NMI" GIC input connects to a latch inside R_INTC, not 1434e346146SSamuel Holland * directly to the pin. So the GIC trigger type does not depend on the 1444e346146SSamuel Holland * NMI pin trigger type. 1454e346146SSamuel Holland */ 1464e346146SSamuel Holland return irq_chip_set_type_parent(data, IRQ_TYPE_LEVEL_HIGH); 1474e346146SSamuel Holland } 1484e346146SSamuel Holland 1494e346146SSamuel Holland static int sun6i_r_intc_nmi_set_irqchip_state(struct irq_data *data, 1504e346146SSamuel Holland enum irqchip_irq_state which, 1514e346146SSamuel Holland bool state) 1524e346146SSamuel Holland { 1534e346146SSamuel Holland if (which == IRQCHIP_STATE_PENDING && !state) 1544e346146SSamuel Holland sun6i_r_intc_ack_nmi(); 1554e346146SSamuel Holland 1564e346146SSamuel Holland return irq_chip_set_parent_state(data, which, state); 1574e346146SSamuel Holland } 1584e346146SSamuel Holland 159*7ab365f6SSamuel Holland static int sun6i_r_intc_irq_set_wake(struct irq_data *data, unsigned int on) 160*7ab365f6SSamuel Holland { 161*7ab365f6SSamuel Holland unsigned long offset_from_nmi = data->hwirq - nmi_hwirq; 162*7ab365f6SSamuel Holland 163*7ab365f6SSamuel Holland if (offset_from_nmi < SUN6I_NR_DIRECT_IRQS) 164*7ab365f6SSamuel Holland assign_bit(offset_from_nmi, wake_irq_enabled, on); 165*7ab365f6SSamuel Holland else if (test_bit(data->hwirq, wake_mux_valid)) 166*7ab365f6SSamuel Holland assign_bit(data->hwirq, wake_mux_enabled, on); 167*7ab365f6SSamuel Holland else 168*7ab365f6SSamuel Holland /* Not wakeup capable. */ 169*7ab365f6SSamuel Holland return -EPERM; 170*7ab365f6SSamuel Holland 171*7ab365f6SSamuel Holland return 0; 172*7ab365f6SSamuel Holland } 173*7ab365f6SSamuel Holland 1744e346146SSamuel Holland static struct irq_chip sun6i_r_intc_nmi_chip = { 1754e346146SSamuel Holland .name = "sun6i-r-intc", 1764e346146SSamuel Holland .irq_ack = sun6i_r_intc_nmi_ack, 1774e346146SSamuel Holland .irq_mask = irq_chip_mask_parent, 1784e346146SSamuel Holland .irq_unmask = sun6i_r_intc_nmi_unmask, 1794e346146SSamuel Holland .irq_eoi = sun6i_r_intc_nmi_eoi, 1804e346146SSamuel Holland .irq_set_affinity = irq_chip_set_affinity_parent, 1814e346146SSamuel Holland .irq_set_type = sun6i_r_intc_nmi_set_type, 1824e346146SSamuel Holland .irq_set_irqchip_state = sun6i_r_intc_nmi_set_irqchip_state, 183*7ab365f6SSamuel Holland .irq_set_wake = sun6i_r_intc_irq_set_wake, 184*7ab365f6SSamuel Holland .flags = IRQCHIP_SET_TYPE_MASKED, 185*7ab365f6SSamuel Holland }; 186*7ab365f6SSamuel Holland 187*7ab365f6SSamuel Holland static struct irq_chip sun6i_r_intc_wakeup_chip = { 188*7ab365f6SSamuel Holland .name = "sun6i-r-intc", 189*7ab365f6SSamuel Holland .irq_mask = irq_chip_mask_parent, 190*7ab365f6SSamuel Holland .irq_unmask = irq_chip_unmask_parent, 191*7ab365f6SSamuel Holland .irq_eoi = irq_chip_eoi_parent, 192*7ab365f6SSamuel Holland .irq_set_affinity = irq_chip_set_affinity_parent, 193*7ab365f6SSamuel Holland .irq_set_type = irq_chip_set_type_parent, 194*7ab365f6SSamuel Holland .irq_set_wake = sun6i_r_intc_irq_set_wake, 195*7ab365f6SSamuel Holland .flags = IRQCHIP_SET_TYPE_MASKED, 1964e346146SSamuel Holland }; 1974e346146SSamuel Holland 1984e346146SSamuel Holland static int sun6i_r_intc_domain_translate(struct irq_domain *domain, 1994e346146SSamuel Holland struct irq_fwspec *fwspec, 2004e346146SSamuel Holland unsigned long *hwirq, 2014e346146SSamuel Holland unsigned int *type) 2024e346146SSamuel Holland { 2034e346146SSamuel Holland /* Accept the old two-cell binding for the NMI only. */ 2044e346146SSamuel Holland if (fwspec->param_count == 2 && fwspec->param[0] == 0) { 2054e346146SSamuel Holland *hwirq = nmi_hwirq; 2064e346146SSamuel Holland *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; 2074e346146SSamuel Holland return 0; 2084e346146SSamuel Holland } 2094e346146SSamuel Holland 2104e346146SSamuel Holland /* Otherwise this binding should match the GIC SPI binding. */ 2114e346146SSamuel Holland if (fwspec->param_count < 3) 2124e346146SSamuel Holland return -EINVAL; 2134e346146SSamuel Holland if (fwspec->param[0] != GIC_SPI) 2144e346146SSamuel Holland return -EINVAL; 2154e346146SSamuel Holland 2164e346146SSamuel Holland *hwirq = fwspec->param[1]; 2174e346146SSamuel Holland *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK; 2184e346146SSamuel Holland 2194e346146SSamuel Holland return 0; 2204e346146SSamuel Holland } 2214e346146SSamuel Holland 2224e346146SSamuel Holland static int sun6i_r_intc_domain_alloc(struct irq_domain *domain, 2234e346146SSamuel Holland unsigned int virq, 2244e346146SSamuel Holland unsigned int nr_irqs, void *arg) 2254e346146SSamuel Holland { 2264e346146SSamuel Holland struct irq_fwspec *fwspec = arg; 2274e346146SSamuel Holland struct irq_fwspec gic_fwspec; 2284e346146SSamuel Holland unsigned long hwirq; 2294e346146SSamuel Holland unsigned int type; 2304e346146SSamuel Holland int i, ret; 2314e346146SSamuel Holland 2324e346146SSamuel Holland ret = sun6i_r_intc_domain_translate(domain, fwspec, &hwirq, &type); 2334e346146SSamuel Holland if (ret) 2344e346146SSamuel Holland return ret; 2354e346146SSamuel Holland if (hwirq + nr_irqs > SUN6I_NR_MUX_BITS) 2364e346146SSamuel Holland return -EINVAL; 2374e346146SSamuel Holland 2384e346146SSamuel Holland /* Construct a GIC-compatible fwspec from this fwspec. */ 2394e346146SSamuel Holland gic_fwspec = (struct irq_fwspec) { 2404e346146SSamuel Holland .fwnode = domain->parent->fwnode, 2414e346146SSamuel Holland .param_count = 3, 2424e346146SSamuel Holland .param = { GIC_SPI, hwirq, type }, 2434e346146SSamuel Holland }; 2444e346146SSamuel Holland 2454e346146SSamuel Holland ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_fwspec); 2464e346146SSamuel Holland if (ret) 2474e346146SSamuel Holland return ret; 2484e346146SSamuel Holland 2494e346146SSamuel Holland for (i = 0; i < nr_irqs; ++i, ++hwirq, ++virq) { 2504e346146SSamuel Holland if (hwirq == nmi_hwirq) { 2514e346146SSamuel Holland irq_domain_set_hwirq_and_chip(domain, virq, hwirq, 2524e346146SSamuel Holland &sun6i_r_intc_nmi_chip, 0); 2534e346146SSamuel Holland irq_set_handler(virq, handle_fasteoi_ack_irq); 2544e346146SSamuel Holland } else { 255*7ab365f6SSamuel Holland irq_domain_set_hwirq_and_chip(domain, virq, hwirq, 256*7ab365f6SSamuel Holland &sun6i_r_intc_wakeup_chip, 0); 2574e346146SSamuel Holland } 2584e346146SSamuel Holland } 2594e346146SSamuel Holland 2604e346146SSamuel Holland return 0; 2614e346146SSamuel Holland } 2624e346146SSamuel Holland 2634e346146SSamuel Holland static const struct irq_domain_ops sun6i_r_intc_domain_ops = { 2644e346146SSamuel Holland .translate = sun6i_r_intc_domain_translate, 2654e346146SSamuel Holland .alloc = sun6i_r_intc_domain_alloc, 2664e346146SSamuel Holland .free = irq_domain_free_irqs_common, 2674e346146SSamuel Holland }; 2684e346146SSamuel Holland 269*7ab365f6SSamuel Holland static int sun6i_r_intc_suspend(void) 270*7ab365f6SSamuel Holland { 271*7ab365f6SSamuel Holland u32 buf[BITS_TO_U32(max(SUN6I_NR_TOP_LEVEL_IRQS, SUN6I_NR_MUX_BITS))]; 272*7ab365f6SSamuel Holland int i; 273*7ab365f6SSamuel Holland 274*7ab365f6SSamuel Holland /* Wake IRQs are enabled during system sleep and shutdown. */ 275*7ab365f6SSamuel Holland bitmap_to_arr32(buf, wake_irq_enabled, SUN6I_NR_TOP_LEVEL_IRQS); 276*7ab365f6SSamuel Holland for (i = 0; i < BITS_TO_U32(SUN6I_NR_TOP_LEVEL_IRQS); ++i) 277*7ab365f6SSamuel Holland writel_relaxed(buf[i], base + SUN6I_IRQ_ENABLE(i)); 278*7ab365f6SSamuel Holland bitmap_to_arr32(buf, wake_mux_enabled, SUN6I_NR_MUX_BITS); 279*7ab365f6SSamuel Holland for (i = 0; i < BITS_TO_U32(SUN6I_NR_MUX_BITS); ++i) 280*7ab365f6SSamuel Holland writel_relaxed(buf[i], base + SUN6I_MUX_ENABLE(i)); 281*7ab365f6SSamuel Holland 282*7ab365f6SSamuel Holland return 0; 283*7ab365f6SSamuel Holland } 284*7ab365f6SSamuel Holland 2854e346146SSamuel Holland static void sun6i_r_intc_resume(void) 2864e346146SSamuel Holland { 2874e346146SSamuel Holland int i; 2884e346146SSamuel Holland 2894e346146SSamuel Holland /* Only the NMI is relevant during normal operation. */ 2904e346146SSamuel Holland writel_relaxed(SUN6I_NMI_BIT, base + SUN6I_IRQ_ENABLE(0)); 2914e346146SSamuel Holland for (i = 1; i < BITS_TO_U32(SUN6I_NR_TOP_LEVEL_IRQS); ++i) 2924e346146SSamuel Holland writel_relaxed(0, base + SUN6I_IRQ_ENABLE(i)); 2934e346146SSamuel Holland } 2944e346146SSamuel Holland 295*7ab365f6SSamuel Holland static void sun6i_r_intc_shutdown(void) 296*7ab365f6SSamuel Holland { 297*7ab365f6SSamuel Holland sun6i_r_intc_suspend(); 298*7ab365f6SSamuel Holland } 299*7ab365f6SSamuel Holland 300*7ab365f6SSamuel Holland static struct syscore_ops sun6i_r_intc_syscore_ops = { 301*7ab365f6SSamuel Holland .suspend = sun6i_r_intc_suspend, 302*7ab365f6SSamuel Holland .resume = sun6i_r_intc_resume, 303*7ab365f6SSamuel Holland .shutdown = sun6i_r_intc_shutdown, 304*7ab365f6SSamuel Holland }; 305*7ab365f6SSamuel Holland 3064e346146SSamuel Holland static int __init sun6i_r_intc_init(struct device_node *node, 307*7ab365f6SSamuel Holland struct device_node *parent, 308*7ab365f6SSamuel Holland const struct sun6i_r_intc_variant *v) 3094e346146SSamuel Holland { 3104e346146SSamuel Holland struct irq_domain *domain, *parent_domain; 3114e346146SSamuel Holland struct of_phandle_args nmi_parent; 3124e346146SSamuel Holland int ret; 3134e346146SSamuel Holland 3144e346146SSamuel Holland /* Extract the NMI hwirq number from the OF node. */ 3154e346146SSamuel Holland ret = of_irq_parse_one(node, 0, &nmi_parent); 3164e346146SSamuel Holland if (ret) 3174e346146SSamuel Holland return ret; 3184e346146SSamuel Holland if (nmi_parent.args_count < 3 || 3194e346146SSamuel Holland nmi_parent.args[0] != GIC_SPI || 3204e346146SSamuel Holland nmi_parent.args[2] != IRQ_TYPE_LEVEL_HIGH) 3214e346146SSamuel Holland return -EINVAL; 3224e346146SSamuel Holland nmi_hwirq = nmi_parent.args[1]; 3234e346146SSamuel Holland 324*7ab365f6SSamuel Holland bitmap_set(wake_irq_enabled, v->first_mux_irq, v->nr_mux_irqs); 325*7ab365f6SSamuel Holland bitmap_from_arr32(wake_mux_valid, v->mux_valid, SUN6I_NR_MUX_BITS); 326*7ab365f6SSamuel Holland 3274e346146SSamuel Holland parent_domain = irq_find_host(parent); 3284e346146SSamuel Holland if (!parent_domain) { 3294e346146SSamuel Holland pr_err("%pOF: Failed to obtain parent domain\n", node); 3304e346146SSamuel Holland return -ENXIO; 3314e346146SSamuel Holland } 3324e346146SSamuel Holland 3334e346146SSamuel Holland base = of_io_request_and_map(node, 0, NULL); 3344e346146SSamuel Holland if (IS_ERR(base)) { 3354e346146SSamuel Holland pr_err("%pOF: Failed to map MMIO region\n", node); 3364e346146SSamuel Holland return PTR_ERR(base); 3374e346146SSamuel Holland } 3384e346146SSamuel Holland 3394e346146SSamuel Holland domain = irq_domain_add_hierarchy(parent_domain, 0, 0, node, 3404e346146SSamuel Holland &sun6i_r_intc_domain_ops, NULL); 3414e346146SSamuel Holland if (!domain) { 3424e346146SSamuel Holland pr_err("%pOF: Failed to allocate domain\n", node); 3434e346146SSamuel Holland iounmap(base); 3444e346146SSamuel Holland return -ENOMEM; 3454e346146SSamuel Holland } 3464e346146SSamuel Holland 347*7ab365f6SSamuel Holland register_syscore_ops(&sun6i_r_intc_syscore_ops); 348*7ab365f6SSamuel Holland 3494e346146SSamuel Holland sun6i_r_intc_ack_nmi(); 3504e346146SSamuel Holland sun6i_r_intc_resume(); 3514e346146SSamuel Holland 3524e346146SSamuel Holland return 0; 3534e346146SSamuel Holland } 354*7ab365f6SSamuel Holland 355*7ab365f6SSamuel Holland static const struct sun6i_r_intc_variant sun6i_a31_r_intc_variant __initconst = { 356*7ab365f6SSamuel Holland .first_mux_irq = 19, 357*7ab365f6SSamuel Holland .nr_mux_irqs = 13, 358*7ab365f6SSamuel Holland .mux_valid = { 0xffffffff, 0xfff80000, 0xffffffff, 0x0000000f }, 359*7ab365f6SSamuel Holland }; 360*7ab365f6SSamuel Holland 361*7ab365f6SSamuel Holland static int __init sun6i_a31_r_intc_init(struct device_node *node, 362*7ab365f6SSamuel Holland struct device_node *parent) 363*7ab365f6SSamuel Holland { 364*7ab365f6SSamuel Holland return sun6i_r_intc_init(node, parent, &sun6i_a31_r_intc_variant); 365*7ab365f6SSamuel Holland } 366*7ab365f6SSamuel Holland IRQCHIP_DECLARE(sun6i_a31_r_intc, "allwinner,sun6i-a31-r-intc", sun6i_a31_r_intc_init); 367*7ab365f6SSamuel Holland 368*7ab365f6SSamuel Holland static const struct sun6i_r_intc_variant sun50i_h6_r_intc_variant __initconst = { 369*7ab365f6SSamuel Holland .first_mux_irq = 21, 370*7ab365f6SSamuel Holland .nr_mux_irqs = 16, 371*7ab365f6SSamuel Holland .mux_valid = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }, 372*7ab365f6SSamuel Holland }; 373*7ab365f6SSamuel Holland 374*7ab365f6SSamuel Holland static int __init sun50i_h6_r_intc_init(struct device_node *node, 375*7ab365f6SSamuel Holland struct device_node *parent) 376*7ab365f6SSamuel Holland { 377*7ab365f6SSamuel Holland return sun6i_r_intc_init(node, parent, &sun50i_h6_r_intc_variant); 378*7ab365f6SSamuel Holland } 379*7ab365f6SSamuel Holland IRQCHIP_DECLARE(sun50i_h6_r_intc, "allwinner,sun50i-h6-r-intc", sun50i_h6_r_intc_init); 380