diff -r 29b14275133a -r e5fd00cbb70a omap3530/omap3530_drivers/spi/test/d_spi_client_m.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/omap3530/omap3530_drivers/spi/test/d_spi_client_m.h Tue Sep 21 02:30:11 2010 +0100 @@ -0,0 +1,252 @@ +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// lukasz.forynski@gmail.com +// +// Contributors: +// +// +// Description: +// omap3530_drivers/spi/test/d_spi_client_m.h +// + +#ifndef __D_SPI_CLIENT_MASTER__ +#define __D_SPI_CLIENT_MASTER__ + +#include +#include + + +const TInt KIntTestThreadPriority = 24; + +const TInt KIntTestMajorVersionNumber = 1; +const TInt KIntTestMinorVersionNumber = 0; +const TInt KIntTestBuildVersionNumber = KE32BuildVersionNumber; + +_LIT(KLddFileName, "d_spi_client_m.ldd"); +_LIT(KLddFileNameRoot, "d_spi_client_m"); + +#ifdef __KERNEL_MODE__ +#include + +// For now - the driver has to know what frequencies are supported and has to specify them directly +// in the transaction header. This might be changes in the IIC PIL (kernelhwsrv)-in a way, that the driver +// returns supported frequencies with some 'GetCaps' method. For now - standard frequencies for CLK +// (that support duty cycle 50-50) are 48MHz divisions per power-of-two. +const TInt KSpiClkBaseFreqHz = 48000000; +const TInt KSpiClkMaxDivider = 4096; + +inline TInt SpiFreqHz(TInt aDivider) + { + __ASSERT_DEBUG(aDivider > 0 && aDivider < KSpiClkMaxDivider, Kern::Fault("d_spi_client_master: divider out of range", 13)); + __ASSERT_DEBUG(!(aDivider & (aDivider-1)), Kern::Fault("d_spi_client_master: divider not power of two", 14)); + return KSpiClkBaseFreqHz / aDivider; + } +#endif + +class RSpiClientTest: public RBusLogicalChannel + { +public: + enum TControl + { + EHalfDuplexSingleWrite, + EHalfDuplexMultipleWrite, + EHalfDuplexSingleRead, + EHalfDuplexMultipleRead, + EHalfDuplexMultipleWriteRead, + EFullDuplexSingle, + EFullDuplexMultiple, + EHalfDuplexExtendable, + EFullDuplexExtendable + }; + + enum TRequest + { + EAsyncHalfDuplexSingleWrite, + EAsyncHalfDuplexMultipleWrite, + EAsyncHalfDuplexSingleRead, + EAsyncHalfDuplexMultipleRead, + EAsyncHalfDuplexMultipleWriteRead, + EAsyncFullDuplexSingle, + EAsyncFullDuplexMultiple, + EAsyncHalfDuplexExtendable, + EAsyncFullDuplexExtendable + }; + +#ifndef __KERNEL_MODE__ +public: + TInt Open() + { + return (DoCreate(KLddFileNameRoot, + TVersion(KIntTestMajorVersionNumber,KIntTestMinorVersionNumber,KIntTestBuildVersionNumber), + -1, + NULL, + NULL, + EOwnerThread)); + } + + // Synchronous calls + TInt HalfDuplexSingleWrite() + {return DoControl(EHalfDuplexSingleWrite);} + + TInt HalfDuplexMultipleWrite() + {return DoControl(EHalfDuplexMultipleWrite);} + + TInt HalfDuplexSingleRead() + {return DoControl(EHalfDuplexSingleRead);} + + TInt HalfDuplexMultipleRead() + {return DoControl(EHalfDuplexMultipleRead);} + + TInt HalfDuplexMultipleWriteRead() + {return DoControl(EHalfDuplexMultipleWriteRead);} + + TInt FullDuplexSingle() + {return DoControl(EFullDuplexSingle);} + + TInt FullDuplexMultiple() + {return DoControl(EFullDuplexMultiple);} + + + // Asynchronous calls.. + void HalfDuplexSingleWrite(TRequestStatus& aStatus) + {DoRequest(EAsyncHalfDuplexSingleWrite, aStatus, NULL);} + + void HalfDuplexMultipleWrite(TRequestStatus& aStatus) + {DoRequest(EAsyncHalfDuplexMultipleWrite, aStatus, NULL);} + + void HalfDuplexSingleRead(TRequestStatus& aStatus) + {DoRequest(EAsyncHalfDuplexSingleRead, aStatus, NULL);} + + void HalfDuplexMultipleRead(TRequestStatus& aStatus) + {DoRequest(EAsyncHalfDuplexMultipleRead, aStatus, NULL);} + + void HalfDuplexMultipleWriteRead(TRequestStatus& aStatus) + {DoRequest(EAsyncHalfDuplexMultipleWriteRead, aStatus, NULL);} + + void FullDuplexSingle(TRequestStatus& aStatus) + {DoRequest(EAsyncFullDuplexSingle, aStatus, NULL);} + + void FullDuplexMultiple(TRequestStatus& aStatus) + {DoRequest(EAsyncFullDuplexMultiple, aStatus, NULL);} + +#endif + }; + +#ifdef __KERNEL_MODE__ +struct TCapsProxyClient + { + TVersion version; + }; + +class DSpiClientTestFactory: public DLogicalDevice + { +public: + DSpiClientTestFactory(); + ~DSpiClientTestFactory(); + virtual TInt Install(); + virtual void GetCaps(TDes8 &aDes) const; + virtual TInt Create(DLogicalChannelBase*& aChannel); + }; + +// declaration for the client channel +class DSpiClientChannel: public DLogicalChannel + { +public: + DSpiClientChannel(); + ~DSpiClientChannel(); + virtual TInt DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer); + +protected: + static void Handler(TAny *aParam); + virtual void HandleMsg(TMessageBase* aMsg); // Note: this is a pure virtual in DLogicalChannel + TInt DoControl(TInt aId, TAny* a1, TAny* a2); + TInt DoRequest(TInt aId, TRequestStatus* aStatus, TAny* a1, TAny* a2); + + // set of example transfers with transactions queued synchronously + TInt HalfDuplexSingleWrite(); + TInt HalfDuplexMultipleWrite(); + TInt HalfDuplexSingleRead(); + TInt HalfDuplexMultipleRead(); + TInt HalfDuplexMultipleWriteRead(); + TInt FullDuplexSingle(); + TInt FullDuplexMultiple(); + TInt HalfDuplexExtendable(); + TInt FullDuplexExtendable(); + + +private: + TRequestStatus iStatus; + DThread* iClient; + }; + +// Below is additional stuff for testing with local loopback +// the IsLoopbackAvailable function checks if McSPI3 is configured to use pins from extension header +// (Beagleboard) and if these pins are physically connected (e.g. with jumper)- in order to determine +// if duplex transfers should receive the same data that was sent to the bus.. +#include +#include +const TInt KSpi3_SIMO_Pin = 131; +const TInt KSpi3_SOMI_Pin = 132; + +inline TBool IsLoopbackAvailable() + { + // first check, if pad is configured to use SPI (this will confirm, if pins are used that way) + // this is their configuration (EMode1) + // CONTROL_PADCONF_MMC2_CLK, SCM::EMsw, SCM::EMode1, // mcspi3_simo + // CONTROL_PADCONF_MMC2_DAT0, SCM::ELsw, SCM::EMode1, // mcspi3_somi + TUint mode_MMC2_CLK = SCM::GetPadConfig(CONTROL_PADCONF_MMC2_CLK, SCM::EMsw); + TUint mode_MMC2_DAT0 = SCM::GetPadConfig(CONTROL_PADCONF_MMC2_DAT0, SCM::ELsw); + + if(!(mode_MMC2_CLK & SCM::EMode1) || + !(mode_MMC2_DAT0 & SCM::EMode1)) + { + return EFalse; // either other pins are used or SPI3 is not configured at all.. + } + + // swap pins to be GPIO (EMode4) + SCM::SetPadConfig(CONTROL_PADCONF_MMC2_CLK, SCM::EMsw, SCM::EMode4 | SCM::EInputEnable); + SCM::SetPadConfig(CONTROL_PADCONF_MMC2_DAT0, SCM::ELsw, SCM::EMode4 | SCM::EInputEnable); + + // set SIMO pin as output + GPIO::SetPinDirection(KSpi3_SIMO_Pin, GPIO::EOutput); + GPIO::SetPinMode(KSpi3_SIMO_Pin, GPIO::EEnabled); + + // and SOMI pin as input + GPIO::SetPinDirection(KSpi3_SOMI_Pin, GPIO::EInput); + GPIO::SetPinMode(KSpi3_SOMI_Pin, GPIO::EEnabled); + + TBool result = ETrue; + GPIO::TGpioState pinState = GPIO::EHigh; + + // test 1: set SIMO to ELow and check if SOMI is the same + GPIO::SetOutputState(KSpi3_SIMO_Pin, GPIO::ELow); + GPIO::GetInputState(KSpi3_SOMI_Pin, pinState); + if(pinState != GPIO::ELow) + { + result = EFalse; + } + else + { + // test 2: set SIMO to EHigh and check if SOMI is the same + GPIO::SetOutputState(KSpi3_SIMO_Pin, GPIO::EHigh); + GPIO::GetInputState(KSpi3_SOMI_Pin, pinState); + if(pinState != GPIO::EHigh) + { + result = EFalse; + } + } + + // restore back oryginal pad configuration for these pins + SCM::SetPadConfig(CONTROL_PADCONF_MMC2_CLK, SCM::EMsw, mode_MMC2_CLK); + SCM::SetPadConfig(CONTROL_PADCONF_MMC2_DAT0, SCM::ELsw, mode_MMC2_DAT0); + + return result; + } + +#endif /* __KERNEL_MODE__ */ + +#endif /* __D_SPI_CLIENT_MASTER__ */