|
1 /* |
|
2 * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * naviengine_assp\gpio.cpp |
|
16 * NaviEngine implementation of the MHA GPIO class |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 |
|
22 #include <naviengine_priv.h> |
|
23 #include <gpio.h> |
|
24 |
|
25 const TInt32 KHwGpioPinMax = 31; |
|
26 const TInt32 KHwGpioEdgeRising = 0x0; |
|
27 const TInt32 KHwGpioEdgeFalling = 0x1; |
|
28 const TInt32 KHwGpioEdgeBoth = 0x2; |
|
29 const TInt32 KHwGpioLevelLow = 0x3; |
|
30 const TInt32 KHwGpioLevelHigh = 0x4; |
|
31 |
|
32 const TInt32 KGpioDebounceInterval = 1; // (in ticks) |
|
33 const TInt32 KGpioMaxRetries = 8; |
|
34 |
|
35 class GpioPin |
|
36 { |
|
37 public: |
|
38 GPIO::TGpioMode iMode; |
|
39 TGpioIsr iIsr; |
|
40 TAny * iPtr; |
|
41 TInt iDebounce; |
|
42 }; |
|
43 |
|
44 static GpioPin GpioPins[KHwGpioPinMax+1]; |
|
45 static TInt32 GpioInterruptId; |
|
46 #ifdef __SMP__ |
|
47 const TInt32 KGpioLockOrder = TSpinLock::EOrderGenericIrqLow2; |
|
48 static TSpinLock GpioSpinLock(KGpioLockOrder); |
|
49 #endif |
|
50 |
|
51 inline TInt GpioLock(); |
|
52 inline void GpioUnlock(TInt irq); |
|
53 |
|
54 /** |
|
55 Calculate 16-bit device pin Id from 32-bit pin Id. Use DeviceId() to |
|
56 get device Id. |
|
57 @param aId 32-bit pin Id |
|
58 @return 16-bit device specific pin Id |
|
59 */ |
|
60 static inline TUint16 DevicePinId(TInt aId) |
|
61 {return static_cast<TUint16>(aId & 0x0000FFFF);} |
|
62 |
|
63 |
|
64 //Commented out to satisfy compiler(as method is not used in the code) but can |
|
65 //be usefull later |
|
66 /** |
|
67 Calculate and return GPIO device Id(either SOC or one of the extenders) |
|
68 defined in TGpioBaseId from the 32-bit pin Id |
|
69 @param aId 32-bit pin Id |
|
70 @return |
|
71 - EInternalId SOC GPIO |
|
72 - EExtender0-15 GPIO extenders from 0-15 |
|
73 |
|
74 static inline GPIO::TGpioBaseId ExtenderId(TInt aId) |
|
75 {return static_cast<GPIO::TGpioBaseId>((aId & 0xFFFF0000));} |
|
76 */ |
|
77 |
|
78 //Commented out to satisfy compiler(as method is not used in the code) but can |
|
79 //be usefull later |
|
80 /** |
|
81 Generate 32-bit pin Id from the device Id and device specific 16-bit |
|
82 pin Id. |
|
83 @param aExtenderId Device Id is defined in TGpioBaseId |
|
84 @param aPinId 16-bit device pin Id |
|
85 return 32-bit pin Id |
|
86 |
|
87 static inline TInt Id(GPIO::TGpioBaseId aExtenderId, TUint16 aPinId) |
|
88 {return static_cast<TInt>(aExtenderId |aPinId);} |
|
89 */ |
|
90 |
|
91 //Commented out to satisfy compiler(as method is not used in the code) but can |
|
92 //be usefull later |
|
93 /** |
|
94 Find index in extender GPIO device table. |
|
95 @param aExtenderId Extender Id is defined in TGpioBaseId |
|
96 @return singned 32-bit integer index device, possible value |
|
97 from 0 to 15 |
|
98 |
|
99 static TInt DeviceIndex(GPIO::TGpioBaseId aExtenderId) |
|
100 { |
|
101 TUint16 val = (TUint16)((aExtenderId & 0xFFFF0000) >> 16); |
|
102 if(val == 0) return GPIO::EInternalId; |
|
103 |
|
104 //The algorithm steps througth the value until first non-zero bit is |
|
105 //found. |
|
106 // |
|
107 TInt index = 0; |
|
108 if(val & 0xFF00) {index = 8; val = val >> 8;} // 2 x 8-bits |
|
109 if(val & 0x00F0) {index += 4; val = val >> 4;} // 2 x 4-bits |
|
110 if(val & 0x000C) {index += 2; val = val >> 2;} // 2 x 2 bits |
|
111 if(val & 0x0002) {index += 1; val = val >> 1;} // 2 x 1 bits |
|
112 |
|
113 return index; |
|
114 } |
|
115 */ |
|
116 |
|
117 //Commented out to satisfy compiler(as method is not used in the code) but can |
|
118 //be usefull later |
|
119 /** |
|
120 Find index in extender GPIO device table. |
|
121 @param aId 32-bit GPIO pin Id |
|
122 @return singned 32-bit integer index device, possible value |
|
123 from 0 to 15 |
|
124 |
|
125 static TInt DeviceIndex(TInt aId){return DeviceIndex(ExtenderId(aId));} |
|
126 */ |
|
127 |
|
128 |
|
129 |
|
130 /** |
|
131 GPIO interrupt handler |
|
132 Takes a generic argument (TAny*) |
|
133 */ |
|
134 void GpioIsrDispatch(TAny *aPtr) |
|
135 { |
|
136 GpioPin *pins = (GpioPin *)aPtr; |
|
137 TInt irq = GpioLock(); |
|
138 TUint32 interrupt = AsspRegister::Read32(KHwRwGpio_Int); |
|
139 TUint32 enabled = AsspRegister::Read32(KHwRwGpio_Int_Enable); |
|
140 TUint32 masked = interrupt & enabled; |
|
141 for (TInt i = 0; i <= KHwGpioPinMax; i++) |
|
142 { |
|
143 if ((masked & 0x1) && (pins[i].iIsr != NULL)) |
|
144 { |
|
145 (*pins[i].iIsr)(pins[i].iPtr); |
|
146 } |
|
147 masked >>= 1; |
|
148 } |
|
149 Interrupt::Clear(GpioInterruptId); |
|
150 GpioUnlock(irq); |
|
151 } |
|
152 |
|
153 #include "gpio.inl" |
|
154 |
|
155 // |
|
156 // work out debounced state |
|
157 // |
|
158 TInt GetDebouncedState(TInt aId, TUint32 &aVal) |
|
159 { |
|
160 |
|
161 TUint16 pinId = DevicePinId(aId); |
|
162 TInt debounceCount = GpioPins[pinId].iDebounce/KGpioDebounceInterval; |
|
163 TInt count = 0; |
|
164 TInt retries = debounceCount*KGpioMaxRetries; |
|
165 TUint lastState = AsspRegister::Read32(KHwRoGpio_Port_Value); |
|
166 TUint state = lastState; |
|
167 |
|
168 for (count = 0; count < debounceCount && retries > 0; count ++) |
|
169 { |
|
170 NKern::Sleep(KGpioDebounceInterval); |
|
171 state = AsspRegister::Read32(KHwRoGpio_Port_Value); |
|
172 |
|
173 if ((state & 1<<pinId) != (lastState & 1<<pinId)) |
|
174 { |
|
175 // state has changed so reset count and lastState |
|
176 lastState = AsspRegister::Read32(KHwRoGpio_Port_Value); |
|
177 count = 0; |
|
178 retries--; |
|
179 } |
|
180 } |
|
181 |
|
182 if (retries == 0) |
|
183 { |
|
184 // too many retries |
|
185 return KErrTimedOut; |
|
186 } |
|
187 |
|
188 aVal = state; |
|
189 return KErrNone; |
|
190 } |
|
191 |
|
192 EXPORT_C TInt GPIO::SetPinMode |
|
193 ( |
|
194 TInt aId, |
|
195 TGpioMode aMode |
|
196 ) |
|
197 { |
|
198 TUint16 pinId = DevicePinId(aId); |
|
199 // the chip doesn't support modes, so just store it |
|
200 if (pinId > KHwGpioPinMax) |
|
201 { |
|
202 return KErrArgument; |
|
203 } |
|
204 |
|
205 __e32_atomic_store_rel32(&GpioPins[pinId].iMode, aMode); |
|
206 return KErrNone; |
|
207 } |
|
208 |
|
209 EXPORT_C TInt GPIO::GetPinMode |
|
210 ( |
|
211 TInt aId, |
|
212 TGpioMode & aMode |
|
213 ) |
|
214 { |
|
215 TUint16 pinId = DevicePinId(aId); |
|
216 // the chip doesn't support modes, so just return what we stored earlier |
|
217 if (pinId > KHwGpioPinMax) |
|
218 { |
|
219 return KErrArgument; |
|
220 } |
|
221 aMode = (TGpioMode) __e32_atomic_load_acq32(&GpioPins[pinId].iMode); |
|
222 return KErrNone; |
|
223 } |
|
224 |
|
225 EXPORT_C TInt GPIO::SetPinDirection |
|
226 ( |
|
227 TInt aId, |
|
228 TGpioDirection aDirection |
|
229 ) |
|
230 { |
|
231 TUint16 pinId = DevicePinId(aId); |
|
232 // tristate not supported |
|
233 if (pinId > KHwGpioPinMax || aDirection == ETriStated) |
|
234 { |
|
235 return KErrArgument; |
|
236 } |
|
237 // port enabled means output, disabled means input |
|
238 if (aDirection == EInput) |
|
239 { |
|
240 AsspRegister::Write32(KHwWoGpio_Port_Control_Disable, 1<<pinId); |
|
241 } |
|
242 else |
|
243 { |
|
244 AsspRegister::Write32(KHwRwGpio_Port_Control_Enable, 1<<pinId); |
|
245 } |
|
246 return KErrNone; |
|
247 } |
|
248 |
|
249 EXPORT_C TInt GPIO::GetPinDirection |
|
250 ( |
|
251 TInt aId, |
|
252 TGpioDirection & aDirection |
|
253 ) |
|
254 { |
|
255 TUint16 pinId = DevicePinId(aId); |
|
256 if (pinId > KHwGpioPinMax) |
|
257 { |
|
258 return KErrArgument; |
|
259 } |
|
260 // port enabled means output, disabled means input |
|
261 TUint enabled = AsspRegister::Read32(KHwRwGpio_Port_Control_Enable); |
|
262 if (enabled & 1<<pinId) |
|
263 { |
|
264 aDirection = EOutput; |
|
265 } |
|
266 else |
|
267 { |
|
268 aDirection = EInput; |
|
269 } |
|
270 return KErrNone; |
|
271 } |
|
272 |
|
273 EXPORT_C TInt GPIO::SetPinBias |
|
274 ( |
|
275 TInt aId, |
|
276 TGpioBias /*aBias*/ |
|
277 ) |
|
278 { |
|
279 TUint16 pinId = DevicePinId(aId); |
|
280 // pin bias not supported |
|
281 if (pinId > KHwGpioPinMax) |
|
282 { |
|
283 return KErrArgument; |
|
284 } |
|
285 return KErrNotSupported; |
|
286 } |
|
287 |
|
288 EXPORT_C TInt GPIO::GetPinBias |
|
289 ( |
|
290 TInt aId, |
|
291 TGpioBias& /*aBias*/ |
|
292 ) |
|
293 { |
|
294 TUint16 pinId = DevicePinId(aId); |
|
295 // pin bias not supported |
|
296 if (pinId > KHwGpioPinMax) |
|
297 { |
|
298 return KErrArgument; |
|
299 } |
|
300 return KErrNotSupported; |
|
301 } |
|
302 |
|
303 EXPORT_C TInt GPIO::SetPinIdleConfigurationAndState |
|
304 ( |
|
305 TInt aId, |
|
306 TInt /*aConf*/ |
|
307 ) |
|
308 { |
|
309 TUint16 pinId = DevicePinId(aId); |
|
310 // pin idle configuration and state not supported |
|
311 if (pinId > KHwGpioPinMax) |
|
312 { |
|
313 return KErrArgument; |
|
314 } |
|
315 return KErrNotSupported; |
|
316 } |
|
317 |
|
318 EXPORT_C TInt GPIO::GetPinIdleConfigurationAndState |
|
319 ( |
|
320 TInt aId, |
|
321 TInt & /*aBias*/ |
|
322 ) |
|
323 { |
|
324 TUint16 pinId = DevicePinId(aId); |
|
325 // pin idle configuration and state not supported |
|
326 if (pinId > KHwGpioPinMax) |
|
327 { |
|
328 return KErrArgument; |
|
329 } |
|
330 return KErrNotSupported; |
|
331 } |
|
332 |
|
333 EXPORT_C TInt GPIO::BindInterrupt |
|
334 ( |
|
335 TInt aId, |
|
336 TGpioIsr aIsr, |
|
337 TAny * aPtr |
|
338 ) |
|
339 { |
|
340 TUint16 pinId = DevicePinId(aId); |
|
341 if (pinId > KHwGpioPinMax || aIsr == NULL) |
|
342 { |
|
343 return KErrArgument; |
|
344 } |
|
345 TInt irq = GpioLock(); |
|
346 if (GpioPins[pinId].iIsr != NULL) |
|
347 { |
|
348 GpioUnlock(irq); |
|
349 // already bound |
|
350 return KErrInUse; |
|
351 } |
|
352 GpioPins[pinId].iIsr = aIsr; |
|
353 GpioPins[pinId].iPtr = aPtr; |
|
354 GpioUnlock(irq); |
|
355 return KErrNone; |
|
356 } |
|
357 |
|
358 EXPORT_C TInt GPIO::UnbindInterrupt |
|
359 ( |
|
360 TInt aId |
|
361 ) |
|
362 { |
|
363 TUint16 pinId = DevicePinId(aId); |
|
364 if (pinId > KHwGpioPinMax) |
|
365 { |
|
366 return KErrArgument; |
|
367 } |
|
368 TInt irq = GpioLock(); |
|
369 if (GpioPins[pinId].iIsr == NULL) |
|
370 { |
|
371 GpioUnlock(irq); |
|
372 // nothing bound |
|
373 return KErrGeneral; |
|
374 } |
|
375 GpioPins[pinId].iIsr = NULL; |
|
376 GpioPins[pinId].iPtr = NULL; |
|
377 GpioUnlock(irq); |
|
378 return KErrNone; |
|
379 } |
|
380 |
|
381 EXPORT_C TInt GPIO::EnableInterrupt |
|
382 ( |
|
383 TInt aId |
|
384 ) |
|
385 { |
|
386 TUint16 pinId = DevicePinId(aId); |
|
387 if (pinId > KHwGpioPinMax) |
|
388 { |
|
389 return KErrArgument; |
|
390 } |
|
391 TInt irq = GpioLock(); |
|
392 if (GpioPins[pinId].iIsr == NULL) |
|
393 { |
|
394 GpioUnlock(irq); |
|
395 // nothing bound |
|
396 return KErrGeneral; |
|
397 } |
|
398 |
|
399 // hold value so it can be read after triggering |
|
400 TUint32 held = AsspRegister::Read32(KHwRwGpio_Int_Hold); |
|
401 AsspRegister::Write32(KHwRwGpio_Int_Hold, held | 1<<pinId); |
|
402 // enable interrupt |
|
403 AsspRegister::Write32(KHwRwGpio_Int_Enable, 1<<pinId); |
|
404 GpioUnlock(irq); |
|
405 return KErrNone; |
|
406 } |
|
407 |
|
408 EXPORT_C TInt GPIO::DisableInterrupt |
|
409 ( |
|
410 TInt aId |
|
411 ) |
|
412 { |
|
413 TUint16 pinId = DevicePinId(aId); |
|
414 if (pinId > KHwGpioPinMax) |
|
415 { |
|
416 return KErrArgument; |
|
417 } |
|
418 TInt irq = GpioLock(); |
|
419 if (GpioPins[pinId].iIsr == NULL) |
|
420 { |
|
421 GpioUnlock(irq); |
|
422 // nothing bound |
|
423 return KErrGeneral; |
|
424 } |
|
425 // disable interrupt |
|
426 AsspRegister::Write32(KHwWoGpio_Int_Disable, 1<<pinId); |
|
427 // disable hold |
|
428 TUint32 held = AsspRegister::Read32(KHwRwGpio_Int_Hold); |
|
429 AsspRegister::Write32(KHwRwGpio_Int_Hold, held & !(1<<pinId)); |
|
430 GpioUnlock(irq); |
|
431 return KErrNone; |
|
432 } |
|
433 |
|
434 EXPORT_C TInt GPIO::IsInterruptEnabled |
|
435 ( |
|
436 TInt aId, |
|
437 TBool & aEnable |
|
438 ) |
|
439 { |
|
440 TUint16 pinId = DevicePinId(aId); |
|
441 if (pinId > KHwGpioPinMax) |
|
442 { |
|
443 return KErrArgument; |
|
444 } |
|
445 TInt irq = GpioLock(); |
|
446 if (GpioPins[pinId].iIsr == NULL) |
|
447 { |
|
448 GpioUnlock(irq); |
|
449 // nothing bound |
|
450 return KErrGeneral; |
|
451 } |
|
452 aEnable = AsspRegister::Read32(KHwRwGpio_Int_Enable) & (1<<pinId); |
|
453 GpioUnlock(irq); |
|
454 |
|
455 return KErrNone; |
|
456 } |
|
457 |
|
458 EXPORT_C TInt GPIO::ClearInterrupt |
|
459 ( |
|
460 TInt aId |
|
461 ) |
|
462 { |
|
463 TUint16 pinId = DevicePinId(aId); |
|
464 if (pinId > KHwGpioPinMax) |
|
465 { |
|
466 return KErrArgument; |
|
467 } |
|
468 // clear pin interrupt status |
|
469 AsspRegister::Write32(KHwRwGpio_Int, 1<<pinId); |
|
470 return KErrNone; |
|
471 } |
|
472 |
|
473 EXPORT_C TInt GPIO::GetMaskedInterruptState |
|
474 ( |
|
475 TInt aId, |
|
476 TBool & aActive |
|
477 ) |
|
478 { |
|
479 TUint16 pinId = DevicePinId(aId); |
|
480 if (pinId > KHwGpioPinMax) |
|
481 { |
|
482 return KErrArgument; |
|
483 } |
|
484 TInt irq = GpioLock(); |
|
485 aActive = AsspRegister::Read32(KHwRwGpio_Int_Enable) & AsspRegister::Read32(KHwRwGpio_Int) & (1<<pinId); |
|
486 GpioUnlock(irq); |
|
487 return KErrNone; |
|
488 } |
|
489 |
|
490 EXPORT_C TInt GPIO::GetRawInterruptState |
|
491 ( |
|
492 TInt aId, |
|
493 TBool & aActive |
|
494 ) |
|
495 { |
|
496 TUint16 pinId = DevicePinId(aId); |
|
497 if (pinId > KHwGpioPinMax) |
|
498 { |
|
499 return KErrArgument; |
|
500 } |
|
501 aActive = AsspRegister::Read32(KHwRwGpio_Int) & (1<<pinId); |
|
502 return KErrNone; |
|
503 } |
|
504 |
|
505 EXPORT_C TInt GPIO::SetInterruptTrigger |
|
506 ( |
|
507 TInt aId, |
|
508 TGpioDetectionTrigger aTrigger |
|
509 ) |
|
510 { |
|
511 TUint16 pinId = DevicePinId(aId); |
|
512 if (pinId > KHwGpioPinMax) |
|
513 { |
|
514 return KErrArgument; |
|
515 } |
|
516 TUint modeRegister = KHwRwGpio_Int_Mode0 + ((pinId >> 3) << 2); |
|
517 TUint modeShift = pinId & 0x7; |
|
518 TUint mode; |
|
519 switch (aTrigger) |
|
520 { |
|
521 case ELevelLow: |
|
522 mode = KHwGpioLevelLow; |
|
523 break; |
|
524 case ELevelHigh: |
|
525 mode = KHwGpioLevelHigh; |
|
526 break; |
|
527 case EEdgeFalling: |
|
528 mode = KHwGpioEdgeFalling; |
|
529 break; |
|
530 case EEdgeRising: |
|
531 mode = KHwGpioEdgeRising; |
|
532 break; |
|
533 case EEdgeBoth: |
|
534 mode = KHwGpioEdgeBoth; |
|
535 break; |
|
536 default: |
|
537 return KErrArgument; |
|
538 } |
|
539 |
|
540 TInt irq = GpioLock(); |
|
541 TUint currentMode = AsspRegister::Read32(modeRegister) & !(0xf << modeShift); |
|
542 AsspRegister::Write32(modeRegister, (mode << modeShift) | currentMode); |
|
543 GpioUnlock(irq); |
|
544 return KErrNone; |
|
545 } |
|
546 |
|
547 EXPORT_C TInt GPIO::EnableWakeup |
|
548 ( |
|
549 TInt aId |
|
550 ) |
|
551 { |
|
552 TUint16 pinId = DevicePinId(aId); |
|
553 // wakeup not supported |
|
554 if (pinId > KHwGpioPinMax) |
|
555 { |
|
556 return KErrArgument; |
|
557 } |
|
558 return KErrNotSupported; |
|
559 } |
|
560 |
|
561 EXPORT_C TInt GPIO::DisableWakeup |
|
562 ( |
|
563 TInt aId |
|
564 ) |
|
565 { |
|
566 TUint16 pinId = DevicePinId(aId); |
|
567 // wakeup not supported |
|
568 if (pinId > KHwGpioPinMax) |
|
569 { |
|
570 return KErrArgument; |
|
571 } |
|
572 return KErrNotSupported; |
|
573 } |
|
574 |
|
575 EXPORT_C TInt GPIO::IsWakeupEnabled |
|
576 ( |
|
577 TInt aId, |
|
578 TBool & /*aEnable*/ |
|
579 ) |
|
580 { |
|
581 TUint16 pinId = DevicePinId(aId); |
|
582 // wakeup not supported |
|
583 if (pinId > KHwGpioPinMax) |
|
584 { |
|
585 return KErrArgument; |
|
586 } |
|
587 return KErrNotSupported; |
|
588 } |
|
589 |
|
590 EXPORT_C TInt GPIO::SetWakeupTrigger |
|
591 ( |
|
592 TInt aId, |
|
593 TGpioDetectionTrigger /*aTrigger*/ |
|
594 ) |
|
595 { |
|
596 TUint16 pinId = DevicePinId(aId); |
|
597 // wakeup not supported |
|
598 if (pinId > KHwGpioPinMax) |
|
599 { |
|
600 return KErrArgument; |
|
601 } |
|
602 return KErrNotSupported; |
|
603 } |
|
604 |
|
605 EXPORT_C TInt GPIO::SetDebounceTime |
|
606 ( |
|
607 TInt aId, |
|
608 TInt aTime |
|
609 ) |
|
610 { |
|
611 TUint16 pinId = DevicePinId(aId); |
|
612 if (pinId > KHwGpioPinMax) |
|
613 { |
|
614 return KErrArgument; |
|
615 } |
|
616 TInt irq = GpioLock(); |
|
617 GpioPins[pinId].iDebounce = NKern::TimerTicks(aTime/1000); |
|
618 GpioUnlock(irq); |
|
619 return KErrNone; |
|
620 } |
|
621 |
|
622 EXPORT_C TInt GPIO::GetDebounceTime |
|
623 ( |
|
624 TInt aId, |
|
625 TInt & aTime |
|
626 ) |
|
627 { |
|
628 TUint16 pinId = DevicePinId(aId); |
|
629 if (pinId > KHwGpioPinMax) |
|
630 { |
|
631 return KErrArgument; |
|
632 } |
|
633 TInt irq = GpioLock(); |
|
634 aTime = (GpioPins[pinId].iDebounce*1000)/NKern::TimerTicks(1); |
|
635 GpioUnlock(irq); |
|
636 return KErrNone; |
|
637 } |
|
638 |
|
639 EXPORT_C TInt GPIO::GetInputState |
|
640 ( |
|
641 TInt aId, |
|
642 TGpioState & aState |
|
643 ) |
|
644 { |
|
645 TUint16 pinId = DevicePinId(aId); |
|
646 if (pinId > KHwGpioPinMax) |
|
647 { |
|
648 return KErrArgument; |
|
649 } |
|
650 // check it is enabled and is an input port |
|
651 TInt irq = GpioLock(); |
|
652 if (GpioPins[pinId].iMode != EEnabled || (AsspRegister::Read32(KHwRwGpio_Port_Control_Enable) & 1<<pinId)) // reg will have 0 for input 1 for output |
|
653 { |
|
654 GpioUnlock(irq); |
|
655 return KErrGeneral; |
|
656 } |
|
657 GpioUnlock(irq); |
|
658 TUint32 state; |
|
659 if (GpioPins[pinId].iDebounce == 0) |
|
660 { |
|
661 // just read it if we are not debouncing |
|
662 state = AsspRegister::Read32(KHwRoGpio_Port_Value); |
|
663 } |
|
664 else |
|
665 { |
|
666 // work out debounced state |
|
667 TInt err = GetDebouncedState(aId, state); |
|
668 if (err != KErrNone) |
|
669 { |
|
670 return err; |
|
671 } |
|
672 } |
|
673 |
|
674 if (state & (1<<pinId)) |
|
675 { |
|
676 aState = EHigh; |
|
677 } |
|
678 else |
|
679 { |
|
680 aState = ELow; |
|
681 } |
|
682 |
|
683 return KErrNone; |
|
684 } |
|
685 |
|
686 EXPORT_C TInt GPIO::SetOutputState |
|
687 ( |
|
688 TInt aId, |
|
689 TGpioState aState |
|
690 ) |
|
691 { |
|
692 TUint16 pinId = DevicePinId(aId); |
|
693 if (pinId > KHwGpioPinMax) |
|
694 { |
|
695 return KErrArgument; |
|
696 } |
|
697 TInt irq = GpioLock(); |
|
698 if (GpioPins[pinId].iMode != EEnabled) |
|
699 { |
|
700 GpioUnlock(irq); |
|
701 return KErrGeneral; |
|
702 } |
|
703 TUint outputReg, value; |
|
704 if (pinId >= 16) |
|
705 { |
|
706 outputReg = KHwWoGpio_Port_Set_Clear_Hi; |
|
707 pinId = pinId - 16; |
|
708 } |
|
709 else |
|
710 { |
|
711 outputReg = KHwWoGpio_Port_Set_Clear_Lo; |
|
712 } |
|
713 if (aState == EHigh) |
|
714 { |
|
715 value = 1 << pinId; // LSW - set.. |
|
716 } |
|
717 else |
|
718 { |
|
719 value = 1 << (pinId + 16); // MSW - clear.. |
|
720 } |
|
721 |
|
722 AsspRegister::Write32(outputReg, value); |
|
723 GpioUnlock(irq); |
|
724 return KErrNone; |
|
725 } |
|
726 |
|
727 EXPORT_C TInt GPIO::GetOutputState |
|
728 ( |
|
729 TInt aId, |
|
730 TGpioState & aState |
|
731 ) |
|
732 { |
|
733 TUint16 pinId = DevicePinId(aId); |
|
734 if (pinId > KHwGpioPinMax) |
|
735 { |
|
736 return KErrArgument; |
|
737 } |
|
738 // atomic - no lock required |
|
739 TUint32 state = AsspRegister::Read32(KHwRoGpio_Port_Value); |
|
740 if(state & (1<<pinId)) |
|
741 { |
|
742 aState = EHigh; |
|
743 } |
|
744 else |
|
745 { |
|
746 aState = ELow; |
|
747 } |
|
748 return KErrNone; |
|
749 } |
|
750 |
|
751 EXPORT_C TInt GPIO::GetInputState |
|
752 ( |
|
753 TInt aId, |
|
754 TGpioCallback * /*aCb*/ |
|
755 ) |
|
756 { |
|
757 TUint16 pinId = DevicePinId(aId); |
|
758 // asynch calls not supported |
|
759 if (pinId > KHwGpioPinMax) |
|
760 { |
|
761 return KErrArgument; |
|
762 } |
|
763 return KErrNotSupported; |
|
764 } |
|
765 |
|
766 EXPORT_C TInt GPIO::SetOutputState |
|
767 ( |
|
768 TInt aId, |
|
769 TGpioState /*aState*/, |
|
770 TGpioCallback * /*aCb*/ |
|
771 ) |
|
772 { |
|
773 TUint16 pinId = DevicePinId(aId); |
|
774 // asynch calls not supported |
|
775 if (pinId > KHwGpioPinMax) |
|
776 { |
|
777 return KErrArgument; |
|
778 } |
|
779 return KErrNotSupported; |
|
780 } |
|
781 |
|
782 #ifndef __USE_GPIO_STATIC_EXTENSION__ |
|
783 EXPORT_C TInt GPIO::StaticExtension |
|
784 ( |
|
785 TInt aId, |
|
786 TInt /*aCmd*/, |
|
787 TAny * /*aArg1*/, |
|
788 TAny * /*aArg2*/ |
|
789 ) |
|
790 { |
|
791 TUint16 pinId = DevicePinId(aId); |
|
792 // static extensions not supported |
|
793 if (pinId > KHwGpioPinMax) |
|
794 { |
|
795 return KErrArgument; |
|
796 } |
|
797 return KErrNotSupported; |
|
798 } |
|
799 #endif |
|
800 |
|
801 DECLARE_STANDARD_EXTENSION() |
|
802 { |
|
803 TInt irq = GpioLock(); |
|
804 // initialise GPIO pins array |
|
805 for (TInt32 i = 0; i <= KHwGpioPinMax; i++) |
|
806 { |
|
807 GpioPins[i].iMode = GPIO::EIdle; |
|
808 GpioPins[i].iIsr = NULL; |
|
809 GpioPins[i].iPtr = NULL; |
|
810 GpioPins[i].iDebounce = 0; |
|
811 } |
|
812 GpioUnlock(irq); |
|
813 TInt r = Interrupt::Bind(KIntIdGpio, GpioIsrDispatch, &GpioPins[0]); |
|
814 if (r < 0) |
|
815 { |
|
816 return r; |
|
817 } |
|
818 GpioInterruptId = r; |
|
819 Interrupt::Clear(GpioInterruptId); |
|
820 Interrupt::Enable(GpioInterruptId); |
|
821 return KErrNone; |
|
822 } |