blob: 3c18e66386c78a4e8e494209b79e2fe279f47a1b [file] [log] [blame]
Vineet Guptaac4c2442013-01-18 15:12:16 +05301/*
2 * Copyright (C) 2011-12 Synopsys, Inc. (www.synopsys.com)
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 */
9
10#include <linux/interrupt.h>
11#include <linux/module.h>
Vineet Guptaabe11dd2013-01-18 15:12:21 +053012#include <linux/of.h>
13#include <linux/irqdomain.h>
Vineet Guptabacdf482013-01-18 15:12:18 +053014#include <asm/sections.h>
15#include <asm/irq.h>
16
17/*
18 * Early Hardware specific Interrupt setup
19 * -Called very early (start_kernel -> setup_arch -> setup_processor)
20 * -Platform Independent (must for any ARC700)
21 * -Needed for each CPU (hence not foldable into init_IRQ)
22 *
23 * what it does ?
24 * -setup Vector Table Base Reg - in case Linux not linked at 0x8000_0000
25 * -Disable all IRQs (on CPU side)
26 */
27void __init arc_init_IRQ(void)
28{
29 int level_mask = level_mask;
30
31 write_aux_reg(AUX_INTR_VEC_BASE, _int_vec_base_lds);
32
33 /* Disable all IRQs: enable them as devices request */
34 write_aux_reg(AUX_IENABLE, 0);
35}
36
37/*
38 * ARC700 core includes a simple on-chip intc supporting
39 * -per IRQ enable/disable
40 * -2 levels of interrupts (high/low)
41 * -all interrupts being level triggered
42 *
43 * To reduce platform code, we assume all IRQs directly hooked-up into intc.
44 * Platforms with external intc, hence cascaded IRQs, are free to over-ride
45 * below, per IRQ.
46 */
47
48static void arc_mask_irq(struct irq_data *data)
49{
50 arch_mask_irq(data->irq);
51}
52
53static void arc_unmask_irq(struct irq_data *data)
54{
55 arch_unmask_irq(data->irq);
56}
57
58static struct irq_chip onchip_intc = {
59 .name = "ARC In-core Intc",
60 .irq_mask = arc_mask_irq,
61 .irq_unmask = arc_unmask_irq,
62};
63
Vineet Guptaabe11dd2013-01-18 15:12:21 +053064static int arc_intc_domain_map(struct irq_domain *d, unsigned int irq,
65 irq_hw_number_t hw)
66{
67 if (irq == TIMER0_IRQ)
68 irq_set_chip_and_handler(irq, &onchip_intc, handle_percpu_irq);
69 else
70 irq_set_chip_and_handler(irq, &onchip_intc, handle_level_irq);
71
72 return 0;
73}
74
75static const struct irq_domain_ops arc_intc_domain_ops = {
76 .xlate = irq_domain_xlate_onecell,
77 .map = arc_intc_domain_map,
78};
79
80static struct irq_domain *root_domain;
81
Vineet Guptabacdf482013-01-18 15:12:18 +053082void __init init_onchip_IRQ(void)
83{
Vineet Guptaabe11dd2013-01-18 15:12:21 +053084 struct device_node *intc = NULL;
Vineet Guptabacdf482013-01-18 15:12:18 +053085
Vineet Guptaabe11dd2013-01-18 15:12:21 +053086 intc = of_find_compatible_node(NULL, NULL, "snps,arc700-intc");
87 if(!intc)
88 panic("DeviceTree Missing incore intc\n");
Vineet Guptabacdf482013-01-18 15:12:18 +053089
Vineet Guptaabe11dd2013-01-18 15:12:21 +053090 root_domain = irq_domain_add_legacy(intc, NR_IRQS, 0, 0,
91 &arc_intc_domain_ops, NULL);
92
93 if (!root_domain)
94 panic("root irq domain not avail\n");
95
96 /* with this we don't need to export root_domain */
97 irq_set_default_host(root_domain);
Vineet Guptabacdf482013-01-18 15:12:18 +053098}
99
100/*
101 * Late Interrupt system init called from start_kernel for Boot CPU only
102 *
103 * Since slab must already be initialized, platforms can start doing any
104 * needed request_irq( )s
105 */
106void __init init_IRQ(void)
107{
108 init_onchip_IRQ();
109 plat_init_IRQ();
110}
111
112/*
113 * "C" Entry point for any ARC ISR, called from low level vector handler
114 * @irq is the vector number read from ICAUSE reg of on-chip intc
115 */
116void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
117{
118 struct pt_regs *old_regs = set_irq_regs(regs);
119
120 irq_enter();
121 generic_handle_irq(irq);
122 irq_exit();
123 set_irq_regs(old_regs);
124}
125
126int __init get_hw_config_num_irq(void)
127{
128 uint32_t val = read_aux_reg(ARC_REG_VECBASE_BCR);
129
130 switch (val & 0x03) {
131 case 0:
132 return 16;
133 case 1:
134 return 32;
135 case 2:
136 return 8;
137 default:
138 return 0;
139 }
140
141 return 0;
142}
Vineet Guptaac4c2442013-01-18 15:12:16 +0530143
144void arch_local_irq_enable(void)
145{
146 unsigned long flags;
147
148 /*
149 * ARC IDE Drivers tries to re-enable interrupts from hard-isr
150 * context which is simply wrong
151 */
152 if (in_irq()) {
153 WARN_ONCE(1, "IRQ enabled from hard-isr");
154 return;
155 }
156
157 flags = arch_local_save_flags();
158 flags |= (STATUS_E1_MASK | STATUS_E2_MASK);
159 arch_local_irq_restore(flags);
160}
161EXPORT_SYMBOL(arch_local_irq_enable);