Root/target/linux/generic/files/drivers/pwm/pwm.c

1/*
2 * drivers/pwm/pwm.c
3 *
4 * Copyright (C) 2010 Bill Gatliff <bgat@billgatliff.com>
5 *
6 * This program is free software; you may redistribute and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA
19 */
20
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/init.h>
24#include <linux/device.h>
25#include <linux/spinlock.h>
26#include <linux/fs.h>
27#include <linux/completion.h>
28#include <linux/workqueue.h>
29#include <linux/list.h>
30#include <linux/sched.h>
31#include <linux/slab.h> /*kcalloc, kfree since 2.6.34 */
32#include <linux/pwm/pwm.h>
33
34static int __pwm_create_sysfs(struct pwm_device *pwm);
35
36static const char *REQUEST_SYSFS = "sysfs";
37static LIST_HEAD(pwm_device_list);
38static DEFINE_MUTEX(device_list_mutex);
39static struct class pwm_class;
40static struct workqueue_struct *pwm_handler_workqueue;
41
42int pwm_register(struct pwm_device *pwm)
43{
44    struct pwm_channel *p;
45    int wchan;
46    int ret;
47
48    spin_lock_init(&pwm->list_lock);
49
50    p = kcalloc(pwm->nchan, sizeof(*p), GFP_KERNEL);
51    if (!p)
52        return -ENOMEM;
53
54    for (wchan = 0; wchan < pwm->nchan; wchan++) {
55        spin_lock_init(&p[wchan].lock);
56        init_completion(&p[wchan].complete);
57        p[wchan].chan = wchan;
58        p[wchan].pwm = pwm;
59    }
60
61    pwm->channels = p;
62
63    mutex_lock(&device_list_mutex);
64
65    list_add_tail(&pwm->list, &pwm_device_list);
66    ret = __pwm_create_sysfs(pwm);
67    if (ret) {
68        mutex_unlock(&device_list_mutex);
69        goto err_create_sysfs;
70    }
71
72    mutex_unlock(&device_list_mutex);
73
74    dev_info(pwm->dev, "%d channel%s\n", pwm->nchan,
75         pwm->nchan > 1 ? "s" : "");
76    return 0;
77
78err_create_sysfs:
79    kfree(p);
80
81    return ret;
82}
83EXPORT_SYMBOL(pwm_register);
84
85static int __match_device(struct device *dev, void *data)
86{
87    return dev_get_drvdata(dev) == data;
88}
89
90int pwm_unregister(struct pwm_device *pwm)
91{
92    int wchan;
93    struct device *dev;
94
95    mutex_lock(&device_list_mutex);
96
97    for (wchan = 0; wchan < pwm->nchan; wchan++) {
98      if (pwm->channels[wchan].flags & BIT(FLAG_REQUESTED)) {
99            mutex_unlock(&device_list_mutex);
100            return -EBUSY;
101        }
102    }
103
104    for (wchan = 0; wchan < pwm->nchan; wchan++) {
105        dev = class_find_device(&pwm_class, NULL,
106                    &pwm->channels[wchan],
107                    __match_device);
108        if (dev) {
109            put_device(dev);
110            device_unregister(dev);
111        }
112    }
113
114    kfree(pwm->channels);
115    list_del(&pwm->list);
116    mutex_unlock(&device_list_mutex);
117
118    return 0;
119}
120EXPORT_SYMBOL(pwm_unregister);
121
122static struct pwm_device *
123__pwm_find_device(const char *bus_id)
124{
125    struct pwm_device *p;
126
127    list_for_each_entry(p, &pwm_device_list, list) {
128        if (!strcmp(bus_id, p->bus_id))
129            return p;
130    }
131    return NULL;
132}
133
134static int
135__pwm_request_channel(struct pwm_channel *p,
136              const char *requester)
137{
138    int ret;
139
140    if (test_and_set_bit(FLAG_REQUESTED, &p->flags))
141        return -EBUSY;
142
143    if (p->pwm->request) {
144        ret = p->pwm->request(p);
145        if (ret) {
146            clear_bit(FLAG_REQUESTED, &p->flags);
147            return ret;
148        }
149    }
150
151    p->requester = requester;
152    if (!strcmp(requester, REQUEST_SYSFS))
153        p->pid = current->pid;
154
155    return 0;
156}
157
158struct pwm_channel *
159pwm_request(const char *bus_id,
160        int chan,
161        const char *requester)
162{
163    struct pwm_device *p;
164    int ret;
165
166    mutex_lock(&device_list_mutex);
167
168    p = __pwm_find_device(bus_id);
169    if (!p || chan >= p->nchan)
170        goto err_no_device;
171
172    if (!try_module_get(p->owner))
173        goto err_module_get_failed;
174
175    ret = __pwm_request_channel(&p->channels[chan], requester);
176    if (ret)
177        goto err_request_failed;
178
179    mutex_unlock(&device_list_mutex);
180    return &p->channels[chan];
181
182err_request_failed:
183    module_put(p->owner);
184err_module_get_failed:
185err_no_device:
186    mutex_unlock(&device_list_mutex);
187    return NULL;
188}
189EXPORT_SYMBOL(pwm_request);
190
191void pwm_free(struct pwm_channel *p)
192{
193    mutex_lock(&device_list_mutex);
194
195    if (!test_and_clear_bit(FLAG_REQUESTED, &p->flags))
196        goto done;
197
198    pwm_stop(p);
199    pwm_unsynchronize(p, NULL);
200    pwm_set_handler(p, NULL, NULL);
201
202    if (p->pwm->free)
203        p->pwm->free(p);
204    module_put(p->pwm->owner);
205done:
206    mutex_unlock(&device_list_mutex);
207}
208EXPORT_SYMBOL(pwm_free);
209
210unsigned long pwm_ns_to_ticks(struct pwm_channel *p,
211                  unsigned long nsecs)
212{
213    unsigned long long ticks;
214
215    ticks = nsecs;
216    ticks *= p->tick_hz;
217    do_div(ticks, 1000000000);
218    return ticks;
219}
220EXPORT_SYMBOL(pwm_ns_to_ticks);
221
222unsigned long pwm_ticks_to_ns(struct pwm_channel *p,
223                  unsigned long ticks)
224{
225    unsigned long long ns;
226
227    if (!p->tick_hz)
228        return 0;
229
230    ns = ticks;
231    ns *= 1000000000UL;
232    do_div(ns, p->tick_hz);
233    return ns;
234}
235EXPORT_SYMBOL(pwm_ticks_to_ns);
236
237static void
238pwm_config_ns_to_ticks(struct pwm_channel *p,
239               struct pwm_channel_config *c)
240{
241    if (c->config_mask & PWM_CONFIG_PERIOD_NS) {
242        c->period_ticks = pwm_ns_to_ticks(p, c->period_ns);
243        c->config_mask &= ~PWM_CONFIG_PERIOD_NS;
244        c->config_mask |= PWM_CONFIG_PERIOD_TICKS;
245    }
246
247    if (c->config_mask & PWM_CONFIG_DUTY_NS) {
248        c->duty_ticks = pwm_ns_to_ticks(p, c->duty_ns);
249        c->config_mask &= ~PWM_CONFIG_DUTY_NS;
250        c->config_mask |= PWM_CONFIG_DUTY_TICKS;
251    }
252}
253
254static void
255pwm_config_percent_to_ticks(struct pwm_channel *p,
256                struct pwm_channel_config *c)
257{
258    if (c->config_mask & PWM_CONFIG_DUTY_PERCENT) {
259        if (c->config_mask & PWM_CONFIG_PERIOD_TICKS)
260            c->duty_ticks = c->period_ticks;
261        else
262            c->duty_ticks = p->period_ticks;
263
264        c->duty_ticks *= c->duty_percent;
265        c->duty_ticks /= 100;
266        c->config_mask &= ~PWM_CONFIG_DUTY_PERCENT;
267        c->config_mask |= PWM_CONFIG_DUTY_TICKS;
268    }
269}
270
271int pwm_config_nosleep(struct pwm_channel *p,
272               struct pwm_channel_config *c)
273{
274    if (!p->pwm->config_nosleep)
275        return -EINVAL;
276
277    pwm_config_ns_to_ticks(p, c);
278    pwm_config_percent_to_ticks(p, c);
279
280    return p->pwm->config_nosleep(p, c);
281}
282EXPORT_SYMBOL(pwm_config_nosleep);
283
284int pwm_config(struct pwm_channel *p,
285           struct pwm_channel_config *c)
286{
287    int ret = 0;
288
289    if (unlikely(!p->pwm->config))
290        return -EINVAL;
291
292    pwm_config_ns_to_ticks(p, c);
293    pwm_config_percent_to_ticks(p, c);
294
295    switch (c->config_mask & (PWM_CONFIG_PERIOD_TICKS
296                  | PWM_CONFIG_DUTY_TICKS)) {
297    case PWM_CONFIG_PERIOD_TICKS:
298        if (p->duty_ticks > c->period_ticks) {
299            ret = -EINVAL;
300            goto err;
301        }
302        break;
303    case PWM_CONFIG_DUTY_TICKS:
304        if (p->period_ticks < c->duty_ticks) {
305            ret = -EINVAL;
306            goto err;
307        }
308        break;
309    case PWM_CONFIG_DUTY_TICKS | PWM_CONFIG_PERIOD_TICKS:
310        if (c->duty_ticks > c->period_ticks) {
311            ret = -EINVAL;
312            goto err;
313        }
314        break;
315    default:
316        break;
317    }
318
319err:
320    dev_dbg(p->pwm->dev, "%s: config_mask %d period_ticks %lu duty_ticks %lu"
321        " polarity %d duty_ns %lu period_ns %lu duty_percent %d\n",
322        __func__, c->config_mask, c->period_ticks, c->duty_ticks,
323        c->polarity, c->duty_ns, c->period_ns, c->duty_percent);
324
325    if (ret)
326        return ret;
327    return p->pwm->config(p, c);
328}
329EXPORT_SYMBOL(pwm_config);
330
331int pwm_set_period_ns(struct pwm_channel *p,
332              unsigned long period_ns)
333{
334    struct pwm_channel_config c = {
335        .config_mask = PWM_CONFIG_PERIOD_TICKS,
336        .period_ticks = pwm_ns_to_ticks(p, period_ns),
337    };
338
339    return pwm_config(p, &c);
340}
341EXPORT_SYMBOL(pwm_set_period_ns);
342
343unsigned long pwm_get_period_ns(struct pwm_channel *p)
344{
345    return pwm_ticks_to_ns(p, p->period_ticks);
346}
347EXPORT_SYMBOL(pwm_get_period_ns);
348
349int pwm_set_duty_ns(struct pwm_channel *p,
350            unsigned long duty_ns)
351{
352    struct pwm_channel_config c = {
353        .config_mask = PWM_CONFIG_DUTY_TICKS,
354        .duty_ticks = pwm_ns_to_ticks(p, duty_ns),
355    };
356    return pwm_config(p, &c);
357}
358EXPORT_SYMBOL(pwm_set_duty_ns);
359
360unsigned long pwm_get_duty_ns(struct pwm_channel *p)
361{
362    return pwm_ticks_to_ns(p, p->duty_ticks);
363}
364EXPORT_SYMBOL(pwm_get_duty_ns);
365
366int pwm_set_duty_percent(struct pwm_channel *p,
367             int percent)
368{
369    struct pwm_channel_config c = {
370        .config_mask = PWM_CONFIG_DUTY_PERCENT,
371        .duty_percent = percent,
372    };
373    return pwm_config(p, &c);
374}
375EXPORT_SYMBOL(pwm_set_duty_percent);
376
377int pwm_set_polarity(struct pwm_channel *p,
378             int active_high)
379{
380    struct pwm_channel_config c = {
381        .config_mask = PWM_CONFIG_POLARITY,
382        .polarity = active_high,
383    };
384    return pwm_config(p, &c);
385}
386EXPORT_SYMBOL(pwm_set_polarity);
387
388int pwm_start(struct pwm_channel *p)
389{
390    struct pwm_channel_config c = {
391        .config_mask = PWM_CONFIG_START,
392    };
393    return pwm_config(p, &c);
394}
395EXPORT_SYMBOL(pwm_start);
396
397int pwm_stop(struct pwm_channel *p)
398{
399    struct pwm_channel_config c = {
400        .config_mask = PWM_CONFIG_STOP,
401    };
402    return pwm_config(p, &c);
403}
404EXPORT_SYMBOL(pwm_stop);
405
406int pwm_synchronize(struct pwm_channel *p,
407            struct pwm_channel *to_p)
408{
409    if (p->pwm != to_p->pwm) {
410        /* TODO: support cross-device synchronization */
411        return -EINVAL;
412    }
413
414    if (!p->pwm->synchronize)
415        return -EINVAL;
416
417    return p->pwm->synchronize(p, to_p);
418}
419EXPORT_SYMBOL(pwm_synchronize);
420
421int pwm_unsynchronize(struct pwm_channel *p,
422              struct pwm_channel *from_p)
423{
424    if (from_p && (p->pwm != from_p->pwm)) {
425        /* TODO: support cross-device synchronization */
426        return -EINVAL;
427    }
428
429    if (!p->pwm->unsynchronize)
430        return -EINVAL;
431
432    return p->pwm->unsynchronize(p, from_p);
433}
434EXPORT_SYMBOL(pwm_unsynchronize);
435
436static void pwm_handler(struct work_struct *w)
437{
438    struct pwm_channel *p = container_of(w, struct pwm_channel,
439                         handler_work);
440    if (p->handler && p->handler(p, p->handler_data))
441        pwm_stop(p);
442}
443
444static void __pwm_callback(struct pwm_channel *p)
445{
446    queue_work(pwm_handler_workqueue, &p->handler_work);
447    dev_dbg(p->pwm->dev, "handler %p scheduled with data %p\n",
448        p->handler, p->handler_data);
449}
450
451int pwm_set_handler(struct pwm_channel *p,
452            pwm_handler_t handler,
453            void *data)
454{
455    if (p->pwm->set_callback) {
456        p->handler_data = data;
457        p->handler = handler;
458        INIT_WORK(&p->handler_work, pwm_handler);
459        return p->pwm->set_callback(p, handler ? __pwm_callback : NULL);
460    }
461    return -EINVAL;
462}
463EXPORT_SYMBOL(pwm_set_handler);
464
465static ssize_t pwm_run_store(struct device *dev,
466                 struct device_attribute *attr,
467                 const char *buf,
468                 size_t len)
469{
470    struct pwm_channel *p = dev_get_drvdata(dev);
471    if (sysfs_streq(buf, "1"))
472        pwm_start(p);
473    else if (sysfs_streq(buf, "0"))
474        pwm_stop(p);
475    return len;
476}
477static DEVICE_ATTR(run, 0200, NULL, pwm_run_store);
478
479static ssize_t pwm_duty_ns_show(struct device *dev,
480                struct device_attribute *attr,
481                char *buf)
482{
483    struct pwm_channel *p = dev_get_drvdata(dev);
484    return sprintf(buf, "%lu\n", pwm_get_duty_ns(p));
485}
486
487static ssize_t pwm_duty_ns_store(struct device *dev,
488                 struct device_attribute *attr,
489                 const char *buf,
490                 size_t len)
491{
492    unsigned long duty_ns;
493    struct pwm_channel *p = dev_get_drvdata(dev);
494
495    if (1 == sscanf(buf, "%lu", &duty_ns))
496        pwm_set_duty_ns(p, duty_ns);
497    return len;
498}
499static DEVICE_ATTR(duty_ns, 0644, pwm_duty_ns_show, pwm_duty_ns_store);
500
501static ssize_t pwm_period_ns_show(struct device *dev,
502                  struct device_attribute *attr,
503                  char *buf)
504{
505    struct pwm_channel *p = dev_get_drvdata(dev);
506    return sprintf(buf, "%lu\n", pwm_get_period_ns(p));
507}
508
509static ssize_t pwm_period_ns_store(struct device *dev,
510                   struct device_attribute *attr,
511                   const char *buf,
512                   size_t len)
513{
514    unsigned long period_ns;
515    struct pwm_channel *p = dev_get_drvdata(dev);
516
517    if (1 == sscanf(buf, "%lu", &period_ns))
518        pwm_set_period_ns(p, period_ns);
519    return len;
520}
521static DEVICE_ATTR(period_ns, 0644, pwm_period_ns_show, pwm_period_ns_store);
522
523static ssize_t pwm_polarity_show(struct device *dev,
524                 struct device_attribute *attr,
525                 char *buf)
526{
527    struct pwm_channel *p = dev_get_drvdata(dev);
528    return sprintf(buf, "%d\n", p->active_high ? 1 : 0);
529}
530
531static ssize_t pwm_polarity_store(struct device *dev,
532                  struct device_attribute *attr,
533                  const char *buf,
534                  size_t len)
535{
536    int polarity;
537    struct pwm_channel *p = dev_get_drvdata(dev);
538
539    if (1 == sscanf(buf, "%d", &polarity))
540        pwm_set_polarity(p, polarity);
541    return len;
542}
543static DEVICE_ATTR(polarity, 0644, pwm_polarity_show, pwm_polarity_store);
544
545static ssize_t pwm_request_show(struct device *dev,
546                struct device_attribute *attr,
547                char *buf)
548{
549    struct pwm_channel *p = dev_get_drvdata(dev);
550    mutex_lock(&device_list_mutex);
551    __pwm_request_channel(p, REQUEST_SYSFS);
552    mutex_unlock(&device_list_mutex);
553
554    if (p->pid)
555        return sprintf(buf, "%s %d\n", p->requester, p->pid);
556    else
557        return sprintf(buf, "%s\n", p->requester);
558}
559
560static ssize_t pwm_request_store(struct device *dev,
561                 struct device_attribute *attr,
562                 const char *buf,
563                 size_t len)
564{
565    struct pwm_channel *p = dev_get_drvdata(dev);
566    pwm_free(p);
567    return len;
568}
569static DEVICE_ATTR(request, 0644, pwm_request_show, pwm_request_store);
570
571static const struct attribute *pwm_attrs[] =
572{
573    &dev_attr_run.attr,
574    &dev_attr_polarity.attr,
575    &dev_attr_duty_ns.attr,
576    &dev_attr_period_ns.attr,
577    &dev_attr_request.attr,
578    NULL,
579};
580
581static const struct attribute_group pwm_device_attr_group = {
582    .attrs = (struct attribute **)pwm_attrs,
583};
584
585static int __pwm_create_sysfs(struct pwm_device *pwm)
586{
587    int ret = 0;
588    struct device *dev;
589    int wchan;
590
591    for (wchan = 0; wchan < pwm->nchan; wchan++) {
592        dev = device_create(&pwm_class, pwm->dev, MKDEV(0, 0),
593                    pwm->channels + wchan,
594                    "%s:%d", pwm->bus_id, wchan);
595        if (!dev)
596            goto err_dev_create;
597        ret = sysfs_create_group(&dev->kobj, &pwm_device_attr_group);
598        if (ret)
599            goto err_dev_create;
600    }
601
602    return ret;
603
604err_dev_create:
605    for (wchan = 0; wchan < pwm->nchan; wchan++) {
606        dev = class_find_device(&pwm_class, NULL,
607                    &pwm->channels[wchan],
608                    __match_device);
609        if (dev) {
610            put_device(dev);
611            device_unregister(dev);
612        }
613    }
614
615    return ret;
616}
617
618static struct class_attribute pwm_class_attrs[] = {
619    __ATTR_NULL,
620};
621
622static struct class pwm_class = {
623    .name = "pwm",
624    .owner = THIS_MODULE,
625
626    .class_attrs = pwm_class_attrs,
627};
628
629static int __init pwm_init(void)
630{
631    int ret;
632
633    /* TODO: how to deal with devices that register very early? */
634    pr_err("%s\n", __func__);
635    ret = class_register(&pwm_class);
636    if (ret < 0)
637        return ret;
638
639    pwm_handler_workqueue = create_workqueue("pwmd");
640
641    return 0;
642}
643postcore_initcall(pwm_init);
644

Archive Download this file



interactive