summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpio/gpiolib-sysfs.c12
-rw-r--r--drivers/gpio/gpiolib.c257
-rw-r--r--drivers/gpio/gpiolib.h10
3 files changed, 149 insertions, 130 deletions
diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
index de65633471af..c56309491e8b 100644
--- a/drivers/gpio/gpiolib-sysfs.c
+++ b/drivers/gpio/gpiolib-sysfs.c
@@ -180,7 +180,7 @@ static int gpio_sysfs_request_irq(struct device *dev, unsigned char flags)
* Remove this redundant call (along with the corresponding
* unlock) when those drivers have been fixed.
*/
- ret = gpiochip_lock_as_irq(desc->chip, gpio_chip_hwgpio(desc));
+ ret = gpiochip_lock_as_irq(desc->gdev->chip, gpio_chip_hwgpio(desc));
if (ret < 0)
goto err_put_kn;
@@ -194,7 +194,7 @@ static int gpio_sysfs_request_irq(struct device *dev, unsigned char flags)
return 0;
err_unlock:
- gpiochip_unlock_as_irq(desc->chip, gpio_chip_hwgpio(desc));
+ gpiochip_unlock_as_irq(desc->gdev->chip, gpio_chip_hwgpio(desc));
err_put_kn:
sysfs_put(data->value_kn);
@@ -212,7 +212,7 @@ static void gpio_sysfs_free_irq(struct device *dev)
data->irq_flags = 0;
free_irq(data->irq, data);
- gpiochip_unlock_as_irq(desc->chip, gpio_chip_hwgpio(desc));
+ gpiochip_unlock_as_irq(desc->gdev->chip, gpio_chip_hwgpio(desc));
sysfs_put(data->value_kn);
}
@@ -566,8 +566,8 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
return -EINVAL;
}
- chip = desc->chip;
- gdev = chip->gpiodev;
+ gdev = desc->gdev;
+ chip = gdev->chip;
mutex_lock(&sysfs_lock);
@@ -765,7 +765,7 @@ void gpiochip_sysfs_unregister(struct gpio_device *gdev)
/* unregister gpiod class devices owned by sysfs */
for (i = 0; i < chip->ngpio; i++) {
- desc = &chip->gpiodev->descs[i];
+ desc = &gdev->descs[i];
if (test_and_clear_bit(FLAG_SYSFS, &desc->flags))
gpiod_free(desc);
}
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index ff8d55ad790c..0738f9a51633 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -85,10 +85,10 @@ struct gpio_desc *gpio_to_desc(unsigned gpio)
spin_lock_irqsave(&gpio_lock, flags);
list_for_each_entry(gdev, &gpio_devices, list) {
- if (gdev->chip->base <= gpio &&
- gdev->chip->base + gdev->chip->ngpio > gpio) {
+ if (gdev->base <= gpio &&
+ gdev->base + gdev->ngpio > gpio) {
spin_unlock_irqrestore(&gpio_lock, flags);
- return &gdev->descs[gpio - gdev->chip->base];
+ return &gdev->descs[gpio - gdev->base];
}
}
@@ -107,10 +107,12 @@ EXPORT_SYMBOL_GPL(gpio_to_desc);
struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip,
u16 hwnum)
{
- if (hwnum >= chip->ngpio)
+ struct gpio_device *gdev = chip->gpiodev;
+
+ if (hwnum >= gdev->ngpio)
return ERR_PTR(-EINVAL);
- return &chip->gpiodev->descs[hwnum];
+ return &gdev->descs[hwnum];
}
/**
@@ -120,7 +122,7 @@ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip,
*/
int desc_to_gpio(const struct gpio_desc *desc)
{
- return desc->chip->base + (desc - &desc->chip->gpiodev->descs[0]);
+ return desc->gdev->base + (desc - &desc->gdev->descs[0]);
}
EXPORT_SYMBOL_GPL(desc_to_gpio);
@@ -131,7 +133,9 @@ EXPORT_SYMBOL_GPL(desc_to_gpio);
*/
struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)
{
- return desc ? desc->chip : NULL;
+ if (!desc || !desc->gdev || !desc->gdev->chip)
+ return NULL;
+ return desc->gdev->chip;
}
EXPORT_SYMBOL_GPL(gpiod_to_chip);
@@ -143,11 +147,11 @@ static int gpiochip_find_base(int ngpio)
list_for_each_entry_reverse(gdev, &gpio_devices, list) {
/* found a free space? */
- if (gdev->chip->base + gdev->chip->ngpio <= base)
+ if (gdev->base + gdev->ngpio <= base)
break;
else
/* nope, check the space right before the chip */
- base = gdev->chip->base - ngpio;
+ base = gdev->base - ngpio;
}
if (gpio_is_valid(base)) {
@@ -214,14 +218,7 @@ static int gpiodev_add_to_list(struct gpio_device *gdev)
}
list_for_each_entry(iterator, &gpio_devices, list) {
- /*
- * The list may contain dangling GPIO devices with no
- * live chip assigned.
- */
- if (!iterator->chip)
- continue;
- if (iterator->chip->base >=
- gdev->chip->base + gdev->chip->ngpio) {
+ if (iterator->base >= gdev->base + gdev->ngpio) {
/*
* Iterator is the first GPIO chip so there is no
* previous one
@@ -234,8 +231,8 @@ static int gpiodev_add_to_list(struct gpio_device *gdev)
* [base, base + ngpio - 1]) between previous
* and iterator chip.
*/
- if (previous->chip->base + previous->chip->ngpio
- <= gdev->chip->base)
+ if (previous->base + previous->ngpio
+ <= gdev->base)
goto found;
}
}
@@ -249,7 +246,7 @@ static int gpiodev_add_to_list(struct gpio_device *gdev)
*/
iterator = list_last_entry(&gpio_devices, struct gpio_device, list);
- if (iterator->chip->base + iterator->chip->ngpio <= gdev->chip->base) {
+ if (iterator->base + iterator->ngpio <= gdev->base) {
list_add(&gdev->list, &iterator->list);
return 0;
}
@@ -276,15 +273,15 @@ static struct gpio_desc *gpio_name_to_desc(const char * const name)
list_for_each_entry(gdev, &gpio_devices, list) {
int i;
- for (i = 0; i != gdev->chip->ngpio; ++i) {
- struct gpio_desc *gpio = &gdev->descs[i];
+ for (i = 0; i != gdev->ngpio; ++i) {
+ struct gpio_desc *desc = &gdev->descs[i];
- if (!gpio->name || !name)
+ if (!desc->name || !name)
continue;
- if (!strcmp(gpio->name, name)) {
+ if (!strcmp(desc->name, name)) {
spin_unlock_irqrestore(&gpio_lock, flags);
- return gpio;
+ return desc;
}
}
}
@@ -302,6 +299,7 @@ static struct gpio_desc *gpio_name_to_desc(const char * const name)
*/
static int gpiochip_set_desc_names(struct gpio_chip *gc)
{
+ struct gpio_device *gdev = gc->gpiodev;
int i;
if (!gc->names)
@@ -313,14 +311,14 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc)
gpio = gpio_name_to_desc(gc->names[i]);
if (gpio)
- dev_warn(&gc->gpiodev->dev,
+ dev_warn(&gdev->dev,
"Detected name collision for GPIO name '%s'\n",
gc->names[i]);
}
/* Then add all names to the GPIO descriptors */
for (i = 0; i != gc->ngpio; ++i)
- gc->gpiodev->descs[i].name = gc->names[i];
+ gdev->descs[i].name = gc->names[i];
return 0;
}
@@ -344,7 +342,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
strncpy(chipinfo.name, dev_name(&gdev->dev),
sizeof(chipinfo.name));
chipinfo.name[sizeof(chipinfo.name)-1] = '\0';
- chipinfo.lines = chip->ngpio;
+ chipinfo.lines = gdev->ngpio;
if (copy_to_user(ip, &chipinfo, sizeof(chipinfo)))
return -EFAULT;
return 0;
@@ -476,17 +474,24 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
goto err_free_gdev;
}
- /* FIXME: move driver data into gpio_device dev_set_drvdata() */
- chip->data = data;
-
if (chip->ngpio == 0) {
chip_err(chip, "tried to insert a GPIO chip with zero lines\n");
status = -EINVAL;
goto err_free_gdev;
}
+ gdev->ngpio = chip->ngpio;
+ /* FIXME: move driver data into gpio_device dev_set_drvdata() */
+ chip->data = data;
spin_lock_irqsave(&gpio_lock, flags);
+ /*
+ * TODO: this allocates a Linux GPIO number base in the global
+ * GPIO numberspace for this chip. In the long run we want to
+ * get *rid* of this numberspace and use only descriptors, but
+ * it may be a pipe dream. It will not happen before we get rid
+ * of the sysfs interface anyways.
+ */
if (base < 0) {
base = gpiochip_find_base(chip->ngpio);
if (base < 0) {
@@ -494,8 +499,15 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
spin_unlock_irqrestore(&gpio_lock, flags);
goto err_free_gdev;
}
+ /*
+ * TODO: it should not be necessary to reflect the assigned
+ * base outside of the GPIO subsystem. Go over drivers and
+ * see if anyone makes use of this, else drop this and assign
+ * a poison instead.
+ */
chip->base = base;
}
+ gdev->base = base;
status = gpiodev_add_to_list(gdev);
if (status) {
@@ -506,8 +518,7 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
for (i = 0; i < chip->ngpio; i++) {
struct gpio_desc *desc = &gdev->descs[i];
- /* REVISIT: maybe a pointer to gpio_device is better */
- desc->chip = chip;
+ desc->gdev = gdev;
/* REVISIT: most hardware initializes GPIOs as inputs (often
* with pullups enabled) so power usage is minimized. Linux
@@ -563,9 +574,9 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
/* From this point, the .release() function cleans up gpio_device */
gdev->dev.release = gpiodevice_release;
get_device(&gdev->dev);
- pr_debug("%s: registered GPIOs %d to %d on device: %s\n", __func__,
- chip->base, chip->base + chip->ngpio - 1,
- chip->label ? : "generic");
+ pr_debug("%s: registered GPIOs %d to %d on device: %s (%s)\n",
+ __func__, gdev->base, gdev->base + gdev->ngpio - 1,
+ dev_name(&gdev->dev), chip->label ? : "generic");
return 0;
@@ -583,11 +594,11 @@ err_remove_from_list:
spin_unlock_irqrestore(&gpio_lock, flags);
err_free_gdev:
ida_simple_remove(&gpio_ida, gdev->id);
- kfree(gdev);
/* failures here can mean systems won't boot... */
pr_err("%s: GPIOs %d..%d (%s) failed to register\n", __func__,
- chip->base, chip->base + chip->ngpio - 1,
- chip->label ? : "generic");
+ gdev->base, gdev->base + gdev->ngpio - 1,
+ chip->label ? : "generic");
+ kfree(gdev);
return status;
}
EXPORT_SYMBOL_GPL(gpiochip_add_data);
@@ -618,16 +629,15 @@ void gpiochip_remove(struct gpio_chip *chip)
of_gpiochip_remove(chip);
spin_lock_irqsave(&gpio_lock, flags);
- for (i = 0; i < chip->ngpio; i++) {
+ for (i = 0; i < gdev->ngpio; i++) {
desc = &gdev->descs[i];
- desc->chip = NULL;
if (test_bit(FLAG_REQUESTED, &desc->flags))
requested = true;
}
spin_unlock_irqrestore(&gpio_lock, flags);
if (requested)
- dev_crit(&chip->gpiodev->dev,
+ dev_crit(&gdev->dev,
"REMOVING GPIOCHIP WITH GPIOS STILL REQUESTED\n");
/*
@@ -967,7 +977,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {}
*/
int gpiochip_generic_request(struct gpio_chip *chip, unsigned offset)
{
- return pinctrl_request_gpio(chip->base + offset);
+ return pinctrl_request_gpio(chip->gpiodev->base + offset);
}
EXPORT_SYMBOL_GPL(gpiochip_generic_request);
@@ -978,7 +988,7 @@ EXPORT_SYMBOL_GPL(gpiochip_generic_request);
*/
void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset)
{
- pinctrl_free_gpio(chip->base + offset);
+ pinctrl_free_gpio(chip->gpiodev->base + offset);
}
EXPORT_SYMBOL_GPL(gpiochip_generic_free);
@@ -996,6 +1006,7 @@ int gpiochip_add_pingroup_range(struct gpio_chip *chip,
unsigned int gpio_offset, const char *pin_group)
{
struct gpio_pin_range *pin_range;
+ struct gpio_device *gdev = chip->gpiodev;
int ret;
pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL);
@@ -1008,7 +1019,7 @@ int gpiochip_add_pingroup_range(struct gpio_chip *chip,
pin_range->range.id = gpio_offset;
pin_range->range.gc = chip;
pin_range->range.name = chip->label;
- pin_range->range.base = chip->base + gpio_offset;
+ pin_range->range.base = gdev->base + gpio_offset;
pin_range->pctldev = pctldev;
ret = pinctrl_get_group_pins(pctldev, pin_group,
@@ -1045,6 +1056,7 @@ int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
unsigned int npins)
{
struct gpio_pin_range *pin_range;
+ struct gpio_device *gdev = chip->gpiodev;
int ret;
pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL);
@@ -1057,7 +1069,7 @@ int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
pin_range->range.id = gpio_offset;
pin_range->range.gc = chip;
pin_range->range.name = chip->label;
- pin_range->range.base = chip->base + gpio_offset;
+ pin_range->range.base = gdev->base + gpio_offset;
pin_range->range.pin_base = pin_offset;
pin_range->range.npins = npins;
pin_range->pctldev = pinctrl_find_and_add_gpio_range(pinctl_name,
@@ -1104,7 +1116,7 @@ EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges);
*/
static int __gpiod_request(struct gpio_desc *desc, const char *label)
{
- struct gpio_chip *chip = desc->chip;
+ struct gpio_chip *chip = desc->gdev->chip;
int status;
unsigned long flags;
@@ -1153,27 +1165,48 @@ done:
return status;
}
+/*
+ * This descriptor validation needs to be inserted verbatim into each
+ * function taking a descriptor, so we need to use a preprocessor
+ * macro to avoid endless duplication.
+ */
+#define VALIDATE_DESC(desc) do { \
+ if (!desc || !desc->gdev) { \
+ pr_warn("%s: invalid GPIO\n", __func__); \
+ return -EINVAL; \
+ } \
+ if ( !desc->gdev->chip ) { \
+ dev_warn(&desc->gdev->dev, \
+ "%s: backing chip is gone\n", __func__); \
+ return 0; \
+ } } while (0)
+
+#define VALIDATE_DESC_VOID(desc) do { \
+ if (!desc || !desc->gdev) { \
+ pr_warn("%s: invalid GPIO\n", __func__); \
+ return; \
+ } \
+ if (!desc->gdev->chip) { \
+ dev_warn(&desc->gdev->dev, \
+ "%s: backing chip is gone\n", __func__); \
+ return; \
+ } } while (0)
+
+
int gpiod_request(struct gpio_desc *desc, const char *label)
{
int status = -EPROBE_DEFER;
- struct gpio_chip *chip;
-
- if (!desc) {
- pr_warn("%s: invalid GPIO\n", __func__);
- return -EINVAL;
- }
+ struct gpio_device *gdev;
- chip = desc->chip;
- if (!chip)
- goto done;
+ VALIDATE_DESC(desc);
+ gdev = desc->gdev;
- if (try_module_get(chip->gpiodev->owner)) {
+ if (try_module_get(gdev->owner)) {
status = __gpiod_request(desc, label);
if (status < 0)
- module_put(chip->gpiodev->owner);
+ module_put(gdev->owner);
}
-done:
if (status)
gpiod_dbg(desc, "%s: status %d\n", __func__, status);
@@ -1192,7 +1225,7 @@ static bool __gpiod_free(struct gpio_desc *desc)
spin_lock_irqsave(&gpio_lock, flags);
- chip = desc->chip;
+ chip = desc->gdev->chip;
if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) {
if (chip->free) {
spin_unlock_irqrestore(&gpio_lock, flags);
@@ -1216,7 +1249,7 @@ static bool __gpiod_free(struct gpio_desc *desc)
void gpiod_free(struct gpio_desc *desc)
{
if (desc && __gpiod_free(desc))
- module_put(desc->chip->gpiodev->owner);
+ module_put(desc->gdev->owner);
else
WARN_ON(extra_checks);
}
@@ -1293,7 +1326,8 @@ void gpiochip_free_own_desc(struct gpio_desc *desc)
}
EXPORT_SYMBOL_GPL(gpiochip_free_own_desc);
-/* Drivers MUST set GPIO direction before making get/set calls. In
+/*
+ * Drivers MUST set GPIO direction before making get/set calls. In
* some cases this is done in early boot, before IRQs are enabled.
*
* As a rule these aren't called more than once (except for drivers
@@ -1316,12 +1350,9 @@ int gpiod_direction_input(struct gpio_desc *desc)
struct gpio_chip *chip;
int status = -EINVAL;
- if (!desc || !desc->chip) {
- pr_warn("%s: invalid GPIO\n", __func__);
- return -EINVAL;
- }
+ VALIDATE_DESC(desc);
+ chip = desc->gdev->chip;
- chip = desc->chip;
if (!chip->get || !chip->direction_input) {
gpiod_warn(desc,
"%s: missing get() or direction_input() operations\n",
@@ -1360,7 +1391,7 @@ static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value)
if (!value && test_bit(FLAG_OPEN_SOURCE, &desc->flags))
return gpiod_direction_input(desc);
- chip = desc->chip;
+ chip = desc->gdev->chip;
if (!chip->set || !chip->direction_output) {
gpiod_warn(desc,
"%s: missing set() or direction_output() operations\n",
@@ -1389,10 +1420,7 @@ static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value)
*/
int gpiod_direction_output_raw(struct gpio_desc *desc, int value)
{
- if (!desc || !desc->chip) {
- pr_warn("%s: invalid GPIO\n", __func__);
- return -EINVAL;
- }
+ VALIDATE_DESC(desc);
return _gpiod_direction_output_raw(desc, value);
}
EXPORT_SYMBOL_GPL(gpiod_direction_output_raw);
@@ -1411,10 +1439,7 @@ EXPORT_SYMBOL_GPL(gpiod_direction_output_raw);
*/
int gpiod_direction_output(struct gpio_desc *desc, int value)
{
- if (!desc || !desc->chip) {
- pr_warn("%s: invalid GPIO\n", __func__);
- return -EINVAL;
- }
+ VALIDATE_DESC(desc);
if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
value = !value;
return _gpiod_direction_output_raw(desc, value);
@@ -1433,12 +1458,8 @@ int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
{
struct gpio_chip *chip;
- if (!desc || !desc->chip) {
- pr_warn("%s: invalid GPIO\n", __func__);
- return -EINVAL;
- }
-
- chip = desc->chip;
+ VALIDATE_DESC(desc);
+ chip = desc->gdev->chip;
if (!chip->set || !chip->set_debounce) {
gpiod_dbg(desc,
"%s: missing set() or set_debounce() operations\n",
@@ -1458,6 +1479,7 @@ EXPORT_SYMBOL_GPL(gpiod_set_debounce);
*/
int gpiod_is_active_low(const struct gpio_desc *desc)
{
+ VALIDATE_DESC(desc);
return test_bit(FLAG_ACTIVE_LOW, &desc->flags);
}
EXPORT_SYMBOL_GPL(gpiod_is_active_low);
@@ -1490,7 +1512,7 @@ static int _gpiod_get_raw_value(const struct gpio_desc *desc)
int offset;
int value;
- chip = desc->chip;
+ chip = desc->gdev->chip;
offset = gpio_chip_hwgpio(desc);
value = chip->get ? chip->get(chip, offset) : -EIO;
value = value < 0 ? value : !!value;
@@ -1510,10 +1532,9 @@ static int _gpiod_get_raw_value(const struct gpio_desc *desc)
*/
int gpiod_get_raw_value(const struct gpio_desc *desc)
{
- if (!desc)
- return 0;
+ VALIDATE_DESC(desc);
/* Should be using gpio_get_value_cansleep() */
- WARN_ON(desc->chip->can_sleep);
+ WARN_ON(desc->gdev->chip->can_sleep);
return _gpiod_get_raw_value(desc);
}
EXPORT_SYMBOL_GPL(gpiod_get_raw_value);
@@ -1531,10 +1552,10 @@ EXPORT_SYMBOL_GPL(gpiod_get_raw_value);
int gpiod_get_value(const struct gpio_desc *desc)
{
int value;
- if (!desc)
- return 0;
+
+ VALIDATE_DESC(desc);
/* Should be using gpio_get_value_cansleep() */
- WARN_ON(desc->chip->can_sleep);
+ WARN_ON(desc->gdev->chip->can_sleep);
value = _gpiod_get_raw_value(desc);
if (value < 0)
@@ -1555,7 +1576,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_value);
static void _gpio_set_open_drain_value(struct gpio_desc *desc, bool value)
{
int err = 0;
- struct gpio_chip *chip = desc->chip;
+ struct gpio_chip *chip = desc->gdev->chip;
int offset = gpio_chip_hwgpio(desc);
if (value) {
@@ -1582,7 +1603,7 @@ static void _gpio_set_open_drain_value(struct gpio_desc *desc, bool value)
static void _gpio_set_open_source_value(struct gpio_desc *desc, bool value)
{
int err = 0;
- struct gpio_chip *chip = desc->chip;
+ struct gpio_chip *chip = desc->gdev->chip;
int offset = gpio_chip_hwgpio(desc);
if (value) {
@@ -1605,7 +1626,7 @@ static void _gpiod_set_raw_value(struct gpio_desc *desc, bool value)
{
struct gpio_chip *chip;
- chip = desc->chip;
+ chip = desc->gdev->chip;
trace_gpio_value(desc_to_gpio(desc), 0, value);
if (test_bit(FLAG_OPEN_DRAIN, &desc->flags))
_gpio_set_open_drain_value(desc, value);
@@ -1653,7 +1674,7 @@ static void gpiod_set_array_value_priv(bool raw, bool can_sleep,
int i = 0;
while (i < array_size) {
- struct gpio_chip *chip = desc_array[i]->chip;
+ struct gpio_chip *chip = desc_array[i]->gdev->chip;
unsigned long mask[BITS_TO_LONGS(chip->ngpio)];
unsigned long bits[BITS_TO_LONGS(chip->ngpio)];
int count = 0;
@@ -1687,7 +1708,8 @@ static void gpiod_set_array_value_priv(bool raw, bool can_sleep,
count++;
}
i++;
- } while ((i < array_size) && (desc_array[i]->chip == chip));
+ } while ((i < array_size) &&
+ (desc_array[i]->gdev->chip == chip));
/* push collected bits to outputs */
if (count != 0)
gpio_chip_set_multiple(chip, mask, bits);
@@ -1707,10 +1729,9 @@ static void gpiod_set_array_value_priv(bool raw, bool can_sleep,
*/
void gpiod_set_raw_value(struct gpio_desc *desc, int value)
{
- if (!desc)
- return;
+ VALIDATE_DESC_VOID(desc);
/* Should be using gpio_set_value_cansleep() */
- WARN_ON(desc->chip->can_sleep);
+ WARN_ON(desc->gdev->chip->can_sleep);
_gpiod_set_raw_value(desc, value);
}
EXPORT_SYMBOL_GPL(gpiod_set_raw_value);
@@ -1728,10 +1749,9 @@ EXPORT_SYMBOL_GPL(gpiod_set_raw_value);
*/
void gpiod_set_value(struct gpio_desc *desc, int value)
{
- if (!desc)
- return;
+ VALIDATE_DESC_VOID(desc);
/* Should be using gpio_set_value_cansleep() */
- WARN_ON(desc->chip->can_sleep);
+ WARN_ON(desc->gdev->chip->can_sleep);
if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
value = !value;
_gpiod_set_raw_value(desc, value);
@@ -1789,9 +1809,8 @@ EXPORT_SYMBOL_GPL(gpiod_set_array_value);
*/
int gpiod_cansleep(const struct gpio_desc *desc)
{
- if (!desc)
- return 0;
- return desc->chip->can_sleep;
+ VALIDATE_DESC(desc);
+ return desc->gdev->chip->can_sleep;
}
EXPORT_SYMBOL_GPL(gpiod_cansleep);
@@ -1807,9 +1826,8 @@ int gpiod_to_irq(const struct gpio_desc *desc)
struct gpio_chip *chip;
int offset;
- if (!desc)
- return -EINVAL;
- chip = desc->chip;
+ VALIDATE_DESC(desc);
+ chip = desc->gdev->chip;
offset = gpio_chip_hwgpio(desc);
return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO;
}
@@ -1878,8 +1896,7 @@ EXPORT_SYMBOL_GPL(gpiochip_line_is_irq);
int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc)
{
might_sleep_if(extra_checks);
- if (!desc)
- return 0;
+ VALIDATE_DESC(desc);
return _gpiod_get_raw_value(desc);
}
EXPORT_SYMBOL_GPL(gpiod_get_raw_value_cansleep);
@@ -1898,9 +1915,7 @@ int gpiod_get_value_cansleep(const struct gpio_desc *desc)
int value;
might_sleep_if(extra_checks);
- if (!desc)
- return 0;
-
+ VALIDATE_DESC(desc);
value = _gpiod_get_raw_value(desc);
if (value < 0)
return value;
@@ -1925,8 +1940,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_value_cansleep);
void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value)
{
might_sleep_if(extra_checks);
- if (!desc)
- return;
+ VALIDATE_DESC_VOID(desc);
_gpiod_set_raw_value(desc, value);
}
EXPORT_SYMBOL_GPL(gpiod_set_raw_value_cansleep);
@@ -1944,9 +1958,7 @@ EXPORT_SYMBOL_GPL(gpiod_set_raw_value_cansleep);
void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
{
might_sleep_if(extra_checks);
- if (!desc)
- return;
-
+ VALIDATE_DESC_VOID(desc);
if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
value = !value;
_gpiod_set_raw_value(desc, value);
@@ -2669,15 +2681,16 @@ core_initcall(gpiolib_dev_init);
#ifdef CONFIG_DEBUG_FS
-static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+static void gpiolib_dbg_show(struct seq_file *s, struct gpio_device *gdev)
{
unsigned i;
- unsigned gpio = chip->base;
- struct gpio_desc *gdesc = &chip->gpiodev->descs[0];
+ struct gpio_chip *chip = gdev->chip;
+ unsigned gpio = gdev->base;
+ struct gpio_desc *gdesc = &gdev->descs[0];
int is_out;
int is_irq;
- for (i = 0; i < chip->ngpio; i++, gpio++, gdesc++) {
+ for (i = 0; i < gdev->ngpio; i++, gpio++, gdesc++) {
if (!test_bit(FLAG_REQUESTED, &gdesc->flags)) {
if (gdesc->name) {
seq_printf(s, " gpio-%-3d (%-20.20s)\n",
@@ -2756,7 +2769,7 @@ static int gpiolib_seq_show(struct seq_file *s, void *v)
seq_printf(s, "%s%s: GPIOs %d-%d", (char *)s->private,
dev_name(&gdev->dev),
- chip->base, chip->base + chip->ngpio - 1);
+ gdev->base, gdev->base + gdev->ngpio - 1);
parent = chip->parent;
if (parent)
seq_printf(s, ", parent: %s/%s",
@@ -2771,7 +2784,7 @@ static int gpiolib_seq_show(struct seq_file *s, void *v)
if (chip->dbg_show)
chip->dbg_show(s, chip);
else
- gpiolib_dbg_show(s, chip);
+ gpiolib_dbg_show(s, gdev);
return 0;
}
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index 39b8301c98b6..d154984c71d9 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -33,6 +33,10 @@ struct acpi_device;
* @chip: pointer to the corresponding gpiochip, holding static
* data for this device
* @descs: array of ngpio descriptors.
+ * @ngpio: the number of GPIO lines on this GPIO device, equal to the size
+ * of the @descs array.
+ * @base: GPIO base in the DEPRECATED global Linux GPIO numberspace, assigned
+ * at device creation time.
* @list: links gpio_device:s together for traversal
*
* This state container holds most of the runtime variable data
@@ -48,6 +52,8 @@ struct gpio_device {
struct module *owner;
struct gpio_chip *chip;
struct gpio_desc *descs;
+ int base;
+ u16 ngpio;
struct list_head list;
};
@@ -125,7 +131,7 @@ extern struct spinlock gpio_lock;
extern struct list_head gpio_devices;
struct gpio_desc {
- struct gpio_chip *chip;
+ struct gpio_device *gdev;
unsigned long flags;
/* flag symbols are bit numbers */
#define FLAG_REQUESTED 0
@@ -154,7 +160,7 @@ int gpiod_hog(struct gpio_desc *desc, const char *name,
*/
static int __maybe_unused gpio_chip_hwgpio(const struct gpio_desc *desc)
{
- return desc - &desc->chip->gpiodev->descs[0];
+ return desc - &desc->gdev->descs[0];
}
/* With descriptor prefix */