Skip to content

Commit 0769746

Browse files
Jani Nikulatorvalds
authored andcommitted
gpiolib: add support for changing value polarity in sysfs
Drivers may use gpiolib sysfs as part of their public user space interface. The GPIO number and polarity might change from board to board. The gpio_export_link() call can be used to hide the GPIO number from user space. Add support for also hiding the GPIO line polarity changes from user space. Signed-off-by: Jani Nikula <[email protected]> Cc: David Brownell <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 35570ac commit 0769746

File tree

4 files changed

+176
-12
lines changed

4 files changed

+176
-12
lines changed

Documentation/gpio.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,13 @@ and have the following read/write attributes:
531531
This file exists only if the pin can be configured as an
532532
interrupt generating input pin.
533533

534+
"active_low" ... reads as either 0 (false) or 1 (true). Write
535+
any nonzero value to invert the value attribute both
536+
for reading and writing. Existing and subsequent
537+
poll(2) support configuration via the edge attribute
538+
for "rising" and "falling" edges will follow this
539+
setting.
540+
534541
GPIO controllers have paths like /sys/class/gpio/gpiochip42/ (for the
535542
controller implementing GPIOs starting at #42) and have the following
536543
read-only attributes:
@@ -566,6 +573,8 @@ requested using gpio_request():
566573
int gpio_export_link(struct device *dev, const char *name,
567574
unsigned gpio)
568575

576+
/* change the polarity of a GPIO node in sysfs */
577+
int gpio_sysfs_set_active_low(unsigned gpio, int value);
569578

570579
After a kernel driver requests a GPIO, it may only be made available in
571580
the sysfs interface by gpio_export(). The driver can control whether the
@@ -580,3 +589,9 @@ After the GPIO has been exported, gpio_export_link() allows creating
580589
symlinks from elsewhere in sysfs to the GPIO sysfs node. Drivers can
581590
use this to provide the interface under their own device in sysfs with
582591
a descriptive name.
592+
593+
Drivers can use gpio_sysfs_set_active_low() to hide GPIO line polarity
594+
differences between boards from user space. This only affects the
595+
sysfs interface. Polarity change can be done both before and after
596+
gpio_export(), and previously enabled poll(2) support for either
597+
rising or falling edge will be reconfigured to follow this setting.

drivers/gpio/gpiolib.c

Lines changed: 149 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ struct gpio_desc {
5353
#define FLAG_SYSFS 4 /* exported via /sys/class/gpio/control */
5454
#define FLAG_TRIG_FALL 5 /* trigger on falling edge */
5555
#define FLAG_TRIG_RISE 6 /* trigger on rising edge */
56+
#define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */
5657

5758
#define PDESC_ID_SHIFT 16 /* add new flags before this one */
5859

@@ -210,6 +211,11 @@ static DEFINE_MUTEX(sysfs_lock);
210211
* * configures behavior of poll(2) on /value
211212
* * available only if pin can generate IRQs on input
212213
* * 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
213219
*/
214220

215221
static ssize_t gpio_direction_show(struct device *dev,
@@ -255,7 +261,7 @@ static ssize_t gpio_direction_store(struct device *dev,
255261
return status ? : size;
256262
}
257263

258-
static const DEVICE_ATTR(direction, 0644,
264+
static /* const */ DEVICE_ATTR(direction, 0644,
259265
gpio_direction_show, gpio_direction_store);
260266

261267
static ssize_t gpio_value_show(struct device *dev,
@@ -267,10 +273,17 @@ static ssize_t gpio_value_show(struct device *dev,
267273

268274
mutex_lock(&sysfs_lock);
269275

270-
if (!test_bit(FLAG_EXPORT, &desc->flags))
276+
if (!test_bit(FLAG_EXPORT, &desc->flags)) {
271277
status = -EIO;
272-
else
273-
status = sprintf(buf, "%d\n", !!gpio_get_value_cansleep(gpio));
278+
} else {
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+
}
274287

275288
mutex_unlock(&sysfs_lock);
276289
return status;
@@ -294,6 +307,8 @@ static ssize_t gpio_value_store(struct device *dev,
294307

295308
status = strict_strtol(buf, 0, &value);
296309
if (status == 0) {
310+
if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
311+
value = !value;
297312
gpio_set_value_cansleep(gpio, value != 0);
298313
status = size;
299314
}
@@ -303,7 +318,7 @@ static ssize_t gpio_value_store(struct device *dev,
303318
return status;
304319
}
305320

306-
static /*const*/ DEVICE_ATTR(value, 0644,
321+
static const DEVICE_ATTR(value, 0644,
307322
gpio_value_show, gpio_value_store);
308323

309324
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,
352367

353368
irq_flags = IRQF_SHARED;
354369
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;
356372
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;
358375

359376
if (!pdesc) {
360377
pdesc = kmalloc(sizeof(*pdesc), GFP_KERNEL);
@@ -475,9 +492,79 @@ static ssize_t gpio_edge_store(struct device *dev,
475492

476493
static DEVICE_ATTR(edge, 0644, gpio_edge_show, gpio_edge_store);
477494

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+
478565
static const struct attribute *gpio_attrs[] = {
479-
&dev_attr_direction.attr,
480566
&dev_attr_value.attr,
567+
&dev_attr_active_low.attr,
481568
NULL,
482569
};
483570

@@ -662,12 +749,12 @@ int gpio_export(unsigned gpio, bool direction_may_change)
662749
dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
663750
desc, ioname ? ioname : "gpio%d", gpio);
664751
if (!IS_ERR(dev)) {
665-
if (direction_may_change)
666-
status = sysfs_create_group(&dev->kobj,
752+
status = sysfs_create_group(&dev->kobj,
667753
&gpio_attr_group);
668-
else
754+
755+
if (!status && direction_may_change)
669756
status = device_create_file(dev,
670-
&dev_attr_value);
757+
&dev_attr_direction);
671758

672759
if (!status && gpio_to_irq(gpio) >= 0
673760
&& (direction_may_change
@@ -744,6 +831,55 @@ int gpio_export_link(struct device *dev, const char *name, unsigned gpio)
744831
}
745832
EXPORT_SYMBOL_GPL(gpio_export_link);
746833

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+
747883
/**
748884
* gpio_unexport - reverse effect of gpio_export()
749885
* @gpio: gpio to make unavailable
@@ -1094,6 +1230,7 @@ void gpio_free(unsigned gpio)
10941230
}
10951231
desc_set_label(desc, NULL);
10961232
module_put(desc->chip->owner);
1233+
clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
10971234
clear_bit(FLAG_REQUESTED, &desc->flags);
10981235
} else
10991236
WARN_ON(extra_checks);

include/asm-generic/gpio.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ extern int __gpio_to_irq(unsigned gpio);
145145
extern int gpio_export(unsigned gpio, bool direction_may_change);
146146
extern int gpio_export_link(struct device *dev, const char *name,
147147
unsigned gpio);
148+
extern int gpio_sysfs_set_active_low(unsigned gpio, int value);
148149
extern void gpio_unexport(unsigned gpio);
149150

150151
#endif /* CONFIG_GPIO_SYSFS */
@@ -197,6 +198,11 @@ static inline int gpio_export_link(struct device *dev, const char *name,
197198
return -ENOSYS;
198199
}
199200

201+
static inline int gpio_sysfs_set_active_low(unsigned gpio, int value)
202+
{
203+
return -ENOSYS;
204+
}
205+
200206
static inline void gpio_unexport(unsigned gpio)
201207
{
202208
}

include/linux/gpio.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ static inline int gpio_export_link(struct device *dev, const char *name,
9999
return -EINVAL;
100100
}
101101

102+
static inline int gpio_sysfs_set_active_low(unsigned gpio, int value)
103+
{
104+
/* GPIO can never have been requested */
105+
WARN_ON(1);
106+
return -EINVAL;
107+
}
102108

103109
static inline void gpio_unexport(unsigned gpio)
104110
{

0 commit comments

Comments
 (0)