1 /*
2  * Copyright (c) 2023 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include "hpm_soc_feature.h"
9 #include "hpm_pwmv2_drv.h"
10 
pwmv2_deinit(PWMV2_Type * pwm_x)11 void pwmv2_deinit(PWMV2_Type *pwm_x)
12 {
13     pwm_x->IRQ_EN_CMP = 0;
14     pwm_x->IRQ_EN_RELOAD = 0;
15     pwm_x->IRQ_EN_CAP_POS = 0;
16     pwm_x->IRQ_EN_CAP_NEG = 0;
17     pwm_x->IRQ_EN_FAULT = 0;
18     pwm_x->IRQ_EN_BURSTEND = 0;
19     pwm_x->IRQ_EN = 0;
20     pwm_x->DMA_EN = 0;
21     pwm_x->IRQ_STS |= pwm_x->IRQ_STS;
22     pwm_x->IRQ_STS_CMP = 0;
23     pwm_x->IRQ_STS_RELOAD = 0;
24     pwm_x->IRQ_STS_CAP_POS = 0;
25     pwm_x->IRQ_STS_CAP_NEG = 0;
26     pwm_x->IRQ_STS_FAULT = 0;
27     pwm_x->IRQ_STS_BURSTEND = 0;
28     for (uint8_t i = 0; i < PWM_SOC_CMP_MAX_COUNT; i++) {
29         pwm_x->CMP[i].CFG = 0;
30     }
31     for (uint8_t i = 0; i < PWM_SOC_OUTPUT_TO_PWM_MAX_COUNT; i++) {
32         pwm_x->PWM[i].CFG0 = 0;
33         pwm_x->PWM[i].CFG1 = 0;
34         pwm_x->PWM[i].DEAD_AREA = 0;
35     }
36     for (uint8_t i = 0; i < PWMV2_SOC_CAL_COUNT_MAX; i++) {
37         pwm_x->CAL[i].CFG0 = 0;
38         pwm_x->CAL[i].CFG1 = 0;
39     }
40 }
41 
pwmv2_config_cmp(PWMV2_Type * pwm_x,uint8_t index,pwmv2_cmp_config_t * config)42 void pwmv2_config_cmp(PWMV2_Type *pwm_x, uint8_t index, pwmv2_cmp_config_t *config)
43 {
44     pwmv2_select_cmp_source(pwm_x, index, config->cmp_source, config->cmp_source_index);
45     pwmv2_cmp_update_trig_time(pwm_x, index, config->update_trigger);
46     if (config->update_trigger == pwm_shadow_register_update_on_trigmux) {
47         pwmv2_select_cmp_trigmux(pwm_x, index, config->update_trigger_index);
48     }
49     if (index >= PWM_CMP_UNABLE_OUTPUT_INDEX) {
50         pwmv2_cmp_select_counter(pwm_x, index, config->cmp_source_index);
51     }
52     if (config->cmp_source == cmp_value_from_shadow_val) {
53         pwmv2_shadow_register_unlock(pwm_x);
54         if (config->enable_hrcmp) {
55             pwmv2_set_shadow_val(pwm_x, config->cmp_source_index, config->cmp, config->hrcmp, config->enable_half_cmp);
56         } else {
57             pwmv2_set_shadow_val(pwm_x, config->cmp_source_index, config->cmp, 0, config->enable_half_cmp);
58         }
59         pwmv2_shadow_register_lock(pwm_x);
60     }
61 }
62 
pwmv2_config_async_fault_source(PWMV2_Type * pwm_x,pwm_channel_t index,pwmv2_async_fault_source_config_t * config)63 void pwmv2_config_async_fault_source(PWMV2_Type *pwm_x, pwm_channel_t index, pwmv2_async_fault_source_config_t *config)
64 {
65     pwm_x->PWM[index].CFG0 = (pwm_x->PWM[index].CFG0 & ~(PWMV2_PWM_CFG0_FAULT_SEL_ASYNC_MASK | PWMV2_PWM_CFG0_FAULT_POL_ASYNC_MASK))
66         | PWMV2_PWM_CFG0_FAULT_SEL_ASYNC_SET(config->async_signal_from_pad_index)
67         | PWMV2_PWM_CFG0_FAULT_POL_ASYNC_SET(config->fault_async_pad_level);
68 }
69 
pwmv2_config_pwm(PWMV2_Type * pwm_x,pwm_channel_t index,pwmv2_config_t * config,bool enable_pair_mode)70 void pwmv2_config_pwm(PWMV2_Type *pwm_x, pwm_channel_t index,
71                                   pwmv2_config_t *config, bool enable_pair_mode)
72 {
73     pwm_x->PWM[index].CFG0 = PWMV2_PWM_CFG0_TRIG_SEL4_SET(config->enable_four_cmp) |
74                             PWMV2_PWM_CFG0_OUT_POLARITY_SET(config->invert_output) |
75                             PWMV2_PWM_CFG0_POL_UPDATE_SEL_SET(config->update_polarity_time);
76     pwm_x->PWM[index].CFG1 = PWMV2_PWM_CFG1_HIGHZ_EN_N_SET(config->enable_output) |
77                             PWMV2_PWM_CFG1_FORCE_UPDATE_TIME_SET(config->force_shadow_trigger) |
78                             PWMV2_PWM_CFG1_FAULT_MODE_SET(config->fault_mode) |
79                             PWMV2_PWM_CFG1_FAULT_REC_TIME_SET(config->fault_recovery_trigger) |
80                             PWMV2_PWM_CFG1_PAIR_MODE_SET(enable_pair_mode) |
81                             PWMV2_PWM_CFG1_PWM_LOGIC_SET(config->logic) |
82                             PWMV2_PWM_CFG1_FORCE_TIME_SET(config->force_trigger) |
83                             PWMV2_PWM_CFG1_FORCE_TRIG_SEL_SET(config->force_shadow_trigmux_index) |
84                             PWMV2_PWM_CFG1_FORCE_ACT_SEL_SET(config->force_trigmux_index) |
85                             PWMV2_PWM_CFG1_PWM_FORCE_SEL_SET(config->fault_recovery_trigmux_index);
86     pwmv2_config_async_fault_source(pwm_x, index, &config->async_fault_source);
87     if (enable_pair_mode) {
88         pwmv2_set_dead_area(pwm_x, index, config->dead_zone_in_half_cycle);
89     }
90 }
91 
pwmv2_setup_waveform(PWMV2_Type * pwm_x,pwm_channel_t chn,pwmv2_config_t * pwm_config,uint8_t cmp_start_index,pwmv2_cmp_config_t * cmp,uint8_t cmp_num)92 hpm_stat_t pwmv2_setup_waveform(PWMV2_Type *pwm_x,
93                         pwm_channel_t chn, pwmv2_config_t *pwm_config,
94                         uint8_t cmp_start_index, pwmv2_cmp_config_t *cmp, uint8_t cmp_num)
95 {
96     uint8_t i;
97 
98     for (i =  0; i < cmp_num; i++) {
99         pwmv2_config_cmp(pwm_x, cmp_start_index + i, &cmp[i]);
100     }
101     pwmv2_config_pwm(pwm_x, chn, pwm_config, false);
102 
103     return status_success;
104 }
105 
pwmv2_setup_waveform_in_pair(PWMV2_Type * pwm_x,pwm_channel_t chn,pwmv2_pair_config_t * pwm_pair_config,uint8_t cmp_start_index,pwmv2_cmp_config_t * cmp,uint8_t cmp_num)106 hpm_stat_t pwmv2_setup_waveform_in_pair(PWMV2_Type *pwm_x, pwm_channel_t chn,
107                         pwmv2_pair_config_t *pwm_pair_config, uint8_t cmp_start_index,
108                         pwmv2_cmp_config_t *cmp, uint8_t cmp_num)
109 {
110     uint8_t i;
111 
112     for (i =  0; i < cmp_num; i++) {
113         pwmv2_config_cmp(pwm_x, cmp_start_index + i, &cmp[i]);
114     }
115     pwmv2_config_pwm(pwm_x, chn, &pwm_pair_config->pwm[0], true);
116     pwmv2_config_pwm(pwm_x, chn + 1, &pwm_pair_config->pwm[1], true);
117 
118     return status_success;
119 }
120 
pwmv2_setup_cmp_calculate(PWMV2_Type * pwm_x,uint8_t cal_index,pwmv2_cmp_calculate_cfg_t * cal)121 void pwmv2_setup_cmp_calculate(PWMV2_Type *pwm_x, uint8_t cal_index, pwmv2_cmp_calculate_cfg_t *cal)
122 {
123     pwm_x->CAL[cal_index].CFG0 = PWMV2_CAL_CFG0_CAL_LU_PARAM_SET(cal->up_limit_param) |
124             PWMV2_CAL_CFG0_CAL_LL_PARAM_SET(cal->low_limit_param) |
125             PWMV2_CAL_CFG0_CAL_T_PARAM_SET(cal->t_param) |
126             PWMV2_CAL_CFG0_CAL_D_PARAM_SET(cal->d_param);
127     pwm_x->CAL[cal_index].CFG1 = PWMV2_CAL_CFG1_CAL_T_INDEX_SET(cal->counter_index) |
128             PWMV2_CAL_CFG1_CAL_IN_INDEX_SET(cal->in_index) |
129             PWMV2_CAL_CFG1_CAL_LU_EN_SET(cal->enable_up_limit) |
130             PWMV2_CAL_CFG1_CAL_LIM_UP_SET(cal->up_limit_offset_index) |
131             PWMV2_CAL_CFG1_CAL_LL_EN_SET(cal->enbale_low_limit) |
132             PWMV2_CAL_CFG1_CAL_LIM_LO_SET (cal->low_limit_offset_index) |
133             PWMV2_CAL_CFG1_CAL_IN_OFF_SET(cal->in_offset_index);
134 }
135