|
1 // This component and the accompanying materials are made available |
|
2 // under the terms of the License "Eclipse Public License v1.0" |
|
3 // which accompanies this distribution, and is available |
|
4 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
5 // |
|
6 // Initial Contributors: |
|
7 // lukasz.forynski@gmail.com |
|
8 // |
|
9 // Contributors: |
|
10 // |
|
11 // |
|
12 // Description: |
|
13 // omap3530_drivers/spi/test/d_spi_client_m.h |
|
14 // |
|
15 |
|
16 #ifndef __D_SPI_CLIENT_MASTER__ |
|
17 #define __D_SPI_CLIENT_MASTER__ |
|
18 |
|
19 #include <e32cmn.h> |
|
20 #include <e32ver.h> |
|
21 |
|
22 |
|
23 const TInt KIntTestThreadPriority = 24; |
|
24 |
|
25 const TInt KIntTestMajorVersionNumber = 1; |
|
26 const TInt KIntTestMinorVersionNumber = 0; |
|
27 const TInt KIntTestBuildVersionNumber = KE32BuildVersionNumber; |
|
28 |
|
29 _LIT(KLddFileName, "d_spi_client_m.ldd"); |
|
30 _LIT(KLddFileNameRoot, "d_spi_client_m"); |
|
31 |
|
32 #ifdef __KERNEL_MODE__ |
|
33 #include <kernel/kernel.h> |
|
34 |
|
35 // For now - the driver has to know what frequencies are supported and has to specify them directly |
|
36 // in the transaction header. This might be changes in the IIC PIL (kernelhwsrv)-in a way, that the driver |
|
37 // returns supported frequencies with some 'GetCaps' method. For now - standard frequencies for CLK |
|
38 // (that support duty cycle 50-50) are 48MHz divisions per power-of-two. |
|
39 const TInt KSpiClkBaseFreqHz = 48000000; |
|
40 const TInt KSpiClkMaxDivider = 4096; |
|
41 |
|
42 inline TInt SpiFreqHz(TInt aDivider) |
|
43 { |
|
44 __ASSERT_DEBUG(aDivider > 0 && aDivider < KSpiClkMaxDivider, Kern::Fault("d_spi_client_master: divider out of range", 13)); |
|
45 __ASSERT_DEBUG(!(aDivider & (aDivider-1)), Kern::Fault("d_spi_client_master: divider not power of two", 14)); |
|
46 return KSpiClkBaseFreqHz / aDivider; |
|
47 } |
|
48 #endif |
|
49 |
|
50 class RSpiClientTest: public RBusLogicalChannel |
|
51 { |
|
52 public: |
|
53 enum TControl |
|
54 { |
|
55 EHalfDuplexSingleWrite, |
|
56 EHalfDuplexMultipleWrite, |
|
57 EHalfDuplexSingleRead, |
|
58 EHalfDuplexMultipleRead, |
|
59 EHalfDuplexMultipleWriteRead, |
|
60 EFullDuplexSingle, |
|
61 EFullDuplexMultiple, |
|
62 EHalfDuplexExtendable, |
|
63 EFullDuplexExtendable |
|
64 }; |
|
65 |
|
66 enum TRequest |
|
67 { |
|
68 EAsyncHalfDuplexSingleWrite, |
|
69 EAsyncHalfDuplexMultipleWrite, |
|
70 EAsyncHalfDuplexSingleRead, |
|
71 EAsyncHalfDuplexMultipleRead, |
|
72 EAsyncHalfDuplexMultipleWriteRead, |
|
73 EAsyncFullDuplexSingle, |
|
74 EAsyncFullDuplexMultiple, |
|
75 EAsyncHalfDuplexExtendable, |
|
76 EAsyncFullDuplexExtendable |
|
77 }; |
|
78 |
|
79 #ifndef __KERNEL_MODE__ |
|
80 public: |
|
81 TInt Open() |
|
82 { |
|
83 return (DoCreate(KLddFileNameRoot, |
|
84 TVersion(KIntTestMajorVersionNumber,KIntTestMinorVersionNumber,KIntTestBuildVersionNumber), |
|
85 -1, |
|
86 NULL, |
|
87 NULL, |
|
88 EOwnerThread)); |
|
89 } |
|
90 |
|
91 // Synchronous calls |
|
92 TInt HalfDuplexSingleWrite() |
|
93 {return DoControl(EHalfDuplexSingleWrite);} |
|
94 |
|
95 TInt HalfDuplexMultipleWrite() |
|
96 {return DoControl(EHalfDuplexMultipleWrite);} |
|
97 |
|
98 TInt HalfDuplexSingleRead() |
|
99 {return DoControl(EHalfDuplexSingleRead);} |
|
100 |
|
101 TInt HalfDuplexMultipleRead() |
|
102 {return DoControl(EHalfDuplexMultipleRead);} |
|
103 |
|
104 TInt HalfDuplexMultipleWriteRead() |
|
105 {return DoControl(EHalfDuplexMultipleWriteRead);} |
|
106 |
|
107 TInt FullDuplexSingle() |
|
108 {return DoControl(EFullDuplexSingle);} |
|
109 |
|
110 TInt FullDuplexMultiple() |
|
111 {return DoControl(EFullDuplexMultiple);} |
|
112 |
|
113 |
|
114 // Asynchronous calls.. |
|
115 void HalfDuplexSingleWrite(TRequestStatus& aStatus) |
|
116 {DoRequest(EAsyncHalfDuplexSingleWrite, aStatus, NULL);} |
|
117 |
|
118 void HalfDuplexMultipleWrite(TRequestStatus& aStatus) |
|
119 {DoRequest(EAsyncHalfDuplexMultipleWrite, aStatus, NULL);} |
|
120 |
|
121 void HalfDuplexSingleRead(TRequestStatus& aStatus) |
|
122 {DoRequest(EAsyncHalfDuplexSingleRead, aStatus, NULL);} |
|
123 |
|
124 void HalfDuplexMultipleRead(TRequestStatus& aStatus) |
|
125 {DoRequest(EAsyncHalfDuplexMultipleRead, aStatus, NULL);} |
|
126 |
|
127 void HalfDuplexMultipleWriteRead(TRequestStatus& aStatus) |
|
128 {DoRequest(EAsyncHalfDuplexMultipleWriteRead, aStatus, NULL);} |
|
129 |
|
130 void FullDuplexSingle(TRequestStatus& aStatus) |
|
131 {DoRequest(EAsyncFullDuplexSingle, aStatus, NULL);} |
|
132 |
|
133 void FullDuplexMultiple(TRequestStatus& aStatus) |
|
134 {DoRequest(EAsyncFullDuplexMultiple, aStatus, NULL);} |
|
135 |
|
136 #endif |
|
137 }; |
|
138 |
|
139 #ifdef __KERNEL_MODE__ |
|
140 struct TCapsProxyClient |
|
141 { |
|
142 TVersion version; |
|
143 }; |
|
144 |
|
145 class DSpiClientTestFactory: public DLogicalDevice |
|
146 { |
|
147 public: |
|
148 DSpiClientTestFactory(); |
|
149 ~DSpiClientTestFactory(); |
|
150 virtual TInt Install(); |
|
151 virtual void GetCaps(TDes8 &aDes) const; |
|
152 virtual TInt Create(DLogicalChannelBase*& aChannel); |
|
153 }; |
|
154 |
|
155 // declaration for the client channel |
|
156 class DSpiClientChannel: public DLogicalChannel |
|
157 { |
|
158 public: |
|
159 DSpiClientChannel(); |
|
160 ~DSpiClientChannel(); |
|
161 virtual TInt DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer); |
|
162 |
|
163 protected: |
|
164 static void Handler(TAny *aParam); |
|
165 virtual void HandleMsg(TMessageBase* aMsg); // Note: this is a pure virtual in DLogicalChannel |
|
166 TInt DoControl(TInt aId, TAny* a1, TAny* a2); |
|
167 TInt DoRequest(TInt aId, TRequestStatus* aStatus, TAny* a1, TAny* a2); |
|
168 |
|
169 // set of example transfers with transactions queued synchronously |
|
170 TInt HalfDuplexSingleWrite(); |
|
171 TInt HalfDuplexMultipleWrite(); |
|
172 TInt HalfDuplexSingleRead(); |
|
173 TInt HalfDuplexMultipleRead(); |
|
174 TInt HalfDuplexMultipleWriteRead(); |
|
175 TInt FullDuplexSingle(); |
|
176 TInt FullDuplexMultiple(); |
|
177 TInt HalfDuplexExtendable(); |
|
178 TInt FullDuplexExtendable(); |
|
179 |
|
180 |
|
181 private: |
|
182 TRequestStatus iStatus; |
|
183 DThread* iClient; |
|
184 }; |
|
185 |
|
186 // Below is additional stuff for testing with local loopback |
|
187 // the IsLoopbackAvailable function checks if McSPI3 is configured to use pins from extension header |
|
188 // (Beagleboard) and if these pins are physically connected (e.g. with jumper)- in order to determine |
|
189 // if duplex transfers should receive the same data that was sent to the bus.. |
|
190 #include <assp/omap3530_assp/omap3530_scm.h> |
|
191 #include <assp/omap3530_assp/omap3530_gpio.h> |
|
192 const TInt KSpi3_SIMO_Pin = 131; |
|
193 const TInt KSpi3_SOMI_Pin = 132; |
|
194 |
|
195 inline TBool IsLoopbackAvailable() |
|
196 { |
|
197 // first check, if pad is configured to use SPI (this will confirm, if pins are used that way) |
|
198 // this is their configuration (EMode1) |
|
199 // CONTROL_PADCONF_MMC2_CLK, SCM::EMsw, SCM::EMode1, // mcspi3_simo |
|
200 // CONTROL_PADCONF_MMC2_DAT0, SCM::ELsw, SCM::EMode1, // mcspi3_somi |
|
201 TUint mode_MMC2_CLK = SCM::GetPadConfig(CONTROL_PADCONF_MMC2_CLK, SCM::EMsw); |
|
202 TUint mode_MMC2_DAT0 = SCM::GetPadConfig(CONTROL_PADCONF_MMC2_DAT0, SCM::ELsw); |
|
203 |
|
204 if(!(mode_MMC2_CLK & SCM::EMode1) || |
|
205 !(mode_MMC2_DAT0 & SCM::EMode1)) |
|
206 { |
|
207 return EFalse; // either other pins are used or SPI3 is not configured at all.. |
|
208 } |
|
209 |
|
210 // swap pins to be GPIO (EMode4) |
|
211 SCM::SetPadConfig(CONTROL_PADCONF_MMC2_CLK, SCM::EMsw, SCM::EMode4 | SCM::EInputEnable); |
|
212 SCM::SetPadConfig(CONTROL_PADCONF_MMC2_DAT0, SCM::ELsw, SCM::EMode4 | SCM::EInputEnable); |
|
213 |
|
214 // set SIMO pin as output |
|
215 GPIO::SetPinDirection(KSpi3_SIMO_Pin, GPIO::EOutput); |
|
216 GPIO::SetPinMode(KSpi3_SIMO_Pin, GPIO::EEnabled); |
|
217 |
|
218 // and SOMI pin as input |
|
219 GPIO::SetPinDirection(KSpi3_SOMI_Pin, GPIO::EInput); |
|
220 GPIO::SetPinMode(KSpi3_SOMI_Pin, GPIO::EEnabled); |
|
221 |
|
222 TBool result = ETrue; |
|
223 GPIO::TGpioState pinState = GPIO::EHigh; |
|
224 |
|
225 // test 1: set SIMO to ELow and check if SOMI is the same |
|
226 GPIO::SetOutputState(KSpi3_SIMO_Pin, GPIO::ELow); |
|
227 GPIO::GetInputState(KSpi3_SOMI_Pin, pinState); |
|
228 if(pinState != GPIO::ELow) |
|
229 { |
|
230 result = EFalse; |
|
231 } |
|
232 else |
|
233 { |
|
234 // test 2: set SIMO to EHigh and check if SOMI is the same |
|
235 GPIO::SetOutputState(KSpi3_SIMO_Pin, GPIO::EHigh); |
|
236 GPIO::GetInputState(KSpi3_SOMI_Pin, pinState); |
|
237 if(pinState != GPIO::EHigh) |
|
238 { |
|
239 result = EFalse; |
|
240 } |
|
241 } |
|
242 |
|
243 // restore back oryginal pad configuration for these pins |
|
244 SCM::SetPadConfig(CONTROL_PADCONF_MMC2_CLK, SCM::EMsw, mode_MMC2_CLK); |
|
245 SCM::SetPadConfig(CONTROL_PADCONF_MMC2_DAT0, SCM::ELsw, mode_MMC2_DAT0); |
|
246 |
|
247 return result; |
|
248 } |
|
249 |
|
250 #endif /* __KERNEL_MODE__ */ |
|
251 |
|
252 #endif /* __D_SPI_CLIENT_MASTER__ */ |