Update SPI master pin handling: added dynamic pin configuration for McSPI3 (needed if want to use multiple device on this interface. Now following number of Slave devices is available: McSPI1: 4, McSPI2: 2, McSPI3: 6 (2 per each pin configuration), McSPI4: 1. Only McSPI3 and McSPI4 are available now -there are issues with McSPI1 & 2 due to register access (something wrong with mapping? There is Fault Category: Exception Fault Reason: 10000000 Beagle_BSP_dev
authorLukasz Forynski <lukasz.forynski@gmail.com>
Tue, 28 Sep 2010 02:37:35 +0100
branchBeagle_BSP_dev
changeset 84 09e266454dcf
parent 83 bcf33365fd8d
child 85 d93b485c1325
Update SPI master pin handling: added dynamic pin configuration for McSPI3 (needed if want to use multiple device on this interface. Now following number of Slave devices is available: McSPI1: 4, McSPI2: 2, McSPI3: 6 (2 per each pin configuration), McSPI4: 1. Only McSPI3 and McSPI4 are available now -there are issues with McSPI1 & 2 due to register access (something wrong with mapping? There is Fault Category: Exception Fault Reason: 10000000
omap3530/beagleboard/bootstrap/beagle.s
omap3530/beagleboard/src/variant.cpp
omap3530/omap3530_drivers/spi/bld.inf
omap3530/omap3530_drivers/spi/master.cpp
omap3530/omap3530_drivers/spi/master.h
omap3530/omap3530_drivers/spi/omap3530_spi.h
omap3530/omap3530_drivers/spi/omap3530_spi.inl
omap3530/omap3530_drivers/spi/psl_init.cpp
omap3530/omap3530_drivers/spi/psl_init.h
omap3530/omap3530_drivers/spi/spi.mmp
omap3530/omap3530_drivers/spi/test/d_spi_client_m.cpp
omap3530/shared/serialkeyb/serialkeyboard.cpp
--- a/omap3530/beagleboard/bootstrap/beagle.s	Wed Sep 22 23:37:20 2010 +0100
+++ b/omap3530/beagleboard/bootstrap/beagle.s	Tue Sep 28 02:37:35 2010 +0100
@@ -25,7 +25,7 @@
 ;
 ; Platform specific constant definitions
 
-DRamBankBase		EQU		0x80000000 ; 256M of DRAM 
+DRamBankBase		EQU		0x80000000 ; 256M of DRAM
 DRamBankMaxSize		EQU		0x10000000
 
 ; HW used by bootstrap
@@ -415,7 +415,7 @@
 	IF  :DEF: CFG_CPU_ARM1136 :LAND: (:LNOT: :DEF: CFG_CPU_ARM1136_ERRATUM_364296_FIXED)
         DCD     BPR_FinalMMUCRSet,      ExtraMMUCR + MMUCR_FI
         DCD     BPR_AuxCRSet,           DefaultAuxCRSet + 0x80000000
-	ENDIF		
+	ENDIF
 		DCD		-1								; terminator
 
 
@@ -577,7 +577,7 @@
 		MOV     r2, #KUART16XMode
 		STR     r2, [r1, #KHwUartMdr1]
 
-    
+
 		MOV     r1, #0x19000                    ; Set up delay loop to allow line to settle
 		SUBS	r1, r1, #1
 		SUBNE	pc, pc, #12
@@ -637,7 +637,7 @@
 		DCD	ReservePhysicalMemory			; reserve physical RAM if required
 		DCD	GetParameters				; get platform dependent parameters
 		DCD	FinalInitialise				; Final initialisation before booting the kernel
-		DCD HandleAllocRequest				; allocate memory		
+		DCD HandleAllocRequest				; allocate memory
 		DCD	GetPdeValue				; usually in generic code
 		DCD	GetPteValue				; usually in generic code
 		DCD	PageTableUpdate				; usually in generic code
--- a/omap3530/beagleboard/src/variant.cpp	Wed Sep 22 23:37:20 2010 +0100
+++ b/omap3530/beagleboard/src/variant.cpp	Tue Sep 28 02:37:35 2010 +0100
@@ -37,16 +37,16 @@
 //These constants define Custom Restart Reasons in SuperPage::iHwStartupReason
 const TUint KHtCustomRestartMax	  = 0xff;
 const TUint KHtCustomRestartShift = 8;
-const TUint KHtCustomRestartMask  = KHtCustomRestartMax << KHtCustomRestartShift; 
+const TUint KHtCustomRestartMask  = KHtCustomRestartMax << KHtCustomRestartShift;
 
 //TODO: unncomment when referenced
-const TUint KHtRestartStartupModesMax = 0xf; // Variable, platform dependant 
-//const TUint KHtRestartStartupModesShift = 16; // Variable, platform dependant 
+const TUint KHtRestartStartupModesMax = 0xf; // Variable, platform dependant
+//const TUint KHtRestartStartupModesShift = 16; // Variable, platform dependant
 //const TUint KHtRestartStartupModesMask = KHtRestartStartupModesMax << KHtRestartStartupModesShift;
 
 void BeagleVariantFault(TInt aLine)
 	{
-	Kern::Fault("BeagleVariant",aLine);	
+	Kern::Fault("BeagleVariant",aLine);
 	}
 
 #define V_FAULT()	BeagleVariantFault(__LINE__)
@@ -78,15 +78,15 @@
 //
 // Specify the RAM zone configuration.
 //
-// The lowest addressed zone must have the highest preference as the bootstrap 
+// The lowest addressed zone must have the highest preference as the bootstrap
 // will always allocate from the lowest address up.  Once the kernel has initialised
 // then the zone preferences will decide from which RAM zone memory is allocated.
 //
 // 	const TUint KVariantRamZoneCount = ?;
-//	static const SRamZone KRamZoneConfig[KVariantRamZoneCount+1] = 
+//	static const SRamZone KRamZoneConfig[KVariantRamZoneCount+1] =
 //				 			iBase      iSize   		iID	iPref	iFlags
 //				{
-//				__SRAM_ZONE(0x????????, 0x???????, 	?,	?, 		?), 
+//				__SRAM_ZONE(0x????????, 0x???????, 	?,	?, 		?),
 //				...
 //				__SRAM_ZONE(0x????????, 0x???????, 	?, 	?, 		?),
 //				__SRAM_ZONE_END, // end of zone list
@@ -117,10 +117,10 @@
 	//	ERamZoneOp_PowerUp:		A RAM zone changing from used to empty.
 	//	ERamZoneOp_PowerDown:	A RAM zone changing from empty to used.
 	//
- 
+
 	switch (aOp)
 		{
-		case ERamZoneOp_Init:	
+		case ERamZoneOp_Init:
 			break;
 		case ERamZoneOp_PowerUp:
 			break;
@@ -158,13 +158,13 @@
 EXPORT_C TInt Variant::GetMsTickPeriod()
 	{
 	return TheVariant.MsTickPeriod();
-	
+
 	}
 
 void Beagle::Init3()
 	{
 	__KTRACE_OPT(KBOOT,Kern::Printf("Beagle::Init3()"));
-	
+
 	Omap3530Assp::Init3();
 
 	Variant::Init3();
@@ -197,13 +197,13 @@
 		if( portNumber >= 0 )
 			{
 			Omap3530Uart::TUart uart( portNumber );
-		
+
 			uart.Init();
 			uart.DefineMode( Omap3530Uart::TUart::EUart );
 			uart.SetBaud( Omap3530Uart::TUart::E115200 );
 			uart.SetDataFormat( Omap3530Uart::TUart::E8Data, Omap3530Uart::TUart::E1Stop, Omap3530Uart::TUart::ENone );
 			uart.Enable();
-			
+
 			TheVariant.iDebugInitialised=ETrue;
 			}
 		}
@@ -245,14 +245,14 @@
 	//
 	// TO DO: (optional)
 	//
-	// Idle Tick supression: 
+	// Idle Tick supression:
 	// 1- obtain the number of idle Ticks before the next NTimer expiration (NTimerQ::IdleTime())
 	// 2- if the number of Ticks is large enough (criteria to be defined) reset the Hardware Timer
 	//    to only interrupt again when the corresponding time has expired.
-	//   2.1- the calculation of the new value to program the Hardware Timer with should take in 
+	//   2.1- the calculation of the new value to program the Hardware Timer with should take in
 	//		  consideration the rounding value (NTimerQ::iRounding)
 	//  3- call the low level Sleep function (e'g. Bootstrap: address in iIdleFunction)
-	//  4- on coming back from Idle need to read the Hardware Timer and determine if woken up due to 
+	//  4- on coming back from Idle need to read the Hardware Timer and determine if woken up due to
 	//     timer expiration (system time for new match<=current system time<system time for new match-tick period)
 	//     or some other Interrupt.
 	//	 4.1- if timer expiration, adjust System Time by adding the number of Ticks suppressed to NTimerQ::iMsCount
@@ -260,8 +260,8 @@
 	//		  above
 	//
 	// Support for different Sleep Modes:
-	// Often the Sleep mode a platform can go to depends on how many resources such as clocks/voltages can be 
-	// turned Off or lowered to a suitable level. If different Sleep modes are supported this code may need 
+	// Often the Sleep mode a platform can go to depends on how many resources such as clocks/voltages can be
+	// turned Off or lowered to a suitable level. If different Sleep modes are supported this code may need
 	// to be able to find out what power resources are On or Off or used to what level. This could be achieved by
 	// enquiring the Resource Manager (see \beagle_variant\inc\beagle_power.h).
 	// Then a decision could be made to what Sleep level we go to.
@@ -269,7 +269,7 @@
 	// Example calls:
 	// Obtain the number of Idle Ticks before the next NTimer expiration
 	// TInt aTicksLeft = NTimerQ::IdleTime();
-	// ... 
+	// ...
 	// Find out the deepest Sleep mode available for current resource usage and sleeping time
 	// TemplateResourceManager* aManager = TTemplatePowerController::ResourceManager();
 	// TemplateResourceManager::TSleepModes aMode = aManager -> MapSleepMode(aTicksLeft*MsTickPeriod());
@@ -368,24 +368,47 @@
 			}
 		case EVariantHalLedMaskSet:
 			{
-			//
-			// TO DO: (optional)
-			//
 			// Set the state of any on-board LEDs, e.g:
-			// TUint32 aLedMask=(TUint32)a1;
-			// Variant::ModifyLedState(~aLedMask,aLedMask);
-			//
+			TUint aLedMask=(TUint)a1;
+			GPIO::TGpioState led_state;
+			if(aLedMask & 1)
+				led_state = GPIO::EHigh;
+			else
+				led_state = GPIO::ELow;
+
+			r = GPIO::SetOutputState(KGPIO_LED0, led_state);
+
+			if(r == KErrNone)
+				{
+				if(aLedMask & 2)
+					led_state = GPIO::EHigh;
+				else
+					led_state = GPIO::ELow;
+
+				r = GPIO::SetOutputState(KGPIO_LED1, led_state);
+				}
 			break;
 			}
 		case EVariantHalLedMaskGet:
 			{
-			//
-			// TO DO: (optional)
-			//
-			// Read the state of any on-board LEDs, e.g:
-			// TUint32 x = Variant::LedState();
-			// kumemput32(a1, &x, sizeof(x));
-			//
+			// Read the state of on-board LEDs
+			GPIO::TGpioState led_state;
+			TUint x = 0;
+			r = GPIO::GetOutputState(KGPIO_LED0, led_state);
+			if(r == KErrNone)
+				{
+				if(led_state == GPIO::EHigh)
+					x = 1;
+
+				r = GPIO::GetOutputState(KGPIO_LED1, led_state);
+				if(r == KErrNone)
+					{
+					if(led_state == GPIO::EHigh)
+						x |= 1 << 1;
+
+					kumemput32(a1, &x, sizeof(x));
+					}
+				}
 			break;
 			}
 
@@ -445,7 +468,7 @@
 			// Read the restart startup mode, e.g:
 			// TInt startup = (Kern::SuperPage().iHwStartupReason & KHtRestartStartupModesMask) >> KHtRestartStartupModesShift;
 			// kumemput32(a1, &startup, sizeof(TInt));
-			break; 			
+			break;
 			}
 
 		case EVariantHalGetMaximumCustomRestartReasons:
@@ -468,7 +491,7 @@
 			// kumemput32(a1, &KHtRestartStartupModesMax, sizeof(TUint));
 			break;
 			}
-		
+
 
 		default:
 			r=KErrNotSupported;
@@ -662,8 +685,8 @@
 	aDay=0;
 	aMonth=0;
 	TInt adjyear = aTime % KSecsDaysPer4Years;
-	
-	
+
+
 	if (adjyear<KSecsPerYr + KSecsPerDay)
 		{
 		GetMonthData(adjyear/KSecsPerDay, ETrue, aMonth, aDay);
@@ -679,7 +702,7 @@
 
 TInt  Beagle::SystemTimeInSecondsFrom2000(TInt& aTime)
 	{
-	
+
 	if(!TPS65950::Initialized())
 		{
 		return KErrNotSupported;
@@ -687,7 +710,7 @@
 
 	TPS65950::TRtcTime  time;
 	TPS65950::GetRtcData( time );
-		 
+
 	aTime = time.iSecond;
 	aTime += time.iMinute * KSecsPerMin;
 	aTime += time.iHour * KSecsPerHour;
@@ -708,9 +731,9 @@
 		{
 		aTime += mTab[isLeap][i] * KSecsPerDay;
 		}
-	
+
 	aTime += (yrs/4) * KSecsDaysPer4Years;
-	
+
 	if ( isLeap )
 		{
 		// Add KSecsPerDay, because first year is always a leap year
@@ -725,8 +748,8 @@
 		{
 		return KErrNotSupported;
 		}
-		
-	TPS65950::TRtcTime  rtc;	
+
+	TPS65950::TRtcTime  rtc;
 	TInt secs = aTime % KSecsPerMin;
 	TInt mins_insecs = (aTime % KSecsPerHour) - secs;
 	TInt hours_insecs = (aTime % KSecsPerDay) - mins_insecs - secs;
@@ -736,7 +759,7 @@
 	rtc.iHour = hours_insecs/KSecsPerHour;
 
 	SecondsToYMD( aTime, rtc.iYear, rtc.iMonth, rtc.iDay);
-	
+
 	TPS65950::SetRtcData( rtc );
 
 	return KErrNone;
--- a/omap3530/omap3530_drivers/spi/bld.inf	Wed Sep 22 23:37:20 2010 +0100
+++ b/omap3530/omap3530_drivers/spi/bld.inf	Tue Sep 28 02:37:35 2010 +0100
@@ -18,7 +18,8 @@
 ARMV5
 
 PRJ_EXPORTS
-spi.iby  rom/omap3530/
+spi.iby         rom/omap3530/
+
 
 PRJ_MMPFILES
 spi
--- a/omap3530/omap3530_drivers/spi/master.cpp	Wed Sep 22 23:37:20 2010 +0100
+++ b/omap3530/omap3530_drivers/spi/master.cpp	Tue Sep 28 02:37:35 2010 +0100
@@ -47,18 +47,17 @@
 	iTransferEndDfc(TransferEndDfc, this, KIicPslDfcPriority)
 	{
 	iChannelNumber = aChannelNumber;
-	iIrqId = KMcSpiIrqId[iChannelNumber];
+	iIrqId  = KMcSpiIrqId[iChannelNumber];
 	iHwBase = KMcSpiRegBase[iChannelNumber];
-	iState = EIdle;
-	iCurrSS = -1;
+	iState  = EIdle;
+	iCurrSS = -1; // make sure channel will be fully configured on the first use
 	DBGPRINT(Kern::Printf("DSpiMasterBeagle::DSpiMasterBeagle: at 0x%x, iChannelNumber = %d", this, iChannelNumber));
 	}
 
 TInt DSpiMasterBeagle::DoCreate()
 	{
-	DBGPRINT(Kern::Printf("\nDSpiMasterBeagle::DoCreate() ch: %d \n", iChannelNumber));
+	DBGPRINT(Kern::Printf("\nDSpiMasterBeagle::DoCreate() McSPI%d \n", iChannelNumber+1));
 	DBGPRINT(Kern::Printf("HW revision is %x", AsspRegister::Read32(iHwBase + MCSPI_REVISION)));
-
 	TInt r = KErrNone;
 
 	// Create the DFCQ to be used by the channel
@@ -99,8 +98,8 @@
 	Prcm::SetClockState( Prcm::EClkMcSpi3_I, Prcm::EClkOn );
 	// TODO:consider auto-idle for PRCM.CM_AUTOIDLE1_CORE
 
+	// setup default spi pins. For channel 2 (McSPI3) it can be configured dynamically
 	SetupSpiPins(iChannelNumber);
-	// end of system wide settings..
 
 	return r;
 	}
@@ -148,44 +147,50 @@
 	iCurrTransaction = aTransaction;
 
 	// Configure the hardware to support the transaction
-	TInt r = KErrNone;
-	if(TransConfigDiffersFromPrev())
+	TInt r = PrepareConfiguration();
+	if(r == KErrNone)
 		{
 		r = ConfigureInterface();
-		if(r != KErrNone)
+		if(r == KErrNone)
 			{
-			return r;
+			// start processing transfers of this transaction.
+			r = ProcessNextTransfers();
 			}
 		}
-
-	// start processing transfers of this transaction.
-	r = ProcessNextTransfers();
 	return r;
 	}
 
-TBool DSpiMasterBeagle::TransConfigDiffersFromPrev()
+TInt DSpiMasterBeagle::PrepareConfiguration()
 	{
 	TConfigSpiV01 &newHeader = (*(TConfigSpiBufV01*) (GetTransactionHeader(iCurrTransaction)))();
 
 	// get the slave address (i.e. known as a 'channel' for the current SPI module)
-	TInt slaveAddr = GET_SLAVE_ADDR(iCurrTransaction->GetBusId());
-	DBGPRINT(Kern::Printf("slaveAddr %x", slaveAddr));
+	TInt busId       = iCurrTransaction->GetBusId();
+	TInt slaveAddr   = GET_SLAVE_ADDR(busId);
+	TInt slavePinSet = 0;
+
+	if(slaveAddr >= KMcSpiNumSupportedSlaves[iChannelNumber]) // address is 0-based
+		{
+		DBG_ERR(Kern::Printf("Slave address for McSPI%d should be < %, was: %d !",
+				iChannelNumber + 1, KMcSpiNumSupportedSlaves[iChannelNumber], slaveAddr));
+		return KErrArgument; // Slave address out of range
+		}
 
-	// compare it to the previous configuration..
-	if(slaveAddr                        != iCurrSS ||
-	   newHeader.iWordWidth             != iCurrHeader.iWordWidth ||
-	   newHeader.iClkSpeedHz            != iCurrHeader.iClkSpeedHz ||
-	   newHeader.iClkMode               != iCurrHeader.iClkMode ||
-	   newHeader.iTimeoutPeriod         != iCurrHeader.iTimeoutPeriod ||
-	   newHeader.iBitOrder              != iCurrHeader.iBitOrder ||
-	   newHeader.iTransactionWaitCycles != iCurrHeader.iTransactionWaitCycles ||
-	   newHeader.iSSPinActiveMode       != iCurrHeader.iSSPinActiveMode)
+	// Slave addresses > 1 for McSPI3 (iChannel2) really means alternative pin settings,
+	// so adjust it in such case. *Pin set indexes are +1 to skip over the pin set for McSPI4
+	// channel in the pin configuration table.
+	if(iChannelNumber == 2 && slaveAddr > 1)
 		{
-		iCurrSS = slaveAddr;
-		iCurrHeader = newHeader; //copy the header..
-		return ETrue;
+		slavePinSet  =  slaveAddr > 3 ?  3 : 2; // slaveAddr: 2-3: pin set 2(1*); 4-5: pin set 3(2*)
+		slaveAddr &= 1; // modulo 2 (i.e. 2 CS for McSPI3)
 		}
-	return EFalse;
+
+	// store configuration parameters
+	iCurrSS          = slaveAddr;
+	iCurrSlavePinSet = slavePinSet;
+	iCurrHeader      = newHeader; //copy the header..
+
+	return KErrNone;
 	}
 
 // Init the hardware with the data provided in the transaction and slave-address field
@@ -194,6 +199,12 @@
 	{
 	DBGPRINT(Kern::Printf("ConfigureInterface()"));
 
+	// make sure pins are set up properly (only for McSPI3)
+	if(iCurrSlavePinSet == 2)
+		{
+		SetupSpiPins(iChannelNumber, iCurrSlavePinSet);
+		}
+
 	// soft reset the SPI..
 	TUint val = AsspRegister::Read32(iHwBase + MCSPI_SYSCONFIG);
 	val = MCSPI_SYSCONFIG_SOFTRESET;  // issue reset
@@ -204,9 +215,14 @@
 	while (!(val & MCSPI_SYSSTATUS_RESETDONE))
 		val = AsspRegister::Read32(iHwBase + MCSPI_SYSSTATUS);
 
-	//AsspRegister::Write32(iHwBase + MCSPI_SYSCONFIG, MCSPI_SYSCONFIG_CLOCKACTIVITY_ALL_ON);
-
-	AsspRegister::Write32(iHwBase + MCSPI_IRQSTATUS, ~0); // clear all interrupts (for now) -- normally only for channel..
+	// disable and clear all interrupts..
+	AsspRegister::Write32(iHwBase + MCSPI_IRQENABLE, 0);
+	AsspRegister::Write32(iHwBase + MCSPI_IRQSTATUS,
+	                      MCSPI_IRQ_RX_FULL(iCurrSS) |
+	                      MCSPI_IRQ_RX_FULL(iCurrSS) |
+	                      MCSPI_IRQ_TX_UNDERFLOW(iCurrSS) |
+	                      MCSPI_IRQ_TX_EMPTY(iCurrSS) |
+	                      MCSPI_IRQ_RX_OVERFLOW);
 
 	// channel configuration
 	//	Set the SPI1.MCSPI_CHxCONF[18] IS bit to 0 for the spi1_somi pin in receive mode.
@@ -259,24 +275,19 @@
 	// update the register..
 	AsspRegister::Write32(iHwBase + MCSPI_CHxCONF(iCurrSS), val);
 
-	// CS (SS) pin direction..
+	// set spim_somi pin direction to input
 	val = MCSPI_SYST_SPIDATDIR0;
 
-	// drive csx pin high or low
-//	val |= (iCurrHeader.iSSPinActiveMode == ESpiCSPinActiveLow)? 1 << iCurrSS : 0;
-//	AsspRegister::Modify32(iHwBase + MCSPI_SYST, val);
-
+	// drive csx pin to inactive state
 	if(iCurrHeader.iSSPinActiveMode == ESpiCSPinActiveLow)
 		{
-		AsspRegister::Modify32(iHwBase + MCSPI_SYST, 1u << iCurrSS, MCSPI_SYST_SPIDATDIR0);
+		AsspRegister::Modify32(iHwBase + MCSPI_SYST, 1u << iCurrSS, 0);
 		}
 	else
 		{
-		AsspRegister::Modify32(iHwBase + MCSPI_SYST, 0, (1u << iCurrSS) | MCSPI_SYST_SPIDATDIR0);
+		AsspRegister::Modify32(iHwBase + MCSPI_SYST, 0, (1u << iCurrSS));
 		}
 
-
-
 	// Set the MS bit to 0 to provide the clock (ie. to setup as master)
 #ifndef SINGLE_MODE
 	AsspRegister::Write32(iHwBase + MCSPI_MODULCTRL, MCSPI_MODULCTRL_MS_MASTER);
@@ -477,7 +488,7 @@
 			AsspRegister::Modify32(iHwBase + MCSPI_CHxCONF(iCurrSS), 0, MCSPI_CHxCONF_FORCE);
 
 			// change the pad config - now the SPI drives the line appropriately..
-			SetCsActive(iChannelNumber, iCurrSS);
+			SetCsActive(iChannelNumber, iCurrSS, iCurrSlavePinSet);
 #endif /*SINGLE_MODE*/
 
 #ifdef USE_TX_FIFO
@@ -538,7 +549,7 @@
 				AsspRegister::Modify32(iHwBase + MCSPI_CHxCONF(iCurrSS), 0, MCSPI_CHxCONF_FORCE);
 
 				// change the pad config - now the SPI drives the line appropriately..
-				SetCsActive(iChannelNumber, iCurrSS);
+				SetCsActive(iChannelNumber, iCurrSS, iCurrSlavePinSet);
 #endif /*SINGLE_MODE*/
 				}
 			else
@@ -761,28 +772,12 @@
 		               Kern::Fault("SPI master: exiting not having received all?", 12));
 		}
 
-	// make sure the CS pin is asserted..
-	if(a->iCurrHeader.iSSPinActiveMode == ESpiCSPinActiveLow)
-		{
-		AsspRegister::Modify32(a->iHwBase + MCSPI_SYST, 0, 1 << a->iCurrSS);
-		}
-	else
-		{
-		AsspRegister::Modify32(a->iHwBase + MCSPI_SYST, 1 << a->iCurrSS, 0);
-		}
-
 #ifdef SINGLE_MODE
 	// manually de-assert CS line for this channel
 	AsspRegister::Modify32(a->iHwBase + MCSPI_CHxCONF(a->iCurrSS), MCSPI_CHxCONF_FORCE, 0);
 
-	// drive csx pin high or low. Doing this here causes, that CS lines are toggled for each transfers.
-	TUint val = (a->iCurrHeader.iSSPinActiveMode == ESpiCSPinActiveLow)? 1 << a->iCurrSS : 0;
-	if (val)
-		{
-		AsspRegister::Modify32(a->iHwBase + MCSPI_SYST, 0, val);
-		}
 	// put the CS signal to 'inactive' state (as on channel disable it would have a glitch)
-	SetCsInactive(a->iChannelNumber, a->iCurrSS, a->iCurrHeader.iSSPinActiveMode);
+	SetCsInactive(a->iChannelNumber, a->iCurrSS, a->iCurrHeader.iSSPinActiveMode, a->iCurrSlavePinSet);
 
 #endif
 
@@ -807,15 +802,19 @@
 	DBGPRINT(Kern::Printf("DSpiMasterBeagle::ExitComplete, aErr %d, aComplete %d", aErr, aComplete));
 
 	// make sure CS is in inactive state (for the current / last transaction) on error
-	if(!aComplete)
+	// TODO: add extendable transaction support (..i.e. with no de-assertion of CS pin between such transactions)
+	SetCsInactive(iChannelNumber, iCurrSS, iCurrHeader.iSSPinActiveMode, iCurrSlavePinSet);
+
+	// disable this channel
+	AsspRegister::Modify32(iHwBase + MCSPI_CHxCTRL(iCurrSS), MCSPI_CHxCTRL_EN, 0);
+
+	// in the case of error - make sure to reset the channel
+	if(aErr != KErrNone)
 		{
-		SetCsInactive(iChannelNumber, iCurrSS, iCurrHeader.iSSPinActiveMode);
+		AsspRegister::Write32(iHwBase + MCSPI_SYSCONFIG, MCSPI_SYSCONFIG_SOFTRESET);
+		iCurrSS = -1; // make sure the interface will be re-configured at next transaction
 		}
 
-	// disable this channel (and reset..)
-	AsspRegister::Modify32(iHwBase + MCSPI_CHxCTRL(iCurrSS), MCSPI_CHxCTRL_EN, 0);
-	AsspRegister::Write32(iHwBase + MCSPI_SYSCONFIG, MCSPI_SYSCONFIG_SOFTRESET);
-
 	// Disable interrupts for the channel
 	Interrupt::Disable(iIrqId);
 
--- a/omap3530/omap3530_drivers/spi/master.h	Wed Sep 22 23:37:20 2010 +0100
+++ b/omap3530/omap3530_drivers/spi/master.h	Tue Sep 28 02:37:35 2010 +0100
@@ -41,8 +41,8 @@
 	virtual TInt HandleSlaveTimeout();
 
 	// Internal methods
+	TInt PrepareConfiguration();
 	TInt ConfigureInterface();
-	TBool TransConfigDiffersFromPrev();
 	TInt ProcessNextTransfers();
 	TInt StartTransfer(TIicBusTransfer* aTransferPtr, TUint8 aType);
 	TInt DoTransfer(TUint8 aType);
@@ -88,6 +88,7 @@
 
 	TConfigSpiV01 iCurrHeader;
 	TInt iCurrSS;
+	TInt iCurrSlavePinSet;
 	};
 
 #endif //__OMAP3530_SPI_MASTER_H__
--- a/omap3530/omap3530_drivers/spi/omap3530_spi.h	Wed Sep 22 23:37:20 2010 +0100
+++ b/omap3530/omap3530_drivers/spi/omap3530_spi.h	Tue Sep 28 02:37:35 2010 +0100
@@ -23,12 +23,10 @@
 #include <assp/omap3530_assp/omap3530_scm.h>
 #include <assp/omap3530_assp/omap3530_gpio.h>
 
-
 #define BIT_MASK(shift,len)       (((1u << (len)) - 1) << (shift))
 #define GET_BITS(w,shift,len)     (((w) >> (shift)) & ((1 << (len)) - 1))
 #define SET_BITS(w,set,shift,len) ((w) &= ~BIT_MASK(shift, len), (w) |= ((set) << (shift)))
 
-
 // Device Instance Summary
 const TUint MCSPI1_phys = 0x48098000; // 4Kbytes
 const TUint MCSPI2_phys = 0x4809A000; // 4Kbytes
@@ -49,7 +47,6 @@
 	Omap3530HwBase::TVirtual<MCSPI4_phys>::Value  //McSPI module 4
 	};
 
-
 //.. and IRQ lines for SPI channels
 const TUint KMcSpiIrqId[] =
 	{
@@ -59,15 +56,17 @@
 	EOmap3530_IRQ48_SPI4_IRQ  //McSPI module 4
 	};
 
-// available channels per module (i.e. number of 'slave select'  inputs/outpus per module)
-const TUint KMcSpiNumChannels[] =
+// available channels per module i.e. number of 'slave select'  inputs/outpus signals / addresses
+// per module.
+const TUint KMcSpiNumSupportedSlaves[] =
 	{
-	4, // channels 0 - 3
-	2, // channels 0 - 1
-	2, // channels 0 - 1
-	1  // channel 0  only
+	4, // slave address range: 0 - 3
+	2, // slave address range: 0 - 1
+	6, // slave address range: 0 - 5 (0,1: pin option 0; 2,3: pin option 1; 4,5: pin option 2)
+	1  // slave address range: 0 only
 	};
 
+
 //---------------------------------------------------------------
 // MCSPI Registers offsets and bits definitions
 //----------------------------------
@@ -370,9 +369,21 @@
 		}
 	};
 
+// McSPI3 supports 3 different pin routing settings
+const TSpiPinConfig TSpiPinConfigMcSpi3_0 =
+	{
+	{CONTROL_PADCONF_MMC2_CLK,  SCM::ELsw, 130, SCM::EMode1 | SCM::EInputEnable}, // mcspi3_clk
+	{CONTROL_PADCONF_MMC2_CLK,  SCM::EMsw, 131, SCM::EMode1 | SCM::EInputEnable}, // mcspi3_simo
+	{CONTROL_PADCONF_MMC2_DAT0, SCM::ELsw, 132, SCM::EMode1 | SCM::EInputEnable}, // mcspi3_somi
+		{
+		{CONTROL_PADCONF_MMC2_DAT2, SCM::EMsw, 135, SCM::EMode1}, // mcspi3_cs0
+		{CONTROL_PADCONF_MMC2_DAT2, SCM::ELsw, 134, SCM::EMode1}, // mcspi3_cs1
+		{0, SCM::ELsw, 0, 0}, // not supported
+		{0, SCM::ELsw, 0, 0}, // not supported
+		}
+	};
 
-#if defined(SPI_MODULE_3_PIN_OPTION_2)
-const TSpiPinConfig TSpiPinConfigMcSpi3 =
+const TSpiPinConfig TSpiPinConfigMcSpi3_1 =
 	{
 	{CONTROL_PADCONF_DSS_DATA18, SCM::ELsw, 88, SCM::EMode2 | SCM::EInputEnable}, // mcspi3_clk
 	{CONTROL_PADCONF_DSS_DATA18, SCM::EMsw, 89, SCM::EMode2 | SCM::EInputEnable}, // mcspi3_simo
@@ -384,8 +395,8 @@
 		{0, SCM::ELsw, 0, 0}, // not supported
 		}
 	};
