1 /**************************************************************************//**
2 * @file sc.c
3 * @version V3.00
4 * @brief M480 Smartcard(SC) driver source file
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 * @copyright (C) 2016-2020 Nuvoton Technology Corp. All rights reserved.
8 *****************************************************************************/
9 #include "NuMicro.h"
10
11 /* Below are variables used locally by SC driver and does not want to parse by doxygen unless HIDDEN_SYMBOLS is defined */
12 /** @cond HIDDEN_SYMBOLS */
13 static uint32_t u32CardStateIgnore[SC_INTERFACE_NUM] = {0UL, 0UL, 0UL};
14
15 /** @endcond HIDDEN_SYMBOLS */
16
17 /** @addtogroup Standard_Driver Standard Driver
18 @{
19 */
20
21 /** @addtogroup SC_Driver SC Driver
22 @{
23 */
24
25 /** @addtogroup SC_EXPORTED_FUNCTIONS SC Exported Functions
26 @{
27 */
28
29 /**
30 * @brief This function indicates specified smartcard slot status
31 * @param[in] sc Base address of smartcard module
32 * @return Card insert status
33 * @retval TRUE Card insert
34 * @retval FALSE Card remove
35 */
SC_IsCardInserted(SC_T * sc)36 uint32_t SC_IsCardInserted(SC_T *sc)
37 {
38 uint32_t ret;
39 /* put conditions into two variable to remove IAR compilation warning */
40 uint32_t cond1 = ((sc->STATUS & SC_STATUS_CDPINSTS_Msk) >> SC_STATUS_CDPINSTS_Pos);
41 uint32_t cond2 = ((sc->CTL & SC_CTL_CDLV_Msk) >> SC_CTL_CDLV_Pos);
42
43 if((sc == SC0) && (u32CardStateIgnore[0] == 1UL))
44 {
45 ret = (uint32_t)TRUE;
46 }
47 else if((sc == SC1) && (u32CardStateIgnore[1] == 1UL))
48 {
49 ret = (uint32_t)TRUE;
50 }
51 else if((sc == SC2) && (u32CardStateIgnore[2] == 1UL))
52 {
53 ret = (uint32_t)TRUE;
54 }
55 else if(cond1 != cond2)
56 {
57 ret = (uint32_t)FALSE;
58 }
59 else
60 {
61 ret = (uint32_t)TRUE;
62 }
63 return ret;
64 }
65
66 /**
67 * @brief This function reset both transmit and receive FIFO of specified smartcard module
68 * @param[in] sc Base address of smartcard module
69 * @return None
70 */
SC_ClearFIFO(SC_T * sc)71 void SC_ClearFIFO(SC_T *sc)
72 {
73 while(sc->ALTCTL & SC_ALTCTL_SYNC_Msk)
74 {
75 ;
76 }
77 sc->ALTCTL |= (SC_ALTCTL_TXRST_Msk | SC_ALTCTL_RXRST_Msk);
78 }
79
80 /**
81 * @brief This function disable specified smartcard module
82 * @param[in] sc Base address of smartcard module
83 * @return None
84 */
SC_Close(SC_T * sc)85 void SC_Close(SC_T *sc)
86 {
87 sc->INTEN = 0UL;
88 while(sc->PINCTL & SC_PINCTL_SYNC_Msk)
89 {
90 ;
91 }
92 sc->PINCTL = 0UL;
93 sc->ALTCTL = 0UL;
94 while(sc->CTL & SC_CTL_SYNC_Msk)
95 {
96 ;
97 }
98 sc->CTL = 0UL;
99 }
100
101 /**
102 * @brief This function initialized smartcard module
103 * @param[in] sc Base address of smartcard module
104 * @param[in] u32CardDet Card detect polarity, select the CD pin state which indicates card absent. Could be
105 * -\ref SC_PIN_STATE_HIGH
106 * -\ref SC_PIN_STATE_LOW
107 * -\ref SC_PIN_STATE_IGNORE, no card detect pin, always assumes card present
108 * @param[in] u32PWR Power on polarity, select the PWR pin state which could set smartcard VCC to high level. Could be
109 * -\ref SC_PIN_STATE_HIGH
110 * -\ref SC_PIN_STATE_LOW
111 * @return None
112 */
SC_Open(SC_T * sc,uint32_t u32CardDet,uint32_t u32PWR)113 void SC_Open(SC_T *sc, uint32_t u32CardDet, uint32_t u32PWR)
114 {
115 uint32_t u32Reg = 0UL, u32Intf;
116
117 if(sc == SC0)
118 {
119 u32Intf = 0UL;
120 }
121 else if(sc == SC1)
122 {
123 u32Intf = 1UL;
124 }
125 else
126 {
127 u32Intf = 2UL;
128 }
129
130 if(u32CardDet != SC_PIN_STATE_IGNORE)
131 {
132 u32Reg = u32CardDet ? 0UL: SC_CTL_CDLV_Msk;
133 u32CardStateIgnore[u32Intf] = 0UL;
134 }
135 else
136 {
137 u32CardStateIgnore[u32Intf] = 1UL;
138 }
139 sc->PINCTL = u32PWR ? 0UL : SC_PINCTL_PWRINV_Msk;
140 while(sc->CTL & SC_CTL_SYNC_Msk)
141 {
142 ;
143 }
144 sc->CTL = SC_CTL_SCEN_Msk | SC_CTL_TMRSEL_Msk | u32Reg;
145 }
146
147 /**
148 * @brief This function reset specified smartcard module to its default state for activate smartcard
149 * @param[in] sc Base address of smartcard module
150 * @return None
151 */
SC_ResetReader(SC_T * sc)152 void SC_ResetReader(SC_T *sc)
153 {
154 uint32_t u32Intf;
155
156 if(sc == SC0)
157 {
158 u32Intf = 0UL;
159 }
160 else if(sc == SC1)
161 {
162 u32Intf = 1UL;
163 }
164 else
165 {
166 u32Intf = 2UL;
167 }
168
169 /* Reset FIFO, enable auto de-activation while card removal */
170 sc->ALTCTL |= (SC_ALTCTL_TXRST_Msk | SC_ALTCTL_RXRST_Msk | SC_ALTCTL_ADACEN_Msk);
171 /* Set Rx trigger level to 1 character, longest card detect debounce period, disable error retry (EMV ATR does not use error retry) */
172 while(sc->CTL & SC_CTL_SYNC_Msk)
173 {
174 ;
175 }
176 sc->CTL &= ~(SC_CTL_RXTRGLV_Msk |
177 SC_CTL_CDDBSEL_Msk |
178 SC_CTL_TXRTY_Msk |
179 SC_CTL_TXRTYEN_Msk |
180 SC_CTL_RXRTY_Msk |
181 SC_CTL_RXRTYEN_Msk);
182 while(sc->CTL & SC_CTL_SYNC_Msk)
183 {
184 ;
185 }
186 /* Enable auto convention, and all three smartcard internal timers */
187 sc->CTL |= SC_CTL_AUTOCEN_Msk | SC_CTL_TMRSEL_Msk;
188 /* Disable Rx timeout */
189 sc->RXTOUT = 0UL;
190 /* 372 clocks per ETU by default */
191 sc->ETUCTL= 371UL;
192
193
194 /* Enable necessary interrupt for smartcard operation */
195 if(u32CardStateIgnore[u32Intf]) /* Do not enable card detect interrupt if card present state ignore */
196 {
197 sc->INTEN = (SC_INTEN_RDAIEN_Msk |
198 SC_INTEN_TERRIEN_Msk |
199 SC_INTEN_TMR0IEN_Msk |
200 SC_INTEN_TMR1IEN_Msk |
201 SC_INTEN_TMR2IEN_Msk |
202 SC_INTEN_BGTIEN_Msk |
203 SC_INTEN_ACERRIEN_Msk);
204 }
205 else
206 {
207 sc->INTEN = (SC_INTEN_RDAIEN_Msk |
208 SC_INTEN_TERRIEN_Msk |
209 SC_INTEN_TMR0IEN_Msk |
210 SC_INTEN_TMR1IEN_Msk |
211 SC_INTEN_TMR2IEN_Msk |
212 SC_INTEN_BGTIEN_Msk |
213 SC_INTEN_CDIEN_Msk |
214 SC_INTEN_ACERRIEN_Msk);
215 }
216 return;
217 }
218
219 /**
220 * @brief This function block guard time (BGT) of specified smartcard module
221 * @param[in] sc Base address of smartcard module
222 * @param[in] u32BGT Block guard time using ETU as unit, valid range are between 1 ~ 32
223 * @return None
224 */
SC_SetBlockGuardTime(SC_T * sc,uint32_t u32BGT)225 void SC_SetBlockGuardTime(SC_T *sc, uint32_t u32BGT)
226 {
227 sc->CTL = (sc->CTL & ~SC_CTL_BGT_Msk) | ((u32BGT - 1UL) << SC_CTL_BGT_Pos);
228 }
229
230 /**
231 * @brief This function character guard time (CGT) of specified smartcard module
232 * @param[in] sc Base address of smartcard module
233 * @param[in] u32CGT Character guard time using ETU as unit, valid range are between 11 ~ 267
234 * @return None
235 */
SC_SetCharGuardTime(SC_T * sc,uint32_t u32CGT)236 void SC_SetCharGuardTime(SC_T *sc, uint32_t u32CGT)
237 {
238 u32CGT -= sc->CTL & SC_CTL_NSB_Msk ? 11UL: 12UL;
239 sc->EGT = u32CGT;
240 }
241
242 /**
243 * @brief This function stop all smartcard timer of specified smartcard module
244 * @param[in] sc Base address of smartcard module
245 * @return None
246 * @note This function stop the timers within smartcard module, \b not timer module
247 */
SC_StopAllTimer(SC_T * sc)248 void SC_StopAllTimer(SC_T *sc)
249 {
250 while(sc->ALTCTL & SC_ALTCTL_SYNC_Msk)
251 {
252 ;
253 }
254 sc->ALTCTL &= ~(SC_ALTCTL_CNTEN0_Msk | SC_ALTCTL_CNTEN1_Msk | SC_ALTCTL_CNTEN2_Msk);
255 }
256
257 /**
258 * @brief This function configure and start a smartcard timer of specified smartcard module
259 * @param[in] sc Base address of smartcard module
260 * @param[in] u32TimerNum Timer to start. Valid values are 0, 1, 2.
261 * @param[in] u32Mode Timer operating mode, valid values are:
262 * - \ref SC_TMR_MODE_0
263 * - \ref SC_TMR_MODE_1
264 * - \ref SC_TMR_MODE_2
265 * - \ref SC_TMR_MODE_3
266 * - \ref SC_TMR_MODE_4
267 * - \ref SC_TMR_MODE_5
268 * - \ref SC_TMR_MODE_6
269 * - \ref SC_TMR_MODE_7
270 * - \ref SC_TMR_MODE_8
271 * - \ref SC_TMR_MODE_F
272 * @param[in] u32ETUCount Timer timeout duration, ETU based. For timer 0, valid range are between 1~0x1000000ETUs.
273 * For timer 1 and timer 2, valid range are between 1 ~ 0x100 ETUs
274 * @return None
275 * @note This function start the timer within smartcard module, \b not timer module
276 * @note Depend on the timer operating mode, timer may not start counting immediately
277 */
SC_StartTimer(SC_T * sc,uint32_t u32TimerNum,uint32_t u32Mode,uint32_t u32ETUCount)278 void SC_StartTimer(SC_T *sc, uint32_t u32TimerNum, uint32_t u32Mode, uint32_t u32ETUCount)
279 {
280 uint32_t reg = u32Mode | (SC_TMRCTL0_CNT_Msk & (u32ETUCount - 1UL));
281 while(sc->ALTCTL & SC_ALTCTL_SYNC_Msk)
282 {
283 ;
284 }
285 if(u32TimerNum == 0UL)
286 {
287 while(sc->TMRCTL0 & SC_TMRCTL0_SYNC_Msk)
288 {
289 ;
290 }
291 sc->TMRCTL0 = reg;
292 sc->ALTCTL |= SC_ALTCTL_CNTEN0_Msk;
293 }
294 else if(u32TimerNum == 1UL)
295 {
296 while(sc->TMRCTL1 & SC_TMRCTL1_SYNC_Msk)
297 {
298 ;
299 }
300 sc->TMRCTL1 = reg;
301 sc->ALTCTL |= SC_ALTCTL_CNTEN1_Msk;
302 }
303 else /* timer 2 */
304 {
305 while(sc->TMRCTL2 & SC_TMRCTL2_SYNC_Msk)
306 {
307 ;
308 }
309 sc->TMRCTL2 = reg;
310 sc->ALTCTL |= SC_ALTCTL_CNTEN2_Msk;
311 }
312 }
313
314 /**
315 * @brief This function stop a smartcard timer of specified smartcard module
316 * @param[in] sc Base address of smartcard module
317 * @param[in] u32TimerNum Timer to stop. Valid values are 0, 1, 2.
318 * @return None
319 * @note This function stop the timer within smartcard module, \b not timer module
320 */
SC_StopTimer(SC_T * sc,uint32_t u32TimerNum)321 void SC_StopTimer(SC_T *sc, uint32_t u32TimerNum)
322 {
323 while(sc->ALTCTL & SC_ALTCTL_SYNC_Msk)
324 {
325 ;
326 }
327 if(u32TimerNum == 0UL)
328 {
329 sc->ALTCTL &= ~SC_ALTCTL_CNTEN0_Msk;
330 }
331 else if(u32TimerNum == 1UL)
332 {
333 sc->ALTCTL &= ~SC_ALTCTL_CNTEN1_Msk;
334 }
335 else /* timer 2 */
336 {
337 sc->ALTCTL &= ~SC_ALTCTL_CNTEN2_Msk;
338 }
339 }
340
341 /**
342 * @brief This function gets smartcard clock frequency.
343 * @param[in] sc Base address of smartcard module
344 * @return Smartcard frequency in kHz
345 */
SC_GetInterfaceClock(SC_T * sc)346 uint32_t SC_GetInterfaceClock(SC_T *sc)
347 {
348 uint32_t u32ClkSrc, u32Num, u32Clk;
349
350 if(sc == SC0)
351 {
352 u32Num = 0UL;
353 }
354 else if(sc == SC1)
355 {
356 u32Num = 1UL;
357 }
358 else
359 {
360 u32Num = 2UL;
361 }
362
363 u32ClkSrc = (CLK->CLKSEL3 >> (2UL * u32Num)) & CLK_CLKSEL3_SC0SEL_Msk;
364
365 /* Get smartcard module clock */
366 if(u32ClkSrc == 0UL)
367 {
368 u32Clk = __HXT;
369 }
370 else if(u32ClkSrc == 1UL)
371 {
372 u32Clk = CLK_GetPLLClockFreq();
373 }
374 else if(u32ClkSrc == 2UL)
375 {
376 if(u32Num == 1UL)
377 {
378 u32Clk = CLK_GetPCLK1Freq();
379 }
380 else
381 {
382 u32Clk = CLK_GetPCLK0Freq();
383 }
384 }
385 else
386 {
387 u32Clk = __HIRC;
388 }
389
390 u32Clk /= (((CLK->CLKDIV1 >> (8UL * u32Num)) & CLK_CLKDIV1_SC0DIV_Msk) + 1UL) * 1000UL;
391 return u32Clk;
392 }
393
394 /*@}*/ /* end of group SC_EXPORTED_FUNCTIONS */
395
396 /*@}*/ /* end of group SC_Driver */
397
398 /*@}*/ /* end of group Standard_Driver */
399
400 /*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/
401