1 /*
2 * Copyright (c) 2021 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include "hpm_soc_feature.h"
9 #include "hpm_pwm_drv.h"
10
pwm_load_cmp_shadow_on_match(PWM_Type * pwm_x,uint8_t index,pwm_cmp_config_t * config)11 hpm_stat_t pwm_load_cmp_shadow_on_match(PWM_Type *pwm_x,
12 uint8_t index,
13 pwm_cmp_config_t *config)
14 {
15 if (config->mode != pwm_cmp_mode_output_compare) {
16 return status_invalid_argument;
17 }
18 pwm_config_cmp(pwm_x, index, config);
19 pwm_issue_shadow_register_lock_event(pwm_x);
20 pwm_x->GCR = ((pwm_x->GCR & ~(PWM_GCR_CMPSHDWSEL_MASK)) | PWM_GCR_CMPSHDWSEL_SET(index));
21 return status_success;
22 }
23
pwm_get_captured_count(PWM_Type * pwm_x,uint32_t * buf,pwm_counter_type_t counter,uint8_t start_index,uint8_t num)24 void pwm_get_captured_count(PWM_Type *pwm_x, uint32_t *buf, pwm_counter_type_t counter, uint8_t start_index, uint8_t num)
25 {
26 uint32_t i;
27 if (counter == pwm_counter_type_capture_falling_edge) {
28 for (i = start_index; i < start_index + num; i++) {
29 *buf = pwm_x->CAPNEG[i];
30 }
31 } else {
32 for (i = start_index; i < start_index + num; i++) {
33 *buf = pwm_x->CAPPOS[i];
34 }
35 }
36 }
37
pwm_get_default_cmp_config(PWM_Type * pwm_x,pwm_cmp_config_t * config)38 void pwm_get_default_cmp_config(PWM_Type *pwm_x, pwm_cmp_config_t *config)
39 {
40 (void) pwm_x;
41 config->mode = pwm_cmp_mode_output_compare;
42 config->update_trigger = pwm_shadow_register_update_on_modify;
43 config->enable_ex_cmp = false;
44 #if defined(PWM_SOC_HRPWM_SUPPORT) && PWM_SOC_HRPWM_SUPPORT
45 config->enable_hrcmp = false;
46 config->hrcmp = 0;
47 #endif
48 config->cmp = 0;
49 config->ex_cmp = 0;
50 config->half_clock_cmp = 0;
51 config->jitter_cmp = 0;
52 }
53
pwm_get_default_output_channel_config(PWM_Type * pwm_x,pwm_output_channel_t * config)54 void pwm_get_default_output_channel_config(PWM_Type *pwm_x, pwm_output_channel_t *config)
55 {
56 (void) pwm_x;
57 config->cmp_start_index = 0;
58 config->cmp_end_index = 0;
59 config->invert_output = false;
60 }
61
pwm_get_default_pwm_config(PWM_Type * pwm_x,pwm_config_t * config)62 void pwm_get_default_pwm_config(PWM_Type *pwm_x, pwm_config_t *config)
63 {
64 (void) pwm_x;
65 config->enable_output = false;
66 config->update_trigger = pwm_shadow_register_update_on_modify;
67 config->fault_mode = pwm_fault_mode_force_output_highz;
68 config->fault_recovery_trigger = pwm_fault_recovery_on_fault_clear;
69 config->force_source = pwm_force_source_software;
70 config->dead_zone_in_half_cycle = 0;
71 }
72
pwm_get_default_pwm_pair_config(PWM_Type * pwm_x,pwm_pair_config_t * config)73 void pwm_get_default_pwm_pair_config(PWM_Type *pwm_x, pwm_pair_config_t *config)
74 {
75 pwm_get_default_pwm_config(pwm_x, &config->pwm[0]);
76 pwm_get_default_pwm_config(pwm_x, &config->pwm[1]);
77 }
78
pwm_setup_waveform_in_pair(PWM_Type * pwm_x,uint8_t pwm_index,pwm_pair_config_t * pwm_pair_config,uint8_t cmp_start_index,pwm_cmp_config_t * cmp,uint8_t cmp_num)79 hpm_stat_t pwm_setup_waveform_in_pair(PWM_Type *pwm_x, uint8_t pwm_index,
80 pwm_pair_config_t *pwm_pair_config, uint8_t cmp_start_index,
81 pwm_cmp_config_t *cmp, uint8_t cmp_num)
82 {
83 uint8_t i;
84 pwm_output_channel_t ch_config;
85
86 if ((pwm_index > PWM_SOC_PWM_MAX_COUNT)
87 || !cmp_num
88 || (cmp_start_index > PWM_SOC_CMP_MAX_COUNT)
89 || (cmp_start_index + cmp_num > PWM_SOC_CMP_MAX_COUNT)
90 || ((pwm_index > (PWM_SOC_PWM_MAX_COUNT - 1))
91 || (pwm_index & 0x1))) {
92 return status_invalid_argument;
93 }
94
95 pwm_x->PWMCFG[pwm_index] &= ~PWM_PWMCFG_OEN_MASK;
96 pwm_x->PWMCFG[pwm_index + 1] &= ~PWM_PWMCFG_OEN_MASK;
97
98 for (i = 0; i < cmp_num; i++) {
99 pwm_config_cmp(pwm_x, cmp_start_index + i, &cmp[i]);
100 }
101 ch_config.cmp_start_index = cmp_start_index;
102 ch_config.cmp_end_index = cmp_start_index + cmp_num - 1;
103 ch_config.invert_output = pwm_pair_config->pwm[0].invert_output;
104 pwm_config_output_channel(pwm_x, pwm_index, &ch_config);
105
106 ch_config.invert_output = pwm_pair_config->pwm[1].invert_output;
107 pwm_config_output_channel(pwm_x, pwm_index + 1, &ch_config);
108
109 pwm_config_pwm(pwm_x, pwm_index, &pwm_pair_config->pwm[0], true);
110 pwm_config_pwm(pwm_x, pwm_index + 1, &pwm_pair_config->pwm[1], true);
111
112 return status_success;
113 }
114
pwm_setup_waveform(PWM_Type * pwm_x,uint8_t pwm_index,pwm_config_t * pwm_config,uint8_t cmp_start_index,pwm_cmp_config_t * cmp,uint8_t cmp_num)115 hpm_stat_t pwm_setup_waveform(PWM_Type *pwm_x,
116 uint8_t pwm_index, pwm_config_t *pwm_config,
117 uint8_t cmp_start_index, pwm_cmp_config_t *cmp, uint8_t cmp_num)
118 {
119 uint8_t i;
120 pwm_output_channel_t ch_config;
121 if (!cmp_num
122 || (cmp_start_index > PWM_SOC_CMP_MAX_COUNT)
123 || (cmp_start_index + cmp_num > PWM_SOC_CMP_MAX_COUNT)) {
124 return status_invalid_argument;
125 }
126
127 for (i = 0; i < cmp_num; i++) {
128 pwm_config_cmp(pwm_x, cmp_start_index + i, &cmp[i]);
129 }
130 ch_config.cmp_start_index = cmp_start_index;
131 ch_config.cmp_end_index = cmp_start_index + cmp_num - 1;
132 ch_config.invert_output = pwm_config->invert_output;
133 pwm_config_output_channel(pwm_x, pwm_index, &ch_config);
134 if (pwm_index < PWM_SOC_PWM_MAX_COUNT) {
135 pwm_config_pwm(pwm_x, pwm_index, pwm_config, false);
136 }
137 return status_success;
138 }
139
pwm_update_raw_cmp_edge_aligned(PWM_Type * pwm_x,uint8_t cmp_index,uint32_t target_cmp)140 hpm_stat_t pwm_update_raw_cmp_edge_aligned(PWM_Type *pwm_x, uint8_t cmp_index, uint32_t target_cmp)
141 {
142 pwm_shadow_register_unlock(pwm_x);
143 pwm_cmp_update_cmp_value(pwm_x, cmp_index, target_cmp, 0);
144 return status_success;
145 }
146
pwm_update_raw_cmp_central_aligned(PWM_Type * pwm_x,uint8_t cmp1_index,uint8_t cmp2_index,uint32_t target_cmp1,uint32_t target_cmp2)147 hpm_stat_t pwm_update_raw_cmp_central_aligned(PWM_Type *pwm_x, uint8_t cmp1_index,
148 uint8_t cmp2_index, uint32_t target_cmp1, uint32_t target_cmp2)
149 {
150 uint32_t reload = PWM_RLD_RLD_GET(pwm_x->RLD);
151 if (!target_cmp1) {
152 target_cmp1 = reload + 1;
153 }
154 if (!target_cmp2) {
155 target_cmp2 = reload + 1;
156 }
157 pwm_shadow_register_unlock(pwm_x);
158 pwm_cmp_update_cmp_value(pwm_x, cmp1_index, target_cmp1, 0);
159 pwm_cmp_update_cmp_value(pwm_x, cmp2_index, target_cmp2, 0);
160 return status_success;
161 }
162 #if defined(PWM_SOC_HRPWM_SUPPORT) && PWM_SOC_HRPWM_SUPPORT
163
pwm_update_raw_hrcmp_edge_aligned(PWM_Type * pwm_x,uint8_t cmp_index,uint32_t target_cmp,uint16_t target_hrcmp)164 hpm_stat_t pwm_update_raw_hrcmp_edge_aligned(PWM_Type *pwm_x, uint8_t cmp_index, uint32_t target_cmp,
165 uint16_t target_hrcmp)
166 {
167 pwm_shadow_register_unlock(pwm_x);
168 pwm_cmp_update_hrcmp_value(pwm_x, cmp_index, target_cmp, target_hrcmp);
169 return status_success;
170 }
171
pwm_update_raw_hrcmp_central_aligned(PWM_Type * pwm_x,uint8_t cmp1_index,uint8_t cmp2_index,uint32_t target_cmp1,uint32_t target_cmp2,uint16_t target_hrcmp1,uint16_t target_hrcmp2)172 hpm_stat_t pwm_update_raw_hrcmp_central_aligned(PWM_Type *pwm_x, uint8_t cmp1_index,
173 uint8_t cmp2_index, uint32_t target_cmp1, uint32_t target_cmp2,
174 uint16_t target_hrcmp1, uint16_t target_hrcmp2)
175 {
176 uint32_t reload = PWM_RLD_RLD_GET(pwm_x->RLD);
177 if (!target_cmp1) {
178 target_cmp1 = reload + 1;
179 }
180 if (!target_cmp2) {
181 target_cmp2 = reload + 1;
182 }
183 pwm_shadow_register_unlock(pwm_x);
184 pwm_cmp_update_hrcmp_value(pwm_x, cmp1_index, target_cmp1, target_hrcmp1);
185 pwm_cmp_update_hrcmp_value(pwm_x, cmp2_index, target_cmp2, target_hrcmp2);
186 return status_success;
187 }
188 #endif
189