pwm: Get rid of pwm->lock
[cascardo/linux.git] / drivers / pwm / sysfs.c
1 /*
2  * A simple sysfs interface for the generic PWM framework
3  *
4  * Copyright (C) 2013 H Hartley Sweeten <hsweeten@visionengravers.com>
5  *
6  * Based on previous work by Lars Poeschel <poeschel@lemonage.de>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2, or (at your option)
11  * any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  */
18
19 #include <linux/device.h>
20 #include <linux/mutex.h>
21 #include <linux/err.h>
22 #include <linux/slab.h>
23 #include <linux/kdev_t.h>
24 #include <linux/pwm.h>
25
26 struct pwm_export {
27         struct device child;
28         struct pwm_device *pwm;
29         struct mutex lock;
30 };
31
32 static struct pwm_export *child_to_pwm_export(struct device *child)
33 {
34         return container_of(child, struct pwm_export, child);
35 }
36
37 static struct pwm_device *child_to_pwm_device(struct device *child)
38 {
39         struct pwm_export *export = child_to_pwm_export(child);
40
41         return export->pwm;
42 }
43
44 static ssize_t period_show(struct device *child,
45                            struct device_attribute *attr,
46                            char *buf)
47 {
48         const struct pwm_device *pwm = child_to_pwm_device(child);
49
50         return sprintf(buf, "%u\n", pwm_get_period(pwm));
51 }
52
53 static ssize_t period_store(struct device *child,
54                             struct device_attribute *attr,
55                             const char *buf, size_t size)
56 {
57         struct pwm_export *export = child_to_pwm_export(child);
58         struct pwm_device *pwm = export->pwm;
59         unsigned int val;
60         int ret;
61
62         ret = kstrtouint(buf, 0, &val);
63         if (ret)
64                 return ret;
65
66         mutex_lock(&export->lock);
67         ret = pwm_config(pwm, pwm_get_duty_cycle(pwm), val);
68         mutex_unlock(&export->lock);
69
70         return ret ? : size;
71 }
72
73 static ssize_t duty_cycle_show(struct device *child,
74                                struct device_attribute *attr,
75                                char *buf)
76 {
77         const struct pwm_device *pwm = child_to_pwm_device(child);
78
79         return sprintf(buf, "%u\n", pwm_get_duty_cycle(pwm));
80 }
81
82 static ssize_t duty_cycle_store(struct device *child,
83                                 struct device_attribute *attr,
84                                 const char *buf, size_t size)
85 {
86         struct pwm_export *export = child_to_pwm_export(child);
87         struct pwm_device *pwm = export->pwm;
88         unsigned int val;
89         int ret;
90
91         ret = kstrtouint(buf, 0, &val);
92         if (ret)
93                 return ret;
94
95         mutex_lock(&export->lock);
96         ret = pwm_config(pwm, val, pwm_get_period(pwm));
97         mutex_unlock(&export->lock);
98
99         return ret ? : size;
100 }
101
102 static ssize_t enable_show(struct device *child,
103                            struct device_attribute *attr,
104                            char *buf)
105 {
106         const struct pwm_device *pwm = child_to_pwm_device(child);
107
108         return sprintf(buf, "%d\n", pwm_is_enabled(pwm));
109 }
110
111 static ssize_t enable_store(struct device *child,
112                             struct device_attribute *attr,
113                             const char *buf, size_t size)
114 {
115         struct pwm_export *export = child_to_pwm_export(child);
116         struct pwm_device *pwm = export->pwm;
117         int val, ret;
118
119         ret = kstrtoint(buf, 0, &val);
120         if (ret)
121                 return ret;
122
123         mutex_lock(&export->lock);
124
125         switch (val) {
126         case 0:
127                 pwm_disable(pwm);
128                 break;
129         case 1:
130                 ret = pwm_enable(pwm);
131                 break;
132         default:
133                 ret = -EINVAL;
134                 break;
135         }
136
137         mutex_unlock(&export->lock);
138
139         return ret ? : size;
140 }
141
142 static ssize_t polarity_show(struct device *child,
143                              struct device_attribute *attr,
144                              char *buf)
145 {
146         const struct pwm_device *pwm = child_to_pwm_device(child);
147         const char *polarity = "unknown";
148
149         switch (pwm_get_polarity(pwm)) {
150         case PWM_POLARITY_NORMAL:
151                 polarity = "normal";
152                 break;
153
154         case PWM_POLARITY_INVERSED:
155                 polarity = "inversed";
156                 break;
157         }
158
159         return sprintf(buf, "%s\n", polarity);
160 }
161
162 static ssize_t polarity_store(struct device *child,
163                               struct device_attribute *attr,
164                               const char *buf, size_t size)
165 {
166         struct pwm_export *export = child_to_pwm_export(child);
167         struct pwm_device *pwm = export->pwm;
168         enum pwm_polarity polarity;
169         int ret;
170
171         if (sysfs_streq(buf, "normal"))
172                 polarity = PWM_POLARITY_NORMAL;
173         else if (sysfs_streq(buf, "inversed"))
174                 polarity = PWM_POLARITY_INVERSED;
175         else
176                 return -EINVAL;
177
178         mutex_lock(&export->lock);
179         ret = pwm_set_polarity(pwm, polarity);
180         mutex_unlock(&export->lock);
181
182         return ret ? : size;
183 }
184
185 static DEVICE_ATTR_RW(period);
186 static DEVICE_ATTR_RW(duty_cycle);
187 static DEVICE_ATTR_RW(enable);
188 static DEVICE_ATTR_RW(polarity);
189
190 static struct attribute *pwm_attrs[] = {
191         &dev_attr_period.attr,
192         &dev_attr_duty_cycle.attr,
193         &dev_attr_enable.attr,
194         &dev_attr_polarity.attr,
195         NULL
196 };
197 ATTRIBUTE_GROUPS(pwm);
198
199 static void pwm_export_release(struct device *child)
200 {
201         struct pwm_export *export = child_to_pwm_export(child);
202
203         kfree(export);
204 }
205
206 static int pwm_export_child(struct device *parent, struct pwm_device *pwm)
207 {
208         struct pwm_export *export;
209         int ret;
210
211         if (test_and_set_bit(PWMF_EXPORTED, &pwm->flags))
212                 return -EBUSY;
213
214         export = kzalloc(sizeof(*export), GFP_KERNEL);
215         if (!export) {
216                 clear_bit(PWMF_EXPORTED, &pwm->flags);
217                 return -ENOMEM;
218         }
219
220         export->pwm = pwm;
221         mutex_init(&export->lock);
222
223         export->child.release = pwm_export_release;
224         export->child.parent = parent;
225         export->child.devt = MKDEV(0, 0);
226         export->child.groups = pwm_groups;
227         dev_set_name(&export->child, "pwm%u", pwm->hwpwm);
228
229         ret = device_register(&export->child);
230         if (ret) {
231                 clear_bit(PWMF_EXPORTED, &pwm->flags);
232                 kfree(export);
233                 return ret;
234         }
235
236         return 0;
237 }
238
239 static int pwm_unexport_match(struct device *child, void *data)
240 {
241         return child_to_pwm_device(child) == data;
242 }
243
244 static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm)
245 {
246         struct device *child;
247
248         if (!test_and_clear_bit(PWMF_EXPORTED, &pwm->flags))
249                 return -ENODEV;
250
251         child = device_find_child(parent, pwm, pwm_unexport_match);
252         if (!child)
253                 return -ENODEV;
254
255         /* for device_find_child() */
256         put_device(child);
257         device_unregister(child);
258         pwm_put(pwm);
259
260         return 0;
261 }
262
263 static ssize_t export_store(struct device *parent,
264                             struct device_attribute *attr,
265                             const char *buf, size_t len)
266 {
267         struct pwm_chip *chip = dev_get_drvdata(parent);
268         struct pwm_device *pwm;
269         unsigned int hwpwm;
270         int ret;
271
272         ret = kstrtouint(buf, 0, &hwpwm);
273         if (ret < 0)
274                 return ret;
275
276         if (hwpwm >= chip->npwm)
277                 return -ENODEV;
278
279         pwm = pwm_request_from_chip(chip, hwpwm, "sysfs");
280         if (IS_ERR(pwm))
281                 return PTR_ERR(pwm);
282
283         ret = pwm_export_child(parent, pwm);
284         if (ret < 0)
285                 pwm_put(pwm);
286
287         return ret ? : len;
288 }
289 static DEVICE_ATTR_WO(export);
290
291 static ssize_t unexport_store(struct device *parent,
292                               struct device_attribute *attr,
293                               const char *buf, size_t len)
294 {
295         struct pwm_chip *chip = dev_get_drvdata(parent);
296         unsigned int hwpwm;
297         int ret;
298
299         ret = kstrtouint(buf, 0, &hwpwm);
300         if (ret < 0)
301                 return ret;
302
303         if (hwpwm >= chip->npwm)
304                 return -ENODEV;
305
306         ret = pwm_unexport_child(parent, &chip->pwms[hwpwm]);
307
308         return ret ? : len;
309 }
310 static DEVICE_ATTR_WO(unexport);
311
312 static ssize_t npwm_show(struct device *parent, struct device_attribute *attr,
313                          char *buf)
314 {
315         const struct pwm_chip *chip = dev_get_drvdata(parent);
316
317         return sprintf(buf, "%u\n", chip->npwm);
318 }
319 static DEVICE_ATTR_RO(npwm);
320
321 static struct attribute *pwm_chip_attrs[] = {
322         &dev_attr_export.attr,
323         &dev_attr_unexport.attr,
324         &dev_attr_npwm.attr,
325         NULL,
326 };
327 ATTRIBUTE_GROUPS(pwm_chip);
328
329 static struct class pwm_class = {
330         .name = "pwm",
331         .owner = THIS_MODULE,
332         .dev_groups = pwm_chip_groups,
333 };
334
335 static int pwmchip_sysfs_match(struct device *parent, const void *data)
336 {
337         return dev_get_drvdata(parent) == data;
338 }
339
340 void pwmchip_sysfs_export(struct pwm_chip *chip)
341 {
342         struct device *parent;
343
344         /*
345          * If device_create() fails the pwm_chip is still usable by
346          * the kernel its just not exported.
347          */
348         parent = device_create(&pwm_class, chip->dev, MKDEV(0, 0), chip,
349                                "pwmchip%d", chip->base);
350         if (IS_ERR(parent)) {
351                 dev_warn(chip->dev,
352                          "device_create failed for pwm_chip sysfs export\n");
353         }
354 }
355
356 void pwmchip_sysfs_unexport(struct pwm_chip *chip)
357 {
358         struct device *parent;
359
360         parent = class_find_device(&pwm_class, NULL, chip,
361                                    pwmchip_sysfs_match);
362         if (parent) {
363                 /* for class_find_device() */
364                 put_device(parent);
365                 device_unregister(parent);
366         }
367 }
368
369 static int __init pwm_sysfs_init(void)
370 {
371         return class_register(&pwm_class);
372 }
373 subsys_initcall(pwm_sysfs_init);