1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2005-2017 Andes Technology Corporation
6 #include <linux/of_irq.h>
7 #include <linux/of_address.h>
8 #include <linux/interrupt.h>
9 #include <linux/irqdomain.h>
10 #include <linux/irqchip.h>
11 #include <nds32_intrinsic.h>
13 static void ativic32_ack_irq(struct irq_data
*data
)
15 __nds32__mtsr_dsb(BIT(data
->hwirq
), NDS32_SR_INT_PEND2
);
18 static void ativic32_mask_irq(struct irq_data
*data
)
20 unsigned long int_mask2
= __nds32__mfsr(NDS32_SR_INT_MASK2
);
21 __nds32__mtsr_dsb(int_mask2
& (~(BIT(data
->hwirq
))), NDS32_SR_INT_MASK2
);
24 static void ativic32_unmask_irq(struct irq_data
*data
)
26 unsigned long int_mask2
= __nds32__mfsr(NDS32_SR_INT_MASK2
);
27 __nds32__mtsr_dsb(int_mask2
| (BIT(data
->hwirq
)), NDS32_SR_INT_MASK2
);
30 static struct irq_chip ativic32_chip
= {
32 .irq_ack
= ativic32_ack_irq
,
33 .irq_mask
= ativic32_mask_irq
,
34 .irq_unmask
= ativic32_unmask_irq
,
37 static unsigned int __initdata nivic_map
[6] = { 6, 2, 10, 16, 24, 32 };
39 static struct irq_domain
*root_domain
;
40 static int ativic32_irq_domain_map(struct irq_domain
*id
, unsigned int virq
,
44 unsigned long int_trigger_type
;
46 struct irq_data
*irq_data
;
47 int_trigger_type
= __nds32__mfsr(NDS32_SR_INT_TRIGGER
);
48 irq_data
= irq_get_irq_data(virq
);
52 if (int_trigger_type
& (BIT(hw
))) {
53 irq_set_chip_and_handler(virq
, &ativic32_chip
, handle_edge_irq
);
54 type
= IRQ_TYPE_EDGE_RISING
;
56 irq_set_chip_and_handler(virq
, &ativic32_chip
, handle_level_irq
);
57 type
= IRQ_TYPE_LEVEL_HIGH
;
60 irqd_set_trigger_type(irq_data
, type
);
64 static struct irq_domain_ops ativic32_ops
= {
65 .map
= ativic32_irq_domain_map
,
66 .xlate
= irq_domain_xlate_onecell
69 static irq_hw_number_t
get_intr_src(void)
71 return ((__nds32__mfsr(NDS32_SR_ITYPE
) & ITYPE_mskVECTOR
) >> ITYPE_offVECTOR
)
72 - NDS32_VECTOR_offINTERRUPT
;
75 asmlinkage
void asm_do_IRQ(struct pt_regs
*regs
)
77 irq_hw_number_t hwirq
= get_intr_src();
78 handle_domain_irq(root_domain
, hwirq
, regs
);
81 int __init
ativic32_init_irq(struct device_node
*node
, struct device_node
*parent
)
83 unsigned long int_vec_base
, nivic
, nr_ints
;
85 if (WARN(parent
, "non-root ativic32 are not supported"))
88 int_vec_base
= __nds32__mfsr(NDS32_SR_IVB
);
90 if (((int_vec_base
& IVB_mskIVIC_VER
) >> IVB_offIVIC_VER
) == 0)
91 panic("Unable to use atcivic32 for this cpu.\n");
93 nivic
= (int_vec_base
& IVB_mskNIVIC
) >> IVB_offNIVIC
;
94 if (nivic
>= ARRAY_SIZE(nivic_map
))
95 panic("The number of input for ativic32 is not supported.\n");
97 nr_ints
= nivic_map
[nivic
];
99 root_domain
= irq_domain_add_linear(node
, nr_ints
,
100 &ativic32_ops
, NULL
);
103 panic("%s: unable to create IRQ domain\n", node
->full_name
);
107 IRQCHIP_DECLARE(ativic32
, "andestech,ativic32", ativic32_init_irq
);