Commit f84f1f462bfaf0e45511f97ef54068b8539a7af6

Authored by Mark Salter
1 parent b3f8956210

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 {