1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "regulator_core.h"
10 #include "hdf_log.h"
11 #include "osal_mem.h"
12 #include "osal_time.h"
13 #include "securec.h"
14 #include "regulator_tree_mgr.h"
15
16 #define HDF_LOG_TAG regulator_core
17 struct RegulatorManager {
18 struct IDeviceIoService service;
19 struct HdfDeviceObject *device;
20 struct DListHead regulatorHead;
21 struct OsalMutex lock;
22 };
23
24 static struct RegulatorManager *g_regulatorManager = NULL;
25
RegulatorNodeOpen(const char * name)26 struct RegulatorNode *RegulatorNodeOpen(const char *name)
27 {
28 CHECK_NULL_PTR_RETURN_VALUE(name, NULL);
29 struct RegulatorNode *pos = NULL;
30 struct RegulatorNode *tmp = NULL;
31
32 struct RegulatorManager *manager = g_regulatorManager;
33 CHECK_NULL_PTR_RETURN_VALUE(manager, NULL);
34
35 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
36 HDF_LOGE("RegulatorNodeOpen: lock regulator manager fail!");
37 return NULL;
38 }
39
40 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->regulatorHead, struct RegulatorNode, node) {
41 if (strcmp(name, pos->regulatorInfo.name) == 0) {
42 if ((pos->ops->open != NULL) && pos->ops->open(pos) != HDF_SUCCESS) {
43 (void)OsalMutexUnlock(&manager->lock);
44 HDF_LOGE("RegulatorNodeOpen: open regulator[%s] fail!", name);
45 return NULL;
46 }
47 (void)OsalMutexUnlock(&manager->lock);
48 return pos;
49 }
50 }
51
52 (void)OsalMutexUnlock(&manager->lock);
53 HDF_LOGE("RegulatorNodeOpen: No %s regulator exist", name);
54 return NULL;
55 }
56
RegulatorNodeClose(struct RegulatorNode * node)57 int32_t RegulatorNodeClose(struct RegulatorNode *node)
58 {
59 CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_OBJECT);
60 return HDF_SUCCESS;
61 }
62
RegulatorNodeListPrint(void)63 void RegulatorNodeListPrint(void)
64 {
65 struct RegulatorNode *pos = NULL;
66 struct RegulatorNode *tmp = NULL;
67
68 struct RegulatorManager *manager = g_regulatorManager;
69 CHECK_NULL_PTR_RETURN(manager);
70
71 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
72 HDF_LOGE("RegulatorNodeListPrint: lock regulator manager fail!");
73 return;
74 }
75
76 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->regulatorHead, struct RegulatorNode, node) {
77 HDF_LOGI("RegulatorNodeListPrint: name[%s], [%u][%hhu][%hhu], [%u][%u]--[%u][%u]",
78 pos->regulatorInfo.name, pos->regulatorInfo.status,
79 pos->regulatorInfo.constraints.alwaysOn, pos->regulatorInfo.constraints.mode,
80 pos->regulatorInfo.constraints.minUv, pos->regulatorInfo.constraints.maxUv,
81 pos->regulatorInfo.constraints.minUa, pos->regulatorInfo.constraints.maxUa);
82 if ((pos->regulatorInfo.parentName != NULL) && (strlen(pos->regulatorInfo.parentName) > 0)) {
83 HDF_LOGI("RegulatorNodeListPrint:parentName[%s]", pos->regulatorInfo.parentName);
84 }
85 }
86
87 (void)OsalMutexUnlock(&manager->lock);
88 RegulatorTreePrint();
89 }
90
RegulatorNodeSetParent(struct RegulatorNode * node)91 int32_t RegulatorNodeSetParent(struct RegulatorNode *node)
92 {
93 CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM);
94 struct RegulatorNode *pos = NULL;
95 struct RegulatorNode *tmp = NULL;
96 struct RegulatorManager *manager = g_regulatorManager;
97 CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE);
98
99 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
100 HDF_LOGE("RegulatorNodeSetParent: lock regulator manager fail!");
101 return HDF_ERR_DEVICE_BUSY;
102 }
103 // parent set
104 if ((node->regulatorInfo.parentName != NULL)
105 && (strlen(node->regulatorInfo.parentName) > 0)) {
106 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->regulatorHead, struct RegulatorNode, node) {
107 if (strcmp(node->regulatorInfo.parentName, pos->regulatorInfo.name) == 0) {
108 if (RegulatorTreeSet(node->regulatorInfo.name, node, pos) != HDF_SUCCESS) {
109 HDF_LOGE("%s: RegulatorTreeSet failed", __func__);
110 (void)OsalMutexUnlock(&manager->lock);
111 return HDF_FAILURE;
112 } else {
113 HDF_LOGI("%s:regulator [%s] RegulatorTreeSet success", __func__, node->regulatorInfo.name);
114 (void)OsalMutexUnlock(&manager->lock);
115 return HDF_SUCCESS;
116 }
117 }
118 }
119
120 HDF_LOGE("%s: RegulatorTreeSet find %s parent %s error",
121 __func__, node->regulatorInfo.name, node->regulatorInfo.parentName);
122 (void)OsalMutexUnlock(&manager->lock);
123 return HDF_FAILURE;
124 }
125
126 (void)OsalMutexUnlock(&manager->lock);
127 HDF_LOGD("%s: the node %s no need to set parent", __func__, node->regulatorInfo.name);
128 return HDF_SUCCESS;
129 }
130
RegulatorNodeSetChild(struct RegulatorNode * parent)131 int32_t RegulatorNodeSetChild(struct RegulatorNode *parent)
132 {
133 CHECK_NULL_PTR_RETURN_VALUE(parent, HDF_ERR_INVALID_PARAM);
134 struct RegulatorNode *pos = NULL;
135 struct RegulatorNode *tmp = NULL;
136 struct RegulatorManager *manager = g_regulatorManager;
137 CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE);
138
139 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
140 HDF_LOGE("RegulatorNodeSetChild: lock regulator manager fail!");
141 return HDF_ERR_DEVICE_BUSY;
142 }
143
144 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->regulatorHead, struct RegulatorNode, node) {
145 if ((pos->regulatorInfo.parentName != NULL) &&
146 (strcmp(parent->regulatorInfo.name, pos->regulatorInfo.parentName) == 0)) {
147 HDF_LOGD("%s: node[%s] parent is %s, tree info process", __func__,
148 pos->regulatorInfo.parentName, parent->regulatorInfo.name);
149 if (RegulatorTreeSet(pos->regulatorInfo.name, pos, parent) != HDF_SUCCESS) {
150 HDF_LOGE("%s: RegulatorTreeSet failed", __func__);
151 (void)OsalMutexUnlock(&manager->lock);
152 return HDF_FAILURE;
153 }
154 }
155 }
156
157 HDF_LOGD("%s: the node %s child info process success", __func__, parent->regulatorInfo.name);
158 (void)OsalMutexUnlock(&manager->lock);
159 return HDF_SUCCESS;
160 }
161
RegulatorNodeInitEnable(struct RegulatorNode * node)162 void RegulatorNodeInitEnable(struct RegulatorNode *node)
163 {
164 CHECK_NULL_PTR_RETURN(node);
165 if (node->regulatorInfo.status == REGULATOR_STATUS_ON) {
166 HDF_LOGD("RegulatorNodeInitEnable: %s status on", node->regulatorInfo.name);
167 return;
168 }
169
170 bool isChildAlwayson = RegulatorTreeIsChildAlwayson(node->regulatorInfo.name);
171 bool isChildOn = RegulatorTreeIsChildStatusOn(node->regulatorInfo.name);
172 // if regulator alwaysOn is true or there is child's alwaysOn is true or there is child's status on, then process
173 if ((node->regulatorInfo.constraints.alwaysOn) || (isChildAlwayson) || (isChildOn)) {
174 // RegulatorTreeIsUpNodeComplete is false, call RegulatorNodeEnable will fail.
175 if (RegulatorTreeIsUpNodeComplete(node->regulatorInfo.name)) {
176 HDF_LOGD("RegulatorNodeInitEnable: %s UpNodeComplete", node->regulatorInfo.name);
177 RegulatorNodeEnable(node);
178 return;
179 }
180 if (OsalMutexLock(&node->lock) != HDF_SUCCESS) {
181 HDF_LOGE("RegulatorNodeInitEnable: lock regulator %s fail!", node->regulatorInfo.name);
182 return;
183 }
184 // first enable
185 if (node->ops->enable(node) != HDF_SUCCESS) {
186 (void)OsalMutexUnlock(&node->lock);
187 HDF_LOGE("RegulatorNodeInitEnable: %s failed", node->regulatorInfo.name);
188 return;
189 }
190 node->regulatorInfo.status = REGULATOR_STATUS_ON;
191 RegulatorNodeStatusCb(node);
192
193 (void)OsalMutexUnlock(&node->lock);
194 HDF_LOGD("RegulatorNodeInitEnable: %s success", node->regulatorInfo.name);
195 return;
196 }
197 }
198
199 /*
200 * complete up and down management topology
201 * process alwayson
202 */
RegulatorNodeInitProcess(struct RegulatorNode * node)203 int32_t RegulatorNodeInitProcess(struct RegulatorNode *node)
204 {
205 CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM);
206
207 // parent or child set
208 if (RegulatorNodeSetParent(node) != HDF_SUCCESS) {
209 HDF_LOGD("%s: node %s RegulatorNodeSetParent fail, parent not add", __func__, node->regulatorInfo.name);
210 }
211
212 if (RegulatorNodeSetChild(node) != HDF_SUCCESS) {
213 HDF_LOGE("%s: node %s RegulatorNodeSetChild fail", __func__, node->regulatorInfo.name);
214 return HDF_FAILURE;
215 }
216
217 if (node->regulatorInfo.constraints.mode == REGULATOR_CHANGE_CURRENT) {
218 RegulatorNodeSetCurrent(node, node->regulatorInfo.constraints.minUa, node->regulatorInfo.constraints.maxUa);
219 } else if (node->regulatorInfo.constraints.mode == REGULATOR_CHANGE_VOLTAGE) {
220 RegulatorNodeSetVoltage(node, node->regulatorInfo.constraints.minUv, node->regulatorInfo.constraints.maxUv);
221 }
222
223 RegulatorNodeInitEnable(node);
224
225 HDF_LOGD("%s: the node %s init success", __func__, node->regulatorInfo.name);
226 return HDF_SUCCESS;
227 }
228
RegulatorNodeAdd(struct RegulatorNode * node)229 int32_t RegulatorNodeAdd(struct RegulatorNode *node)
230 {
231 CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM);
232 CHECK_NULL_PTR_RETURN_VALUE(node->ops, HDF_ERR_INVALID_PARAM);
233 struct RegulatorNode *pos = NULL;
234 struct RegulatorNode *tmp = NULL;
235 struct RegulatorManager *manager = g_regulatorManager;
236 CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE);
237
238 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->regulatorHead, struct RegulatorNode, node) {
239 if (strcmp(node->regulatorInfo.name, pos->regulatorInfo.name) == 0) {
240 HDF_LOGE("%s: regulatorInfo[%s] existed", __func__, node->regulatorInfo.name);
241 return HDF_FAILURE;
242 }
243 }
244
245 // init node info
246 node->regulatorInfo.cb = NULL;
247 node->regulatorInfo.useCount = 0;
248 node->regulatorInfo.status = REGULATOR_STATUS_OFF;
249 node->regulatorInfo.useCount = 0;
250 if (OsalMutexInit(&node->lock) != HDF_SUCCESS) {
251 HDF_LOGE("%s: OsalMutexInit %s failed", __func__, node->regulatorInfo.name);
252 return HDF_FAILURE;
253 }
254
255 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
256 HDF_LOGE("RegulatorManagerAddNode: lock regulator manager fail!");
257 return HDF_ERR_DEVICE_BUSY;
258 }
259 DListInsertTail(&node->node, &manager->regulatorHead);
260 (void)OsalMutexUnlock(&manager->lock);
261
262 if (RegulatorNodeInitProcess(node) != HDF_SUCCESS) {
263 HDF_LOGE("%s: node %s RegulatorNodeInitProcess fail", __func__, node->regulatorInfo.name);
264 return HDF_FAILURE;
265 }
266
267 HDF_LOGI("%s: add regulator name[%s] success", __func__, node->regulatorInfo.name);
268
269 return HDF_SUCCESS;
270 }
271
RegulatorNodeRemove(const char * name)272 int32_t RegulatorNodeRemove(const char *name)
273 {
274 CHECK_NULL_PTR_RETURN_VALUE(name, HDF_ERR_INVALID_PARAM);
275
276 struct RegulatorNode *pos = NULL;
277 struct RegulatorNode *tmp = NULL;
278 struct RegulatorManager *manager = g_regulatorManager;
279 if (manager == NULL) {
280 HDF_LOGE("RegulatorNodeRemoveAll: regulator manager null!");
281 return HDF_ERR_NOT_SUPPORT;
282 }
283
284 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
285 HDF_LOGE("RegulatorNodeRemoveAll: lock regulator manager fail!");
286 return HDF_ERR_DEVICE_BUSY;
287 }
288
289 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->regulatorHead, struct RegulatorNode, node) {
290 if (strcmp(pos->regulatorInfo.name, name) == 0) {
291 if ((pos->ops->release != NULL) && pos->ops->release(pos) != HDF_SUCCESS) {
292 HDF_LOGE("RegulatorNodeRemoveAll: release regulator[%s] fail!", pos->regulatorInfo.name);
293 }
294 DListRemove(&pos->node);
295 (void)OsalMutexDestroy(&pos->lock);
296 OsalMemFree(pos);
297 break;
298 }
299 }
300
301 (void)OsalMutexUnlock(&manager->lock);
302 HDF_LOGI("%s: remove regulator %s success", __func__, name);
303 return HDF_SUCCESS;
304 }
305
RegulatorNodeRemoveAll(void)306 int32_t RegulatorNodeRemoveAll(void)
307 {
308 if (RegulatorTreeNodeRemoveAll() != HDF_SUCCESS) {
309 HDF_LOGE("RegulatorNodeRemoveAll: RegulatorTreeNodeRemoveAll failed");
310 return HDF_FAILURE;
311 }
312
313 struct RegulatorNode *pos = NULL;
314 struct RegulatorNode *tmp = NULL;
315 struct RegulatorManager *manager = g_regulatorManager;
316 if (manager == NULL) {
317 HDF_LOGE("RegulatorNodeRemoveAll: regulator manager null!");
318 return HDF_ERR_NOT_SUPPORT;
319 }
320
321 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
322 HDF_LOGE("RegulatorNodeRemoveAll: lock regulator manager fail!");
323 return HDF_ERR_DEVICE_BUSY;
324 }
325
326 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->regulatorHead, struct RegulatorNode, node) {
327 if ((pos->ops->release != NULL) && pos->ops->release(pos) != HDF_SUCCESS) {
328 HDF_LOGE("RegulatorNodeRemoveAll: release regulator[%s] fail!", pos->regulatorInfo.name);
329 }
330 DListRemove(&pos->node);
331 (void)OsalMutexDestroy(&pos->lock);
332 OsalMemFree(pos);
333 }
334
335 (void)OsalMutexUnlock(&manager->lock);
336 HDF_LOGI("%s: remove all regulator success", __func__);
337 return HDF_SUCCESS;
338 }
339
RegulatorNodeStatusCb(struct RegulatorNode * node)340 int32_t RegulatorNodeStatusCb(struct RegulatorNode *node)
341 {
342 CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM);
343 CHECK_NULL_PTR_RETURN_VALUE(node->regulatorInfo.cb, HDF_SUCCESS);
344 struct RegulatorStatusChangeInfo info;
345 (void)memset_s(&info, sizeof(struct RegulatorStatusChangeInfo), 0, sizeof(struct RegulatorStatusChangeInfo));
346
347 info.status = node->regulatorInfo.status;
348 info.name = node->regulatorInfo.name;
349 HDF_LOGI("%s: Cb %s %u", __func__, info.name, info.status);
350
351 return node->regulatorInfo.cb(&info);
352 }
353
RegulatorNodeEnable(struct RegulatorNode * node)354 int32_t RegulatorNodeEnable(struct RegulatorNode *node)
355 {
356 CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM);
357 if (node->regulatorInfo.status == REGULATOR_STATUS_ON) {
358 HDF_LOGD("RegulatorNodeEnable: %s status on", node->regulatorInfo.name);
359 return HDF_SUCCESS;
360 }
361
362 if (OsalMutexLock(&node->lock) != HDF_SUCCESS) {
363 HDF_LOGE("RegulatorNodeEnable: lock regulator %s fail!", node->regulatorInfo.name);
364 return HDF_ERR_DEVICE_BUSY;
365 }
366
367 if ((node->regulatorInfo.parentName != NULL) && (strlen(node->regulatorInfo.parentName) > 0)) {
368 struct RegulatorNode *parent = RegulatorTreeGetParent(node->regulatorInfo.name);
369 if (parent == NULL) {
370 (void)OsalMutexUnlock(&node->lock);
371 HDF_LOGE("RegulatorNodeEnable: %s failed", node->regulatorInfo.name);
372 return HDF_FAILURE;
373 }
374 if (RegulatorNodeEnable(parent) != HDF_SUCCESS) {
375 (void)OsalMutexUnlock(&node->lock);
376 HDF_LOGE("RegulatorNodeEnable: %s failed", parent->regulatorInfo.name);
377 return HDF_FAILURE;
378 }
379 }
380
381 // first enable
382 if (node->ops->enable(node) != HDF_SUCCESS) {
383 (void)OsalMutexUnlock(&node->lock);
384 HDF_LOGE("RegulatorNodeEnable:enable: %s failed", node->regulatorInfo.name);
385 return HDF_FAILURE;
386 }
387 RegulatorNodeStatusCb(node);
388
389 (void)OsalMutexUnlock(&node->lock);
390 return HDF_SUCCESS;
391 }
392
RegulatorNodeDisable(struct RegulatorNode * node)393 int32_t RegulatorNodeDisable(struct RegulatorNode *node)
394 {
395 CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM);
396 if ((node->regulatorInfo.status == REGULATOR_STATUS_OFF) || (node->regulatorInfo.constraints.alwaysOn)) {
397 HDF_LOGI("RegulatorNodeDisable: %s [%u][%hhu], unsatisfied closing adjusment",
398 node->regulatorInfo.name, node->regulatorInfo.status, node->regulatorInfo.constraints.alwaysOn);
399 return HDF_SUCCESS;
400 }
401
402 if (OsalMutexLock(&node->lock) != HDF_SUCCESS) {
403 HDF_LOGE("RegulatorNodeDisable: lock regulator %s fail!", node->regulatorInfo.name);
404 return HDF_ERR_DEVICE_BUSY;
405 }
406
407 if (!RegulatorTreeIsAllChildDisable(node->regulatorInfo.name)) {
408 (void)OsalMutexUnlock(&node->lock);
409 HDF_LOGE("RegulatorNodeDisable:there is %s child not disable, so disable node failed",
410 node->regulatorInfo.name);
411 return HDF_FAILURE;
412 }
413
414 // the regulator no user, can disable
415
416 if (node->ops->disable(node) != HDF_SUCCESS) {
417 (void)OsalMutexUnlock(&node->lock);
418 HDF_LOGE("RegulatorNodeDisable:disable %s failed", node->regulatorInfo.name);
419 return HDF_FAILURE;
420 }
421
422 RegulatorNodeStatusCb(node);
423
424 // set parent
425 if ((node->regulatorInfo.parentName != NULL) && (strlen(node->regulatorInfo.parentName) > 0)) {
426 struct RegulatorNode *parent = RegulatorTreeGetParent(node->regulatorInfo.name);
427 if (parent == NULL) {
428 (void)OsalMutexUnlock(&node->lock);
429 HDF_LOGE("RegulatorNodeDisable: %s failed", node->regulatorInfo.name);
430 return HDF_FAILURE;
431 }
432 if (RegulatorNodeDisable(parent) != HDF_SUCCESS) {
433 (void)OsalMutexUnlock(&node->lock);
434 HDF_LOGD("RegulatorNodeDisable: disable %s's parent %s failed",
435 node->regulatorInfo.name, parent->regulatorInfo.name);
436 return HDF_SUCCESS;
437 }
438 }
439
440 (void)OsalMutexUnlock(&node->lock);
441 return HDF_SUCCESS;
442 }
443
RegulatorNodeForceDisable(struct RegulatorNode * node)444 int32_t RegulatorNodeForceDisable(struct RegulatorNode *node)
445 {
446 CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM);
447 if (OsalMutexLock(&node->lock) != HDF_SUCCESS) {
448 HDF_LOGE(": lock regulator %s fail!", node->regulatorInfo.name);
449 return HDF_ERR_DEVICE_BUSY;
450 }
451
452 if (node->regulatorInfo.status == REGULATOR_STATUS_OFF) {
453 (void)OsalMutexUnlock(&node->lock);
454 return HDF_SUCCESS;
455 }
456
457 // if the regulator force disable ,set all child node disable
458 if (RegulatorTreeChildForceDisable(node) != HDF_SUCCESS) {
459 (void)OsalMutexUnlock(&node->lock);
460 HDF_LOGE("RegulatorNodeForceDisable--RegulatorTreeConsumerForceDisable: %s failed", node->regulatorInfo.name);
461 return HDF_FAILURE;
462 }
463
464 if (node->ops->forceDisable != NULL) {
465 if (node->ops->forceDisable(node) != HDF_SUCCESS) {
466 (void)OsalMutexUnlock(&node->lock);
467 HDF_LOGE("RegulatorNodeForceDisable:forceDisable %s failed", node->regulatorInfo.name);
468 return HDF_FAILURE;
469 }
470 } else if (node->ops->disable(node) != HDF_SUCCESS) {
471 (void)OsalMutexUnlock(&node->lock);
472 HDF_LOGE("RegulatorNodeForceDisable:disable %s failed", node->regulatorInfo.name);
473 return HDF_FAILURE;
474 }
475 node->regulatorInfo.status = REGULATOR_STATUS_OFF;
476 RegulatorNodeStatusCb(node);
477 HDF_LOGI("RegulatorNodeForceDisable:regulator %s force disable success", node->regulatorInfo.name);
478
479 // set parent
480 if ((node->regulatorInfo.parentName != NULL) && (strlen(node->regulatorInfo.parentName) > 0)) {
481 struct RegulatorNode *parent = RegulatorTreeGetParent(node->regulatorInfo.name);
482 if (parent == NULL) {
483 (void)OsalMutexUnlock(&node->lock);
484 HDF_LOGE(": %s failed", node->regulatorInfo.name);
485 return HDF_FAILURE;
486 }
487 if (RegulatorNodeDisable(parent) != HDF_SUCCESS) {
488 (void)OsalMutexUnlock(&node->lock);
489 HDF_LOGD("RegulatorNodeDisable: disable %s's parent %s failed",
490 node->regulatorInfo.name, parent->regulatorInfo.name);
491 return HDF_SUCCESS;
492 }
493 }
494
495 (void)OsalMutexUnlock(&node->lock);
496 return HDF_SUCCESS;
497 }
498
RegulatorNodeSetVoltage(struct RegulatorNode * node,uint32_t minUv,uint32_t maxUv)499 int32_t RegulatorNodeSetVoltage(struct RegulatorNode *node, uint32_t minUv, uint32_t maxUv)
500 {
501 CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM);
502 if (node->regulatorInfo.constraints.mode != REGULATOR_CHANGE_VOLTAGE) {
503 HDF_LOGE("RegulatorNodeSetVoltage: %s mode %d invalid!",
504 node->regulatorInfo.name, node->regulatorInfo.constraints.mode);
505 return HDF_FAILURE;
506 }
507
508 if (minUv == node->regulatorInfo.minUv && maxUv == node->regulatorInfo.maxUv) {
509 return HDF_SUCCESS;
510 }
511
512 if ((minUv > maxUv) ||
513 (minUv < node->regulatorInfo.constraints.minUv ||
514 maxUv > node->regulatorInfo.constraints.maxUv)) {
515 HDF_LOGE("RegulatorNodeSetVoltage: %s Uv [%u, %u] invalid!",
516 node->regulatorInfo.name, minUv, maxUv);
517 return HDF_FAILURE;
518 }
519
520 if (OsalMutexLock(&node->lock) != HDF_SUCCESS) {
521 HDF_LOGE("RegulatorNodeSetVoltage: lock regulator %s fail!", node->regulatorInfo.name);
522 return HDF_ERR_DEVICE_BUSY;
523 }
524
525 int ret = node->ops->setVoltage(node, minUv, maxUv);
526 if (ret != HDF_SUCCESS) {
527 (void)OsalMutexUnlock(&node->lock);
528 HDF_LOGE("RegulatorNodeSetVoltage: setVoltage %s fail!", node->regulatorInfo.name);
529 return HDF_FAILURE;
530 }
531
532 node->regulatorInfo.minUv = minUv;
533 node->regulatorInfo.maxUv = maxUv;
534 (void)OsalMutexUnlock(&node->lock);
535
536 return HDF_SUCCESS;
537 }
538
RegulatorNodeGetVoltage(struct RegulatorNode * node,uint32_t * voltage)539 int32_t RegulatorNodeGetVoltage(struct RegulatorNode *node, uint32_t *voltage)
540 {
541 CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM);
542 CHECK_NULL_PTR_RETURN_VALUE(voltage, HDF_ERR_INVALID_PARAM);
543
544 if (node->regulatorInfo.constraints.mode != REGULATOR_CHANGE_VOLTAGE) {
545 HDF_LOGE("RegulatorNodeSetVoltage: %s mode %hhu invalid!",
546 node->regulatorInfo.name, node->regulatorInfo.constraints.mode);
547 return HDF_FAILURE;
548 }
549
550 int ret = node->ops->getVoltage(node, voltage);
551 if (ret != HDF_SUCCESS) {
552 HDF_LOGE("RegulatorNodeGetVoltage: getVoltage %s fail!", node->regulatorInfo.name);
553 return HDF_FAILURE;
554 }
555
556 return HDF_SUCCESS;
557 }
558
RegulatorNodeSetCurrent(struct RegulatorNode * node,uint32_t minUA,uint32_t maxUA)559 int32_t RegulatorNodeSetCurrent(struct RegulatorNode *node, uint32_t minUA, uint32_t maxUA)
560 {
561 CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM);
562 if (node->regulatorInfo.constraints.mode != REGULATOR_CHANGE_CURRENT) {
563 HDF_LOGE("RegulatorNodeSetVoltage: %s mode %hhu invalid!",
564 node->regulatorInfo.name, node->regulatorInfo.constraints.mode);
565 return HDF_FAILURE;
566 }
567
568 if (minUA == node->regulatorInfo.minUa && maxUA == node->regulatorInfo.maxUa) {
569 return HDF_SUCCESS;
570 }
571
572 if ((minUA > maxUA) ||
573 (minUA < node->regulatorInfo.constraints.minUa ||
574 maxUA > node->regulatorInfo.constraints.maxUa)) {
575 HDF_LOGE("RegulatorNodeSetCurrent: %s UA [%u, %u] invalid!",
576 node->regulatorInfo.name, minUA, maxUA);
577 return HDF_FAILURE;
578 }
579
580 if (OsalMutexLock(&node->lock) != HDF_SUCCESS) {
581 HDF_LOGE("RegulatorNodeSetCurrent: lock regulator %s fail!", node->regulatorInfo.name);
582 return HDF_ERR_DEVICE_BUSY;
583 }
584
585 int ret = node->ops->setCurrent(node, minUA, maxUA);
586 if (ret != HDF_SUCCESS) {
587 (void)OsalMutexUnlock(&node->lock);
588 HDF_LOGE("RegulatorNodeSetCurrent: setCurrent %s fail!", node->regulatorInfo.name);
589 return HDF_FAILURE;
590 }
591
592 node->regulatorInfo.minUa = minUA;
593 node->regulatorInfo.maxUa = maxUA;
594 (void)OsalMutexUnlock(&node->lock);
595 return HDF_SUCCESS;
596 }
597
RegulatorNodeGetCurrent(struct RegulatorNode * node,uint32_t * regCurrent)598 int32_t RegulatorNodeGetCurrent(struct RegulatorNode *node, uint32_t *regCurrent)
599 {
600 CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_OBJECT);
601 CHECK_NULL_PTR_RETURN_VALUE(regCurrent, HDF_ERR_INVALID_OBJECT);
602 if (node->regulatorInfo.constraints.mode != REGULATOR_CHANGE_CURRENT) {
603 HDF_LOGE("RegulatorNodeGetCurrent: %s mode %hhu invalid!",
604 node->regulatorInfo.name, node->regulatorInfo.constraints.mode);
605 return HDF_FAILURE;
606 }
607
608 int ret = node->ops->getCurrent(node, regCurrent);
609 if (ret != HDF_SUCCESS) {
610 HDF_LOGE("RegulatorNodeGetCurrent: getCurrent %s fail!", node->regulatorInfo.name);
611 return HDF_FAILURE;
612 }
613
614 return HDF_SUCCESS;
615 }
616
RegulatorNodeGetStatus(struct RegulatorNode * node,uint32_t * status)617 int32_t RegulatorNodeGetStatus(struct RegulatorNode *node, uint32_t *status)
618 {
619 CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_OBJECT);
620 CHECK_NULL_PTR_RETURN_VALUE(status, HDF_ERR_INVALID_OBJECT);
621 if (node->ops->getStatus(node, status) != HDF_SUCCESS) {
622 HDF_LOGE("RegulatorNodeGetStatus: getStatus %s fail!", node->regulatorInfo.name);
623 return HDF_FAILURE;
624 }
625
626 return HDF_SUCCESS;
627 }
628
RegulatorNodeRegisterStatusChangeCb(struct RegulatorNode * node,RegulatorStatusChangecb cb)629 int32_t RegulatorNodeRegisterStatusChangeCb(struct RegulatorNode *node, RegulatorStatusChangecb cb)
630 {
631 CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_OBJECT);
632 CHECK_NULL_PTR_RETURN_VALUE(cb, HDF_ERR_INVALID_OBJECT);
633 node->regulatorInfo.cb = cb;
634 return HDF_SUCCESS;
635 }
636
RegulatorTreeInfoInit(struct RegulatorNode * node)637 int32_t RegulatorTreeInfoInit(struct RegulatorNode *node)
638 {
639 struct RegulatorNode *pos = NULL;
640 struct RegulatorNode *tmp = NULL;
641 CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_OBJECT);
642 struct RegulatorManager *manager = g_regulatorManager;
643 CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_ERR_INVALID_OBJECT);
644
645 if ((node->regulatorInfo.parentName != NULL)
646 && (strlen(node->regulatorInfo.parentName) > 0)) {
647 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->regulatorHead, struct RegulatorNode, node) {
648 if (strcmp(node->regulatorInfo.parentName, pos->regulatorInfo.name) == 0) {
649 if (RegulatorTreeSet(node->regulatorInfo.name, node, pos) != HDF_SUCCESS) {
650 HDF_LOGE("%s: RegulatorTreeSet failed", __func__);
651 return HDF_FAILURE;
652 } else {
653 HDF_LOGI("%s:regulator [%s] RegulatorTreeSet success", __func__, node->regulatorInfo.name);
654 return HDF_SUCCESS;
655 }
656 }
657 }
658
659 HDF_LOGE("%s: RegulatorTreeSet find %s parent %s error",
660 __func__, node->regulatorInfo.name, node->regulatorInfo.parentName);
661 return HDF_FAILURE;
662 }
663 return HDF_SUCCESS;
664 }
665
RegulatorManagerBind(struct HdfDeviceObject * device)666 static int32_t RegulatorManagerBind(struct HdfDeviceObject *device)
667 {
668 int32_t ret;
669 struct RegulatorManager *manager = NULL;
670
671 HDF_LOGI("RegulatorManagerBind: Enter!");
672 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_OBJECT);
673
674 manager = (struct RegulatorManager *)OsalMemCalloc(sizeof(*manager));
675 if (manager == NULL) {
676 HDF_LOGE("RegulatorManagerBind: malloc manager fail!");
677 return HDF_ERR_MALLOC_FAIL;
678 }
679
680 ret = OsalMutexInit(&manager->lock);
681 if (ret != HDF_SUCCESS) {
682 HDF_LOGE("RegulatorManagerBind: mutex init fail:%d", ret);
683 OsalMemFree(manager);
684 return HDF_FAILURE;
685 }
686
687 manager->device = device;
688 device->service = &manager->service;
689 DListHeadInit(&manager->regulatorHead);
690 g_regulatorManager = manager;
691
692 if (RegulatorTreeManagerInit() != HDF_SUCCESS) {
693 HDF_LOGE("RegulatorManagerBind: RegulatorTreeManagerInit init fail");
694 OsalMemFree(manager);
695 return HDF_FAILURE;
696 }
697 HDF_LOGI("RegulatorManagerBind: success!");
698 return HDF_SUCCESS;
699 }
700
RegulatorManagerInit(struct HdfDeviceObject * device)701 static int32_t RegulatorManagerInit(struct HdfDeviceObject *device)
702 {
703 (void)device;
704
705 HDF_LOGI("RegulatorManagerInit: success!");
706 return HDF_SUCCESS;
707 }
708
RegulatorManagerRelease(struct HdfDeviceObject * device)709 static void RegulatorManagerRelease(struct HdfDeviceObject *device)
710 {
711 HDF_LOGI("RegulatorManagerRelease: enter");
712 CHECK_NULL_PTR_RETURN(device);
713
714 if (RegulatorNodeRemoveAll() != HDF_SUCCESS) {
715 HDF_LOGE("RegulatorNodeRemoveAll failed");
716 return;
717 }
718
719 struct RegulatorManager *manager = (struct RegulatorManager *)device->service;
720 CHECK_NULL_PTR_RETURN(manager);
721 OsalMutexDestroy(&manager->lock);
722 OsalMemFree(manager);
723 g_regulatorManager = NULL;
724
725 if (RegulatorTreeManagerDestory() != HDF_SUCCESS) {
726 HDF_LOGE("RegulatorTreeManagerDestory failed");
727 return;
728 }
729 }
730
731 struct HdfDriverEntry g_regulatorManagerEntry = {
732 .moduleVersion = 1,
733 .Bind = RegulatorManagerBind,
734 .Init = RegulatorManagerInit,
735 .Release = RegulatorManagerRelease,
736 .moduleName = "HDF_PLATFORM_REGULATOR_MANAGER",
737 };
738
739 HDF_INIT(g_regulatorManagerEntry);
740