1/*  *********************************************************************
2    *  SB1250 Board Support Package
3    *
4    *  IRQ polling				File: sb1250_ircpoll.S
5    *
6    *  This module contains code to poll the interrupt controller
7    *  and invoke the servicing of pending, unmasked interrupts.
8    *
9    *********************************************************************
10    *
11    *  Copyright 2000,2001,2002,2003
12    *  Broadcom Corporation. All rights reserved.
13    *
14    *  This software is furnished under license and may be used and
15    *  copied only in accordance with the following terms and
16    *  conditions.  Subject to these conditions, you may download,
17    *  copy, install, use, modify and distribute modified or unmodified
18    *  copies of this software in source and/or binary form.  No title
19    *  or ownership is transferred hereby.
20    *
21    *  1) Any source code used, modified or distributed must reproduce
22    *     and retain this copyright notice and list of conditions
23    *     as they appear in the source file.
24    *
25    *  2) No right is granted to use any trade name, trademark, or
26    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
27    *     name may not be used to endorse or promote products derived
28    *     from this software without the prior written permission of
29    *     Broadcom Corporation.
30    *
31    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
32    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
33    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
34    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
35    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
36    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
37    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
39    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
40    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
41    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
42    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
43    *     THE POSSIBILITY OF SUCH DAMAGE.
44    ********************************************************************* */
45
46#include "sbmips.h"
47#include "cpu_config.h"
48#include "mipsmacros.h"
49#include "sb1250_regs.h"
50#include "sb1250_int.h"
51
52/*
53 * External interrupt conventions:
54 *   i5 (IP7) is reserved for sources within the CPU
55 *   i0 (IP2) is used for polling and always masked
56 *   i1 (IP3) is used for armed interrupts that are registered (not yet)
57 *   i2-i4 are available for specific devices.
58 */
59
60/* EOIs are issued when LDT interrupts are programmed as levels. */
61
62#define A_LDT_EOI PHYS_TO_XKPHYS_UNCACHED(0x00D8000000)
63#define D_EOI_MDT (0x7 << 2)
64
65	.text
66
67/*  *********************************************************************
68    *  CFE_IRQ_POLL
69    *
70    *  Scan the interrupt_source_status and interrupt_ldt registers.
71    *  For those not masked by the interrupt_mask register, invoke
72    *  <cpu>_dispatch_irq with the interrupt number as argument.
73    *
74    *  For LDT-signaled interrupts, also clear the pending vector.
75    *
76    *  For asynchronous dispatch, called with interrupts disabled.
77    *
78    *  Input parameters:
79    *  	   nothing
80    *
81    *  Return value:
82    *  	   nothing
83    ********************************************************************* */
84
85	.set    push
86	.set	noreorder
87	.set	noat
88	.set    mips64
89
90	.extern	sb1250_dispatch_irq	/* NB: accessed via gp */
91
92#if 1
93	 /* This version accomodates level-triggered LDT interrupts by
94	issuing EOI's on return from each handler.  In pass 1 chips,
95	EOIs are not issued correctly and will not clear a
96	level-triggered interrupt.  Thus only edge-triggered mode
97	should be used in pass 1.  This code depends on the fact that
98	an EOI will cause a level-sensitive interrupt to resend the
99	interrupt message if that interrupt is still pending.  It is
100	not safe for edge-triggered interrupts.  See below for a
101	version that avoids EOIs.  */
102
103	/* Note that and'ing the interrupt_mask and interrupt_status
104	effectively merges processing of all IP levels.  Reading
105	interrupt status[n] will be a better strategy when we know n.
106	We still need to determine which bits are sourced by LDT and
107	potentially require EOIs. */
108
109LEAF(cfe_irq_poll)
110
111	daddiu	sp, -72		/* saved register space */
112	sd	s0, 32(sp)
113	sd	s1, 40(sp)
114	sd	s2, 48(sp)
115	sd	s3, 56(sp)
116	sd	ra, 64(sp)
117
118	mfc0	a0, C0_CAUSE
119	andi	a0, a0, M_CAUSE_IP2
120	beqz	a0, 5f
121
122	la	v0, K1BASE + A_IMR_CPU0_BASE
123	ld	a1, R_IMR_INTERRUPT_MASK(v0)
124        ld	s0, R_IMR_INTERRUPT_SOURCE_STATUS(v0)
125	ld	s2, R_IMR_LDT_INTERRUPT(v0)
126        nor	a1, a1, zero	/* Negate mask to turn it into an and mask */
127	or	s0, s0, s2	/* Unified pending bits */
128	and	s0, s0, a1	/* Bit vector of unmasked pending IRQs */
129	beqz	s0, 5f		/* No interrupts.  Return */
130	and	s2, s2, a1      /* ... and unmasked LDT IRQs */
131
132	/* The bit scan loop */
133	dclz	s1, s0		/* Find index of the next interrupt */
1343:
135	li	s3, 1
136	dsubu	s1, zero, s1
137	daddiu	s1, s1, 63
138	dsllv	s3, s3, s1
139	xor	s0, s0, s3	/* clear current bit */
140	la	t9, sb1250_dispatch_irq
141	jalr	ra, t9		/* NB:	 SVR4 PIC requires t9 */
142	move	a0, s1		/* a0 is interrupt number */
143
144	and	a0, s2, s3
145	beqz	a0, 4f		/* not LDT */
146	dsll	s1, s1, 16
147
148	/* Clear the latched bit and send EOI if a pending LDT interrupt */
149	la	v0, K1BASE + A_IMR_CPU0_BASE
150	sd	s3, R_IMR_LDT_INTERRUPT_CLR(v0)
151	dla	v0, A_LDT_EOI
152	or	v0, v0, s1
153	sync
154
155	mfc0	s3, C0_SR
156	ori	AT, s3, M_SR_KX
157	mtc0	AT, C0_SR
158	HAZARD
159
160	sw	zero, D_EOI_MDT(v0)
161
162	mtc0	s3, C0_SR
163	HAZARD
164
1654:
166	bnez	s0, 3b		/* More interrupts to service?       */
167	dclz	s1, s0		/* unroll for branch delay slot */
1685:
169	ld	ra, 64(sp)	/* restore registers */
170	ld	s3, 56(sp)
171	ld	s2, 48(sp)
172	ld	s1, 40(sp)
173	ld	s0, 32(sp)
174
175	jr	ra
176	daddiu	sp, 72		/* saved register space */
177
178END(cfe_irq_poll)
179
180#else
181	/* The version for only edge-triggered LDT interrupts. */
182
183        /* This version also shows one way of saving 64-bit registers
184	in systems that don't necessarily preserve the high 32 bits
185	across subroutine calls.  That is not an issue for CFE with
186	current compilation options but is required for, e.g., 32-bit
187	Linux and NetBSD systems. */
188
189LEAF(cfe_irq_poll)
190
191	daddiu	sp, -56		/* saved register space */
192	sd	s0, 32(sp)
193	sd	s1, 40(sp)
194	sd	ra, 48(sp)
195
196	mfc0	a0, C0_CAUSE
197	andi	a0, a0, M_CAUSE_IP2
198	beqz	a0, 4f
199
200	la	v0, K1BASE + A_IMR_CPU0_BASE
201	ld	a1, R_IMR_INTERRUPT_MASK(v0)
202        ld	s0, R_IMR_INTERRUPT_SOURCE_STATUS(v0)
203	ld	s1, R_IMR_LDT_INTERRUPT(v0)
204        nor	a1, a1, zero	/* Negate mask to turn it into an and mask */
205	or	s0, s0, s1	/* Unified pending bits */
206	and	s0, s0, a1	/* Bit vector of unmasked pending IRQs */
207	and	s1, s1, a1      /* ... and unmasked LDT IRQs */
208	beqz	s0, 4f		/* No interrupts.  Return */
209	nop
210
211	/* Clear the accumulated LDT (edge-triggered) interrupts */
212	sd	s1, R_IMR_LDT_INTERRUPT_CLR(v0)
213
214	/* The bit scan loop */
215	dclz	s1, s0		/* Find index of the next interrupt */
2163:
217	li	a1, 1
218	dsubu	a0, zero, s1
219	daddiu	a0, a0, 63
220	dsllv	a1, a1, a0
221	xor	s0, s0, a1	/* clear current bit */
222	la	t9, sb1250_dispatch_irq
223	jalr	ra, t9		/* NB:	 SVR4 PIC requires t9 */
224	dsrl32	s1, s0, 0	/* Save upper 32 bits of unified vector */
225
226	dsll32	s0, s0, 0	/* clear upper bits of s0            */
227	dsll32	s1, s1, 0	/* get saved back in the right place */
228	dsrl32	s0, s0, 0	/* realign s0                        */
229	or	s0, s0, s1	/* restore the saved bits            */
230	bnez	s0, 3b		/* More interrupts to service?       */
231	dclz	s1, s0		/* unroll for branch delay slot */
2324:
233	ld	ra, 48(sp)	/* restore registers */
234	ld	s1, 40(sp)
235	ld	s0, 32(sp)
236
237	jr	ra
238	daddiu	sp, 56		/* saved register space */
239
240END(cfe_irq_poll)
241
242#endif
243
244	.set	pop
245
246
247/*  *********************************************************************
248    * sb1250_irq_arm()
249    *
250    * Set up CP0 Status and Cause per conventions above (not really -- yet)
251    *
252    * This function should be called with interrupts disabled.
253    *
254    * Input parameters:
255    *	nothing
256    *
257    * Return value:
258    *	nothing
259    ********************************************************************* */
260
261	.set    push
262	.set	noreorder
263	.set    mips64
264
265LEAF(sb1250_irq_arm)
266
267	mfc0	t0,C0_CAUSE
268	or	t0,t0,M_CAUSE_IV
269	mtc0	t0,C0_CAUSE
270
271	mfc0	t0,C0_SR
272	li	t1,M_SR_IMMASK		/* Mask all interrupt levels */
273	nor	t1,t1,zero
274	and	t0,t0,t1
275	or	t0,t0,M_SR_IE		/* but set IE */
276	mtc0	t0,C0_SR
277
278	HAZARD
279
280	jr	ra
281	nop
282
283END(sb1250_irq_arm)
284
285	.set	pop
286
287
288
289/*  *********************************************************************
290    * cfe_irq_disable()
291    *
292    * Disable interrupts
293    * XXX: This is not really atomic.
294    *
295    * Input parameters:
296    *	none
297    *
298    * Return value:
299    *	current SR interrupt mask
300    ********************************************************************* */
301
302	.set    push
303	.set	noreorder
304	.set    mips64
305
306LEAF(cfe_irq_disable)
307
308	mfc0	t0,C0_SR
309	li	t1,M_SR_IMMASK|M_SR_IE
310	li	t2,~(M_SR_IMMASK|M_SR_IE)
311	and	v0,t0,t1                /* current mask bits */
312	and	t0,t0,t2
313	mtc0	t0,C0_SR                /* all enables cleared */
314
315	HAZARD
316
317	jr	ra
318	nop
319
320END(cfe_irq_disable)
321
322	.set	pop
323
324
325/*  *********************************************************************
326    * cfe_irq_enable(mask)
327    *
328    * Restore enabled interrupts
329    * XXX: This is not really atomic.
330    *
331    * Input parameters:
332    *	interrupt mask (from irq_disable)
333    *
334    * Return value:
335    *	nothing
336    ********************************************************************* */
337
338	.set    push
339	.set	noreorder
340	.set    mips64
341
342LEAF(cfe_irq_enable)
343
344	mfc0	t0,C0_SR
345	li	t1,M_SR_IMMASK|M_SR_IE
346	li	t2,~(M_SR_IMMASK|M_SR_IE)
347	and	a0,a0,t1
348	and	t0,t0,t2
349	or	t0,t0,a0
350	mtc0	t0,C0_SR
351
352	HAZARD
353
354	jr	ra
355	nop
356
357END(cfe_irq_enable)
358
359	.set	pop
360
361
362/*  *********************************************************************
363    * sb1250_update_sr(clear,set)
364    *
365    * Upate Status.IM according to masks
366    *
367    * Caller should disable interrupts if the effect is to be atomic.
368    *
369    * Input parameters:
370    *	a0         SR bits to be cleared
371    *   a1         SR bits to be set
372    *
373    * Return value:
374    *	none
375    ********************************************************************* */
376
377	.set    push
378	.set	noreorder
379	.set    mips64
380
381LEAF(sb1250_update_sr)
382
383	nor	a0,a0,zero
384	mfc0	t0,C0_SR
385	and	t0,t0,a0                /* current mask bits */
386	or	t0,t0,a1
387	mtc0	t0,C0_SR                /* all enables cleared */
388
389	HAZARD
390
391	jr	ra
392	nop
393
394END(sb1250_update_sr)
395
396	.set	pop
397