First public contribution.
1 // Copyright (c) 1994-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 // template\template_variant\specific\variant.cpp
20 #include <videodriver.h>
21 #include <drivers/xyin.h>
22 #include "template_power.h"
24 //These constants define Custom Restart Reasons in SuperPage::iHwStartupReason
25 const TUint KHtCustomRestartMax = 0xff;
26 const TUint KHtCustomRestartShift = 8;
27 const TUint KHtCustomRestartMask = KHtCustomRestartMax << KHtCustomRestartShift;
29 const TUint KHtRestartStartupModesMax = 0xf; // Variable, platform dependant
30 const TUint KHtRestartStartupModesShift = 16; // Variable, platform dependant
31 const TUint KHtRestartStartupModesMask = KHtRestartStartupModesMax << KHtRestartStartupModesShift;
33 void TemplateVariantFault(TInt aLine)
35 Kern::Fault("TemplateVariant",aLine);
38 #define V_FAULT() TemplateVariantFault(__LINE__)
43 #define DEBUG_XON_XOFF 0 // Non-zero if we want XON-XOFF handshaking
45 GLDEF_D Template TheVariant;
46 TUint32 Variant::iBaseAddress=0;
48 TUint32 Template::HandlerData[3];
49 SInterruptHandler Template::Handlers[ENumXInts];
51 extern void XIntDispatch(TAny*);
53 EXPORT_C Asic* VariantInitialise()
60 iDebugInitialised=EFalse;
66 // Specify the RAM zone configuration.
68 // The lowest addressed zone must have the highest preference as the bootstrap
69 // will always allocate from the lowest address up. Once the kernel has initialised
70 // then the zone preferences will decide from which RAM zone memory is allocated.
72 // const TUint KVariantRamZoneCount = ?;
73 // static const SRamZone KRamZoneConfig[KVariantRamZoneCount+1] =
74 // iBase iSize iID iPref iFlags
76 // __SRAM_ZONE(0x????????, 0x???????, ?, ?, ?),
78 // __SRAM_ZONE(0x????????, 0x???????, ?, ?, ?),
79 // __SRAM_ZONE_END, // end of zone list
83 TInt Template::RamZoneCallback(TRamZoneOp aOp, TAny* aId, const TAny* aMasks)
88 // Handle RAM zone operations requested by the kernel.
90 return TheVariant.DoRamZoneCallback(aOp, (TUint)aId, (const TUint*)aMasks);
94 TInt Template::DoRamZoneCallback(TRamZoneOp aOp, TUint aId, const TUint* aMasks)
99 // Handle RAM zone operations requested by the kernel.
101 // Three types of operation need to be supported:
102 // ERamZoneOp_Init: Update power state of the RAM zones after the
103 // kernel has initialised.
104 // ERamZoneOp_PowerUp: A RAM zone changing from used to empty.
105 // ERamZoneOp_PowerDown: A RAM zone changing from empty to used.
110 case ERamZoneOp_Init:
112 case ERamZoneOp_PowerUp:
114 case ERamZoneOp_PowerDown:
117 return KErrNotSupported;
123 void Template::Init1()
125 __KTRACE_OPT(KBOOT,Kern::Printf("Template::Init1()"));
128 // TO DO: (mandatory)
130 // Configure Memory controller and Memrory Bus parameters (in addition to what was done in the Bootstrap)
132 __KTRACE_OPT(KBOOT,Kern::Printf("Memory Configuration done"));
137 // Inform the kernel of the RAM zone configuration via Epoc::SetRamZoneConfig().
138 // For devices that wish to reduce power consumption of the RAM IC(s) the callback functions
139 // RamZoneCallback() and DoRamZoneCallback() will need to be implemented and passed
140 // to Epoc::SetRamZoneConfig() as the parameter aCallback.
141 // The kernel will assume that all RAM ICs are fully intialised and ready for use from boot.
147 // Initialise other critical hardware functions such as I/O interfaces, etc, not done by Bootstrap
149 // if CPU is Sleep-capable, and requires some preparation to be put in that state (code provided in Bootstrap),
150 // the address of the idle code is writen at this location by the Bootstrap
152 // iIdleFunction=*(TLinAddr*)((TUint8*)&Kern::SuperPage()+0x1000);
154 TemplateAssp::Init1();
157 void Template::Init3()
159 __KTRACE_OPT(KBOOT,Kern::Printf("Template::Init3()"));
161 TemplateAssp::Init3();
167 // Initialise other accessor classes, if required
173 void Variant::Init3()
175 // Phase 3 initialisation
178 __KTRACE_OPT(KHARDWARE, Kern::Printf(">Variant::Init3"));
183 // Initialise any Variant class data members here, map in Variant and external hardware addresses
185 DPlatChunkHw* pC=NULL;
186 TInt r=DPlatChunkHw::New(pC,KHwVariantPhysBase,0x2000,EMapAttrSupRw|EMapAttrFullyBlocking);
187 __ASSERT_ALWAYS(r==KErrNone,V_FAULT());
188 iBaseAddress=pC->LinearAddress();
191 EXPORT_C TUint Variant::BaseLinAddress()
193 return((TUint)iBaseAddress);
196 EXPORT_C void Variant::MarkDebugPortOff()
198 TheVariant.iDebugInitialised=EFalse;
201 EXPORT_C void Variant::UartInit()
204 if (!TheVariant.iDebugInitialised)
207 // TO DO: (mandatory)
209 // Reset and initialise the UART used to output debug strings
211 TheVariant.iDebugInitialised=ETrue;
216 void Template::DebugInit()
219 // TO DO: (mandatory)
221 // Initialise the UART used for outputting Debug Strings (no Interrupts), as in the following EXAMPLE ONLY:
224 TTemplate::BootWaitMilliSeconds(10); // wait loop to ensure that the port is fully initialised and output buffer empty
227 void Template::DebugOutput(TUint aLetter)
229 // Output a character to the debug port
232 if (!iDebugInitialised)
237 // TO DO: (mandatory)
239 // Write the character aLetter to the UART output register and wait until sent (do NOT use interrupts!)
243 void Template::Idle()
245 // The NULL thread idle loop
248 // Idle the CPU, suppressing the system tick if possible
253 // Idle Tick supression:
254 // 1- obtain the number of idle Ticks before the next NTimer expiration (NTimerQ::IdleTime())
255 // 2- if the number of Ticks is large enough (criteria to be defined) reset the Hardware Timer
256 // to only interrupt again when the corresponding time has expired.
257 // 2.1- the calculation of the new value to program the Hardware Timer with should take in
258 // consideration the rounding value (NTimerQ::iRounding)
259 // 3- call the low level Sleep function (e'g. Bootstrap: address in iIdleFunction)
260 // 4- on coming back from Idle need to read the Hardware Timer and determine if woken up due to
261 // timer expiration (system time for new match<=current system time<system time for new match-tick period)
262 // or some other Interrupt.
263 // 4.1- if timer expiration, adjust System Time by adding the number of Ticks suppressed to NTimerQ::iMsCount
264 // 4.2- if other interrupt, calculate the number of Ticks skipped until woken up and adjust the System Time as
267 // Support for different Sleep Modes:
268 // Often the Sleep mode a platform can go to depends on how many resources such as clocks/voltages can be
269 // turned Off or lowered to a suitable level. If different Sleep modes are supported this code may need
270 // to be able to find out what power resources are On or Off or used to what level. This could be achieved by
271 // enquiring the Resource Manager (see \template_variant\inc\template_power.h).
272 // Then a decision could be made to what Sleep level we go to.
275 // Obtain the number of Idle Ticks before the next NTimer expiration
276 // TInt aTicksLeft = NTimerQ::IdleTime();
278 // Find out the deepest Sleep mode available for current resource usage and sleeping time
279 // TemplateResourceManager* aManager = TTemplatePowerController::ResourceManager();
280 // TemplateResourceManager::TSleepModes aMode = aManager -> MapSleepMode(aTicksLeft*MsTickPeriod());
282 // Find out the state of some particular resources
283 // TBool aResourceState = aManager -> GetResourceState(TemplateResourceManager::AsynchBinResourceUsedByZOnly);
284 // TUint aResourceLevel = aManager -> GetResourceLevel(TemplateResourceManager::SynchMlResourceUsedByXOnly);
288 TInt Template::VariantHal(TInt aFunction, TAny* a1, TAny* a2)
293 case EVariantHalVariantInfo:
295 TVariantInfoV01Buf infoBuf;
296 TVariantInfoV01& info=infoBuf();
297 info.iRomVersion=Epoc::RomHeader().iVersion;
300 // TO DO: (mandatory)
302 // Fill in the TVariantInfoV01 info structure
303 // info.iMachineUniqueId=;
304 // info.iLedCapabilities=;
305 // info.iProcessorClockInKHz=;
306 // info.iSpeedFactor=;
308 Kern::InfoCopy(*(TDes8*)a1,infoBuf);
311 case EVariantHalDebugPortSet:
314 // TO DO: (mandatory)
316 // Write the iDebugPort field of the SuperPage, as in the following EXAMPLE ONLY:
318 TUint32 thePort = (TUint32)a1;
324 TheVariant.iDebugInitialised=EFalse;
325 case (TUint32)KNullDebugPort:
326 Kern::SuperPage().iDebugPort = thePort;
333 case EVariantHalDebugPortGet:
336 // TO DO: (mandatory)
338 // Obtain the Linear address of the Uart used for outputting Debug strings as in the following EXAMPLE ONLY:
341 TUint32 thePort = TTemplate::DebugPortAddr();
342 kumemput32(a1, &thePort, sizeof(TUint32));
345 case EVariantHalSwitches:
350 // Read the state of any switches, as in the following EXAMPLE ONLY:
352 TUint32 x = Variant::Switches();
353 kumemput32(a1, &x, sizeof(x));
356 case EVariantHalLedMaskSet:
361 // Set the state of any on-board LEDs, e.g:
362 // TUint32 aLedMask=(TUint32)a1;
363 // Variant::ModifyLedState(~aLedMask,aLedMask);
367 case EVariantHalLedMaskGet:
372 // Read the state of any on-board LEDs, e.g:
373 // TUint32 x = Variant::LedState();
374 // kumemput32(a1, &x, sizeof(x));
379 case EVariantHalCustomRestartReason:
381 //Restart reason is stored in super page
382 TInt x = (Kern::SuperPage().iHwStartupReason & KHtCustomRestartMask) >> KHtCustomRestartShift ;
383 kumemput32(a1, &x, sizeof(TInt));
387 case EVariantHalCustomRestart:
389 if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EVariantHalCustomRestart")))
390 return KErrPermissionDenied;
391 if ((TUint)a1 > KHtCustomRestartMax)
393 Kern::Restart((TInt)a1 << KHtCustomRestartShift);
397 case EVariantHalCaseState:
402 // Read the state of the case, e.g:
403 // TUint32 x = Variant::CaseState();
404 // kumemput32(a1, &x, sizeof(x));
409 case EVariantHalPersistStartupMode:
411 if (!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetBacklightOn")))
412 return KErrPermissionDenied;
414 if ((TUint)a1 > KHtRestartStartupModesMax ) // Restart startup mode max value
419 // Store the restart reason locally,
420 // which will eventually be picked up by
421 // the power controller, e.g:
422 // iCustomRestartReason = (TUint)a1;
427 case EVariantHalGetPersistedStartupMode:
432 // Read the restart startup mode, e.g:
433 // TInt startup = (Kern::SuperPage().iHwStartupReason & KHtRestartStartupModesMask) >> KHtRestartStartupModesShift;
434 // kumemput32(a1, &startup, sizeof(TInt));
438 case EVariantHalGetMaximumCustomRestartReasons:
443 // Read the maximum custom restart reason, e.g:
444 // kumemput32(a1, &KHtCustomRestartMax, sizeof(TUint));
449 case EVariantHalGetMaximumRestartStartupModes:
454 // Read the maximum restart startup mode, e.g:
455 // kumemput32(a1, &KHtRestartStartupModesMax, sizeof(TUint));
459 case EVariantHalProfilingDefaultInterruptBase:
464 //Set the default interrupt number for the sampling profiler.
465 //TInt interruptNumber = KIntCpuProfilingDefaultInterruptBase;
466 //kumemput(a1,&interruptNumber,sizeof(interruptNumber));
477 TPtr8 Template::MachineConfiguration()
479 return TPtr8((TUint8*)&Kern::MachineConfig(),sizeof(TActualMachineConfig),sizeof(TActualMachineConfig));
482 TInt Template::VideoRamSize()
485 // TO DO: (mandatory)
487 // Return the size of the area of RAM used to store the Video Buffer, as in the following EXAMPLE ONLY:
492 EXPORT_C void Variant::PowerReset()
497 // Reset all power supplies
501 EXPORT_C TUint Variant::Switches()
506 // Read the state of on-board switches
508 return 0; // EXAMPLE ONLY
511 /******************************************************************************
512 * Interrupt handling/dispatch
513 ******************************************************************************/
514 TInt Template::InterruptBind(TInt anId, TIsr anIsr, TAny* aPtr)
516 TUint id=anId&0x7fffffff; // mask off second-level interrupt mask
520 SInterruptHandler& h=Handlers[id];
521 TInt irq=NKern::DisableAllInterrupts();
522 if (h.iIsr!=Spurious)
529 NKern::RestoreInterrupts(irq);
533 TInt Template::InterruptUnbind(TInt anId)
535 TUint id=anId&0x7fffffff; // mask off second-level interrupt mask
538 InterruptDisable(anId);
539 InterruptClear(anId);
541 SInterruptHandler& h=Handlers[id];
542 TInt irq=NKern::DisableAllInterrupts();
543 if (h.iIsr!=Spurious)
548 NKern::RestoreInterrupts(irq);
552 TInt Template::InterruptEnable(TInt anId)
554 TUint id=anId&0x7fffffff; // mask off second-level interrupt mask
558 SInterruptHandler& h=Handlers[id];
559 TInt irq=NKern::DisableAllInterrupts();
560 if (h.iIsr==Spurious)
565 // TO DO: (mandatory)
567 // Enable the hardware interrupt in the source, e.g.
568 // Variant::EnableInt(anId);
571 NKern::RestoreInterrupts(irq);
575 TInt Template::InterruptDisable(TInt anId)
577 TUint id=anId&0x7fffffff; // mask off second-level interrupt mask
581 // TO DO: (mandatory)
583 // Disable the hardware interrupt in the source, e.g.
584 // Variant::DisableInt(anId);
589 TInt Template::InterruptClear(TInt anId)
591 TUint id=anId&0x7fffffff;
595 // TO DO: (mandatory)
597 // Clear the hardware interrupt in the source, e.g.
598 // Variant::ClearInt(anId);
603 void Template::InitInterrupts()
605 // Set up the variant interrupt dispatcher
607 // all interrupts initially unbound
609 for (i=0; i<(TInt)ENumXInts; i++)
611 Handlers[i].iPtr=(TAny*)i;
612 Handlers[i].iIsr=Spurious;
615 // Set up data for 2nd level interrupt dispatcher
616 HandlerData[0]=Variant::BaseLinAddress(); // Linear Base address of 2nd level Int Controller
617 HandlerData[1]=(TUint32)&Handlers[0]; // Pointer to handler array
621 // TO DO: (mandatory)
623 // set up ASSP expansion interrupt to generate interrupts whenever a 2nd level interrupt occurrs
626 // bind Template ASSP expansion interrupt input to our interrupt dispatcher
627 TInt r=Interrupt::Bind(KIntIdExpansion, XIntDispatch, HandlerData);
628 __ASSERT_ALWAYS(r==KErrNone,V_FAULT());
629 Interrupt::Enable(KIntIdExpansion); // enable expansion interrupt
632 void Template::Spurious(TAny* aId)
634 TUint32 id=((TUint32)aId)|0x80000000u;
635 Kern::Fault("SpuriousInt",id);
639 // USB Client controller
641 TBool Template::UsbClientConnectorDetectable()
643 __KTRACE_OPT(KHARDWARE, Kern::Printf("Template::UsbClientConnectorDetectable"));
645 // TO DO: The return value should reflect the actual situation.
650 TBool Template::UsbClientConnectorInserted()
652 __KTRACE_OPT(KHARDWARE, Kern::Printf("Template::UsbClientConnectorInserted"));
654 // TO DO: Query cable status here. The return value should reflect the actual current state.
659 TInt Template::RegisterUsbClientConnectorCallback(TInt (*aCallback)(TAny*), TAny* aPtr)
661 __KTRACE_OPT(KHARDWARE, Kern::Printf("Template::RegisterUsbClientConnectorCallback"));
663 iUsbClientConnectorCallback = aCallback;
664 iUsbClientConnectorCallbackArg = aPtr;
666 // TO DO: Register and enable the interrupt(s) for detecting USB cable insertion/removal here.
667 // (Register UsbClientConnectorIsr.)
669 // TO DO: The return value should reflect the actual situation.
674 void Template::UnregisterUsbClientConnectorCallback()
676 __KTRACE_OPT(KHARDWARE, Kern::Printf("Template::UnregisterUsbClientConnectorCallback"));
678 // TO DO: Disable and unbind the interrupt(s) for detecting USB cable insertion/removal here.
680 iUsbClientConnectorCallback = NULL;
681 iUsbClientConnectorCallbackArg = NULL;
685 TBool Template::UsbSoftwareConnectable()
687 __KTRACE_OPT(KHARDWARE, Kern::Printf("Template::UsbSoftwareConnectable"));
689 // TO DO: The return value should reflect the actual situation.
694 TInt Template::UsbConnect()
696 __KTRACE_OPT(KHARDWARE, Kern::Printf("Template::UsbConnect"));
698 // TO DO: Do here whatever is necessary for the UDC to appear on the bus (and thus to the host).
704 TInt Template::UsbDisconnect()
706 __KTRACE_OPT(KHARDWARE, Kern::Printf("Template::UsbDisconnect"));
708 // TO DO: Do here whatever is necessary for the UDC to appear disconnected from the bus (and thus from the
715 void Template::UsbClientConnectorIsr(TAny *aPtr)
717 // Services the USB cable interrupt.
720 __KTRACE_OPT(KHARDWARE, Kern::Printf("Template::UsbClientConnectorIsr()"));
722 Template* tm = static_cast<Template*>(aPtr);
724 // TO DO: Service interrupt here: determmine cause, clear condition flag (if applicable), etc.
726 if (tm->UsbClientConnectorInserted())
728 __KTRACE_OPT(KHARDWARE, Kern::Printf(" > USB cable now inserted."));
732 __KTRACE_OPT(KHARDWARE, Kern::Printf(" > USB cable now removed."));
735 // Important: Inform the USB stack.
736 if (tm->iUsbClientConnectorCallback)
738 (*tm->iUsbClientConnectorCallback)(tm->iUsbClientConnectorCallbackArg);