Update contrib.
1 // Copyright (c) 2007-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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\nkernsmp\x86\ncirq.cpp
29 #define DMEMDUMP(base,size) DbgMemDump((TLinAddr)base,size)
30 void DbgMemDump(TLinAddr aBase, TInt aSize)
33 const TUint8* p=(const TUint8*)aBase;
35 for (off=0; off<aSize; off+=16, p+=16)
37 DEBUGPRINT("%08x: %02x %02x %02x %02x %02x %02x %02x %02x | %02x %02x %02x %02x %02x %02x %02x %02x",
38 p, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
39 p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
44 #define DMEMDUMP(base,size)
47 #define IO_APIC_BASE 0xFEC00000
48 #define IO_APIC_REGSEL_OFFSET 0x00
49 #define IO_APIC_IOWIN_OFFSET 0x10
51 #define IO_APIC_REG_ID 0x00
52 #define IO_APIC_REG_VER 0x01
53 #define IO_APIC_REG_ARB 0x02
55 #define IO_APIC_CTRL_IMASK 0x10000 // 1 = masked
56 #define IO_APIC_CTRL_LEVEL 0x08000 // 1 = level triggered, 0 = edge
57 #define IO_APIC_CTRL_REMOTE_IRR 0x04000 //
58 #define IO_APIC_CTRL_INTPOL_LOW 0x02000 // 1 = active low
59 #define IO_APIC_CTRL_DELIVS 0x01000 //
60 #define IO_APIC_CTRL_DESTMOD 0x00800 // 1 = logical, 0 = physical
61 #define IO_APIC_CTRL_DELMOD_MASK 0x00700
62 #define IO_APIC_CTRL_DELMOD_FIXED 0x00000
63 #define IO_APIC_CTRL_DELMOD_LOWP 0x00100
64 #define IO_APIC_CTRL_DELMOD_SMI 0x00200
65 #define IO_APIC_CTRL_DELMOD_NMI 0x00400
66 #define IO_APIC_CTRL_DELMOD_INIT 0x00500
67 #define IO_APIC_CTRL_DELMOD_EXTINT 0x00700
68 #define IO_APIC_CTRL_INTVEC_MASK 0x000FF
71 /******************************************************************************
73 ******************************************************************************/
75 #define IO_APIC_SELECT(x) ((void)(*(volatile TUint32*)(iAddr + IO_APIC_REGSEL_OFFSET) = (x)))
76 #define IO_APIC_REG (*(volatile TUint32*)(iAddr + IO_APIC_IOWIN_OFFSET))
81 TIoApic(TLinAddr aAddr);
85 TUint32 Dest(TInt aIndex);
86 TUint32 Control(TInt aIndex);
87 TUint32 ModifyDest(TInt aIndex, TUint32 aNewDest);
88 TUint32 ModifyControl(TInt aIndex, TUint32 aClear, TUint32 aSet);
96 TIoApic TheIoApic(IO_APIC_BASE);
98 TIoApic::TIoApic(TLinAddr aAddr)
99 : iLock(TSpinLock::EOrderBTrace)
104 TUint32 TIoApic::Id()
106 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
107 IO_APIC_SELECT(IO_APIC_REG_ID);
108 TUint32 x = IO_APIC_REG;
109 __SPIN_UNLOCK_IRQRESTORE(iLock,irq);
113 TUint32 TIoApic::Ver()
115 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
116 IO_APIC_SELECT(IO_APIC_REG_VER);
117 TUint32 x = IO_APIC_REG;
118 __SPIN_UNLOCK_IRQRESTORE(iLock,irq);
122 TUint32 TIoApic::Arb()
124 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
125 IO_APIC_SELECT(IO_APIC_REG_ARB);
126 TUint32 x = IO_APIC_REG;
127 __SPIN_UNLOCK_IRQRESTORE(iLock,irq);
131 TUint32 TIoApic::Dest(TInt aIndex)
133 TUint32 reg = 2*aIndex + 0x11;
134 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
136 TUint32 x = IO_APIC_REG;
137 __SPIN_UNLOCK_IRQRESTORE(iLock,irq);
141 TUint32 TIoApic::Control(TInt aIndex)
143 TUint32 reg = 2*aIndex + 0x10;
144 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
146 TUint32 x = IO_APIC_REG;
147 __SPIN_UNLOCK_IRQRESTORE(iLock,irq);
151 TUint32 TIoApic::ModifyDest(TInt aIndex, TUint32 aNewDest)
153 TUint32 reg = 2*aIndex + 0x11;
154 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
156 TUint32 x = IO_APIC_REG;
157 IO_APIC_REG = (x&0x00ffffffu) | (aNewDest<<24);
158 __SPIN_UNLOCK_IRQRESTORE(iLock,irq);
162 TUint32 TIoApic::ModifyControl(TInt aIndex, TUint32 aClear, TUint32 aSet)
164 TUint32 reg = 2*aIndex + 0x10;
165 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
167 TUint32 x = IO_APIC_REG;
172 __SPIN_UNLOCK_IRQRESTORE(iLock,irq);
181 __KTRACE_OPT(KBOOT,DEBUGPRINT("IOAPIC ID=%08x VER=%08x ARB=%08x", id, ver, arb));
183 TInt max = (ver>>16)&0xff;
185 for (i=0; i<=max; ++i)
187 TUint32 dest = Dest(i);
188 TUint32 ctrl = Control(i);
189 __KTRACE_OPT(KBOOT,DEBUGPRINT("IOAPIC[%02x] DEST=%02x CTRL=%08x", i, dest, ctrl));
196 if (iX && iX->iEoiFn)
200 volatile TUint32* const apic_eoi = (volatile TUint32*)(X86_LOCAL_APIC_BASE + X86_LOCAL_APIC_OFFSET_EOI);
205 void NIrq::HwEnable()
207 if (iX && iX->iEnableFn)
208 (*iX->iEnableFn)(this);
211 // if ((iStaticFlags & ELevel) || (iIState & ERaw))
212 TheIoApic.ModifyControl(iIndex, IO_APIC_CTRL_IMASK, 0);
216 void NIrq::HwDisable()
218 if (iX && iX->iDisableFn)
219 (*iX->iDisableFn)(this);
222 if ((iStaticFlags & ELevel) || (iIState & ERaw))
223 TheIoApic.ModifyControl(iIndex, 0, IO_APIC_CTRL_IMASK);
227 void NIrq::HwSetCpu(TInt aCpu)
229 if (iX && iX->iSetCpuFn)
230 (*iX->iSetCpuFn)(this, 1u<<aCpu);
233 TheIoApic.ModifyDest(iIndex, 1u<<aCpu);
237 void NIrq::HwSetCpuMask(TUint32 aMask)
239 if (iX && iX->iSetCpuFn)
240 (*iX->iSetCpuFn)(this, aMask);
243 TheIoApic.ModifyDest(iIndex, aMask);
249 if (iX && iX->iInitFn)
250 (*iX->iInitFn)(this);
253 __KTRACE_OPT(KBOOT,DEBUGPRINT("NIrq %02x HwInit", iIndex));
254 TUint32 clear = IO_APIC_CTRL_INTVEC_MASK;
255 TUint32 set = iVector & IO_APIC_CTRL_INTVEC_MASK;
256 set |= IO_APIC_CTRL_IMASK;
257 if (iStaticFlags & ELevel)
258 set |= (IO_APIC_CTRL_LEVEL /*| IO_APIC_CTRL_IMASK*/);
260 clear |= (IO_APIC_CTRL_LEVEL /*| IO_APIC_CTRL_IMASK*/);
261 if (iStaticFlags & EPolarity)
262 clear |= IO_APIC_CTRL_INTPOL_LOW;
264 set |= IO_APIC_CTRL_INTPOL_LOW;
265 TheIoApic.ModifyControl(iIndex, clear, set);
270 TBool NIrq::HwPending()
272 if (iX && iX->iPendingFn)
273 return (*iX->iPendingFn)(this);
277 void NIrq::HwWaitCpus()
279 if (iX && iX->iWaitFn)
280 (*iX->iWaitFn)(this);
286 TInt n = 1 + (TheIoApic.Ver() >> 16);
290 TheIoApic.ModifyControl(i,
291 IO_APIC_CTRL_DELMOD_MASK | IO_APIC_CTRL_INTVEC_MASK | IO_APIC_CTRL_LEVEL | IO_APIC_CTRL_INTPOL_LOW,
292 IO_APIC_CTRL_DESTMOD | IO_APIC_CTRL_IMASK | 0xff);
293 TheIoApic.ModifyDest(i, 0x01);
296 TheIoApic.ModifyControl(i, 0, IO_APIC_CTRL_LEVEL | IO_APIC_CTRL_INTPOL_LOW);
304 write_apic_reg(SIVR, 0x300 | SPURIOUS_INTERRUPT_VECTOR);
305 write_apic_reg(DIVCNF, 10); // APIC timer clock divide by 128 (bus clock freq / 128)
306 write_apic_reg(LVTTMR, 0x10000|TIMESLICE_VECTOR);
307 write_apic_reg(DFR, 0xf0000000u); // set flat logical destination mode
308 write_apic_reg(LDR, 0x01000000u); // this CPU will be selected by logical destination with bit 0 set
311 void NIrq::HwInit2AP()
313 TInt cpu = NKern::CurrentCpu();
314 write_apic_reg(SIVR, 0x300 | SPURIOUS_INTERRUPT_VECTOR);
315 write_apic_reg(DIVCNF, 10);
316 write_apic_reg(LVTTMR, 0x10000|TIMESLICE_VECTOR);
317 write_apic_reg(DFR, 0xf0000000u); // set flat logical destination mode
318 write_apic_reg(LDR, 0x01000000u<<cpu); // this CPU will be selected by logical destination with bit n set