aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/include/asm/netlogic/mips-extns.h79
-rw-r--r--arch/mips/netlogic/common/irq.c39
-rw-r--r--arch/mips/netlogic/common/smp.c8
3 files changed, 98 insertions, 28 deletions
diff --git a/arch/mips/include/asm/netlogic/mips-extns.h b/arch/mips/include/asm/netlogic/mips-extns.h
index 32ba6d95d47c..cc4296595df5 100644
--- a/arch/mips/include/asm/netlogic/mips-extns.h
+++ b/arch/mips/include/asm/netlogic/mips-extns.h
@@ -68,6 +68,85 @@ do { \
68 __write_64bit_c0_register($9, 7, (val)); \ 68 __write_64bit_c0_register($9, 7, (val)); \
69} while (0) 69} while (0)
70 70
71/*
72 * Handling the 64 bit EIMR and EIRR registers in 32-bit mode with
73 * standard functions will be very inefficient. This provides
74 * optimized functions for the normal operations on the registers.
75 *
76 * Call with interrupts disabled.
77 */
78static inline void ack_c0_eirr(int irq)
79{
80 __asm__ __volatile__(
81 ".set push\n\t"
82 ".set mips64\n\t"
83 ".set noat\n\t"
84 "li $1, 1\n\t"
85 "dsllv $1, $1, %0\n\t"
86 "dmtc0 $1, $9, 6\n\t"
87 ".set pop"
88 : : "r" (irq));
89}
90
91static inline void set_c0_eimr(int irq)
92{
93 __asm__ __volatile__(
94 ".set push\n\t"
95 ".set mips64\n\t"
96 ".set noat\n\t"
97 "li $1, 1\n\t"
98 "dsllv %0, $1, %0\n\t"
99 "dmfc0 $1, $9, 7\n\t"
100 "or $1, %0\n\t"
101 "dmtc0 $1, $9, 7\n\t"
102 ".set pop"
103 : "+r" (irq));
104}
105
106static inline void clear_c0_eimr(int irq)
107{
108 __asm__ __volatile__(
109 ".set push\n\t"
110 ".set mips64\n\t"
111 ".set noat\n\t"
112 "li $1, 1\n\t"
113 "dsllv %0, $1, %0\n\t"
114 "dmfc0 $1, $9, 7\n\t"
115 "or $1, %0\n\t"
116 "xor $1, %0\n\t"
117 "dmtc0 $1, $9, 7\n\t"
118 ".set pop"
119 : "+r" (irq));
120}
121
122/*
123 * Read c0 eimr and c0 eirr, do AND of the two values, the result is
124 * the interrupts which are raised and are not masked.
125 */
126static inline uint64_t read_c0_eirr_and_eimr(void)
127{
128 uint64_t val;
129
130#ifdef CONFIG_64BIT
131 val = read_c0_eimr() & read_c0_eirr();
132#else
133 __asm__ __volatile__(
134 ".set push\n\t"
135 ".set mips64\n\t"
136 ".set noat\n\t"
137 "dmfc0 %M0, $9, 6\n\t"
138 "dmfc0 %L0, $9, 7\n\t"
139 "and %M0, %L0\n\t"
140 "dsll %L0, %M0, 32\n\t"
141 "dsra %M0, %M0, 32\n\t"
142 "dsra %L0, %L0, 32\n\t"
143 ".set pop"
144 : "=r" (val));
145#endif
146
147 return val;
148}
149
71static inline int hard_smp_processor_id(void) 150static inline int hard_smp_processor_id(void)
72{ 151{
73 return __read_32bit_c0_register($15, 1) & 0x3ff; 152 return __read_32bit_c0_register($15, 1) & 0x3ff;
diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c
index 00dcc7a2bc5a..d42cd1a2a124 100644
--- a/arch/mips/netlogic/common/irq.c
+++ b/arch/mips/netlogic/common/irq.c
@@ -105,21 +105,23 @@ static void xlp_pic_disable(struct irq_data *d)
105static void xlp_pic_mask_ack(struct irq_data *d) 105static void xlp_pic_mask_ack(struct irq_data *d)
106{ 106{
107 struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d); 107 struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
108 uint64_t mask = 1ull << pd->picirq;
109 108
110 write_c0_eirr(mask); /* ack by writing EIRR */ 109 clear_c0_eimr(pd->picirq);
110 ack_c0_eirr(pd->picirq);
111} 111}
112 112
113static void xlp_pic_unmask(struct irq_data *d) 113static void xlp_pic_unmask(struct irq_data *d)
114{ 114{
115 struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d); 115 struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
116 116
117 if (!pd) 117 BUG_ON(!pd);
118 return;
119 118
120 if (pd->extra_ack) 119 if (pd->extra_ack)
121 pd->extra_ack(d); 120 pd->extra_ack(d);
122 121
122 /* re-enable the intr on this cpu */
123 set_c0_eimr(pd->picirq);
124
123 /* Ack is a single write, no need to lock */ 125 /* Ack is a single write, no need to lock */
124 nlm_pic_ack(pd->node->picbase, pd->irt); 126 nlm_pic_ack(pd->node->picbase, pd->irt);
125} 127}
@@ -134,32 +136,17 @@ static struct irq_chip xlp_pic = {
134 136
135static void cpuintr_disable(struct irq_data *d) 137static void cpuintr_disable(struct irq_data *d)
136{ 138{
137 uint64_t eimr; 139 clear_c0_eimr(d->irq);
138 uint64_t mask = 1ull << d->irq;
139
140 eimr = read_c0_eimr();
141 write_c0_eimr(eimr & ~mask);
142} 140}
143 141
144static void cpuintr_enable(struct irq_data *d) 142static void cpuintr_enable(struct irq_data *d)
145{ 143{
146 uint64_t eimr; 144 set_c0_eimr(d->irq);
147 uint64_t mask = 1ull << d->irq;
148
149 eimr = read_c0_eimr();
150 write_c0_eimr(eimr | mask);
151} 145}
152 146
153static void cpuintr_ack(struct irq_data *d) 147static void cpuintr_ack(struct irq_data *d)
154{ 148{
155 uint64_t mask = 1ull << d->irq; 149 ack_c0_eirr(d->irq);
156
157 write_c0_eirr(mask);
158}
159
160static void cpuintr_nop(struct irq_data *d)
161{
162 WARN(d->irq >= PIC_IRQ_BASE, "Bad irq %d", d->irq);
163} 150}
164 151
165/* 152/*
@@ -170,9 +157,9 @@ struct irq_chip nlm_cpu_intr = {
170 .name = "XLP-CPU-INTR", 157 .name = "XLP-CPU-INTR",
171 .irq_enable = cpuintr_enable, 158 .irq_enable = cpuintr_enable,
172 .irq_disable = cpuintr_disable, 159 .irq_disable = cpuintr_disable,
173 .irq_mask = cpuintr_nop, 160 .irq_mask = cpuintr_disable,
174 .irq_ack = cpuintr_nop, 161 .irq_ack = cpuintr_ack,
175 .irq_eoi = cpuintr_ack, 162 .irq_eoi = cpuintr_enable,
176}; 163};
177 164
178static void __init nlm_init_percpu_irqs(void) 165static void __init nlm_init_percpu_irqs(void)
@@ -265,7 +252,7 @@ asmlinkage void plat_irq_dispatch(void)
265 int i, node; 252 int i, node;
266 253
267 node = nlm_nodeid(); 254 node = nlm_nodeid();
268 eirr = read_c0_eirr() & read_c0_eimr(); 255 eirr = read_c0_eirr_and_eimr();
269 256
270 i = __ilog2_u64(eirr); 257 i = __ilog2_u64(eirr);
271 if (i == -1) 258 if (i == -1)
diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c
index a080d9ee3cd7..2bb95dcfe20a 100644
--- a/arch/mips/netlogic/common/smp.c
+++ b/arch/mips/netlogic/common/smp.c
@@ -84,15 +84,19 @@ void nlm_send_ipi_mask(const struct cpumask *mask, unsigned int action)
84/* IRQ_IPI_SMP_FUNCTION Handler */ 84/* IRQ_IPI_SMP_FUNCTION Handler */
85void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc) 85void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc)
86{ 86{
87 write_c0_eirr(1ull << irq); 87 clear_c0_eimr(irq);
88 ack_c0_eirr(irq);
88 smp_call_function_interrupt(); 89 smp_call_function_interrupt();
90 set_c0_eimr(irq);
89} 91}
90 92
91/* IRQ_IPI_SMP_RESCHEDULE handler */ 93/* IRQ_IPI_SMP_RESCHEDULE handler */
92void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc) 94void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc)
93{ 95{
94 write_c0_eirr(1ull << irq); 96 clear_c0_eimr(irq);
97 ack_c0_eirr(irq);
95 scheduler_ipi(); 98 scheduler_ipi();
99 set_c0_eimr(irq);
96} 100}
97 101
98/* 102/*