Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
virtual.c
Go to the documentation of this file.
1 /*
2  * reg-virtual-consumer.c
3  *
4  * Copyright 2008 Wolfson Microelectronics PLC.
5  *
6  * Author: Mark Brown <[email protected]>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of the
11  * License, or (at your option) any later version.
12  */
13 
14 #include <linux/err.h>
15 #include <linux/mutex.h>
16 #include <linux/platform_device.h>
18 #include <linux/slab.h>
19 #include <linux/module.h>
20 
22  struct mutex lock;
24  bool enabled;
25  int min_uV;
26  int max_uV;
27  int min_uA;
28  int max_uA;
29  unsigned int mode;
30 };
31 
32 static void update_voltage_constraints(struct device *dev,
34 {
35  int ret;
36 
37  if (data->min_uV && data->max_uV
38  && data->min_uV <= data->max_uV) {
39  dev_dbg(dev, "Requesting %d-%duV\n",
40  data->min_uV, data->max_uV);
41  ret = regulator_set_voltage(data->regulator,
42  data->min_uV, data->max_uV);
43  if (ret != 0) {
44  dev_err(dev,
45  "regulator_set_voltage() failed: %d\n", ret);
46  return;
47  }
48  }
49 
50  if (data->min_uV && data->max_uV && !data->enabled) {
51  dev_dbg(dev, "Enabling regulator\n");
52  ret = regulator_enable(data->regulator);
53  if (ret == 0)
54  data->enabled = true;
55  else
56  dev_err(dev, "regulator_enable() failed: %d\n",
57  ret);
58  }
59 
60  if (!(data->min_uV && data->max_uV) && data->enabled) {
61  dev_dbg(dev, "Disabling regulator\n");
62  ret = regulator_disable(data->regulator);
63  if (ret == 0)
64  data->enabled = false;
65  else
66  dev_err(dev, "regulator_disable() failed: %d\n",
67  ret);
68  }
69 }
70 
71 static void update_current_limit_constraints(struct device *dev,
72  struct virtual_consumer_data *data)
73 {
74  int ret;
75 
76  if (data->max_uA
77  && data->min_uA <= data->max_uA) {
78  dev_dbg(dev, "Requesting %d-%duA\n",
79  data->min_uA, data->max_uA);
81  data->min_uA, data->max_uA);
82  if (ret != 0) {
83  dev_err(dev,
84  "regulator_set_current_limit() failed: %d\n",
85  ret);
86  return;
87  }
88  }
89 
90  if (data->max_uA && !data->enabled) {
91  dev_dbg(dev, "Enabling regulator\n");
92  ret = regulator_enable(data->regulator);
93  if (ret == 0)
94  data->enabled = true;
95  else
96  dev_err(dev, "regulator_enable() failed: %d\n",
97  ret);
98  }
99 
100  if (!(data->min_uA && data->max_uA) && data->enabled) {
101  dev_dbg(dev, "Disabling regulator\n");
102  ret = regulator_disable(data->regulator);
103  if (ret == 0)
104  data->enabled = false;
105  else
106  dev_err(dev, "regulator_disable() failed: %d\n",
107  ret);
108  }
109 }
110 
111 static ssize_t show_min_uV(struct device *dev,
112  struct device_attribute *attr, char *buf)
113 {
114  struct virtual_consumer_data *data = dev_get_drvdata(dev);
115  return sprintf(buf, "%d\n", data->min_uV);
116 }
117 
118 static ssize_t set_min_uV(struct device *dev, struct device_attribute *attr,
119  const char *buf, size_t count)
120 {
121  struct virtual_consumer_data *data = dev_get_drvdata(dev);
122  long val;
123 
124  if (kstrtol(buf, 10, &val) != 0)
125  return count;
126 
127  mutex_lock(&data->lock);
128 
129  data->min_uV = val;
130  update_voltage_constraints(dev, data);
131 
132  mutex_unlock(&data->lock);
133 
134  return count;
135 }
136 
137 static ssize_t show_max_uV(struct device *dev,
138  struct device_attribute *attr, char *buf)
139 {
140  struct virtual_consumer_data *data = dev_get_drvdata(dev);
141  return sprintf(buf, "%d\n", data->max_uV);
142 }
143 
144 static ssize_t set_max_uV(struct device *dev, struct device_attribute *attr,
145  const char *buf, size_t count)
146 {
147  struct virtual_consumer_data *data = dev_get_drvdata(dev);
148  long val;
149 
150  if (kstrtol(buf, 10, &val) != 0)
151  return count;
152 
153  mutex_lock(&data->lock);
154 
155  data->max_uV = val;
156  update_voltage_constraints(dev, data);
157 
158  mutex_unlock(&data->lock);
159 
160  return count;
161 }
162 
163 static ssize_t show_min_uA(struct device *dev,
164  struct device_attribute *attr, char *buf)
165 {
166  struct virtual_consumer_data *data = dev_get_drvdata(dev);
167  return sprintf(buf, "%d\n", data->min_uA);
168 }
169 
170 static ssize_t set_min_uA(struct device *dev, struct device_attribute *attr,
171  const char *buf, size_t count)
172 {
173  struct virtual_consumer_data *data = dev_get_drvdata(dev);
174  long val;
175 
176  if (kstrtol(buf, 10, &val) != 0)
177  return count;
178 
179  mutex_lock(&data->lock);
180 
181  data->min_uA = val;
182  update_current_limit_constraints(dev, data);
183 
184  mutex_unlock(&data->lock);
185 
186  return count;
187 }
188 
189 static ssize_t show_max_uA(struct device *dev,
190  struct device_attribute *attr, char *buf)
191 {
192  struct virtual_consumer_data *data = dev_get_drvdata(dev);
193  return sprintf(buf, "%d\n", data->max_uA);
194 }
195 
196 static ssize_t set_max_uA(struct device *dev, struct device_attribute *attr,
197  const char *buf, size_t count)
198 {
199  struct virtual_consumer_data *data = dev_get_drvdata(dev);
200  long val;
201 
202  if (kstrtol(buf, 10, &val) != 0)
203  return count;
204 
205  mutex_lock(&data->lock);
206 
207  data->max_uA = val;
208  update_current_limit_constraints(dev, data);
209 
210  mutex_unlock(&data->lock);
211 
212  return count;
213 }
214 
215 static ssize_t show_mode(struct device *dev,
216  struct device_attribute *attr, char *buf)
217 {
218  struct virtual_consumer_data *data = dev_get_drvdata(dev);
219 
220  switch (data->mode) {
221  case REGULATOR_MODE_FAST:
222  return sprintf(buf, "fast\n");
224  return sprintf(buf, "normal\n");
225  case REGULATOR_MODE_IDLE:
226  return sprintf(buf, "idle\n");
228  return sprintf(buf, "standby\n");
229  default:
230  return sprintf(buf, "unknown\n");
231  }
232 }
233 
234 static ssize_t set_mode(struct device *dev, struct device_attribute *attr,
235  const char *buf, size_t count)
236 {
237  struct virtual_consumer_data *data = dev_get_drvdata(dev);
238  unsigned int mode;
239  int ret;
240 
241  /*
242  * sysfs_streq() doesn't need the \n's, but we add them so the strings
243  * will be shared with show_mode(), above.
244  */
245  if (sysfs_streq(buf, "fast\n"))
246  mode = REGULATOR_MODE_FAST;
247  else if (sysfs_streq(buf, "normal\n"))
248  mode = REGULATOR_MODE_NORMAL;
249  else if (sysfs_streq(buf, "idle\n"))
250  mode = REGULATOR_MODE_IDLE;
251  else if (sysfs_streq(buf, "standby\n"))
252  mode = REGULATOR_MODE_STANDBY;
253  else {
254  dev_err(dev, "Configuring invalid mode\n");
255  return count;
256  }
257 
258  mutex_lock(&data->lock);
259  ret = regulator_set_mode(data->regulator, mode);
260  if (ret == 0)
261  data->mode = mode;
262  else
263  dev_err(dev, "Failed to configure mode: %d\n", ret);
264  mutex_unlock(&data->lock);
265 
266  return count;
267 }
268 
269 static DEVICE_ATTR(min_microvolts, 0666, show_min_uV, set_min_uV);
270 static DEVICE_ATTR(max_microvolts, 0666, show_max_uV, set_max_uV);
271 static DEVICE_ATTR(min_microamps, 0666, show_min_uA, set_min_uA);
272 static DEVICE_ATTR(max_microamps, 0666, show_max_uA, set_max_uA);
273 static DEVICE_ATTR(mode, 0666, show_mode, set_mode);
274 
275 static struct attribute *regulator_virtual_attributes[] = {
276  &dev_attr_min_microvolts.attr,
277  &dev_attr_max_microvolts.attr,
278  &dev_attr_min_microamps.attr,
279  &dev_attr_max_microamps.attr,
280  &dev_attr_mode.attr,
281  NULL
282 };
283 
284 static const struct attribute_group regulator_virtual_attr_group = {
285  .attrs = regulator_virtual_attributes,
286 };
287 
288 static int __devinit regulator_virtual_probe(struct platform_device *pdev)
289 {
290  char *reg_id = pdev->dev.platform_data;
292  int ret;
293 
294  drvdata = devm_kzalloc(&pdev->dev, sizeof(struct virtual_consumer_data),
295  GFP_KERNEL);
296  if (drvdata == NULL)
297  return -ENOMEM;
298 
299  mutex_init(&drvdata->lock);
300 
301  drvdata->regulator = devm_regulator_get(&pdev->dev, reg_id);
302  if (IS_ERR(drvdata->regulator)) {
303  ret = PTR_ERR(drvdata->regulator);
304  dev_err(&pdev->dev, "Failed to obtain supply '%s': %d\n",
305  reg_id, ret);
306  return ret;
307  }
308 
309  ret = sysfs_create_group(&pdev->dev.kobj,
310  &regulator_virtual_attr_group);
311  if (ret != 0) {
312  dev_err(&pdev->dev,
313  "Failed to create attribute group: %d\n", ret);
314  return ret;
315  }
316 
317  drvdata->mode = regulator_get_mode(drvdata->regulator);
318 
319  platform_set_drvdata(pdev, drvdata);
320 
321  return 0;
322 }
323 
324 static int __devexit regulator_virtual_remove(struct platform_device *pdev)
325 {
326  struct virtual_consumer_data *drvdata = platform_get_drvdata(pdev);
327 
328  sysfs_remove_group(&pdev->dev.kobj, &regulator_virtual_attr_group);
329 
330  if (drvdata->enabled)
331  regulator_disable(drvdata->regulator);
332 
333  platform_set_drvdata(pdev, NULL);
334 
335  return 0;
336 }
337 
338 static struct platform_driver regulator_virtual_consumer_driver = {
339  .probe = regulator_virtual_probe,
340  .remove = __devexit_p(regulator_virtual_remove),
341  .driver = {
342  .name = "reg-virt-consumer",
343  .owner = THIS_MODULE,
344  },
345 };
346 
347 module_platform_driver(regulator_virtual_consumer_driver);
348 
349 MODULE_AUTHOR("Mark Brown <[email protected]>");
350 MODULE_DESCRIPTION("Virtual regulator consumer");
351 MODULE_LICENSE("GPL");
352 MODULE_ALIAS("platform:reg-virt-consumer");