blob: 3d7465dc278e543a0ac67a4418038a64284ea747 [file] [log] [blame]
David Collins74f0dd02016-07-08 18:05:35 -07001/*
2 * Copyright (c) 2012, 2016, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#define pr_fmt(fmt) "%s: " fmt, __func__
15
16#include <linux/module.h>
17#include <linux/err.h>
18#include <linux/kernel.h>
19#include <linux/of.h>
20#include <linux/of_device.h>
21#include <linux/platform_device.h>
22#include <linux/slab.h>
23#include <linux/types.h>
24#include <linux/regulator/driver.h>
25#include <linux/regulator/of_regulator.h>
26#include <linux/regulator/stub-regulator.h>
27
28#define STUB_REGULATOR_MAX_NAME 40
29
30struct regulator_stub {
31 struct regulator_desc rdesc;
32 struct regulator_dev *rdev;
33 int voltage;
34 bool enabled;
35 int mode;
36 int hpm_min_load;
37 int system_uA;
38 char name[STUB_REGULATOR_MAX_NAME];
39};
40
41static int regulator_stub_set_voltage(struct regulator_dev *rdev, int min_uV,
42 int max_uV, unsigned *selector)
43{
44 struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
45
46 vreg_priv->voltage = min_uV;
47 return 0;
48}
49
50static int regulator_stub_get_voltage(struct regulator_dev *rdev)
51{
52 struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
53
54 return vreg_priv->voltage;
55}
56
57static int regulator_stub_list_voltage(struct regulator_dev *rdev,
58 unsigned selector)
59{
60 struct regulation_constraints *constraints = rdev->constraints;
61
62 if (selector >= 2)
63 return -EINVAL;
64 else if (selector == 0)
65 return constraints->min_uV;
66 else
67 return constraints->max_uV;
68}
69
70static unsigned int regulator_stub_get_mode(struct regulator_dev *rdev)
71{
72 struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
73
74 return vreg_priv->mode;
75}
76
77static int regulator_stub_set_mode(struct regulator_dev *rdev,
78 unsigned int mode)
79{
80 struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
81
82 if (mode != REGULATOR_MODE_NORMAL && mode != REGULATOR_MODE_IDLE) {
83 dev_err(&rdev->dev, "%s: invalid mode requested %u\n",
84 __func__, mode);
85 return -EINVAL;
86 }
87 vreg_priv->mode = mode;
88 return 0;
89}
90
91static unsigned int regulator_stub_get_optimum_mode(struct regulator_dev *rdev,
92 int input_uV, int output_uV, int load_uA)
93{
94 struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
95 unsigned int mode;
96
97 if (load_uA + vreg_priv->system_uA >= vreg_priv->hpm_min_load)
98 mode = REGULATOR_MODE_NORMAL;
99 else
100 mode = REGULATOR_MODE_IDLE;
101
102 return mode;
103}
104
105static int regulator_stub_enable(struct regulator_dev *rdev)
106{
107 struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
108
109 vreg_priv->enabled = true;
110 return 0;
111}
112
113static int regulator_stub_disable(struct regulator_dev *rdev)
114{
115 struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
116
117 vreg_priv->enabled = false;
118 return 0;
119}
120
121static int regulator_stub_is_enabled(struct regulator_dev *rdev)
122{
123 struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
124
125 return vreg_priv->enabled;
126}
127
128/* Real regulator operations. */
129static struct regulator_ops regulator_stub_ops = {
130 .enable = regulator_stub_enable,
131 .disable = regulator_stub_disable,
132 .is_enabled = regulator_stub_is_enabled,
133 .set_voltage = regulator_stub_set_voltage,
134 .get_voltage = regulator_stub_get_voltage,
135 .list_voltage = regulator_stub_list_voltage,
136 .set_mode = regulator_stub_set_mode,
137 .get_mode = regulator_stub_get_mode,
138 .get_optimum_mode = regulator_stub_get_optimum_mode,
139};
140
141static void regulator_stub_cleanup(struct regulator_stub *vreg_priv)
142{
143 if (vreg_priv && vreg_priv->rdev)
144 regulator_unregister(vreg_priv->rdev);
145 kfree(vreg_priv);
146}
147
148static int regulator_stub_probe(struct platform_device *pdev)
149{
150 struct regulator_config reg_config = {};
151 struct regulator_init_data *init_data = NULL;
152 struct device *dev = &pdev->dev;
153 struct stub_regulator_pdata *vreg_pdata;
154 struct regulator_desc *rdesc;
155 struct regulator_stub *vreg_priv;
156 int rc;
157
158 vreg_priv = kzalloc(sizeof(*vreg_priv), GFP_KERNEL);
159 if (!vreg_priv)
160 return -ENOMEM;
161
162 if (dev->of_node) {
163 /* Use device tree. */
164 init_data = of_get_regulator_init_data(dev, dev->of_node,
165 &vreg_priv->rdesc);
166 if (!init_data) {
167 dev_err(dev, "%s: unable to allocate memory\n",
168 __func__);
169 rc = -ENOMEM;
170 goto err_probe;
171 }
172
173 if (init_data->constraints.name == NULL) {
174 dev_err(dev, "%s: regulator name not specified\n",
175 __func__);
176 rc = -EINVAL;
177 goto err_probe;
178 }
179
180 if (of_get_property(dev->of_node, "parent-supply", NULL))
181 init_data->supply_regulator = "parent";
182
183 of_property_read_u32(dev->of_node, "qcom,system-load",
184 &vreg_priv->system_uA);
185 of_property_read_u32(dev->of_node, "qcom,hpm-min-load",
186 &vreg_priv->hpm_min_load);
187
188 init_data->constraints.input_uV = init_data->constraints.max_uV;
189
190 init_data->constraints.valid_ops_mask
191 |= REGULATOR_CHANGE_STATUS;
192 init_data->constraints.valid_ops_mask
193 |= REGULATOR_CHANGE_VOLTAGE;
194 init_data->constraints.valid_ops_mask
195 |= REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_DRMS;
196 init_data->constraints.valid_modes_mask
197 = REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE;
198 } else {
199 /* Use platform data. */
200 vreg_pdata = dev->platform_data;
201 if (!vreg_pdata) {
202 dev_err(dev, "%s: no platform data\n", __func__);
203 rc = -EINVAL;
204 goto err_probe;
205 }
206 init_data = &vreg_pdata->init_data;
207
208 vreg_priv->system_uA = vreg_pdata->system_uA;
209 vreg_priv->hpm_min_load = vreg_pdata->hpm_min_load;
210 }
211
212 dev_set_drvdata(dev, vreg_priv);
213
214 rdesc = &vreg_priv->rdesc;
215 strlcpy(vreg_priv->name, init_data->constraints.name,
216 STUB_REGULATOR_MAX_NAME);
217 rdesc->name = vreg_priv->name;
218 rdesc->ops = &regulator_stub_ops;
219
220 /*
221 * Ensure that voltage set points are handled correctly for regulators
222 * which have a specified voltage constraint range, as well as those
223 * that do not.
224 */
225 if (init_data->constraints.min_uV == 0 &&
226 init_data->constraints.max_uV == 0)
227 rdesc->n_voltages = 0;
228 else
229 rdesc->n_voltages = 2;
230
231 rdesc->id = pdev->id;
232 rdesc->owner = THIS_MODULE;
233 rdesc->type = REGULATOR_VOLTAGE;
234 vreg_priv->voltage = init_data->constraints.min_uV;
235 if (vreg_priv->system_uA >= vreg_priv->hpm_min_load)
236 vreg_priv->mode = REGULATOR_MODE_NORMAL;
237 else
238 vreg_priv->mode = REGULATOR_MODE_IDLE;
239
240 reg_config.dev = dev;
241 reg_config.init_data = init_data;
242 reg_config.driver_data = vreg_priv;
243 reg_config.of_node = dev->of_node;
244 vreg_priv->rdev = regulator_register(rdesc, &reg_config);
245
246 if (IS_ERR(vreg_priv->rdev)) {
247 rc = PTR_ERR(vreg_priv->rdev);
248 vreg_priv->rdev = NULL;
249 if (rc != -EPROBE_DEFER)
250 dev_err(dev, "%s: regulator_register failed\n",
251 __func__);
252 goto err_probe;
253 }
254
255 return 0;
256
257err_probe:
258 regulator_stub_cleanup(vreg_priv);
259 return rc;
260}
261
262static int regulator_stub_remove(struct platform_device *pdev)
263{
264 struct regulator_stub *vreg_priv = dev_get_drvdata(&pdev->dev);
265
266 regulator_stub_cleanup(vreg_priv);
267 return 0;
268}
269
270static const struct of_device_id regulator_stub_match_table[] = {
271 { .compatible = "qcom," STUB_REGULATOR_DRIVER_NAME, },
272 {}
273};
274
275static struct platform_driver regulator_stub_driver = {
276 .probe = regulator_stub_probe,
277 .remove = regulator_stub_remove,
278 .driver = {
279 .name = STUB_REGULATOR_DRIVER_NAME,
280 .owner = THIS_MODULE,
281 .of_match_table = regulator_stub_match_table,
282 },
283};
284
285int __init regulator_stub_init(void)
286{
287 static int registered;
288
289 if (registered)
290 return 0;
291
292 registered = 1;
293
294 return platform_driver_register(&regulator_stub_driver);
295}
296EXPORT_SYMBOL(regulator_stub_init);
297postcore_initcall(regulator_stub_init);
298
299static void __exit regulator_stub_exit(void)
300{
301 platform_driver_unregister(&regulator_stub_driver);
302}
303module_exit(regulator_stub_exit);
304
305MODULE_LICENSE("GPL v2");
306MODULE_DESCRIPTION("stub regulator driver");
307MODULE_ALIAS("platform: " STUB_REGULATOR_DRIVER_NAME);