1 /*
2 * Copyright (c) 2023 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include "hpm_qeo_drv.h"
9
qeo_wave_get_default_mode_config(QEO_Type * base,qeo_wave_mode_t * config)10 void qeo_wave_get_default_mode_config(QEO_Type *base, qeo_wave_mode_t *config)
11 {
12 (void) base;
13 config->wave0.above_max_limit = qeo_wave_above_max_limit_max_val;
14 config->wave0.high_area0_limit = qeo_wave_high_area_limit_max_val;
15 config->wave0.high_area1_limit = qeo_wave_high_area_limit_max_val;
16 config->wave0.low_area0_limit = qeo_wave_low_area_limit_zero;
17 config->wave0.low_area1_limit = qeo_wave_low_area_limit_zero;
18 config->wave0.below_min_limit = qeo_wave_below_min_limit_zero;
19
20 config->wave1.above_max_limit = qeo_wave_above_max_limit_max_val;
21 config->wave1.high_area0_limit = qeo_wave_high_area_limit_max_val;
22 config->wave1.high_area1_limit = qeo_wave_high_area_limit_max_val;
23 config->wave1.low_area0_limit = qeo_wave_low_area_limit_zero;
24 config->wave1.low_area1_limit = qeo_wave_low_area_limit_zero;
25 config->wave1.below_min_limit = qeo_wave_below_min_limit_zero;
26
27 config->wave2.above_max_limit = qeo_wave_above_max_limit_max_val;
28 config->wave2.high_area0_limit = qeo_wave_high_area_limit_max_val;
29 config->wave2.high_area1_limit = qeo_wave_high_area_limit_max_val;
30 config->wave2.low_area0_limit = qeo_wave_low_area_limit_zero;
31 config->wave2.low_area1_limit = qeo_wave_low_area_limit_zero;
32 config->wave2.below_min_limit = qeo_wave_below_min_limit_zero;
33
34 config->saddle_type = 0;
35 config->wave_type = qeo_wave_cosine;
36 }
37
qeo_wave_config_mode(QEO_Type * base,qeo_wave_mode_t * config)38 void qeo_wave_config_mode(QEO_Type *base, qeo_wave_mode_t *config)
39 {
40 /* clear other bit except EN_WAVEx_VD_VQ_INJECT in MODE register */
41 base->WAVE.MODE &= QEO_WAVE_MODE_EN_WAVE2_VD_VQ_INJECT_MASK
42 | QEO_WAVE_MODE_EN_WAVE1_VD_VQ_INJECT_MASK
43 | QEO_WAVE_MODE_EN_WAVE0_VD_VQ_INJECT_MASK;
44
45 base->WAVE.MODE |= QEO_WAVE_MODE_WAVE2_ABOVE_MAX_LIMIT_SET(config->wave2.above_max_limit)
46 | QEO_WAVE_MODE_WAVE2_HIGH_AREA1_LIMIT_SET(config->wave2.high_area1_limit)
47 | QEO_WAVE_MODE_WAVE2_HIGH_AREA0_LIMIT_SET(config->wave2.high_area0_limit)
48 | QEO_WAVE_MODE_WAVE2_LOW_AREA1_LIMIT_SET(config->wave2.low_area1_limit)
49 | QEO_WAVE_MODE_WAVE2_LOW_AREA0_LIMIT_SET(config->wave2.low_area0_limit)
50 | QEO_WAVE_MODE_WAVE2_BELOW_MIN_LIMIT_SET(config->wave2.below_min_limit)
51
52 | QEO_WAVE_MODE_WAVE1_ABOVE_MAX_LIMIT_SET(config->wave1.above_max_limit)
53 | QEO_WAVE_MODE_WAVE1_HIGH_AREA1_LIMIT_SET(config->wave1.high_area1_limit)
54 | QEO_WAVE_MODE_WAVE1_HIGH_AREA0_LIMIT_SET(config->wave1.high_area0_limit)
55 | QEO_WAVE_MODE_WAVE1_LOW_AREA1_LIMIT_SET(config->wave1.low_area1_limit)
56 | QEO_WAVE_MODE_WAVE1_LOW_AREA0_LIMIT_SET(config->wave1.low_area0_limit)
57 | QEO_WAVE_MODE_WAVE1_BELOW_MIN_LIMIT_SET(config->wave1.below_min_limit)
58
59 | QEO_WAVE_MODE_WAVE0_ABOVE_MAX_LIMIT_SET(config->wave0.above_max_limit)
60 | QEO_WAVE_MODE_WAVE0_HIGH_AREA1_LIMIT_SET(config->wave0.high_area1_limit)
61 | QEO_WAVE_MODE_WAVE0_HIGH_AREA0_LIMIT_SET(config->wave0.high_area0_limit)
62 | QEO_WAVE_MODE_WAVE0_LOW_AREA1_LIMIT_SET(config->wave0.low_area1_limit)
63 | QEO_WAVE_MODE_WAVE0_LOW_AREA0_LIMIT_SET(config->wave0.low_area0_limit)
64 | QEO_WAVE_MODE_WAVE0_BELOW_MIN_LIMIT_SET(config->wave0.below_min_limit)
65 | QEO_WAVE_MODE_SADDLE_TYPE_SET(config->saddle_type)
66 | QEO_WAVE_MODE_WAVES_OUTPUT_TYPE_SET(config->wave_type);
67 }
68
qeo_abz_get_default_mode_config(QEO_Type * base,qeo_abz_mode_t * config)69 void qeo_abz_get_default_mode_config(QEO_Type *base, qeo_abz_mode_t *config)
70 {
71 (void) base;
72 config->a_inv_pol = false;
73 config->b_inv_pol = false;
74 config->z_inv_pol = false;
75 config->output_type = qeo_abz_output_abz;
76 config->z_pulse_period = qeo_z_pulse_100_percent;
77 }
78
qeo_abz_config_mode(QEO_Type * base,qeo_abz_mode_t * config)79 void qeo_abz_config_mode(QEO_Type *base, qeo_abz_mode_t *config)
80 {
81 base->ABZ.MODE &= ~(QEO_ABZ_MODE_Z_POLARITY_MASK
82 | QEO_ABZ_MODE_B_POLARITY_MASK
83 | QEO_ABZ_MODE_A_POLARITY_MASK
84 | QEO_ABZ_MODE_Z_TYPE_MASK
85 | QEO_ABZ_MODE_B_TYPE_MASK
86 | QEO_ABZ_MODE_A_TYPE_MASK);
87
88 base->ABZ.MODE = QEO_ABZ_MODE_Z_POLARITY_SET(config->z_inv_pol)
89 | QEO_ABZ_MODE_B_POLARITY_SET(config->b_inv_pol)
90 | QEO_ABZ_MODE_A_POLARITY_SET(config->a_inv_pol);
91
92 if ((config->output_type == qeo_abz_output_pulse_revise) || (config->output_type == qeo_abz_output_up_down)) {
93 base->ABZ.MODE |= QEO_ABZ_MODE_B_TYPE_SET(config->output_type)
94 | QEO_ABZ_MODE_A_TYPE_SET(config->output_type);
95 } else if (config->output_type == qeo_abz_output_three_phase) {
96 base->ABZ.MODE |= QEO_ABZ_MODE_Z_TYPE_SET(config->output_type)
97 | QEO_ABZ_MODE_B_TYPE_SET(config->output_type)
98 | QEO_ABZ_MODE_A_TYPE_SET(config->output_type);
99 } else {
100 base->ABZ.MODE |= QEO_ABZ_MODE_Z_TYPE_SET(config->z_pulse_period)
101 | QEO_ABZ_MODE_B_TYPE_SET(config->output_type)
102 | QEO_ABZ_MODE_A_TYPE_SET(config->output_type);
103 }
104 }
105
qeo_abz_set_max_frequency(QEO_Type * base,uint32_t src_freq,uint32_t freq)106 hpm_stat_t qeo_abz_set_max_frequency(QEO_Type *base, uint32_t src_freq, uint32_t freq)
107 {
108 uint32_t count;
109
110 if ((freq > 0xffffffffU / 4U) || ((src_freq % (freq * 4U)) != 0)) {
111 return status_invalid_argument;
112 }
113 count = src_freq / (freq * 4U);
114 base->ABZ.LINE_WIDTH = QEO_ABZ_LINE_WIDTH_LINE_SET(count);
115
116 return status_success;
117 }
118
qeo_abz_set_wdog_frequency(QEO_Type * base,uint32_t src_freq,uint32_t freq)119 hpm_stat_t qeo_abz_set_wdog_frequency(QEO_Type *base, uint32_t src_freq, uint32_t freq)
120 {
121 uint32_t count;
122
123 if ((src_freq % freq) != 0) {
124 return status_invalid_argument;
125 }
126 count = src_freq / freq;
127 base->ABZ.WDOG_WIDTH = QEO_ABZ_WDOG_WIDTH_WIDTH_SET(count);
128 base->ABZ.MODE |= QEO_ABZ_MODE_EN_WDOG_MASK;
129
130 return status_success;
131 }
132
qeo_pwm_get_default_safety_table_config(QEO_Type * base,qeo_pwm_safety_output_table_t * table)133 void qeo_pwm_get_default_safety_table_config(QEO_Type *base, qeo_pwm_safety_output_table_t *table)
134 {
135 (void) base;
136 table->pwm7_output = qeo_pwm_safety_output_highz;
137 table->pwm6_output = qeo_pwm_safety_output_highz;
138 table->pwm5_output = qeo_pwm_safety_output_highz;
139 table->pwm4_output = qeo_pwm_safety_output_highz;
140 table->pwm3_output = qeo_pwm_safety_output_highz;
141 table->pwm2_output = qeo_pwm_safety_output_highz;
142 table->pwm1_output = qeo_pwm_safety_output_highz;
143 table->pwm0_output = qeo_pwm_safety_output_highz;
144 }
145
qeo_pwm_get_default_phase_table_config(QEO_Type * base,qeo_pwm_phase_output_table_t * table)146 void qeo_pwm_get_default_phase_table_config(QEO_Type *base, qeo_pwm_phase_output_table_t *table)
147 {
148 (void) base;
149 table->pwm7_output = qeo_pwm_output_force_0;
150 table->pwm6_output = qeo_pwm_output_force_0;
151 table->pwm5_output = qeo_pwm_output_force_0;
152 table->pwm4_output = qeo_pwm_output_force_0;
153 table->pwm3_output = qeo_pwm_output_force_0;
154 table->pwm2_output = qeo_pwm_output_force_0;
155 table->pwm1_output = qeo_pwm_output_force_0;
156 table->pwm0_output = qeo_pwm_output_force_0;
157 }
158
qeo_pwm_get_default_mode_config(QEO_Type * base,qeo_pwm_mode_t * config)159 void qeo_pwm_get_default_mode_config(QEO_Type *base, qeo_pwm_mode_t *config)
160 {
161 (void) base;
162 config->phase_num = 4;
163 config->shield_hardware_trig_safety = false;
164 config->revise_pairs_output = false;
165 }
166
qeo_pwm_config_mode(QEO_Type * base,qeo_pwm_mode_t * config)167 void qeo_pwm_config_mode(QEO_Type *base, qeo_pwm_mode_t *config)
168 {
169 base->PWM.MODE &= ~(QEO_PWM_MODE_PWM_SAFETY_BYPASS_MASK
170 | QEO_PWM_MODE_REVISE_UP_DN_MASK
171 | QEO_PWM_MODE_PHASE_NUM_MASK);
172 base->PWM.MODE |= QEO_PWM_MODE_PWM_SAFETY_BYPASS_SET(config->shield_hardware_trig_safety)
173 | QEO_PWM_MODE_REVISE_UP_DN_SET(config->revise_pairs_output)
174 | QEO_PWM_MODE_PHASE_NUM_SET(config->phase_num);
175 }
176
qeo_pwm_config_phase_table(QEO_Type * base,uint8_t index,qeo_pwm_phase_output_table_t * table)177 void qeo_pwm_config_phase_table(QEO_Type *base, uint8_t index, qeo_pwm_phase_output_table_t *table)
178 {
179 base->PWM.PHASE_TABLE[index] = QEO_PWM_PHASE_TABLE_PWM7_SET(table->pwm7_output)
180 | QEO_PWM_PHASE_TABLE_PWM6_SET(table->pwm6_output)
181 | QEO_PWM_PHASE_TABLE_PWM5_SET(table->pwm5_output)
182 | QEO_PWM_PHASE_TABLE_PWM4_SET(table->pwm4_output)
183 | QEO_PWM_PHASE_TABLE_PWM3_SET(table->pwm3_output)
184 | QEO_PWM_PHASE_TABLE_PWM2_SET(table->pwm2_output)
185 | QEO_PWM_PHASE_TABLE_PWM1_SET(table->pwm1_output)
186 | QEO_PWM_PHASE_TABLE_PWM0_SET(table->pwm0_output);
187 }
188
qeo_pwm_config_safety_table(QEO_Type * base,qeo_pwm_safety_output_table_t * table)189 void qeo_pwm_config_safety_table(QEO_Type *base, qeo_pwm_safety_output_table_t *table)
190 {
191 /*< clear safety table */
192 base->PWM.MODE &= ~(QEO_PWM_MODE_PWM7_SAFETY_MASK
193 | QEO_PWM_MODE_PWM6_SAFETY_MASK
194 | QEO_PWM_MODE_PWM5_SAFETY_MASK
195 | QEO_PWM_MODE_PWM4_SAFETY_MASK
196 | QEO_PWM_MODE_PWM3_SAFETY_MASK
197 | QEO_PWM_MODE_PWM2_SAFETY_MASK
198 | QEO_PWM_MODE_PWM1_SAFETY_MASK
199 | QEO_PWM_MODE_PWM0_SAFETY_MASK);
200 /*< set safety table */
201 base->PWM.MODE |= QEO_PWM_MODE_PWM7_SAFETY_SET(table->pwm7_output)
202 | QEO_PWM_MODE_PWM6_SAFETY_SET(table->pwm6_output)
203 | QEO_PWM_MODE_PWM5_SAFETY_SET(table->pwm5_output)
204 | QEO_PWM_MODE_PWM4_SAFETY_SET(table->pwm4_output)
205 | QEO_PWM_MODE_PWM3_SAFETY_SET(table->pwm3_output)
206 | QEO_PWM_MODE_PWM2_SAFETY_SET(table->pwm2_output)
207 | QEO_PWM_MODE_PWM1_SAFETY_SET(table->pwm1_output)
208 | QEO_PWM_MODE_PWM0_SAFETY_SET(table->pwm0_output);
209 }
210
211 /**
212 * If the line step of the position to be synchronized after position value
213 * to ABZ value conversion is the same as the current position, will hang the ABZ.
214 * ABZ value = m lines + n line_steps(0 <= m <= 3)
215 * This API will check the sync_pos and shift it if needed
216 */
qeo_abz_position_sync(QEO_Type * base,uint32_t lines,uint32_t sync_pos)217 void qeo_abz_position_sync(QEO_Type *base, uint32_t lines, uint32_t sync_pos)
218 {
219 uint32_t line_width;
220 uint32_t line_step_width;
221 uint32_t shift_pos;
222 uint32_t current_line_step;
223 uint32_t temp;
224
225 line_width = (uint32_t)(0x100000000UL / lines);
226 line_step_width = line_width / 4U;
227 current_line_step = base->DEBUG2 & 0x3; /* get the lowest two bits */
228 temp = (sync_pos % line_width) / line_step_width;
229 if (temp == current_line_step) {
230 shift_pos = sync_pos - line_step_width;
231 } else {
232 shift_pos = sync_pos;
233 }
234
235 base->ABZ.POSTION_SYNC = QEO_ABZ_POSTION_SYNC_POSTION_MASK;
236 qeo_enable_software_position_inject(base);
237 qeo_software_position_inject(base, shift_pos);
238 qeo_disable_software_position_inject(base);
239 }