--- /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 <e32cmn.h>
+#include <e32ver.h>
+
+
+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 <kernel/kernel.h>
+
+// 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 <assp/omap3530_assp/omap3530_scm.h>
+#include <assp/omap3530_assp/omap3530_gpio.h>
+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__ */