• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * regulator driver adapter of linux
3  *
4  * Copyright (c) 2021 Huawei Device Co., Ltd.
5  *
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  */
16 #include "regulator_adapter.h"
17 #include "regulator_adapter_consumer.h"
18 #include "regulator_core.h"
19 #include <linux/regulator/consumer.h>
20 #include "device_resource_if.h"
21 #include "hdf_device_desc.h"
22 #include "hdf_log.h"
23 #include "osal_mem.h"
24 
25 #define HDF_LOG_TAG regulator_linux_adapter
LinuxRegulatorOpen(struct RegulatorNode * node)26 static int32_t LinuxRegulatorOpen(struct RegulatorNode *node)
27 {
28     if (node == NULL || node->priv == NULL) {
29         HDF_LOGE("%s: node null", __func__);
30         return HDF_ERR_INVALID_OBJECT;
31     }
32 
33     struct LinuxRegulatorInfo *info = (struct LinuxRegulatorInfo *)node->priv;
34     if (info->adapterReg == NULL) {
35         const char *devname = dev_name(info->dev);
36         if ((devname == NULL) || (strcmp(devname, info->devName) != 0)) {
37             HDF_LOGE("%s:dev info error [%s][%s]!", __func__, devname, info->devName);
38             return HDF_FAILURE;
39         }
40 
41         info->adapterReg = regulator_get(info->dev, info->supplyName);
42         if (IS_ERR(info->adapterReg)) {
43             HDF_LOGE("%s: regulator_get [%s][%s] ERROR!", __func__, devname, info->supplyName);
44             info->adapterReg = NULL;
45             return HDF_FAILURE;
46         }
47         if (info->adapterReg == NULL) {
48             HDF_LOGE("%s: regulator_get [%s][%s]!", __func__, devname, info->supplyName);
49             return HDF_FAILURE;
50         }
51     }
52 
53     return HDF_SUCCESS;
54 }
LinuxRegulatorClose(struct RegulatorNode * node)55 static int32_t LinuxRegulatorClose(struct RegulatorNode *node)
56 {
57     if (node == NULL || node->priv == NULL) {
58         HDF_LOGE("%s: node null", __func__);
59         return HDF_ERR_INVALID_OBJECT;
60     }
61 
62     struct LinuxRegulatorInfo *info = (struct LinuxRegulatorInfo *)node->priv;
63     if (info->adapterReg != NULL) {
64         if (regulator_disable(info->adapterReg) != HDF_SUCCESS) {
65             HDF_LOGE("%s:regulator_disable[%s][%s] FAIL", __func__, node->regulatorInfo.name, info->supplyName);
66         }
67         regulator_put(info->adapterReg);
68         info->adapterReg = NULL;
69     }
70     return HDF_SUCCESS;
71 }
LinuxRegulatorRemove(struct RegulatorNode * node)72 static int32_t LinuxRegulatorRemove(struct RegulatorNode *node)
73 {
74     if (node == NULL || node->priv == NULL) {
75         HDF_LOGE("%s: node null", __func__);
76         return HDF_ERR_INVALID_OBJECT;
77     }
78 
79     struct LinuxRegulatorInfo *info = (struct LinuxRegulatorInfo *)node->priv;
80     HDF_LOGI("%s:regulator [%s][%s] release!", __func__, info->devName, info->supplyName);
81     if (LinuxRegulatorClose(node) != HDF_SUCCESS) {
82         HDF_LOGE("%s:LinuxRegulatorClose fail[%s][%s]!", __func__, info->devName, info->supplyName);
83     }
84 
85     OsalMemFree(info);
86     node->priv = NULL;
87     return HDF_SUCCESS;
88 }
89 
LinuxRegulatorEnable(struct RegulatorNode * node)90 static int32_t LinuxRegulatorEnable(struct RegulatorNode *node)
91 {
92     if (node == NULL || node->priv == NULL) {
93         HDF_LOGE("%s: node null", __func__);
94         return HDF_ERR_INVALID_OBJECT;
95     }
96 
97     struct LinuxRegulatorInfo *info = (struct LinuxRegulatorInfo *)node->priv;
98     if (info->adapterReg == NULL) {
99         HDF_LOGE("%s adapterReg null, please open dev", __func__);
100         return HDF_ERR_INVALID_OBJECT;
101     }
102     int ret = regulator_enable(info->adapterReg);
103     if (ret != HDF_SUCCESS) {
104         HDF_LOGE("%s:[%s][%s][%d] FAIL", __func__, node->regulatorInfo.name, info->supplyName, ret);
105         return HDF_FAILURE;
106     }
107     if (regulator_is_enabled(info->adapterReg) > 0) {
108         node->regulatorInfo.status = REGULATOR_STATUS_ON;
109     } else {
110         node->regulatorInfo.status = REGULATOR_STATUS_OFF;
111     }
112     return HDF_SUCCESS;
113 }
114 
LinuxRegulatorDisable(struct RegulatorNode * node)115 static int32_t LinuxRegulatorDisable(struct RegulatorNode *node)
116 {
117     if (node == NULL || node->priv == NULL) {
118         HDF_LOGE("%s: node null", __func__);
119         return HDF_ERR_INVALID_OBJECT;
120     }
121 
122     struct LinuxRegulatorInfo *info = (struct LinuxRegulatorInfo *)node->priv;
123     if (info->adapterReg == NULL) {
124         HDF_LOGE("%s adapterReg null, please open dev", __func__);
125         return HDF_ERR_INVALID_OBJECT;
126     }
127     if (regulator_disable(info->adapterReg) != HDF_SUCCESS) {
128         HDF_LOGE("%s:[%s][%s] FAIL", __func__, node->regulatorInfo.name, info->supplyName);
129         return HDF_FAILURE;
130     }
131     // node maybe alwayson
132     if (regulator_is_enabled(info->adapterReg) > 0) {
133         node->regulatorInfo.status = REGULATOR_STATUS_ON;
134     } else {
135         node->regulatorInfo.status = REGULATOR_STATUS_OFF;
136     }
137     return HDF_SUCCESS;
138 }
139 
LinuxRegulatorForceDisable(struct RegulatorNode * node)140 static int32_t LinuxRegulatorForceDisable(struct RegulatorNode *node)
141 {
142     if (node == NULL || node->priv == NULL) {
143         HDF_LOGE("%s: node null", __func__);
144         return HDF_ERR_INVALID_OBJECT;
145     }
146 
147     struct LinuxRegulatorInfo *info = (struct LinuxRegulatorInfo *)node->priv;
148     if (info->adapterReg == NULL) {
149         HDF_LOGE("%s adapterReg null, please open dev", __func__);
150         return HDF_ERR_INVALID_OBJECT;
151     }
152     if (regulator_force_disable(info->adapterReg) != HDF_SUCCESS) {
153         HDF_LOGE("regulator_force_disable[%s][%s] FAIL", node->regulatorInfo.name, info->supplyName);
154         return HDF_FAILURE;
155     }
156     node->regulatorInfo.status = REGULATOR_STATUS_OFF;
157     HDF_LOGI("%s:[%s][%s] success!", __func__, info->devName, info->supplyName);
158     return HDF_SUCCESS;
159 }
160 
LinuxRegulatorSetVoltage(struct RegulatorNode * node,uint32_t minUv,uint32_t maxUv)161 static int32_t LinuxRegulatorSetVoltage(struct RegulatorNode *node, uint32_t minUv, uint32_t maxUv)
162 {
163     if (node == NULL || node->priv == NULL) {
164         HDF_LOGE("%s: node null", __func__);
165         return HDF_ERR_INVALID_OBJECT;
166     }
167 
168     struct LinuxRegulatorInfo *info = (struct LinuxRegulatorInfo *)node->priv;
169     if (info->adapterReg == NULL) {
170         HDF_LOGE("%s adapterReg null, please open dev", __func__);
171         return HDF_ERR_INVALID_OBJECT;
172     }
173     if (regulator_set_voltage(info->adapterReg, minUv, maxUv) != HDF_SUCCESS) {
174         HDF_LOGE("%s: [%s][%s] FAIL", __func__, node->regulatorInfo.name, info->supplyName);
175         return HDF_FAILURE;
176     }
177 
178     return HDF_SUCCESS;
179 }
180 
LinuxRegulatorGetVoltage(struct RegulatorNode * node,uint32_t * voltage)181 static int32_t LinuxRegulatorGetVoltage(struct RegulatorNode *node, uint32_t *voltage)
182 {
183     if (node == NULL || node->priv == NULL || voltage == NULL) {
184         HDF_LOGE("%s: node null", __func__);
185         return HDF_ERR_INVALID_OBJECT;
186     }
187 
188     struct LinuxRegulatorInfo *info = (struct LinuxRegulatorInfo *)node->priv;
189     if (info->adapterReg == NULL) {
190         HDF_LOGE("%s adapterReg null, please open dev", __func__);
191         return HDF_ERR_INVALID_OBJECT;
192     }
193     int ret = regulator_get_voltage(info->adapterReg);
194     if (ret < 0) {
195         HDF_LOGE("%s: [%s] FAIL", __func__, node->regulatorInfo.name);
196         return HDF_FAILURE;
197     }
198 
199     *voltage = ret;
200     return HDF_SUCCESS;
201 }
202 
LinuxRegulatorSetCurrent(struct RegulatorNode * node,uint32_t minUa,uint32_t maxUa)203 static int32_t LinuxRegulatorSetCurrent(struct RegulatorNode *node, uint32_t minUa, uint32_t maxUa)
204 {
205     if (node == NULL) {
206         HDF_LOGE("%s: node null", __func__);
207         return HDF_ERR_INVALID_OBJECT;
208     }
209 
210     struct LinuxRegulatorInfo *info = (struct LinuxRegulatorInfo *)node->priv;
211     if (info->adapterReg == NULL) {
212         HDF_LOGE("%s adapterReg null, please open dev", __func__);
213         return HDF_ERR_INVALID_OBJECT;
214     }
215     if (regulator_set_current_limit(info->adapterReg, minUa, maxUa) != HDF_SUCCESS) {
216         HDF_LOGE("%s: [%s][%s] FAIL", __func__, node->regulatorInfo.name, info->supplyName);
217         return HDF_FAILURE;
218     }
219     return HDF_SUCCESS;
220 }
221 
LinuxRegulatorGetCurrent(struct RegulatorNode * node,uint32_t * regCurrent)222 static int32_t LinuxRegulatorGetCurrent(struct RegulatorNode *node, uint32_t *regCurrent)
223 {
224     if (node == NULL || regCurrent == NULL) {
225         HDF_LOGE("%s: node null", __func__);
226         return HDF_ERR_INVALID_OBJECT;
227     }
228 
229     struct LinuxRegulatorInfo *info = (struct LinuxRegulatorInfo *)node->priv;
230     if (info->adapterReg == NULL) {
231         HDF_LOGE("%s adapterReg null, please open dev", __func__);
232         return HDF_ERR_INVALID_OBJECT;
233     }
234     int ret = regulator_get_current_limit(info->adapterReg);
235     if (ret < 0) {
236         HDF_LOGE("%s: [%s] FAIL", __func__, node->regulatorInfo.name);
237         return HDF_FAILURE;
238     }
239 
240     *regCurrent = ret;
241     return HDF_SUCCESS;
242 }
243 
LinuxRegulatorGetStatus(struct RegulatorNode * node,uint32_t * status)244 static int32_t LinuxRegulatorGetStatus(struct RegulatorNode *node, uint32_t *status)
245 {
246     if (node == NULL || status == NULL) {
247         HDF_LOGE("%s: node null", __func__);
248         return HDF_ERR_INVALID_OBJECT;
249     }
250     struct LinuxRegulatorInfo *info = (struct LinuxRegulatorInfo *)node->priv;
251     if (info->adapterReg == NULL) {
252         HDF_LOGE("%s adapterReg null, please open dev", __func__);
253         return HDF_ERR_INVALID_OBJECT;
254     }
255 
256     if (regulator_is_enabled(info->adapterReg) > 0) {
257         *status = REGULATOR_STATUS_ON;
258     } else {
259         *status = REGULATOR_STATUS_OFF;
260     }
261     return HDF_SUCCESS;
262 }
263 
264 static struct RegulatorMethod g_method = {
265     .open = LinuxRegulatorOpen,
266     .close = LinuxRegulatorClose,
267     .release = LinuxRegulatorRemove,
268     .enable = LinuxRegulatorEnable,
269     .disable = LinuxRegulatorDisable,
270     .forceDisable = LinuxRegulatorForceDisable,
271     .setVoltage = LinuxRegulatorSetVoltage,
272     .getVoltage = LinuxRegulatorGetVoltage,
273     .setCurrent = LinuxRegulatorSetCurrent,
274     .getCurrent = LinuxRegulatorGetCurrent,
275     .getStatus = LinuxRegulatorGetStatus,
276 };
277 
278 static struct device *g_consumer_dev;
LinuxRegulatorSetConsumerDev(struct device * dev)279 int32_t LinuxRegulatorSetConsumerDev(struct device *dev)
280 {
281     if (dev == NULL) {
282         HDF_LOGE("%s: node null", __func__);
283         return HDF_ERR_INVALID_OBJECT;
284     }
285 
286     g_consumer_dev = dev;
287     return HDF_SUCCESS;
288 }
289 
LinuxRegulatorBind(struct HdfDeviceObject * device)290 static int32_t LinuxRegulatorBind(struct HdfDeviceObject *device)
291 {
292     (void)device;
293     return HDF_SUCCESS;
294 }
295 
LinuxRegulatorReadHcs(struct RegulatorNode * regNode,const struct DeviceResourceNode * node)296 static int32_t LinuxRegulatorReadHcs(struct RegulatorNode *regNode, const struct DeviceResourceNode *node)
297 {
298     int32_t ret;
299     struct DeviceResourceIface *drsOps = NULL;
300 
301     drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
302     if (drsOps == NULL || drsOps->GetString == NULL) {
303         HDF_LOGE("%s: invalid drs ops fail!", __func__);
304         return HDF_FAILURE;
305     }
306 
307     ret = drsOps->GetString(node, "name", &(regNode->regulatorInfo.name), "ERROR");
308     if ((ret != HDF_SUCCESS) || (regNode->regulatorInfo.name == NULL)) {
309         HDF_LOGE("%s: read name fail!", __func__);
310         return HDF_FAILURE;
311     }
312     HDF_LOGD("%s:name[%s]", __func__, regNode->regulatorInfo.name);
313 
314     ret = drsOps->GetUint8(node, "mode", &regNode->regulatorInfo.constraints.mode, 0);
315     if (ret != HDF_SUCCESS) {
316         HDF_LOGE("%s: read mode fail!", __func__);
317         return HDF_FAILURE;
318     }
319 
320     ret = drsOps->GetUint32(node, "minUv", &regNode->regulatorInfo.constraints.minUv, 0);
321     if (ret != HDF_SUCCESS) {
322         HDF_LOGE("%s: read minUv fail!", __func__);
323         return HDF_FAILURE;
324     }
325 
326     ret = drsOps->GetUint32(node, "maxUv", &regNode->regulatorInfo.constraints.maxUv, 0);
327     if (ret != HDF_SUCCESS) {
328         HDF_LOGE("%s: read maxUv fail!", __func__);
329         return HDF_FAILURE;
330     }
331 
332     ret = drsOps->GetUint32(node, "minUa", &regNode->regulatorInfo.constraints.minUa, 0);
333     if (ret != HDF_SUCCESS) {
334         HDF_LOGE("%s: read minUa fail!", __func__);
335         return HDF_FAILURE;
336     }
337 
338     ret = drsOps->GetUint32(node, "maxUa", &regNode->regulatorInfo.constraints.maxUa, 0);
339     if (ret != HDF_SUCCESS) {
340         HDF_LOGE("%s: read maxUa fail!", __func__);
341         return HDF_FAILURE;
342     }
343 
344     regNode->regulatorInfo.parentName = NULL;
345     regNode->regulatorInfo.status = REGULATOR_STATUS_OFF;
346 
347     HDF_LOGI("%s: name[%s][%d]--[%d][%d]--[%d][%d]", __func__,
348         regNode->regulatorInfo.name, regNode->regulatorInfo.constraints.mode,
349         regNode->regulatorInfo.constraints.minUv, regNode->regulatorInfo.constraints.maxUv,
350         regNode->regulatorInfo.constraints.minUa, regNode->regulatorInfo.constraints.maxUa);
351 
352     return HDF_SUCCESS;
353 }
354 
LinuxRegulatorReadAdapterHcs(struct LinuxRegulatorInfo * info,const struct DeviceResourceNode * node)355 static int32_t LinuxRegulatorReadAdapterHcs(struct LinuxRegulatorInfo *info, const struct DeviceResourceNode *node)
356 {
357     int32_t ret;
358     struct DeviceResourceIface *drsOps = NULL;
359 
360     drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
361     if (info == NULL || drsOps == NULL || drsOps->GetString == NULL) {
362         HDF_LOGE("%s: invalid drs ops fail!", __func__);
363         return HDF_FAILURE;
364     }
365 
366     ret = drsOps->GetString(node, "devName", &(info->devName), "ERROR");
367     if ((ret != HDF_SUCCESS) || (info->devName == NULL)) {
368         HDF_LOGE("%s: read devName fail!", __func__);
369         return HDF_FAILURE;
370     }
371     HDF_LOGI("%s:devName[%s]", __func__, info->devName);
372 
373     ret = drsOps->GetString(node, "supplyName", &(info->supplyName), "ERROR");
374     if ((ret != HDF_SUCCESS) || (info->supplyName == NULL)) {
375         HDF_LOGE("%s: read supplyName fail!", __func__);
376         return HDF_FAILURE;
377     }
378     HDF_LOGI("%s:supplyName[%s]", __func__, info->supplyName);
379 
380     info->dev = g_consumer_dev;
381     return HDF_SUCCESS;
382 }
383 
LinuxRegulatorParseAndInit(struct HdfDeviceObject * device,const struct DeviceResourceNode * node)384 static int32_t LinuxRegulatorParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node)
385 {
386     int32_t ret;
387     struct RegulatorNode *regNode = NULL;
388     struct LinuxRegulatorInfo *info = NULL;
389     (void)device;
390 
391     regNode = (struct RegulatorNode *)OsalMemCalloc(sizeof(*regNode));
392     if (regNode == NULL) {
393         HDF_LOGE("%s: malloc regNode fail!", __func__);
394         return HDF_ERR_MALLOC_FAIL;
395     }
396 
397     info = (struct LinuxRegulatorInfo *)OsalMemCalloc(sizeof(*info));
398     if (info == NULL) {
399         HDF_LOGE("%s: malloc info fail!", __func__);
400         OsalMemFree(regNode);
401         regNode = NULL;
402         return HDF_ERR_MALLOC_FAIL;
403     }
404 
405     do {
406         ret = LinuxRegulatorReadHcs(regNode, node);
407         if (ret != HDF_SUCCESS) {
408             HDF_LOGE("%s: read drs fail! ret:%d", __func__, ret);
409             break;
410         }
411 
412         ret = LinuxRegulatorReadAdapterHcs(info, node);
413         if (ret != HDF_SUCCESS) {
414             HDF_LOGE("%s: LinuxRegulatorReadAdapterHcs fail! ret:%d", __func__, ret);
415             break;
416         }
417 
418         HDF_LOGI("%s: name[%s][%d]--[%d][%d]--[%d][%d]--[%s][%s]", __func__,
419             regNode->regulatorInfo.name, regNode->regulatorInfo.constraints.mode,
420             regNode->regulatorInfo.constraints.minUv, regNode->regulatorInfo.constraints.maxUv,
421             regNode->regulatorInfo.constraints.minUa, regNode->regulatorInfo.constraints.maxUa,
422             info->devName, info->supplyName);
423 
424         regNode->priv = (void *)info;
425         regNode->ops = &g_method;
426 
427         ret = RegulatorNodeAdd(regNode);
428         if (ret != HDF_SUCCESS) {
429             HDF_LOGE("%s: add regulator controller fail:%d!", __func__, ret);
430             break;
431         }
432     } while (0);
433 
434     if (ret != HDF_SUCCESS) {
435         HDF_LOGE("%s: fail [%d]!", __func__, ret);
436         OsalMemFree(regNode);
437         regNode = NULL;
438         OsalMemFree(info);
439         info = NULL;
440         return HDF_FAILURE;
441     }
442     return HDF_SUCCESS;
443 }
444 
445 /* get all linux regulator, then add to hdf */
LinuxRegulatorInit(struct HdfDeviceObject * device)446 static int32_t LinuxRegulatorInit(struct HdfDeviceObject *device)
447 {
448     int32_t ret;
449     const struct DeviceResourceNode *childNode = NULL;
450     RegulatorAdapterConsumerInit();
451 
452     if (device == NULL || device->property == NULL) {
453         HDF_LOGE("%s: device is NULL", __func__);
454         return HDF_ERR_INVALID_OBJECT;
455     }
456 
457     DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
458         ret = LinuxRegulatorParseAndInit(device, childNode);
459         if (ret != HDF_SUCCESS) {
460             HDF_LOGE("%s:LinuxRegulatorParseAndInit fail", __func__);
461             return HDF_FAILURE;
462         }
463     }
464     return ret;
465 }
LinuxRegulatorParseAndRelease(struct HdfDeviceObject * device,const struct DeviceResourceNode * node)466 static int32_t LinuxRegulatorParseAndRelease(struct HdfDeviceObject *device, const struct DeviceResourceNode *node)
467 {
468     int32_t ret;
469     struct LinuxRegulatorInfo *info = NULL;
470     struct DeviceResourceIface *drsOps = NULL;
471     (void)device;
472 
473     HDF_LOGI("LinuxRegulatorParseAndRelease");
474 
475     drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
476     if (drsOps == NULL || drsOps->GetString == NULL) {
477         HDF_LOGE("%s: invalid drs ops fail!", __func__);
478         return HDF_FAILURE;
479     }
480 
481     const char *name;
482     ret = drsOps->GetString(node, "name", &(name), "ERROR");
483     if ((ret != HDF_SUCCESS) || (name == NULL)) {
484         HDF_LOGE("%s: read name fail!", __func__);
485         return HDF_FAILURE;
486     }
487 
488     HDF_LOGI("LinuxRegulatorParseAndRelease: name[%s]", name);
489 
490     ret = RegulatorNodeRemove(name);
491     if (ret != HDF_SUCCESS) {
492         HDF_LOGE("%s: LinuxRegulatorRelease fail:%d!", __func__, ret);
493         return HDF_FAILURE;
494     }
495     HDF_LOGI("LinuxRegulatorParseAndRelease: name[%s] success", name);
496     return HDF_SUCCESS;
497 }
498 
LinuxRegulatorRelease(struct HdfDeviceObject * device)499 static void LinuxRegulatorRelease(struct HdfDeviceObject *device)
500 {
501     HDF_LOGI("%s: enter", __func__);
502     if (device == NULL || device->property == NULL) {
503         HDF_LOGE("%s: device is NULL", __func__);
504         return;
505     }
506     const struct DeviceResourceNode *childNode = NULL;
507 
508     DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
509         int ret = LinuxRegulatorParseAndRelease(device, childNode);
510         if (ret != HDF_SUCCESS) {
511             HDF_LOGE("%s:LinuxRegulatorParseAndInit fail", __func__);
512         }
513     }
514 }
515 
516 struct HdfDriverEntry g_regulatorLinuxDriverEntry = {
517     .moduleVersion = 1,
518     .Bind = LinuxRegulatorBind,
519     .Init = LinuxRegulatorInit,
520     .Release = LinuxRegulatorRelease,
521     .moduleName = "linux_regulator_adapter",
522 };
523 HDF_INIT(g_regulatorLinuxDriverEntry);
524