|
1 /* |
|
2 * tiwlanhpa.cpp |
|
3 * |
|
4 * Copyright(c) 1998 - 2010 Texas Instruments. All rights reserved. |
|
5 * All rights reserved. |
|
6 * |
|
7 * This program and the accompanying materials are made available under the |
|
8 * terms of the Eclipse Public License v1.0 or BSD License which accompanies |
|
9 * this distribution. The Eclipse Public License is available at |
|
10 * http://www.eclipse.org/legal/epl-v10.html and the BSD License is as below. |
|
11 * |
|
12 * Redistribution and use in source and binary forms, with or without |
|
13 * modification, are permitted provided that the following conditions |
|
14 * are met: |
|
15 * |
|
16 * * Redistributions of source code must retain the above copyright |
|
17 * notice, this list of conditions and the following disclaimer. |
|
18 * * Redistributions in binary form must reproduce the above copyright |
|
19 * notice, this list of conditions and the following disclaimer in |
|
20 * the documentation and/or other materials provided with the |
|
21 * distribution. |
|
22 * * Neither the name Texas Instruments nor the names of its |
|
23 * contributors may be used to endorse or promote products derived |
|
24 * from this software without specific prior written permission. |
|
25 * |
|
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
30 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
36 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
37 */ |
|
38 |
|
39 |
|
40 |
|
41 /** \file TIWlanHpa.cpp |
|
42 * \brief Interface between the sandbox to the BSP of Omap3430 |
|
43 * |
|
44 * \see |
|
45 */ |
|
46 |
|
47 #include <omap_reg.h> |
|
48 |
|
49 #include "kernel.h" |
|
50 #include "TIWlanHpa.h" |
|
51 #include "wlanhpa.h" |
|
52 #include "wlanosaext.h" |
|
53 |
|
54 /* To debug HPA, define some prints here using OSA*/ |
|
55 #define TRACE(msg) |
|
56 /*Kern::Printf(msg)*/ |
|
57 #define ERROR_TRACE(msg) Kern::Printf(msg); |
|
58 |
|
59 |
|
60 extern void Assert( const TInt8*, TInt, TInt ); |
|
61 |
|
62 /** |
|
63 * \fn Create |
|
64 * \brief static creator |
|
65 * |
|
66 * Create hpa layer object |
|
67 * |
|
68 * \note |
|
69 * \param aOsaExt osa extension object |
|
70 * \return hpa layer object, NULL upon failure |
|
71 */ |
|
72 WlanHpa* WlanHpa::Create( MWlanOsaExt& aOsaExt, MWlanOsa& aOsa) |
|
73 { |
|
74 TRACE(("WlanHpa::Create\n")); |
|
75 |
|
76 return new TIWlanHpa(aOsaExt, aOsa); |
|
77 } |
|
78 |
|
79 /** |
|
80 * \fn Destroy |
|
81 * \brief |
|
82 * |
|
83 * Destroy hpa layer object |
|
84 * |
|
85 * \note |
|
86 * \param aWlanHpa hpa layer object |
|
87 */ |
|
88 void WlanHpa::Destroy( WlanHpa* aWlanHpa ) |
|
89 { |
|
90 if (aWlanHpa) |
|
91 { |
|
92 delete aWlanHpa; |
|
93 } |
|
94 } |
|
95 |
|
96 /** |
|
97 * \fn TIWlanHpa |
|
98 * \brief constructor |
|
99 * |
|
100 * \note |
|
101 * \param aOsaExt |
|
102 */ |
|
103 TIWlanHpa::TIWlanHpa(MWlanOsaExt& aOsaExt, MWlanOsa& aOsa): |
|
104 WlanHpa( aOsaExt, aOsa), |
|
105 iIrqDfc(InterruptHandlerDfc,(TAny*)this,0) |
|
106 { |
|
107 TRACE(("%s\n",__FUNCTION__)); |
|
108 TRACE(("construct")); |
|
109 iIrqDfc.SetDfcQ( Kern::DfcQue0() ); |
|
110 } |
|
111 |
|
112 /** |
|
113 * \fn TIWlanHpa |
|
114 * \brief destructor |
|
115 * |
|
116 * \note |
|
117 */ |
|
118 TIWlanHpa::~TIWlanHpa() |
|
119 { |
|
120 TRACE(("%s\n",__FUNCTION__)); |
|
121 |
|
122 } |
|
123 |
|
124 /** |
|
125 * \fn TIWlanHpa |
|
126 * \brief Turns WLAN device power on |
|
127 * |
|
128 * \note |
|
129 */ |
|
130 void TIWlanHpa::PowerOnDevice() |
|
131 { |
|
132 TRACE(("PowerOnDevice\n")); |
|
133 |
|
134 /* Hook to IRQ line */ |
|
135 SetupIrqHw(iConfig.iIsrPolarity); |
|
136 TRACE(("PowerOnDevice 2\n")); |
|
137 |
|
138 /* Hook to Reset (PM Enable) line */ |
|
139 SetupRstHw(); |
|
140 TRACE(("PowerOnDevice 3\n")); |
|
141 |
|
142 TOmap::ModifyRegister32(KHwBaseSysCtrlReg +0x0c8,0xFFFF,0x411C); |
|
143 |
|
144 TOmap::ModifyRegister32(KHwBaseSysCtrlReg +0xA0C,0xFFFF,0x104); |
|
145 |
|
146 /* Activate PM Enable line */ |
|
147 ExitReset(); |
|
148 } |
|
149 |
|
150 /** |
|
151 * \fn TIWlanHpa |
|
152 * \brief Turns WLAN devices power off |
|
153 * |
|
154 * \note |
|
155 */ |
|
156 void TIWlanHpa::PowerOffDevice() |
|
157 { |
|
158 TRACE(("%s\n",__FUNCTION__)); |
|
159 |
|
160 /* Unbind ISR and disable notification */ |
|
161 KillInterrupts(); |
|
162 |
|
163 TOmap::ModifyRegister32(KHwBaseSysCtrlReg +0x0c8,0xFFFF,0x10C); |
|
164 |
|
165 TOmap::ModifyRegister32(KHwBaseSysCtrlReg +0xA0C,0xFFFF,0x10C); |
|
166 |
|
167 /* Deactivate PM Enable */ |
|
168 EnterReset(); |
|
169 |
|
170 /* Release reset & IRQ pins */ |
|
171 GPIO::SetPinMode(RST_GPIO_NUM, GPIO::EDisabled); |
|
172 |
|
173 /* cancel any pending interrupts (i.e DFC was scheduled before calling PowerOffDevice() ) */ |
|
174 iIrqDfc.Cancel(); |
|
175 } |
|
176 |
|
177 /** |
|
178 * \fn InterruptServiced |
|
179 * \brief |
|
180 * |
|
181 * Called by hpa layer object client when peripheral interrupt |
|
182 * informed by OnInterrupt method has been serviced. |
|
183 * NOTE: on systems implementing level sensitive interrupt handling |
|
184 * host interrupt is enabled at this state |
|
185 * |
|
186 * \note |
|
187 */ |
|
188 void TIWlanHpa::InterruptServiced() |
|
189 { |
|
190 Enable(); |
|
191 } |
|
192 |
|
193 /** |
|
194 * \fn Configure |
|
195 * \brief configure polarity of IRQ |
|
196 * |
|
197 * \note |
|
198 * \param aWlanHpa::TConfig |
|
199 */ |
|
200 void TIWlanHpa::Configure( const WlanHpa::TConfig& aConfig ) |
|
201 { |
|
202 TRACE(("Configure")); |
|
203 |
|
204 /* Save configuration of polarity, to be used in SetupIrqHw() */ |
|
205 iConfig = aConfig; |
|
206 } |
|
207 |
|
208 /** |
|
209 * \fn Configure |
|
210 * \brief configure polarity of IRQ |
|
211 * |
|
212 * \note |
|
213 * \param aWlanHpa::TConfig |
|
214 */ |
|
215 void TIWlanHpa::EnableIrq() |
|
216 { |
|
217 TRACE(("EnableIrq")); |
|
218 |
|
219 Enable(); |
|
220 } |
|
221 |
|
222 /** |
|
223 * \fn DebugGpioToggle |
|
224 * \brief |
|
225 * |
|
226 * \note |
|
227 * \param |
|
228 */ |
|
229 TBool TIWlanHpa::DebugGpioToggle( TBool aHigh ){ return 0;} |
|
230 /** |
|
231 * \fn ExitReset |
|
232 * \brief Sets WLAN PMEN line. |
|
233 * |
|
234 * \note |
|
235 * \param |
|
236 */ |
|
237 void TIWlanHpa::ExitReset() |
|
238 { |
|
239 /* Set GPIO driver output to logic High */ |
|
240 GPIO::SetOutputState(RST_GPIO_NUM, GPIO::EHigh); |
|
241 } |
|
242 |
|
243 /** |
|
244 * \fn EnterReset |
|
245 * \brief Clears WLAN PMEN line. |
|
246 * |
|
247 * \note |
|
248 * \param |
|
249 */ |
|
250 void TIWlanHpa::EnterReset() |
|
251 { |
|
252 /* Set GPIO driver output to logic Low */ |
|
253 GPIO::SetOutputState(RST_GPIO_NUM, GPIO::ELow); |
|
254 } |
|
255 |
|
256 /** |
|
257 * \fn Disable |
|
258 * \brief Disables WLAN interrupt notification. |
|
259 * |
|
260 * \note |
|
261 * \param aOsaExt |
|
262 */ |
|
263 void TIWlanHpa::Disable() |
|
264 { |
|
265 GPIO::DisableInterrupt(IRQ_GPIO_NUM); |
|
266 } |
|
267 |
|
268 /** |
|
269 * \fn Enable |
|
270 * \brief Enables WLAN interrupt notification. |
|
271 * |
|
272 * \note |
|
273 * \param |
|
274 */ |
|
275 void TIWlanHpa::Enable() |
|
276 { |
|
277 GPIO::EnableInterrupt(IRQ_GPIO_NUM); |
|
278 } |
|
279 |
|
280 /** |
|
281 * \fn SetupIrqHw |
|
282 * \brief set IRQ line |
|
283 * |
|
284 * Sets GPIO as input line, binds it to an interrupt. Static function |
|
285 * Isr() is bound to the interrupt service routine. |
|
286 * |
|
287 * Uses following defines: |
|
288 * |
|
289 * #define IRQ_GPIO_NUM 61 |
|
290 * #define IRQ_MOD_NUM 0 |
|
291 * |
|
292 * of which IRQ_GPIO_NUM is the GPIO number and |
|
293 * IRQ_MOD_NUM is the module number where the corresponding |
|
294 * GPIO belongs to. |
|
295 * |
|
296 * \note |
|
297 * \param |
|
298 */ |
|
299 void TIWlanHpa::SetupIrqHw( WlanHpa::TIsrPolarity aPolarity) |
|
300 { |
|
301 Kern::Printf("SetupIrqHw %d", IRQ_GPIO_NUM); |
|
302 |
|
303 /*--------------------------------------------------------*/ |
|
304 /* common code to init the irq pin */ |
|
305 /*--------------------------------------------------------*/ |
|
306 TInt r = GPIO::SetPinMode(IRQ_GPIO_NUM, GPIO::EEnabled); |
|
307 if (r != KErrNone) |
|
308 { |
|
309 ERROR_TRACE(("ERROR:cant grab wlan interrupt pin")) |
|
310 Assert( __FILE__, __LINE__, EFalse ); |
|
311 } |
|
312 GPIO::SetPinDirection(IRQ_GPIO_NUM, GPIO::EInput); |
|
313 GPIO::ClearInterrupt(IRQ_GPIO_NUM); |
|
314 GPIO::DisableInterrupt(IRQ_GPIO_NUM); |
|
315 GPIO::DisableWakeup(IRQ_GPIO_NUM); |
|
316 |
|
317 r = GPIO::BindInterrupt (IRQ_GPIO_NUM, Isr, this); |
|
318 if (r != KErrNone) |
|
319 { |
|
320 ERROR_TRACE(("ERROR:cant bind wlan interrupt to pin")) |
|
321 Assert( __FILE__, __LINE__, EFalse ); |
|
322 } |
|
323 |
|
324 /* #warning "IRQ type is EDGE" */ |
|
325 if( WlanHpa::EIsrPolarityHigh == aPolarity) |
|
326 /* Configure the Intr on Rising edge sensitive */ |
|
327 GPIO::SetInterruptTrigger(IRQ_GPIO_NUM, GPIO::EEdgeRising); |
|
328 else |
|
329 /* Configure the Intr on Falling edge sensitive */ |
|
330 GPIO::SetInterruptTrigger(IRQ_GPIO_NUM, GPIO::EEdgeFalling); |
|
331 #if 0 |
|
332 #warning "IRQ type is LEVEL" |
|
333 if( WlanHpa::EIsrPolarityHigh == aPolarity) |
|
334 /* Configure the Intr on Rising leve sensitive */ |
|
335 GPIO::SetInterruptTrigger(IRQ_GPIO_NUM, GPIO::ELevelHigh); |
|
336 else |
|
337 /* Configure the Intr on Falling leve sensitive */ |
|
338 GPIO::SetInterruptTrigger(IRQ_GPIO_NUM, GPIO::ELevelLow); |
|
339 #endif |
|
340 Disable(); // disable int until required |
|
341 } |
|
342 |
|
343 /** |
|
344 * \fn SetupRstHw |
|
345 * \brief set reset line. |
|
346 * |
|
347 * Sets GPIO as output line. Used for controlling the PMEN signal of the WLAN chip. |
|
348 * #define RST_GPIO_NUM 3 |
|
349 * #define RST_MOD_NUM 0 |
|
350 * |
|
351 * of which RST_GPIO_NUM is the GPIO number and |
|
352 * RST_MOD_NUM is the module number where the corresponding |
|
353 * GPIO belongs to. |
|
354 * \note |
|
355 * \param |
|
356 */ |
|
357 void TIWlanHpa::SetupRstHw() |
|
358 { |
|
359 Kern::Printf("SetupRstHw %d", RST_GPIO_NUM); |
|
360 |
|
361 /*--------------------------------------------------------*/ |
|
362 /* common code to init the rst pin */ |
|
363 /*--------------------------------------------------------*/ |
|
364 /* Get control of GPIO driver line */ |
|
365 TInt r = GPIO::SetPinMode(RST_GPIO_NUM, GPIO::EEnabled); |
|
366 if (r != KErrNone) |
|
367 { |
|
368 ERROR_TRACE(("ERROR:cant grab wlan enable pin")) |
|
369 Assert( __FILE__, __LINE__, EFalse ); |
|
370 } |
|
371 |
|
372 GPIO::SetPinDirection(RST_GPIO_NUM, GPIO::EOutput); |
|
373 |
|
374 EnterReset(); |
|
375 } |
|
376 |
|
377 /** |
|
378 * \fn Isr |
|
379 * \brief Interrupt handler function. |
|
380 * |
|
381 * \note |
|
382 * \param aPtr HPA object context. |
|
383 * \param aPinHandle is not used. |
|
384 */ |
|
385 void TIWlanHpa::Isr( TAny* aPtr) |
|
386 { |
|
387 TIWlanHpa* p = static_cast<TIWlanHpa*>( aPtr ); |
|
388 |
|
389 // Ack and Disable the interrupt |
|
390 GPIO::ClearInterrupt(IRQ_GPIO_NUM); |
|
391 GPIO::DisableInterrupt(IRQ_GPIO_NUM); |
|
392 GPIO::DisableWakeup(IRQ_GPIO_NUM); |
|
393 |
|
394 p->Disable(); |
|
395 |
|
396 p->InterruptHandlerStartDfc(); |
|
397 } |
|
398 |
|
399 /** |
|
400 * \fn InterruptHandlerStartDfc |
|
401 * \brief Start the DFC queue |
|
402 * |
|
403 * \note |
|
404 * \param |
|
405 */ |
|
406 |
|
407 void TIWlanHpa::InterruptHandlerStartDfc() |
|
408 { |
|
409 iIrqDfc.Add(); |
|
410 } |
|
411 |
|
412 /** |
|
413 * \fn InterruptHandlerDfc |
|
414 * |
|
415 * DFC - function called by a DFC to handle the interrupt |
|
416 * call another function to get in the correct class and |
|
417 * therefore don't need me-> all the time |
|
418 * Doesn't always work having me-> for the C software |
|
419 * \note |
|
420 * \param |
|
421 */ |
|
422 void TIWlanHpa::InterruptHandlerDfc(TAny* aPtr) |
|
423 { |
|
424 TIWlanHpa* me = (TIWlanHpa*)aPtr; |
|
425 me->InterruptHandler(); |
|
426 } |
|
427 |
|
428 /** |
|
429 * \fn InterruptHandler |
|
430 * \brief Call the actual interrupt handling routine and |
|
431 * |
|
432 * \note |
|
433 * \param |
|
434 */ |
|
435 void TIWlanHpa::InterruptHandler() |
|
436 { |
|
437 OsaExtCb().MutexAcquire(); |
|
438 HpaCb().OnInterrupt(); |
|
439 OsaExtCb().MutexRelease(); |
|
440 } |
|
441 |
|
442 /** |
|
443 * \fn KillInterrupts |
|
444 * \brief Call the actual interrupt handling routine and |
|
445 * |
|
446 * Disables interrupts and |
|
447 * unbinds the interrupt service routine. |
|
448 * |
|
449 * \note |
|
450 * \param |
|
451 */ |
|
452 void TIWlanHpa::KillInterrupts() |
|
453 { |
|
454 GPIO::ClearInterrupt(IRQ_GPIO_NUM); |
|
455 GPIO::DisableInterrupt(IRQ_GPIO_NUM); |
|
456 GPIO::DisableWakeup(IRQ_GPIO_NUM); |
|
457 GPIO::UnbindInterrupt(IRQ_GPIO_NUM); |
|
458 GPIO::SetPinMode(IRQ_GPIO_NUM, GPIO::EDisabled); |
|
459 } |
|
460 |