From dc75a392ffe74347c499808efd99ff6cd309e70f Mon Sep 17 00:00:00 2001 From: s00442234 Date: Sat, 18 Dec 2021 16:39:07 +0800 Subject: [PATCH] feat:add linux hdf regulator Signed-off-by: s00442234 --- include/platform/regulator_if.h | 2 +- .../include/regulator/regulator_core.h | 9 +- .../include/regulator/regulator_tree_mgr.h | 5 +- .../platform/src/regulator/regulator_core.c | 1366 +++++++++-------- support/platform/src/regulator/regulator_if.c | 6 +- .../src/regulator/regulator_tree_mgr.c | 117 +- .../unittest/platform/common/regulator_test.c | 25 +- .../regulator_linux_current_virtual_driver.c | 217 +++ .../regulator_linux_current_virtual_driver.h | 15 + .../regulator_linux_voltage_virtual_driver.c | 221 +++ .../regulator_linux_voltage_virtual_driver.h | 15 + .../platform/virtual/regulator_virtual.c | 3 +- 12 files changed, 1335 insertions(+), 666 deletions(-) create mode 100755 test/unittest/platform/virtual/regulator_linux_current_virtual_driver.c create mode 100755 test/unittest/platform/virtual/regulator_linux_current_virtual_driver.h create mode 100755 test/unittest/platform/virtual/regulator_linux_voltage_virtual_driver.c create mode 100755 test/unittest/platform/virtual/regulator_linux_voltage_virtual_driver.h diff --git a/include/platform/regulator_if.h b/include/platform/regulator_if.h index cd1617f1..d3d01a9f 100755 --- a/include/platform/regulator_if.h +++ b/include/platform/regulator_if.h @@ -130,7 +130,7 @@ int32_t RegulatorSetCurrent(DevHandle handle, uint32_t minUa, uint32_t maxUa); * * @since 1.0 */ -int32_t RegulatorGetCurrent(DevHandle handle, uint32_t *current); +int32_t RegulatorGetCurrent(DevHandle handle, uint32_t *regCurrent); /** * @brief Get a regulator status * diff --git a/support/platform/include/regulator/regulator_core.h b/support/platform/include/regulator/regulator_core.h index a46c6f6d..163526e8 100755 --- a/support/platform/include/regulator/regulator_core.h +++ b/support/platform/include/regulator/regulator_core.h @@ -97,12 +97,16 @@ struct RegulatorNode { }; struct RegulatorMethod { + int32_t (*open)(struct RegulatorNode *node); + int32_t (*close)(struct RegulatorNode *node); + int32_t (*release)(struct RegulatorNode *node); int32_t (*enable)(struct RegulatorNode *node); int32_t (*disable)(struct RegulatorNode *node); + int32_t (*forceDisable)(struct RegulatorNode *node); int32_t (*setVoltage)(struct RegulatorNode *node, uint32_t minUv, uint32_t maxUv); int32_t (*getVoltage)(struct RegulatorNode *node, uint32_t *voltage); int32_t (*setCurrent)(struct RegulatorNode *node, uint32_t minUa, uint32_t maxUa); - int32_t (*getCurrent)(struct RegulatorNode *node, uint32_t *current); + int32_t (*getCurrent)(struct RegulatorNode *node, uint32_t *regCurrent); int32_t (*getStatus)(struct RegulatorNode *node, uint32_t *status); }; @@ -120,6 +124,7 @@ int32_t RegulatorNodeClose(struct RegulatorNode *node); * @return success or fail */ int32_t RegulatorNodeAdd(struct RegulatorNode *node); +int32_t RegulatorNodeRemove(const char *name); /** * @brief remove all regulator controllers * @param @@ -173,7 +178,7 @@ int32_t RegulatorNodeSetCurrent(struct RegulatorNode *node, uint32_t minUA, uint * @param current regulator current * @return success or fail */ -int32_t RegulatorNodeGetCurrent(struct RegulatorNode *node, uint32_t *current); +int32_t RegulatorNodeGetCurrent(struct RegulatorNode *node, uint32_t *regCurrent); /** * @brief get regulator status * @param node Indicates a regulator controller. diff --git a/support/platform/include/regulator/regulator_tree_mgr.h b/support/platform/include/regulator/regulator_tree_mgr.h index 035d9cfc..eecd4b2f 100755 --- a/support/platform/include/regulator/regulator_tree_mgr.h +++ b/support/platform/include/regulator/regulator_tree_mgr.h @@ -29,7 +29,7 @@ struct RegulatorTreeInfo { const char *name; /* regulator name */ struct RegulatorNode *parent; /* regulator parent info */ struct DListHead node; - struct DListHead childHead; /* child regulator list */ + struct DListHead childHead; /* next level child regulator list */ }; struct RegulatorTreeManager { @@ -45,6 +45,9 @@ void RegulatorTreePrint(void); struct RegulatorNode *RegulatorTreeGetParent(const char *name); int32_t RegulatorTreeChildForceDisable(struct RegulatorNode *node); bool RegulatorTreeIsAllChildDisable(const char *name); +bool RegulatorTreeIsChildAlwayson(const char *name); +bool RegulatorTreeIsChildStatusOn(const char *name); +bool RegulatorTreeIsUpNodeComplete(const char *name); #ifdef __cplusplus #if __cplusplus diff --git a/support/platform/src/regulator/regulator_core.c b/support/platform/src/regulator/regulator_core.c index 1ff17197..fcfcadd6 100755 --- a/support/platform/src/regulator/regulator_core.c +++ b/support/platform/src/regulator/regulator_core.c @@ -1,627 +1,739 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * - * HDF is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * See the LICENSE file in the root of this repository for complete details. - */ - -#include "regulator_core.h" -#include "hdf_log.h" -#include "osal_mem.h" -#include "osal_time.h" -#include "securec.h" -#include "regulator_tree_mgr.h" - -#define HDF_LOG_TAG regulator_core - -struct RegulatorManager { - struct IDeviceIoService service; - struct HdfDeviceObject *device; - struct DListHead regulatorHead; - struct OsalMutex lock; -}; - -static struct RegulatorManager *g_regulatorManager = NULL; - -struct RegulatorNode *RegulatorNodeOpen(const char *name) -{ - CHECK_NULL_PTR_RETURN_VALUE(name, NULL); - struct RegulatorNode *pos = NULL; - - struct RegulatorManager *manager = g_regulatorManager; - CHECK_NULL_PTR_RETURN_VALUE(manager, NULL); - - if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) { - HDF_LOGE("RegulatorNodeOpen: lock regulator manager fail!"); - return NULL; - } - - DLIST_FOR_EACH_ENTRY(pos, &manager->regulatorHead, struct RegulatorNode, node) { - if (strcmp(name, pos->regulatorInfo.name) == 0) { - HDF_LOGD("RegulatorNodeOpen:[%s] SUCCESS", name); - (void)OsalMutexUnlock(&manager->lock); - return pos; - } - } - - (void)OsalMutexUnlock(&manager->lock); - HDF_LOGE("RegulatorNodeOpen: No %s regulator exist", name); - return NULL; -} - -int32_t RegulatorNodeClose(struct RegulatorNode *node) -{ - CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_OBJECT); - return HDF_SUCCESS; -} - -void RegulatorNodeListPrint(void) -{ - struct RegulatorNode *pos = NULL; - - struct RegulatorManager *manager = g_regulatorManager; - CHECK_NULL_PTR_RETURN(manager); - - if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) { - HDF_LOGE("RegulatorNodeListPrint: lock regulator manager fail!"); - return; - } - - DLIST_FOR_EACH_ENTRY(pos, &manager->regulatorHead, struct RegulatorNode, node) { - HDF_LOGI("RegulatorNodeListPrint: name[%s], [%d][%d][%d], [%d][%d]--[%d][%d]", - pos->regulatorInfo.name, pos->regulatorInfo.status, - pos->regulatorInfo.constraints.alwaysOn, pos->regulatorInfo.constraints.mode, - pos->regulatorInfo.minUv, pos->regulatorInfo.maxUv, - pos->regulatorInfo.minUa, pos->regulatorInfo.maxUa); - if (pos->regulatorInfo.parentName != NULL) { - HDF_LOGI("RegulatorNodeListPrint:parentName[%s]", pos->regulatorInfo.parentName); - } - } - - (void)OsalMutexUnlock(&manager->lock); - RegulatorTreePrint(); -} - -int32_t RegulatorNodeSetParent(struct RegulatorNode *node) -{ - CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); - struct RegulatorNode *pos = NULL; - struct RegulatorManager *manager = g_regulatorManager; - CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE); - - if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) { - HDF_LOGE("RegulatorNodeSetParent: lock regulator manager fail!"); - return HDF_ERR_DEVICE_BUSY; - } - // parent set - if ((node->regulatorInfo.parentName != NULL) - && (strlen(node->regulatorInfo.parentName) > 0)) { - DLIST_FOR_EACH_ENTRY(pos, &manager->regulatorHead, struct RegulatorNode, node) { - if (strcmp(node->regulatorInfo.parentName, pos->regulatorInfo.name) == 0) { - if (RegulatorTreeSet(node->regulatorInfo.name, node, pos) != HDF_SUCCESS) { - HDF_LOGE("%s: RegulatorTreeSet failed", __func__); - (void)OsalMutexUnlock(&manager->lock); - return HDF_FAILURE; - } else { - HDF_LOGI("%s:regulator [%s] RegulatorTreeSet success", __func__, node->regulatorInfo.name); - (void)OsalMutexUnlock(&manager->lock); - return HDF_SUCCESS; - } - } - } - - HDF_LOGE("%s: RegulatorTreeSet find %s parent %s error", - __func__, node->regulatorInfo.name, node->regulatorInfo.parentName); - (void)OsalMutexUnlock(&manager->lock); - return HDF_FAILURE; - } - - (void)OsalMutexUnlock(&manager->lock); - HDF_LOGE("%s: the node %s no need to set parent", __func__, node->regulatorInfo.name); - return HDF_SUCCESS; -} - -/** - * complete up and down management topology - * process alwayson - */ -int32_t RegulatorNodeInitProcess(struct RegulatorNode *node) -{ - CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); - - // parent or child set - if (RegulatorNodeSetParent(node) != HDF_SUCCESS) { - HDF_LOGE("%s: node %s RegulatorNodeSetParent fail", __func__, node->regulatorInfo.name); - return HDF_FAILURE; - } - - // if alwaysOn is true, process - if (node->regulatorInfo.constraints.alwaysOn) { - if (node->regulatorInfo.constraints.mode == REGULATOR_CHANGE_CURRENT) { - RegulatorNodeSetCurrent(node, node->regulatorInfo.constraints.minUa, node->regulatorInfo.constraints.maxUa); - } else if (node->regulatorInfo.constraints.mode == REGULATOR_CHANGE_VOLTAGE) { - RegulatorNodeSetVoltage(node, node->regulatorInfo.constraints.minUv, node->regulatorInfo.constraints.maxUv); - } - RegulatorNodeEnable(node); - } - - HDF_LOGD("%s: the node %s init success", __func__, node->regulatorInfo.name); - return HDF_SUCCESS; -} - -int32_t RegulatorNodeAdd(struct RegulatorNode *node) -{ - CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); - struct RegulatorNode *pos = NULL; - struct RegulatorManager *manager = g_regulatorManager; - CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE); - - DLIST_FOR_EACH_ENTRY(pos, &manager->regulatorHead, struct RegulatorNode, node) { - if (strcmp(node->regulatorInfo.name, pos->regulatorInfo.name) == 0) { - HDF_LOGE("%s: regulatorInfo[%s] existed", __func__, node->regulatorInfo.name); - return HDF_FAILURE; - } - } - - // init node info - node->regulatorInfo.cb = NULL; - node->regulatorInfo.useCount = 0; - node->regulatorInfo.status = REGULATOR_STATUS_OFF; - node->regulatorInfo.useCount = 0; - if (OsalMutexInit(&node->lock) != HDF_SUCCESS) { - HDF_LOGE("%s: OsalMutexInit %s failed", __func__, node->regulatorInfo.name); - return HDF_FAILURE; - } - - if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) { - HDF_LOGE("RegulatorManagerAddNode: lock regulator manager fail!"); - return HDF_ERR_DEVICE_BUSY; - } - DListInsertTail(&node->node, &manager->regulatorHead); - (void)OsalMutexUnlock(&manager->lock); - - if (RegulatorNodeInitProcess(node) != HDF_SUCCESS) { - HDF_LOGE("%s: node %s RegulatorNodeInitProcess fail", __func__, node->regulatorInfo.name); - return HDF_FAILURE; - } - - HDF_LOGI("%s: add regulator name[%s] success", __func__, node->regulatorInfo.name); - RegulatorNodeListPrint(); - return HDF_SUCCESS; -} -int32_t RegulatorNodeRemoveAll(void) -{ - if (RegulatorTreeNodeRemoveAll() != HDF_SUCCESS) { - HDF_LOGE("RegulatorNodeRemoveAll: RegulatorTreeNodeRemoveAll failed"); - return HDF_FAILURE; - } - - struct RegulatorNode *pos = NULL; - struct RegulatorManager *manager = g_regulatorManager; - if (manager == NULL) { - HDF_LOGE("RegulatorNodeRemoveAll: regulator manager null!"); - return HDF_ERR_NOT_SUPPORT; - } - - if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) { - HDF_LOGE("RegulatorNodeRemoveAll: lock regulator manager fail!"); - return HDF_ERR_DEVICE_BUSY; - } - - DLIST_FOR_EACH_ENTRY(pos, &manager->regulatorHead, struct RegulatorNode, node) { - DListRemove(&pos->node); - (void)OsalMutexDestroy(&pos->lock); - OsalMemFree(pos); - } - - (void)OsalMutexUnlock(&manager->lock); - HDF_LOGI("%s: remove all regulator success", __func__); - return HDF_SUCCESS; -} -int32_t RegulatorNodeStatusCb(struct RegulatorNode *node) -{ - CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); - CHECK_NULL_PTR_RETURN_VALUE(node->regulatorInfo.cb, HDF_SUCCESS); - struct RegulatorStatusChangeInfo info; - memset_s(&info, sizeof(struct RegulatorStatusChangeInfo), 0, sizeof(struct RegulatorStatusChangeInfo)); - - info.status = node->regulatorInfo.status; - info.name = node->regulatorInfo.name; - HDF_LOGI("%s: Cb %s %d", __func__, info.name, info.status); - - return node->regulatorInfo.cb(&info); -} -int32_t RegulatorNodeEnable(struct RegulatorNode *node) -{ - CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); - if (node->regulatorInfo.status == REGULATOR_STATUS_ON) { - HDF_LOGD("RegulatorNodeEnable: %s status on", node->regulatorInfo.name); - return HDF_SUCCESS; - } - - if (OsalMutexLock(&node->lock) != HDF_SUCCESS) { - HDF_LOGE("RegulatorNodeEnable: lock regulator %s fail!", node->regulatorInfo.name); - return HDF_ERR_DEVICE_BUSY; - } - - if ((node->regulatorInfo.parentName != NULL) && (strlen(node->regulatorInfo.parentName) > 0)) { - struct RegulatorNode *parent = RegulatorTreeGetParent(node->regulatorInfo.name); - if (parent == NULL) { - (void)OsalMutexUnlock(&node->lock); - HDF_LOGE("RegulatorNodeEnable: %s failed", node->regulatorInfo.name); - return HDF_FAILURE; - } - if (RegulatorNodeEnable(parent) != HDF_SUCCESS) { - (void)OsalMutexUnlock(&node->lock); - HDF_LOGE("RegulatorNodeEnable: %s failed", parent->regulatorInfo.name); - return HDF_FAILURE; - } - } - - // first enable - if (node->ops->enable(node) != HDF_SUCCESS) { - (void)OsalMutexUnlock(&node->lock); - HDF_LOGE("enable: %s failed", node->regulatorInfo.name); - return HDF_FAILURE; - } - node->regulatorInfo.status = REGULATOR_STATUS_ON; - RegulatorNodeStatusCb(node); - - (void)OsalMutexUnlock(&node->lock); - HDF_LOGD("RegulatorNodeEnable: %s success", node->regulatorInfo.name); - return HDF_SUCCESS; -} - -static int32_t RegulatorNodeDisable(struct RegulatorNode *node) -{ - CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); - if ((node->regulatorInfo.status == REGULATOR_STATUS_OFF) || (node->regulatorInfo.constraints.alwaysOn)) { - HDF_LOGI("RegulatorNodeDisable: %s [%d][%d], unsatisfied closing adjusment", - node->regulatorInfo.name, node->regulatorInfo.status, node->regulatorInfo.constraints.alwaysOn); - return HDF_SUCCESS; - } - - if (OsalMutexLock(&node->lock) != HDF_SUCCESS) { - HDF_LOGE("RegulatorNodeDisable: lock regulator %s fail!", node->regulatorInfo.name); - return HDF_ERR_DEVICE_BUSY; - } - - if (!RegulatorTreeIsAllChildDisable(node->regulatorInfo.name)) { - (void)OsalMutexUnlock(&node->lock); - HDF_LOGE("RegulatorNodeDisable:there is %s child not disable ", node->regulatorInfo.name); - return HDF_FAILURE; - } - - // the regulator no user, can disable - if (node->ops->disable(node) != HDF_SUCCESS) { - (void)OsalMutexUnlock(&node->lock); - HDF_LOGE("RegulatorNodeDisable:disable %s failed", node->regulatorInfo.name); - return HDF_FAILURE; - } - node->regulatorInfo.status = REGULATOR_STATUS_OFF; - RegulatorNodeStatusCb(node); - HDF_LOGD("RegulatorNodeDisable:disable %s success", node->regulatorInfo.name); - - // set parent - if (strlen(node->regulatorInfo.parentName) != 0) { - struct RegulatorNode *parent = RegulatorTreeGetParent(node->regulatorInfo.name); - if (parent == NULL) { - (void)OsalMutexUnlock(&node->lock); - HDF_LOGE("RegulatorNodeDisable: %s failed", node->regulatorInfo.name); - return HDF_FAILURE; - } - if (RegulatorNodeDisable(parent) != HDF_SUCCESS) { - (void)OsalMutexUnlock(&node->lock); - HDF_LOGE("RegulatorNodeDisable: %s failed", parent->regulatorInfo.name); - return HDF_FAILURE; - } - } - - (void)OsalMutexUnlock(&node->lock); - return HDF_SUCCESS; -} - -int32_t RegulatorNodeForceDisable(struct RegulatorNode *node) -{ - CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); - if (OsalMutexLock(&node->lock) != HDF_SUCCESS) { - HDF_LOGE(": lock regulator %s fail!", node->regulatorInfo.name); - return HDF_ERR_DEVICE_BUSY; - } - - if (node->regulatorInfo.status == REGULATOR_STATUS_OFF) { - (void)OsalMutexUnlock(&node->lock); - HDF_LOGI(": %s useCount[%d] has been closed", - node->regulatorInfo.name, node->regulatorInfo.useCount); - return HDF_SUCCESS; - } - - // if the regulator force disable ,set all child node disable - if (RegulatorTreeChildForceDisable(node)) { - (void)OsalMutexUnlock(&node->lock); - HDF_LOGE("RegulatorTreeConsumerForceDisable: %s failed", node->regulatorInfo.name); - return HDF_FAILURE; - } - - if (node->ops->disable(node) != HDF_SUCCESS) { - (void)OsalMutexUnlock(&node->lock); - HDF_LOGE("RegulatorNodeDisable:disable %s failed", node->regulatorInfo.name); - return HDF_FAILURE; - } - node->regulatorInfo.status = REGULATOR_STATUS_OFF; - RegulatorNodeStatusCb(node); - HDF_LOGD(":regulator %s force disable success", node->regulatorInfo.name); - - // set parent - if (strlen(node->regulatorInfo.parentName) != 0) { - struct RegulatorNode *parent = RegulatorTreeGetParent(node->regulatorInfo.name); - if (parent == NULL) { - (void)OsalMutexUnlock(&node->lock); - HDF_LOGE(": %s failed", node->regulatorInfo.name); - return HDF_FAILURE; - } - if (RegulatorNodeDisable(parent) != HDF_SUCCESS) { - (void)OsalMutexUnlock(&node->lock); - HDF_LOGE(": %s failed", parent->regulatorInfo.name); - return HDF_FAILURE; - } - } - - (void)OsalMutexUnlock(&node->lock); - return HDF_SUCCESS; -} - -int32_t RegulatorNodeSetVoltage(struct RegulatorNode *node, uint32_t minUv, uint32_t maxUv) -{ - CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); - if (node->regulatorInfo.constraints.mode != REGULATOR_CHANGE_VOLTAGE) { - HDF_LOGE("RegulatorNodeSetVoltage: %s mode %d invalid!", - node->regulatorInfo.name, node->regulatorInfo.constraints.mode); - return HDF_FAILURE; - } - - if (minUv == node->regulatorInfo.minUv && maxUv == node->regulatorInfo.maxUv) { - HDF_LOGD("RegulatorNodeSetVoltage: %s voltage", node->regulatorInfo.name); - return HDF_SUCCESS; - } - - if ((minUv > maxUv) || - (minUv < node->regulatorInfo.constraints.minUv || - maxUv > node->regulatorInfo.constraints.maxUv)) { - HDF_LOGE("RegulatorNodeSetVoltage: %s Uv [%d, %d] invalid!", - node->regulatorInfo.name, minUv, maxUv); - return HDF_FAILURE; - } - - if (OsalMutexLock(&node->lock) != HDF_SUCCESS) { - HDF_LOGE("RegulatorNodeSetVoltage: lock regulator %s fail!", node->regulatorInfo.name); - return HDF_ERR_DEVICE_BUSY; - } - - int ret = node->ops->setVoltage(node, minUv, maxUv); - if (ret != HDF_SUCCESS) { - (void)OsalMutexUnlock(&node->lock); - HDF_LOGE("RegulatorNodeSetVoltage: setVoltage %s fail!", node->regulatorInfo.name); - return HDF_FAILURE; - } - - node->regulatorInfo.minUv = minUv; - node->regulatorInfo.maxUv = maxUv; - (void)OsalMutexUnlock(&node->lock); - - HDF_LOGD("RegulatorNodeSetVoltage: %s voltage[%d, %d] success", - node->regulatorInfo.name, minUv, maxUv); - return HDF_SUCCESS; -} - -int32_t RegulatorNodeGetVoltage(struct RegulatorNode *node, uint32_t *voltage) -{ - CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); - CHECK_NULL_PTR_RETURN_VALUE(voltage, HDF_ERR_INVALID_PARAM); - - if (node->regulatorInfo.constraints.mode != REGULATOR_CHANGE_VOLTAGE) { - HDF_LOGE("RegulatorNodeSetVoltage: %s mode %d invalid!", - node->regulatorInfo.name, node->regulatorInfo.constraints.mode); - return HDF_FAILURE; - } - - int ret = node->ops->getVoltage(node, voltage); - if (ret != HDF_SUCCESS) { - HDF_LOGE("RegulatorNodeGetVoltage: getVoltage %s fail!", node->regulatorInfo.name); - return HDF_FAILURE; - } - - HDF_LOGD("RegulatorNodeGetVoltage: %s voltage[%d] success", - node->regulatorInfo.name, *voltage); - return HDF_SUCCESS; -} - -int32_t RegulatorNodeSetCurrent(struct RegulatorNode *node, uint32_t minUA, uint32_t maxUA) -{ - CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); - if (node->regulatorInfo.constraints.mode != REGULATOR_CHANGE_CURRENT) { - HDF_LOGE("RegulatorNodeSetVoltage: %s mode %d invalid!", - node->regulatorInfo.name, node->regulatorInfo.constraints.mode); - return HDF_FAILURE; - } - - if (minUA == node->regulatorInfo.minUa && maxUA == node->regulatorInfo.maxUa) { - HDF_LOGD("RegulatorNodeSetCurrent: %s [%d, %d] [%d, %d]", node->regulatorInfo.name, - minUA, maxUA, node->regulatorInfo.minUa, node->regulatorInfo.maxUa); - return HDF_SUCCESS; - } - - if ((minUA > maxUA) || - (minUA < node->regulatorInfo.constraints.minUa || - maxUA > node->regulatorInfo.constraints.maxUa)) { - HDF_LOGE("RegulatorNodeSetCurrent: %s UA [%d, %d] invalid!", - node->regulatorInfo.name, minUA, maxUA); - return HDF_FAILURE; - } - - if (OsalMutexLock(&node->lock) != HDF_SUCCESS) { - HDF_LOGE("RegulatorNodeSetCurrent: lock regulator %s fail!", node->regulatorInfo.name); - return HDF_ERR_DEVICE_BUSY; - } - - int ret = node->ops->setCurrent(node, minUA, maxUA); - if (ret != HDF_SUCCESS) { - (void)OsalMutexUnlock(&node->lock); - HDF_LOGE("RegulatorNodeSetCurrent: setCurrent %s fail!", node->regulatorInfo.name); - return HDF_FAILURE; - } - - node->regulatorInfo.minUa = minUA; - node->regulatorInfo.maxUa = maxUA; - (void)OsalMutexUnlock(&node->lock); - - HDF_LOGD("RegulatorNodeSetCurrent: %s UA[%d, %d] SUCCESS", - node->regulatorInfo.name, minUA, maxUA); - return HDF_SUCCESS; -} - -int32_t RegulatorNodeGetCurrent(struct RegulatorNode *node, uint32_t *current) -{ - CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_OBJECT); - CHECK_NULL_PTR_RETURN_VALUE(current, HDF_ERR_INVALID_OBJECT); - if (node->regulatorInfo.constraints.mode != REGULATOR_CHANGE_CURRENT) { - HDF_LOGE("RegulatorNodeSetVoltage: %s mode %d invalid!", - node->regulatorInfo.name, node->regulatorInfo.constraints.mode); - return HDF_FAILURE; - } - - int ret = node->ops->getCurrent(node, current); - if (ret != HDF_SUCCESS) { - HDF_LOGE("RegulatorNodeGetVoltage: getCurrent %s fail!", node->regulatorInfo.name); - return HDF_FAILURE; - } - - HDF_LOGD("RegulatorNodeGetVoltage: %s current[%d] success", - node->regulatorInfo.name, *current); - return HDF_SUCCESS; -} - -int32_t RegulatorNodeGetStatus(struct RegulatorNode *node, uint32_t *status) -{ - CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_OBJECT); - CHECK_NULL_PTR_RETURN_VALUE(status, HDF_ERR_INVALID_OBJECT); - if (node->ops->getStatus(node, status) != HDF_SUCCESS) { - HDF_LOGE("RegulatorNodeGetStatus: getStatus %s fail!", node->regulatorInfo.name); - return HDF_FAILURE; - } - - HDF_LOGD("RegulatorNodeGetStatus: %s status[%d] success", - node->regulatorInfo.name, *status); - return HDF_SUCCESS; -} - -int32_t RegulatorNodeRegisterStatusChangeCb(struct RegulatorNode *node, RegulatorStatusChangecb cb) -{ - CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_OBJECT); - CHECK_NULL_PTR_RETURN_VALUE(cb, HDF_ERR_INVALID_OBJECT); - node->regulatorInfo.cb = cb; - return HDF_SUCCESS; -} - -int32_t RegulatorTreeInfoInit(struct RegulatorNode *node) -{ - struct RegulatorNode *pos = NULL; - CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_OBJECT); - struct RegulatorManager *manager = g_regulatorManager; - CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_ERR_INVALID_OBJECT); - - if ((node->regulatorInfo.parentName != NULL) - && (strlen(node->regulatorInfo.parentName) > 0)) { - DLIST_FOR_EACH_ENTRY(pos, &manager->regulatorHead, struct RegulatorNode, node) { - if (strcmp(node->regulatorInfo.parentName, pos->regulatorInfo.name) == 0) { - if (RegulatorTreeSet(node->regulatorInfo.name, node, pos) != HDF_SUCCESS) { - HDF_LOGE("%s: RegulatorTreeSet failed", __func__); - return HDF_FAILURE; - } else { - HDF_LOGI("%s:regulator [%s] RegulatorTreeSet success", __func__, node->regulatorInfo.name); - return HDF_SUCCESS; - } - } - } - - HDF_LOGE("%s: RegulatorTreeSet find %s parent %s error", - __func__, node->regulatorInfo.name, node->regulatorInfo.parentName); - return HDF_FAILURE; - } - return HDF_SUCCESS; -} - -static int32_t RegulatorManagerBind(struct HdfDeviceObject *device) -{ - int32_t ret; - struct RegulatorManager *manager = NULL; - - HDF_LOGI("RegulatorManagerBind: Enter!"); - CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_OBJECT); - - manager = (struct RegulatorManager *)OsalMemCalloc(sizeof(*manager)); - if (manager == NULL) { - HDF_LOGE("RegulatorManagerBind: malloc manager fail!"); - return HDF_ERR_MALLOC_FAIL; - } - - ret = OsalMutexInit(&manager->lock); - if (ret != HDF_SUCCESS) { - HDF_LOGE("RegulatorManagerBind: mutex init fail:%d", ret); - OsalMemFree(manager); - return HDF_FAILURE; - } - - manager->device = device; - device->service = &manager->service; - DListHeadInit(&manager->regulatorHead); - g_regulatorManager = manager; - - if (RegulatorTreeManagerInit() != HDF_SUCCESS) { - HDF_LOGE("RegulatorManagerBind: RegulatorTreeManagerInit init fail"); - OsalMemFree(manager); - return HDF_FAILURE; - } - HDF_LOGI("RegulatorManagerBind: success!"); - return HDF_SUCCESS; -} - -static int32_t RegulatorManagerInit(struct HdfDeviceObject *device) -{ - (void)device; - - HDF_LOGI("RegulatorManagerInit: success!"); - return HDF_SUCCESS; -} - -static void RegulatorManagerRelease(struct HdfDeviceObject *device) -{ - HDF_LOGI("RegulatorManagerRelease: enter"); - CHECK_NULL_PTR_RETURN(device); - - if (RegulatorNodeRemoveAll() != HDF_SUCCESS) { - HDF_LOGE("RegulatorNodeRemoveAll failed"); - return; - } - - struct RegulatorManager *manager = (struct RegulatorManager *)device->service; - CHECK_NULL_PTR_RETURN(manager); - OsalMutexDestroy(&manager->lock); - OsalMemFree(manager); - g_regulatorManager = NULL; - - if (RegulatorTreeManagerDestory() != HDF_SUCCESS) { - HDF_LOGE("RegulatorTreeManagerDestory failed"); - return; - } -} - -struct HdfDriverEntry g_regulatorManagerEntry = { - .moduleVersion = 1, - .Bind = RegulatorManagerBind, - .Init = RegulatorManagerInit, - .Release = RegulatorManagerRelease, - .moduleName = "HDF_PLATFORM_REGULATOR_MANAGER", -}; -HDF_INIT(g_regulatorManagerEntry); +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "regulator_core.h" +#include "hdf_log.h" +#include "osal_mem.h" +#include "osal_time.h" +#include "securec.h" +#include "regulator_tree_mgr.h" + +#define HDF_LOG_TAG regulator_core +struct RegulatorManager { + struct IDeviceIoService service; + struct HdfDeviceObject *device; + struct DListHead regulatorHead; + struct OsalMutex lock; +}; + +static struct RegulatorManager *g_regulatorManager = NULL; + +struct RegulatorNode *RegulatorNodeOpen(const char *name) +{ + CHECK_NULL_PTR_RETURN_VALUE(name, NULL); + struct RegulatorNode *pos = NULL; + struct RegulatorNode *tmp = NULL; + + struct RegulatorManager *manager = g_regulatorManager; + CHECK_NULL_PTR_RETURN_VALUE(manager, NULL); + + if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) { + HDF_LOGE("RegulatorNodeOpen: lock regulator manager fail!"); + return NULL; + } + + DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->regulatorHead, struct RegulatorNode, node) { + if (strcmp(name, pos->regulatorInfo.name) == 0) { + if ((pos->ops->open != NULL) && pos->ops->open(pos) != HDF_SUCCESS) { + (void)OsalMutexUnlock(&manager->lock); + HDF_LOGE("RegulatorNodeOpen: open regulator[%s] fail!", name); + return NULL; + } + (void)OsalMutexUnlock(&manager->lock); + return pos; + } + } + + (void)OsalMutexUnlock(&manager->lock); + HDF_LOGE("RegulatorNodeOpen: No %s regulator exist", name); + return NULL; +} + +int32_t RegulatorNodeClose(struct RegulatorNode *node) +{ + CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_OBJECT); + return HDF_SUCCESS; +} + +void RegulatorNodeListPrint(void) +{ + struct RegulatorNode *pos = NULL; + struct RegulatorNode *tmp = NULL; + + struct RegulatorManager *manager = g_regulatorManager; + CHECK_NULL_PTR_RETURN(manager); + + if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) { + HDF_LOGE("RegulatorNodeListPrint: lock regulator manager fail!"); + return; + } + + DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->regulatorHead, struct RegulatorNode, node) { + HDF_LOGI("RegulatorNodeListPrint: name[%s], [%d][%d][%d], [%d][%d]--[%d][%d]", + pos->regulatorInfo.name, pos->regulatorInfo.status, + pos->regulatorInfo.constraints.alwaysOn, pos->regulatorInfo.constraints.mode, + pos->regulatorInfo.constraints.minUv, pos->regulatorInfo.constraints.maxUv, + pos->regulatorInfo.constraints.minUa, pos->regulatorInfo.constraints.maxUa); + if ((pos->regulatorInfo.parentName != NULL) && (strlen(pos->regulatorInfo.parentName) > 0)) { + HDF_LOGI("RegulatorNodeListPrint:parentName[%s]", pos->regulatorInfo.parentName); + } + } + + (void)OsalMutexUnlock(&manager->lock); + RegulatorTreePrint(); +} + +int32_t RegulatorNodeSetParent(struct RegulatorNode *node) +{ + CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); + struct RegulatorNode *pos = NULL; + struct RegulatorNode *tmp = NULL; + struct RegulatorManager *manager = g_regulatorManager; + CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE); + + if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) { + HDF_LOGE("RegulatorNodeSetParent: lock regulator manager fail!"); + return HDF_ERR_DEVICE_BUSY; + } + // parent set + if ((node->regulatorInfo.parentName != NULL) + && (strlen(node->regulatorInfo.parentName) > 0)) { + DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->regulatorHead, struct RegulatorNode, node) { + if (strcmp(node->regulatorInfo.parentName, pos->regulatorInfo.name) == 0) { + if (RegulatorTreeSet(node->regulatorInfo.name, node, pos) != HDF_SUCCESS) { + HDF_LOGE("%s: RegulatorTreeSet failed", __func__); + (void)OsalMutexUnlock(&manager->lock); + return HDF_FAILURE; + } else { + HDF_LOGI("%s:regulator [%s] RegulatorTreeSet success", __func__, node->regulatorInfo.name); + (void)OsalMutexUnlock(&manager->lock); + return HDF_SUCCESS; + } + } + } + + HDF_LOGE("%s: RegulatorTreeSet find %s parent %s error", + __func__, node->regulatorInfo.name, node->regulatorInfo.parentName); + (void)OsalMutexUnlock(&manager->lock); + return HDF_FAILURE; + } + + (void)OsalMutexUnlock(&manager->lock); + HDF_LOGD("%s: the node %s no need to set parent", __func__, node->regulatorInfo.name); + return HDF_SUCCESS; +} + +int32_t RegulatorNodeSetChild(struct RegulatorNode *parent) +{ + CHECK_NULL_PTR_RETURN_VALUE(parent, HDF_ERR_INVALID_PARAM); + struct RegulatorNode *pos = NULL; + struct RegulatorNode *tmp = NULL; + struct RegulatorManager *manager = g_regulatorManager; + CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE); + + if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) { + HDF_LOGE("RegulatorNodeSetChild: lock regulator manager fail!"); + return HDF_ERR_DEVICE_BUSY; + } + + DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->regulatorHead, struct RegulatorNode, node) { + if ((pos->regulatorInfo.parentName != NULL) && + (strcmp(parent->regulatorInfo.name, pos->regulatorInfo.parentName) == 0)) { + HDF_LOGD("%s: node[%s] parent is %s, tree info process", __func__, + pos->regulatorInfo.parentName, parent->regulatorInfo.name); + if (RegulatorTreeSet(pos->regulatorInfo.name, pos, parent) != HDF_SUCCESS) { + HDF_LOGE("%s: RegulatorTreeSet failed", __func__); + (void)OsalMutexUnlock(&manager->lock); + return HDF_FAILURE; + } + } + } + + HDF_LOGD("%s: the node %s child info process suceess", __func__, parent->regulatorInfo.name); + (void)OsalMutexUnlock(&manager->lock); + return HDF_SUCCESS; +} + +void RegulatorNodeInitEnable(struct RegulatorNode *node) +{ + CHECK_NULL_PTR_RETURN(node); + if (node->regulatorInfo.status == REGULATOR_STATUS_ON) { + HDF_LOGD("RegulatorNodeInitEnable: %s status on", node->regulatorInfo.name); + return; + } + + bool isChildAlwayson = RegulatorTreeIsChildAlwayson(node->regulatorInfo.name); + bool isChildOn = RegulatorTreeIsChildStatusOn(node->regulatorInfo.name); + // if regulator alwaysOn is true or there is child's alwaysOn is true or there is child's status on, then process + if ((node->regulatorInfo.constraints.alwaysOn) || (isChildAlwayson) || (isChildOn)) { + // RegulatorTreeIsUpNodeComplete is false, call RegulatorNodeEnable will fail. + if (RegulatorTreeIsUpNodeComplete(node->regulatorInfo.name)) { + HDF_LOGD("RegulatorNodeInitEnable: %s UpNodeComplete", node->regulatorInfo.name); + RegulatorNodeEnable(node); + return; + } + if (OsalMutexLock(&node->lock) != HDF_SUCCESS) { + HDF_LOGE("RegulatorNodeInitEnable: lock regulator %s fail!", node->regulatorInfo.name); + return; + } + // first enable + if (node->ops->enable(node) != HDF_SUCCESS) { + (void)OsalMutexUnlock(&node->lock); + HDF_LOGE("RegulatorNodeInitEnable: %s failed", node->regulatorInfo.name); + return; + } + node->regulatorInfo.status = REGULATOR_STATUS_ON; + RegulatorNodeStatusCb(node); + + (void)OsalMutexUnlock(&node->lock); + HDF_LOGD("RegulatorNodeInitEnable: %s success", node->regulatorInfo.name); + return; + } +} + +/* +* complete up and down management topology +* process alwayson +*/ +int32_t RegulatorNodeInitProcess(struct RegulatorNode *node) +{ + CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); + + // parent or child set + if (RegulatorNodeSetParent(node) != HDF_SUCCESS) { + HDF_LOGD("%s: node %s RegulatorNodeSetParent fail, parent not add", __func__, node->regulatorInfo.name); + } + + if (RegulatorNodeSetChild(node) != HDF_SUCCESS) { + HDF_LOGE("%s: node %s RegulatorNodeSetChild fail", __func__, node->regulatorInfo.name); + return HDF_FAILURE; + } + + if (node->regulatorInfo.constraints.mode == REGULATOR_CHANGE_CURRENT) { + RegulatorNodeSetCurrent(node, node->regulatorInfo.constraints.minUa, node->regulatorInfo.constraints.maxUa); + } else if(node->regulatorInfo.constraints.mode == REGULATOR_CHANGE_VOLTAGE) { + RegulatorNodeSetVoltage(node, node->regulatorInfo.constraints.minUv, node->regulatorInfo.constraints.maxUv); + } + + RegulatorNodeInitEnable(node); + + HDF_LOGD("%s: the node %s init success", __func__, node->regulatorInfo.name); + return HDF_SUCCESS; +} + +int32_t RegulatorNodeAdd(struct RegulatorNode *node) +{ + CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); + CHECK_NULL_PTR_RETURN_VALUE(node->ops, HDF_ERR_INVALID_PARAM); + struct RegulatorNode *pos = NULL; + struct RegulatorNode *tmp = NULL; + struct RegulatorManager *manager = g_regulatorManager; + CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE); + + DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->regulatorHead, struct RegulatorNode, node) { + if (strcmp(node->regulatorInfo.name, pos->regulatorInfo.name) == 0) { + HDF_LOGE("%s: regulatorInfo[%s] existed", __func__, node->regulatorInfo.name); + return HDF_FAILURE; + } + } + + // init node info + node->regulatorInfo.cb = NULL; + node->regulatorInfo.useCount = 0; + node->regulatorInfo.status = REGULATOR_STATUS_OFF; + node->regulatorInfo.useCount = 0; + if (OsalMutexInit(&node->lock) != HDF_SUCCESS) { + HDF_LOGE("%s: OsalMutexInit %s failed", __func__, node->regulatorInfo.name); + return HDF_FAILURE; + } + + if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) { + HDF_LOGE("RegulatorManagerAddNode: lock regulator manager fail!"); + return HDF_ERR_DEVICE_BUSY; + } + DListInsertTail(&node->node, &manager->regulatorHead); + (void)OsalMutexUnlock(&manager->lock); + + if (RegulatorNodeInitProcess(node) != HDF_SUCCESS) { + HDF_LOGE("%s: node %s RegulatorNodeInitProcess fail", __func__, node->regulatorInfo.name); + return HDF_FAILURE; + } + + HDF_LOGI("%s: add regulator name[%s] success", __func__, node->regulatorInfo.name); + + return HDF_SUCCESS; +} + +int32_t RegulatorNodeRemove(const char *name) +{ + CHECK_NULL_PTR_RETURN_VALUE(name, HDF_ERR_INVALID_PARAM); + + struct RegulatorNode *pos = NULL; + struct RegulatorNode *tmp = NULL; + struct RegulatorManager *manager = g_regulatorManager; + if (manager == NULL) { + HDF_LOGE("RegulatorNodeRemoveAll: regulator manager null!"); + return HDF_ERR_NOT_SUPPORT; + } + + if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) { + HDF_LOGE("RegulatorNodeRemoveAll: lock regulator manager fail!"); + return HDF_ERR_DEVICE_BUSY; + } + + DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->regulatorHead, struct RegulatorNode, node) { + if (strcmp(pos->regulatorInfo.name, name) == 0) { + if ((pos->ops->release != NULL) && pos->ops->release(pos) != HDF_SUCCESS) { + HDF_LOGE("RegulatorNodeRemoveAll: release regulator[%s] fail!", pos->regulatorInfo.name); + } + DListRemove(&pos->node); + (void)OsalMutexDestroy(&pos->lock); + OsalMemFree(pos); + break; + } + } + + (void)OsalMutexUnlock(&manager->lock); + HDF_LOGI("%s: remove regulator %s success", __func__, name); + return HDF_SUCCESS; +} + +int32_t RegulatorNodeRemoveAll(void) +{ + if (RegulatorTreeNodeRemoveAll() != HDF_SUCCESS) { + HDF_LOGE("RegulatorNodeRemoveAll: RegulatorTreeNodeRemoveAll failed"); + return HDF_FAILURE; + } + + struct RegulatorNode *pos = NULL; + struct RegulatorNode *tmp = NULL; + struct RegulatorManager *manager = g_regulatorManager; + if (manager == NULL) { + HDF_LOGE("RegulatorNodeRemoveAll: regulator manager null!"); + return HDF_ERR_NOT_SUPPORT; + } + + if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) { + HDF_LOGE("RegulatorNodeRemoveAll: lock regulator manager fail!"); + return HDF_ERR_DEVICE_BUSY; + } + + DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->regulatorHead, struct RegulatorNode, node) { + if ((pos->ops->release != NULL) && pos->ops->release(pos) != HDF_SUCCESS) { + HDF_LOGE("RegulatorNodeRemoveAll: release regulator[%s] fail!", pos->regulatorInfo.name); + } + DListRemove(&pos->node); + (void)OsalMutexDestroy(&pos->lock); + OsalMemFree(pos); + } + + (void)OsalMutexUnlock(&manager->lock); + HDF_LOGI("%s: remove all regulator success", __func__); + return HDF_SUCCESS; +} + +int32_t RegulatorNodeStatusCb(struct RegulatorNode *node) +{ + CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); + CHECK_NULL_PTR_RETURN_VALUE(node->regulatorInfo.cb, HDF_SUCCESS); + struct RegulatorStatusChangeInfo info; + memset_s(&info, sizeof(struct RegulatorStatusChangeInfo), 0, sizeof(struct RegulatorStatusChangeInfo)); + + info.status = node->regulatorInfo.status; + info.name = node->regulatorInfo.name; + HDF_LOGI("%s: Cb %s %d", __func__, info.name, info.status); + + return node->regulatorInfo.cb(&info); +} + +int32_t RegulatorNodeEnable(struct RegulatorNode *node) +{ + CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); + if (node->regulatorInfo.status == REGULATOR_STATUS_ON) { + HDF_LOGD("RegulatorNodeEnable: %s status on", node->regulatorInfo.name); + return HDF_SUCCESS; + } + + if (OsalMutexLock(&node->lock) != HDF_SUCCESS) { + HDF_LOGE("RegulatorNodeEnable: lock regulator %s fail!", node->regulatorInfo.name); + return HDF_ERR_DEVICE_BUSY; + } + + if ((node->regulatorInfo.parentName != NULL) && (strlen(node->regulatorInfo.parentName) > 0)) { + struct RegulatorNode *parent = RegulatorTreeGetParent(node->regulatorInfo.name); + if (parent == NULL) { + (void)OsalMutexUnlock(&node->lock); + HDF_LOGE("RegulatorNodeEnable: %s failed", node->regulatorInfo.name); + return HDF_FAILURE; + } + if (RegulatorNodeEnable(parent) != HDF_SUCCESS) { + (void)OsalMutexUnlock(&node->lock); + HDF_LOGE("RegulatorNodeEnable: %s failed", parent->regulatorInfo.name); + return HDF_FAILURE; + } + } + + // first enable + if (node->ops->enable(node) != HDF_SUCCESS) { + (void)OsalMutexUnlock(&node->lock); + HDF_LOGE("RegulatorNodeEnable:enable: %s failed", node->regulatorInfo.name); + return HDF_FAILURE; + } + RegulatorNodeStatusCb(node); + + (void)OsalMutexUnlock(&node->lock); + return HDF_SUCCESS; +} + +int32_t RegulatorNodeDisable(struct RegulatorNode *node) +{ + CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); + if ((node->regulatorInfo.status == REGULATOR_STATUS_OFF) || (node->regulatorInfo.constraints.alwaysOn)) { + HDF_LOGI("RegulatorNodeDisable: %s [%d][%d], unsatisfied closing adjusment", + node->regulatorInfo.name, node->regulatorInfo.status, node->regulatorInfo.constraints.alwaysOn); + return HDF_SUCCESS; + } + + if (OsalMutexLock(&node->lock) != HDF_SUCCESS) { + HDF_LOGE("RegulatorNodeDisable: lock regulator %s fail!", node->regulatorInfo.name); + return HDF_ERR_DEVICE_BUSY; + } + + if (!RegulatorTreeIsAllChildDisable(node->regulatorInfo.name)) { + (void)OsalMutexUnlock(&node->lock); + HDF_LOGE("RegulatorNodeDisable:there is %s child not disable, so disable node failed", + node->regulatorInfo.name); + return HDF_FAILURE; + } + + // the regulator no user, can disable + + if (node->ops->disable(node) != HDF_SUCCESS) { + (void)OsalMutexUnlock(&node->lock); + HDF_LOGE("RegulatorNodeDisable:disable %s failed", node->regulatorInfo.name); + return HDF_FAILURE; + } + + RegulatorNodeStatusCb(node); + + // set parent + if ((node->regulatorInfo.parentName != NULL) && (strlen(node->regulatorInfo.parentName) > 0)) { + struct RegulatorNode *parent = RegulatorTreeGetParent(node->regulatorInfo.name); + if (parent == NULL) { + (void)OsalMutexUnlock(&node->lock); + HDF_LOGE("RegulatorNodeDisable: %s failed", node->regulatorInfo.name); + return HDF_FAILURE; + } + if (RegulatorNodeDisable(parent) != HDF_SUCCESS) { + (void)OsalMutexUnlock(&node->lock); + HDF_LOGD("RegulatorNodeDisable: disable %s's parent %s failed", + node->regulatorInfo.name, parent->regulatorInfo.name); + return HDF_SUCCESS; + } + } + + (void)OsalMutexUnlock(&node->lock); + return HDF_SUCCESS; +} + +int32_t RegulatorNodeForceDisable(struct RegulatorNode *node) +{ + CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); + if (OsalMutexLock(&node->lock) != HDF_SUCCESS) { + HDF_LOGE(": lock regulator %s fail!", node->regulatorInfo.name); + return HDF_ERR_DEVICE_BUSY; + } + + if (node->regulatorInfo.status == REGULATOR_STATUS_OFF) { + (void)OsalMutexUnlock(&node->lock); + return HDF_SUCCESS; + } + + // if the regulator force disable ,set all child node disable + if (RegulatorTreeChildForceDisable(node)) { + (void)OsalMutexUnlock(&node->lock); + HDF_LOGE("RegulatorNodeForceDisable--RegulatorTreeConsumerForceDisable: %s failed", node->regulatorInfo.name); + return HDF_FAILURE; + } + + if (node->ops->forceDisable != NULL) { + if (node->ops->forceDisable(node) != HDF_SUCCESS) { + (void)OsalMutexUnlock(&node->lock); + HDF_LOGE("RegulatorNodeForceDisable:forceDisable %s failed", node->regulatorInfo.name); + return HDF_FAILURE; + } + } else if (node->ops->disable(node) != HDF_SUCCESS) { + (void)OsalMutexUnlock(&node->lock); + HDF_LOGE("RegulatorNodeForceDisable:disable %s failed", node->regulatorInfo.name); + return HDF_FAILURE; + } + node->regulatorInfo.status = REGULATOR_STATUS_OFF; + RegulatorNodeStatusCb(node); + HDF_LOGI("RegulatorNodeForceDisable:regulator %s force disable success", node->regulatorInfo.name); + + // set parent + if ((node->regulatorInfo.parentName != NULL) && (strlen(node->regulatorInfo.parentName) > 0)) { + struct RegulatorNode *parent = RegulatorTreeGetParent(node->regulatorInfo.name); + if (parent == NULL) { + (void)OsalMutexUnlock(&node->lock); + HDF_LOGE(": %s failed", node->regulatorInfo.name); + return HDF_FAILURE; + } + if (RegulatorNodeDisable(parent) != HDF_SUCCESS) { + (void)OsalMutexUnlock(&node->lock); + HDF_LOGD("RegulatorNodeDisable: disable %s's parent %s failed", + node->regulatorInfo.name, parent->regulatorInfo.name); + return HDF_SUCCESS; + } + } + + (void)OsalMutexUnlock(&node->lock); + return HDF_SUCCESS; +} + +int32_t RegulatorNodeSetVoltage(struct RegulatorNode *node, uint32_t minUv, uint32_t maxUv) +{ + CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); + if (node->regulatorInfo.constraints.mode != REGULATOR_CHANGE_VOLTAGE) { + HDF_LOGE("RegulatorNodeSetVoltage: %s mode %d invalid!", + node->regulatorInfo.name, node->regulatorInfo.constraints.mode); + return HDF_FAILURE; + } + + if (minUv == node->regulatorInfo.minUv && maxUv == node->regulatorInfo.maxUv) { + return HDF_SUCCESS; + } + + if ((minUv > maxUv) || + (minUv < node->regulatorInfo.constraints.minUv || + maxUv > node->regulatorInfo.constraints.maxUv)) { + HDF_LOGE("RegulatorNodeSetVoltage: %s Uv [%d, %d] invalid!", + node->regulatorInfo.name, minUv, maxUv); + return HDF_FAILURE; + } + + if (OsalMutexLock(&node->lock) != HDF_SUCCESS) { + HDF_LOGE("RegulatorNodeSetVoltage: lock regulator %s fail!", node->regulatorInfo.name); + return HDF_ERR_DEVICE_BUSY; + } + + int ret = node->ops->setVoltage(node, minUv, maxUv); + if (ret != HDF_SUCCESS) { + (void)OsalMutexUnlock(&node->lock); + HDF_LOGE("RegulatorNodeSetVoltage: setVoltage %s fail!", node->regulatorInfo.name); + return HDF_FAILURE; + } + + node->regulatorInfo.minUv = minUv; + node->regulatorInfo.maxUv = maxUv; + (void)OsalMutexUnlock(&node->lock); + + return HDF_SUCCESS; +} + +int32_t RegulatorNodeGetVoltage(struct RegulatorNode *node, uint32_t *voltage) +{ + CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); + CHECK_NULL_PTR_RETURN_VALUE(voltage, HDF_ERR_INVALID_PARAM); + + if (node->regulatorInfo.constraints.mode != REGULATOR_CHANGE_VOLTAGE) { + HDF_LOGE("RegulatorNodeSetVoltage: %s mode %d invalid!", + node->regulatorInfo.name, node->regulatorInfo.constraints.mode); + return HDF_FAILURE; + } + + int ret = node->ops->getVoltage(node, voltage); + if (ret != HDF_SUCCESS) { + HDF_LOGE("RegulatorNodeGetVoltage: getVoltage %s fail!", node->regulatorInfo.name); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} + +int32_t RegulatorNodeSetCurrent(struct RegulatorNode *node, uint32_t minUA, uint32_t maxUA) +{ + CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); + if (node->regulatorInfo.constraints.mode != REGULATOR_CHANGE_CURRENT) { + HDF_LOGE("RegulatorNodeSetVoltage: %s mode %d invalid!", + node->regulatorInfo.name, node->regulatorInfo.constraints.mode); + return HDF_FAILURE; + } + + if (minUA == node->regulatorInfo.minUa && maxUA == node->regulatorInfo.maxUa) { + return HDF_SUCCESS; + } + + if ((minUA > maxUA) || + (minUA < node->regulatorInfo.constraints.minUa || + maxUA > node->regulatorInfo.constraints.maxUa)) { + HDF_LOGE("RegulatorNodeSetCurrent: %s UA [%d, %d] invalid!", + node->regulatorInfo.name, minUA, maxUA); + return HDF_FAILURE; + } + + if (OsalMutexLock(&node->lock) != HDF_SUCCESS) { + HDF_LOGE("RegulatorNodeSetCurrent: lock regulator %s fail!", node->regulatorInfo.name); + return HDF_ERR_DEVICE_BUSY; + } + + int ret = node->ops->setCurrent(node, minUA, maxUA); + if (ret != HDF_SUCCESS) { + (void)OsalMutexUnlock(&node->lock); + HDF_LOGE("RegulatorNodeSetCurrent: setCurrent %s fail!", node->regulatorInfo.name); + return HDF_FAILURE; + } + + node->regulatorInfo.minUa = minUA; + node->regulatorInfo.maxUa = maxUA; + (void)OsalMutexUnlock(&node->lock); + return HDF_SUCCESS; +} + +int32_t RegulatorNodeGetCurrent(struct RegulatorNode *node, uint32_t *regCurrent) +{ + CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_OBJECT); + CHECK_NULL_PTR_RETURN_VALUE(regCurrent, HDF_ERR_INVALID_OBJECT); + if (node->regulatorInfo.constraints.mode != REGULATOR_CHANGE_CURRENT) { + HDF_LOGE("RegulatorNodeGetCurrent: %s mode %d invalid!", + node->regulatorInfo.name, node->regulatorInfo.constraints.mode); + return HDF_FAILURE; + } + + int ret = node->ops->getCurrent(node, regCurrent); + if (ret != HDF_SUCCESS) { + HDF_LOGE("RegulatorNodeGetCurrent: getCurrent %s fail!", node->regulatorInfo.name); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} + +int32_t RegulatorNodeGetStatus(struct RegulatorNode *node, uint32_t *status) +{ + CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_OBJECT); + CHECK_NULL_PTR_RETURN_VALUE(status, HDF_ERR_INVALID_OBJECT); + if (node->ops->getStatus(node, status) != HDF_SUCCESS) { + HDF_LOGE("RegulatorNodeGetStatus: getStatus %s fail!", node->regulatorInfo.name); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} + +int32_t RegulatorNodeRegisterStatusChangeCb(struct RegulatorNode *node, RegulatorStatusChangecb cb) +{ + CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_OBJECT); + CHECK_NULL_PTR_RETURN_VALUE(cb, HDF_ERR_INVALID_OBJECT); + node->regulatorInfo.cb = cb; + return HDF_SUCCESS; +} + +int32_t RegulatorTreeInfoInit(struct RegulatorNode *node) +{ + struct RegulatorNode *pos = NULL; + struct RegulatorNode *tmp = NULL; + CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_OBJECT); + struct RegulatorManager *manager = g_regulatorManager; + CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_ERR_INVALID_OBJECT); + + if ((node->regulatorInfo.parentName != NULL) + && (strlen(node->regulatorInfo.parentName) > 0)) { + DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->regulatorHead, struct RegulatorNode, node) { + if (strcmp(node->regulatorInfo.parentName, pos->regulatorInfo.name) == 0) { + if (RegulatorTreeSet(node->regulatorInfo.name, node, pos) != HDF_SUCCESS) { + HDF_LOGE("%s: RegulatorTreeSet failed", __func__); + return HDF_FAILURE; + } else { + HDF_LOGI("%s:regulator [%s] RegulatorTreeSet success", __func__, node->regulatorInfo.name); + return HDF_SUCCESS; + } + } + } + + HDF_LOGE("%s: RegulatorTreeSet find %s parent %s error", + __func__, node->regulatorInfo.name, node->regulatorInfo.parentName); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +static int32_t RegulatorManagerBind(struct HdfDeviceObject *device) +{ + int32_t ret; + struct RegulatorManager *manager = NULL; + + HDF_LOGI("RegulatorManagerBind: Enter!"); + CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_OBJECT); + + manager = (struct RegulatorManager *)OsalMemCalloc(sizeof(*manager)); + if (manager == NULL) { + HDF_LOGE("RegulatorManagerBind: malloc manager fail!"); + return HDF_ERR_MALLOC_FAIL; + } + + ret = OsalMutexInit(&manager->lock); + if (ret != HDF_SUCCESS) { + HDF_LOGE("RegulatorManagerBind: mutex init fail:%d", ret); + OsalMemFree(manager); + return HDF_FAILURE; + } + + manager->device = device; + device->service = &manager->service; + DListHeadInit(&manager->regulatorHead); + g_regulatorManager = manager; + + if (RegulatorTreeManagerInit() != HDF_SUCCESS) { + HDF_LOGE("RegulatorManagerBind: RegulatorTreeManagerInit init fail"); + OsalMemFree(manager); + return HDF_FAILURE; + } + HDF_LOGI("RegulatorManagerBind: success!"); + return HDF_SUCCESS; +} + +static int32_t RegulatorManagerInit(struct HdfDeviceObject *device) +{ + (void)device; + + HDF_LOGI("RegulatorManagerInit: success!"); + return HDF_SUCCESS; +} + +static void RegulatorManagerRelease(struct HdfDeviceObject *device) +{ + HDF_LOGI("RegulatorManagerRelease: enter"); + CHECK_NULL_PTR_RETURN(device); + + if (RegulatorNodeRemoveAll() != HDF_SUCCESS) { + HDF_LOGE("RegulatorNodeRemoveAll failed"); + return; + } + + struct RegulatorManager *manager = (struct RegulatorManager *)device->service; + CHECK_NULL_PTR_RETURN(manager); + OsalMutexDestroy(&manager->lock); + OsalMemFree(manager); + g_regulatorManager = NULL; + + if (RegulatorTreeManagerDestory() != HDF_SUCCESS) { + HDF_LOGE("RegulatorTreeManagerDestory failed"); + return; + } +} + +struct HdfDriverEntry g_regulatorManagerEntry = { + .moduleVersion = 1, + .Bind = RegulatorManagerBind, + .Init = RegulatorManagerInit, + .Release = RegulatorManagerRelease, + .moduleName = "HDF_PLATFORM_REGULATOR_MANAGER", +}; + +HDF_INIT(g_regulatorManagerEntry); diff --git a/support/platform/src/regulator/regulator_if.c b/support/platform/src/regulator/regulator_if.c index d59eaa8e..90165741 100755 --- a/support/platform/src/regulator/regulator_if.c +++ b/support/platform/src/regulator/regulator_if.c @@ -147,15 +147,15 @@ int32_t RegulatorSetCurrent(DevHandle handle, uint32_t minUa, uint32_t maxUa) return HDF_SUCCESS; } -int32_t RegulatorGetCurrent(DevHandle handle, uint32_t *current) +int32_t RegulatorGetCurrent(DevHandle handle, uint32_t *regCurrent) { struct RegulatorNode *node = (struct RegulatorNode *)handle; - if (node == NULL || current == NULL) { + if (node == NULL || regCurrent == NULL) { HDF_LOGE("%s: param is null", __func__); return HDF_FAILURE; } - int ret = RegulatorNodeGetCurrent(node, current); + int ret = RegulatorNodeGetCurrent(node, regCurrent); if (ret != HDF_SUCCESS) { HDF_LOGE("%s: RegulatorNodeGetCurrent fail", __func__); return HDF_FAILURE; diff --git a/support/platform/src/regulator/regulator_tree_mgr.c b/support/platform/src/regulator/regulator_tree_mgr.c index 652a42f6..c49b0a5d 100755 --- a/support/platform/src/regulator/regulator_tree_mgr.c +++ b/support/platform/src/regulator/regulator_tree_mgr.c @@ -8,6 +8,7 @@ #include "regulator_tree_mgr.h" #include "osal_mem.h" +#include "securec.h" static struct RegulatorTreeManager *g_regulatorTreeManager = NULL; static int RegulatorChildNodeAdd(struct RegulatorTreeInfo *pRegulator, struct RegulatorNode *child) @@ -28,21 +29,26 @@ static int RegulatorChildNodeAdd(struct RegulatorTreeInfo *pRegulator, struct Re HDF_LOGI("RegulatorChildNodeAdd: add %s child node success!", pRegulator->name); return HDF_SUCCESS; } + void RegulatorChildListDestroy(struct RegulatorTreeInfo *pRegulator) { CHECK_NULL_PTR_RETURN(pRegulator); struct RegulatorChildNode *nodeInfo = NULL; + struct RegulatorChildNode *tmp = NULL; - DLIST_FOR_EACH_ENTRY(nodeInfo, &pRegulator->childHead, struct RegulatorChildNode, node) { + DLIST_FOR_EACH_ENTRY_SAFE(nodeInfo, tmp, &pRegulator->childHead, struct RegulatorChildNode, node) { DListRemove(&nodeInfo->node); OsalMemFree(nodeInfo); } } -struct RegulatorNode *RegulatorTreeGetParent(const char *name) + +// name:the regulator node name; fun :get the node parent struct RegulatorNode +struct RegulatorNode * RegulatorTreeGetParent(const char *name) { CHECK_NULL_PTR_RETURN_VALUE(name, NULL); struct RegulatorTreeInfo *pos = NULL; + struct RegulatorTreeInfo *tmp = NULL; struct RegulatorTreeManager *manager = g_regulatorTreeManager; CHECK_NULL_PTR_RETURN_VALUE(manager, NULL); @@ -51,7 +57,7 @@ struct RegulatorNode *RegulatorTreeGetParent(const char *name) return NULL; } - DLIST_FOR_EACH_ENTRY(pos, &manager->treeMgrHead, struct RegulatorTreeInfo, node) { + DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->treeMgrHead, struct RegulatorTreeInfo, node) { if (strcmp(pos->name, name) == 0) { if (pos->parent == NULL) { (void)OsalMutexUnlock(&manager->lock); @@ -70,11 +76,13 @@ struct RegulatorNode *RegulatorTreeGetParent(const char *name) return NULL; } +// next level child static struct DListHead *RegulatorTreeGetChild(const char *name) { CHECK_NULL_PTR_RETURN_VALUE(name, NULL); struct RegulatorTreeInfo *pos = NULL; + struct RegulatorTreeInfo *tmp = NULL; struct RegulatorTreeManager *manager = g_regulatorTreeManager; CHECK_NULL_PTR_RETURN_VALUE(manager, NULL); @@ -83,7 +91,7 @@ static struct DListHead *RegulatorTreeGetChild(const char *name) return NULL; } - DLIST_FOR_EACH_ENTRY(pos, &manager->treeMgrHead, struct RegulatorTreeInfo, node) { + DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->treeMgrHead, struct RegulatorTreeInfo, node) { if (strcmp(pos->name, name) == 0) { (void)OsalMutexUnlock(&manager->lock); HDF_LOGI("RegulatorTreeGetChild: get %s child success!", name); @@ -96,6 +104,61 @@ static struct DListHead *RegulatorTreeGetChild(const char *name) return NULL; } +// name:the regulator node name +bool RegulatorTreeIsUpNodeComplete(const char *name) +{ + CHECK_NULL_PTR_RETURN_VALUE(name, false); + + struct RegulatorNode *node = RegulatorTreeGetParent(name); + CHECK_NULL_PTR_RETURN_VALUE(node, false); + + if ((node->regulatorInfo.parentName == NULL) || (strlen(node->regulatorInfo.parentName) == 0)) { + return true; + } else { + return RegulatorTreeIsUpNodeComplete(node->regulatorInfo.name); + } +} + +bool RegulatorTreeIsChildAlwayson(const char *name) +{ + CHECK_NULL_PTR_RETURN_VALUE(name, false); + struct DListHead *pList = RegulatorTreeGetChild(name); + CHECK_NULL_PTR_RETURN_VALUE(pList, false); + + struct RegulatorChildNode *nodeInfo = NULL; + struct RegulatorChildNode *tmp = NULL; + DLIST_FOR_EACH_ENTRY_SAFE(nodeInfo, tmp, pList, struct RegulatorChildNode, node) { + if (nodeInfo->child->regulatorInfo.constraints.alwaysOn) { + HDF_LOGD("RegulatorTreeIsChildAlwayson:%s's child %s alwaysOn true!", + name, nodeInfo->child->regulatorInfo.name); + return true; + } + } + + HDF_LOGD("RegulatorTreeIsChildAlwayson:%s's all child alwaysOn false!", name); + return false; +} + +bool RegulatorTreeIsChildStatusOn(const char *name) +{ + CHECK_NULL_PTR_RETURN_VALUE(name, false); + struct DListHead *pList = RegulatorTreeGetChild(name); + CHECK_NULL_PTR_RETURN_VALUE(pList, false); + + struct RegulatorChildNode *nodeInfo = NULL; + struct RegulatorChildNode *tmp = NULL; + DLIST_FOR_EACH_ENTRY_SAFE(nodeInfo, tmp, pList, struct RegulatorChildNode, node) { + if (nodeInfo->child->regulatorInfo.status == REGULATOR_STATUS_ON) { + HDF_LOGD("RegulatorTreeIsChildAlwayson:%s's child %s status on!", + name, nodeInfo->child->regulatorInfo.name); + return true; + } + } + + HDF_LOGD("RegulatorTreeIsChildAlwayson:%s's all child status off!", name); + return false; +} + bool RegulatorTreeIsAllChildDisable(const char *name) { CHECK_NULL_PTR_RETURN_VALUE(name, true); @@ -103,7 +166,8 @@ bool RegulatorTreeIsAllChildDisable(const char *name) CHECK_NULL_PTR_RETURN_VALUE(pList, true); struct RegulatorChildNode *nodeInfo = NULL; - DLIST_FOR_EACH_ENTRY(nodeInfo, pList, struct RegulatorChildNode, node) { + struct RegulatorChildNode *tmp = NULL; + DLIST_FOR_EACH_ENTRY_SAFE(nodeInfo, tmp, pList, struct RegulatorChildNode, node) { if (nodeInfo->child->regulatorInfo.status == REGULATOR_STATUS_ON) { HDF_LOGI("RegulatorTreeIsAllChildDisable:%s's child %s on!", name, nodeInfo->child->regulatorInfo.name); return false; @@ -118,10 +182,11 @@ int32_t RegulatorTreeChildForceDisable(struct RegulatorNode *node) { CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); struct DListHead *pList = RegulatorTreeGetChild(node->regulatorInfo.name); - CHECK_NULL_PTR_RETURN_VALUE(pList, HDF_ERR_INVALID_PARAM); + CHECK_NULL_PTR_RETURN_VALUE(pList, HDF_SUCCESS); struct RegulatorChildNode *nodeInfo = NULL; - DLIST_FOR_EACH_ENTRY(nodeInfo, pList, struct RegulatorChildNode, node) { + struct RegulatorChildNode *tmp = NULL; + DLIST_FOR_EACH_ENTRY_SAFE(nodeInfo, tmp, pList, struct RegulatorChildNode, node) { if (RegulatorTreeChildForceDisable(nodeInfo->child) != HDF_SUCCESS) { HDF_LOGE("RegulatorTreeChildForceDisable: %s fail!", nodeInfo->child->regulatorInfo.name); return HDF_FAILURE; @@ -150,17 +215,18 @@ static int32_t RegulatorTreeManagerNodeInit(const char *name) struct RegulatorTreeInfo *nodeInfo = NULL; struct RegulatorTreeInfo *pos = NULL; + struct RegulatorTreeInfo *tmp = NULL; struct RegulatorTreeManager *manager = g_regulatorTreeManager; CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE); if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) { - HDF_LOGE("RegulatorTreeSetParent: lock regulator manager fail!"); + HDF_LOGE("RegulatorTreeManagerNodeInit: lock regulator manager fail!"); return HDF_ERR_DEVICE_BUSY; } - DLIST_FOR_EACH_ENTRY(pos, &manager->treeMgrHead, struct RegulatorTreeInfo, node) { + DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->treeMgrHead, struct RegulatorTreeInfo, node) { if (strcmp(pos->name, name) == 0) { - HDF_LOGI("node %s has exists!", name); + HDF_LOGI("RegulatorTreeManagerNodeInit: node %s has exists!", name); (void)OsalMutexUnlock(&manager->lock); return HDF_SUCCESS; } @@ -179,12 +245,14 @@ static int32_t RegulatorTreeManagerNodeInit(const char *name) return HDF_SUCCESS; } +// set regulator (name)'s (parent) info static int RegulatorTreeSetParent(const char *name, struct RegulatorNode *parent) { CHECK_NULL_PTR_RETURN_VALUE(name, HDF_ERR_INVALID_PARAM); CHECK_NULL_PTR_RETURN_VALUE(parent, HDF_ERR_INVALID_PARAM); struct RegulatorTreeInfo *pos = NULL; + struct RegulatorTreeInfo *tmp = NULL; struct RegulatorTreeManager *manager = g_regulatorTreeManager; CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE); @@ -193,7 +261,7 @@ static int RegulatorTreeSetParent(const char *name, struct RegulatorNode *parent return HDF_ERR_DEVICE_BUSY; } - DLIST_FOR_EACH_ENTRY(pos, &manager->treeMgrHead, struct RegulatorTreeInfo, node) { + DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->treeMgrHead, struct RegulatorTreeInfo, node) { if (strcmp(pos->name, name) == 0) { pos->parent = parent; (void)OsalMutexUnlock(&manager->lock); @@ -206,12 +274,15 @@ static int RegulatorTreeSetParent(const char *name, struct RegulatorNode *parent HDF_LOGI("RegulatorTreeSetParent:%s does not exist!", name); return HDF_FAILURE; } + +// add (child) to regulator (name)'s childHead static int RegulatorTreeSetChild(const char *name, struct RegulatorNode *child) { CHECK_NULL_PTR_RETURN_VALUE(name, HDF_ERR_INVALID_PARAM); CHECK_NULL_PTR_RETURN_VALUE(child, HDF_ERR_INVALID_PARAM); struct RegulatorTreeInfo *pos = NULL; + struct RegulatorTreeInfo *tmp = NULL; struct RegulatorTreeManager *manager = g_regulatorTreeManager; CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE); @@ -220,7 +291,7 @@ static int RegulatorTreeSetChild(const char *name, struct RegulatorNode *child) return HDF_ERR_DEVICE_BUSY; } - DLIST_FOR_EACH_ENTRY(pos, &manager->treeMgrHead, struct RegulatorTreeInfo, node) { + DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->treeMgrHead, struct RegulatorTreeInfo, node) { if (strcmp(pos->name, name) == 0) { if (RegulatorChildNodeAdd(pos, child) != HDF_SUCCESS) { HDF_LOGE("RegulatorTreeSetChild: RegulatorChildNodeAdd fail!"); @@ -228,7 +299,7 @@ static int RegulatorTreeSetChild(const char *name, struct RegulatorNode *child) return HDF_FAILURE; } (void)OsalMutexUnlock(&manager->lock); - HDF_LOGI("RegulatorTreeSetChild: set %s parent success!", name); + HDF_LOGI("RegulatorTreeSetChild: set %s child success!", name); return HDF_SUCCESS; } } @@ -238,6 +309,12 @@ static int RegulatorTreeSetChild(const char *name, struct RegulatorNode *child) return HDF_FAILURE; } +/* +* name: child regulator node name +* child: child regulator node info +* parent: parent regulator node info +* process: set regultor (name)'s RegulatorTreeInfo:parent,and add (name) to (parent)'s RegulatorTreeInfo:childHead +*/ int RegulatorTreeSet(const char *name, struct RegulatorNode *child, struct RegulatorNode *parent) { CHECK_NULL_PTR_RETURN_VALUE(name, HDF_ERR_INVALID_PARAM); @@ -262,7 +339,8 @@ int RegulatorTreeSet(const char *name, struct RegulatorNode *child, struct Regul return HDF_FAILURE; } - HDF_LOGI("RegulatorTreeSet: set [%s], parent[%s] success!", name, parent->regulatorInfo.name); + HDF_LOGI("RegulatorTreeSet: set [%s], parent[%s] and child info success!", + name, parent->regulatorInfo.name); return HDF_SUCCESS; } static void RegulatorTreePrintChild(const char *name, struct DListHead *childHead) @@ -271,16 +349,18 @@ static void RegulatorTreePrintChild(const char *name, struct DListHead *childHea CHECK_NULL_PTR_RETURN(name); struct RegulatorChildNode *nodeInfo = NULL; + struct RegulatorChildNode *tmp = NULL; - DLIST_FOR_EACH_ENTRY(nodeInfo, childHead, struct RegulatorChildNode, node) { + DLIST_FOR_EACH_ENTRY_SAFE(nodeInfo, tmp, childHead, struct RegulatorChildNode, node) { HDF_LOGI("RegulatorTreePrintChild: %s's child %s !", name, nodeInfo->child->regulatorInfo.name); } } -static void RegulatorTreePrint(void) +void RegulatorTreePrint(void) { struct RegulatorTreeInfo *pos = NULL; + struct RegulatorTreeInfo *tmp = NULL; struct RegulatorTreeManager *manager = g_regulatorTreeManager; CHECK_NULL_PTR_RETURN(manager); @@ -289,7 +369,7 @@ static void RegulatorTreePrint(void) return; } - DLIST_FOR_EACH_ENTRY(pos, &manager->treeMgrHead, struct RegulatorTreeInfo, node) { + DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->treeMgrHead, struct RegulatorTreeInfo, node) { HDF_LOGI("RegulatorTreePrint %s info IN ---->", pos->name); if (pos->parent != NULL) { HDF_LOGI("RegulatorTreePrint %s info, parent name[%s]", @@ -305,6 +385,7 @@ static void RegulatorTreePrint(void) int RegulatorTreeNodeRemoveAll(void) { struct RegulatorTreeInfo *nodeInfo = NULL; + struct RegulatorTreeInfo *tmp = NULL; struct RegulatorTreeManager *manager = g_regulatorTreeManager; CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE); @@ -313,7 +394,7 @@ int RegulatorTreeNodeRemoveAll(void) return HDF_ERR_DEVICE_BUSY; } - DLIST_FOR_EACH_ENTRY(nodeInfo, &manager->treeMgrHead, struct RegulatorTreeInfo, node) { + DLIST_FOR_EACH_ENTRY_SAFE(nodeInfo, tmp, &manager->treeMgrHead, struct RegulatorTreeInfo, node) { RegulatorChildListDestroy(nodeInfo); DListRemove(&nodeInfo->node); OsalMemFree(nodeInfo); diff --git a/test/unittest/platform/common/regulator_test.c b/test/unittest/platform/common/regulator_test.c index 78a789e7..3bbebe10 100755 --- a/test/unittest/platform/common/regulator_test.c +++ b/test/unittest/platform/common/regulator_test.c @@ -12,6 +12,10 @@ #include "osal_thread.h" #include "osal_time.h" #include "regulator_if.h" +#if defined(CONFIG_DRIVERS_HDF_PLATFORM_REGULATOR) +#include "virtual/regulator_linux_voltage_virtual_driver.h" +#include "virtual/regulator_linux_current_virtual_driver.h" +#endif #define HDF_LOG_TAG regulator_test_c @@ -73,7 +77,6 @@ static int32_t RegulatorSetVoltageTest(struct RegulatorTest *test) return HDF_SUCCESS; } - HDF_LOGD("%s: UV[%d, %d]", __func__, test->maxUv, test->minUv); if (RegulatorSetVoltage(test->handle, test->minUv, test->maxUv) != HDF_SUCCESS) { HDF_LOGE("%s:[%d, %d] test fail", __func__, test->maxUv, test->minUv); return HDF_FAILURE; @@ -97,7 +100,6 @@ static int32_t RegulatorGetVoltageTest(struct RegulatorTest *test) return HDF_FAILURE; } - HDF_LOGD("%s: UV[%d]", __func__, test->uv); return HDF_SUCCESS; } static int32_t RegulatorSetCurrentTest(struct RegulatorTest *test) @@ -111,7 +113,6 @@ static int32_t RegulatorSetCurrentTest(struct RegulatorTest *test) return HDF_SUCCESS; } - HDF_LOGD("%s: Ua[%d, %d]", __func__, test->minUa, test->maxUa); if (RegulatorSetCurrent(test->handle, test->minUa, test->maxUa) != HDF_SUCCESS) { HDF_LOGE("%s:[%d, %d] test fail", __func__, test->minUa, test->maxUa); return HDF_FAILURE; @@ -135,7 +136,6 @@ static int32_t RegulatorGetCurrentTest(struct RegulatorTest *test) return HDF_FAILURE; } - HDF_LOGD("%s: Ua[%d]", __func__, test->ua); return HDF_SUCCESS; } static int32_t RegulatorGetStatusTest(struct RegulatorTest *test) @@ -155,7 +155,6 @@ static int32_t RegulatorGetStatusTest(struct RegulatorTest *test) return HDF_FAILURE; } - HDF_LOGD("%s: status[%d]", __func__, test->status); return HDF_SUCCESS; } static int RegulatorTestThreadFunc(void *param) @@ -269,8 +268,6 @@ static int32_t RegulatorTestEntry(struct RegulatorTest *test, int32_t cmd) int32_t i; int32_t ret = HDF_ERR_NOT_SUPPORT; - HDF_LOGD("regulator test-- -- -- -- -- -->%s: enter cmd %d", __func__, cmd); - if (test == NULL || test->name == NULL) { HDF_LOGE("%s: test null cmd %d", __func__, cmd); return HDF_ERR_INVALID_OBJECT; @@ -301,7 +298,6 @@ static int32_t RegulatorTestEntry(struct RegulatorTest *test, int32_t cmd) static int32_t RegulatorTestBind(struct HdfDeviceObject *device) { static struct RegulatorTest test; - HDF_LOGD("RegulatorTestBind in\r\n"); if (device != NULL) { device->service = &test.service; @@ -309,7 +305,7 @@ static int32_t RegulatorTestBind(struct HdfDeviceObject *device) HDF_LOGE("%s: device is NULL", __func__); } - HDF_LOGD("RegulatorTestBind out\r\n"); + HDF_LOGI("RegulatorTestBind success\r\n"); return HDF_SUCCESS; } @@ -364,7 +360,7 @@ static int32_t RegulatorTestInitFromHcs(struct RegulatorTest *test, const struct return HDF_FAILURE; } - HDF_LOGD("regulator test init:[%s][%d]--[%d][%d]--[%d][%d]!", + HDF_LOGI("regulator test init:[%s][%d]--[%d][%d]--[%d][%d]!", test->name, test->mode, test->minUv, test->maxUv, test->minUa, test->maxUa); return HDF_SUCCESS; @@ -374,7 +370,12 @@ static int32_t RegulatorTestInit(struct HdfDeviceObject *device) { struct RegulatorTest *test = NULL; - HDF_LOGD("RegulatorTestInit in\r\n"); + HDF_LOGI("RegulatorTestInit in\r\n"); + +#if defined(CONFIG_DRIVERS_HDF_PLATFORM_REGULATOR) + VirtualVoltageRegulatorAdapterInit(); + VirtualCurrentRegulatorAdapterInit(); +#endif if (device == NULL || device->service == NULL || device->property == NULL) { HDF_LOGE("%s: invalid parameter", __func__); @@ -388,7 +389,7 @@ static int32_t RegulatorTestInit(struct HdfDeviceObject *device) } test->TestEntry = RegulatorTestEntry; - HDF_LOGD("%s: success", __func__); + HDF_LOGI("%s: success", __func__); return HDF_SUCCESS; } diff --git a/test/unittest/platform/virtual/regulator_linux_current_virtual_driver.c b/test/unittest/platform/virtual/regulator_linux_current_virtual_driver.c new file mode 100755 index 00000000..dd669efb --- /dev/null +++ b/test/unittest/platform/virtual/regulator_linux_current_virtual_driver.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hdf_log.h" +#include "hdf_base.h" + +#define HDF_LOG_TAG regulator_virtual_current + +struct VirtualCurrentRegulatorDev { + struct regmap *regmap; + struct regulator_dev *dev; +}; + +// note:linux kernel constraints:len(devName) + len(supplyName) < REG_STR_SIZE(64) +static struct regulator_consumer_supply g_virtualCurrentRegulatorSupplies[] = { + REGULATOR_SUPPLY("vir-current-reg-hdf-adp", "regulator_adapter_consumer01"), +}; + +// virtual regulator init info +static struct regulator_init_data g_virtualCurrentRegulatorInitData = { + .constraints = { + .name = "virtual_current_regulator", + .min_uA = 1000, + .max_uA = 50000, + .valid_ops_mask = REGULATOR_CHANGE_CURRENT | + REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(g_virtualCurrentRegulatorSupplies), + .consumer_supplies = g_virtualCurrentRegulatorSupplies, +}; + +static void VirtualCurrentRegulatorDevRelease(struct device *dev) +{ +} + +static struct platform_device g_virtualCurrentRegulatorPlatformDevice = { + .name = "virtual_current_regulator_dev", + .id = -1, + .dev = { + .release = VirtualCurrentRegulatorDevRelease, + } +}; + +enum RegulatorStatus { + VIR_REGULATOR_STATUS_OFF, + VIR_REGULATOR_STATUS_ON, +}; + +static int g_virStatus = VIR_REGULATOR_STATUS_OFF; +static int VirtualCurrentRegulatorEnable(struct regulator_dev *rdev) +{ + if (rdev == NULL) { + HDF_LOGE("%s: rdev NULL", __func__); + return HDF_FAILURE; + } + + g_virStatus = VIR_REGULATOR_STATUS_ON; + return HDF_SUCCESS; +} + +static int VirtualCurrentRegulatorDisable(struct regulator_dev *rdev) +{ + if (rdev == NULL) { + HDF_LOGE("%s: rdev NULL", __func__); + return HDF_FAILURE; + } + + g_virStatus = VIR_REGULATOR_STATUS_OFF; + return HDF_SUCCESS; +} + +static int VirtualCurrentRegulatorIsEnabled(struct regulator_dev *rdev) +{ + if (rdev == NULL) { + HDF_LOGE("%s: rdev NULL", __func__); + return HDF_FAILURE; + } + + return g_virStatus; +} + +static int VirtualCurrentRegulatorSetCurrent(struct regulator_dev *rdev, int min_uA, + int max_uA) +{ + if ((rdev == NULL) || (rdev->constraints == NULL)) { + HDF_LOGE("%s: rdev NULL", __func__); + return HDF_FAILURE; + } + + struct regulation_constraints *regu_constraints = rdev->constraints; + if (regu_constraints->min_uA == min_uA && + regu_constraints->max_uA == max_uA) { + return HDF_SUCCESS; + } + + return HDF_SUCCESS; +} + +#define VIRTUAL_CURRENT_VAL_500 500 +static int VirtualCurrentRegulatorGetCurrent(struct regulator_dev *rdev) +{ + if (rdev == NULL) { + HDF_LOGE("%s: rdev NULL", __func__); + return HDF_FAILURE; + } + + return VIRTUAL_CURRENT_VAL_500; +} + +static struct regulator_ops g_virtualCurrentRegulatorOps = { + .enable = VirtualCurrentRegulatorEnable, + .disable = VirtualCurrentRegulatorDisable, + .is_enabled = VirtualCurrentRegulatorIsEnabled, + .set_current_limit = VirtualCurrentRegulatorSetCurrent, + .get_current_limit = VirtualCurrentRegulatorGetCurrent, +}; + +static struct regulator_desc g_virtualCurrentRegulatorDesc = { + .name = "regulator_virtual_current", + .type = REGULATOR_CURRENT, + .ops = &g_virtualCurrentRegulatorOps, + .owner = THIS_MODULE, +}; + +static int VirtualCurrentRegulatorPlatformProbe(struct platform_device *platform_dev) +{ + if (platform_dev == NULL) { + HDF_LOGE("%s: platform_dev null!", __func__); + return HDF_FAILURE; + } + struct VirtualCurrentRegulatorDev *data; + struct regulator_config config; + + memset(&config, 0, sizeof(struct regulator_config)); + + data = devm_kzalloc(&platform_dev->dev, sizeof(*data), GFP_KERNEL); + if (!data) { + HDF_LOGE("%s: devm_kzalloc error!", __func__); + return -ENOMEM; + } + config.dev = &platform_dev->dev; + config.init_data = &g_virtualCurrentRegulatorInitData; + config.driver_data = data; + + data->dev = regulator_register(&g_virtualCurrentRegulatorDesc, &config); + if (IS_ERR(data->dev)) { + HDF_LOGE("%s: failed to register regulator %s\n", __func__, g_virtualCurrentRegulatorDesc.name); + return PTR_ERR(data->dev); + } + + platform_set_drvdata(platform_dev, data); + HDF_LOGI("%s: success", __func__); + return 0; +} + +static int VirtualCurrentRegulatorPlatformRemove(struct platform_device *platform_dev) +{ + struct VirtualCurrentRegulatorDev *rdev = platform_get_drvdata(platform_dev); + + regulator_unregister(rdev->dev); + + platform_set_drvdata(platform_dev, NULL); + HDF_LOGI("%s: success", __func__); + return 0; +} + +static struct platform_driver g_virtualCurrentRegulatorPlatformDriver = { + .driver = { + .name = "virtual_current_regulator_dev", + .owner = THIS_MODULE, + }, + .probe = VirtualCurrentRegulatorPlatformProbe, + .remove = VirtualCurrentRegulatorPlatformRemove, +}; + +int VirtualCurrentRegulatorAdapterInit(void) +{ + int ret = platform_device_register(&g_virtualCurrentRegulatorPlatformDevice); + if(ret == 0) { + ret = platform_driver_register(&g_virtualCurrentRegulatorPlatformDriver); + } else { + HDF_LOGE("%s:device register fail %d", __func__, ret); + } + return ret; +} + +static int __init VirtualCurrentRegulatorInit(void) +{ + int ret = platform_device_register(&g_virtualCurrentRegulatorPlatformDevice); + if(ret == 0) { + ret = platform_driver_register(&g_virtualCurrentRegulatorPlatformDriver); + } + return ret; +} + +static void __exit VirtualCurrentRegulatorExit(void) +{ + platform_device_unregister(&g_virtualCurrentRegulatorPlatformDevice); + platform_driver_unregister(&g_virtualCurrentRegulatorPlatformDriver); +} + +MODULE_DESCRIPTION("Virtual current Regulator Controller Platform Device Drivers"); +MODULE_LICENSE("GPL"); diff --git a/test/unittest/platform/virtual/regulator_linux_current_virtual_driver.h b/test/unittest/platform/virtual/regulator_linux_current_virtual_driver.h new file mode 100755 index 00000000..5ee1ef55 --- /dev/null +++ b/test/unittest/platform/virtual/regulator_linux_current_virtual_driver.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef REGULATOR_LINUX_CURRENT_VIRTUAL_DRIVER_H +#define REGULATOR_LINUX_CURRENT_VIRTUAL_DRIVER_H +#include "hdf_base.h" + +int VirtualCurrentRegulatorAdapterInit(void); + +#endif /* REGULATOR_LINUX_CURRENT_VIRTUAL_DRIVER_H */ diff --git a/test/unittest/platform/virtual/regulator_linux_voltage_virtual_driver.c b/test/unittest/platform/virtual/regulator_linux_voltage_virtual_driver.c new file mode 100755 index 00000000..19894220 --- /dev/null +++ b/test/unittest/platform/virtual/regulator_linux_voltage_virtual_driver.c @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hdf_log.h" +#include "hdf_base.h" + +#define HDF_LOG_TAG regulator_virtual + +struct VirtualVoltageRegulatorDev { + struct regmap *regmap; + struct regulator_dev *dev; +}; + +// note:linux kernel constraints:len(devName) + len(supplyName) < REG_STR_SIZE(64) +static struct regulator_consumer_supply g_virtualVoltageRegulatorVoltSupplies[] = { + REGULATOR_SUPPLY("vir-voltage-reg-hdf-adp", "regulator_adapter_consumer01"), +}; + +// virtual regulator init info +static struct regulator_init_data g_virtualVoltageRegulatorInitData = { + .constraints = { + .name = "virtual_regulator", + .min_uV = 1000, + .max_uV = 50000, + .always_on = 1, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(g_virtualVoltageRegulatorVoltSupplies), + .consumer_supplies = g_virtualVoltageRegulatorVoltSupplies, +}; + +static void VirtualVoltageRegulatorDevRelease(struct device *dev) +{ +} +static struct platform_device g_virtualVoltageRegulatorPlatformDevice = { + .name = "virtual_regulator_dev", + .id = -1, + .dev = { + .release = VirtualVoltageRegulatorDevRelease, + } +}; + +enum RegulatorStatus { + VIR_REGULATOR_STATUS_OFF, + VIR_REGULATOR_STATUS_ON, +}; + +static int g_virStatus = VIR_REGULATOR_STATUS_OFF; +static int VirtualVoltageRegulatorEnable(struct regulator_dev *rdev) +{ + if (rdev == NULL) { + HDF_LOGE("%s: rdev NULL", __func__); + return HDF_FAILURE; + } + + g_virStatus = VIR_REGULATOR_STATUS_ON; + return HDF_SUCCESS; +} + +static int VirtualVoltageRegulatorDisable(struct regulator_dev *rdev) +{ + if (rdev == NULL) { + HDF_LOGE("%s: rdev NULL", __func__); + return HDF_FAILURE; + } + + g_virStatus = VIR_REGULATOR_STATUS_OFF; + return HDF_SUCCESS; +} + +static int VirtualVoltageRegulatorIsEnabled(struct regulator_dev *rdev) +{ + if (rdev == NULL) { + HDF_LOGE("%s: rdev NULL", __func__); + return HDF_FAILURE; + } + + return g_virStatus; +} + +static int VirtualVoltageRegulatorSetVoltage(struct regulator_dev *rdev, int min_uV, + int max_uV, unsigned *selector) +{ + if ((rdev == NULL) || (rdev->constraints == NULL)) { + HDF_LOGE("%s: rdev NULL", __func__); + return HDF_FAILURE; + } + + struct regulation_constraints *regu_constraints = rdev->constraints; + if (regu_constraints->min_uV == min_uV && + regu_constraints->max_uV == max_uV) { + return HDF_SUCCESS; + } + + return HDF_SUCCESS; +} + +#define VIRTUAL_VOLTAGE_VAL_500 500 +static int VirtualVoltageRegulatorGetVoltage(struct regulator_dev *rdev) +{ + if (rdev == NULL) { + HDF_LOGE("%s: rdev NULL", __func__); + return HDF_FAILURE; + } + + return VIRTUAL_VOLTAGE_VAL_500; +} + +static struct regulator_ops g_virtualVoltageRegulatorOps = { + .enable = VirtualVoltageRegulatorEnable, + .disable = VirtualVoltageRegulatorDisable, + .is_enabled = VirtualVoltageRegulatorIsEnabled, + .set_voltage = VirtualVoltageRegulatorSetVoltage, + .get_voltage = VirtualVoltageRegulatorGetVoltage, +}; + +static struct regulator_desc g_virtualVoltageRegulatorDesc = { + .name = "regulator_virtual", + .type = REGULATOR_VOLTAGE, + .ops = &g_virtualVoltageRegulatorOps, + .min_uV = 1000, + .owner = THIS_MODULE, +}; + +static int VirtualVoltageRegulatorPlatformProbe(struct platform_device *platform_dev) +{ + if (platform_dev == NULL) { + HDF_LOGE("%s: platform_dev null!", __func__); + return HDF_FAILURE; + } + struct VirtualVoltageRegulatorDev *data; + struct regulator_config config; + + memset(&config, 0, sizeof(struct regulator_config)); + + data = devm_kzalloc(&platform_dev->dev, sizeof(*data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + config.dev = &platform_dev->dev; + config.init_data = &g_virtualVoltageRegulatorInitData; + config.driver_data = data; + + data->dev = regulator_register(&g_virtualVoltageRegulatorDesc, &config); + if (IS_ERR(data->dev)) { + HDF_LOGE("%s: failed to register regulator %s\n", __func__, g_virtualVoltageRegulatorDesc.name); + return PTR_ERR(data->dev); + } + + platform_set_drvdata(platform_dev, data); + HDF_LOGI("%s: success", __func__); + return 0; +} + +static int VirtualVoltageRegulatorPlatformRemove(struct platform_device *platform_dev) +{ + struct VirtualVoltageRegulatorDev *rdev = platform_get_drvdata(platform_dev); + + regulator_unregister(rdev->dev); + + platform_set_drvdata(platform_dev, NULL); + HDF_LOGI("VirtualVoltageRegulatorPlatformRemove"); + return 0; +} + +static struct platform_driver g_virtualVoltageRegulatorPlatformDriver = { + .driver = { + .name = "virtual_regulator_dev", + .owner = THIS_MODULE, + }, + .probe = VirtualVoltageRegulatorPlatformProbe, + .remove = VirtualVoltageRegulatorPlatformRemove, +}; + +int VirtualVoltageRegulatorAdapterInit(void) +{ + HDF_LOGI("VirtualVoltageRegulatorAdapterInit"); + int ret = platform_device_register(&g_virtualVoltageRegulatorPlatformDevice); + if(ret == 0) { + ret = platform_driver_register(&g_virtualVoltageRegulatorPlatformDriver); + } else { + HDF_LOGE("VirtualVoltageRegulatorAdapterInit:device register fail %d", ret); + } + return ret; +} + +static int __init VirtualVoltageRegulatorInit(void) +{ + HDF_LOGI("VirtualVoltageRegulatorInit"); + int ret = platform_device_register(&g_virtualVoltageRegulatorPlatformDevice); + if(ret == 0) { + ret = platform_driver_register(&g_virtualVoltageRegulatorPlatformDriver); + } + return ret; +} + +static void __exit VirtualVoltageRegulatorExit(void) +{ + HDF_LOGI("VirtualVoltageRegulatorExit"); + platform_device_unregister(&g_virtualVoltageRegulatorPlatformDevice); + platform_driver_unregister(&g_virtualVoltageRegulatorPlatformDriver); +} + +MODULE_DESCRIPTION("Virtual voltage Regulator Controller Platform Device Drivers"); +MODULE_LICENSE("GPL"); diff --git a/test/unittest/platform/virtual/regulator_linux_voltage_virtual_driver.h b/test/unittest/platform/virtual/regulator_linux_voltage_virtual_driver.h new file mode 100755 index 00000000..706f0f2c --- /dev/null +++ b/test/unittest/platform/virtual/regulator_linux_voltage_virtual_driver.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef REGULATOR_LINUX_VOLTAGE_VIRTUAL_DRIVER_H +#define REGULATOR_LINUX_VOLTAGE_VIRTUAL_DRIVER_H +#include "hdf_base.h" + +int VirtualVoltageRegulatorAdapterInit(void); + +#endif /* REGULATOR_LINUX_VOLTAGE_VIRTUAL_DRIVER_H */ diff --git a/test/unittest/platform/virtual/regulator_virtual.c b/test/unittest/platform/virtual/regulator_virtual.c index 5bd0414e..847f0993 100755 --- a/test/unittest/platform/virtual/regulator_virtual.c +++ b/test/unittest/platform/virtual/regulator_virtual.c @@ -273,11 +273,10 @@ static int32_t VirtualRegulatorInit(struct HdfDeviceObject *device) ret = VirtualRegulatorParseAndInit(device, childNode); if (ret != HDF_SUCCESS) { HDF_LOGE("%s:VirtualRegulatorParseAndInit fail", __func__); - RegulatorNodeRemoveAll(); return HDF_FAILURE; } } - + HDF_LOGI("%s: success", __func__); return HDF_SUCCESS; }