1 /* 2 * A simple sysfs interface for the generic PWM framework 3 * 4 * Copyright (C) 2013 H Hartley Sweeten <hsweeten@visionengravers.com> 5 * 6 * Based on previous work by Lars Poeschel <poeschel@lemonage.de> 7 * 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) 11 * any later version. 12 * 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. 17 */ 18 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> 25 26 struct pwm_export { 27 struct device child; 28 struct pwm_device *pwm; 29 }; 30 31 static struct pwm_export *child_to_pwm_export(struct device *child) 32 { 33 return container_of(child, struct pwm_export, child); 34 } 35 36 static struct pwm_device *child_to_pwm_device(struct device *child) 37 { 38 struct pwm_export *export = child_to_pwm_export(child); 39 40 return export->pwm; 41 } 42 43 static ssize_t period_show(struct device *child, 44 struct device_attribute *attr, 45 char *buf) 46 { 47 const struct pwm_device *pwm = child_to_pwm_device(child); 48 49 return sprintf(buf, "%u\n", pwm_get_period(pwm)); 50 } 51 52 static ssize_t period_store(struct device *child, 53 struct device_attribute *attr, 54 const char *buf, size_t size) 55 { 56 struct pwm_device *pwm = child_to_pwm_device(child); 57 unsigned int val; 58 int ret; 59 60 ret = kstrtouint(buf, 0, &val); 61 if (ret) 62 return ret; 63 64 ret = pwm_config(pwm, pwm_get_duty_cycle(pwm), val); 65 66 return ret ? : size; 67 } 68 69 static ssize_t duty_cycle_show(struct device *child, 70 struct device_attribute *attr, 71 char *buf) 72 { 73 const struct pwm_device *pwm = child_to_pwm_device(child); 74 75 return sprintf(buf, "%u\n", pwm_get_duty_cycle(pwm)); 76 } 77 78 static ssize_t duty_cycle_store(struct device *child, 79 struct device_attribute *attr, 80 const char *buf, size_t size) 81 { 82 struct pwm_device *pwm = child_to_pwm_device(child); 83 unsigned int val; 84 int ret; 85 86 ret = kstrtouint(buf, 0, &val); 87 if (ret) 88 return ret; 89 90 ret = pwm_config(pwm, val, pwm_get_period(pwm)); 91 92 return ret ? : size; 93 } 94 95 static ssize_t enable_show(struct device *child, 96 struct device_attribute *attr, 97 char *buf) 98 { 99 const struct pwm_device *pwm = child_to_pwm_device(child); 100 101 return sprintf(buf, "%d\n", pwm_is_enabled(pwm)); 102 } 103 104 static ssize_t enable_store(struct device *child, 105 struct device_attribute *attr, 106 const char *buf, size_t size) 107 { 108 struct pwm_device *pwm = child_to_pwm_device(child); 109 int val, ret; 110 111 ret = kstrtoint(buf, 0, &val); 112 if (ret) 113 return ret; 114 115 switch (val) { 116 case 0: 117 pwm_disable(pwm); 118 break; 119 case 1: 120 ret = pwm_enable(pwm); 121 break; 122 default: 123 ret = -EINVAL; 124 break; 125 } 126 127 return ret ? : size; 128 } 129 130 static ssize_t polarity_show(struct device *child, 131 struct device_attribute *attr, 132 char *buf) 133 { 134 const struct pwm_device *pwm = child_to_pwm_device(child); 135 const char *polarity = "unknown"; 136 137 switch (pwm_get_polarity(pwm)) { 138 case PWM_POLARITY_NORMAL: 139 polarity = "normal"; 140 break; 141 142 case PWM_POLARITY_INVERSED: 143 polarity = "inversed"; 144 break; 145 } 146 147 return sprintf(buf, "%s\n", polarity); 148 } 149 150 static ssize_t polarity_store(struct device *child, 151 struct device_attribute *attr, 152 const char *buf, size_t size) 153 { 154 struct pwm_device *pwm = child_to_pwm_device(child); 155 enum pwm_polarity polarity; 156 int ret; 157 158 if (sysfs_streq(buf, "normal")) 159 polarity = PWM_POLARITY_NORMAL; 160 else if (sysfs_streq(buf, "inversed")) 161 polarity = PWM_POLARITY_INVERSED; 162 else 163 return -EINVAL; 164 165 ret = pwm_set_polarity(pwm, polarity); 166 167 return ret ? : size; 168 } 169 170 static DEVICE_ATTR_RW(period); 171 static DEVICE_ATTR_RW(duty_cycle); 172 static DEVICE_ATTR_RW(enable); 173 static DEVICE_ATTR_RW(polarity); 174 175 static struct attribute *pwm_attrs[] = { 176 &dev_attr_period.attr, 177 &dev_attr_duty_cycle.attr, 178 &dev_attr_enable.attr, 179 &dev_attr_polarity.attr, 180 NULL 181 }; 182 ATTRIBUTE_GROUPS(pwm); 183 184 static void pwm_export_release(struct device *child) 185 { 186 struct pwm_export *export = child_to_pwm_export(child); 187 188 kfree(export); 189 } 190 191 static int pwm_export_child(struct device *parent, struct pwm_device *pwm) 192 { 193 struct pwm_export *export; 194 int ret; 195 196 if (test_and_set_bit(PWMF_EXPORTED, &pwm->flags)) 197 return -EBUSY; 198 199 export = kzalloc(sizeof(*export), GFP_KERNEL); 200 if (!export) { 201 clear_bit(PWMF_EXPORTED, &pwm->flags); 202 return -ENOMEM; 203 } 204 205 export->pwm = pwm; 206 207 export->child.release = pwm_export_release; 208 export->child.parent = parent; 209 export->child.devt = MKDEV(0, 0); 210 export->child.groups = pwm_groups; 211 dev_set_name(&export->child, "pwm%u", pwm->hwpwm); 212 213 ret = device_register(&export->child); 214 if (ret) { 215 clear_bit(PWMF_EXPORTED, &pwm->flags); 216 kfree(export); 217 return ret; 218 } 219 220 return 0; 221 } 222 223 static int pwm_unexport_match(struct device *child, void *data) 224 { 225 return child_to_pwm_device(child) == data; 226 } 227 228 static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm) 229 { 230 struct device *child; 231 232 if (!test_and_clear_bit(PWMF_EXPORTED, &pwm->flags)) 233 return -ENODEV; 234 235 child = device_find_child(parent, pwm, pwm_unexport_match); 236 if (!child) 237 return -ENODEV; 238 239 /* for device_find_child() */ 240 put_device(child); 241 device_unregister(child); 242 pwm_put(pwm); 243 244 return 0; 245 } 246 247 static ssize_t export_store(struct device *parent, 248 struct device_attribute *attr, 249 const char *buf, size_t len) 250 { 251 struct pwm_chip *chip = dev_get_drvdata(parent); 252 struct pwm_device *pwm; 253 unsigned int hwpwm; 254 int ret; 255 256 ret = kstrtouint(buf, 0, &hwpwm); 257 if (ret < 0) 258 return ret; 259 260 if (hwpwm >= chip->npwm) 261 return -ENODEV; 262 263 pwm = pwm_request_from_chip(chip, hwpwm, "sysfs"); 264 if (IS_ERR(pwm)) 265 return PTR_ERR(pwm); 266 267 ret = pwm_export_child(parent, pwm); 268 if (ret < 0) 269 pwm_put(pwm); 270 271 return ret ? : len; 272 } 273 static DEVICE_ATTR_WO(export); 274 275 static ssize_t unexport_store(struct device *parent, 276 struct device_attribute *attr, 277 const char *buf, size_t len) 278 { 279 struct pwm_chip *chip = dev_get_drvdata(parent); 280 unsigned int hwpwm; 281 int ret; 282 283 ret = kstrtouint(buf, 0, &hwpwm); 284 if (ret < 0) 285 return ret; 286 287 if (hwpwm >= chip->npwm) 288 return -ENODEV; 289 290 ret = pwm_unexport_child(parent, &chip->pwms[hwpwm]); 291 292 return ret ? : len; 293 } 294 static DEVICE_ATTR_WO(unexport); 295 296 static ssize_t npwm_show(struct device *parent, struct device_attribute *attr, 297 char *buf) 298 { 299 const struct pwm_chip *chip = dev_get_drvdata(parent); 300 301 return sprintf(buf, "%u\n", chip->npwm); 302 } 303 static DEVICE_ATTR_RO(npwm); 304 305 static struct attribute *pwm_chip_attrs[] = { 306 &dev_attr_export.attr, 307 &dev_attr_unexport.attr, 308 &dev_attr_npwm.attr, 309 NULL, 310 }; 311 ATTRIBUTE_GROUPS(pwm_chip); 312 313 static struct class pwm_class = { 314 .name = "pwm", 315 .owner = THIS_MODULE, 316 .dev_groups = pwm_chip_groups, 317 }; 318 319 static int pwmchip_sysfs_match(struct device *parent, const void *data) 320 { 321 return dev_get_drvdata(parent) == data; 322 } 323 324 void pwmchip_sysfs_export(struct pwm_chip *chip) 325 { 326 struct device *parent; 327 328 /* 329 * If device_create() fails the pwm_chip is still usable by 330 * the kernel its just not exported. 331 */ 332 parent = device_create(&pwm_class, chip->dev, MKDEV(0, 0), chip, 333 "pwmchip%d", chip->base); 334 if (IS_ERR(parent)) { 335 dev_warn(chip->dev, 336 "device_create failed for pwm_chip sysfs export\n"); 337 } 338 } 339 340 void pwmchip_sysfs_unexport(struct pwm_chip *chip) 341 { 342 struct device *parent; 343 344 parent = class_find_device(&pwm_class, NULL, chip, 345 pwmchip_sysfs_match); 346 if (parent) { 347 /* for class_find_device() */ 348 put_device(parent); 349 device_unregister(parent); 350 } 351 } 352 353 static int __init pwm_sysfs_init(void) 354 { 355 return class_register(&pwm_class); 356 } 357 subsys_initcall(pwm_sysfs_init); 358