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_pwm.c
18 *
19 * @brief pwm driver module
20 *
21 * @author dave
22 *
23 * Copyright (c) 2014 Winner Microelectronics Co., Ltd.
24 */
25 #include <string.h>
26
27 #include "wm_debug.h"
28 #include "wm_regs.h"
29 #include "wm_irq.h"
30 #include "wm_gpio.h"
31 #include "wm_cpu.h"
32 #include "tls_common.h"
33 #include "wm_pwm.h"
34
35 typedef void (*pwm_irq_callback)(void);
36 static pwm_irq_callback pwm_callback;
37
PWM_IRQHandler(void)38 ATTRIBUTE_ISR void PWM_IRQHandler(void)
39 {
40 csi_kernel_intrpt_enter();
41 if (pwm_callback) {
42 pwm_callback();
43 }
44 csi_kernel_intrpt_exit();
45 }
46
47 /**
48 * @brief This function is used to register the pwm interrupt callback function
49 *
50 * @param[in] callback the pwm interrupt callback function
51 *
52 * @return None
53 *
54 * @note None
55 */
tls_pwm_isr_register(void (* callback)(void))56 void tls_pwm_isr_register(void (*callback)(void))
57 {
58 pwm_callback = callback;
59 tls_irq_enable(PWM_IRQn);
60 }
61
62 /**
63 * @brief This function is used to set duty ratio
64 *
65 * @param[in] channel pwm channel NO.,range form 0 to 4
66 * @param[in] duty Number of active levels
67 *
68 * @retval WM_SUCCESS success
69 * @retval WM_FAILED failed
70 *
71 * @note None
72 */
tls_pwm_duty_config(u8 channel,u8 duty)73 int tls_pwm_duty_config(u8 channel, u8 duty)
74 {
75 u32 temp = 0;
76
77 if (channel > (PWM_CHANNEL_MAX_NUM - 1)) {
78 TLS_DBGPRT_ERR("duty param err\n");
79 return WM_FAILED;
80 }
81
82 if (duty == 0) {
83 tls_pwm_stop(channel);
84 return WM_SUCCESS;
85 }
86
87 if (channel == 4) {
88 temp = tls_reg_read32(HR_PWM_CH4_REG2) & ~0x0000FF00;
89 temp |= (duty << 8);
90 tls_reg_write32(HR_PWM_CH4_REG2, temp); /* duty radio */
91 } else {
92 temp = tls_reg_read32(HR_PWM_CMPDAT) & ~(0xFF << (channel * 8));
93 temp |= (duty << (channel * 8));
94 tls_reg_write32(HR_PWM_CMPDAT, temp); /* duty radio */
95 }
96
97 return WM_SUCCESS;
98 }
99
100 /**
101 * @brief This function is used to set frequency
102 *
103 * @param[in] channel pwm channel NO., range form 0 to 4
104 * @param[in] clkdiv clock divider, range 0 to 65535
105 * @param[in] period the number of the counting clock cycle
106 *
107 * @retval WM_SUCCESS success
108 * @retval WM_FAILED failed
109 *
110 * @note None
111 */
tls_pwm_freq_config(u8 channel,u16 clkdiv,u8 period)112 int tls_pwm_freq_config(u8 channel, u16 clkdiv, u8 period)
113 {
114 u32 temp = 0;
115
116 if (channel > (PWM_CHANNEL_MAX_NUM - 1)) {
117 TLS_DBGPRT_ERR("freq param err\n");
118 return WM_FAILED;
119 }
120
121 if (channel == 4) {
122 temp = tls_reg_read32(HR_PWM_CH4_REG1) & ~0xFFFF0000;
123 temp |= (clkdiv << 16);
124 tls_reg_write32(HR_PWM_CH4_REG1, temp); /* clock divider */
125
126 temp = tls_reg_read32(HR_PWM_CH4_REG1) & ~0x0000FF00;
127 temp |= (period << 8);
128 tls_reg_write32(HR_PWM_CH4_REG1, temp); /* the number of the counting clock cycle */
129 } else {
130 temp = tls_reg_read32(HR_PWM_CLKDIV01 + (channel / 2) * 4) & ~(0xFFFF << ((channel % 2) * 16));
131 temp |= (clkdiv << ((channel % 2) * 16));
132 tls_reg_write32(HR_PWM_CLKDIV01 + (channel / 2) * 4, temp); /* clock divider */
133
134 temp = tls_reg_read32(HR_PWM_PERIOD) & ~(0xFF << (channel * 8));
135 temp |= (period << (channel * 8));
136 tls_reg_write32(HR_PWM_PERIOD, temp); /* the number of the counting clock cycle */
137 }
138
139 return WM_SUCCESS;
140 }
141
142 /**
143 * @brief This function is used to set the output mode
144 *
145 * @param[in] channel pwm channel NO.,range form 0 to 4
146 * @param[in] mode pwm work mode for signal generate
147 *
148 * @retval WM_SUCCESS success
149 * @retval WM_FAILED failed
150 *
151 * @note None
152 */
tls_pwm_out_mode_config(u8 channel,enum tls_pwm_out_mode mode)153 int tls_pwm_out_mode_config(u8 channel, enum tls_pwm_out_mode mode)
154 {
155 if (channel > (PWM_CHANNEL_MAX_NUM - 1))
156 return WM_FAILED;
157
158 if (WM_PWM_OUT_MODE_BRAKE == mode)
159 tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) | BIT(11 + channel)); /* the brake mode */
160 else if (WM_PWM_OUT_MODE_ALLSYC == mode) {
161 if (channel != 0)
162 return WM_FAILED;
163 tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) & ~0xF800); /* disable the brake mode */
164 /* enable the all synchronous mode mode */
165 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(6));
166 } else if (WM_PWM_OUT_MODE_2SYC == mode) {
167 if (channel != 0 && channel != 2) // 2:byte alignment
168 return WM_FAILED;
169 /* disable the brake mode */
170 tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) & ~(0x1800<<channel));
171 /* disable the all synchronous mode mode */
172 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & ~BIT(6));
173 /* enable the two channel synchronous mode */
174 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(14 + channel / 2));
175 } else if (WM_PWM_OUT_MODE_MC == mode) {
176 if (channel != 0 && channel != 2) // 2:byte alignment
177 return WM_FAILED;
178 /* disable the brake mode */
179 tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) & ~(0x1800<<channel));
180 /* disable the all synchronous mode mode */
181 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & ~BIT(6));
182 /* disable the two channel synchronous mode */
183 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & ~BIT(14 + channel / 2));
184 /* enable the complementary mode */
185 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(0 + channel / 2));
186 } else if (WM_PWM_OUT_MODE_INDPT == mode) {
187 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(6)));
188 if (channel != 4) { // 4:byte alignment
189 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(0 + channel / 2)));
190 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(14 + channel / 2)));
191 }
192 /* enable the independent mode */
193 tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) & (~BIT(11 + channel)));
194 } else
195 return WM_FAILED;
196
197 return WM_SUCCESS;
198 }
199
200 /**
201 * @brief This function is used to set the counting mode
202 *
203 * @param[in] channel pwm channel NO.,range form 0 to 4
204 * @param[in] cnt_type counting mode
205 *
206 * @retval WM_SUCCESS success
207 * @retval WM_FAILED failed
208 *
209 * @note None
210 */
tls_pwm_cnt_type_config(u8 channel,enum tls_pwm_cnt_type cnt_type)211 int tls_pwm_cnt_type_config(u8 channel, enum tls_pwm_cnt_type cnt_type)
212 {
213 if (channel > (PWM_CHANNEL_MAX_NUM - 1))
214 return WM_FAILED;
215
216 if (channel == 4) {
217 if (WM_PWM_CNT_TYPE_EDGE_ALLGN_CAP == cnt_type) {
218 tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(4)));
219 tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(3)));
220 }
221 if (WM_PWM_CNT_TYPE_EDGE_ALIGN_OUT == cnt_type) {
222 tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(4)));
223 tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) | BIT(3));
224 } else if (WM_PWM_CNT_TYPE_CENTER_ALIGN == cnt_type) {
225 tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) | BIT(4));
226 tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(3)));
227 }
228 } else {
229 if (WM_PWM_CNT_TYPE_EDGE_ALLGN_CAP == cnt_type && channel == 0) {
230 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(17)));
231 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(16)));
232 }
233 if (WM_PWM_CNT_TYPE_EDGE_ALIGN_OUT == cnt_type) {
234 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(17 + channel * 2)));
235 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(16 + channel * 2));
236 } else if (WM_PWM_CNT_TYPE_CENTER_ALIGN == cnt_type) {
237 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(17 + channel * 2));
238 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(16 + channel * 2)));
239 } else
240 return WM_FAILED;
241 }
242
243 return WM_SUCCESS;
244 }
245
246 /**
247 * @brief This function is used to set whether to loop
248 *
249 * @param[in] channel pwm channel NO.,range form 0 to 4
250 * @param[in] loop_mode whether to loop
251 *
252 * @retval WM_SUCCESS success
253 * @retval WM_FAILED failed
254 *
255 * @note None
256 */
tls_pwm_loop_mode_config(u8 channel,enum tls_pwm_loop_type loop_mode)257 int tls_pwm_loop_mode_config(u8 channel, enum tls_pwm_loop_type loop_mode)
258 {
259 if (channel > (PWM_CHANNEL_MAX_NUM - 1))
260 return WM_FAILED;
261
262 if (channel == 4) {
263 if (WM_PWM_LOOP_TYPE_LOOP == loop_mode)
264 tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) | BIT(1));
265 else
266 tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(1)));
267 } else {
268 if (WM_PWM_LOOP_TYPE_LOOP == loop_mode)
269 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(8 + channel));
270 else
271 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(8 + channel)));
272 }
273
274 return WM_SUCCESS;
275 }
276
277 /**
278 * @brief This function is used to set whether to inverse the output
279
280 *
281 * @param[in] channel pwm channel NO.,range form 0 to 4
282 * @param[in] en ENABLE or DISABLE
283 *
284 * @retval WM_SUCCESS success
285 * @retval WM_FAILED failed
286 *
287 * @note None
288 */
tls_pwm_out_inverse_cmd(u8 channel,bool en)289 int tls_pwm_out_inverse_cmd(u8 channel, bool en)
290 {
291 if (channel > (PWM_CHANNEL_MAX_NUM - 1))
292 return WM_FAILED;
293
294 if (channel == 4) {
295 if (ENABLE == en)
296 tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) | BIT(0));
297 else
298 tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(0)));
299 } else {
300 if (ENABLE == en)
301 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(2 + channel));
302 else
303 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(2 + channel)));
304 }
305
306 return WM_SUCCESS;
307 }
308
309 /**
310 * @brief This function is used to set the number of period to be generated
311 *
312 * @param[in] channel pwm channel NO.,range form 0 to 4
313 * @param[in] pnum the number of period to be generated,range from 0 to 255
314 *
315 * @retval WM_SUCCESS success
316 * @retval WM_FAILED failed
317 *
318 * @note None
319 */
tls_pwm_stoptime_by_period_config(u8 channel,u8 pnum)320 int tls_pwm_stoptime_by_period_config(u8 channel, u8 pnum)
321 {
322 u32 temp = 0;
323
324 if (channel > (PWM_CHANNEL_MAX_NUM - 1))
325 return WM_FAILED;
326
327 if (channel == 4) {
328 temp = tls_reg_read32(HR_PWM_CH4_REG1) & ~0x000000FF;
329 temp |= pnum;
330 tls_reg_write32(HR_PWM_CH4_REG1, temp);
331 } else {
332 temp = tls_reg_read32(HR_PWM_PNUM) & ~(0xFF << (channel * 8));
333 temp |= (pnum << (channel * 8));
334 tls_reg_write32(HR_PWM_PNUM, temp);
335 }
336 return WM_SUCCESS;
337 }
338
339 /**
340 * @brief This function is used to set output enable
341 *
342 * @param[in] channel pwm channel NO.,channel 0 or channel 4
343 * @param[in] en ENABLE or DISABLE
344 *
345 * @retval WM_SUCCESS success
346 * @retval WM_FAILED failed
347 *
348 * @note None
349 */
tls_pwm_output_en_cmd(u8 channel,bool en)350 int tls_pwm_output_en_cmd(u8 channel, bool en)
351 {
352 if (channel != 0 && channel != 4)
353 return WM_FAILED;
354
355 if (channel == 4) {
356 if (ENABLE == en)
357 tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(2)));
358 else
359 tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(2));
360 } else {
361 if (ENABLE == en)
362 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(12)));
363 else
364 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(12));
365 }
366
367 return WM_SUCCESS;
368 }
369
370 /**
371 * @brief This function is used to set the dead time
372 *
373 * @param[in] channel pwm channel NO.,channel 0 or channel 2
374 * @param[in] dten whether enalbe the deat time, ENABLE or DISABLE
375 * @param[in] dtclkdiv dead zone clock divider, range 0 to 3
376 * @param[in] dtcnt the number of the counting clock cycle, range 0 to 255
377 *
378 * @retval WM_SUCCESS success
379 * @retval WM_FAILED failed
380 *
381 * @note None
382 */
tls_pwm_deadzone_config(u8 channel,bool dten,u8 dtclkdiv,u8 dtcnt)383 int tls_pwm_deadzone_config(u8 channel, bool dten, u8 dtclkdiv, u8 dtcnt)
384 {
385 u32 temp = 0;
386
387 if ((channel !=0 && channel != 2) || dtclkdiv > 3)
388 return WM_FAILED;
389
390 if (ENABLE == dten) {
391 temp = tls_reg_read32(HR_PWM_DTCTL) & ~0x00030000;
392 temp |= (dtclkdiv<<16);
393 tls_reg_write32(HR_PWM_DTCTL, temp); /* dead zone clock divider */
394
395 if (channel == 0 || channel == 1) {
396 temp = tls_reg_read32(HR_PWM_DTCTL) & ~0x000000FF;
397 temp |= dtcnt;
398 tls_reg_write32(HR_PWM_DTCTL, temp); /* the number of the counting clock cycle */
399
400 tls_reg_write32(HR_PWM_DTCTL, tls_reg_read32(HR_PWM_CTL) | BIT(20)); /* whether enalbe the deat time */
401 } else if (channel == 2 || channel == 3) {
402 temp = tls_reg_read32(HR_PWM_DTCTL) & ~0x0000FF00;
403 temp |= (dtcnt<<8);
404 tls_reg_write32(HR_PWM_DTCTL, temp); /* the number of the counting clock cycle */
405
406 tls_reg_write32(HR_PWM_DTCTL, tls_reg_read32(HR_PWM_CTL) | BIT(21)); /* whether enalbe the deat time */
407 }
408 } else {
409 if (channel == 0 || channel == 1) {
410 tls_reg_write32(HR_PWM_DTCTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(20))); /* whether enalbe the deat time */
411 } else if (channel == 2 || channel == 3) {
412 tls_reg_write32(HR_PWM_DTCTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(21))); /* whether enalbe the deat time */
413 }
414 }
415
416 return WM_SUCCESS;
417 }
418
419 /**
420 * @brief This function is used to set whether to inverse the capture input
421 *
422 * @param[in] channel pwm channel NO.,channel 0 or channel 4
423 * @param[in] en ENABLE or DISABLE
424 *
425 * @retval WM_SUCCESS success
426 * @retval WM_FAILED failed
427 *
428 * @note None
429 */
tls_pwm_capture_inverse_cmd(u8 channel,bool en)430 int tls_pwm_capture_inverse_cmd(u8 channel, bool en)
431 {
432 if (channel != 0 && channel != 4)
433 return WM_FAILED;
434
435 if (channel == 0) {
436 if (ENABLE == en)
437 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(25));
438 else
439 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(25)));
440 } else {
441 if (ENABLE == en)
442 tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(0));
443 else
444 tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(0)));
445 }
446
447 return WM_SUCCESS;
448 }
449
450 /**
451 * @brief This function is used to set break mode
452 *
453 * @param[in] channel pwm channel NO.,channel 0 or channel 4
454 * @param[in] en whether enable the break mode,ENABLE or DISABLE
455 * @param[in] brok when break
456 *
457 * @retval WM_SUCCESS success
458 * @retval WM_FAILED failed
459 *
460 * @note None
461 */
tls_pwm_brake_mode_config(u8 channel,bool en,enum tls_pwm_brake_out_level brok)462 int tls_pwm_brake_mode_config(u8 channel, bool en, enum tls_pwm_brake_out_level brok)
463 {
464 if (channel > (PWM_CHANNEL_MAX_NUM - 1))
465 return WM_FAILED;
466
467 if (ENABLE == en) {
468 if (WM_PWM_BRAKE_OUT_HIGH == brok)
469 tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) | BIT(3+channel));
470 else
471 tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) & (~BIT(3+channel)));
472 tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) | BIT(11+channel));
473 } else {
474 tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) & (~BIT(11+channel)));
475 }
476
477 return WM_SUCCESS;
478 }
479
480 /**
481 * @brief This function is used to enable the capture mode
482 *
483 * @param[in] channel pwm channel NO.,channel 0 or channel 4
484 *
485 * @retval WM_SUCCESS success
486 * @retval WM_FAILED failed
487 *
488 * @note None
489 */
tls_pwm_capture_mode_config(u8 channel)490 int tls_pwm_capture_mode_config(u8 channel)
491 {
492 if (channel != 0 && channel != 4)
493 return WM_FAILED;
494 if (channel == 0) {
495 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(24));
496 } else {
497 tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(1));
498 }
499
500 return WM_SUCCESS;
501 }
502
503 /**
504 * @brief This function is used to set the interrupt about the number of period
505 *
506 * @param[in] channel pwm channel,range from 0 to 4
507 * @param[in] en enble or disable
508 *
509 * @retval WM_SUCCESS success
510 * @retval WM_FAILED failed
511 *
512 * @note None
513 */
tls_pwm_stoptime_irq_cmd(u8 channel,bool en)514 int tls_pwm_stoptime_irq_cmd(u8 channel, bool en)
515 {
516 if (channel > (PWM_CHANNEL_MAX_NUM - 1))
517 return WM_FAILED;
518
519 if (channel == 4) {
520 if (en)
521 tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(4));
522 else
523 tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(4)));
524 } else {
525 if (en)
526 tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(channel));
527 else
528 tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(channel)));
529 }
530
531 return WM_SUCCESS;
532 }
533
534 /**
535 * @brief This function is used to set the interrupt about the
536 capture
537 *
538 * @param[in] channel pwm channel,channel 0 or channel 4
539 * @param[in] int_type interrupt type
540 *
541 * @retval WM_SUCCESS success
542 * @retval WM_FAILED failed
543 *
544 * @note None
545 */
tls_pwm_capture_irq_type_config(u8 channel,enum tls_pwm_cap_int_type int_type)546 int tls_pwm_capture_irq_type_config(u8 channel, enum tls_pwm_cap_int_type int_type)
547 {
548 if (channel != 0 && channel != 4)
549 return WM_FAILED;
550
551 if (channel == 0) {
552 if (WM_PWM_CAP_RISING_FALLING_EDGE_INT == int_type) {
553 tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(5));
554 tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(6));
555 tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(7)));
556 } else if (WM_PWM_CAP_RISING_EDGE_INT == int_type) {
557 tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(5));
558 tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(6)));
559 tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(7)));
560 } else if (WM_PWM_CAP_FALLING_EDGE_INT == int_type) {
561 tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(6));
562 tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(5)));
563 tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(7)));
564 } else if (WM_PWM_CAP_DMA_INT == int_type) {
565 tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(7));
566 tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(5)));
567 tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(6)));
568 }
569 } else if (channel == 4) {
570 if (WM_PWM_CAP_RISING_FALLING_EDGE_INT == int_type) {
571 tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(8));
572 tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(9));
573 tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(10)));
574 } else if (WM_PWM_CAP_RISING_EDGE_INT == int_type) {
575 tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(8));
576 tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(9)));
577 tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(10)));
578 } else if (WM_PWM_CAP_FALLING_EDGE_INT == int_type) {
579 tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(9));
580 tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(8)));
581 tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(10)));
582 } else if (WM_PWM_CAP_DMA_INT == int_type) {
583 tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(10));
584 tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(8)));
585 tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(9)));
586 }
587 }
588
589 return WM_SUCCESS;
590 }
591
592 /**
593 * @brief This function is used to initial pwm(out mode)
594 *
595 * @param[in] pwm_param structure containing the initialization parameters
596 *
597 * @retval WM_SUCCESS success
598 * @retval WM_FAILED failed
599 *
600 * @note None
601 */
tls_pwm_out_init(pwm_init_param * pwm_param)602 int tls_pwm_out_init(pwm_init_param * pwm_param)
603 {
604 int ret = 0;
605
606 if (pwm_param->channel > (PWM_CHANNEL_MAX_NUM - 1))
607 return WM_FAILED;
608
609 /* set output mode */
610 ret = tls_pwm_out_mode_config(pwm_param->channel, pwm_param->mode);
611 if (ret!=WM_SUCCESS)
612 return WM_FAILED;
613
614 if (WM_PWM_OUT_MODE_MC == pwm_param->mode) {
615 /* set dead time */
616 ret = tls_pwm_deadzone_config(pwm_param->channel, pwm_param->dten, pwm_param->dtclkdiv, pwm_param->dtcnt);
617 if (ret!=WM_SUCCESS)
618 return WM_FAILED;
619 }
620
621 /* set count type */
622 tls_pwm_cnt_type_config(pwm_param->channel, pwm_param->cnt_type);
623
624 /* set period value and duty radio */
625 tls_pwm_freq_config(pwm_param->channel, pwm_param->clkdiv, pwm_param->period);
626 tls_pwm_duty_config(pwm_param->channel, pwm_param->duty);
627
628 /* set cycle type */
629 tls_pwm_loop_mode_config(pwm_param->channel, pwm_param->loop_type);
630
631 /* set output whether is inverse */
632 tls_pwm_out_inverse_cmd(pwm_param->channel, pwm_param->inverse_en);
633
634 /* set period number of generating */
635 tls_pwm_stoptime_by_period_config(pwm_param->channel, pwm_param->pnum);
636
637 /* set interrupt of period number whether is enable */
638 tls_pwm_stoptime_irq_cmd(pwm_param->channel, pwm_param->pnum_int);
639
640 /* set output status */
641 if (pwm_param->channel == 0 || pwm_param->channel == 4)
642 tls_pwm_output_en_cmd(pwm_param->channel, WM_PWM_OUT_EN_STATE_OUT);
643 if (pwm_param->mode == WM_PWM_OUT_MODE_ALLSYC && pwm_param->channel == 0)
644 tls_pwm_output_en_cmd(4, WM_PWM_OUT_EN_STATE_OUT);
645 return WM_SUCCESS;
646 }
647
648 /**
649 * @brief This function is used to initial pwm(capture mode)
650 *
651 * @param[in] channel pwm channel, channel 0 or channel 4
652 * @param[in] clkdiv clock divider, range 0 to 65535
653 * @param[in] inverse_en whether the input signal is reversed
654 * @param[in] int_type interrupt type
655 *
656 * @retval WM_SUCCESS success
657 * @retval WM_FAILED failed
658 *
659 * @note None
660 */
tls_pwm_cap_init(u8 channel,u16 clkdiv,bool inverse_en,enum tls_pwm_cap_int_type int_type)661 int tls_pwm_cap_init(u8 channel, u16 clkdiv, bool inverse_en, enum tls_pwm_cap_int_type int_type)
662 {
663 if (channel != 0 && channel != 4)
664 return WM_FAILED;
665
666 /* set clock divider and period value */
667 tls_pwm_freq_config(channel, clkdiv, 0xFF);
668
669 /* set input of capture mode whether is inverse */
670 tls_pwm_capture_inverse_cmd(channel, inverse_en);
671
672 /* set the capture mode */
673 tls_pwm_capture_mode_config(channel);
674
675 /* set count type (only edge alignment in the capture mode) */
676 tls_pwm_cnt_type_config(channel, WM_PWM_CNT_TYPE_EDGE_ALLGN_CAP);
677
678 /* set output status */
679 if (channel == 0)
680 tls_pwm_output_en_cmd(channel, WM_PWM_OUT_EN_STATE_TRI);
681
682 /* set cycle mode (must be set int the capture mode) */
683 tls_pwm_loop_mode_config(channel, WM_PWM_LOOP_TYPE_LOOP);
684
685 /* set interrupt type */
686 tls_pwm_capture_irq_type_config(channel, int_type);
687
688 return WM_SUCCESS;
689 }
690
691 /**
692 * @brief This function is used to start pwm
693 *
694 * @param[in] channel pwm channel, range from 0 to 4
695 *
696 * @retval WM_SUCCESS success
697 * @retval WM_FAILED failed
698 *
699 * @note None
700 */
tls_pwm_start(u8 channel)701 int tls_pwm_start(u8 channel)
702 {
703 if (channel > (PWM_CHANNEL_MAX_NUM - 1))
704 return WM_FAILED;
705
706 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(27 + channel)); /* start counter */
707
708 return WM_SUCCESS;
709 }
710
711 /**
712 * @brief This function is used to stop pwm
713 *
714 * @param[in] channel pwm channel, range from 0 to 4
715 *
716 * @retval WM_SUCCESS success
717 * @retval WM_FAILED failed
718 *
719 * @note None
720 */
tls_pwm_stop(u8 channel)721 int tls_pwm_stop(u8 channel)
722 {
723 if (channel > (PWM_CHANNEL_MAX_NUM - 1))
724 return WM_FAILED;
725
726 tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(27 + channel))); /* stop counter */
727
728 return WM_SUCCESS;
729 }
730
731 /**
732 * @brief This function is used to stop pwm
733 *
734 * @param[in] channel pwm channel no, range form 0 to 4
735 * @param[in] freq frequency, range from 1 to 156250
736 *
737 * @return None
738 *
739 * @note None
740 */
tls_pwm_freq_set(u8 channel,u32 freq)741 void tls_pwm_freq_set(u8 channel, u32 freq)
742 {
743 u16 clkdiv = 0;
744 tls_sys_clk sysclk;
745
746 if (channel > (PWM_CHANNEL_MAX_NUM - 1))
747 return;
748
749 tls_sys_clk_get(&sysclk);
750
751 if (freq == 0) {
752 }
753 clkdiv = sysclk.apbclk*UNIT_MHZ/256/freq;
754 tls_pwm_stop(channel);
755 tls_pwm_freq_config(channel, clkdiv, 255);
756 tls_pwm_start(channel);
757 }
758
759 /**
760 * @brief This function is used to set duty radio
761 *
762 * @param[in] channel pwm channel NO., range form 0 to 4
763 * @param[in] duty duty radio, range from 0 to 255
764 *
765 * @return None
766 *
767 * @note None
768 */
tls_pwm_duty_set(u8 channel,u8 duty)769 void tls_pwm_duty_set(u8 channel, u8 duty)
770 {
771 if (channel > (PWM_CHANNEL_MAX_NUM - 1))
772 return;
773 if (duty == 0) {
774 tls_pwm_stop(channel);
775 } else {
776 tls_pwm_duty_config(channel, duty);
777 tls_pwm_start(channel);
778 }
779 }
780
781 /**
782 * @brief This function is used to initial pwm
783 *
784 * @param[in] channel pwm channel, range from 0 to 4
785 * @param[in] freq freq range from 1 to 156250
786 * @param[in] duty duty range from 0 to 255
787 * @param[in] pnum period num,range from 0 to 255
788 *
789 * @retval WM_SUCCESS success
790 * @retval WM_FAILED failed
791 *
792 * @note None
793 */
tls_pwm_init(u8 channel,u32 freq,u8 duty,u8 pnum)794 int tls_pwm_init(u8 channel, u32 freq, u8 duty, u8 pnum)
795 {
796 pwm_init_param pwm_param;
797 int ret;
798 tls_sys_clk sysclk;
799
800 tls_sys_clk_get(&sysclk);
801
802 memset_s(&pwm_param, sizeof(pwm_param), 0, sizeof(pwm_init_param));
803 pwm_param.period = 255; // 255:byte alignment
804 pwm_param.cnt_type = WM_PWM_CNT_TYPE_EDGE_ALIGN_OUT;
805 pwm_param.loop_type = WM_PWM_LOOP_TYPE_LOOP;
806 pwm_param.mode = WM_PWM_OUT_MODE_INDPT;
807 pwm_param.inverse_en = DISABLE;
808 pwm_param.pnum = pnum;
809 pwm_param.pnum_int = DISABLE;
810 pwm_param.duty = duty;
811 pwm_param.channel = channel;
812 if (freq == 0) {
813 }
814 pwm_param.clkdiv = sysclk.apbclk*UNIT_MHZ/256/freq;
815 ret = tls_pwm_out_init(&pwm_param);
816 return ret;
817 }