• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }