|
1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // omap3530/assp/src/interrupts.cpp |
|
15 // Template ASSP interrupt control and dispatch |
|
16 // |
|
17 |
|
18 #include <assp/omap3530_assp/omap3530_assp_priv.h> |
|
19 #include <assp/omap3530_assp/omap3530_irqmap.h> |
|
20 #include <assp/omap3530_assp/locks.h> |
|
21 |
|
22 SInterruptHandler Omap3530Interrupt::Handlers[KNumOmap3530Ints]; |
|
23 MInterruptDispatcher* TheDispatchers[ KIrqRangeCount ]; |
|
24 |
|
25 #define OMAP3530_INTERRUPTS_INC |
|
26 |
|
27 #ifndef OMAP3530_INTERRUPTS_INC |
|
28 //TODO: Implement the asm IRQ & FIQ dispatcher |
|
29 #include "interrupts.cia" |
|
30 |
|
31 #else |
|
32 |
|
33 void IrqDispatch() |
|
34 { |
|
35 CHECK_PRECONDITIONS( MASK_INTERRUPTS_DISABLED ,Kern::Fault("IRQS ENABLED While reading IVT",__FILE__)); |
|
36 |
|
37 TUint irqVector = AsspRegister::Read32(INTCPS_SIR_IRQ) &INTCPS_PENDING_MASK; |
|
38 |
|
39 TUint irqFlags = __SPIN_LOCK_IRQSAVE_R(Omap3530IVTLock); |
|
40 SInterruptHandler handler = Omap3530Interrupt::Handlers[irqVector]; |
|
41 __SPIN_UNLOCK_IRQRESTORE_R(Omap3530IVTLock,irqFlags); |
|
42 |
|
43 //may be useful in the interim but dont want a print in every dispatch |
|
44 //__KTRACE_OPT(KHARDWARE,Kern::Printf("IRQDISPATCH V %x isr %x ptr %x",irqVector,handler.iIsr,handler.iPtr)); |
|
45 //execute handler now |
|
46 ((TIsr)*handler.iIsr)(handler.iPtr); |
|
47 |
|
48 AsspRegister::Write32(INTCPS_CONTROL,INTCPS_CONTROL_IRQ_CLEAR); |
|
49 } |
|
50 |
|
51 void FiqDispatch() |
|
52 { |
|
53 Omap3530Interrupt::Spurious((TAny*)KErrNotFound); |
|
54 } |
|
55 |
|
56 #endif |
|
57 |
|
58 #ifndef _DEBUG |
|
59 |
|
60 void Omap3530Interrupt::dumpINTCState(){} |
|
61 void Omap3530Interrupt::dumpIVTState(){} |
|
62 void TestHandler(TAny * wibble){} |
|
63 EXPORT_C void TestInterrupts(TInt id,TIsr func){} |
|
64 void TestExternalInterrupts(){} |
|
65 EXPORT_C void ClearAndDisableTestInterrupt(TInt anId){} |
|
66 void TestPriorities(){} |
|
67 #else |
|
68 |
|
69 void Omap3530Interrupt::dumpINTCState() |
|
70 { |
|
71 Kern::Printf("INTCPS_SYSCONFIG %x",AsspRegister::Read32(INTCPS_SYSCONFIG)); |
|
72 Kern::Printf("INTCPS_SYSSTATUS %x",AsspRegister::Read32(INTCPS_SYSSTATUS)); |
|
73 Kern::Printf("INTCPS_SIR_IRQ %x",AsspRegister::Read32(INTCPS_SIR_IRQ)); |
|
74 Kern::Printf("INTCPS_SIR_FIQ %x",AsspRegister::Read32(INTCPS_SIR_FIQ)); |
|
75 Kern::Printf("INTCPS_CONTROL %x",AsspRegister::Read32(INTCPS_CONTROL)); |
|
76 Kern::Printf("INTCPS_PROTECTION %x",AsspRegister::Read32(INTCPS_PROTECTION)); |
|
77 Kern::Printf("INTCPS_IDLE %x",AsspRegister::Read32(INTCPS_IDLE)); |
|
78 Kern::Printf("INTCPS_IRQ_PRIORITY %x",AsspRegister::Read32(INTCPS_IRQ_PRIORITY)); |
|
79 Kern::Printf("INTCPS_FIQ_PRIORITY %x",AsspRegister::Read32(INTCPS_FIQ_PRIORITY)); |
|
80 Kern::Printf("INTCPS_THRESHOLD %x",AsspRegister::Read32(INTCPS_THRESHOLD)); |
|
81 Kern::Printf("INTCPS_ITR0 %x",AsspRegister::Read32(INTCPS_ITR(0))); |
|
82 Kern::Printf("INTCPS_ITR1 %x",AsspRegister::Read32(INTCPS_ITR(1))); |
|
83 Kern::Printf("INTCPS_ITR 2%x",AsspRegister::Read32(INTCPS_ITR(2))); |
|
84 Kern::Printf("INTCPS_MIR0 %x",AsspRegister::Read32(INTCPS_MIRn(0))); |
|
85 Kern::Printf("INTCPS_MIR1 %x",AsspRegister::Read32(INTCPS_MIRn(1))); |
|
86 Kern::Printf("INTCPS_MIR2 %x",AsspRegister::Read32(INTCPS_MIRn(2))); |
|
87 Kern::Printf("INTCPS_PENDING_IRQ0 %x",AsspRegister::Read32(INTCPS_PENDING_IRQ(0))); |
|
88 Kern::Printf("INTCPS_PENDING_IRQ1 %x",AsspRegister::Read32(INTCPS_PENDING_IRQ(1))); |
|
89 Kern::Printf("INTCPS_PENDING_IRQ2 %x",AsspRegister::Read32(INTCPS_PENDING_IRQ(2))); |
|
90 Kern::Printf("INTCPS_PENDING_FIQ1 %x",AsspRegister::Read32(INTCPS_PENDING_FIQ(0))); |
|
91 Kern::Printf("INTCPS_PENDING_FIQ0 %x",AsspRegister::Read32(INTCPS_PENDING_FIQ(1))); |
|
92 Kern::Printf("INTCPS_PENDING_FIQ2 %x",AsspRegister::Read32(INTCPS_PENDING_FIQ(2))); |
|
93 Kern::Printf("INTCPS_ILR0 %x",AsspRegister::Read32(INTCPS_ILRM(0))); |
|
94 Kern::Printf("INTCPS_ILR1 %x",AsspRegister::Read32(INTCPS_ILRM(1))); |
|
95 Kern::Printf("INTCPS_ILR2 %x",AsspRegister::Read32(INTCPS_ILRM(2))); |
|
96 Kern::Printf("INTCPS_ISRSET0 %x", AsspRegister::Read32(INTCPS_ISRSET(0))); |
|
97 Kern::Printf("INTCPS_ISRSET1 %x", AsspRegister::Read32(INTCPS_ISRSET(1))); |
|
98 Kern::Printf("INTCPS_ISRSET2 %x", AsspRegister::Read32(INTCPS_ISRSET(2))); |
|
99 } |
|
100 |
|
101 |
|
102 void Omap3530Interrupt::dumpIVTState() |
|
103 { |
|
104 //NOTE NOT THREAD SAFE ! |
|
105 TInt reg; |
|
106 TInt bit; |
|
107 |
|
108 __KTRACE_OPT(KHARDWARE,Kern::Printf("Omap3530Interrupt::dumpIVTState")); |
|
109 |
|
110 for(TInt i=0;i<KNumOmap3530Ints;i++) |
|
111 { |
|
112 GetRegisterAndBitOffset(i,reg,bit); |
|
113 TUint val = AsspRegister::Read32(INTCPS_MIRn(reg)); |
|
114 TUint priVal = AsspRegister::Read32(INTCPS_ILRM(i)); |
|
115 val &= (0x1 << bit ); |
|
116 |
|
117 Kern::Printf("INT_VECT %d F %x P %x MASK %d PRIORITY %d",i,Handlers[i].iIsr,Handlers[i].iPtr,(val >> bit),priVal >> 2); |
|
118 } |
|
119 } |
|
120 |
|
121 void TestHandler(TAny * wibble) |
|
122 { |
|
123 TInt irq = (TInt)wibble; |
|
124 __KTRACE_OPT(KHARDWARE,Kern::Printf("TestHandler IN IRQ %d",irq)); |
|
125 Omap3530Interrupt::dumpINTCState(); |
|
126 ClearAndDisableTestInterrupt(irq); |
|
127 Omap3530Interrupt::dumpINTCState(); |
|
128 __KTRACE_OPT(KHARDWARE,Kern::Printf("TestHandler Interrupts OK ",irq)); |
|
129 } |
|
130 |
|
131 |
|
132 |
|
133 void TestPriHandler(TAny * wibble) |
|
134 { |
|
135 TInt irq = (TInt)wibble; |
|
136 __KTRACE_OPT(KHARDWARE,Kern::Printf("TestHandler PRI IN IRQ %d",irq)); |
|
137 Omap3530Interrupt::dumpINTCState(); |
|
138 ClearAndDisableTestInterrupt(irq); |
|
139 Omap3530Interrupt::dumpINTCState(); |
|
140 |
|
141 __KTRACE_OPT(KHARDWARE,Kern::Printf("TestHandler Interrupts OK ",irq)); |
|
142 } |
|
143 |
|
144 |
|
145 EXPORT_C void ClearAndDisableTestInterrupt(TInt anId) |
|
146 { |
|
147 TInt reg,bit; |
|
148 TInt irq = (TInt)anId; |
|
149 __KTRACE_OPT(KHARDWARE,Kern::Printf("ClearAndDisableTestInterrupt IN IRQ %d",irq)); |
|
150 |
|
151 Omap3530Interrupt::GetRegisterAndBitOffset(irq,reg,bit); |
|
152 |
|
153 AsspRegister::Write32(INTCPS_ISR_CLEAR(reg),1 << bit); |
|
154 |
|
155 Interrupt::Clear(irq); |
|
156 |
|
157 Interrupt::Disable(irq); |
|
158 |
|
159 Interrupt::Unbind(irq); |
|
160 |
|
161 |
|
162 |
|
163 } |
|
164 |
|
165 void TestPriorities() |
|
166 { |
|
167 __KTRACE_OPT(KHARDWARE,Kern::Printf("Priorities")); |
|
168 Interrupt::Bind(EOmap3530_IRQ4_MCBSP2_ST_IRQ,TestPriHandler,(TAny*)EOmap3530_IRQ4_MCBSP2_ST_IRQ); |
|
169 Interrupt::Bind(EOmap3530_IRQ5_MCBSP3_ST_IRQ,TestPriHandler,(TAny*)EOmap3530_IRQ5_MCBSP3_ST_IRQ); |
|
170 |
|
171 |
|
172 TInt r = Interrupt::SetPriority(EOmap3530_IRQ4_MCBSP2_ST_IRQ,0); |
|
173 if(r != KErrNone) |
|
174 { |
|
175 __KTRACE_OPT(KHARDWARE,Kern::Printf("%s SP1 r %d ",__FUNCTION__,r)); |
|
176 } |
|
177 |
|
178 r = Interrupt::SetPriority(EOmap3530_IRQ5_MCBSP3_ST_IRQ,0); |
|
179 if(r != KErrNone) |
|
180 { |
|
181 __KTRACE_OPT(KHARDWARE,Kern::Printf("%s SP2 r %d ",__FUNCTION__,r)); |
|
182 } |
|
183 |
|
184 Omap3530Interrupt::dumpINTCState(); |
|
185 |
|
186 Interrupt::Enable(EOmap3530_IRQ4_MCBSP2_ST_IRQ); |
|
187 Interrupt::Enable(EOmap3530_IRQ5_MCBSP3_ST_IRQ); |
|
188 |
|
189 |
|
190 Omap3530Interrupt::dumpIVTState(); |
|
191 TInt reg,bit,bit1; |
|
192 Omap3530Interrupt::GetRegisterAndBitOffset(EOmap3530_IRQ5_MCBSP3_ST_IRQ,reg,bit); |
|
193 Omap3530Interrupt::GetRegisterAndBitOffset(EOmap3530_IRQ4_MCBSP2_ST_IRQ,reg,bit1); |
|
194 |
|
195 AsspRegister::Write32(INTCPS_ISRSET(reg),((1 << bit) | ( 1 << bit1))); |
|
196 } |
|
197 |
|
198 EXPORT_C void TestInterrupts(TInt id,TIsr func) |
|
199 { |
|
200 __KTRACE_OPT(KHARDWARE,Kern::Printf("TestInterrupts")); |
|
201 Interrupt::Bind(id,func,(TAny*)id); |
|
202 |
|
203 Omap3530Interrupt::dumpIVTState(); |
|
204 |
|
205 Interrupt::Enable(id); |
|
206 Omap3530Interrupt::dumpIVTState(); |
|
207 |
|
208 TInt reg,bit; |
|
209 Omap3530Interrupt::GetRegisterAndBitOffset(id,reg,bit); |
|
210 |
|
211 AsspRegister::Write32(INTCPS_ISRSET(reg),1 << bit); |
|
212 Omap3530Interrupt::dumpINTCState(); |
|
213 } |
|
214 |
|
215 |
|
216 |
|
217 #endif |
|
218 |
|
219 |
|
220 void Omap3530Interrupt::DisableAndClearAll() |
|
221 { |
|
222 // Disable then clear all Hardware Interrupt sources |
|
223 __KTRACE_OPT(KBOOT,Kern::Printf("Omap3530Interrupt::DisableAndClearAll 0 %x 1 %x 2 %x", |
|
224 INTCPS_MIR_SETn(0), |
|
225 INTCPS_MIR_SETn(1), |
|
226 INTCPS_MIR_SETn(2))); |
|
227 |
|
228 //first we mask all vectors |
|
229 AsspRegister::Write32(INTCPS_MIR_SETn(0),INTCPS_MIR_ALL_SET); |
|
230 AsspRegister::Write32(INTCPS_MIR_SETn(1),INTCPS_MIR_ALL_SET); |
|
231 AsspRegister::Write32(INTCPS_MIR_SETn(2),INTCPS_MIR_ALL_SET); |
|
232 |
|
233 AsspRegister::Write32(INTCPS_ISR_CLEAR(0),0xffffffff); |
|
234 AsspRegister::Write32(INTCPS_ISR_CLEAR(1),0xffffffff); |
|
235 AsspRegister::Write32(INTCPS_ISR_CLEAR(2),0xffffffff); |
|
236 |
|
237 |
|
238 AsspRegister::Write32(INTCPS_CONTROL,INTCPS_CONTROL_IRQ_CLEAR|INTCPS_CONTROL_FIQ_CLEAR); |
|
239 |
|
240 __KTRACE_OPT(KBOOT,Kern::Printf("Omap3530Interrupt::DisableAndClearAll INTCPS_SIR_IRQ %x at %x",AsspRegister::Read32(INTCPS_SIR_IRQ),INTCPS_BASE )); |
|
241 |
|
242 __KTRACE_OPT(KBOOT,Kern::Printf("Omap3530Interrupt::DisableAndClearAll OUT")); |
|
243 } |
|
244 |
|
245 void Omap3530Interrupt::Init1() |
|
246 { |
|
247 |
|
248 __KTRACE_OPT(KBOOT,Kern::Printf("Omap3530Interrupt::Init1()")); |
|
249 |
|
250 //make sure everything is off first |
|
251 |
|
252 DisableAndClearAll(); |
|
253 |
|
254 //Initialise the IVT to the spurious handler |
|
255 //interrupts are not enabled yet but take mutex on the IVT anyway |
|
256 |
|
257 TUint irq = __SPIN_LOCK_IRQSAVE_W(Omap3530IVTLock); |
|
258 for (TInt i=0; i<KNumOmap3530Ints; i++) |
|
259 { |
|
260 Handlers[i].iPtr=(TAny*)i; |
|
261 Handlers[i].iIsr=Spurious; |
|
262 } |
|
263 __SPIN_UNLOCK_IRQRESTORE_W(Omap3530IVTLock,irq); |
|
264 |
|
265 |
|
266 Arm::SetIrqHandler((TLinAddr)IrqDispatch); |
|
267 Arm::SetFiqHandler((TLinAddr)FiqDispatch); |
|
268 |
|
269 |
|
270 //set the low power mode |
|
271 //TODO: these registers are outside the mapped addressable ranged - and may be reserved as according to |
|
272 // part of the TRM. So we will omit for now. |
|
273 //AsspRegister::Write32(INTC_INIT_REGISTER1,INTCPS_INIT_RG_LOW_PWR); |
|
274 //AsspRegister::Write32(INTC_INIT_REGISTER2,INTCPS_INIT_RG_LOW_PWR); |
|
275 |
|
276 //enable the clock sources ? |
|
277 |
|
278 //program the INTC to initial state. |
|
279 AsspRegister::Write32(INTCPS_SYSCONFIG,INTCPS_SYSCONFIG_AUTOIDLE); |
|
280 AsspRegister::Write32(INTCPS_IDLE,INTCPS_IDLE_TURBO); |
|
281 |
|
282 //TODO do we really want flat priorities ? |
|
283 for(TInt i=0;i<KNumOmap3530Ints;i++) |
|
284 { |
|
285 AsspRegister::Write32(INTCPS_ILRM(i), (INTCPS_ILRM_ROUTE_IRQ | (KOmap3530DefIntPriority <<2) )); |
|
286 } |
|
287 __KTRACE_OPT(KBOOT,Kern::Printf("Omap3530Interrupt::Init1() OUT ")); |
|
288 |
|
289 } |
|
290 |
|
291 void Omap3530Interrupt::Init3() |
|
292 { |
|
293 |
|
294 __KTRACE_OPT(KBOOT,Kern::Printf("Omap3530Interrupt::Init3")); |
|
295 |
|
296 } |
|
297 |
|
298 void Omap3530Interrupt::Spurious(TAny* anId) |
|
299 { |
|
300 // handle an unexpected interrupt |
|
301 dumpIVTState(); |
|
302 Kern::Fault("Omap3530Interrupt::Spurious",(TInt)anId); |
|
303 } |
|
304 |
|
305 EXPORT_C TInt Omap3530Interrupt::IsInterruptEnabled(TInt anId) |
|
306 { |
|
307 TInt isrBitOffset=0; |
|
308 TInt reg=0; |
|
309 Omap3530Interrupt::GetRegisterAndBitOffset(anId,reg,isrBitOffset); |
|
310 |
|
311 TUint val = AsspRegister::Read32(INTCPS_MIRn(reg)); |
|
312 val &= (~(0x1 << isrBitOffset )); |
|
313 return (val & 0x1 << isrBitOffset) ? |
|
314 1: |
|
315 0; |
|
316 } |
|
317 |
|
318 TInt Omap3530Interrupt::GetRegisterAndBitOffset(TInt anId,TInt &aReg,TInt &aOffset) |
|
319 { |
|
320 if ((TUint)anId >= (TUint)KNumOmap3530Ints) |
|
321 { |
|
322 return KErrArgument; |
|
323 } |
|
324 else |
|
325 { |
|
326 aOffset = (anId % 32); |
|
327 aReg = (anId / 32); |
|
328 } |
|
329 return KErrNone; |
|
330 |
|
331 } |
|
332 // |
|
333 // The APIs below assume ther is a second level Interrupt controller located at Omap3530Assp::Variant level which handles |
|
334 // interrupts generated by hardware at that level. |
|
335 // |
|
336 |
|
337 EXPORT_C TInt Interrupt::Bind(TInt aId, TIsr aIsr, TAny* aPtr) |
|
338 { |
|
339 __KTRACE_OPT(KHARDWARE,Kern::Printf("Interrupt::Bind id=%d func=%08x ptr=%08x Var %x",aId,aIsr,aPtr,Omap3530Assp::Omap3530Assp::Variant)); |
|
340 TInt r; |
|
341 // if ID indicates a chained interrupt, call Omap3530Assp::Variant... |
|
342 |
|
343 TInt index = aId >> KIrqRangeIndexShift; |
|
344 if( index == 0 ) |
|
345 { |
|
346 if ((TUint)aId >= (TUint)KNumOmap3530Ints) |
|
347 { |
|
348 __KTRACE_OPT(KHARDWARE,Kern::Printf("Interrupt::Bind id OOB %d MAX %d",aId,KNumOmap3530Ints)); |
|
349 r = KErrArgument; |
|
350 } |
|
351 else |
|
352 { |
|
353 TUint irq = __SPIN_LOCK_IRQSAVE_R(Omap3530IVTLock); |
|
354 SInterruptHandler& h=Omap3530Interrupt::Handlers[aId]; |
|
355 |
|
356 if (h.iIsr != Omap3530Interrupt::Spurious) |
|
357 { |
|
358 r=KErrInUse; |
|
359 __SPIN_UNLOCK_IRQRESTORE_R(Omap3530IVTLock,irq); |
|
360 __KTRACE_OPT(KHARDWARE,Kern::Printf("Interrupt::Bind Cant Bind irq (IN_USE %d",aId)); |
|
361 } |
|
362 else |
|
363 { |
|
364 __SPIN_UNLOCK_IRQRESTORE_R(Omap3530IVTLock,irq); |
|
365 TUint irq = __SPIN_LOCK_IRQSAVE_W(Omap3530Interrupt::Omap3530IVTLock); |
|
366 h.iPtr=aPtr; |
|
367 h.iIsr=aIsr; |
|
368 __SPIN_UNLOCK_IRQRESTORE_W(Omap3530Interrupt::Omap3530IVTLock,irq); |
|
369 __KTRACE_OPT(KHARDWARE,Kern::Printf("Interrupt::Bind BOUND %d",aId)); |
|
370 r = KErrNone; |
|
371 } |
|
372 __KTRACE_OPT(KHARDWARE,Kern::Printf("Interrupt::Bind OUT")); |
|
373 } |
|
374 } |
|
375 else if( index > 0 ) |
|
376 { |
|
377 r = TheDispatchers[ index ]->Bind( aId, aIsr, aPtr ); |
|
378 } |
|
379 else if (Omap3530Assp::Variant->IsExternalInterrupt(aId)) |
|
380 { |
|
381 __KTRACE_OPT(KHARDWARE,Kern::Printf("Interrupt::Bind extint %d",aId)); |
|
382 return Omap3530Assp::Variant->InterruptBind(aId,aIsr,aPtr); |
|
383 } |
|
384 else |
|
385 { |
|
386 r = KErrArgument; |
|
387 } |
|
388 |
|
389 return r; |
|
390 } |
|
391 |
|
392 EXPORT_C TInt Interrupt::Unbind(TInt aId) |
|
393 { |
|
394 __KTRACE_OPT(KHARDWARE,Kern::Printf("Interrupt::Unbind id=%d",aId)); |
|
395 TInt r; |
|
396 TInt index = aId >> KIrqRangeIndexShift; |
|
397 |
|
398 if( index == 0 ) |
|
399 { |
|
400 if ((TUint)aId >= (TUint)KNumOmap3530Ints) |
|
401 { |
|
402 r=KErrArgument; |
|
403 } |
|
404 else |
|
405 { |
|
406 TUint irq = __SPIN_LOCK_IRQSAVE_R(Omap3530IVTLock); |
|
407 SInterruptHandler& h=Omap3530Interrupt::Handlers[aId]; |
|
408 __SPIN_UNLOCK_IRQRESTORE_R(Omap3530IVTLock,irq); |
|
409 |
|
410 if (h.iIsr == Omap3530Interrupt::Spurious) |
|
411 { |
|
412 r=KErrGeneral; |
|
413 } |
|
414 else |
|
415 { |
|
416 TInt isrBitOffset=0; |
|
417 TInt reg=0; |
|
418 Omap3530Interrupt::GetRegisterAndBitOffset(aId,reg,isrBitOffset); |
|
419 #ifdef _DEBUG |
|
420 TUint val = AsspRegister::Read32(INTCPS_MIRn(reg)); |
|
421 if( ! (val & (0x1 << isrBitOffset))) |
|
422 { |
|
423 __KTRACE_OPT(KHARDWARE,Kern::Printf("Interrupt::Unbind THIS IRQ IS STILL ENABLED - update your code")); |
|
424 } |
|
425 |
|
426 TUint irqVector = AsspRegister::Read32(INTCPS_SIR_IRQ) &INTCPS_PENDING_MASK; |
|
427 if(irqVector == aId ) |
|
428 { |
|
429 __KTRACE_OPT(KHARDWARE,Kern::Printf("Interrupt::Unbind THIS IRQ IS STILL PENDING - update your code")); |
|
430 } |
|
431 #endif |
|
432 TUint irq = __SPIN_LOCK_IRQSAVE_W(Omap3530Interrupt::Omap3530INTCLock); |
|
433 h.iPtr=(TAny*)aId; |
|
434 h.iIsr=Omap3530Interrupt::Spurious; |
|
435 __SPIN_UNLOCK_IRQRESTORE_W(Omap3530Interrupt::Omap3530INTCLock,irq); |
|
436 |
|
437 //calculate the register and bit offset for this id |
|
438 //and disable the corresponding Hardware Interrupt source |
|
439 |
|
440 AsspRegister::Write32(INTCPS_MIR_SETn(reg),(1 << isrBitOffset)); |
|
441 r = KErrNone; |
|
442 } |
|
443 } |
|
444 } |
|
445 else if( index > 0 ) |
|
446 { |
|
447 r = TheDispatchers[ index ]->Unbind( aId ); |
|
448 } |
|
449 else if (Omap3530Assp::Variant->IsExternalInterrupt(aId)) |
|
450 { |
|
451 r = Omap3530Assp::Variant->InterruptUnbind(aId); |
|
452 } |
|
453 else |
|
454 { |
|
455 r = KErrArgument; |
|
456 } |
|
457 |
|
458 return r; |
|
459 } |
|
460 |
|
461 EXPORT_C TInt Interrupt::Enable(TInt aId) |
|
462 { |
|
463 __KTRACE_OPT(KHARDWARE,Kern::Printf("Interrupt::Enable id=%d",aId)); |
|
464 TInt r; |
|
465 TInt index = aId >> KIrqRangeIndexShift; |
|
466 |
|
467 if( index == 0 ) |
|
468 { |
|
469 if ((TUint)aId>=(TUint)KNumOmap3530Ints) |
|
470 { |
|
471 r=KErrArgument; |
|
472 } |
|
473 else if (Omap3530Interrupt::Handlers[aId].iIsr==Omap3530Interrupt::Spurious) |
|
474 { |
|
475 r=KErrNotReady; |
|
476 } |
|
477 else |
|
478 { |
|
479 __KTRACE_OPT(KHARDWARE,Kern::Printf("Interrupt::Enable %d",aId)); |
|
480 // Enable the corresponding Hardware Interrupt source |
|
481 TInt isrBitOffset=0; |
|
482 TInt reg=0; |
|
483 Omap3530Interrupt::GetRegisterAndBitOffset(aId,reg,isrBitOffset); |
|
484 AsspRegister::Write32(INTCPS_MIR_CLEARn(reg),(1 << isrBitOffset)); |
|
485 r = KErrNone; |
|
486 } |
|
487 } |
|
488 else if( index > 0 ) |
|
489 { |
|
490 r = TheDispatchers[ index ]->Enable( aId ); |
|
491 } |
|
492 else if (Omap3530Assp::Variant->IsExternalInterrupt(aId)) |
|
493 { |
|
494 r = Omap3530Assp::Variant->InterruptEnable(aId); |
|
495 } |
|
496 else |
|
497 { |
|
498 r = KErrArgument; |
|
499 } |
|
500 return r; |
|
501 } |
|
502 |
|
503 EXPORT_C TInt Interrupt::Disable(TInt aId) |
|
504 { |
|
505 __KTRACE_OPT(KHARDWARE,Kern::Printf("Interrupt::Disable id=%d",aId)); |
|
506 TInt r; |
|
507 TInt index = aId >> KIrqRangeIndexShift; |
|
508 |
|
509 if( index == 0 ) |
|
510 { |
|
511 if ((TUint)aId >= (TUint)KNumOmap3530Ints) |
|
512 { |
|
513 r=KErrArgument; |
|
514 } |
|
515 else |
|
516 { |
|
517 // Disable the corresponding Hardware Interrupt source |
|
518 TInt isrBitOffset=0; |
|
519 TInt reg=0; |
|
520 Omap3530Interrupt::GetRegisterAndBitOffset(aId,reg,isrBitOffset); |
|
521 AsspRegister::Write32(INTCPS_MIR_SETn(reg),(1 << isrBitOffset)); |
|
522 r = KErrNone; |
|
523 } |
|
524 } |
|
525 else if( index > 0 ) |
|
526 { |
|
527 r = TheDispatchers[ index ]->Disable( aId ); |
|
528 } |
|
529 else if (Omap3530Assp::Variant->IsExternalInterrupt(aId)) |
|
530 { |
|
531 r = Omap3530Assp::Variant->InterruptDisable(aId); |
|
532 } |
|
533 else |
|
534 { |
|
535 r = KErrArgument; |
|
536 } |
|
537 |
|
538 return r; |
|
539 } |
|
540 |
|
541 EXPORT_C TInt Interrupt::Clear(TInt aId) |
|
542 { |
|
543 //__KTRACE_OPT(KHARDWARE,Kern::Printf("Interrupt::Clear id=%d",aId)); |
|
544 TInt r = KErrUnknown; |
|
545 TInt index = aId >> KIrqRangeIndexShift; |
|
546 |
|
547 if( index == 0 ) |
|
548 { |
|
549 if ((TUint)aId >= (TUint)KNumOmap3530Ints) |
|
550 { |
|
551 r=KErrArgument; |
|
552 } |
|
553 else |
|
554 { |
|
555 TInt curVector = AsspRegister::Read32(INTCPS_SIR_IRQ); |
|
556 // Clear the corresponding Hardware Interrupt source |
|
557 if(curVector == aId) |
|
558 { |
|
559 //TODO: determine whether we are dealing with a FIQ or IRQ source |
|
560 // for now assuming all are IRQS |
|
561 //__KTRACE_OPT(KHARDWARE,Kern::Printf("Interrupt::Clear id=%d x %x",aId,curVector )); |
|
562 AsspRegister::Write32(INTCPS_CONTROL,INTCPS_CONTROL_IRQ_CLEAR); |
|
563 } |
|
564 } |
|
565 } |
|
566 else if( index > 0 ) |
|
567 { |
|
568 r = TheDispatchers[ index ]->Clear( aId ); |
|
569 } |
|
570 else if (Omap3530Assp::Variant->IsExternalInterrupt(aId)) |
|
571 { |
|
572 r = Omap3530Assp::Variant->InterruptClear(aId); |
|
573 } |
|
574 else |
|
575 { |
|
576 r = KErrArgument; |
|
577 } |
|
578 |
|
579 return r; |
|
580 } |
|
581 |
|
582 EXPORT_C TInt Interrupt::SetPriority(TInt aId, TInt aPriority) |
|
583 { |
|
584 // If Interrupt priorities are supported the dispatchers need to take this in consideration |
|
585 |
|
586 // (IrqDispatch/FiqDispatch) |
|
587 __KTRACE_OPT(KHARDWARE,Kern::Printf("Interrupt::SetPriority id=%d pri=%d",aId,aPriority)); |
|
588 |
|
589 TInt r; |
|
590 TInt index = aId >> KIrqRangeIndexShift; |
|
591 |
|
592 if( index == 0 ) |
|
593 { |
|
594 if ((TUint)aId >= (TUint)KNumOmap3530Ints) |
|
595 { |
|
596 r = KErrArgument; |
|
597 } |
|
598 else |
|
599 { |
|
600 TUint irq = __SPIN_LOCK_IRQSAVE_W(Omap3530Interrupt::Omap3530INTCLock); |
|
601 TUint curIRLMi = AsspRegister::Read32(INTCPS_ILRM(aId)); |
|
602 curIRLMi = ( curIRLMi & 0x000000003) | (aPriority << 0x2) ; |
|
603 AsspRegister::Write32(INTCPS_ILRM(aId),curIRLMi); |
|
604 __SPIN_UNLOCK_IRQRESTORE_W(Omap3530Interrupt::Omap3530INTCLock,irq); |
|
605 r = KErrNone; |
|
606 } |
|
607 } |
|
608 else if( index > 0 ) |
|
609 { |
|
610 r = TheDispatchers[ index ]->SetPriority( aId, aPriority ); |
|
611 } |
|
612 else if (Omap3530Assp::Variant->IsExternalInterrupt(aId)) |
|
613 { |
|
614 r = KErrNotSupported; |
|
615 } |
|
616 else |
|
617 { |
|
618 r = KErrArgument; |
|
619 } |
|
620 |
|
621 return r; |
|
622 } |
|
623 |
|
624 |
|
625 EXPORT_C void MInterruptDispatcher::Register( TIrqRangeIndex aIndex ) |
|
626 { |
|
627 __ASSERT_ALWAYS( TheDispatchers[ aIndex ] == NULL, Kern::Fault( "interrupts.cpp", __LINE__ ) ); |
|
628 TheDispatchers[ aIndex ] = this; |
|
629 } |
|
630 |