]>
git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/pwm/sysfs.c
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
;
31 static struct pwm_export
*child_to_pwm_export(struct device
*child
)
33 return container_of(child
, struct pwm_export
, child
);
36 static struct pwm_device
*child_to_pwm_device(struct device
*child
)
38 struct pwm_export
*export
= child_to_pwm_export(child
);
43 static ssize_t
pwm_period_show(struct device
*child
,
44 struct device_attribute
*attr
,
47 const struct pwm_device
*pwm
= child_to_pwm_device(child
);
49 return sprintf(buf
, "%u\n", pwm_get_period(pwm
));
52 static ssize_t
pwm_period_store(struct device
*child
,
53 struct device_attribute
*attr
,
54 const char *buf
, size_t size
)
56 struct pwm_device
*pwm
= child_to_pwm_device(child
);
60 ret
= kstrtouint(buf
, 0, &val
);
64 ret
= pwm_config(pwm
, pwm_get_duty_cycle(pwm
), val
);
69 static ssize_t
pwm_duty_cycle_show(struct device
*child
,
70 struct device_attribute
*attr
,
73 const struct pwm_device
*pwm
= child_to_pwm_device(child
);
75 return sprintf(buf
, "%u\n", pwm_get_duty_cycle(pwm
));
78 static ssize_t
pwm_duty_cycle_store(struct device
*child
,
79 struct device_attribute
*attr
,
80 const char *buf
, size_t size
)
82 struct pwm_device
*pwm
= child_to_pwm_device(child
);
86 ret
= kstrtouint(buf
, 0, &val
);
90 ret
= pwm_config(pwm
, val
, pwm_get_period(pwm
));
95 static ssize_t
pwm_enable_show(struct device
*child
,
96 struct device_attribute
*attr
,
99 const struct pwm_device
*pwm
= child_to_pwm_device(child
);
100 int enabled
= pwm_is_enabled(pwm
);
102 return sprintf(buf
, "%d\n", enabled
);
105 static ssize_t
pwm_enable_store(struct device
*child
,
106 struct device_attribute
*attr
,
107 const char *buf
, size_t size
)
109 struct pwm_device
*pwm
= child_to_pwm_device(child
);
112 ret
= kstrtoint(buf
, 0, &val
);
121 ret
= pwm_enable(pwm
);
131 static ssize_t
pwm_polarity_show(struct device
*child
,
132 struct device_attribute
*attr
,
135 const struct pwm_device
*pwm
= child_to_pwm_device(child
);
136 const char *polarity
= "unknown";
138 switch (pwm_get_polarity(pwm
)) {
139 case PWM_POLARITY_NORMAL
:
143 case PWM_POLARITY_INVERSED
:
144 polarity
= "inversed";
148 return sprintf(buf
, "%s\n", polarity
);
151 static ssize_t
pwm_polarity_store(struct device
*child
,
152 struct device_attribute
*attr
,
153 const char *buf
, size_t size
)
155 struct pwm_device
*pwm
= child_to_pwm_device(child
);
156 enum pwm_polarity polarity
;
159 if (sysfs_streq(buf
, "normal"))
160 polarity
= PWM_POLARITY_NORMAL
;
161 else if (sysfs_streq(buf
, "inversed"))
162 polarity
= PWM_POLARITY_INVERSED
;
166 ret
= pwm_set_polarity(pwm
, polarity
);
171 static DEVICE_ATTR(period
, 0644, pwm_period_show
, pwm_period_store
);
172 static DEVICE_ATTR(duty_cycle
, 0644, pwm_duty_cycle_show
, pwm_duty_cycle_store
);
173 static DEVICE_ATTR(enable
, 0644, pwm_enable_show
, pwm_enable_store
);
174 static DEVICE_ATTR(polarity
, 0644, pwm_polarity_show
, pwm_polarity_store
);
176 static struct attribute
*pwm_attrs
[] = {
177 &dev_attr_period
.attr
,
178 &dev_attr_duty_cycle
.attr
,
179 &dev_attr_enable
.attr
,
180 &dev_attr_polarity
.attr
,
183 ATTRIBUTE_GROUPS(pwm
);
185 static void pwm_export_release(struct device
*child
)
187 struct pwm_export
*export
= child_to_pwm_export(child
);
192 static int pwm_export_child(struct device
*parent
, struct pwm_device
*pwm
)
194 struct pwm_export
*export
;
197 if (test_and_set_bit(PWMF_EXPORTED
, &pwm
->flags
))
200 export
= kzalloc(sizeof(*export
), GFP_KERNEL
);
202 clear_bit(PWMF_EXPORTED
, &pwm
->flags
);
208 export
->child
.release
= pwm_export_release
;
209 export
->child
.parent
= parent
;
210 export
->child
.devt
= MKDEV(0, 0);
211 export
->child
.groups
= pwm_groups
;
212 dev_set_name(&export
->child
, "pwm%u", pwm
->hwpwm
);
214 ret
= device_register(&export
->child
);
216 clear_bit(PWMF_EXPORTED
, &pwm
->flags
);
224 static int pwm_unexport_match(struct device
*child
, void *data
)
226 return child_to_pwm_device(child
) == data
;
229 static int pwm_unexport_child(struct device
*parent
, struct pwm_device
*pwm
)
231 struct device
*child
;
233 if (!test_and_clear_bit(PWMF_EXPORTED
, &pwm
->flags
))
236 child
= device_find_child(parent
, pwm
, pwm_unexport_match
);
240 /* for device_find_child() */
242 device_unregister(child
);
248 static ssize_t
pwm_export_store(struct device
*parent
,
249 struct device_attribute
*attr
,
250 const char *buf
, size_t len
)
252 struct pwm_chip
*chip
= dev_get_drvdata(parent
);
253 struct pwm_device
*pwm
;
257 ret
= kstrtouint(buf
, 0, &hwpwm
);
261 if (hwpwm
>= chip
->npwm
)
264 pwm
= pwm_request_from_chip(chip
, hwpwm
, "sysfs");
268 ret
= pwm_export_child(parent
, pwm
);
274 static DEVICE_ATTR(export
, 0200, NULL
, pwm_export_store
);
276 static ssize_t
pwm_unexport_store(struct device
*parent
,
277 struct device_attribute
*attr
,
278 const char *buf
, size_t len
)
280 struct pwm_chip
*chip
= dev_get_drvdata(parent
);
284 ret
= kstrtouint(buf
, 0, &hwpwm
);
288 if (hwpwm
>= chip
->npwm
)
291 ret
= pwm_unexport_child(parent
, &chip
->pwms
[hwpwm
]);
295 static DEVICE_ATTR(unexport
, 0200, NULL
, pwm_unexport_store
);
297 static ssize_t
npwm_show(struct device
*parent
, struct device_attribute
*attr
,
300 const struct pwm_chip
*chip
= dev_get_drvdata(parent
);
302 return sprintf(buf
, "%u\n", chip
->npwm
);
304 static DEVICE_ATTR_RO(npwm
);
306 static struct attribute
*pwm_chip_attrs
[] = {
307 &dev_attr_export
.attr
,
308 &dev_attr_unexport
.attr
,
312 ATTRIBUTE_GROUPS(pwm_chip
);
314 static struct class pwm_class
= {
316 .owner
= THIS_MODULE
,
317 .dev_groups
= pwm_chip_groups
,
320 static int pwmchip_sysfs_match(struct device
*parent
, const void *data
)
322 return dev_get_drvdata(parent
) == data
;
325 void pwmchip_sysfs_export(struct pwm_chip
*chip
)
327 struct device
*parent
;
330 * If device_create() fails the pwm_chip is still usable by
331 * the kernel its just not exported.
333 parent
= device_create(&pwm_class
, chip
->dev
, MKDEV(0, 0), chip
,
334 "pwmchip%d", chip
->base
);
335 if (IS_ERR(parent
)) {
337 "device_create failed for pwm_chip sysfs export\n");
341 void pwmchip_sysfs_unexport(struct pwm_chip
*chip
)
343 struct device
*parent
;
345 parent
= class_find_device(&pwm_class
, NULL
, chip
,
346 pwmchip_sysfs_match
);
348 /* for class_find_device() */
350 device_unregister(parent
);
354 static int __init
pwm_sysfs_init(void)
356 return class_register(&pwm_class
);
358 subsys_initcall(pwm_sysfs_init
);