|
1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // omap3530/omap3530_drivers/uart/uart.cpp |
|
15 // This file is part of the Beagle Base port |
|
16 // |
|
17 |
|
18 #include <e32cmn.h> |
|
19 #include <assp/omap3530_assp/omap3530_uart.h> |
|
20 |
|
21 |
|
22 LOCAL_C void ClientPanic( TInt aLine ) |
|
23 { |
|
24 _LIT( KString, "uart.cpp" ); |
|
25 Kern::PanicCurrentThread( KString, aLine ); |
|
26 } |
|
27 |
|
28 |
|
29 namespace Omap3530Uart |
|
30 { |
|
31 |
|
32 struct THwInfo |
|
33 { |
|
34 TUint32 iBaseAddress; |
|
35 TInt iInterruptId; |
|
36 Prcm::TClock iInterfaceClock : 16; |
|
37 Prcm::TClock iFunctionClock : 16; |
|
38 // Omap3530Prm::TPrmId iPrmInterfaceClock : 16; |
|
39 // Omap3530Prm::TPrmId iPrmFunctionClock : 16; |
|
40 }; |
|
41 |
|
42 static const THwInfo KHwInfo[3] = |
|
43 { |
|
44 { // EUart0 |
|
45 TUartTraits< EUart0 >::KBaseAddress, |
|
46 TUartTraits< EUart0 >::KInterruptId, |
|
47 TUartTraits< EUart0 >::KInterfaceClock, |
|
48 TUartTraits< EUart0 >::KFunctionClock, |
|
49 // TUartTraits< EUart0 >::KPrmInterfaceClock, |
|
50 // TUartTraits< EUart0 >::KPrmFunctionClock |
|
51 }, |
|
52 { // EUart1 |
|
53 TUartTraits< EUart1 >::KBaseAddress, |
|
54 TUartTraits< EUart1 >::KInterruptId, |
|
55 TUartTraits< EUart1 >::KInterfaceClock, |
|
56 TUartTraits< EUart1 >::KFunctionClock, |
|
57 // TUartTraits< EUart1 >::KPrmInterfaceClock, |
|
58 // TUartTraits< EUart1 >::KPrmFunctionClock |
|
59 }, |
|
60 { // EUart2 |
|
61 TUartTraits< EUart2 >::KBaseAddress, |
|
62 TUartTraits< EUart2 >::KInterruptId, |
|
63 TUartTraits< EUart2 >::KInterfaceClock, |
|
64 TUartTraits< EUart2 >::KFunctionClock, |
|
65 // TUartTraits< EUart2 >::KPrmInterfaceClock, |
|
66 // TUartTraits< EUart2 >::KPrmFunctionClock |
|
67 }, |
|
68 }; |
|
69 |
|
70 // Baud lookup table, indexed by [ TBaud, TUartMode ]. |
|
71 // Values obtained from 3530 datasheet |
|
72 |
|
73 struct TBaudInfo |
|
74 { |
|
75 TUint8 iDlh; |
|
76 TUint8 iDll; |
|
77 TUint8 iMultiplier; // Multiplier selection for UART16x/13x mode |
|
78 }; |
|
79 |
|
80 static const TBaudInfo KBaudControl[ TUart::KSupportedBaudCount ][ TUart::KSupportedUartModes ] = |
|
81 { |
|
82 // EUart EUartAutoBaud ESIR EMIR EFIR ECIR |
|
83 /*1200*/ { {0x09, 0xC4, 16 }, {0x09, 0xC4, 16 }, {0x09, 0xC4, 16 }, {0x00, 0x02, 1 }, {0x00, 0x0, 1 }, {0x09, 0xC4, 16 } }, |
|
84 /*2400*/ { {0x04, 0xE2, 16 }, {0x04, 0xE2, 16 }, {0x04, 0xE2, 16 }, {0x00, 0x02, 1 }, {0x00, 0x0, 1 }, {0x09, 0xC4, 16 } }, |
|
85 /*4800*/ { {0x02, 0x71, 16 }, {0x02, 0x71, 16 }, {0x02, 0x71, 16 }, {0x00, 0x02, 1 }, {0x00, 0x0, 1 }, {0x09, 0xC4, 16 } }, |
|
86 /*9600*/ { {0x01, 0x38, 16 }, {0x01, 0x38, 16 }, {0x01, 0x38, 16 }, {0x00, 0x02, 1 }, {0x00, 0x0, 1 }, {0x09, 0xC4, 16 } }, |
|
87 /*14400*/ { {0x00, 0xD0, 16 }, {0x00, 0xD0, 16 }, {0x00, 0xD0, 16 }, {0x00, 0x02, 1 }, {0x00, 0x0, 1 }, {0x09, 0xC4, 16 } }, |
|
88 /*19200*/ { {0x00, 0x9C, 16 }, {0x00, 0x9C, 16 }, {0x00, 0x9C, 16 }, {0x00, 0x02, 1 }, {0x00, 0x0, 1 }, {0x09, 0xC4, 16 } }, |
|
89 /*28800*/ { {0x00, 0x68, 16 }, {0x00, 0x68, 16 }, {0x00, 0x68, 16 }, {0x00, 0x02, 1 }, {0x00, 0x0, 1 }, {0x09, 0xC4, 16 } }, |
|
90 /*38400*/ { {0x00, 0x4E, 16 }, {0x00, 0x4E, 16 }, {0x00, 0x4E, 16 }, {0x00, 0x02, 1 }, {0x00, 0x0, 1 }, {0x09, 0xC4, 16 } }, |
|
91 /*57600*/ { {0x00, 0x34, 16 }, {0x00, 0x34, 16 }, {0x00, 0x34, 16 }, {0x00, 0x02, 1 }, {0x00, 0x0, 1 }, {0x09, 0xC4, 16 } }, |
|
92 /*115200*/ { {0x00, 0x1A, 16 }, {0x00, 0x1A, 16 }, {0x00, 0x1A, 16 }, {0x00, 0x01, 1 }, {0x00, 0x0, 1 }, {0x09, 0xC4, 16 } }, |
|
93 /*230400*/ { {0x00, 0x0D, 16 }, {0x09, 0xC4, 16 }, {0x00, 0x1A, 16 }, {0x00, 0x01, 1 }, {0x00, 0x0, 1 }, {0x09, 0xC4, 16 } }, |
|
94 /*460800*/ { {0x00, 0x08, 13 }, {0x09, 0xC4, 13 }, {0x00, 0x1A, 16 }, {0x00, 0x01, 1 }, {0x00, 0x0, 1 }, {0x09, 0xC4, 13 } }, |
|
95 /*921600*/ { {0x00, 0x04, 13 }, {0x09, 0xC4, 13 }, {0x00, 0x1A, 16 }, {0x00, 0x01, 1 }, {0x00, 0x0, 1 }, {0x09, 0xC4, 13 } }, |
|
96 /*1843000*/ { {0x00, 0x02, 13 }, {0x09, 0xC4, 13 }, {0x00, 0x1A, 16 }, {0x00, 0x01, 1 }, {0x00, 0x0, 1 }, {0x09, 0xC4, 13 } }, |
|
97 /*3688400*/ { {0x00, 0x01, 13 }, {0x09, 0xC4, 13 }, {0x00, 0x1A, 16 }, {0x00, 0x01, 1 }, {0x00, 0x0, 1 }, {0x09, 0xC4, 13 } }, |
|
98 /*4000000*/ { {0x00, 0x01, 13 }, {0x09, 0xC4, 13 }, {0x00, 0x1A, 16 }, {0x00, 0x01, 1 }, {0x00, 0x0, 1 }, {0x09, 0xC4, 13 } } |
|
99 }; |
|
100 |
|
101 /** Default mode to target mode conversion */ |
|
102 static const MDR1::MODE_SELECT::TMode KDefaultTargetMode[ TUart::KSupportedUartModes ] = |
|
103 { |
|
104 MDR1::MODE_SELECT::EUart16x, // EUart |
|
105 MDR1::MODE_SELECT::EUart16xAutoBaud, // EUartAutoBaud |
|
106 MDR1::MODE_SELECT::ESIR, // ESIR |
|
107 MDR1::MODE_SELECT::EMIR, // EMIR |
|
108 MDR1::MODE_SELECT::EFIR, // EFIR |
|
109 MDR1::MODE_SELECT::ECIR, // ECIR |
|
110 }; |
|
111 |
|
112 /** Conversion table from parity mode to LCR bit settings */ |
|
113 static const TUint8 KParitySelectTable[ 5 ] = |
|
114 { |
|
115 LCR::PARITY_TYPE2::KOff bitor LCR::PARITY_TYPE1::KOff bitor LCR::PARITY_EN::KOff, // ENone, |
|
116 LCR::PARITY_TYPE2::KOff bitor LCR::PARITY_TYPE1::KOff bitor LCR::PARITY_EN::KOn, // EOdd, |
|
117 LCR::PARITY_TYPE2::KOff bitor LCR::PARITY_TYPE1::KOn bitor LCR::PARITY_EN::KOn, // EEven, |
|
118 LCR::PARITY_TYPE2::KOn bitor LCR::PARITY_TYPE1::KOff bitor LCR::PARITY_EN::KOn, // EMark, |
|
119 LCR::PARITY_TYPE2::KOn bitor LCR::PARITY_TYPE1::KOn bitor LCR::PARITY_EN::KOn, // ESpace |
|
120 }; |
|
121 |
|
122 static const TUint8 KRxFifoTrigTable[] = |
|
123 { |
|
124 FCR::RX_FIFO_TRIG::K8Char, // EFifoTrigger8, |
|
125 FCR::RX_FIFO_TRIG::K16Char, // EFifoTrigger16, |
|
126 FCR::RX_FIFO_TRIG::K16Char, // EFifoTrigger32, |
|
127 FCR::RX_FIFO_TRIG::K56Char, // EFifoTrigger56, |
|
128 FCR::RX_FIFO_TRIG::K60Char, // EFifoTrigger60 |
|
129 }; |
|
130 |
|
131 static const TUint8 KTxFifoTrigTable[] = |
|
132 { |
|
133 FCR::TX_FIFO_TRIG::K8Char, // EFifoTrigger8, |
|
134 FCR::TX_FIFO_TRIG::K16Char, // EFifoTrigger16, |
|
135 FCR::TX_FIFO_TRIG::K32Char, // EFifoTrigger32, |
|
136 FCR::TX_FIFO_TRIG::K56Char, // EFifoTrigger56, |
|
137 FCR::TX_FIFO_TRIG::K56Char, // EFifoTrigger60 |
|
138 }; |
|
139 |
|
140 // RAII for entering and leaving mode B with enhanced enabled |
|
141 class TRaiiEnhancedModeB |
|
142 { |
|
143 public: |
|
144 TRaiiEnhancedModeB( TUart& aUart ); |
|
145 ~TRaiiEnhancedModeB(); |
|
146 |
|
147 private: |
|
148 TRaiiEnhancedModeB(); |
|
149 |
|
150 private: |
|
151 TUart& iUart; |
|
152 TUint8 iOldLcr; |
|
153 TUint8 iOldEnhanced; |
|
154 }; |
|
155 |
|
156 TRaiiEnhancedModeB::TRaiiEnhancedModeB( TUart& aUart ) |
|
157 : iUart( aUart ) |
|
158 { |
|
159 iOldLcr = LCR::iMem.Read( aUart ); |
|
160 LCR::iMem.Write( aUart, LCR::KConfigModeB ); |
|
161 iOldEnhanced = EFR::iMem.Read( aUart ) bitand EFR::ENHANCED_EN::KMask; |
|
162 EFR::iMem.Modify( aUart, KClearNone, EFR::ENHANCED_EN::KOn ); |
|
163 } |
|
164 |
|
165 TRaiiEnhancedModeB::~TRaiiEnhancedModeB() |
|
166 { |
|
167 LCR::iMem.Write( iUart, LCR::KConfigModeB ); |
|
168 EFR::iMem.Modify( iUart, EFR::ENHANCED_EN::KMask, iOldEnhanced ); |
|
169 LCR::iMem.Write( iUart, iOldLcr ); |
|
170 } |
|
171 |
|
172 |
|
173 |
|
174 EXPORT_C void TUart::Init() |
|
175 { |
|
176 // Perfom a UART soft reset |
|
177 SYSC::iMem.Write( *this, SYSC::SOFTRESET::KOn ); |
|
178 while( 0 == (SYSS::iMem.Read( *this ) bitand SYSS::RESETDONE::KMask) ); |
|
179 LCR::iMem.Write( *this, LCR::KConfigModeB ); |
|
180 EFR::iMem.Modify( *this, KClearNone, EFR::ENHANCED_EN::KOn ); |
|
181 LCR::iMem.Write( *this, LCR::KConfigModeA ); |
|
182 MCR::iMem.Modify( *this, KClearNone, MCR::TCR_TLR::KOn ); |
|
183 FCR::iMem.Write( *this, FCR::FIFO_EN::KOn |
|
184 bitor FCR::RX_FIFO_CLEAR::KOn |
|
185 bitor FCR::TX_FIFO_CLEAR::KOn ); |
|
186 LCR::iMem.Write( *this, LCR::KConfigModeB ); |
|
187 EFR::iMem.Modify( *this, EFR::ENHANCED_EN::KOn, KSetNone ); |
|
188 LCR::iMem.Write( *this, LCR::KConfigModeA ); |
|
189 MCR::iMem.Modify( *this, MCR::TCR_TLR::KOn, KSetNone ); |
|
190 LCR::iMem.Write( *this, LCR::KConfigModeOperational ); |
|
191 } |
|
192 |
|
193 EXPORT_C TInt TUart::InterruptId() const |
|
194 { |
|
195 return KHwInfo[ iUartNumber ].iInterruptId; |
|
196 } |
|
197 |
|
198 EXPORT_C Prcm::TClock TUart::PrcmInterfaceClk() const |
|
199 { |
|
200 return KHwInfo[ iUartNumber ].iInterfaceClock; |
|
201 } |
|
202 |
|
203 EXPORT_C Prcm::TClock TUart::PrcmFunctionClk() const |
|
204 { |
|
205 return KHwInfo[ iUartNumber ].iFunctionClock; |
|
206 } |
|
207 |
|
208 /*PORT_C TInt TUart::PrmInterfaceClk() const |
|
209 { |
|
210 return KHwInfo[ iUartNumber ].iPrmInterfaceClock; |
|
211 } |
|
212 |
|
213 EXPORT_C TInt TUart::PrmFunctionClk() const |
|
214 { |
|
215 return KHwInfo[ iUartNumber ].iPrmFunctionClock; |
|
216 } |
|
217 */ |
|
218 EXPORT_C void TUart::DefineMode( const TUartMode aMode ) |
|
219 { |
|
220 __ASSERT_DEBUG( (TUint)aMode <= KSupportedUartModes, ClientPanic( __LINE__ ) ); |
|
221 iMode = aMode; |
|
222 iTargetMode = KDefaultTargetMode[ aMode ]; |
|
223 } |
|
224 |
|
225 EXPORT_C void TUart::Enable() |
|
226 { |
|
227 // UART won't be enabled if a read-write cycle is done to MDR1 |
|
228 // So just write the mode into MDR1 and clear anythis already in register |
|
229 // MDR1::iMem.Modify( *this, MDR1::MODE_SELECT::KFieldMask, iTargetMode ); |
|
230 MDR1::iMem.Write( *this, iTargetMode ); |
|
231 } |
|
232 |
|
233 EXPORT_C void TUart::Disable() |
|
234 { |
|
235 MDR1::iMem.Modify( *this, MDR1::MODE_SELECT::KFieldMask, MDR1::MODE_SELECT::EDisable ); |
|
236 } |
|
237 |
|
238 EXPORT_C void TUart::SetBaud( const TBaud aBaud ) |
|
239 { |
|
240 __ASSERT_DEBUG( (TUint)aBaud < KSupportedBaudCount, ClientPanic( __LINE__ ) ); |
|
241 |
|
242 const TUint dlh = KBaudControl[ aBaud ][ iMode ].iDlh; |
|
243 const TUint dll = KBaudControl[ aBaud ][ iMode ].iDll; |
|
244 |
|
245 { |
|
246 TRaiiEnhancedModeB enhanced_mode_b_in_current_scope( *this ); |
|
247 |
|
248 LCR::iMem.Write( *this, LCR::KConfigModeOperational ); |
|
249 const TUint8 ier = IER::iMem.Read( *this ); |
|
250 IER::iMem.Write( *this, 0 ); |
|
251 LCR::iMem.Write( *this, LCR::KConfigModeB ); |
|
252 |
|
253 DLL::iMem.Write( *this, dll ); |
|
254 DLH::iMem.Write( *this, dlh ); |
|
255 |
|
256 LCR::iMem.Write( *this, LCR::KConfigModeOperational ); |
|
257 IER::iMem.Write( *this, ier ); |
|
258 LCR::iMem.Write( *this, LCR::KConfigModeB ); |
|
259 } |
|
260 |
|
261 // Update target mode if a multipler change is required |
|
262 if( EUart == iMode ) |
|
263 { |
|
264 const TUint m = KBaudControl[ aBaud ][ iMode ].iMultiplier; |
|
265 if( 13 == m ) |
|
266 { |
|
267 iTargetMode = MDR1::MODE_SELECT::EUart13x; |
|
268 } |
|
269 else |
|
270 { |
|
271 iTargetMode = MDR1::MODE_SELECT::EUart16x; |
|
272 } |
|
273 } |
|
274 } |
|
275 |
|
276 EXPORT_C void TUart::SetDataFormat( const TDataBits aDataBits, const TStopBits aStopBits, const TParity aParity ) |
|
277 { |
|
278 __ASSERT_DEBUG( (TUint)aDataBits <= E8Data, ClientPanic( __LINE__ ) ); |
|
279 __ASSERT_DEBUG( (TUint)aStopBits <= E2Stop, ClientPanic( __LINE__ ) ); |
|
280 __ASSERT_DEBUG( (TUint)aParity <= ESpace, ClientPanic( __LINE__ ) ); |
|
281 |
|
282 const TRegValue8 lcrSet = aDataBits bitor aStopBits bitor KParitySelectTable[ aParity ]; |
|
283 const TRegValue8 KClearMask = LCR::PARITY_TYPE2::KFieldMask |
|
284 bitor LCR::PARITY_TYPE1::KFieldMask |
|
285 bitor LCR::PARITY_EN::KFieldMask |
|
286 bitor LCR::NB_STOP::KFieldMask |
|
287 bitor LCR::CHAR_LENGTH::KFieldMask; |
|
288 |
|
289 LCR::iMem.Modify( *this, KClearMask, lcrSet ); |
|
290 |
|
291 } |
|
292 |
|
293 EXPORT_C void TUart::EnableFifo( const TEnableState aState, const TFifoTrigger aRxTrigger, const TFifoTrigger aTxTrigger ) |
|
294 { |
|
295 TRaiiEnhancedModeB enhanced_mode_b_in_current_scope( *this ); |
|
296 |
|
297 const TUint8 dll = DLL::iMem.Read( *this ); |
|
298 const TUint8 dlh = DLH::iMem.Read( *this ); |
|
299 |
|
300 DLL::iMem.Write( *this, 0 ); |
|
301 DLH::iMem.Write( *this, 0 ); |
|
302 |
|
303 const TUint8 rx_trig = ((TUint)aRxTrigger >= ETriggerUnchanged) |
|
304 ? 0 |
|
305 : KRxFifoTrigTable[ aRxTrigger ]; |
|
306 const TUint8 tx_trig = ((TUint)aTxTrigger >= ETriggerUnchanged) |
|
307 ? 0 |
|
308 : KTxFifoTrigTable[ aTxTrigger ]; |
|
309 const TUint8 KClearMask = TUint8(Omap3530Uart::FCR::RX_FIFO_TRIG::KFieldMask bitor Omap3530Uart::FCR::TX_FIFO_TRIG::KFieldMask); |
|
310 |
|
311 if( EEnabled == aState ) |
|
312 { |
|
313 FCR::iMem.Modify( *this, |
|
314 KClearMask, |
|
315 rx_trig bitor tx_trig bitor FCR::FIFO_EN::KOn ); |
|
316 } |
|
317 else |
|
318 { |
|
319 FCR::iMem.Modify( *this, FCR::FIFO_EN::KOn, KSetNone ); |
|
320 } |
|
321 |
|
322 DLL::iMem.Write( *this, dll ); |
|
323 DLH::iMem.Write( *this, dlh ); |
|
324 } |
|
325 |
|
326 |
|
327 LOCAL_C void ModifyIER( TUart& aUart, TUint8 aClearMask, TUint8 aSetMask ) |
|
328 { |
|
329 TRaiiEnhancedModeB enhanced_mode_b_in_current_scope( aUart ); |
|
330 |
|
331 LCR::iMem.Write( aUart, Omap3530Uart::LCR::KConfigModeOperational ); |
|
332 IER::iMem.Modify( aUart, aClearMask, aSetMask ); |
|
333 LCR::iMem.Write( aUart, LCR::KConfigModeB ); |
|
334 } |
|
335 |
|
336 inline void EnableDisableInterrupt( TUart& aUart, TBool aEnable, TUart::TInterrupt aWhich ) |
|
337 { |
|
338 ModifyIER( aUart, |
|
339 (aEnable ? KClearNone : (TUint8)1 << aWhich), |
|
340 (aEnable ? (TUint8)1 << aWhich : KSetNone) ); |
|
341 } |
|
342 |
|
343 EXPORT_C void TUart::EnableInterrupt( const TInterrupt aWhich ) |
|
344 { |
|
345 EnableDisableInterrupt( *this, ETrue, aWhich ); |
|
346 } |
|
347 |
|
348 EXPORT_C void TUart::DisableInterrupt( const TInterrupt aWhich ) |
|
349 { |
|
350 EnableDisableInterrupt( *this, EFalse, aWhich ); |
|
351 } |
|
352 |
|
353 |
|
354 EXPORT_C void TUart::DisableAllInterrupts() |
|
355 { |
|
356 ModifyIER( *this, (TUint8)KClearAll, KSetNone ); |
|
357 } |
|
358 |
|
359 |
|
360 } // namespace Omap3530Uart |
|
361 |
|
362 |
|
363 DECLARE_STANDARD_EXTENSION() |
|
364 { |
|
365 return KErrNone; |
|
366 } |
|
367 |