linux/drivers/pwm/sysfs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * A simple sysfs interface for the generic PWM framework
   4 *
   5 * Copyright (C) 2013 H Hartley Sweeten <hsweeten@visionengravers.com>
   6 *
   7 * Based on previous work by Lars Poeschel <poeschel@lemonage.de>
   8 */
   9
  10#include <linux/device.h>
  11#include <linux/mutex.h>
  12#include <linux/err.h>
  13#include <linux/slab.h>
  14#include <linux/kdev_t.h>
  15#include <linux/pwm.h>
  16
  17struct pwm_export {
  18        struct device child;
  19        struct pwm_device *pwm;
  20        struct mutex lock;
  21        struct pwm_state suspend;
  22};
  23
  24static struct pwm_export *child_to_pwm_export(struct device *child)
  25{
  26        return container_of(child, struct pwm_export, child);
  27}
  28
  29static struct pwm_device *child_to_pwm_device(struct device *child)
  30{
  31        struct pwm_export *export = child_to_pwm_export(child);
  32
  33        return export->pwm;
  34}
  35
  36static ssize_t period_show(struct device *child,
  37                           struct device_attribute *attr,
  38                           char *buf)
  39{
  40        const struct pwm_device *pwm = child_to_pwm_device(child);
  41        struct pwm_state state;
  42
  43        pwm_get_state(pwm, &state);
  44
  45        return sprintf(buf, "%llu\n", state.period);
  46}
  47
  48static ssize_t period_store(struct device *child,
  49                            struct device_attribute *attr,
  50                            const char *buf, size_t size)
  51{
  52        struct pwm_export *export = child_to_pwm_export(child);
  53        struct pwm_device *pwm = export->pwm;
  54        struct pwm_state state;
  55        u64 val;
  56        int ret;
  57
  58        ret = kstrtou64(buf, 0, &val);
  59        if (ret)
  60                return ret;
  61
  62        mutex_lock(&export->lock);
  63        pwm_get_state(pwm, &state);
  64        state.period = val;
  65        ret = pwm_apply_state(pwm, &state);
  66        mutex_unlock(&export->lock);
  67
  68        return ret ? : size;
  69}
  70
  71static ssize_t duty_cycle_show(struct device *child,
  72                               struct device_attribute *attr,
  73                               char *buf)
  74{
  75        const struct pwm_device *pwm = child_to_pwm_device(child);
  76        struct pwm_state state;
  77
  78        pwm_get_state(pwm, &state);
  79
  80        return sprintf(buf, "%llu\n", state.duty_cycle);
  81}
  82
  83static ssize_t duty_cycle_store(struct device *child,
  84                                struct device_attribute *attr,
  85                                const char *buf, size_t size)
  86{
  87        struct pwm_export *export = child_to_pwm_export(child);
  88        struct pwm_device *pwm = export->pwm;
  89        struct pwm_state state;
  90        u64 val;
  91        int ret;
  92
  93        ret = kstrtou64(buf, 0, &val);
  94        if (ret)
  95                return ret;
  96
  97        mutex_lock(&export->lock);
  98        pwm_get_state(pwm, &state);
  99        state.duty_cycle = val;
 100        ret = pwm_apply_state(pwm, &state);
 101        mutex_unlock(&export->lock);
 102
 103        return ret ? : size;
 104}
 105
 106static ssize_t enable_show(struct device *child,
 107                           struct device_attribute *attr,
 108                           char *buf)
 109{
 110        const struct pwm_device *pwm = child_to_pwm_device(child);
 111        struct pwm_state state;
 112
 113        pwm_get_state(pwm, &state);
 114
 115        return sprintf(buf, "%d\n", state.enabled);
 116}
 117
 118static ssize_t enable_store(struct device *child,
 119                            struct device_attribute *attr,
 120                            const char *buf, size_t size)
 121{
 122        struct pwm_export *export = child_to_pwm_export(child);
 123        struct pwm_device *pwm = export->pwm;
 124        struct pwm_state state;
 125        int val, ret;
 126
 127        ret = kstrtoint(buf, 0, &val);
 128        if (ret)
 129                return ret;
 130
 131        mutex_lock(&export->lock);
 132
 133        pwm_get_state(pwm, &state);
 134
 135        switch (val) {
 136        case 0:
 137                state.enabled = false;
 138                break;
 139        case 1:
 140                state.enabled = true;
 141                break;
 142        default:
 143                ret = -EINVAL;
 144                goto unlock;
 145        }
 146
 147        ret = pwm_apply_state(pwm, &state);
 148
 149unlock:
 150        mutex_unlock(&export->lock);
 151        return ret ? : size;
 152}
 153
 154static ssize_t polarity_show(struct device *child,
 155                             struct device_attribute *attr,
 156                             char *buf)
 157{
 158        const struct pwm_device *pwm = child_to_pwm_device(child);
 159        const char *polarity = "unknown";
 160        struct pwm_state state;
 161
 162        pwm_get_state(pwm, &state);
 163
 164        switch (state.polarity) {
 165        case PWM_POLARITY_NORMAL:
 166                polarity = "normal";
 167                break;
 168
 169        case PWM_POLARITY_INVERSED:
 170                polarity = "inversed";
 171                break;
 172        }
 173
 174        return sprintf(buf, "%s\n", polarity);
 175}
 176
 177static ssize_t polarity_store(struct device *child,
 178                              struct device_attribute *attr,
 179                              const char *buf, size_t size)
 180{
 181        struct pwm_export *export = child_to_pwm_export(child);
 182        struct pwm_device *pwm = export->pwm;
 183        enum pwm_polarity polarity;
 184        struct pwm_state state;
 185        int ret;
 186
 187        if (sysfs_streq(buf, "normal"))
 188                polarity = PWM_POLARITY_NORMAL;
 189        else if (sysfs_streq(buf, "inversed"))
 190                polarity = PWM_POLARITY_INVERSED;
 191        else
 192                return -EINVAL;
 193
 194        mutex_lock(&export->lock);
 195        pwm_get_state(pwm, &state);
 196        state.polarity = polarity;
 197        ret = pwm_apply_state(pwm, &state);
 198        mutex_unlock(&export->lock);
 199
 200        return ret ? : size;
 201}
 202
 203static ssize_t capture_show(struct device *child,
 204                            struct device_attribute *attr,
 205                            char *buf)
 206{
 207        struct pwm_device *pwm = child_to_pwm_device(child);
 208        struct pwm_capture result;
 209        int ret;
 210
 211        ret = pwm_capture(pwm, &result, jiffies_to_msecs(HZ));
 212        if (ret)
 213                return ret;
 214
 215        return sprintf(buf, "%u %u\n", result.period, result.duty_cycle);
 216}
 217
 218static DEVICE_ATTR_RW(period);
 219static DEVICE_ATTR_RW(duty_cycle);
 220static DEVICE_ATTR_RW(enable);
 221static DEVICE_ATTR_RW(polarity);
 222static DEVICE_ATTR_RO(capture);
 223
 224static struct attribute *pwm_attrs[] = {
 225        &dev_attr_period.attr,
 226        &dev_attr_duty_cycle.attr,
 227        &dev_attr_enable.attr,
 228        &dev_attr_polarity.attr,
 229        &dev_attr_capture.attr,
 230        NULL
 231};
 232ATTRIBUTE_GROUPS(pwm);
 233
 234static void pwm_export_release(struct device *child)
 235{
 236        struct pwm_export *export = child_to_pwm_export(child);
 237
 238        kfree(export);
 239}
 240
 241static int pwm_export_child(struct device *parent, struct pwm_device *pwm)
 242{
 243        struct pwm_export *export;
 244        char *pwm_prop[2];
 245        int ret;
 246
 247        if (test_and_set_bit(PWMF_EXPORTED, &pwm->flags))
 248                return -EBUSY;
 249
 250        export = kzalloc(sizeof(*export), GFP_KERNEL);
 251        if (!export) {
 252                clear_bit(PWMF_EXPORTED, &pwm->flags);
 253                return -ENOMEM;
 254        }
 255
 256        export->pwm = pwm;
 257        mutex_init(&export->lock);
 258
 259        export->child.release = pwm_export_release;
 260        export->child.parent = parent;
 261        export->child.devt = MKDEV(0, 0);
 262        export->child.groups = pwm_groups;
 263        dev_set_name(&export->child, "pwm%u", pwm->hwpwm);
 264
 265        ret = device_register(&export->child);
 266        if (ret) {
 267                clear_bit(PWMF_EXPORTED, &pwm->flags);
 268                put_device(&export->child);
 269                export = NULL;
 270                return ret;
 271        }
 272        pwm_prop[0] = kasprintf(GFP_KERNEL, "EXPORT=pwm%u", pwm->hwpwm);
 273        pwm_prop[1] = NULL;
 274        kobject_uevent_env(&parent->kobj, KOBJ_CHANGE, pwm_prop);
 275        kfree(pwm_prop[0]);
 276
 277        return 0;
 278}
 279
 280static int pwm_unexport_match(struct device *child, void *data)
 281{
 282        return child_to_pwm_device(child) == data;
 283}
 284
 285static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm)
 286{
 287        struct device *child;
 288        char *pwm_prop[2];
 289
 290        if (!test_and_clear_bit(PWMF_EXPORTED, &pwm->flags))
 291                return -ENODEV;
 292
 293        child = device_find_child(parent, pwm, pwm_unexport_match);
 294        if (!child)
 295                return -ENODEV;
 296
 297        pwm_prop[0] = kasprintf(GFP_KERNEL, "UNEXPORT=pwm%u", pwm->hwpwm);
 298        pwm_prop[1] = NULL;
 299        kobject_uevent_env(&parent->kobj, KOBJ_CHANGE, pwm_prop);
 300        kfree(pwm_prop[0]);
 301
 302        /* for device_find_child() */
 303        put_device(child);
 304        device_unregister(child);
 305        pwm_put(pwm);
 306
 307        return 0;
 308}
 309
 310static ssize_t export_store(struct device *parent,
 311                            struct device_attribute *attr,
 312                            const char *buf, size_t len)
 313{
 314        struct pwm_chip *chip = dev_get_drvdata(parent);
 315        struct pwm_device *pwm;
 316        unsigned int hwpwm;
 317        int ret;
 318
 319        ret = kstrtouint(buf, 0, &hwpwm);
 320        if (ret < 0)
 321                return ret;
 322
 323        if (hwpwm >= chip->npwm)
 324                return -ENODEV;
 325
 326        pwm = pwm_request_from_chip(chip, hwpwm, "sysfs");
 327        if (IS_ERR(pwm))
 328                return PTR_ERR(pwm);
 329
 330        ret = pwm_export_child(parent, pwm);
 331        if (ret < 0)
 332                pwm_put(pwm);
 333
 334        return ret ? : len;
 335}
 336static DEVICE_ATTR_WO(export);
 337
 338static ssize_t unexport_store(struct device *parent,
 339                              struct device_attribute *attr,
 340                              const char *buf, size_t len)
 341{
 342        struct pwm_chip *chip = dev_get_drvdata(parent);
 343        unsigned int hwpwm;
 344        int ret;
 345
 346        ret = kstrtouint(buf, 0, &hwpwm);
 347        if (ret < 0)
 348                return ret;
 349
 350        if (hwpwm >= chip->npwm)
 351                return -ENODEV;
 352
 353        ret = pwm_unexport_child(parent, &chip->pwms[hwpwm]);
 354
 355        return ret ? : len;
 356}
 357static DEVICE_ATTR_WO(unexport);
 358
 359static ssize_t npwm_show(struct device *parent, struct device_attribute *attr,
 360                         char *buf)
 361{
 362        const struct pwm_chip *chip = dev_get_drvdata(parent);
 363
 364        return sprintf(buf, "%u\n", chip->npwm);
 365}
 366static DEVICE_ATTR_RO(npwm);
 367
 368static struct attribute *pwm_chip_attrs[] = {
 369        &dev_attr_export.attr,
 370        &dev_attr_unexport.attr,
 371        &dev_attr_npwm.attr,
 372        NULL,
 373};
 374ATTRIBUTE_GROUPS(pwm_chip);
 375
 376/* takes export->lock on success */
 377static struct pwm_export *pwm_class_get_state(struct device *parent,
 378                                              struct pwm_device *pwm,
 379                                              struct pwm_state *state)
 380{
 381        struct device *child;
 382        struct pwm_export *export;
 383
 384        if (!test_bit(PWMF_EXPORTED, &pwm->flags))
 385                return NULL;
 386
 387        child = device_find_child(parent, pwm, pwm_unexport_match);
 388        if (!child)
 389                return NULL;
 390
 391        export = child_to_pwm_export(child);
 392        put_device(child);      /* for device_find_child() */
 393
 394        mutex_lock(&export->lock);
 395        pwm_get_state(pwm, state);
 396
 397        return export;
 398}
 399
 400static int pwm_class_apply_state(struct pwm_export *export,
 401                                 struct pwm_device *pwm,
 402                                 struct pwm_state *state)
 403{
 404        int ret = pwm_apply_state(pwm, state);
 405
 406        /* release lock taken in pwm_class_get_state */
 407        mutex_unlock(&export->lock);
 408
 409        return ret;
 410}
 411
 412static int pwm_class_resume_npwm(struct device *parent, unsigned int npwm)
 413{
 414        struct pwm_chip *chip = dev_get_drvdata(parent);
 415        unsigned int i;
 416        int ret = 0;
 417
 418        for (i = 0; i < npwm; i++) {
 419                struct pwm_device *pwm = &chip->pwms[i];
 420                struct pwm_state state;
 421                struct pwm_export *export;
 422
 423                export = pwm_class_get_state(parent, pwm, &state);
 424                if (!export)
 425                        continue;
 426
 427                state.enabled = export->suspend.enabled;
 428                ret = pwm_class_apply_state(export, pwm, &state);
 429                if (ret < 0)
 430                        break;
 431        }
 432
 433        return ret;
 434}
 435
 436static int __maybe_unused pwm_class_suspend(struct device *parent)
 437{
 438        struct pwm_chip *chip = dev_get_drvdata(parent);
 439        unsigned int i;
 440        int ret = 0;
 441
 442        for (i = 0; i < chip->npwm; i++) {
 443                struct pwm_device *pwm = &chip->pwms[i];
 444                struct pwm_state state;
 445                struct pwm_export *export;
 446
 447                export = pwm_class_get_state(parent, pwm, &state);
 448                if (!export)
 449                        continue;
 450
 451                export->suspend = state;
 452                state.enabled = false;
 453                ret = pwm_class_apply_state(export, pwm, &state);
 454                if (ret < 0) {
 455                        /*
 456                         * roll back the PWM devices that were disabled by
 457                         * this suspend function.
 458                         */
 459                        pwm_class_resume_npwm(parent, i);
 460                        break;
 461                }
 462        }
 463
 464        return ret;
 465}
 466
 467static int __maybe_unused pwm_class_resume(struct device *parent)
 468{
 469        struct pwm_chip *chip = dev_get_drvdata(parent);
 470
 471        return pwm_class_resume_npwm(parent, chip->npwm);
 472}
 473
 474static SIMPLE_DEV_PM_OPS(pwm_class_pm_ops, pwm_class_suspend, pwm_class_resume);
 475
 476static struct class pwm_class = {
 477        .name = "pwm",
 478        .owner = THIS_MODULE,
 479        .dev_groups = pwm_chip_groups,
 480        .pm = &pwm_class_pm_ops,
 481};
 482
 483static int pwmchip_sysfs_match(struct device *parent, const void *data)
 484{
 485        return dev_get_drvdata(parent) == data;
 486}
 487
 488void pwmchip_sysfs_export(struct pwm_chip *chip)
 489{
 490        struct device *parent;
 491
 492        /*
 493         * If device_create() fails the pwm_chip is still usable by
 494         * the kernel it's just not exported.
 495         */
 496        parent = device_create(&pwm_class, chip->dev, MKDEV(0, 0), chip,
 497                               "pwmchip%d", chip->base);
 498        if (IS_ERR(parent)) {
 499                dev_warn(chip->dev,
 500                         "device_create failed for pwm_chip sysfs export\n");
 501        }
 502}
 503
 504void pwmchip_sysfs_unexport(struct pwm_chip *chip)
 505{
 506        struct device *parent;
 507        unsigned int i;
 508
 509        parent = class_find_device(&pwm_class, NULL, chip,
 510                                   pwmchip_sysfs_match);
 511        if (!parent)
 512                return;
 513
 514        for (i = 0; i < chip->npwm; i++) {
 515                struct pwm_device *pwm = &chip->pwms[i];
 516
 517                if (test_bit(PWMF_EXPORTED, &pwm->flags))
 518                        pwm_unexport_child(parent, pwm);
 519        }
 520
 521        put_device(parent);
 522        device_unregister(parent);
 523}
 524
 525static int __init pwm_sysfs_init(void)
 526{
 527        return class_register(&pwm_class);
 528}
 529subsys_initcall(pwm_sysfs_init);
 530