1 /*
2 * Copyright (c) 2022 Winner Microelectronics Co., Ltd. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 /****************************************************************************
17 * @file wm_i2s.c
18 * @author
19 * @version
20 * @date
21 * @brief
22 *
23 * Copyright (c) 2014 Winner Microelectronics Co., Ltd. All rights reserved.
24 *****************************************************************************/
25
26 #include <stdbool.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include "wm_regs.h"
30 #include "wm_gpio.h"
31 #include "wm_uart.h"
32 #include "wm_cpu.h"
33 #include "wm_7816.h"
34
35 #include "wm_osal.h"
36
37 #define DEBUG_7816 1
38
39 #if DEBUG_7816
40 #define PRINT_DEBUG(fmt, args...) do {(printf("[DEBUG] "), printf(fmt, ##args));}while (0)
41 #else
42 #define PRINT_DEBUG(fmt, args...)
43 #endif
44
45 #define SYS_CLK (40000000)
46 #define WM_SC_RST_PIN WM_IO_PB_23 // (23)
47 #define WM_SC_PWR_PIN WM_IO_PB_24 // (29)
48
49 sc_io_map sc_io;
50
51 /**
52 * @brief
53 * This function is used to config the pin in gpio or 7816 mode for the 7816 power on timing
54 * @param[in] mode : 1--gpio mode ; 0--7816 mode
55 * @retval
56 */
wm_sc_io_clk_config(uint8_t mode)57 void wm_sc_io_clk_config(uint8_t mode)
58 {
59 if (sc_io.initialed == 0) {
60 printf("error : 7816 io map must init....\r\n");
61 return ;
62 }
63 if (mode) { // gpio mode
64 tls_io_cfg_set(sc_io.clk_pin_num, WM_IO_OPTION5);
65 tls_io_cfg_set(sc_io.io_pin_num, WM_IO_OPTION5);
66 tls_gpio_cfg(sc_io.clk_pin_num, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
67 tls_gpio_cfg(sc_io.io_pin_num, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
68 } else { // 7816 mode
69 tls_io_cfg_set(sc_io.clk_pin_num, sc_io.clk_opt);
70 tls_io_cfg_set(sc_io.io_pin_num, sc_io.io_opt);
71 }
72 }
73
74 /**
75 * @brief
76 * This function is used to config the block guard time param in 7816 mode
77 * @param[in] bgt : the value of blcok guard time will be set
78 * @retval
79 */
wm_sc_set_bgt(uint8_t bgt)80 void wm_sc_set_bgt(uint8_t bgt)
81 {
82 uint32_t reg;
83 bgt = (bgt > 0x1f) ? 0x1F : bgt;
84 reg = tls_reg_read32(HR_UART2_LINE_CTRL);
85 reg &= ~(0x1f << 11);
86 reg |= (bgt << 11);
87 tls_reg_write32(HR_UART2_LINE_CTRL, reg);
88 }
89
90 /**
91 * @brief
92 * This function is used to config the tx retry count when detect err signal
93 * @param[in] count : the value of retry time will be set 7 for max
94 * @retval
95 */
wm_sc_tx_retry_times(uint8_t count)96 void wm_sc_tx_retry_times(uint8_t count)
97 {
98 uint32_t reg;
99 reg = tls_reg_read32(HR_UART2_LINE_CTRL);
100 reg &= ~(0x7 << 16);
101 tls_reg_write32(HR_UART2_LINE_CTRL, reg|(count<<16));
102 tls_bitband_write(HR_UART2_LINE_CTRL, 23, 1);
103 }
104
105 /**
106 * @brief
107 * This function is used to config the rx retry count when detect parity error
108 * @param[in] count : the value of retry time will be set 7 for max
109 * @retval
110 */
wm_sc_rx_retry_times(uint8_t count)111 void wm_sc_rx_retry_times(uint8_t count)
112 {
113 uint32_t reg;
114 reg = tls_reg_read32(HR_UART2_LINE_CTRL);
115 reg &= ~(0x7 << 20);
116 tls_reg_write32(HR_UART2_LINE_CTRL, reg|(count<<20));
117 tls_bitband_write(HR_UART2_LINE_CTRL, 19, 1);
118 }
119
120 /**
121 * @brief
122 * This function is used to config the etu param
123 * @param[in] etu : the value of etu will be set
124 * @retval
125 */
wm_sc_set_etu(uint16_t etu)126 void wm_sc_set_etu(uint16_t etu)
127 {
128 uint32_t reg;
129
130 reg = tls_reg_read32(HR_UART2_BAUD_RATE_CTRL);
131 reg &= ~ 0xFFFF;
132 reg |= etu;
133 tls_reg_write32(HR_UART2_BAUD_RATE_CTRL, reg);
134 }
135
136 /**
137 * @brief
138 * This function config the module clock freq
139 * @param[in] freq : the value of clock freq
140 * @retval
141 */
wm_sc_set_frequency(uint32_t freq)142 void wm_sc_set_frequency(uint32_t freq)
143 {
144 uint32_t reg;
145 uint8_t div;
146 tls_sys_clk clk;
147
148 tls_sys_clk_get(&clk);
149
150 div = (clk.apbclk * 1000000 + freq)/(2 * freq) - 1;
151
152 reg = tls_reg_read32(HR_UART2_BAUD_RATE_CTRL);
153 reg &= ~ 0x3F0000;
154 reg |= (div<<16);
155 tls_reg_write32(HR_UART2_BAUD_RATE_CTRL, reg);
156 }
157
158 /**
159 * @brief
160 * close af to use PB23 and PB24(uart2_rx as default if af is on) as gpio
161 * @retval
162 */
wm_sc_powerInit(void)163 void wm_sc_powerInit(void)
164 {
165 #ifdef WM_SC_PWR_PIN
166 tls_gpio_cfg(WM_SC_RST_PIN, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
167 tls_gpio_cfg(WM_SC_PWR_PIN, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
168 #endif
169 }
170
171 /**
172 * @brief
173 * power on the 7816 device if power is controled by GPIO
174 * @retval
175 */
wm_sc_poweron(void)176 void wm_sc_poweron(void)
177 {
178 #ifdef WM_SC_PWR_PIN
179 tls_gpio_cfg(WM_SC_PWR_PIN, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
180 tls_gpio_write(WM_SC_PWR_PIN, 1);
181 #endif
182 }
183
184 /**
185 * @brief
186 * power off the 7816 device if power is controled by GPIO
187 * @retval
188 */
wm_sc_poweroff(void)189 void wm_sc_poweroff(void)
190 {
191 #ifdef WM_SC_PWR_PIN
192 tls_gpio_cfg(WM_SC_PWR_PIN, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
193 tls_gpio_write(WM_SC_PWR_PIN, 0);
194 #endif
195 }
196
197 /**
198 * @brief
199 * driver the reset gpio in low level
200 * @retval
201 */
wm_sc_rst_low(void)202 void wm_sc_rst_low(void)
203 {
204 #ifdef WM_SC_RST_PIN
205 tls_gpio_cfg(WM_SC_RST_PIN, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
206 tls_gpio_write(WM_SC_RST_PIN, 0);
207 #endif
208 }
209
210 /**
211 * @brief
212 * driver the reset gpio in high level
213 * @retval
214 */
wm_sc_rst_high(void)215 void wm_sc_rst_high(void)
216 {
217 #ifdef WM_SC_RST_PIN
218 tls_gpio_cfg(WM_SC_RST_PIN, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
219 tls_gpio_write(WM_SC_RST_PIN, 1);
220 #endif
221 }
222
223 /**
224 * @brief
225 * hotrest the 7816 device obey the 7816-3 timing
226 * @retval
227 */
wm_sc_hotreset(void)228 void wm_sc_hotreset(void)
229 {
230 uint32_t delay = 0xffff;
231
232 /* set the rst pin to low */
233 wm_sc_rst_low();
234 /* delay */
235 while (delay--);
236 /* set f/d to default 372 */
237 wm_sc_set_etu(WM_SC_DEFAULT_FD);
238 /* set the rst pin to high */
239 wm_sc_rst_high();
240 }
241
242 /**
243 * @brief
244 * colreset the 7816 device obey the 7816-3 timing
245 * @retval
246 */
wm_sc_colreset(void)247 void wm_sc_colreset(void)
248 {
249 /* power down */
250 wm_sc_poweroff();
251 /* select the clk io in gpio mode */
252 wm_sc_io_clk_config(1);
253 /* reset the clk pin */
254 tls_gpio_write(sc_io.clk_pin_num, 0);
255 /* reset the io pin */
256 tls_gpio_write(sc_io.io_pin_num, 0);
257 /* set the ret pin to low */
258 wm_sc_rst_low();
259 /* power on the card */
260 wm_sc_poweron();
261 /* config the model in 7816 mode */
262 wm_sc_7816_mode(1);
263 /* select the clk io pin in 7816 mode */
264 wm_sc_io_clk_config(0);
265 /* config the output clock freq */
266 wm_sc_set_frequency(5000000);
267 /* set the F/D to default (372) */
268 wm_sc_set_etu(WM_SC_DEFAULT_FD);
269 /* set the rst pin to high */
270 wm_sc_rst_high();
271 }
272
273 /**
274 * @brief
275 * deactive the 7816 device obey the 7816-3 timing
276 * @retval
277 */
wm_sc_deactive(void)278 void wm_sc_deactive(void)
279 {
280 /* set the rst pin in low level */
281 wm_sc_rst_low();
282 /* select the clk and io pin to 7816 mode */
283 wm_sc_io_clk_config(0);
284 /* disable the output clock */
285 wm_sc_clk_enable(0);
286 /* select the clk and io pin to gpio mode */
287 wm_sc_io_clk_config(1);
288 /* set the clk pin to low */
289 tls_gpio_write(sc_io.clk_pin_num, 0);
290 /* set the io pin to low */
291 tls_gpio_write(sc_io.io_pin_num, 0);
292 /* set the power pin to low */
293 wm_sc_poweroff();
294 }