diff options
author | Guo Ren <ren_guo@c-sky.com> | 2019-06-06 03:37:31 -0400 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2019-06-11 07:28:13 -0400 |
commit | 648f835a028f4f7f031a89bc099e363d4292e5b9 (patch) | |
tree | 7f6b13c4dd10d1b1f6a129ebd0a0c2342c5148f9 /drivers/irqchip | |
parent | 17c88892094973acd7176b794eff21abf24779fc (diff) |
irqchip/irq-csky-mpintc: Add triger type
Support 4 triger types:
- IRQ_TYPE_LEVEL_HIGH
- IRQ_TYPE_LEVEL_LOW
- IRQ_TYPE_EDGE_RISING
- IRQ_TYPE_EDGE_FALLING
All of above could be set in DeviceTree file and it still compatible
with the old DeviceTree format.
Signed-off-by: Guo Ren <ren_guo@c-sky.com>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r-- | drivers/irqchip/irq-csky-mpintc.c | 78 |
1 files changed, 77 insertions, 1 deletions
diff --git a/drivers/irqchip/irq-csky-mpintc.c b/drivers/irqchip/irq-csky-mpintc.c index c67c961ab6cc..4457722cdd18 100644 --- a/drivers/irqchip/irq-csky-mpintc.c +++ b/drivers/irqchip/irq-csky-mpintc.c | |||
@@ -32,6 +32,7 @@ static void __iomem *INTCL_base; | |||
32 | #define INTCG_CIDSTR 0x1000 | 32 | #define INTCG_CIDSTR 0x1000 |
33 | 33 | ||
34 | #define INTCL_PICTLR 0x0 | 34 | #define INTCL_PICTLR 0x0 |
35 | #define INTCL_CFGR 0x14 | ||
35 | #define INTCL_SIGR 0x60 | 36 | #define INTCL_SIGR 0x60 |
36 | #define INTCL_HPPIR 0x68 | 37 | #define INTCL_HPPIR 0x68 |
37 | #define INTCL_RDYIR 0x6c | 38 | #define INTCL_RDYIR 0x6c |
@@ -41,6 +42,35 @@ static void __iomem *INTCL_base; | |||
41 | 42 | ||
42 | static DEFINE_PER_CPU(void __iomem *, intcl_reg); | 43 | static DEFINE_PER_CPU(void __iomem *, intcl_reg); |
43 | 44 | ||
45 | static unsigned long *__trigger; | ||
46 | |||
47 | #define IRQ_OFFSET(irq) ((irq < COMM_IRQ_BASE) ? irq : (irq - COMM_IRQ_BASE)) | ||
48 | |||
49 | #define TRIG_BYTE_OFFSET(i) ((((i) * 2) / 32) * 4) | ||
50 | #define TRIG_BIT_OFFSET(i) (((i) * 2) % 32) | ||
51 | |||
52 | #define TRIG_VAL(trigger, irq) (trigger << TRIG_BIT_OFFSET(IRQ_OFFSET(irq))) | ||
53 | #define TRIG_VAL_MSK(irq) (~(3 << TRIG_BIT_OFFSET(IRQ_OFFSET(irq)))) | ||
54 | |||
55 | #define TRIG_BASE(irq) \ | ||
56 | (TRIG_BYTE_OFFSET(IRQ_OFFSET(irq)) + ((irq < COMM_IRQ_BASE) ? \ | ||
57 | (this_cpu_read(intcl_reg) + INTCL_CFGR) : (INTCG_base + INTCG_CICFGR))) | ||
58 | |||
59 | static DEFINE_SPINLOCK(setup_lock); | ||
60 | static void setup_trigger(unsigned long irq, unsigned long trigger) | ||
61 | { | ||
62 | unsigned int tmp; | ||
63 | |||
64 | spin_lock(&setup_lock); | ||
65 | |||
66 | /* setup trigger */ | ||
67 | tmp = readl_relaxed(TRIG_BASE(irq)) & TRIG_VAL_MSK(irq); | ||
68 | |||
69 | writel_relaxed(tmp | TRIG_VAL(trigger, irq), TRIG_BASE(irq)); | ||
70 | |||
71 | spin_unlock(&setup_lock); | ||
72 | } | ||
73 | |||
44 | static void csky_mpintc_handler(struct pt_regs *regs) | 74 | static void csky_mpintc_handler(struct pt_regs *regs) |
45 | { | 75 | { |
46 | void __iomem *reg_base = this_cpu_read(intcl_reg); | 76 | void __iomem *reg_base = this_cpu_read(intcl_reg); |
@@ -56,6 +86,8 @@ static void csky_mpintc_enable(struct irq_data *d) | |||
56 | { | 86 | { |
57 | void __iomem *reg_base = this_cpu_read(intcl_reg); | 87 | void __iomem *reg_base = this_cpu_read(intcl_reg); |
58 | 88 | ||
89 | setup_trigger(d->hwirq, __trigger[d->hwirq]); | ||
90 | |||
59 | writel_relaxed(d->hwirq, reg_base + INTCL_SENR); | 91 | writel_relaxed(d->hwirq, reg_base + INTCL_SENR); |
60 | } | 92 | } |
61 | 93 | ||
@@ -73,6 +105,28 @@ static void csky_mpintc_eoi(struct irq_data *d) | |||
73 | writel_relaxed(d->hwirq, reg_base + INTCL_CACR); | 105 | writel_relaxed(d->hwirq, reg_base + INTCL_CACR); |
74 | } | 106 | } |
75 | 107 | ||
108 | static int csky_mpintc_set_type(struct irq_data *d, unsigned int type) | ||
109 | { | ||
110 | switch (type & IRQ_TYPE_SENSE_MASK) { | ||
111 | case IRQ_TYPE_LEVEL_HIGH: | ||
112 | __trigger[d->hwirq] = 0; | ||
113 | break; | ||
114 | case IRQ_TYPE_LEVEL_LOW: | ||
115 | __trigger[d->hwirq] = 1; | ||
116 | break; | ||
117 | case IRQ_TYPE_EDGE_RISING: | ||
118 | __trigger[d->hwirq] = 2; | ||
119 | break; | ||
120 | case IRQ_TYPE_EDGE_FALLING: | ||
121 | __trigger[d->hwirq] = 3; | ||
122 | break; | ||
123 | default: | ||
124 | return -EINVAL; | ||
125 | } | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
76 | #ifdef CONFIG_SMP | 130 | #ifdef CONFIG_SMP |
77 | static int csky_irq_set_affinity(struct irq_data *d, | 131 | static int csky_irq_set_affinity(struct irq_data *d, |
78 | const struct cpumask *mask_val, | 132 | const struct cpumask *mask_val, |
@@ -105,6 +159,7 @@ static struct irq_chip csky_irq_chip = { | |||
105 | .irq_eoi = csky_mpintc_eoi, | 159 | .irq_eoi = csky_mpintc_eoi, |
106 | .irq_enable = csky_mpintc_enable, | 160 | .irq_enable = csky_mpintc_enable, |
107 | .irq_disable = csky_mpintc_disable, | 161 | .irq_disable = csky_mpintc_disable, |
162 | .irq_set_type = csky_mpintc_set_type, | ||
108 | #ifdef CONFIG_SMP | 163 | #ifdef CONFIG_SMP |
109 | .irq_set_affinity = csky_irq_set_affinity, | 164 | .irq_set_affinity = csky_irq_set_affinity, |
110 | #endif | 165 | #endif |
@@ -125,9 +180,26 @@ static int csky_irqdomain_map(struct irq_domain *d, unsigned int irq, | |||
125 | return 0; | 180 | return 0; |
126 | } | 181 | } |
127 | 182 | ||
183 | static int csky_irq_domain_xlate_cells(struct irq_domain *d, | ||
184 | struct device_node *ctrlr, const u32 *intspec, | ||
185 | unsigned int intsize, unsigned long *out_hwirq, | ||
186 | unsigned int *out_type) | ||
187 | { | ||
188 | if (WARN_ON(intsize < 1)) | ||
189 | return -EINVAL; | ||
190 | |||
191 | *out_hwirq = intspec[0]; | ||
192 | if (intsize > 1) | ||
193 | *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK; | ||
194 | else | ||
195 | *out_type = IRQ_TYPE_LEVEL_HIGH; | ||
196 | |||
197 | return 0; | ||
198 | } | ||
199 | |||
128 | static const struct irq_domain_ops csky_irqdomain_ops = { | 200 | static const struct irq_domain_ops csky_irqdomain_ops = { |
129 | .map = csky_irqdomain_map, | 201 | .map = csky_irqdomain_map, |
130 | .xlate = irq_domain_xlate_onecell, | 202 | .xlate = csky_irq_domain_xlate_cells, |
131 | }; | 203 | }; |
132 | 204 | ||
133 | #ifdef CONFIG_SMP | 205 | #ifdef CONFIG_SMP |
@@ -161,6 +233,10 @@ csky_mpintc_init(struct device_node *node, struct device_node *parent) | |||
161 | if (ret < 0) | 233 | if (ret < 0) |
162 | nr_irq = INTC_IRQS; | 234 | nr_irq = INTC_IRQS; |
163 | 235 | ||
236 | __trigger = kcalloc(nr_irq, sizeof(unsigned long), GFP_KERNEL); | ||
237 | if (__trigger == NULL) | ||
238 | return -ENXIO; | ||
239 | |||
164 | if (INTCG_base == NULL) { | 240 | if (INTCG_base == NULL) { |
165 | INTCG_base = ioremap(mfcr("cr<31, 14>"), | 241 | INTCG_base = ioremap(mfcr("cr<31, 14>"), |
166 | INTCL_SIZE*nr_cpu_ids + INTCG_SIZE); | 242 | INTCL_SIZE*nr_cpu_ids + INTCG_SIZE); |