navienginebsp/naviengine_assp/gpio.cpp
changeset 0 5de814552237
equal deleted inserted replaced
-1:000000000000 0:5de814552237
       
     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 	}