diff options
Diffstat (limited to 'drivers/gpio/gpiolib.c')
| -rw-r--r-- | drivers/gpio/gpiolib.c | 759 | 
1 files changed, 451 insertions, 308 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5359ca78130..4828fe7c66c 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3,6 +3,7 @@  #include <linux/interrupt.h>  #include <linux/irq.h>  #include <linux/spinlock.h> +#include <linux/list.h>  #include <linux/device.h>  #include <linux/err.h>  #include <linux/debugfs.h> @@ -52,14 +53,13 @@ struct gpio_desc {  /* flag symbols are bit numbers */  #define FLAG_REQUESTED	0  #define FLAG_IS_OUT	1 -#define FLAG_RESERVED	2 -#define FLAG_EXPORT	3	/* protected by sysfs_lock */ -#define FLAG_SYSFS	4	/* exported via /sys/class/gpio/control */ -#define FLAG_TRIG_FALL	5	/* trigger on falling edge */ -#define FLAG_TRIG_RISE	6	/* trigger on rising edge */ -#define FLAG_ACTIVE_LOW	7	/* sysfs value has active low */ -#define FLAG_OPEN_DRAIN	8	/* Gpio is open drain type */ -#define FLAG_OPEN_SOURCE 9	/* Gpio is open source type */ +#define FLAG_EXPORT	2	/* protected by sysfs_lock */ +#define FLAG_SYSFS	3	/* exported via /sys/class/gpio/control */ +#define FLAG_TRIG_FALL	4	/* trigger on falling edge */ +#define FLAG_TRIG_RISE	5	/* trigger on rising edge */ +#define FLAG_ACTIVE_LOW	6	/* sysfs value has active low */ +#define FLAG_OPEN_DRAIN	7	/* Gpio is open drain type */ +#define FLAG_OPEN_SOURCE 8	/* Gpio is open source type */  #define ID_SHIFT	16	/* add new flags before this one */ @@ -72,10 +72,36 @@ struct gpio_desc {  };  static struct gpio_desc gpio_desc[ARCH_NR_GPIOS]; +#define GPIO_OFFSET_VALID(chip, offset) (offset >= 0 && offset < chip->ngpio) + +static LIST_HEAD(gpio_chips); +  #ifdef CONFIG_GPIO_SYSFS  static DEFINE_IDR(dirent_idr);  #endif +/* + * Internal gpiod_* API using descriptors instead of the integer namespace. + * Most of this should eventually go public. + */ +static int gpiod_request(struct gpio_desc *desc, const char *label); +static void gpiod_free(struct gpio_desc *desc); +static int gpiod_direction_input(struct gpio_desc *desc); +static int gpiod_direction_output(struct gpio_desc *desc, int value); +static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce); +static int gpiod_get_value_cansleep(struct gpio_desc *desc); +static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value); +static int gpiod_get_value(struct gpio_desc *desc); +static void gpiod_set_value(struct gpio_desc *desc, int value); +static int gpiod_cansleep(struct gpio_desc *desc); +static int gpiod_to_irq(struct gpio_desc *desc); +static int gpiod_export(struct gpio_desc *desc, bool direction_may_change); +static int gpiod_export_link(struct device *dev, const char *name, +			     struct gpio_desc *desc); +static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value); +static void gpiod_unexport(struct gpio_desc *desc); + +  static inline void desc_set_label(struct gpio_desc *d, const char *label)  {  #ifdef CONFIG_DEBUG_FS @@ -83,6 +109,36 @@ static inline void desc_set_label(struct gpio_desc *d, const char *label)  #endif  } +/* + * Return the GPIO number of the passed descriptor relative to its chip + */ +static int gpio_chip_hwgpio(const struct gpio_desc *desc) +{ +	return desc - &desc->chip->desc[0]; +} + +/** + * Convert a GPIO number to its descriptor + */ +static struct gpio_desc *gpio_to_desc(unsigned gpio) +{ +	if (WARN(!gpio_is_valid(gpio), "invalid GPIO %d\n", gpio)) +		return NULL; +	else +		return &gpio_desc[gpio]; +} + +/** + * Convert a GPIO descriptor to the integer namespace. + * This should disappear in the future but is needed since we still + * use GPIO numbers for error messages and sysfs nodes + */ +static int desc_to_gpio(const struct gpio_desc *desc) +{ +	return desc->chip->base + gpio_chip_hwgpio(desc); +} + +  /* Warn when drivers omit gpio_request() calls -- legal but ill-advised   * when setting direction, and otherwise illegal.  Until board setup code   * and drivers use explicit requests everywhere (which won't happen when @@ -94,10 +150,10 @@ static inline void desc_set_label(struct gpio_desc *d, const char *label)   * only "legal" in the sense that (old) code using it won't break yet,   * but instead only triggers a WARN() stack dump.   */ -static int gpio_ensure_requested(struct gpio_desc *desc, unsigned offset) +static int gpio_ensure_requested(struct gpio_desc *desc)  {  	const struct gpio_chip *chip = desc->chip; -	const int gpio = chip->base + offset; +	const int gpio = desc_to_gpio(desc);  	if (WARN(test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0,  			"autorequest GPIO-%d\n", gpio)) { @@ -116,95 +172,54 @@ static int gpio_ensure_requested(struct gpio_desc *desc, unsigned offset)  }  /* caller holds gpio_lock *OR* gpio is marked as requested */ +static struct gpio_chip *gpiod_to_chip(struct gpio_desc *desc) +{ +	return desc->chip; +} +  struct gpio_chip *gpio_to_chip(unsigned gpio)  { -	return gpio_desc[gpio].chip; +	return gpiod_to_chip(gpio_to_desc(gpio));  }  /* dynamic allocation of GPIOs, e.g. on a hotplugged device */  static int gpiochip_find_base(int ngpio)  { -	int i; -	int spare = 0; -	int base = -ENOSPC; - -	for (i = ARCH_NR_GPIOS - 1; i >= 0 ; i--) { -		struct gpio_desc *desc = &gpio_desc[i]; -		struct gpio_chip *chip = desc->chip; +	struct gpio_chip *chip; +	int base = ARCH_NR_GPIOS - ngpio; -		if (!chip && !test_bit(FLAG_RESERVED, &desc->flags)) { -			spare++; -			if (spare == ngpio) { -				base = i; -				break; -			} -		} else { -			spare = 0; -			if (chip) -				i -= chip->ngpio - 1; -		} +	list_for_each_entry_reverse(chip, &gpio_chips, list) { +		/* found a free space? */ +		if (chip->base + chip->ngpio <= base) +			break; +		else +			/* nope, check the space right before the chip */ +			base = chip->base - ngpio;  	} -	if (gpio_is_valid(base)) +	if (gpio_is_valid(base)) {  		pr_debug("%s: found new base at %d\n", __func__, base); -	return base; -} - -/** - * gpiochip_reserve() - reserve range of gpios to use with platform code only - * @start: starting gpio number - * @ngpio: number of gpios to reserve - * Context: platform init, potentially before irqs or kmalloc will work - * - * Returns a negative errno if any gpio within the range is already reserved - * or registered, else returns zero as a success code.  Use this function - * to mark a range of gpios as unavailable for dynamic gpio number allocation, - * for example because its driver support is not yet loaded. - */ -int __init gpiochip_reserve(int start, int ngpio) -{ -	int ret = 0; -	unsigned long flags; -	int i; - -	if (!gpio_is_valid(start) || !gpio_is_valid(start + ngpio - 1)) -		return -EINVAL; - -	spin_lock_irqsave(&gpio_lock, flags); - -	for (i = start; i < start + ngpio; i++) { -		struct gpio_desc *desc = &gpio_desc[i]; - -		if (desc->chip || test_bit(FLAG_RESERVED, &desc->flags)) { -			ret = -EBUSY; -			goto err; -		} - -		set_bit(FLAG_RESERVED, &desc->flags); +		return base; +	} else { +		pr_err("%s: cannot find free range\n", __func__); +		return -ENOSPC;  	} - -	pr_debug("%s: reserved gpios from %d to %d\n", -		 __func__, start, start + ngpio - 1); -err: -	spin_unlock_irqrestore(&gpio_lock, flags); - -	return ret;  }  /* caller ensures gpio is valid and requested, chip->get_direction may sleep  */ -static int gpio_get_direction(unsigned gpio) +static int gpiod_get_direction(struct gpio_desc *desc)  {  	struct gpio_chip	*chip; -	struct gpio_desc	*desc = &gpio_desc[gpio]; +	unsigned		offset;  	int			status = -EINVAL; -	chip = gpio_to_chip(gpio); -	gpio -= chip->base; +	chip = gpiod_to_chip(desc); +	offset = gpio_chip_hwgpio(desc);  	if (!chip->get_direction)  		return status; -	status = chip->get_direction(chip, gpio); +	status = chip->get_direction(chip, offset);  	if (status > 0) {  		/* GPIOF_DIR_IN, or other positive */  		status = 1; @@ -248,19 +263,19 @@ static DEFINE_MUTEX(sysfs_lock);  static ssize_t gpio_direction_show(struct device *dev,  		struct device_attribute *attr, char *buf)  { -	const struct gpio_desc	*desc = dev_get_drvdata(dev); -	unsigned		gpio = desc - gpio_desc; +	struct gpio_desc	*desc = dev_get_drvdata(dev);  	ssize_t			status;  	mutex_lock(&sysfs_lock); -	if (!test_bit(FLAG_EXPORT, &desc->flags)) +	if (!test_bit(FLAG_EXPORT, &desc->flags)) {  		status = -EIO; -	else -		gpio_get_direction(gpio); +	} else { +		gpiod_get_direction(desc);  		status = sprintf(buf, "%s\n",  			test_bit(FLAG_IS_OUT, &desc->flags)  				? "out" : "in"); +	}  	mutex_unlock(&sysfs_lock);  	return status; @@ -269,8 +284,7 @@ static ssize_t gpio_direction_show(struct device *dev,  static ssize_t gpio_direction_store(struct device *dev,  		struct device_attribute *attr, const char *buf, size_t size)  { -	const struct gpio_desc	*desc = dev_get_drvdata(dev); -	unsigned		gpio = desc - gpio_desc; +	struct gpio_desc	*desc = dev_get_drvdata(dev);  	ssize_t			status;  	mutex_lock(&sysfs_lock); @@ -278,11 +292,11 @@ static ssize_t gpio_direction_store(struct device *dev,  	if (!test_bit(FLAG_EXPORT, &desc->flags))  		status = -EIO;  	else if (sysfs_streq(buf, "high")) -		status = gpio_direction_output(gpio, 1); +		status = gpiod_direction_output(desc, 1);  	else if (sysfs_streq(buf, "out") || sysfs_streq(buf, "low")) -		status = gpio_direction_output(gpio, 0); +		status = gpiod_direction_output(desc, 0);  	else if (sysfs_streq(buf, "in")) -		status = gpio_direction_input(gpio); +		status = gpiod_direction_input(desc);  	else  		status = -EINVAL; @@ -296,8 +310,7 @@ static /* const */ DEVICE_ATTR(direction, 0644,  static ssize_t gpio_value_show(struct device *dev,  		struct device_attribute *attr, char *buf)  { -	const struct gpio_desc	*desc = dev_get_drvdata(dev); -	unsigned		gpio = desc - gpio_desc; +	struct gpio_desc	*desc = dev_get_drvdata(dev);  	ssize_t			status;  	mutex_lock(&sysfs_lock); @@ -307,7 +320,7 @@ static ssize_t gpio_value_show(struct device *dev,  	} else {  		int value; -		value = !!gpio_get_value_cansleep(gpio); +		value = !!gpiod_get_value_cansleep(desc);  		if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))  			value = !value; @@ -321,8 +334,7 @@ static ssize_t gpio_value_show(struct device *dev,  static ssize_t gpio_value_store(struct device *dev,  		struct device_attribute *attr, const char *buf, size_t size)  { -	const struct gpio_desc	*desc = dev_get_drvdata(dev); -	unsigned		gpio = desc - gpio_desc; +	struct gpio_desc	*desc = dev_get_drvdata(dev);  	ssize_t			status;  	mutex_lock(&sysfs_lock); @@ -338,7 +350,7 @@ static ssize_t gpio_value_store(struct device *dev,  		if (status == 0) {  			if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))  				value = !value; -			gpio_set_value_cansleep(gpio, value != 0); +			gpiod_set_value_cansleep(desc, value != 0);  			status = size;  		}  	} @@ -368,7 +380,7 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,  	if ((desc->flags & GPIO_TRIGGER_MASK) == gpio_flags)  		return 0; -	irq = gpio_to_irq(desc - gpio_desc); +	irq = gpiod_to_irq(desc);  	if (irq < 0)  		return -EIO; @@ -638,29 +650,32 @@ static ssize_t export_store(struct class *class,  				struct class_attribute *attr,  				const char *buf, size_t len)  { -	long	gpio; -	int	status; +	long			gpio; +	struct gpio_desc	*desc; +	int			status;  	status = strict_strtol(buf, 0, &gpio);  	if (status < 0)  		goto done; +	desc = gpio_to_desc(gpio); +  	/* No extra locking here; FLAG_SYSFS just signifies that the  	 * request and export were done by on behalf of userspace, so  	 * they may be undone on its behalf too.  	 */ -	status = gpio_request(gpio, "sysfs"); +	status = gpiod_request(desc, "sysfs");  	if (status < 0) {  		if (status == -EPROBE_DEFER)  			status = -ENODEV;  		goto done;  	} -	status = gpio_export(gpio, true); +	status = gpiod_export(desc, true);  	if (status < 0) -		gpio_free(gpio); +		gpiod_free(desc);  	else -		set_bit(FLAG_SYSFS, &gpio_desc[gpio].flags); +		set_bit(FLAG_SYSFS, &desc->flags);  done:  	if (status) @@ -672,8 +687,9 @@ static ssize_t unexport_store(struct class *class,  				struct class_attribute *attr,  				const char *buf, size_t len)  { -	long	gpio; -	int	status; +	long			gpio; +	struct gpio_desc	*desc; +	int			status;  	status = strict_strtol(buf, 0, &gpio);  	if (status < 0) @@ -681,17 +697,18 @@ static ssize_t unexport_store(struct class *class,  	status = -EINVAL; +	desc = gpio_to_desc(gpio);  	/* reject bogus commands (gpio_unexport ignores them) */ -	if (!gpio_is_valid(gpio)) +	if (!desc)  		goto done;  	/* No extra locking here; FLAG_SYSFS just signifies that the  	 * request and export were done by on behalf of userspace, so  	 * they may be undone on its behalf too.  	 */ -	if (test_and_clear_bit(FLAG_SYSFS, &gpio_desc[gpio].flags)) { +	if (test_and_clear_bit(FLAG_SYSFS, &desc->flags)) {  		status = 0; -		gpio_free(gpio); +		gpiod_free(desc);  	}  done:  	if (status) @@ -728,13 +745,13 @@ static struct class gpio_class = {   *   * Returns zero on success, else an error.   */ -int gpio_export(unsigned gpio, bool direction_may_change) +static int gpiod_export(struct gpio_desc *desc, bool direction_may_change)  {  	unsigned long		flags; -	struct gpio_desc	*desc;  	int			status;  	const char		*ioname = NULL;  	struct device		*dev; +	int			offset;  	/* can't export until sysfs is available ... */  	if (!gpio_class.p) { @@ -742,20 +759,19 @@ int gpio_export(unsigned gpio, bool direction_may_change)  		return -ENOENT;  	} -	if (!gpio_is_valid(gpio)) { -		pr_debug("%s: gpio %d is not valid\n", __func__, gpio); +	if (!desc) { +		pr_debug("%s: invalid gpio descriptor\n", __func__);  		return -EINVAL;  	}  	mutex_lock(&sysfs_lock);  	spin_lock_irqsave(&gpio_lock, flags); -	desc = &gpio_desc[gpio];  	if (!test_bit(FLAG_REQUESTED, &desc->flags) ||  	     test_bit(FLAG_EXPORT, &desc->flags)) {  		spin_unlock_irqrestore(&gpio_lock, flags);  		pr_debug("%s: gpio %d unavailable (requested=%d, exported=%d)\n", -				__func__, gpio, +				__func__, desc_to_gpio(desc),  				test_bit(FLAG_REQUESTED, &desc->flags),  				test_bit(FLAG_EXPORT, &desc->flags));  		status = -EPERM; @@ -766,11 +782,13 @@ int gpio_export(unsigned gpio, bool direction_may_change)  		direction_may_change = false;  	spin_unlock_irqrestore(&gpio_lock, flags); -	if (desc->chip->names && desc->chip->names[gpio - desc->chip->base]) -		ioname = desc->chip->names[gpio - desc->chip->base]; +	offset = gpio_chip_hwgpio(desc); +	if (desc->chip->names && desc->chip->names[offset]) +		ioname = desc->chip->names[offset];  	dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), -			    desc, ioname ? ioname : "gpio%u", gpio); +			    desc, ioname ? ioname : "gpio%u", +			    desc_to_gpio(desc));  	if (IS_ERR(dev)) {  		status = PTR_ERR(dev);  		goto fail_unlock; @@ -786,7 +804,7 @@ int gpio_export(unsigned gpio, bool direction_may_change)  			goto fail_unregister_device;  	} -	if (gpio_to_irq(gpio) >= 0 && (direction_may_change || +	if (gpiod_to_irq(desc) >= 0 && (direction_may_change ||  				       !test_bit(FLAG_IS_OUT, &desc->flags))) {  		status = device_create_file(dev, &dev_attr_edge);  		if (status) @@ -801,9 +819,15 @@ fail_unregister_device:  	device_unregister(dev);  fail_unlock:  	mutex_unlock(&sysfs_lock); -	pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); +	pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), +		 status);  	return status;  } + +int gpio_export(unsigned gpio, bool direction_may_change) +{ +	return gpiod_export(gpio_to_desc(gpio), direction_may_change); +}  EXPORT_SYMBOL_GPL(gpio_export);  static int match_export(struct device *dev, const void *data) @@ -822,18 +846,16 @@ static int match_export(struct device *dev, const void *data)   *   * Returns zero on success, else an error.   */ -int gpio_export_link(struct device *dev, const char *name, unsigned gpio) +static int gpiod_export_link(struct device *dev, const char *name, +			     struct gpio_desc *desc)  { -	struct gpio_desc	*desc;  	int			status = -EINVAL; -	if (!gpio_is_valid(gpio)) +	if (!desc)  		goto done;  	mutex_lock(&sysfs_lock); -	desc = &gpio_desc[gpio]; -  	if (test_bit(FLAG_EXPORT, &desc->flags)) {  		struct device *tdev; @@ -850,12 +872,17 @@ int gpio_export_link(struct device *dev, const char *name, unsigned gpio)  done:  	if (status) -		pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); +		pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), +			 status);  	return status;  } -EXPORT_SYMBOL_GPL(gpio_export_link); +int gpio_export_link(struct device *dev, const char *name, unsigned gpio) +{ +	return gpiod_export_link(dev, name, gpio_to_desc(gpio)); +} +EXPORT_SYMBOL_GPL(gpio_export_link);  /**   * gpio_sysfs_set_active_low - set the polarity of gpio sysfs value @@ -869,19 +896,16 @@ EXPORT_SYMBOL_GPL(gpio_export_link);   *   * Returns zero on success, else an error.   */ -int gpio_sysfs_set_active_low(unsigned gpio, int value) +static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)  { -	struct gpio_desc	*desc;  	struct device		*dev = NULL;  	int			status = -EINVAL; -	if (!gpio_is_valid(gpio)) +	if (!desc)  		goto done;  	mutex_lock(&sysfs_lock); -	desc = &gpio_desc[gpio]; -  	if (test_bit(FLAG_EXPORT, &desc->flags)) {  		dev = class_find_device(&gpio_class, NULL, desc, match_export);  		if (dev == NULL) { @@ -897,10 +921,16 @@ unlock:  done:  	if (status) -		pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); +		pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), +			 status);  	return status;  } + +int gpio_sysfs_set_active_low(unsigned gpio, int value) +{ +	return gpiod_sysfs_set_active_low(gpio_to_desc(gpio), value); +}  EXPORT_SYMBOL_GPL(gpio_sysfs_set_active_low);  /** @@ -909,21 +939,18 @@ EXPORT_SYMBOL_GPL(gpio_sysfs_set_active_low);   *   * This is implicit on gpio_free().   */ -void gpio_unexport(unsigned gpio) +static void gpiod_unexport(struct gpio_desc *desc)  { -	struct gpio_desc	*desc;  	int			status = 0;  	struct device		*dev = NULL; -	if (!gpio_is_valid(gpio)) { +	if (!desc) {  		status = -EINVAL;  		goto done;  	}  	mutex_lock(&sysfs_lock); -	desc = &gpio_desc[gpio]; -  	if (test_bit(FLAG_EXPORT, &desc->flags)) {  		dev = class_find_device(&gpio_class, NULL, desc, match_export); @@ -935,13 +962,20 @@ void gpio_unexport(unsigned gpio)  	}  	mutex_unlock(&sysfs_lock); +  	if (dev) {  		device_unregister(dev);  		put_device(dev);  	}  done:  	if (status) -		pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); +		pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), +			 status); +} + +void gpio_unexport(unsigned gpio) +{ +	gpiod_unexport(gpio_to_desc(gpio));  }  EXPORT_SYMBOL_GPL(gpio_unexport); @@ -975,9 +1009,9 @@ static int gpiochip_export(struct gpio_chip *chip)  		unsigned	gpio;  		spin_lock_irqsave(&gpio_lock, flags); -		gpio = chip->base; -		while (gpio_desc[gpio].chip == chip) -			gpio_desc[gpio++].chip = NULL; +		gpio = 0; +		while (gpio < chip->ngpio) +			chip->desc[gpio++].chip = NULL;  		spin_unlock_irqrestore(&gpio_lock, flags);  		pr_debug("%s: chip %s status %d\n", __func__, @@ -1012,7 +1046,7 @@ static int __init gpiolib_sysfs_init(void)  {  	int		status;  	unsigned long	flags; -	unsigned	gpio; +	struct gpio_chip *chip;  	status = class_register(&gpio_class);  	if (status < 0) @@ -1025,10 +1059,7 @@ static int __init gpiolib_sysfs_init(void)  	 * registered, and so arch_initcall() can always gpio_export().  	 */  	spin_lock_irqsave(&gpio_lock, flags); -	for (gpio = 0; gpio < ARCH_NR_GPIOS; gpio++) { -		struct gpio_chip	*chip; - -		chip = gpio_desc[gpio].chip; +	list_for_each_entry(chip, &gpio_chips, list) {  		if (!chip || chip->exported)  			continue; @@ -1053,8 +1084,66 @@ static inline void gpiochip_unexport(struct gpio_chip *chip)  {  } +static inline int gpiod_export(struct gpio_desc *desc, +			       bool direction_may_change) +{ +	return -ENOSYS; +} + +static inline int gpiod_export_link(struct device *dev, const char *name, +				    struct gpio_desc *desc) +{ +	return -ENOSYS; +} + +static inline int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value) +{ +	return -ENOSYS; +} + +static inline void gpiod_unexport(struct gpio_desc *desc) +{ +} +  #endif /* CONFIG_GPIO_SYSFS */ +/* + * Add a new chip to the global chips list, keeping the list of chips sorted + * by base order. + * + * Return -EBUSY if the new chip overlaps with some other chip's integer + * space. + */ +static int gpiochip_add_to_list(struct gpio_chip *chip) +{ +	struct list_head *pos = &gpio_chips; +	struct gpio_chip *_chip; +	int err = 0; + +	/* find where to insert our chip */ +	list_for_each(pos, &gpio_chips) { +		_chip = list_entry(pos, struct gpio_chip, list); +		/* shall we insert before _chip? */ +		if (_chip->base >= chip->base + chip->ngpio) +			break; +	} + +	/* are we stepping on the chip right before? */ +	if (pos != &gpio_chips && pos->prev != &gpio_chips) { +		_chip = list_entry(pos->prev, struct gpio_chip, list); +		if (_chip->base + _chip->ngpio > chip->base) { +			dev_err(chip->dev, +			       "GPIO integer space overlap, cannot add chip\n"); +			err = -EBUSY; +		} +	} + +	if (!err) +		list_add_tail(&chip->list, pos); + +	return err; +} +  /**   * gpiochip_add() - register a gpio_chip   * @chip: the chip to register, with chip->base initialized @@ -1096,16 +1185,14 @@ int gpiochip_add(struct gpio_chip *chip)  		chip->base = base;  	} -	/* these GPIO numbers must not be managed by another gpio_chip */ -	for (id = base; id < base + chip->ngpio; id++) { -		if (gpio_desc[id].chip != NULL) { -			status = -EBUSY; -			break; -		} -	} +	status = gpiochip_add_to_list(chip); +  	if (status == 0) { -		for (id = base; id < base + chip->ngpio; id++) { -			gpio_desc[id].chip = chip; +		chip->desc = &gpio_desc[chip->base]; + +		for (id = 0; id < chip->ngpio; id++) { +			struct gpio_desc *desc = &chip->desc[id]; +			desc->chip = chip;  			/* REVISIT:  most hardware initializes GPIOs as  			 * inputs (often with pullups enabled) so power @@ -1114,7 +1201,7 @@ int gpiochip_add(struct gpio_chip *chip)  			 * and in case chip->get_direction is not set,  			 * we may expose the wrong direction in sysfs.  			 */ -			gpio_desc[id].flags = !chip->direction_input +			desc->flags = !chip->direction_input  				? (1 << FLAG_IS_OUT)  				: 0;  		} @@ -1167,15 +1254,17 @@ int gpiochip_remove(struct gpio_chip *chip)  	gpiochip_remove_pin_ranges(chip);  	of_gpiochip_remove(chip); -	for (id = chip->base; id < chip->base + chip->ngpio; id++) { -		if (test_bit(FLAG_REQUESTED, &gpio_desc[id].flags)) { +	for (id = 0; id < chip->ngpio; id++) { +		if (test_bit(FLAG_REQUESTED, &chip->desc[id].flags)) {  			status = -EBUSY;  			break;  		}  	}  	if (status == 0) { -		for (id = chip->base; id < chip->base + chip->ngpio; id++) -			gpio_desc[id].chip = NULL; +		for (id = 0; id < chip->ngpio; id++) +			chip->desc[id].chip = NULL; + +		list_del(&chip->list);  	}  	spin_unlock_irqrestore(&gpio_lock, flags); @@ -1202,20 +1291,17 @@ struct gpio_chip *gpiochip_find(void *data,  				int (*match)(struct gpio_chip *chip,  					     void *data))  { -	struct gpio_chip *chip = NULL; +	struct gpio_chip *chip;  	unsigned long flags; -	int i;  	spin_lock_irqsave(&gpio_lock, flags); -	for (i = 0; i < ARCH_NR_GPIOS; i++) { -		if (!gpio_desc[i].chip) -			continue; - -		if (match(gpio_desc[i].chip, data)) { -			chip = gpio_desc[i].chip; +	list_for_each_entry(chip, &gpio_chips, list) +		if (match(chip, data))  			break; -		} -	} + +	/* No match? */ +	if (&chip->list == &gpio_chips) +		chip = NULL;  	spin_unlock_irqrestore(&gpio_lock, flags);  	return chip; @@ -1297,20 +1383,18 @@ EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges);   * on each other, and help provide better diagnostics in debugfs.   * They're called even less than the "set direction" calls.   */ -int gpio_request(unsigned gpio, const char *label) +static int gpiod_request(struct gpio_desc *desc, const char *label)  { -	struct gpio_desc	*desc;  	struct gpio_chip	*chip;  	int			status = -EPROBE_DEFER;  	unsigned long		flags;  	spin_lock_irqsave(&gpio_lock, flags); -	if (!gpio_is_valid(gpio)) { +	if (!desc) {  		status = -EINVAL;  		goto done;  	} -	desc = &gpio_desc[gpio];  	chip = desc->chip;  	if (chip == NULL)  		goto done; @@ -1334,7 +1418,7 @@ int gpio_request(unsigned gpio, const char *label)  	if (chip->request) {  		/* chip->request may sleep */  		spin_unlock_irqrestore(&gpio_lock, flags); -		status = chip->request(chip, gpio - chip->base); +		status = chip->request(chip, gpio_chip_hwgpio(desc));  		spin_lock_irqsave(&gpio_lock, flags);  		if (status < 0) { @@ -1347,42 +1431,46 @@ int gpio_request(unsigned gpio, const char *label)  	if (chip->get_direction) {  		/* chip->get_direction may sleep */  		spin_unlock_irqrestore(&gpio_lock, flags); -		gpio_get_direction(gpio); +		gpiod_get_direction(desc);  		spin_lock_irqsave(&gpio_lock, flags);  	}  done:  	if (status) -		pr_debug("gpio_request: gpio-%d (%s) status %d\n", -			gpio, label ? : "?", status); +		pr_debug("_gpio_request: gpio-%d (%s) status %d\n", +			 desc ? desc_to_gpio(desc) : -1, +			 label ? : "?", status);  	spin_unlock_irqrestore(&gpio_lock, flags);  	return status;  } + +int gpio_request(unsigned gpio, const char *label) +{ +	return gpiod_request(gpio_to_desc(gpio), label); +}  EXPORT_SYMBOL_GPL(gpio_request); -void gpio_free(unsigned gpio) +static void gpiod_free(struct gpio_desc *desc)  {  	unsigned long		flags; -	struct gpio_desc	*desc;  	struct gpio_chip	*chip;  	might_sleep(); -	if (!gpio_is_valid(gpio)) { +	if (!desc) {  		WARN_ON(extra_checks);  		return;  	} -	gpio_unexport(gpio); +	gpiod_unexport(desc);  	spin_lock_irqsave(&gpio_lock, flags); -	desc = &gpio_desc[gpio];  	chip = desc->chip;  	if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) {  		if (chip->free) {  			spin_unlock_irqrestore(&gpio_lock, flags);  			might_sleep_if(chip->can_sleep); -			chip->free(chip, gpio - chip->base); +			chip->free(chip, gpio_chip_hwgpio(desc));  			spin_lock_irqsave(&gpio_lock, flags);  		}  		desc_set_label(desc, NULL); @@ -1396,6 +1484,11 @@ void gpio_free(unsigned gpio)  	spin_unlock_irqrestore(&gpio_lock, flags);  } + +void gpio_free(unsigned gpio) +{ +	gpiod_free(gpio_to_desc(gpio)); +}  EXPORT_SYMBOL_GPL(gpio_free);  /** @@ -1406,29 +1499,32 @@ EXPORT_SYMBOL_GPL(gpio_free);   */  int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)  { +	struct gpio_desc *desc;  	int err; -	err = gpio_request(gpio, label); +	desc = gpio_to_desc(gpio); + +	err = gpiod_request(desc, label);  	if (err)  		return err;  	if (flags & GPIOF_OPEN_DRAIN) -		set_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags); +		set_bit(FLAG_OPEN_DRAIN, &desc->flags);  	if (flags & GPIOF_OPEN_SOURCE) -		set_bit(FLAG_OPEN_SOURCE, &gpio_desc[gpio].flags); +		set_bit(FLAG_OPEN_SOURCE, &desc->flags);  	if (flags & GPIOF_DIR_IN) -		err = gpio_direction_input(gpio); +		err = gpiod_direction_input(desc);  	else -		err = gpio_direction_output(gpio, +		err = gpiod_direction_output(desc,  				(flags & GPIOF_INIT_HIGH) ? 1 : 0);  	if (err)  		goto free_gpio;  	if (flags & GPIOF_EXPORT) { -		err = gpio_export(gpio, flags & GPIOF_EXPORT_CHANGEABLE); +		err = gpiod_export(desc, flags & GPIOF_EXPORT_CHANGEABLE);  		if (err)  			goto free_gpio;  	} @@ -1436,7 +1532,7 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)  	return 0;   free_gpio: -	gpio_free(gpio); +	gpiod_free(desc);  	return err;  }  EXPORT_SYMBOL_GPL(gpio_request_one); @@ -1491,14 +1587,17 @@ EXPORT_SYMBOL_GPL(gpio_free_array);   */  const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset)  { -	unsigned gpio = chip->base + offset; +	struct gpio_desc *desc; -	if (!gpio_is_valid(gpio) || gpio_desc[gpio].chip != chip) +	if (!GPIO_OFFSET_VALID(chip, offset))  		return NULL; -	if (test_bit(FLAG_REQUESTED, &gpio_desc[gpio].flags) == 0) + +	desc = &chip->desc[offset]; + +	if (test_bit(FLAG_REQUESTED, &desc->flags) == 0)  		return NULL;  #ifdef CONFIG_DEBUG_FS -	return gpio_desc[gpio].label; +	return desc->label;  #else  	return "?";  #endif @@ -1515,24 +1614,21 @@ EXPORT_SYMBOL_GPL(gpiochip_is_requested);   * rely on gpio_request() having been called beforehand.   */ -int gpio_direction_input(unsigned gpio) +static int gpiod_direction_input(struct gpio_desc *desc)  {  	unsigned long		flags;  	struct gpio_chip	*chip; -	struct gpio_desc	*desc = &gpio_desc[gpio];  	int			status = -EINVAL; +	int			offset;  	spin_lock_irqsave(&gpio_lock, flags); -	if (!gpio_is_valid(gpio)) +	if (!desc)  		goto fail;  	chip = desc->chip;  	if (!chip || !chip->get || !chip->direction_input)  		goto fail; -	gpio -= chip->base; -	if (gpio >= chip->ngpio) -		goto fail; -	status = gpio_ensure_requested(desc, gpio); +	status = gpio_ensure_requested(desc);  	if (status < 0)  		goto fail; @@ -1542,11 +1638,12 @@ int gpio_direction_input(unsigned gpio)  	might_sleep_if(chip->can_sleep); +	offset = gpio_chip_hwgpio(desc);  	if (status) { -		status = chip->request(chip, gpio); +		status = chip->request(chip, offset);  		if (status < 0) {  			pr_debug("GPIO-%d: chip request fail, %d\n", -				chip->base + gpio, status); +				desc_to_gpio(desc), status);  			/* and it's not available to anyone else ...  			 * gpio_request() is the fully clean solution.  			 */ @@ -1554,48 +1651,54 @@ int gpio_direction_input(unsigned gpio)  		}  	} -	status = chip->direction_input(chip, gpio); +	status = chip->direction_input(chip, offset);  	if (status == 0)  		clear_bit(FLAG_IS_OUT, &desc->flags); -	trace_gpio_direction(chip->base + gpio, 1, status); +	trace_gpio_direction(desc_to_gpio(desc), 1, status);  lose:  	return status;  fail:  	spin_unlock_irqrestore(&gpio_lock, flags); -	if (status) +	if (status) { +		int gpio = -1; +		if (desc) +			gpio = desc_to_gpio(desc);  		pr_debug("%s: gpio-%d status %d\n",  			__func__, gpio, status); +	}  	return status;  } + +int gpio_direction_input(unsigned gpio) +{ +	return gpiod_direction_input(gpio_to_desc(gpio)); +}  EXPORT_SYMBOL_GPL(gpio_direction_input); -int gpio_direction_output(unsigned gpio, int value) +static int gpiod_direction_output(struct gpio_desc *desc, int value)  {  	unsigned long		flags;  	struct gpio_chip	*chip; -	struct gpio_desc	*desc = &gpio_desc[gpio];  	int			status = -EINVAL; +	int offset;  	/* Open drain pin should not be driven to 1 */  	if (value && test_bit(FLAG_OPEN_DRAIN,  &desc->flags)) -		return gpio_direction_input(gpio); +		return gpiod_direction_input(desc);  	/* Open source pin should not be driven to 0 */  	if (!value && test_bit(FLAG_OPEN_SOURCE,  &desc->flags)) -		return gpio_direction_input(gpio); +		return gpiod_direction_input(desc);  	spin_lock_irqsave(&gpio_lock, flags); -	if (!gpio_is_valid(gpio)) +	if (!desc)  		goto fail;  	chip = desc->chip;  	if (!chip || !chip->set || !chip->direction_output)  		goto fail; -	gpio -= chip->base; -	if (gpio >= chip->ngpio) -		goto fail; -	status = gpio_ensure_requested(desc, gpio); +	status = gpio_ensure_requested(desc);  	if (status < 0)  		goto fail; @@ -1605,11 +1708,12 @@ int gpio_direction_output(unsigned gpio, int value)  	might_sleep_if(chip->can_sleep); +	offset = gpio_chip_hwgpio(desc);  	if (status) { -		status = chip->request(chip, gpio); +		status = chip->request(chip, offset);  		if (status < 0) {  			pr_debug("GPIO-%d: chip request fail, %d\n", -				chip->base + gpio, status); +				desc_to_gpio(desc), status);  			/* and it's not available to anyone else ...  			 * gpio_request() is the fully clean solution.  			 */ @@ -1617,20 +1721,29 @@ int gpio_direction_output(unsigned gpio, int value)  		}  	} -	status = chip->direction_output(chip, gpio, value); +	status = chip->direction_output(chip, offset, value);  	if (status == 0)  		set_bit(FLAG_IS_OUT, &desc->flags); -	trace_gpio_value(chip->base + gpio, 0, value); -	trace_gpio_direction(chip->base + gpio, 0, status); +	trace_gpio_value(desc_to_gpio(desc), 0, value); +	trace_gpio_direction(desc_to_gpio(desc), 0, status);  lose:  	return status;  fail:  	spin_unlock_irqrestore(&gpio_lock, flags); -	if (status) +	if (status) { +		int gpio = -1; +		if (desc) +			gpio = desc_to_gpio(desc);  		pr_debug("%s: gpio-%d status %d\n",  			__func__, gpio, status); +	}  	return status;  } + +int gpio_direction_output(unsigned gpio, int value) +{ +	return gpiod_direction_output(gpio_to_desc(gpio), value); +}  EXPORT_SYMBOL_GPL(gpio_direction_output);  /** @@ -1638,24 +1751,22 @@ EXPORT_SYMBOL_GPL(gpio_direction_output);   * @gpio: the gpio to set debounce time   * @debounce: debounce time is microseconds   */ -int gpio_set_debounce(unsigned gpio, unsigned debounce) +static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)  {  	unsigned long		flags;  	struct gpio_chip	*chip; -	struct gpio_desc	*desc = &gpio_desc[gpio];  	int			status = -EINVAL; +	int			offset;  	spin_lock_irqsave(&gpio_lock, flags); -	if (!gpio_is_valid(gpio)) +	if (!desc)  		goto fail;  	chip = desc->chip;  	if (!chip || !chip->set || !chip->set_debounce)  		goto fail; -	gpio -= chip->base; -	if (gpio >= chip->ngpio) -		goto fail; -	status = gpio_ensure_requested(desc, gpio); + +	status = gpio_ensure_requested(desc);  	if (status < 0)  		goto fail; @@ -1665,16 +1776,26 @@ int gpio_set_debounce(unsigned gpio, unsigned debounce)  	might_sleep_if(chip->can_sleep); -	return chip->set_debounce(chip, gpio, debounce); +	offset = gpio_chip_hwgpio(desc); +	return chip->set_debounce(chip, offset, debounce);  fail:  	spin_unlock_irqrestore(&gpio_lock, flags); -	if (status) +	if (status) { +		int gpio = -1; +		if (desc) +			gpio = desc_to_gpio(desc);  		pr_debug("%s: gpio-%d status %d\n",  			__func__, gpio, status); +	}  	return status;  } + +int gpio_set_debounce(unsigned gpio, unsigned debounce) +{ +	return gpiod_set_debounce(gpio_to_desc(gpio), debounce); +}  EXPORT_SYMBOL_GPL(gpio_set_debounce);  /* I/O calls are only valid after configuration completed; the relevant @@ -1708,18 +1829,25 @@ EXPORT_SYMBOL_GPL(gpio_set_debounce);   * It returns the zero or nonzero value provided by the associated   * gpio_chip.get() method; or zero if no such method is provided.   */ -int __gpio_get_value(unsigned gpio) +static int gpiod_get_value(struct gpio_desc *desc)  {  	struct gpio_chip	*chip;  	int value; +	int offset; -	chip = gpio_to_chip(gpio); +	chip = desc->chip; +	offset = gpio_chip_hwgpio(desc);  	/* Should be using gpio_get_value_cansleep() */  	WARN_ON(chip->can_sleep); -	value = chip->get ? chip->get(chip, gpio - chip->base) : 0; -	trace_gpio_value(gpio, 1, value); +	value = chip->get ? chip->get(chip, offset) : 0; +	trace_gpio_value(desc_to_gpio(desc), 1, value);  	return value;  } + +int __gpio_get_value(unsigned gpio) +{ +	return gpiod_get_value(gpio_to_desc(gpio)); +}  EXPORT_SYMBOL_GPL(__gpio_get_value);  /* @@ -1728,23 +1856,25 @@ EXPORT_SYMBOL_GPL(__gpio_get_value);   * @chip: Gpio chip.   * @value: Non-zero for setting it HIGH otherise it will set to LOW.   */ -static void _gpio_set_open_drain_value(unsigned gpio, -			struct gpio_chip *chip, int value) +static void _gpio_set_open_drain_value(struct gpio_desc *desc, int value)  {  	int err = 0; +	struct gpio_chip *chip = desc->chip; +	int offset = gpio_chip_hwgpio(desc); +  	if (value) { -		err = chip->direction_input(chip, gpio - chip->base); +		err = chip->direction_input(chip, offset);  		if (!err) -			clear_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags); +			clear_bit(FLAG_IS_OUT, &desc->flags);  	} else { -		err = chip->direction_output(chip, gpio - chip->base, 0); +		err = chip->direction_output(chip, offset, 0);  		if (!err) -			set_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags); +			set_bit(FLAG_IS_OUT, &desc->flags);  	} -	trace_gpio_direction(gpio, value, err); +	trace_gpio_direction(desc_to_gpio(desc), value, err);  	if (err < 0)  		pr_err("%s: Error in set_value for open drain gpio%d err %d\n", -					__func__, gpio, err); +					__func__, desc_to_gpio(desc), err);  }  /* @@ -1753,26 +1883,27 @@ static void _gpio_set_open_drain_value(unsigned gpio,   * @chip: Gpio chip.   * @value: Non-zero for setting it HIGH otherise it will set to LOW.   */ -static void _gpio_set_open_source_value(unsigned gpio, -			struct gpio_chip *chip, int value) +static void _gpio_set_open_source_value(struct gpio_desc *desc, int value)  {  	int err = 0; +	struct gpio_chip *chip = desc->chip; +	int offset = gpio_chip_hwgpio(desc); +  	if (value) { -		err = chip->direction_output(chip, gpio - chip->base, 1); +		err = chip->direction_output(chip, offset, 1);  		if (!err) -			set_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags); +			set_bit(FLAG_IS_OUT, &desc->flags);  	} else { -		err = chip->direction_input(chip, gpio - chip->base); +		err = chip->direction_input(chip, offset);  		if (!err) -			clear_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags); +			clear_bit(FLAG_IS_OUT, &desc->flags);  	} -	trace_gpio_direction(gpio, !value, err); +	trace_gpio_direction(desc_to_gpio(desc), !value, err);  	if (err < 0)  		pr_err("%s: Error in set_value for open source gpio%d err %d\n", -					__func__, gpio, err); +					__func__, desc_to_gpio(desc), err);  } -  /**   * __gpio_set_value() - assign a gpio's value   * @gpio: gpio whose value will be assigned @@ -1782,20 +1913,25 @@ static void _gpio_set_open_source_value(unsigned gpio,   * This is used directly or indirectly to implement gpio_set_value().   * It invokes the associated gpio_chip.set() method.   */ -void __gpio_set_value(unsigned gpio, int value) +static void gpiod_set_value(struct gpio_desc *desc, int value)  {  	struct gpio_chip	*chip; -	chip = gpio_to_chip(gpio); +	chip = desc->chip;  	/* Should be using gpio_set_value_cansleep() */  	WARN_ON(chip->can_sleep); -	trace_gpio_value(gpio, 0, value); -	if (test_bit(FLAG_OPEN_DRAIN,  &gpio_desc[gpio].flags)) -		_gpio_set_open_drain_value(gpio, chip, value); -	else if (test_bit(FLAG_OPEN_SOURCE,  &gpio_desc[gpio].flags)) -		_gpio_set_open_source_value(gpio, chip, value); +	trace_gpio_value(desc_to_gpio(desc), 0, value); +	if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) +		_gpio_set_open_drain_value(desc, value); +	else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) +		_gpio_set_open_source_value(desc, value);  	else -		chip->set(chip, gpio - chip->base, value); +		chip->set(chip, gpio_chip_hwgpio(desc), value); +} + +void __gpio_set_value(unsigned gpio, int value) +{ +	return gpiod_set_value(gpio_to_desc(gpio), value);  }  EXPORT_SYMBOL_GPL(__gpio_set_value); @@ -1807,14 +1943,15 @@ EXPORT_SYMBOL_GPL(__gpio_set_value);   * This is used directly or indirectly to implement gpio_cansleep().  It   * returns nonzero if access reading or writing the GPIO value can sleep.   */ -int __gpio_cansleep(unsigned gpio) +static int gpiod_cansleep(struct gpio_desc *desc)  { -	struct gpio_chip	*chip; -  	/* only call this on GPIOs that are valid! */ -	chip = gpio_to_chip(gpio); +	return desc->chip->can_sleep; +} -	return chip->can_sleep; +int __gpio_cansleep(unsigned gpio) +{ +	return gpiod_cansleep(gpio_to_desc(gpio));  }  EXPORT_SYMBOL_GPL(__gpio_cansleep); @@ -1827,50 +1964,67 @@ EXPORT_SYMBOL_GPL(__gpio_cansleep);   * It returns the number of the IRQ signaled by this (input) GPIO,   * or a negative errno.   */ -int __gpio_to_irq(unsigned gpio) +static int gpiod_to_irq(struct gpio_desc *desc)  {  	struct gpio_chip	*chip; +	int			offset; -	chip = gpio_to_chip(gpio); -	return chip->to_irq ? chip->to_irq(chip, gpio - chip->base) : -ENXIO; +	chip = desc->chip; +	offset = gpio_chip_hwgpio(desc); +	return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO;  } -EXPORT_SYMBOL_GPL(__gpio_to_irq); +int __gpio_to_irq(unsigned gpio) +{ +	return gpiod_to_irq(gpio_to_desc(gpio)); +} +EXPORT_SYMBOL_GPL(__gpio_to_irq);  /* There's no value in making it easy to inline GPIO calls that may sleep.   * Common examples include ones connected to I2C or SPI chips.   */ -int gpio_get_value_cansleep(unsigned gpio) +static int gpiod_get_value_cansleep(struct gpio_desc *desc)  {  	struct gpio_chip	*chip;  	int value; +	int offset;  	might_sleep_if(extra_checks); -	chip = gpio_to_chip(gpio); -	value = chip->get ? chip->get(chip, gpio - chip->base) : 0; -	trace_gpio_value(gpio, 1, value); +	chip = desc->chip; +	offset = gpio_chip_hwgpio(desc); +	value = chip->get ? chip->get(chip, offset) : 0; +	trace_gpio_value(desc_to_gpio(desc), 1, value);  	return value;  } + +int gpio_get_value_cansleep(unsigned gpio) +{ +	return gpiod_get_value_cansleep(gpio_to_desc(gpio)); +}  EXPORT_SYMBOL_GPL(gpio_get_value_cansleep); -void gpio_set_value_cansleep(unsigned gpio, int value) +static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)  {  	struct gpio_chip	*chip;  	might_sleep_if(extra_checks); -	chip = gpio_to_chip(gpio); -	trace_gpio_value(gpio, 0, value); -	if (test_bit(FLAG_OPEN_DRAIN,  &gpio_desc[gpio].flags)) -		_gpio_set_open_drain_value(gpio, chip, value); -	else if (test_bit(FLAG_OPEN_SOURCE,  &gpio_desc[gpio].flags)) -		_gpio_set_open_source_value(gpio, chip, value); +	chip = desc->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); +	else if (test_bit(FLAG_OPEN_SOURCE,  &desc->flags)) +		_gpio_set_open_source_value(desc, value);  	else -		chip->set(chip, gpio - chip->base, value); +		chip->set(chip, gpio_chip_hwgpio(desc), value);  } -EXPORT_SYMBOL_GPL(gpio_set_value_cansleep); +void gpio_set_value_cansleep(unsigned gpio, int value) +{ +	return gpiod_set_value_cansleep(gpio_to_desc(gpio), value); +} +EXPORT_SYMBOL_GPL(gpio_set_value_cansleep);  #ifdef CONFIG_DEBUG_FS @@ -1878,14 +2032,14 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)  {  	unsigned		i;  	unsigned		gpio = chip->base; -	struct gpio_desc	*gdesc = &gpio_desc[gpio]; +	struct gpio_desc	*gdesc = &chip->desc[0];  	int			is_out;  	for (i = 0; i < chip->ngpio; i++, gpio++, gdesc++) {  		if (!test_bit(FLAG_REQUESTED, &gdesc->flags))  			continue; -		gpio_get_direction(gpio); +		gpiod_get_direction(gdesc);  		is_out = test_bit(FLAG_IS_OUT, &gdesc->flags);  		seq_printf(s, " gpio-%-3d (%-20.20s) %s %s",  			gpio, gdesc->label, @@ -1899,46 +2053,35 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)  static void *gpiolib_seq_start(struct seq_file *s, loff_t *pos)  { +	unsigned long flags;  	struct gpio_chip *chip = NULL; -	unsigned int gpio; -	void *ret = NULL; -	loff_t index = 0; - -	/* REVISIT this isn't locked against gpio_chip removal ... */ +	loff_t index = *pos; -	for (gpio = 0; gpio_is_valid(gpio); gpio++) { -		if (gpio_desc[gpio].chip == chip) -			continue; - -		chip = gpio_desc[gpio].chip; -		if (!chip) -			continue; +	s->private = ""; -		if (index++ >= *pos) { -			ret = chip; -			break; +	spin_lock_irqsave(&gpio_lock, flags); +	list_for_each_entry(chip, &gpio_chips, list) +		if (index-- == 0) { +			spin_unlock_irqrestore(&gpio_lock, flags); +			return chip;  		} -	} - -	s->private = ""; +	spin_unlock_irqrestore(&gpio_lock, flags); -	return ret; +	return NULL;  }  static void *gpiolib_seq_next(struct seq_file *s, void *v, loff_t *pos)  { +	unsigned long flags;  	struct gpio_chip *chip = v; -	unsigned int gpio;  	void *ret = NULL; -	/* skip GPIOs provided by the current chip */ -	for (gpio = chip->base + chip->ngpio; gpio_is_valid(gpio); gpio++) { -		chip = gpio_desc[gpio].chip; -		if (chip) { -			ret = chip; -			break; -		} -	} +	spin_lock_irqsave(&gpio_lock, flags); +	if (list_is_last(&chip->list, &gpio_chips)) +		ret = NULL; +	else +		ret = list_entry(chip->list.next, struct gpio_chip, list); +	spin_unlock_irqrestore(&gpio_lock, flags);  	s->private = "\n";  	++*pos;  |