1 /*
2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include <linux/err.h>
10 #include <linux/kernel.h>
11 #include <linux/device.h>
12 #include <linux/delay.h>
13 #include <linux/platform_device.h>
14 #include <linux/regulator/driver.h>
15 #include <linux/regulator/machine.h>
16 #include <linux/regmap.h>
17 #include <linux/sysfs.h>
18 #include "hdf_log.h"
19 #include "hdf_base.h"
20
21 #define HDF_LOG_TAG regulator_virtual_current
22
23 #define MINIMUN_CURRENT 1000
24 #define MAXIMUN_CURRENT 50000
25
26 struct VirtualCurrentRegulatorDev {
27 struct regmap *regmap;
28 struct regulator_dev *dev;
29 };
30
31 // note:linux kernel constraints:len(devName) + len(supplyName) < REG_STR_SIZE(64)
32 static struct regulator_consumer_supply g_virtualCurrentRegulatorSupplies[] = {
33 REGULATOR_SUPPLY("vir-current-reg-hdf-adp", "regulator_adapter_consumer01"),
34 };
35
36 // virtual regulator init info
37 static struct regulator_init_data g_virtualCurrentRegulatorInitData = {
38 .constraints = {
39 .name = "virtual_current_regulator",
40 .min_uA = MINIMUN_CURRENT,
41 .max_uA = MAXIMUN_CURRENT,
42 .valid_ops_mask = REGULATOR_CHANGE_CURRENT | REGULATOR_CHANGE_STATUS,
43 },
44 .num_consumer_supplies = ARRAY_SIZE(g_virtualCurrentRegulatorSupplies),
45 .consumer_supplies = g_virtualCurrentRegulatorSupplies,
46 };
47
VirtualCurrentRegulatorDevRelease(struct device * dev)48 static void VirtualCurrentRegulatorDevRelease(struct device *dev)
49 {
50 (void)dev;
51 }
52
53 static struct platform_device g_virtualCurrentRegulatorPlatformDevice = {
54 .name = "virtual_current_regulator_dev",
55 .id = -1,
56 .dev = {
57 .release = VirtualCurrentRegulatorDevRelease,
58 }
59 };
60
61 enum RegulatorStatus {
62 VIR_REGULATOR_STATUS_OFF,
63 VIR_REGULATOR_STATUS_ON,
64 };
65
66 static int g_virStatus = VIR_REGULATOR_STATUS_OFF;
VirtualCurrentRegulatorEnable(struct regulator_dev * rdev)67 static int VirtualCurrentRegulatorEnable(struct regulator_dev *rdev)
68 {
69 if (rdev == NULL) {
70 HDF_LOGE("VirtualCurrentRegulatorEnable: rdev is null!");
71 return HDF_FAILURE;
72 }
73
74 g_virStatus = VIR_REGULATOR_STATUS_ON;
75 return HDF_SUCCESS;
76 }
77
VirtualCurrentRegulatorDisable(struct regulator_dev * rdev)78 static int VirtualCurrentRegulatorDisable(struct regulator_dev *rdev)
79 {
80 if (rdev == NULL) {
81 HDF_LOGE("VirtualCurrentRegulatorDisable: rdev is null!");
82 return HDF_FAILURE;
83 }
84
85 g_virStatus = VIR_REGULATOR_STATUS_OFF;
86 return HDF_SUCCESS;
87 }
88
VirtualCurrentRegulatorIsEnabled(struct regulator_dev * rdev)89 static int VirtualCurrentRegulatorIsEnabled(struct regulator_dev *rdev)
90 {
91 if (rdev == NULL) {
92 HDF_LOGE("VirtualCurrentRegulatorIsEnabled: rdev is null!");
93 return HDF_FAILURE;
94 }
95
96 return g_virStatus;
97 }
98
VirtualCurrentRegulatorSetCurrent(struct regulator_dev * rdev,int minUa,int maxUa)99 static int VirtualCurrentRegulatorSetCurrent(struct regulator_dev *rdev, int minUa,
100 int maxUa)
101 {
102 if ((rdev == NULL) || (rdev->constraints == NULL)) {
103 HDF_LOGE("VirtualCurrentRegulatorSetCurrent: rdev or constraints is null!");
104 return HDF_FAILURE;
105 }
106
107 struct regulation_constraints *regu_constraints = rdev->constraints;
108 if (regu_constraints->min_uA == minUa &&
109 regu_constraints->max_uA == maxUa) {
110 return HDF_SUCCESS;
111 }
112
113 return HDF_SUCCESS;
114 }
115
116 #define VIRTUAL_CURRENT_VAL_500 500
VirtualCurrentRegulatorGetCurrent(struct regulator_dev * rdev)117 static int VirtualCurrentRegulatorGetCurrent(struct regulator_dev *rdev)
118 {
119 if (rdev == NULL) {
120 HDF_LOGE("VirtualCurrentRegulatorGetCurrent: rdev is null!");
121 return HDF_FAILURE;
122 }
123
124 return VIRTUAL_CURRENT_VAL_500;
125 }
126
127 static struct regulator_ops g_virtualCurrentRegulatorOps = {
128 .enable = VirtualCurrentRegulatorEnable,
129 .disable = VirtualCurrentRegulatorDisable,
130 .is_enabled = VirtualCurrentRegulatorIsEnabled,
131 .set_current_limit = VirtualCurrentRegulatorSetCurrent,
132 .get_current_limit = VirtualCurrentRegulatorGetCurrent,
133 };
134
135 static struct regulator_desc g_virtualCurrentRegulatorDesc = {
136 .name = "regulator_virtual_current",
137 .type = REGULATOR_CURRENT,
138 .ops = &g_virtualCurrentRegulatorOps,
139 .owner = THIS_MODULE,
140 };
141
VirtualCurrentRegulatorPlatformProbe(struct platform_device * platformDev)142 static int VirtualCurrentRegulatorPlatformProbe(struct platform_device *platformDev)
143 {
144 if (platformDev == NULL) {
145 HDF_LOGE("VirtualCurrentRegulatorPlatformProbe: platformDev is null!");
146 return HDF_FAILURE;
147 }
148 struct VirtualCurrentRegulatorDev *data;
149 struct regulator_config config = {0};
150
151 data = devm_kzalloc(&platformDev->dev, sizeof(*data), GFP_KERNEL);
152 if (!data) {
153 HDF_LOGE("VirtualCurrentRegulatorPlatformProbe: devm_kzalloc error!");
154 return -ENOMEM;
155 }
156 config.dev = &platformDev->dev;
157 config.init_data = &g_virtualCurrentRegulatorInitData;
158 config.driver_data = data;
159
160 data->dev = regulator_register(&g_virtualCurrentRegulatorDesc, &config);
161 if (IS_ERR(data->dev)) {
162 HDF_LOGE("VirtualCurrentRegulatorPlatformProbe: fail to register regulator %s\n",
163 g_virtualCurrentRegulatorDesc.name);
164 return PTR_ERR(data->dev);
165 }
166
167 platform_set_drvdata(platformDev, data);
168 HDF_LOGI("VirtualCurrentRegulatorPlatformProbe: success!");
169 return 0;
170 }
171
VirtualCurrentRegulatorPlatformRemove(struct platform_device * platformDev)172 static int VirtualCurrentRegulatorPlatformRemove(struct platform_device *platformDev)
173 {
174 struct VirtualCurrentRegulatorDev *rdev = platform_get_drvdata(platformDev);
175
176 regulator_unregister(rdev->dev);
177
178 platform_set_drvdata(platformDev, NULL);
179 HDF_LOGI("VirtualCurrentRegulatorPlatformRemove: success!");
180 return 0;
181 }
182
183 static struct platform_driver g_virtualCurrentRegulatorPlatformDriver = {
184 .driver = {
185 .name = "virtual_current_regulator_dev",
186 .owner = THIS_MODULE,
187 },
188 .probe = VirtualCurrentRegulatorPlatformProbe,
189 .remove = VirtualCurrentRegulatorPlatformRemove,
190 };
191
VirtualCurrentRegulatorAdapterInit(void)192 int VirtualCurrentRegulatorAdapterInit(void)
193 {
194 int ret = platform_device_register(&g_virtualCurrentRegulatorPlatformDevice);
195 if (ret == 0) {
196 ret = platform_driver_register(&g_virtualCurrentRegulatorPlatformDriver);
197 } else {
198 HDF_LOGE("VirtualCurrentRegulatorAdapterInit:device register fail, ret: %d!", ret);
199 }
200 return ret;
201 }
202
VirtualCurrentRegulatorInit(void)203 static int __init VirtualCurrentRegulatorInit(void)
204 {
205 int ret = platform_device_register(&g_virtualCurrentRegulatorPlatformDevice);
206 if (ret == 0) {
207 ret = platform_driver_register(&g_virtualCurrentRegulatorPlatformDriver);
208 }
209 return ret;
210 }
211
VirtualCurrentRegulatorExit(void)212 static void __exit VirtualCurrentRegulatorExit(void)
213 {
214 platform_device_unregister(&g_virtualCurrentRegulatorPlatformDevice);
215 platform_driver_unregister(&g_virtualCurrentRegulatorPlatformDriver);
216 }
217
218 MODULE_DESCRIPTION("Virtual current Regulator Controller Platform Device Drivers");
219 MODULE_LICENSE("GPL");
220