2 * A simple sysfs interface for the generic PWM framework
4 * Copyright (C) 2013 H Hartley Sweeten <hsweeten@visionengravers.com>
6 * Based on previous work by Lars Poeschel <poeschel@lemonage.de>
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)
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.
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>
28 struct pwm_device
*pwm
;
32 static struct pwm_export
*child_to_pwm_export(struct device
*child
)
34 return container_of(child
, struct pwm_export
, child
);
37 static struct pwm_device
*child_to_pwm_device(struct device
*child
)
39 struct pwm_export
*export
= child_to_pwm_export(child
);
44 static ssize_t
period_show(struct device
*child
,
45 struct device_attribute
*attr
,
48 const struct pwm_device
*pwm
= child_to_pwm_device(child
);
49 struct pwm_state state
;
51 pwm_get_state(pwm
, &state
);
53 return sprintf(buf
, "%u\n", state
.period
);
56 static ssize_t
period_store(struct device
*child
,
57 struct device_attribute
*attr
,
58 const char *buf
, size_t size
)
60 struct pwm_export
*export
= child_to_pwm_export(child
);
61 struct pwm_device
*pwm
= export
->pwm
;
62 struct pwm_state state
;
66 ret
= kstrtouint(buf
, 0, &val
);
70 mutex_lock(&export
->lock
);
71 pwm_get_state(pwm
, &state
);
73 ret
= pwm_apply_state(pwm
, &state
);
74 mutex_unlock(&export
->lock
);
79 static ssize_t
duty_cycle_show(struct device
*child
,
80 struct device_attribute
*attr
,
83 const struct pwm_device
*pwm
= child_to_pwm_device(child
);
84 struct pwm_state state
;
86 pwm_get_state(pwm
, &state
);
88 return sprintf(buf
, "%u\n", state
.duty_cycle
);
91 static ssize_t
duty_cycle_store(struct device
*child
,
92 struct device_attribute
*attr
,
93 const char *buf
, size_t size
)
95 struct pwm_export
*export
= child_to_pwm_export(child
);
96 struct pwm_device
*pwm
= export
->pwm
;
97 struct pwm_state state
;
101 ret
= kstrtouint(buf
, 0, &val
);
105 mutex_lock(&export
->lock
);
106 pwm_get_state(pwm
, &state
);
107 state
.duty_cycle
= val
;
108 ret
= pwm_apply_state(pwm
, &state
);
109 mutex_unlock(&export
->lock
);
114 static ssize_t
enable_show(struct device
*child
,
115 struct device_attribute
*attr
,
118 const struct pwm_device
*pwm
= child_to_pwm_device(child
);
119 struct pwm_state state
;
121 pwm_get_state(pwm
, &state
);
123 return sprintf(buf
, "%d\n", state
.enabled
);
126 static ssize_t
enable_store(struct device
*child
,
127 struct device_attribute
*attr
,
128 const char *buf
, size_t size
)
130 struct pwm_export
*export
= child_to_pwm_export(child
);
131 struct pwm_device
*pwm
= export
->pwm
;
132 struct pwm_state state
;
135 ret
= kstrtoint(buf
, 0, &val
);
139 mutex_lock(&export
->lock
);
141 pwm_get_state(pwm
, &state
);
145 state
.enabled
= false;
148 state
.enabled
= true;
155 ret
= pwm_apply_state(pwm
, &state
);
158 mutex_unlock(&export
->lock
);
162 static ssize_t
polarity_show(struct device
*child
,
163 struct device_attribute
*attr
,
166 const struct pwm_device
*pwm
= child_to_pwm_device(child
);
167 const char *polarity
= "unknown";
168 struct pwm_state state
;
170 pwm_get_state(pwm
, &state
);
172 switch (state
.polarity
) {
173 case PWM_POLARITY_NORMAL
:
177 case PWM_POLARITY_INVERSED
:
178 polarity
= "inversed";
182 return sprintf(buf
, "%s\n", polarity
);
185 static ssize_t
polarity_store(struct device
*child
,
186 struct device_attribute
*attr
,
187 const char *buf
, size_t size
)
189 struct pwm_export
*export
= child_to_pwm_export(child
);
190 struct pwm_device
*pwm
= export
->pwm
;
191 enum pwm_polarity polarity
;
192 struct pwm_state state
;
195 if (sysfs_streq(buf
, "normal"))
196 polarity
= PWM_POLARITY_NORMAL
;
197 else if (sysfs_streq(buf
, "inversed"))
198 polarity
= PWM_POLARITY_INVERSED
;
202 mutex_lock(&export
->lock
);
203 pwm_get_state(pwm
, &state
);
204 state
.polarity
= polarity
;
205 ret
= pwm_apply_state(pwm
, &state
);
206 mutex_unlock(&export
->lock
);
211 static ssize_t
capture_show(struct device
*child
,
212 struct device_attribute
*attr
,
215 struct pwm_device
*pwm
= child_to_pwm_device(child
);
216 struct pwm_capture result
;
219 ret
= pwm_capture(pwm
, &result
, jiffies_to_msecs(HZ
));
223 return sprintf(buf
, "%u %u\n", result
.period
, result
.duty_cycle
);
226 static DEVICE_ATTR_RW(period
);
227 static DEVICE_ATTR_RW(duty_cycle
);
228 static DEVICE_ATTR_RW(enable
);
229 static DEVICE_ATTR_RW(polarity
);
230 static DEVICE_ATTR_RO(capture
);
232 static struct attribute
*pwm_attrs
[] = {
233 &dev_attr_period
.attr
,
234 &dev_attr_duty_cycle
.attr
,
235 &dev_attr_enable
.attr
,
236 &dev_attr_polarity
.attr
,
237 &dev_attr_capture
.attr
,
240 ATTRIBUTE_GROUPS(pwm
);
242 static void pwm_export_release(struct device
*child
)
244 struct pwm_export
*export
= child_to_pwm_export(child
);
249 static int pwm_export_child(struct device
*parent
, struct pwm_device
*pwm
)
251 struct pwm_export
*export
;
254 if (test_and_set_bit(PWMF_EXPORTED
, &pwm
->flags
))
257 export
= kzalloc(sizeof(*export
), GFP_KERNEL
);
259 clear_bit(PWMF_EXPORTED
, &pwm
->flags
);
264 mutex_init(&export
->lock
);
266 export
->child
.release
= pwm_export_release
;
267 export
->child
.parent
= parent
;
268 export
->child
.devt
= MKDEV(0, 0);
269 export
->child
.groups
= pwm_groups
;
270 dev_set_name(&export
->child
, "pwm%u", pwm
->hwpwm
);
272 ret
= device_register(&export
->child
);
274 clear_bit(PWMF_EXPORTED
, &pwm
->flags
);
282 static int pwm_unexport_match(struct device
*child
, void *data
)
284 return child_to_pwm_device(child
) == data
;
287 static int pwm_unexport_child(struct device
*parent
, struct pwm_device
*pwm
)
289 struct device
*child
;
291 if (!test_and_clear_bit(PWMF_EXPORTED
, &pwm
->flags
))
294 child
= device_find_child(parent
, pwm
, pwm_unexport_match
);
298 /* for device_find_child() */
300 device_unregister(child
);
306 static ssize_t
export_store(struct device
*parent
,
307 struct device_attribute
*attr
,
308 const char *buf
, size_t len
)
310 struct pwm_chip
*chip
= dev_get_drvdata(parent
);
311 struct pwm_device
*pwm
;
315 ret
= kstrtouint(buf
, 0, &hwpwm
);
319 if (hwpwm
>= chip
->npwm
)
322 pwm
= pwm_request_from_chip(chip
, hwpwm
, "sysfs");
326 ret
= pwm_export_child(parent
, pwm
);
332 static DEVICE_ATTR_WO(export
);
334 static ssize_t
unexport_store(struct device
*parent
,
335 struct device_attribute
*attr
,
336 const char *buf
, size_t len
)
338 struct pwm_chip
*chip
= dev_get_drvdata(parent
);
342 ret
= kstrtouint(buf
, 0, &hwpwm
);
346 if (hwpwm
>= chip
->npwm
)
349 ret
= pwm_unexport_child(parent
, &chip
->pwms
[hwpwm
]);
353 static DEVICE_ATTR_WO(unexport
);
355 static ssize_t
npwm_show(struct device
*parent
, struct device_attribute
*attr
,
358 const struct pwm_chip
*chip
= dev_get_drvdata(parent
);
360 return sprintf(buf
, "%u\n", chip
->npwm
);
362 static DEVICE_ATTR_RO(npwm
);
364 static struct attribute
*pwm_chip_attrs
[] = {
365 &dev_attr_export
.attr
,
366 &dev_attr_unexport
.attr
,
370 ATTRIBUTE_GROUPS(pwm_chip
);
372 static struct class pwm_class
= {
374 .owner
= THIS_MODULE
,
375 .dev_groups
= pwm_chip_groups
,
378 static int pwmchip_sysfs_match(struct device
*parent
, const void *data
)
380 return dev_get_drvdata(parent
) == data
;
383 void pwmchip_sysfs_export(struct pwm_chip
*chip
)
385 struct device
*parent
;
388 * If device_create() fails the pwm_chip is still usable by
389 * the kernel its just not exported.
391 parent
= device_create(&pwm_class
, chip
->dev
, MKDEV(0, 0), chip
,
392 "pwmchip%d", chip
->base
);
393 if (IS_ERR(parent
)) {
395 "device_create failed for pwm_chip sysfs export\n");
399 void pwmchip_sysfs_unexport(struct pwm_chip
*chip
)
401 struct device
*parent
;
403 parent
= class_find_device(&pwm_class
, NULL
, chip
,
404 pwmchip_sysfs_match
);
406 /* for class_find_device() */
408 device_unregister(parent
);
412 void pwmchip_sysfs_unexport_children(struct pwm_chip
*chip
)
414 struct device
*parent
;
417 parent
= class_find_device(&pwm_class
, NULL
, chip
,
418 pwmchip_sysfs_match
);
422 for (i
= 0; i
< chip
->npwm
; i
++) {
423 struct pwm_device
*pwm
= &chip
->pwms
[i
];
425 if (test_bit(PWMF_EXPORTED
, &pwm
->flags
))
426 pwm_unexport_child(parent
, pwm
);
432 static int __init
pwm_sysfs_init(void)
434 return class_register(&pwm_class
);
436 subsys_initcall(pwm_sysfs_init
);