176abbddeSH Hartley Sweeten /* 276abbddeSH Hartley Sweeten * A simple sysfs interface for the generic PWM framework 376abbddeSH Hartley Sweeten * 476abbddeSH Hartley Sweeten * Copyright (C) 2013 H Hartley Sweeten <hsweeten@visionengravers.com> 576abbddeSH Hartley Sweeten * 676abbddeSH Hartley Sweeten * Based on previous work by Lars Poeschel <poeschel@lemonage.de> 776abbddeSH Hartley Sweeten * 876abbddeSH Hartley Sweeten * This program is free software; you can redistribute it and/or modify 976abbddeSH Hartley Sweeten * it under the terms of the GNU General Public License as published by 1076abbddeSH Hartley Sweeten * the Free Software Foundation; either version 2, or (at your option) 1176abbddeSH Hartley Sweeten * any later version. 1276abbddeSH Hartley Sweeten * 1376abbddeSH Hartley Sweeten * This program is distributed in the hope that it will be useful, 1476abbddeSH Hartley Sweeten * but WITHOUT ANY WARRANTY; without even the implied warranty of 1576abbddeSH Hartley Sweeten * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1676abbddeSH Hartley Sweeten * GNU General Public License for more details. 1776abbddeSH Hartley Sweeten */ 1876abbddeSH Hartley Sweeten 1976abbddeSH Hartley Sweeten #include <linux/device.h> 2076abbddeSH Hartley Sweeten #include <linux/mutex.h> 2176abbddeSH Hartley Sweeten #include <linux/err.h> 2276abbddeSH Hartley Sweeten #include <linux/slab.h> 2376abbddeSH Hartley Sweeten #include <linux/kdev_t.h> 2476abbddeSH Hartley Sweeten #include <linux/pwm.h> 2576abbddeSH Hartley Sweeten 2676abbddeSH Hartley Sweeten struct pwm_export { 2776abbddeSH Hartley Sweeten struct device child; 2876abbddeSH Hartley Sweeten struct pwm_device *pwm; 29459a25afSBoris BREZILLON struct mutex lock; 3076abbddeSH Hartley Sweeten }; 3176abbddeSH Hartley Sweeten 3276abbddeSH Hartley Sweeten static struct pwm_export *child_to_pwm_export(struct device *child) 3376abbddeSH Hartley Sweeten { 3476abbddeSH Hartley Sweeten return container_of(child, struct pwm_export, child); 3576abbddeSH Hartley Sweeten } 3676abbddeSH Hartley Sweeten 3776abbddeSH Hartley Sweeten static struct pwm_device *child_to_pwm_device(struct device *child) 3876abbddeSH Hartley Sweeten { 3976abbddeSH Hartley Sweeten struct pwm_export *export = child_to_pwm_export(child); 4076abbddeSH Hartley Sweeten 4176abbddeSH Hartley Sweeten return export->pwm; 4276abbddeSH Hartley Sweeten } 4376abbddeSH Hartley Sweeten 4465cdc691SOlliver Schinagl static ssize_t period_show(struct device *child, 4576abbddeSH Hartley Sweeten struct device_attribute *attr, 4676abbddeSH Hartley Sweeten char *buf) 4776abbddeSH Hartley Sweeten { 4876abbddeSH Hartley Sweeten const struct pwm_device *pwm = child_to_pwm_device(child); 4939100ceeSBoris Brezillon struct pwm_state state; 5076abbddeSH Hartley Sweeten 5139100ceeSBoris Brezillon pwm_get_state(pwm, &state); 5239100ceeSBoris Brezillon 5339100ceeSBoris Brezillon return sprintf(buf, "%u\n", state.period); 5476abbddeSH Hartley Sweeten } 5576abbddeSH Hartley Sweeten 5665cdc691SOlliver Schinagl static ssize_t period_store(struct device *child, 5776abbddeSH Hartley Sweeten struct device_attribute *attr, 5876abbddeSH Hartley Sweeten const char *buf, size_t size) 5976abbddeSH Hartley Sweeten { 60459a25afSBoris BREZILLON struct pwm_export *export = child_to_pwm_export(child); 61459a25afSBoris BREZILLON struct pwm_device *pwm = export->pwm; 6239100ceeSBoris Brezillon struct pwm_state state; 6376abbddeSH Hartley Sweeten unsigned int val; 6476abbddeSH Hartley Sweeten int ret; 6576abbddeSH Hartley Sweeten 6676abbddeSH Hartley Sweeten ret = kstrtouint(buf, 0, &val); 6776abbddeSH Hartley Sweeten if (ret) 6876abbddeSH Hartley Sweeten return ret; 6976abbddeSH Hartley Sweeten 70459a25afSBoris BREZILLON mutex_lock(&export->lock); 7139100ceeSBoris Brezillon pwm_get_state(pwm, &state); 7239100ceeSBoris Brezillon state.period = val; 7339100ceeSBoris Brezillon ret = pwm_apply_state(pwm, &state); 74459a25afSBoris BREZILLON mutex_unlock(&export->lock); 7576abbddeSH Hartley Sweeten 7676abbddeSH Hartley Sweeten return ret ? : size; 7776abbddeSH Hartley Sweeten } 7876abbddeSH Hartley Sweeten 7965cdc691SOlliver Schinagl static ssize_t duty_cycle_show(struct device *child, 8076abbddeSH Hartley Sweeten struct device_attribute *attr, 8176abbddeSH Hartley Sweeten char *buf) 8276abbddeSH Hartley Sweeten { 8376abbddeSH Hartley Sweeten const struct pwm_device *pwm = child_to_pwm_device(child); 8439100ceeSBoris Brezillon struct pwm_state state; 8576abbddeSH Hartley Sweeten 8639100ceeSBoris Brezillon pwm_get_state(pwm, &state); 8739100ceeSBoris Brezillon 8839100ceeSBoris Brezillon return sprintf(buf, "%u\n", state.duty_cycle); 8976abbddeSH Hartley Sweeten } 9076abbddeSH Hartley Sweeten 9165cdc691SOlliver Schinagl static ssize_t duty_cycle_store(struct device *child, 9276abbddeSH Hartley Sweeten struct device_attribute *attr, 9376abbddeSH Hartley Sweeten const char *buf, size_t size) 9476abbddeSH Hartley Sweeten { 95459a25afSBoris BREZILLON struct pwm_export *export = child_to_pwm_export(child); 96459a25afSBoris BREZILLON struct pwm_device *pwm = export->pwm; 9739100ceeSBoris Brezillon struct pwm_state state; 9876abbddeSH Hartley Sweeten unsigned int val; 9976abbddeSH Hartley Sweeten int ret; 10076abbddeSH Hartley Sweeten 10176abbddeSH Hartley Sweeten ret = kstrtouint(buf, 0, &val); 10276abbddeSH Hartley Sweeten if (ret) 10376abbddeSH Hartley Sweeten return ret; 10476abbddeSH Hartley Sweeten 105459a25afSBoris BREZILLON mutex_lock(&export->lock); 10639100ceeSBoris Brezillon pwm_get_state(pwm, &state); 10739100ceeSBoris Brezillon state.duty_cycle = val; 10839100ceeSBoris Brezillon ret = pwm_apply_state(pwm, &state); 109459a25afSBoris BREZILLON mutex_unlock(&export->lock); 11076abbddeSH Hartley Sweeten 11176abbddeSH Hartley Sweeten return ret ? : size; 11276abbddeSH Hartley Sweeten } 11376abbddeSH Hartley Sweeten 11465cdc691SOlliver Schinagl static ssize_t enable_show(struct device *child, 11576abbddeSH Hartley Sweeten struct device_attribute *attr, 11676abbddeSH Hartley Sweeten char *buf) 11776abbddeSH Hartley Sweeten { 11876abbddeSH Hartley Sweeten const struct pwm_device *pwm = child_to_pwm_device(child); 11939100ceeSBoris Brezillon struct pwm_state state; 12076abbddeSH Hartley Sweeten 12139100ceeSBoris Brezillon pwm_get_state(pwm, &state); 12239100ceeSBoris Brezillon 12339100ceeSBoris Brezillon return sprintf(buf, "%d\n", state.enabled); 12476abbddeSH Hartley Sweeten } 12576abbddeSH Hartley Sweeten 12665cdc691SOlliver Schinagl static ssize_t enable_store(struct device *child, 12776abbddeSH Hartley Sweeten struct device_attribute *attr, 12876abbddeSH Hartley Sweeten const char *buf, size_t size) 12976abbddeSH Hartley Sweeten { 130459a25afSBoris BREZILLON struct pwm_export *export = child_to_pwm_export(child); 131459a25afSBoris BREZILLON struct pwm_device *pwm = export->pwm; 13239100ceeSBoris Brezillon struct pwm_state state; 13376abbddeSH Hartley Sweeten int val, ret; 13476abbddeSH Hartley Sweeten 13576abbddeSH Hartley Sweeten ret = kstrtoint(buf, 0, &val); 13676abbddeSH Hartley Sweeten if (ret) 13776abbddeSH Hartley Sweeten return ret; 13876abbddeSH Hartley Sweeten 139459a25afSBoris BREZILLON mutex_lock(&export->lock); 140459a25afSBoris BREZILLON 14139100ceeSBoris Brezillon pwm_get_state(pwm, &state); 14239100ceeSBoris Brezillon 14376abbddeSH Hartley Sweeten switch (val) { 14476abbddeSH Hartley Sweeten case 0: 14539100ceeSBoris Brezillon state.enabled = false; 14676abbddeSH Hartley Sweeten break; 14776abbddeSH Hartley Sweeten case 1: 14839100ceeSBoris Brezillon state.enabled = true; 14976abbddeSH Hartley Sweeten break; 15076abbddeSH Hartley Sweeten default: 15176abbddeSH Hartley Sweeten ret = -EINVAL; 15239100ceeSBoris Brezillon goto unlock; 15376abbddeSH Hartley Sweeten } 15476abbddeSH Hartley Sweeten 15539100ceeSBoris Brezillon pwm_apply_state(pwm, &state); 156459a25afSBoris BREZILLON 15739100ceeSBoris Brezillon unlock: 15839100ceeSBoris Brezillon mutex_unlock(&export->lock); 15976abbddeSH Hartley Sweeten return ret ? : size; 16076abbddeSH Hartley Sweeten } 16176abbddeSH Hartley Sweeten 16265cdc691SOlliver Schinagl static ssize_t polarity_show(struct device *child, 16376abbddeSH Hartley Sweeten struct device_attribute *attr, 16476abbddeSH Hartley Sweeten char *buf) 16576abbddeSH Hartley Sweeten { 16676abbddeSH Hartley Sweeten const struct pwm_device *pwm = child_to_pwm_device(child); 1675a063d87SThierry Reding const char *polarity = "unknown"; 16839100ceeSBoris Brezillon struct pwm_state state; 16976abbddeSH Hartley Sweeten 17039100ceeSBoris Brezillon pwm_get_state(pwm, &state); 17139100ceeSBoris Brezillon 17239100ceeSBoris Brezillon switch (state.polarity) { 1735a063d87SThierry Reding case PWM_POLARITY_NORMAL: 1745a063d87SThierry Reding polarity = "normal"; 1755a063d87SThierry Reding break; 1765a063d87SThierry Reding 1775a063d87SThierry Reding case PWM_POLARITY_INVERSED: 1785a063d87SThierry Reding polarity = "inversed"; 1795a063d87SThierry Reding break; 1805a063d87SThierry Reding } 1815a063d87SThierry Reding 1825a063d87SThierry Reding return sprintf(buf, "%s\n", polarity); 18376abbddeSH Hartley Sweeten } 18476abbddeSH Hartley Sweeten 18565cdc691SOlliver Schinagl static ssize_t polarity_store(struct device *child, 18676abbddeSH Hartley Sweeten struct device_attribute *attr, 18776abbddeSH Hartley Sweeten const char *buf, size_t size) 18876abbddeSH Hartley Sweeten { 189459a25afSBoris BREZILLON struct pwm_export *export = child_to_pwm_export(child); 190459a25afSBoris BREZILLON struct pwm_device *pwm = export->pwm; 19176abbddeSH Hartley Sweeten enum pwm_polarity polarity; 19239100ceeSBoris Brezillon struct pwm_state state; 19376abbddeSH Hartley Sweeten int ret; 19476abbddeSH Hartley Sweeten 19576abbddeSH Hartley Sweeten if (sysfs_streq(buf, "normal")) 19676abbddeSH Hartley Sweeten polarity = PWM_POLARITY_NORMAL; 19776abbddeSH Hartley Sweeten else if (sysfs_streq(buf, "inversed")) 19876abbddeSH Hartley Sweeten polarity = PWM_POLARITY_INVERSED; 19976abbddeSH Hartley Sweeten else 20076abbddeSH Hartley Sweeten return -EINVAL; 20176abbddeSH Hartley Sweeten 202459a25afSBoris BREZILLON mutex_lock(&export->lock); 20339100ceeSBoris Brezillon pwm_get_state(pwm, &state); 20439100ceeSBoris Brezillon state.polarity = polarity; 20539100ceeSBoris Brezillon ret = pwm_apply_state(pwm, &state); 206459a25afSBoris BREZILLON mutex_unlock(&export->lock); 20776abbddeSH Hartley Sweeten 20876abbddeSH Hartley Sweeten return ret ? : size; 20976abbddeSH Hartley Sweeten } 21076abbddeSH Hartley Sweeten 2111a366fe9SLee Jones static ssize_t capture_show(struct device *child, 2121a366fe9SLee Jones struct device_attribute *attr, 2131a366fe9SLee Jones char *buf) 2141a366fe9SLee Jones { 2151a366fe9SLee Jones struct pwm_device *pwm = child_to_pwm_device(child); 2161a366fe9SLee Jones struct pwm_capture result; 2171a366fe9SLee Jones int ret; 2181a366fe9SLee Jones 2191a366fe9SLee Jones ret = pwm_capture(pwm, &result, jiffies_to_msecs(HZ)); 2201a366fe9SLee Jones if (ret) 2211a366fe9SLee Jones return ret; 2221a366fe9SLee Jones 2231a366fe9SLee Jones return sprintf(buf, "%u %u\n", result.period, result.duty_cycle); 2241a366fe9SLee Jones } 2251a366fe9SLee Jones 22665cdc691SOlliver Schinagl static DEVICE_ATTR_RW(period); 22765cdc691SOlliver Schinagl static DEVICE_ATTR_RW(duty_cycle); 22865cdc691SOlliver Schinagl static DEVICE_ATTR_RW(enable); 22965cdc691SOlliver Schinagl static DEVICE_ATTR_RW(polarity); 2301a366fe9SLee Jones static DEVICE_ATTR_RO(capture); 23176abbddeSH Hartley Sweeten 23276abbddeSH Hartley Sweeten static struct attribute *pwm_attrs[] = { 23376abbddeSH Hartley Sweeten &dev_attr_period.attr, 23476abbddeSH Hartley Sweeten &dev_attr_duty_cycle.attr, 23576abbddeSH Hartley Sweeten &dev_attr_enable.attr, 23676abbddeSH Hartley Sweeten &dev_attr_polarity.attr, 2371a366fe9SLee Jones &dev_attr_capture.attr, 23876abbddeSH Hartley Sweeten NULL 23976abbddeSH Hartley Sweeten }; 2406ca142adSAxel Lin ATTRIBUTE_GROUPS(pwm); 24176abbddeSH Hartley Sweeten 24276abbddeSH Hartley Sweeten static void pwm_export_release(struct device *child) 24376abbddeSH Hartley Sweeten { 24476abbddeSH Hartley Sweeten struct pwm_export *export = child_to_pwm_export(child); 24576abbddeSH Hartley Sweeten 24676abbddeSH Hartley Sweeten kfree(export); 24776abbddeSH Hartley Sweeten } 24876abbddeSH Hartley Sweeten 24976abbddeSH Hartley Sweeten static int pwm_export_child(struct device *parent, struct pwm_device *pwm) 25076abbddeSH Hartley Sweeten { 25176abbddeSH Hartley Sweeten struct pwm_export *export; 25276abbddeSH Hartley Sweeten int ret; 25376abbddeSH Hartley Sweeten 25476abbddeSH Hartley Sweeten if (test_and_set_bit(PWMF_EXPORTED, &pwm->flags)) 25576abbddeSH Hartley Sweeten return -EBUSY; 25676abbddeSH Hartley Sweeten 25776abbddeSH Hartley Sweeten export = kzalloc(sizeof(*export), GFP_KERNEL); 25876abbddeSH Hartley Sweeten if (!export) { 25976abbddeSH Hartley Sweeten clear_bit(PWMF_EXPORTED, &pwm->flags); 26076abbddeSH Hartley Sweeten return -ENOMEM; 26176abbddeSH Hartley Sweeten } 26276abbddeSH Hartley Sweeten 26376abbddeSH Hartley Sweeten export->pwm = pwm; 264459a25afSBoris BREZILLON mutex_init(&export->lock); 26576abbddeSH Hartley Sweeten 26676abbddeSH Hartley Sweeten export->child.release = pwm_export_release; 26776abbddeSH Hartley Sweeten export->child.parent = parent; 26876abbddeSH Hartley Sweeten export->child.devt = MKDEV(0, 0); 2696ca142adSAxel Lin export->child.groups = pwm_groups; 27076abbddeSH Hartley Sweeten dev_set_name(&export->child, "pwm%u", pwm->hwpwm); 27176abbddeSH Hartley Sweeten 27276abbddeSH Hartley Sweeten ret = device_register(&export->child); 27376abbddeSH Hartley Sweeten if (ret) { 27476abbddeSH Hartley Sweeten clear_bit(PWMF_EXPORTED, &pwm->flags); 27576abbddeSH Hartley Sweeten kfree(export); 27676abbddeSH Hartley Sweeten return ret; 27776abbddeSH Hartley Sweeten } 27876abbddeSH Hartley Sweeten 27976abbddeSH Hartley Sweeten return 0; 28076abbddeSH Hartley Sweeten } 28176abbddeSH Hartley Sweeten 28276abbddeSH Hartley Sweeten static int pwm_unexport_match(struct device *child, void *data) 28376abbddeSH Hartley Sweeten { 28476abbddeSH Hartley Sweeten return child_to_pwm_device(child) == data; 28576abbddeSH Hartley Sweeten } 28676abbddeSH Hartley Sweeten 28776abbddeSH Hartley Sweeten static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm) 28876abbddeSH Hartley Sweeten { 28976abbddeSH Hartley Sweeten struct device *child; 29076abbddeSH Hartley Sweeten 29176abbddeSH Hartley Sweeten if (!test_and_clear_bit(PWMF_EXPORTED, &pwm->flags)) 29276abbddeSH Hartley Sweeten return -ENODEV; 29376abbddeSH Hartley Sweeten 29476abbddeSH Hartley Sweeten child = device_find_child(parent, pwm, pwm_unexport_match); 29576abbddeSH Hartley Sweeten if (!child) 29676abbddeSH Hartley Sweeten return -ENODEV; 29776abbddeSH Hartley Sweeten 29876abbddeSH Hartley Sweeten /* for device_find_child() */ 29976abbddeSH Hartley Sweeten put_device(child); 30076abbddeSH Hartley Sweeten device_unregister(child); 30176abbddeSH Hartley Sweeten pwm_put(pwm); 30276abbddeSH Hartley Sweeten 30376abbddeSH Hartley Sweeten return 0; 30476abbddeSH Hartley Sweeten } 30576abbddeSH Hartley Sweeten 30665cdc691SOlliver Schinagl static ssize_t export_store(struct device *parent, 30776abbddeSH Hartley Sweeten struct device_attribute *attr, 30876abbddeSH Hartley Sweeten const char *buf, size_t len) 30976abbddeSH Hartley Sweeten { 31076abbddeSH Hartley Sweeten struct pwm_chip *chip = dev_get_drvdata(parent); 31176abbddeSH Hartley Sweeten struct pwm_device *pwm; 31276abbddeSH Hartley Sweeten unsigned int hwpwm; 31376abbddeSH Hartley Sweeten int ret; 31476abbddeSH Hartley Sweeten 31576abbddeSH Hartley Sweeten ret = kstrtouint(buf, 0, &hwpwm); 31676abbddeSH Hartley Sweeten if (ret < 0) 31776abbddeSH Hartley Sweeten return ret; 31876abbddeSH Hartley Sweeten 31976abbddeSH Hartley Sweeten if (hwpwm >= chip->npwm) 32076abbddeSH Hartley Sweeten return -ENODEV; 32176abbddeSH Hartley Sweeten 32276abbddeSH Hartley Sweeten pwm = pwm_request_from_chip(chip, hwpwm, "sysfs"); 32376abbddeSH Hartley Sweeten if (IS_ERR(pwm)) 32476abbddeSH Hartley Sweeten return PTR_ERR(pwm); 32576abbddeSH Hartley Sweeten 32676abbddeSH Hartley Sweeten ret = pwm_export_child(parent, pwm); 32776abbddeSH Hartley Sweeten if (ret < 0) 32876abbddeSH Hartley Sweeten pwm_put(pwm); 32976abbddeSH Hartley Sweeten 33076abbddeSH Hartley Sweeten return ret ? : len; 33176abbddeSH Hartley Sweeten } 33265cdc691SOlliver Schinagl static DEVICE_ATTR_WO(export); 33376abbddeSH Hartley Sweeten 33465cdc691SOlliver Schinagl static ssize_t unexport_store(struct device *parent, 33576abbddeSH Hartley Sweeten struct device_attribute *attr, 33676abbddeSH Hartley Sweeten const char *buf, size_t len) 33776abbddeSH Hartley Sweeten { 33876abbddeSH Hartley Sweeten struct pwm_chip *chip = dev_get_drvdata(parent); 33976abbddeSH Hartley Sweeten unsigned int hwpwm; 34076abbddeSH Hartley Sweeten int ret; 34176abbddeSH Hartley Sweeten 34276abbddeSH Hartley Sweeten ret = kstrtouint(buf, 0, &hwpwm); 34376abbddeSH Hartley Sweeten if (ret < 0) 34476abbddeSH Hartley Sweeten return ret; 34576abbddeSH Hartley Sweeten 34676abbddeSH Hartley Sweeten if (hwpwm >= chip->npwm) 34776abbddeSH Hartley Sweeten return -ENODEV; 34876abbddeSH Hartley Sweeten 34976abbddeSH Hartley Sweeten ret = pwm_unexport_child(parent, &chip->pwms[hwpwm]); 35076abbddeSH Hartley Sweeten 35176abbddeSH Hartley Sweeten return ret ? : len; 35276abbddeSH Hartley Sweeten } 35365cdc691SOlliver Schinagl static DEVICE_ATTR_WO(unexport); 35476abbddeSH Hartley Sweeten 3559da01759SGreg Kroah-Hartman static ssize_t npwm_show(struct device *parent, struct device_attribute *attr, 35676abbddeSH Hartley Sweeten char *buf) 35776abbddeSH Hartley Sweeten { 35876abbddeSH Hartley Sweeten const struct pwm_chip *chip = dev_get_drvdata(parent); 35976abbddeSH Hartley Sweeten 36076abbddeSH Hartley Sweeten return sprintf(buf, "%u\n", chip->npwm); 36176abbddeSH Hartley Sweeten } 3629da01759SGreg Kroah-Hartman static DEVICE_ATTR_RO(npwm); 36376abbddeSH Hartley Sweeten 3649da01759SGreg Kroah-Hartman static struct attribute *pwm_chip_attrs[] = { 3659da01759SGreg Kroah-Hartman &dev_attr_export.attr, 3669da01759SGreg Kroah-Hartman &dev_attr_unexport.attr, 3679da01759SGreg Kroah-Hartman &dev_attr_npwm.attr, 3689da01759SGreg Kroah-Hartman NULL, 36976abbddeSH Hartley Sweeten }; 3709da01759SGreg Kroah-Hartman ATTRIBUTE_GROUPS(pwm_chip); 37176abbddeSH Hartley Sweeten 37276abbddeSH Hartley Sweeten static struct class pwm_class = { 37376abbddeSH Hartley Sweeten .name = "pwm", 37476abbddeSH Hartley Sweeten .owner = THIS_MODULE, 3759da01759SGreg Kroah-Hartman .dev_groups = pwm_chip_groups, 37676abbddeSH Hartley Sweeten }; 37776abbddeSH Hartley Sweeten 37876abbddeSH Hartley Sweeten static int pwmchip_sysfs_match(struct device *parent, const void *data) 37976abbddeSH Hartley Sweeten { 38076abbddeSH Hartley Sweeten return dev_get_drvdata(parent) == data; 38176abbddeSH Hartley Sweeten } 38276abbddeSH Hartley Sweeten 38376abbddeSH Hartley Sweeten void pwmchip_sysfs_export(struct pwm_chip *chip) 38476abbddeSH Hartley Sweeten { 38576abbddeSH Hartley Sweeten struct device *parent; 38676abbddeSH Hartley Sweeten 38776abbddeSH Hartley Sweeten /* 38876abbddeSH Hartley Sweeten * If device_create() fails the pwm_chip is still usable by 38976abbddeSH Hartley Sweeten * the kernel its just not exported. 39076abbddeSH Hartley Sweeten */ 39176abbddeSH Hartley Sweeten parent = device_create(&pwm_class, chip->dev, MKDEV(0, 0), chip, 39276abbddeSH Hartley Sweeten "pwmchip%d", chip->base); 39376abbddeSH Hartley Sweeten if (IS_ERR(parent)) { 39476abbddeSH Hartley Sweeten dev_warn(chip->dev, 39576abbddeSH Hartley Sweeten "device_create failed for pwm_chip sysfs export\n"); 39676abbddeSH Hartley Sweeten } 39776abbddeSH Hartley Sweeten } 39876abbddeSH Hartley Sweeten 39976abbddeSH Hartley Sweeten void pwmchip_sysfs_unexport(struct pwm_chip *chip) 40076abbddeSH Hartley Sweeten { 40176abbddeSH Hartley Sweeten struct device *parent; 40276abbddeSH Hartley Sweeten 40376abbddeSH Hartley Sweeten parent = class_find_device(&pwm_class, NULL, chip, 40476abbddeSH Hartley Sweeten pwmchip_sysfs_match); 40576abbddeSH Hartley Sweeten if (parent) { 40676abbddeSH Hartley Sweeten /* for class_find_device() */ 40776abbddeSH Hartley Sweeten put_device(parent); 40876abbddeSH Hartley Sweeten device_unregister(parent); 40976abbddeSH Hartley Sweeten } 41076abbddeSH Hartley Sweeten } 41176abbddeSH Hartley Sweeten 41276abbddeSH Hartley Sweeten static int __init pwm_sysfs_init(void) 41376abbddeSH Hartley Sweeten { 41476abbddeSH Hartley Sweeten return class_register(&pwm_class); 41576abbddeSH Hartley Sweeten } 41676abbddeSH Hartley Sweeten subsys_initcall(pwm_sysfs_init); 417