diff options
Diffstat (limited to 'drivers/gpio/gpiolib.c')
| -rw-r--r-- | drivers/gpio/gpiolib.c | 161 |
1 files changed, 149 insertions, 12 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 50de0f5750d8..a25ad284a272 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
| @@ -53,6 +53,7 @@ struct gpio_desc { | |||
| 53 | #define FLAG_SYSFS 4 /* exported via /sys/class/gpio/control */ | 53 | #define FLAG_SYSFS 4 /* exported via /sys/class/gpio/control */ |
| 54 | #define FLAG_TRIG_FALL 5 /* trigger on falling edge */ | 54 | #define FLAG_TRIG_FALL 5 /* trigger on falling edge */ |
| 55 | #define FLAG_TRIG_RISE 6 /* trigger on rising edge */ | 55 | #define FLAG_TRIG_RISE 6 /* trigger on rising edge */ |
| 56 | #define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */ | ||
| 56 | 57 | ||
| 57 | #define PDESC_ID_SHIFT 16 /* add new flags before this one */ | 58 | #define PDESC_ID_SHIFT 16 /* add new flags before this one */ |
| 58 | 59 | ||
| @@ -210,6 +211,11 @@ static DEFINE_MUTEX(sysfs_lock); | |||
| 210 | * * configures behavior of poll(2) on /value | 211 | * * configures behavior of poll(2) on /value |
| 211 | * * available only if pin can generate IRQs on input | 212 | * * available only if pin can generate IRQs on input |
| 212 | * * is read/write as "none", "falling", "rising", or "both" | 213 | * * is read/write as "none", "falling", "rising", or "both" |
| 214 | * /active_low | ||
| 215 | * * configures polarity of /value | ||
| 216 | * * is read/write as zero/nonzero | ||
| 217 | * * also affects existing and subsequent "falling" and "rising" | ||
| 218 | * /edge configuration | ||
| 213 | */ | 219 | */ |
| 214 | 220 | ||
| 215 | static ssize_t gpio_direction_show(struct device *dev, | 221 | static ssize_t gpio_direction_show(struct device *dev, |
| @@ -255,7 +261,7 @@ static ssize_t gpio_direction_store(struct device *dev, | |||
| 255 | return status ? : size; | 261 | return status ? : size; |
| 256 | } | 262 | } |
| 257 | 263 | ||
| 258 | static const DEVICE_ATTR(direction, 0644, | 264 | static /* const */ DEVICE_ATTR(direction, 0644, |
| 259 | gpio_direction_show, gpio_direction_store); | 265 | gpio_direction_show, gpio_direction_store); |
| 260 | 266 | ||
| 261 | static ssize_t gpio_value_show(struct device *dev, | 267 | static ssize_t gpio_value_show(struct device *dev, |
| @@ -267,10 +273,17 @@ static ssize_t gpio_value_show(struct device *dev, | |||
| 267 | 273 | ||
| 268 | mutex_lock(&sysfs_lock); | 274 | mutex_lock(&sysfs_lock); |
| 269 | 275 | ||
| 270 | if (!test_bit(FLAG_EXPORT, &desc->flags)) | 276 | if (!test_bit(FLAG_EXPORT, &desc->flags)) { |
| 271 | status = -EIO; | 277 | status = -EIO; |
| 272 | else | 278 | } else { |
| 273 | status = sprintf(buf, "%d\n", !!gpio_get_value_cansleep(gpio)); | 279 | int value; |
| 280 | |||
| 281 | value = !!gpio_get_value_cansleep(gpio); | ||
| 282 | if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) | ||
| 283 | value = !value; | ||
| 284 | |||
| 285 | status = sprintf(buf, "%d\n", value); | ||
| 286 | } | ||
| 274 | 287 | ||
| 275 | mutex_unlock(&sysfs_lock); | 288 | mutex_unlock(&sysfs_lock); |
| 276 | return status; | 289 | return status; |
| @@ -294,6 +307,8 @@ static ssize_t gpio_value_store(struct device *dev, | |||
| 294 | 307 | ||
| 295 | status = strict_strtol(buf, 0, &value); | 308 | status = strict_strtol(buf, 0, &value); |
| 296 | if (status == 0) { | 309 | if (status == 0) { |
| 310 | if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) | ||
| 311 | value = !value; | ||
| 297 | gpio_set_value_cansleep(gpio, value != 0); | 312 | gpio_set_value_cansleep(gpio, value != 0); |
| 298 | status = size; | 313 | status = size; |
| 299 | } | 314 | } |
| @@ -303,7 +318,7 @@ static ssize_t gpio_value_store(struct device *dev, | |||
| 303 | return status; | 318 | return status; |
| 304 | } | 319 | } |
| 305 | 320 | ||
| 306 | static /*const*/ DEVICE_ATTR(value, 0644, | 321 | static const DEVICE_ATTR(value, 0644, |
| 307 | gpio_value_show, gpio_value_store); | 322 | gpio_value_show, gpio_value_store); |
| 308 | 323 | ||
| 309 | static irqreturn_t gpio_sysfs_irq(int irq, void *priv) | 324 | static irqreturn_t gpio_sysfs_irq(int irq, void *priv) |
| @@ -352,9 +367,11 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev, | |||
| 352 | 367 | ||
| 353 | irq_flags = IRQF_SHARED; | 368 | irq_flags = IRQF_SHARED; |
| 354 | if (test_bit(FLAG_TRIG_FALL, &gpio_flags)) | 369 | if (test_bit(FLAG_TRIG_FALL, &gpio_flags)) |
| 355 | irq_flags |= IRQF_TRIGGER_FALLING; | 370 | irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? |
| 371 | IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING; | ||
| 356 | if (test_bit(FLAG_TRIG_RISE, &gpio_flags)) | 372 | if (test_bit(FLAG_TRIG_RISE, &gpio_flags)) |
| 357 | irq_flags |= IRQF_TRIGGER_RISING; | 373 | irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? |
| 374 | IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; | ||
| 358 | 375 | ||
| 359 | if (!pdesc) { | 376 | if (!pdesc) { |
| 360 | pdesc = kmalloc(sizeof(*pdesc), GFP_KERNEL); | 377 | pdesc = kmalloc(sizeof(*pdesc), GFP_KERNEL); |
| @@ -475,9 +492,79 @@ found: | |||
| 475 | 492 | ||
| 476 | static DEVICE_ATTR(edge, 0644, gpio_edge_show, gpio_edge_store); | 493 | static DEVICE_ATTR(edge, 0644, gpio_edge_show, gpio_edge_store); |
| 477 | 494 | ||
| 495 | static int sysfs_set_active_low(struct gpio_desc *desc, struct device *dev, | ||
| 496 | int value) | ||
| 497 | { | ||
| 498 | int status = 0; | ||
| 499 | |||
| 500 | if (!!test_bit(FLAG_ACTIVE_LOW, &desc->flags) == !!value) | ||
| 501 | return 0; | ||
| 502 | |||
| 503 | if (value) | ||
| 504 | set_bit(FLAG_ACTIVE_LOW, &desc->flags); | ||
| 505 | else | ||
| 506 | clear_bit(FLAG_ACTIVE_LOW, &desc->flags); | ||
| 507 | |||
| 508 | /* reconfigure poll(2) support if enabled on one edge only */ | ||
| 509 | if (dev != NULL && (!!test_bit(FLAG_TRIG_RISE, &desc->flags) ^ | ||
| 510 | !!test_bit(FLAG_TRIG_FALL, &desc->flags))) { | ||
| 511 | unsigned long trigger_flags = desc->flags & GPIO_TRIGGER_MASK; | ||
| 512 | |||
| 513 | gpio_setup_irq(desc, dev, 0); | ||
| 514 | status = gpio_setup_irq(desc, dev, trigger_flags); | ||
| 515 | } | ||
| 516 | |||
| 517 | return status; | ||
| 518 | } | ||
| 519 | |||
| 520 | static ssize_t gpio_active_low_show(struct device *dev, | ||
| 521 | struct device_attribute *attr, char *buf) | ||
| 522 | { | ||
| 523 | const struct gpio_desc *desc = dev_get_drvdata(dev); | ||
| 524 | ssize_t status; | ||
| 525 | |||
| 526 | mutex_lock(&sysfs_lock); | ||
| 527 | |||
| 528 | if (!test_bit(FLAG_EXPORT, &desc->flags)) | ||
| 529 | status = -EIO; | ||
| 530 | else | ||
| 531 | status = sprintf(buf, "%d\n", | ||
| 532 | !!test_bit(FLAG_ACTIVE_LOW, &desc->flags)); | ||
| 533 | |||
| 534 | mutex_unlock(&sysfs_lock); | ||
| 535 | |||
| 536 | return status; | ||
| 537 | } | ||
| 538 | |||
| 539 | static ssize_t gpio_active_low_store(struct device *dev, | ||
| 540 | struct device_attribute *attr, const char *buf, size_t size) | ||
| 541 | { | ||
| 542 | struct gpio_desc *desc = dev_get_drvdata(dev); | ||
| 543 | ssize_t status; | ||
| 544 | |||
| 545 | mutex_lock(&sysfs_lock); | ||
| 546 | |||
| 547 | if (!test_bit(FLAG_EXPORT, &desc->flags)) { | ||
| 548 | status = -EIO; | ||
| 549 | } else { | ||
| 550 | long value; | ||
| 551 | |||
| 552 | status = strict_strtol(buf, 0, &value); | ||
| 553 | if (status == 0) | ||
| 554 | status = sysfs_set_active_low(desc, dev, value != 0); | ||
| 555 | } | ||
| 556 | |||
| 557 | mutex_unlock(&sysfs_lock); | ||
| 558 | |||
| 559 | return status ? : size; | ||
| 560 | } | ||
| 561 | |||
| 562 | static const DEVICE_ATTR(active_low, 0644, | ||
| 563 | gpio_active_low_show, gpio_active_low_store); | ||
| 564 | |||
| 478 | static const struct attribute *gpio_attrs[] = { | 565 | static const struct attribute *gpio_attrs[] = { |
| 479 | &dev_attr_direction.attr, | ||
| 480 | &dev_attr_value.attr, | 566 | &dev_attr_value.attr, |
| 567 | &dev_attr_active_low.attr, | ||
| 481 | NULL, | 568 | NULL, |
| 482 | }; | 569 | }; |
| 483 | 570 | ||
| @@ -662,12 +749,12 @@ int gpio_export(unsigned gpio, bool direction_may_change) | |||
| 662 | dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), | 749 | dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), |
| 663 | desc, ioname ? ioname : "gpio%d", gpio); | 750 | desc, ioname ? ioname : "gpio%d", gpio); |
| 664 | if (!IS_ERR(dev)) { | 751 | if (!IS_ERR(dev)) { |
| 665 | if (direction_may_change) | 752 | status = sysfs_create_group(&dev->kobj, |
| 666 | status = sysfs_create_group(&dev->kobj, | ||
| 667 | &gpio_attr_group); | 753 | &gpio_attr_group); |
| 668 | else | 754 | |
| 755 | if (!status && direction_may_change) | ||
| 669 | status = device_create_file(dev, | 756 | status = device_create_file(dev, |
| 670 | &dev_attr_value); | 757 | &dev_attr_direction); |
| 671 | 758 | ||
| 672 | if (!status && gpio_to_irq(gpio) >= 0 | 759 | if (!status && gpio_to_irq(gpio) >= 0 |
| 673 | && (direction_may_change | 760 | && (direction_may_change |
| @@ -744,6 +831,55 @@ done: | |||
| 744 | } | 831 | } |
| 745 | EXPORT_SYMBOL_GPL(gpio_export_link); | 832 | EXPORT_SYMBOL_GPL(gpio_export_link); |
| 746 | 833 | ||
| 834 | |||
| 835 | /** | ||
| 836 | * gpio_sysfs_set_active_low - set the polarity of gpio sysfs value | ||
| 837 | * @gpio: gpio to change | ||
| 838 | * @value: non-zero to use active low, i.e. inverted values | ||
| 839 | * | ||
| 840 | * Set the polarity of /sys/class/gpio/gpioN/value sysfs attribute. | ||
| 841 | * The GPIO does not have to be exported yet. If poll(2) support has | ||
| 842 | * been enabled for either rising or falling edge, it will be | ||
| 843 | * reconfigured to follow the new polarity. | ||
| 844 | * | ||
| 845 | * Returns zero on success, else an error. | ||
| 846 | */ | ||
| 847 | int gpio_sysfs_set_active_low(unsigned gpio, int value) | ||
| 848 | { | ||
| 849 | struct gpio_desc *desc; | ||
| 850 | struct device *dev = NULL; | ||
| 851 | int status = -EINVAL; | ||
| 852 | |||
| 853 | if (!gpio_is_valid(gpio)) | ||
| 854 | goto done; | ||
| 855 | |||
| 856 | mutex_lock(&sysfs_lock); | ||
| 857 | |||
| 858 | desc = &gpio_desc[gpio]; | ||
| 859 | |||
| 860 | if (test_bit(FLAG_EXPORT, &desc->flags)) { | ||
| 861 | struct device *dev; | ||
| 862 | |||
| 863 | dev = class_find_device(&gpio_class, NULL, desc, match_export); | ||
| 864 | if (dev == NULL) { | ||
| 865 | status = -ENODEV; | ||
| 866 | goto unlock; | ||
| 867 | } | ||
| 868 | } | ||
| 869 | |||
| 870 | status = sysfs_set_active_low(desc, dev, value); | ||
| 871 | |||
| 872 | unlock: | ||
| 873 | mutex_unlock(&sysfs_lock); | ||
| 874 | |||
| 875 | done: | ||
| 876 | if (status) | ||
| 877 | pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); | ||
| 878 | |||
| 879 | return status; | ||
| 880 | } | ||
| 881 | EXPORT_SYMBOL_GPL(gpio_sysfs_set_active_low); | ||
| 882 | |||
| 747 | /** | 883 | /** |
| 748 | * gpio_unexport - reverse effect of gpio_export() | 884 | * gpio_unexport - reverse effect of gpio_export() |
| 749 | * @gpio: gpio to make unavailable | 885 | * @gpio: gpio to make unavailable |
| @@ -1094,6 +1230,7 @@ void gpio_free(unsigned gpio) | |||
| 1094 | } | 1230 | } |
| 1095 | desc_set_label(desc, NULL); | 1231 | desc_set_label(desc, NULL); |
| 1096 | module_put(desc->chip->owner); | 1232 | module_put(desc->chip->owner); |
| 1233 | clear_bit(FLAG_ACTIVE_LOW, &desc->flags); | ||
| 1097 | clear_bit(FLAG_REQUESTED, &desc->flags); | 1234 | clear_bit(FLAG_REQUESTED, &desc->flags); |
| 1098 | } else | 1235 | } else |
| 1099 | WARN_ON(extra_checks); | 1236 | WARN_ON(extra_checks); |
