Commit f84f1f462bfaf0e45511f97ef54068b8539a7af6
1 parent
b3f8956210
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
C6X: remove dependence on legacy IRQs
The core priority PIC code uses legacy irq support to facilitate direct mapping of core hw interrupt numbers to linux interrupt numbers. This patch removes the legacy irq usage and replaces it with a generic linear mapping. Signed-off-by: Mark Salter <msalter@redhat.com>
Showing 2 changed files with 10 additions and 13 deletions Inline Diff
arch/c6x/include/asm/irq.h
1 | /* | 1 | /* |
2 | * Port on Texas Instruments TMS320C6x architecture | 2 | * Port on Texas Instruments TMS320C6x architecture |
3 | * | 3 | * |
4 | * Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated | 4 | * Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated |
5 | * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) | 5 | * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) |
6 | * | 6 | * |
7 | * Large parts taken directly from powerpc. | 7 | * Large parts taken directly from powerpc. |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License version 2 as | 10 | * it under the terms of the GNU General Public License version 2 as |
11 | * published by the Free Software Foundation. | 11 | * published by the Free Software Foundation. |
12 | */ | 12 | */ |
13 | #ifndef _ASM_C6X_IRQ_H | 13 | #ifndef _ASM_C6X_IRQ_H |
14 | #define _ASM_C6X_IRQ_H | 14 | #define _ASM_C6X_IRQ_H |
15 | 15 | ||
16 | #include <linux/irqdomain.h> | 16 | #include <linux/irqdomain.h> |
17 | #include <linux/threads.h> | 17 | #include <linux/threads.h> |
18 | #include <linux/list.h> | 18 | #include <linux/list.h> |
19 | #include <linux/radix-tree.h> | 19 | #include <linux/radix-tree.h> |
20 | #include <asm/percpu.h> | 20 | #include <asm/percpu.h> |
21 | 21 | ||
22 | #define irq_canonicalize(irq) (irq) | 22 | #define irq_canonicalize(irq) (irq) |
23 | 23 | ||
24 | /* | 24 | /* |
25 | * The C64X+ core has 16 IRQ vectors. One each is used by Reset and NMI. Two | 25 | * The C64X+ core has 16 IRQ vectors. One each is used by Reset and NMI. Two |
26 | * are reserved. The remaining 12 vectors are used to route SoC interrupts. | 26 | * are reserved. The remaining 12 vectors are used to route SoC interrupts. |
27 | * These interrupt vectors are prioritized with IRQ 4 having the highest | 27 | * These interrupt vectors are prioritized with IRQ 4 having the highest |
28 | * priority and IRQ 15 having the lowest. | 28 | * priority and IRQ 15 having the lowest. |
29 | * | 29 | * |
30 | * The C64x+ megamodule provides a PIC which combines SoC IRQ sources into a | 30 | * The C64x+ megamodule provides a PIC which combines SoC IRQ sources into a |
31 | * single core IRQ vector. There are four combined sources, each of which | 31 | * single core IRQ vector. There are four combined sources, each of which |
32 | * feed into one of the 12 general interrupt vectors. The remaining 8 vectors | 32 | * feed into one of the 12 general interrupt vectors. The remaining 8 vectors |
33 | * can each route a single SoC interrupt directly. | 33 | * can each route a single SoC interrupt directly. |
34 | */ | 34 | */ |
35 | #define NR_PRIORITY_IRQS 16 | 35 | #define NR_PRIORITY_IRQS 16 |
36 | 36 | ||
37 | #define NR_IRQS_LEGACY NR_PRIORITY_IRQS | ||
38 | |||
39 | /* Total number of virq in the platform */ | 37 | /* Total number of virq in the platform */ |
40 | #define NR_IRQS 256 | 38 | #define NR_IRQS 256 |
41 | 39 | ||
42 | /* This number is used when no interrupt has been assigned */ | 40 | /* This number is used when no interrupt has been assigned */ |
43 | #define NO_IRQ 0 | 41 | #define NO_IRQ 0 |
44 | 42 | ||
45 | extern void __init init_pic_c64xplus(void); | 43 | extern void __init init_pic_c64xplus(void); |
46 | 44 | ||
47 | extern void init_IRQ(void); | 45 | extern void init_IRQ(void); |
48 | 46 | ||
49 | struct pt_regs; | 47 | struct pt_regs; |
50 | 48 | ||
51 | extern asmlinkage void c6x_do_IRQ(unsigned int prio, struct pt_regs *regs); | 49 | extern asmlinkage void c6x_do_IRQ(unsigned int prio, struct pt_regs *regs); |
52 | 50 | ||
53 | extern unsigned long irq_err_count; | 51 | extern unsigned long irq_err_count; |
54 | 52 | ||
55 | #endif /* _ASM_C6X_IRQ_H */ | 53 | #endif /* _ASM_C6X_IRQ_H */ |
56 | 54 |
arch/c6x/kernel/irq.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2011 Texas Instruments Incorporated | 2 | * Copyright (C) 2011-2012 Texas Instruments Incorporated |
3 | * | 3 | * |
4 | * This borrows heavily from powerpc version, which is: | 4 | * This borrows heavily from powerpc version, which is: |
5 | * | 5 | * |
6 | * Derived from arch/i386/kernel/irq.c | 6 | * Derived from arch/i386/kernel/irq.c |
7 | * Copyright (C) 1992 Linus Torvalds | 7 | * Copyright (C) 1992 Linus Torvalds |
8 | * Adapted from arch/i386 by Gary Thomas | 8 | * Adapted from arch/i386 by Gary Thomas |
9 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | 9 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) |
10 | * Updated and modified by Cort Dougan <cort@fsmlabs.com> | 10 | * Updated and modified by Cort Dougan <cort@fsmlabs.com> |
11 | * Copyright (C) 1996-2001 Cort Dougan | 11 | * Copyright (C) 1996-2001 Cort Dougan |
12 | * Adapted for Power Macintosh by Paul Mackerras | 12 | * Adapted for Power Macintosh by Paul Mackerras |
13 | * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) | 13 | * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) |
14 | * | 14 | * |
15 | * This program is free software; you can redistribute it and/or | 15 | * This program is free software; you can redistribute it and/or |
16 | * modify it under the terms of the GNU General Public License | 16 | * modify it under the terms of the GNU General Public License |
17 | * as published by the Free Software Foundation; either version | 17 | * as published by the Free Software Foundation; either version |
18 | * 2 of the License, or (at your option) any later version. | 18 | * 2 of the License, or (at your option) any later version. |
19 | */ | 19 | */ |
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/seq_file.h> | 21 | #include <linux/seq_file.h> |
22 | #include <linux/radix-tree.h> | 22 | #include <linux/radix-tree.h> |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/of.h> | 24 | #include <linux/of.h> |
25 | #include <linux/of_irq.h> | 25 | #include <linux/of_irq.h> |
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/kernel_stat.h> | 27 | #include <linux/kernel_stat.h> |
28 | 28 | ||
29 | #include <asm/megamod-pic.h> | 29 | #include <asm/megamod-pic.h> |
30 | #include <asm/special_insns.h> | 30 | #include <asm/special_insns.h> |
31 | 31 | ||
32 | unsigned long irq_err_count; | 32 | unsigned long irq_err_count; |
33 | 33 | ||
34 | static DEFINE_RAW_SPINLOCK(core_irq_lock); | 34 | static DEFINE_RAW_SPINLOCK(core_irq_lock); |
35 | 35 | ||
36 | static void mask_core_irq(struct irq_data *data) | 36 | static void mask_core_irq(struct irq_data *data) |
37 | { | 37 | { |
38 | unsigned int prio = data->irq; | 38 | unsigned int prio = data->hwirq; |
39 | 39 | ||
40 | BUG_ON(prio < 4 || prio >= NR_PRIORITY_IRQS); | ||
41 | |||
42 | raw_spin_lock(&core_irq_lock); | 40 | raw_spin_lock(&core_irq_lock); |
43 | and_creg(IER, ~(1 << prio)); | 41 | and_creg(IER, ~(1 << prio)); |
44 | raw_spin_unlock(&core_irq_lock); | 42 | raw_spin_unlock(&core_irq_lock); |
45 | } | 43 | } |
46 | 44 | ||
47 | static void unmask_core_irq(struct irq_data *data) | 45 | static void unmask_core_irq(struct irq_data *data) |
48 | { | 46 | { |
49 | unsigned int prio = data->irq; | 47 | unsigned int prio = data->hwirq; |
50 | 48 | ||
51 | raw_spin_lock(&core_irq_lock); | 49 | raw_spin_lock(&core_irq_lock); |
52 | or_creg(IER, 1 << prio); | 50 | or_creg(IER, 1 << prio); |
53 | raw_spin_unlock(&core_irq_lock); | 51 | raw_spin_unlock(&core_irq_lock); |
54 | } | 52 | } |
55 | 53 | ||
56 | static struct irq_chip core_chip = { | 54 | static struct irq_chip core_chip = { |
57 | .name = "core", | 55 | .name = "core", |
58 | .irq_mask = mask_core_irq, | 56 | .irq_mask = mask_core_irq, |
59 | .irq_unmask = unmask_core_irq, | 57 | .irq_unmask = unmask_core_irq, |
60 | }; | 58 | }; |
61 | 59 | ||
60 | static int prio_to_virq[NR_PRIORITY_IRQS]; | ||
61 | |||
62 | asmlinkage void c6x_do_IRQ(unsigned int prio, struct pt_regs *regs) | 62 | asmlinkage void c6x_do_IRQ(unsigned int prio, struct pt_regs *regs) |
63 | { | 63 | { |
64 | struct pt_regs *old_regs = set_irq_regs(regs); | 64 | struct pt_regs *old_regs = set_irq_regs(regs); |
65 | 65 | ||
66 | irq_enter(); | 66 | irq_enter(); |
67 | 67 | ||
68 | BUG_ON(prio < 4 || prio >= NR_PRIORITY_IRQS); | 68 | generic_handle_irq(prio_to_virq[prio]); |
69 | 69 | ||
70 | generic_handle_irq(prio); | ||
71 | |||
72 | irq_exit(); | 70 | irq_exit(); |
73 | 71 | ||
74 | set_irq_regs(old_regs); | 72 | set_irq_regs(old_regs); |
75 | } | 73 | } |
76 | 74 | ||
77 | static struct irq_domain *core_domain; | 75 | static struct irq_domain *core_domain; |
78 | 76 | ||
79 | static int core_domain_map(struct irq_domain *h, unsigned int virq, | 77 | static int core_domain_map(struct irq_domain *h, unsigned int virq, |
80 | irq_hw_number_t hw) | 78 | irq_hw_number_t hw) |
81 | { | 79 | { |
82 | if (hw < 4 || hw >= NR_PRIORITY_IRQS) | 80 | if (hw < 4 || hw >= NR_PRIORITY_IRQS) |
83 | return -EINVAL; | 81 | return -EINVAL; |
84 | 82 | ||
83 | prio_to_virq[hw] = virq; | ||
84 | |||
85 | irq_set_status_flags(virq, IRQ_LEVEL); | 85 | irq_set_status_flags(virq, IRQ_LEVEL); |
86 | irq_set_chip_and_handler(virq, &core_chip, handle_level_irq); | 86 | irq_set_chip_and_handler(virq, &core_chip, handle_level_irq); |
87 | return 0; | 87 | return 0; |
88 | } | 88 | } |
89 | 89 | ||
90 | static const struct irq_domain_ops core_domain_ops = { | 90 | static const struct irq_domain_ops core_domain_ops = { |
91 | .map = core_domain_map, | 91 | .map = core_domain_map, |
92 | .xlate = irq_domain_xlate_onecell, | 92 | .xlate = irq_domain_xlate_onecell, |
93 | }; | 93 | }; |
94 | 94 | ||
95 | void __init init_IRQ(void) | 95 | void __init init_IRQ(void) |
96 | { | 96 | { |
97 | struct device_node *np; | 97 | struct device_node *np; |
98 | 98 | ||
99 | /* Mask all priority IRQs */ | 99 | /* Mask all priority IRQs */ |
100 | and_creg(IER, ~0xfff0); | 100 | and_creg(IER, ~0xfff0); |
101 | 101 | ||
102 | np = of_find_compatible_node(NULL, NULL, "ti,c64x+core-pic"); | 102 | np = of_find_compatible_node(NULL, NULL, "ti,c64x+core-pic"); |
103 | if (np != NULL) { | 103 | if (np != NULL) { |
104 | /* create the core host */ | 104 | /* create the core host */ |
105 | core_domain = irq_domain_add_legacy(np, NR_PRIORITY_IRQS, | 105 | core_domain = irq_domain_add_linear(np, NR_PRIORITY_IRQS, |
106 | 0, 0, &core_domain_ops, | 106 | &core_domain_ops, NULL); |
107 | NULL); | ||
108 | if (core_domain) | 107 | if (core_domain) |
109 | irq_set_default_host(core_domain); | 108 | irq_set_default_host(core_domain); |
110 | of_node_put(np); | 109 | of_node_put(np); |
111 | } | 110 | } |
112 | 111 | ||
113 | printk(KERN_INFO "Core interrupt controller initialized\n"); | 112 | printk(KERN_INFO "Core interrupt controller initialized\n"); |
114 | 113 | ||
115 | /* now we're ready for other SoC controllers */ | 114 | /* now we're ready for other SoC controllers */ |
116 | megamod_pic_init(); | 115 | megamod_pic_init(); |
117 | 116 | ||
118 | /* Clear all general IRQ flags */ | 117 | /* Clear all general IRQ flags */ |
119 | set_creg(ICR, 0xfff0); | 118 | set_creg(ICR, 0xfff0); |
120 | } | 119 | } |
121 | 120 | ||
122 | void ack_bad_irq(int irq) | 121 | void ack_bad_irq(int irq) |
123 | { | 122 | { |
124 | printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq); | 123 | printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq); |
125 | irq_err_count++; | 124 | irq_err_count++; |
126 | } | 125 | } |
127 | 126 | ||
128 | int arch_show_interrupts(struct seq_file *p, int prec) | 127 | int arch_show_interrupts(struct seq_file *p, int prec) |
129 | { | 128 | { |