1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /*
3 * Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
4 */
5
6 #include "hal_base.h"
7
8 #ifdef HAL_PWR_MODULE_ENABLED
9
10 /** @addtogroup RK_HAL_Driver
11 * @{
12 */
13
14 /** @addtogroup PWR
15 * @{
16 */
17
18 /** @defgroup PWR_How_To_Use How To Use
19 * @{
20
21 The PWR driver can be used as follows:
22
23 - Invoke HAL_PWR_SetVoltage to set voltage value.
24 - Invoke HAL_PWR_GetVoltage to Get voltage value.
25 - Invoke HAL_PWR_SetVoltageSuspend to set voltage value for suspend mode.
26 - Invoke HAL_PWR_GetVoltageSuspend to get voltage value for suspend mode.
27 - Invoke HAL_PWR_GetVoltageReal to get voltage value while is in effect.
28 - Invoke HAL_PWR_Enable to enable a regulator.
29 - Invoke HAL_PWR_Disable to disable a regulator.
30 - Invoke HAL_PWR_GetEnableState to get the enable state.
31 - Invoke HAL_PWR_RoundVoltage to check the volt is valid or not.
32
33 @} */
34
35 #ifdef HAL_PWR_INTBUS_MODULE_ENABLED
36
37 /** @defgroup PWR_Private_Definition Private Definition
38 * @{
39 */
40 /********************* Private MACRO Definition ******************************/
41
42 #define WM_SET_BITS(msk, shift, bits) ((msk <<(shift + 16)) | (bits << shift))
43 #define WM_SET_BIT(shift) ((1 << (16 + shift) ) | (1 << shift))
44 #define WM_CLR_BIT(shift) (1 << (16 + shift) )
45
46 /********************* Private Structure Definition **************************/
47 /********************* Private Variable Definition ***************************/
48 /********************* Private Function Definition ***************************/
PWR_SetVoltage_Linear(struct PWR_INTREG_DESC * desc,uint32_t volt,ePWR_CtrlType ctrlType)49 static HAL_Status PWR_SetVoltage_Linear(struct PWR_INTREG_DESC *desc, uint32_t volt,
50 ePWR_CtrlType ctrlType)
51 {
52 uint32_t val, delta, mod;
53 __IO uint32_t *preg;
54
55 HAL_ASSERT(desc->flag & HAL_BIT(ctrlType));
56
57 HAL_ASSERT(volt >= desc->minVolt);
58
59 HAL_ASSERT(ctrlType <= PWR_CTRL_VOLT_SSPD);
60
61 delta = volt - desc->minVolt;
62 mod = delta % desc->volt_list.stepVolt;
63 if (mod) {
64 return HAL_INVAL;
65 }
66
67 val = delta / desc->volt_list.stepVolt;
68
69 HAL_ASSERT(val < desc->voltCnt);
70
71 preg = desc->preg[ctrlType];
72
73 val = WM_SET_BITS(desc->voltMask, desc->shift[ctrlType], val);
74 WRITE_REG(*preg, val);
75
76 return HAL_OK;
77 }
78
PWR_RoundVoltage_Linear(struct PWR_INTREG_DESC * desc,uint32_t volt)79 static uint32_t PWR_RoundVoltage_Linear(struct PWR_INTREG_DESC *desc, uint32_t volt)
80 {
81 uint32_t val, delta, mod;
82
83 HAL_ASSERT(volt >= desc->minVolt);
84
85 delta = volt - desc->minVolt;
86 val = delta / desc->volt_list.stepVolt;
87
88 mod = delta % desc->volt_list.stepVolt;
89
90 if (mod) {
91 val += 1;
92 }
93
94 return (desc->minVolt + desc->volt_list.stepVolt * val);
95 }
96
PWR_GetVoltageLinear(struct PWR_INTREG_DESC * desc,ePWR_CtrlType ctrlType)97 static uint32_t PWR_GetVoltageLinear(struct PWR_INTREG_DESC *desc,
98 ePWR_CtrlType ctrlType)
99 {
100 uint32_t val;
101 __IO uint32_t *preg;
102
103 HAL_ASSERT(desc->flag & HAL_BIT(ctrlType));
104 HAL_ASSERT(ctrlType <= PWR_CTRL_VOLT_ST);
105
106 preg = desc->preg[ctrlType];
107
108 val = (READ_REG(*preg) >> desc->shift[ctrlType]) & desc->voltMask;
109
110 HAL_ASSERT(val < desc->voltCnt);
111
112 return (desc->minVolt + desc->volt_list.stepVolt * val);
113 }
114
PWR_EnableDisable(struct PWR_INTREG_DESC * desc,uint32_t enable)115 static HAL_Status PWR_EnableDisable(struct PWR_INTREG_DESC *desc, uint32_t enable)
116 {
117 uint32_t val;
118 __IO uint32_t *preg;
119
120 HAL_ASSERT(desc->flag & HAL_BIT(PWR_CTRL_PWR_EN));
121
122 preg = desc->preg[PWR_CTRL_PWR_EN];
123
124 if (enable) {
125 val = WM_SET_BIT(desc->shift[PWR_CTRL_PWR_EN]);
126 } else {
127 val = WM_CLR_BIT(desc->shift[PWR_CTRL_PWR_EN]);
128 }
129
130 WRITE_REG(*preg, val);
131
132 return HAL_OK;
133 }
134
135 /** @} */
136 /********************* Public Function Definition ****************************/
137 /** @defgroup PWR_Exported_Functions_Group2 State and Errors Functions
138
139 This section provides functions allowing to get the status of the module:
140
141 * @{
142 */
143
144 /**
145 * @brief get enable state for the power regulator.
146 * @param desc: the power regulator description pointer.
147 * @return 1 is enable, 0 is disable.
148 */
HAL_PWR_GetEnableState(struct PWR_INTREG_DESC * desc)149 int HAL_PWR_GetEnableState(struct PWR_INTREG_DESC *desc)
150 {
151 __IO uint32_t *preg;
152
153 HAL_ASSERT(desc->flag & HAL_BIT(PWR_CTRL_PWR_EN));
154
155 preg = desc->preg[PWR_CTRL_PWR_EN];
156
157 return (READ_REG(*preg) >> desc->shift[PWR_CTRL_PWR_EN]) & 0x1;
158 }
159
160 /**
161 * @brief get voltage value.
162 * @param desc: the power regulator description pointer.
163 * @return the voltage value if support, otherwise return 0.
164 */
HAL_PWR_GetVoltage(struct PWR_INTREG_DESC * desc)165 uint32_t HAL_PWR_GetVoltage(struct PWR_INTREG_DESC *desc)
166 {
167 HAL_ASSERT(desc);
168 if (desc->flag & PWR_FLG_LINEAR) {
169 return PWR_GetVoltageLinear(desc, PWR_CTRL_VOLT_RUN);
170 } else {
171 return 0;
172 }
173 }
174
175 /**
176 * @brief round voltage value.
177 * @param desc: the power regulator description pointer.
178 * @param volt: the volt value to be check
179 * @return the voltage value if support, otherwise return 0.
180 */
HAL_PWR_RoundVoltage(struct PWR_INTREG_DESC * desc,uint32_t volt)181 uint32_t HAL_PWR_RoundVoltage(struct PWR_INTREG_DESC *desc, uint32_t volt)
182 {
183 HAL_ASSERT(desc);
184 if (desc->flag & PWR_FLG_LINEAR) {
185 return PWR_RoundVoltage_Linear(desc, volt);
186 } else {
187 return 0;
188 }
189 }
190
191 /**
192 * @brief get voltage value for suspend mode.
193 * @param desc: the power regulator description pointer.
194 * @return the voltage value if support, otherwise return 0.
195 */
HAL_PWR_GetVoltageSuspend(struct PWR_INTREG_DESC * desc)196 uint32_t HAL_PWR_GetVoltageSuspend(struct PWR_INTREG_DESC *desc)
197 {
198 HAL_ASSERT(desc);
199 if (desc->flag & PWR_FLG_LINEAR) {
200 return PWR_GetVoltageLinear(desc, PWR_CTRL_VOLT_SSPD);
201 } else {
202 return 0;
203 }
204 }
205
206 /**
207 * @brief get real voltage value.
208 * @param desc: the power regulator description pointer.
209 * @return the voltage value if support, otherwise return 0.
210 */
HAL_PWR_GetVoltageReal(struct PWR_INTREG_DESC * desc)211 uint32_t HAL_PWR_GetVoltageReal(struct PWR_INTREG_DESC *desc)
212 {
213 HAL_ASSERT(desc);
214 if ((desc->flag & (PWR_FLG_LINEAR | PWR_FLG_VOLT_ST)) ==
215 (PWR_FLG_LINEAR | PWR_FLG_VOLT_ST)) {
216 return PWR_GetVoltageLinear(desc, PWR_CTRL_VOLT_ST);
217 } else {
218 return 0;
219 }
220 }
221
222 /** @} */
223
224 /** @defgroup PWR_Exported_Functions_Group5 Other Functions
225 * @{
226 */
227
228 /**
229 * @brief set voltage value.
230 * @param desc: the power regulator description pointer.
231 * @param volt: the volt value to be config
232 * @return HAL_Status.
233 */
HAL_PWR_SetVoltage(struct PWR_INTREG_DESC * desc,uint32_t volt)234 HAL_Status HAL_PWR_SetVoltage(struct PWR_INTREG_DESC *desc, uint32_t volt)
235 {
236 HAL_ASSERT(desc);
237
238 if (desc->flag & PWR_FLG_LINEAR) {
239 return PWR_SetVoltage_Linear(desc, volt, PWR_CTRL_VOLT_RUN);
240 } else {
241 return HAL_NODEV;
242 }
243 }
244
245 /**
246 * @brief set voltage value for suspend mode.
247 * @param desc: the power regulator description pointer.
248 * @param volt: the volt value to be config
249 * @return HAL_Status.
250 */
HAL_PWR_SetVoltageSuspend(struct PWR_INTREG_DESC * desc,uint32_t volt)251 HAL_Status HAL_PWR_SetVoltageSuspend(struct PWR_INTREG_DESC *desc,
252 uint32_t volt)
253 {
254 HAL_ASSERT(desc);
255 if (desc->flag & PWR_FLG_LINEAR) {
256 return PWR_SetVoltage_Linear(desc, volt, PWR_CTRL_VOLT_SSPD);
257 } else {
258 return HAL_NODEV;
259 }
260 }
261
262 /**
263 * @brief enable a power regulator.
264 * @param desc: the power regulator description pointer.
265 * @return HAL_Status.
266 */
HAL_PWR_Enable(struct PWR_INTREG_DESC * desc)267 HAL_Status HAL_PWR_Enable(struct PWR_INTREG_DESC *desc)
268 {
269 HAL_ASSERT(desc);
270
271 return PWR_EnableDisable(desc, 1);
272 }
273
274 /**
275 * @brief disable a power regulator.
276 * @param desc: the power regulator description pointer.
277 * @return HAL_Status.
278 */
HAL_PWR_Disable(struct PWR_INTREG_DESC * desc)279 HAL_Status HAL_PWR_Disable(struct PWR_INTREG_DESC *desc)
280 {
281 HAL_ASSERT(desc);
282
283 return PWR_EnableDisable(desc, 0);
284 }
285
286 /**
287 * @brief match a power regulator description by pwr id.
288 * @param desc: a power regulator description.
289 * @param pwrId: a regulator channel id.
290 * @return if match return HAL_TRUE.
291 */
HAL_PWR_CheckDescByPwrId(struct PWR_INTREG_DESC * desc,ePWR_ID pwrId)292 HAL_Check HAL_PWR_CheckDescByPwrId(struct PWR_INTREG_DESC *desc,
293 ePWR_ID pwrId)
294 {
295 if (desc->info.pwrId == pwrId) {
296 return HAL_TRUE;
297 } else {
298 return HAL_FALSE;
299 }
300 }
301
302 /** @} */
303
304 #endif
305
306 /** @defgroup PWR_Exported_Functions_Group5 Other Functions
307 * @{
308 */
309
310 /**
311 * @brief use linear ranges to convert seletor to voltage.
312 * @param linearTables: the power linear range table pointer.
313 * @param sel: the selector value to be converted
314 * @return seletor value.
315 */
HAL_PWR_LinearRangeSelToVolt(const struct PWR_LINEAR_RANGE_TABLE * linearTables,uint32_t sel)316 int HAL_PWR_LinearRangeSelToVolt(const struct PWR_LINEAR_RANGE_TABLE *linearTables, uint32_t sel)
317 {
318 const struct PWR_LINEAR_RANGE *range;
319 int i;
320
321 HAL_ASSERT(linearTables);
322 HAL_ASSERT(linearTables->entry);
323
324 for (i = 0; i < linearTables->nEntry; i++) {
325 range = &linearTables->entry[i];
326 if (sel < range->minSel || sel > range->maxSel) {
327 continue;
328 }
329
330 sel -= range->minSel;
331
332 return range->minUV + (range->uVStep * sel);
333 }
334
335 return HAL_INVAL;
336 }
337 /**
338 * @brief use linear ranges to convert voltage to seletor.
339 * @param linearTables: the power linear range table pointer.
340 * @param volt: the volt value to be converted
341 * @return voltage value.
342 */
HAL_PWR_LinearRangeVoltToSel(const struct PWR_LINEAR_RANGE_TABLE * linearTables,uint32_t volt)343 int HAL_PWR_LinearRangeVoltToSel(const struct PWR_LINEAR_RANGE_TABLE *linearTables, uint32_t volt)
344 {
345 const struct PWR_LINEAR_RANGE *range;
346 int ret = HAL_INVAL;
347 int i;
348
349 HAL_ASSERT(linearTables);
350 HAL_ASSERT(linearTables->entry);
351
352 for (i = 0; i < linearTables->nEntry; i++) {
353 unsigned int linear_max_uV;
354
355 range = &linearTables->entry[i];
356 HAL_ASSERT(range->maxSel >= range->minSel);
357 linear_max_uV = range->minUV +
358 (range->maxSel - range->minSel) * range->uVStep;
359
360 if (volt > linear_max_uV || volt < range->minUV) {
361 continue;
362 }
363
364 /* range->uV_step == 0 means fixed voltage range */
365 if (range->uVStep == 0) {
366 ret = 0;
367 } else {
368 ret = HAL_DIV_ROUND_UP(volt - range->minUV,
369 range->uVStep);
370 if (ret < 0) {
371 return ret;
372 }
373 }
374
375 ret += range->minSel;
376
377 break;
378 }
379
380 return ret;
381 }
382
383 /** @} */
384
385 /** @} */
386
387 /** @} */
388
389 #endif /* HAL_PWR_MODULE_ENABLED */
390