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