-#elif defined(SPI_MODULE_3_PIN_OPTION_3)
-const TSpiPinConfig TSpiPinConfigMcSpi3 =
+
+const TSpiPinConfig TSpiPinConfigMcSpi3_2 =
 	{
 	{CONTROL_PADCONF_ETK_D2, SCM::EMsw, 17, SCM::EMode1 | SCM::EInputEnable}, // mcspi3_clk
 	{CONTROL_PADCONF_ETK_D0, SCM::ELsw, 14, SCM::EMode1 | SCM::EInputEnable}, // mcspi3_simo
@@ -397,20 +408,6 @@
 		{0, SCM::ELsw, 0, 0}, // not supported
 		}
 	};
-#else // default option (for beagle- these are pins on the extension header)
-const TSpiPinConfig TSpiPinConfigMcSpi3 =
-	{
-	{CONTROL_PADCONF_MMC2_CLK,  SCM::ELsw, 130, SCM::EMode1 | SCM::EInputEnable}, // mcspi3_clk
-	{CONTROL_PADCONF_MMC2_CLK,  SCM::EMsw, 131, SCM::EMode1 | SCM::EInputEnable}, // mcspi3_simo
-	{CONTROL_PADCONF_MMC2_DAT0, SCM::ELsw, 132, SCM::EMode1 | SCM::EInputEnable}, // mcspi3_somi
-		{
-		{CONTROL_PADCONF_MMC2_DAT2, SCM::EMsw, 135, SCM::EMode1}, // mcspi3_cs0
-		{CONTROL_PADCONF_MMC2_DAT2, SCM::ELsw, 134, SCM::EMode1}, // mcspi3_cs1
-		{0, SCM::ELsw, 0, 0}, // not supported
-		{0, SCM::ELsw, 0, 0}, // not supported
-		}
-	};
-#endif
 
 const TSpiPinConfig TSpiPinConfigMcSpi4 =
 	{
@@ -429,10 +426,14 @@
 	{
 	TSpiPinConfigMcSpi1,
 	TSpiPinConfigMcSpi2,
-	TSpiPinConfigMcSpi3,
-	TSpiPinConfigMcSpi4
+	TSpiPinConfigMcSpi3_0, // (default mode for McSPI3 - SPI addresses: 0 and 1)
+	TSpiPinConfigMcSpi4,
+	TSpiPinConfigMcSpi3_1, // other pin mode for McSPI3.. (spi addresses: 2 and 3)
+	TSpiPinConfigMcSpi3_2  // other pin mode for McSPI3.. (spi addresses: 4 and 5)
 	};
 
+
 #include "omap3530_spi.inl"
 
+
 #endif /* __OMAP3530_SPI_H__ */
--- a/omap3530/omap3530_drivers/spi/omap3530_spi.inl	Wed Sep 22 23:37:20 2010 +0100
+++ b/omap3530/omap3530_drivers/spi/omap3530_spi.inl	Tue Sep 28 02:37:35 2010 +0100
@@ -20,23 +20,28 @@
 // This sets the CS line to inactive mode (Specify aActiveMode as appropriate for configuration)
 // The CS pin will be put back to the opposite mode - using GPIO.. THis is in order to always keep
 // the CS line in an 'inactive' state (de-asserted) when the SPI is disabled.
-inline void SetCsInactive(TInt aModule, TInt aChannel, TSpiSsPinMode aActiveMode)
+inline void SetCsInactive(TInt aModule, TInt aChannel, TSpiSsPinMode aActiveMode, TUint aPinSetId = 0)
 	{
-	//__ASSERT_DEBUG(aModule < KMaxSpiChannelsPerModule, Kern::Fault("omap3530_spi.inl, line: ", __LINE__)); // aChannel > module channels
+	__ASSERT_DEBUG(aModule < KMaxSpiChannelsPerModule, Kern::Fault("omap3530_spi.inl, line: ", __LINE__)); // aChannel > module channels
+	__ASSERT_DEBUG( aModule != 2 ? !aPinSetId : ETrue, Kern::Fault("omap3530_spi.inl, line: ", __LINE__)); // only channel 3 supports other pin configurations
+
 	// set the pin to the opposite to the currently active CS mode..
 	const TPinConfig& csConf = ModulePinConfig[aModule].iCs[aChannel];
-	__ASSERT_DEBUG(csConf.iAddress, Kern::Fault("omap3530_spi.inl, line: ", __LINE__)); // aChannel > module channels
+	__ASSERT_DEBUG(csConf.iAddress, Kern::Fault("omap3530_spi.inl, line: ", __LINE__)); // don't try to use non-existing CS!
 
 	// now switch the pin mode..(making sure it is at the proper level before that)
 	GPIO::SetOutputState(csConf.iPinNumber, aActiveMode == ESpiCSPinActiveLow ? GPIO::EHigh : GPIO::ELow);
 	SCM::SetPadConfig(csConf.iAddress, csConf.iMswLsw, SCM::EMode4); // always go to mode 4 (gpio)
 	}
 
-void SetCsActive(TInt aModule, TInt aChannel)
+
+inline void SetCsActive(TInt aModule, TInt aChannel, TUint aPinSetId = 0)
 	{
-	//__ASSERT_DEBUG(aModule < KMaxSpiChannelsPerModule, Kern::Fault("omap3530_spi.inl, line: ", __LINE__)); // aChannel > module channels
-	const TPinConfig &csConf = ModulePinConfig[aModule].iCs[aChannel];
-	__ASSERT_DEBUG(csConf.iAddress, Kern::Fault("omap3530_spi.inl, line: ", __LINE__)); // aChannel > module channels
+	__ASSERT_DEBUG(aModule < KMaxSpiChannelsPerModule, Kern::Fault("omap3530_spi.inl, line: ", __LINE__)); // aChannel > module channels
+	__ASSERT_DEBUG( aModule != 2 ? !aPinSetId : ETrue, Kern::Fault("omap3530_spi.inl, line: ", __LINE__)); // only channel 3 supports other pin configurations
+
+	const TPinConfig &csConf = ModulePinConfig[aModule + aPinSetId].iCs[aChannel];
+	__ASSERT_DEBUG(csConf.iAddress, Kern::Fault("omap3530_spi.inl, line: ", __LINE__)); // don't try to use non-existing CS!
 
 	// now switch the pin mode back to the SPI
 	SCM::SetPadConfig(csConf.iAddress, csConf.iMswLsw, csConf.iFlags | SCM::EInputEnable); // revert to intended mode
@@ -44,10 +49,13 @@
 
 
 // Setup pad function for SPI pins..
-void SetupSpiPins(TUint aSpiModule)
+inline void SetupSpiPins(TUint aModule, TUint aPinSetId = 0)
 	{
-	//__ASSERT_DEBUG(aModule < KMaxSpiChannelsPerModule, Kern::Fault("omap3530_spi.inl, line: ", __LINE__)); // aChannel > module channels
-	const TSpiPinConfig& pinCnf = ModulePinConfig[aSpiModule];
+	__ASSERT_DEBUG(aModule < KMaxSpiChannelsPerModule, Kern::Fault("omap3530_spi.inl, line: ", __LINE__)); // aChannel > module channels
+	__ASSERT_DEBUG(aModule != 2 ? !aPinSetId : ETrue, Kern::Fault("omap3530_spi.inl, line: ", __LINE__)); // only channel 3 supports other pin configurations
+
+	const TSpiPinConfig& pinCnf = ModulePinConfig[aModule + aPinSetId];
+
 	SCM::SetPadConfig(pinCnf.iClk.iAddress, pinCnf.iClk.iMswLsw, pinCnf.iClk.iFlags);
 	SCM::SetPadConfig(pinCnf.iSimo.iAddress, pinCnf.iSimo.iMswLsw, pinCnf.iSimo.iFlags);
 	SCM::SetPadConfig(pinCnf.iSomi.iAddress, pinCnf.iSomi.iMswLsw, pinCnf.iSomi.iFlags);
@@ -57,12 +65,13 @@
 		{
 		if(pinCnf.iCs[i].iPinNumber)
 			{
+			// pre-set the GPIO..
 			GPIO::SetPinDirection(pinCnf.iCs[i].iPinNumber, GPIO::EOutput);
 			GPIO::SetPinMode(pinCnf.iCs[i].iPinNumber, GPIO::EEnabled);
 			}
 		else
 			{
-			break;
+			break; // no more channels (cs signals)
 			}
 		}
 	}
--- a/omap3530/omap3530_drivers/spi/psl_init.cpp	Wed Sep 22 23:37:20 2010 +0100
+++ b/omap3530/omap3530_drivers/spi/psl_init.cpp	Tue Sep 28 02:37:35 2010 +0100
@@ -50,8 +50,8 @@
 		// The first argument repesents the PSL-assigned channel number
 		// The second argument, DIicBusChannel::ESpi, should be replaced with the relevant bus type for the PSL
 //		chan = DSpiMasterBeagle::New(i, DIicBusChannel::ESpi, DIicBusChannel::EFullDuplex);
-		if((TInt)KIicPslNumOfChannels == 1)// TODO: hack - only for the time being - enable channel 3
-			chan = DSpiMasterBeagle::New(2, DIicBusChannel::ESpi, DIicBusChannel::EFullDuplex);
+		if((TInt)KIicPslNumOfChannels == 2)// TODO: hack - only for the time being - enable channel 3
+			chan = DSpiMasterBeagle::New(i+2, DIicBusChannel::ESpi, DIicBusChannel::EFullDuplex);
 		else
 			{
 			Kern::Printf("remove hack from here: %s,line %d", __FILE__, __LINE__);
--- a/omap3530/omap3530_drivers/spi/psl_init.h	Wed Sep 22 23:37:20 2010 +0100
+++ b/omap3530/omap3530_drivers/spi/psl_init.h	Tue Sep 28 02:37:35 2010 +0100
@@ -19,7 +19,8 @@
 #ifndef __OMAP3530_SPI_PSL_H__
 #define __OMAP3530_SPI_PSL_H__
 
-const TInt KIicPslNumOfChannels = 1; // Number of channels supported // TODO only one for now..
+const TInt KIicPslNumOfChannels = 2; // Number of channels supported // TODO only two 3 and 4 for now..
+// FIXME - there is a crash when using channels 1 and 2 - when accesing registers at e.g. 0xc609a000
 
 struct TIicOperationType
     {
--- a/omap3530/omap3530_drivers/spi/spi.mmp	Wed Sep 22 23:37:20 2010 +0100
+++ b/omap3530/omap3530_drivers/spi/spi.mmp	Tue Sep 28 02:37:35 2010 +0100
@@ -41,13 +41,6 @@
 SOURCE           slave.cpp
 #endif
 
-// define one of the below values to switch PIN modes for McSPI3 to match your PCB connections.
-// i.e. McSPI3 can be routed to 3 different pin sets using below defines - if both commented out
-// the default routing is used, which takes McSPI3 out to the extension header (beagleboard).
-// See omap3530_spi.h for more details.
-//macro SPI_MODULE_3_PIN_OPTION_2
-//macro SPI_MODULE_3_PIN_OPTION_3
-
 
 // PIL source
 #include   "../../../../../os/kernelhwsrv/kernel/eka/drivers/iic/iic_channel.mmh"
--- a/omap3530/omap3530_drivers/spi/test/d_spi_client_m.cpp	Wed Sep 22 23:37:20 2010 +0100
+++ b/omap3530/omap3530_drivers/spi/test/d_spi_client_m.cpp	Tue Sep 28 02:37:35 2010 +0100
@@ -14,6 +14,8 @@
 //
 // This test driver is a simple example IIC SPI client implementation - and a test to SPI implementation.
 // It is an LDD but PDD or kernel extension can implement / use the IIC SPI bus exactly the same way.
+// There is a lot of code duplication in this test code, but this is in order to provide clear and separate implementation
+// for each of these use cases, which can serve as example usecases that should be easy to adopt for the real purpose.
 //
 
 // Note: IMPORTANT! -If you intend to make changes to the driver!
@@ -95,7 +97,9 @@
 TInt DSpiClientTestFactory::Create(DLogicalChannelBase*& aChannel)
 	{
 	if (iOpenChannels >= KMaxNumChannels)
+		{
 		return KErrOverflow;
+		}
 
 	aChannel = new DSpiClientChannel;
 	return aChannel ? KErrNone : KErrNoMemory;
@@ -232,7 +236,7 @@
 					aId, aStatus, a1, a2));
 
 	// TODO: There are unimplemented functions - returning KErrNotSupported - treat this as a 'sort of'
-	// of test-driven development.. Ideally - they should all be implemented..
+	// test-driven development.. Ideally - they should all be implemented..
 	TInt r = KErrNone;
 	switch (aId)
 		{
@@ -367,7 +371,7 @@
 
 	TUint32 busId = 0;
 	SET_BUS_TYPE(busId, DIicBusChannel::ESpi);
-	SET_CHAN_NUM(busId, 2);   // THis is the ModuleNumber, i.e. McSPIx (minus one), e.g. 2 for McSPI3
+	SET_CHAN_NUM(busId, 3);   // THis is the ModuleNumber, i.e. McSPIx (minus one), e.g. 2 for McSPI3
 	SET_SLAVE_ADDR(busId, 0); // THis is the ChannelNumber (Slave number of the above McSPIx)
 
 	// create header
--- a/omap3530/shared/serialkeyb/serialkeyboard.cpp	Wed Sep 22 23:37:20 2010 +0100
+++ b/omap3530/shared/serialkeyb/serialkeyboard.cpp	Tue Sep 28 02:37:35 2010 +0100
@@ -323,7 +323,7 @@
 	static void UartIsr( TAny* aParam );
 	static void AddKeyDfc( TAny* aParam );
 	void AddKey( TUint aKey );
-	
+
 
 private:
 	enum TState
@@ -377,8 +377,6 @@
 			return r;
  			}
 
-		Kern::Printf("+TSerialKeyboard::Create bound to interrupt" );
-
 #ifdef USE_SYMBIAN_PRM
 		// Ask power resource manager to turn on clocks to the UART
 		// (this could take some time but we're not in any hurry)
@@ -407,7 +405,7 @@
 void TSerialKeyboard::UartIsr( TAny* aParam )
 	{
 	TSerialKeyboard* self = reinterpret_cast<TSerialKeyboard*>( aParam );
-	
+
 	const TUint iir = Omap3530Uart::IIR::iMem.Read( self->iUart );
 
 	if ( 0 == (iir bitand Omap3530Uart::IIR::IT_PENDING::KMask) )
@@ -419,7 +417,7 @@
 		if ( (pending bitand Omap3530Uart::IIR::IT_TYPE::ERHR) || (pending bitand Omap3530Uart::IIR::IT_TYPE::ERxLineStatus) )
 			{
 			TUint byte = self->iUart.Read();
-			
+
 			if( KMagicCrashValue == byte )
 				{
 				Kern::Fault( "SERKEY-FORCED", 0 );
@@ -467,7 +465,7 @@
 	case EEscaping2:
 		{
 		TInt index = self->iKey - KEscapeBase;
-		
+
 		if ( (index >= 0) && (index < KEscapeCount) )
 			{
 			self->AddKey( KEscapedScanCode[ index ] );
@@ -498,13 +496,13 @@
 
 	TRawEvent e;
 
-	
+
 	if ( func )
 		{
 		e.Set( TRawEvent::EKeyDown, EStdKeyRightFunc, 0 );
 		Kern::AddEvent( e );
 		}
-	
+
 	if ( ctrl )
 		{
 		e.Set( TRawEvent::EKeyDown, EStdKeyRightCtrl, 0 );