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", ®Node->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", ®Node->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", ®Node->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", ®Node->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", ®Node->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