|
1 // Copyright (c) 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/shared/mstick/mstick.cpp |
|
15 // |
|
16 |
|
17 #include <nk_priv.h> |
|
18 #include <assp/omap3530_assp/omap3530_timer.h> |
|
19 #include <assp/omap3530_assp/omap3530_prcm.h> |
|
20 #include <assp/omap3530_assp/omap3530_irqmap.h> |
|
21 #include <assp/omap3530_assp/omap3530_hardware_base.h> |
|
22 |
|
23 using namespace TexasInstruments::Omap3530 ; |
|
24 using namespace TexasInstruments::Omap3530::GPTimer ; |
|
25 |
|
26 const TUint32 KMaxIdleTicks = 0xFFFFFF; |
|
27 const TUint KMinSuppressTickCount = 2; |
|
28 static const Omap3530HwBase::TRegValue KTickInterruptMask = TISR::T_OVF_IT_FLAG::KOn; |
|
29 |
|
30 |
|
31 namespace Omap3 |
|
32 { |
|
33 namespace MsTick |
|
34 { |
|
35 |
|
36 void MsTickIsr(TAny* aPtr ) |
|
37 { |
|
38 // Clear interrupts |
|
39 TGpTimer1::iTISR.Write( KTickInterruptMask ); |
|
40 TGpTimer1::iTOCR.Write( 0 ); |
|
41 reinterpret_cast< NTimerQ* >( aPtr )->Tick(); |
|
42 } |
|
43 |
|
44 |
|
45 EXPORT_C TInt Start() |
|
46 { |
|
47 __KTRACE_OPT(KBOOT,Kern::Printf("+Omap3:MsTick:Start")); |
|
48 |
|
49 // Enable GPT1 and set it to run from the 32kHz sysclk |
|
50 Prcm::SetGptClockSource( Prcm::EGpt1, Prcm::EGptClock32k ); |
|
51 Prcm::SetClockState( Prcm::EClkGpt1_F, Prcm::EClkOn ); |
|
52 Prcm::SetClockState( Prcm::EClkGpt1_I, Prcm::EClkAuto ); |
|
53 |
|
54 __NK_ASSERT_DEBUG(TGpTimer1::iTISTAT.Read() == 0x1); |
|
55 |
|
56 // Prcm::AddToWakeupGroup( Prcm::EClkGpt1_I, Prcm::EWakeGroupMpu ); |
|
57 |
|
58 //Set GPT1 to highest priority |
|
59 Interrupt::SetPriority(EOmap3530_IRQ37_GPT1_IRQ,KOmap3530MaxIntPriority); |
|
60 |
|
61 // Bind to GPTimer 1 interrupt |
|
62 TInt r = Interrupt::Bind( TGpTimer1::Irq(), MsTickIsr, NTimerQ::TimerAddress() ); |
|
63 |
|
64 if( KErrNone == r ) |
|
65 { |
|
66 TGpTimer1::Reset(); |
|
67 while ( !TGpTimer1::ResetComplete()) {} |
|
68 |
|
69 const TRegValue startOcp = ( TIOCP_CFG::T_AUTOIDLE::KOff |
|
70 | TIOCP_CFG::T_SOFTRESET::KOff |
|
71 | TIOCP_CFG::T_ENAWAKEUP::KOn |
|
72 | TIOCP_CFG::T_IDLEMODE::KSmartIdle |
|
73 | TIOCP_CFG::T_EMUFREE::KOff |
|
74 | TIOCP_CFG::T_CLOCKACTIVITY::KMaintainFuncClock); |
|
75 TGpTimer1::iTIOCP_CFG.Write(startOcp) ; |
|
76 TGpTimer1::iTIOCP_CFG.Modify(TIOCP_CFG::T_SOFTRESET::KOn, KClear32); |
|
77 TGpTimer1::iTIOCP_CFG.Write(startOcp); |
|
78 |
|
79 // Enable timer to generate wakeups |
|
80 TGpTimer1::iTWER.Write(TWER::T_MAT_WUP_ENA::KOff | TWER::T_OVF_WUP_ENA::KOn | TWER::T_TCAR_WUP_ENA::KOff); |
|
81 |
|
82 TGpTimer1::ConfigureFor1Ms(); |
|
83 |
|
84 TGpTimer1::iTIER.Write(TIER::T_MAT_IT_ENA::KOff | TIER::T_OVF_IT_ENA::KOn | TIER::T_TCAR_IT_ENA::KOff); |
|
85 TGpTimer1::iTISR.Write(TISR::T_MAT_IT_FLAG::KOn | TISR::T_OVF_IT_FLAG::KOn | TISR::T_TCAR_IT_FLAG::KOff); |
|
86 |
|
87 TGpTimer1::iTTGR.Write(1); |
|
88 |
|
89 TGpTimer1::iTOWR.Write( 0 ); |
|
90 |
|
91 while (TGpTimer1::WriteOutstanding()) {} |
|
92 |
|
93 // Start the timer in auto-reload mode |
|
94 TGpTimer1::iTCLR.Modify(KClear32, (TCLR::T_ST::KOn | TCLR::T_AR::KOn | TCLR::T_IDLEMODE::KOverflow)); |
|
95 |
|
96 // Ensure Timer Control Reg write is completed |
|
97 while(TGpTimer1::WriteOutstanding()); |
|
98 |
|
99 Interrupt::Enable(TGpTimer1::Irq()); |
|
100 } |
|
101 |
|
102 __KTRACE_OPT(KBOOT,Kern::Printf("-Omap3:MsTick:Start:%d", r )); |
|
103 return r; |
|
104 } |
|
105 |
|
106 EXPORT_C TInt SuppressIdleTicks( TInt aMaxSleepTicks ) |
|
107 { |
|
108 TUint32 targetSleepTicks = (aMaxSleepTicks >= KMaxIdleTicks) ? KMaxIdleTicks : aMaxSleepTicks; |
|
109 |
|
110 if( targetSleepTicks >= KMinSuppressTickCount ) |
|
111 { |
|
112 while(TGpTimer1::WriteOutstanding()); |
|
113 |
|
114 // Mask out the next <targetSleepTicks> number of overflow events |
|
115 // Don't clear TOCR - we want to include any pending expiries that happened |
|
116 // while we were setting up into the sleep count |
|
117 TGpTimer1::iTOWR.Write( targetSleepTicks ); |
|
118 |
|
119 // Clear any pending interrupt so we don't wake up immediately |
|
120 TGpTimer1::iTISR.Write( KTickInterruptMask ); |
|
121 while(TGpTimer1::WriteOutstanding()); |
|
122 } |
|
123 else |
|
124 { |
|
125 targetSleepTicks = 0; |
|
126 } |
|
127 |
|
128 return targetSleepTicks; |
|
129 } |
|
130 |
|
131 EXPORT_C TInt EndIdleTickSuppression( TInt aMaxSleepTicks ) |
|
132 { |
|
133 TUint actualSleepTicks = 0; |
|
134 |
|
135 if( aMaxSleepTicks >= KMinSuppressTickCount ) |
|
136 { |
|
137 // Get counter values immediately. TCRR must be read first so we can check for |
|
138 // overflow while we are executing this code |
|
139 TUint32 tcrr = TGpTimer1::iTCRR.Read(); |
|
140 TUint32 tisr = TGpTimer1::iTISR.Read() bitand KTickInterruptMask; |
|
141 TUint32 tocr = TGpTimer1::iTOCR.Read(); |
|
142 |
|
143 TUint32 targetSleepTicks = (aMaxSleepTicks >= KMaxIdleTicks) ? KMaxIdleTicks : aMaxSleepTicks; |
|
144 |
|
145 // Initial assumption is number of ticks missed == overflow count |
|
146 actualSleepTicks = tocr; |
|
147 |
|
148 if( tisr ) |
|
149 { |
|
150 // If maximum time has expired TOCR will be reset to zero |
|
151 // we want to handle the pending tick interrupt immediately |
|
152 // in the normal tick ISR so don't include it in the count of |
|
153 // ticks slept |
|
154 actualSleepTicks = targetSleepTicks - 1; |
|
155 } |
|
156 |
|
157 // Set timer back to normal mode |
|
158 // Dont' clear interrupts - we want any pending timer interrupt handled in the tick ISR |
|
159 TGpTimer1::iTOWR.Write( 0 ); |
|
160 TGpTimer1::iTOCR.Write( 0 ); |
|
161 while(TGpTimer1::WriteOutstanding()); |
|
162 |
|
163 // Check whether another tick has expired while we were doing this |
|
164 if( TGpTimer1::iTCRR.Read() < tcrr ) |
|
165 { |
|
166 // it's overflowed since we first checked |
|
167 if( tisr ) |
|
168 { |
|
169 // if there was already a pending interrupt to be handled by the tick ISR |
|
170 // we need to include this new expiry in the sleep count |
|
171 ++actualSleepTicks; |
|
172 } |
|
173 // else if there wasn't already a pending interrupt, this overflow will have generated |
|
174 // one which will be handled by the tick ISR |
|
175 } |
|
176 } |
|
177 |
|
178 return actualSleepTicks; |
|
179 } |
|
180 |
|
181 } // namespace MsTick |
|
182 } // namespace Omap3 |
|
183 |
|
184 |
|
185 DECLARE_STANDARD_EXTENSION() |
|
186 { |
|
187 return KErrNone; |
|
188 } |
|
189 |