diff options
Diffstat (limited to 'drivers/gpio')
| -rw-r--r-- | drivers/gpio/gpio-ich.c | 6 | ||||
| -rw-r--r-- | drivers/gpio/gpio-mvebu.c | 7 | ||||
| -rw-r--r-- | drivers/gpio/gpio-pca953x.c | 2 | ||||
| -rw-r--r-- | drivers/gpio/gpio-pl061.c | 125 | ||||
| -rw-r--r-- | drivers/gpio/gpio-pxa.c | 7 | ||||
| -rw-r--r-- | drivers/gpio/gpio-stmpe.c | 15 | ||||
| -rw-r--r-- | drivers/gpio/gpiolib-of.c | 20 | ||||
| -rw-r--r-- | drivers/gpio/gpiolib.c | 143 | 
8 files changed, 200 insertions, 125 deletions
diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c index 6f2306db859..de3c317bd3e 100644 --- a/drivers/gpio/gpio-ich.c +++ b/drivers/gpio/gpio-ich.c @@ -128,9 +128,9 @@ static int ichx_read_bit(int reg, unsigned nr)  	return data & (1 << bit) ? 1 : 0;  } -static int ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr) +static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr)  { -	return (ichx_priv.use_gpio & (1 << (nr / 32))) ? 0 : -ENXIO; +	return ichx_priv.use_gpio & (1 << (nr / 32));  }  static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) @@ -214,7 +214,7 @@ static int ichx_gpio_request(struct gpio_chip *chip, unsigned nr)  	 * If it can't be trusted, assume that the pin can be used as a GPIO.  	 */  	if (ichx_priv.desc->use_sel_ignore[nr / 32] & (1 << (nr & 0x1f))) -		return 1; +		return 0;  	return ichx_read_bit(GPIO_USE_SEL, nr) ? 0 : -ENODEV;  } diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 7472182967c..61a6fde6c08 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -42,6 +42,7 @@  #include <linux/io.h>  #include <linux/of_irq.h>  #include <linux/of_device.h> +#include <linux/clk.h>  #include <linux/pinctrl/consumer.h>  /* @@ -496,6 +497,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev)  	struct resource *res;  	struct irq_chip_generic *gc;  	struct irq_chip_type *ct; +	struct clk *clk;  	unsigned int ngpios;  	int soc_variant;  	int i, cpu, id; @@ -529,6 +531,11 @@ static int mvebu_gpio_probe(struct platform_device *pdev)  		return id;  	} +	clk = devm_clk_get(&pdev->dev, NULL); +	/* Not all SoCs require a clock.*/ +	if (!IS_ERR(clk)) +		clk_prepare_enable(clk); +  	mvchip->soc_variant = soc_variant;  	mvchip->chip.label = dev_name(&pdev->dev);  	mvchip->chip.dev = &pdev->dev; diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 24059462c87..9391cf16e99 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -575,7 +575,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,  						chip->gpio_chip.ngpio,  						irq_base,  						&pca953x_irq_simple_ops, -						NULL); +						chip);  		if (!chip->domain)  			return -ENODEV; diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index b820869ca93..d7008dfdd6f 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -15,6 +15,7 @@  #include <linux/io.h>  #include <linux/ioport.h>  #include <linux/irq.h> +#include <linux/irqdomain.h>  #include <linux/bitops.h>  #include <linux/workqueue.h>  #include <linux/gpio.h> @@ -22,6 +23,7 @@  #include <linux/amba/bus.h>  #include <linux/amba/pl061.h>  #include <linux/slab.h> +#include <linux/pinctrl/consumer.h>  #include <linux/pm.h>  #include <asm/mach/irq.h> @@ -51,8 +53,7 @@ struct pl061_gpio {  	spinlock_t		lock;  	void __iomem		*base; -	int			irq_base; -	struct irq_chip_generic	*irq_gc; +	struct irq_domain	*domain;  	struct gpio_chip	gc;  #ifdef CONFIG_PM @@ -60,6 +61,24 @@ struct pl061_gpio {  #endif  }; +static int pl061_gpio_request(struct gpio_chip *chip, unsigned offset) +{ +	/* +	 * Map back to global GPIO space and request muxing, the direction +	 * parameter does not matter for this controller. +	 */ +	int gpio = chip->base + offset; + +	return pinctrl_request_gpio(gpio); +} + +static void pl061_gpio_free(struct gpio_chip *chip, unsigned offset) +{ +	int gpio = chip->base + offset; + +	pinctrl_free_gpio(gpio); +} +  static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)  {  	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); @@ -122,24 +141,20 @@ static int pl061_to_irq(struct gpio_chip *gc, unsigned offset)  {  	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); -	if (chip->irq_base <= 0) -		return -EINVAL; - -	return chip->irq_base + offset; +	return irq_create_mapping(chip->domain, offset);  }  static int pl061_irq_type(struct irq_data *d, unsigned trigger)  { -	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); -	struct pl061_gpio *chip = gc->private; -	int offset = d->irq - chip->irq_base; +	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); +	int offset = irqd_to_hwirq(d);  	unsigned long flags;  	u8 gpiois, gpioibe, gpioiev;  	if (offset < 0 || offset >= PL061_GPIO_NR)  		return -EINVAL; -	raw_spin_lock_irqsave(&gc->lock, flags); +	spin_lock_irqsave(&chip->lock, flags);  	gpioiev = readb(chip->base + GPIOIEV); @@ -168,7 +183,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)  	writeb(gpioiev, chip->base + GPIOIEV); -	raw_spin_unlock_irqrestore(&gc->lock, flags); +	spin_unlock_irqrestore(&chip->lock, flags);  	return 0;  } @@ -192,31 +207,61 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)  	chained_irq_exit(irqchip, desc);  } -static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base) +static void pl061_irq_mask(struct irq_data *d) +{ +	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); +	u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR); +	u8 gpioie; + +	spin_lock(&chip->lock); +	gpioie = readb(chip->base + GPIOIE) & ~mask; +	writeb(gpioie, chip->base + GPIOIE); +	spin_unlock(&chip->lock); +} + +static void pl061_irq_unmask(struct irq_data *d)  { -	struct irq_chip_type *ct; +	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); +	u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR); +	u8 gpioie; -	chip->irq_gc = irq_alloc_generic_chip("gpio-pl061", 1, irq_base, -					      chip->base, handle_simple_irq); -	chip->irq_gc->private = chip; +	spin_lock(&chip->lock); +	gpioie = readb(chip->base + GPIOIE) | mask; +	writeb(gpioie, chip->base + GPIOIE); +	spin_unlock(&chip->lock); +} -	ct = chip->irq_gc->chip_types; -	ct->chip.irq_mask = irq_gc_mask_clr_bit; -	ct->chip.irq_unmask = irq_gc_mask_set_bit; -	ct->chip.irq_set_type = pl061_irq_type; -	ct->chip.irq_set_wake = irq_gc_set_wake; -	ct->regs.mask = GPIOIE; +static struct irq_chip pl061_irqchip = { +	.name		= "pl061 gpio", +	.irq_mask	= pl061_irq_mask, +	.irq_unmask	= pl061_irq_unmask, +	.irq_set_type	= pl061_irq_type, +}; + +static int pl061_irq_map(struct irq_domain *d, unsigned int virq, +			 irq_hw_number_t hw) +{ +	struct pl061_gpio *chip = d->host_data; -	irq_setup_generic_chip(chip->irq_gc, IRQ_MSK(PL061_GPIO_NR), -			       IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0); +	irq_set_chip_and_handler_name(virq, &pl061_irqchip, handle_simple_irq, +				      "pl061"); +	irq_set_chip_data(virq, chip); +	irq_set_irq_type(virq, IRQ_TYPE_NONE); + +	return 0;  } +static const struct irq_domain_ops pl061_domain_ops = { +	.map	= pl061_irq_map, +	.xlate	= irq_domain_xlate_twocell, +}; +  static int pl061_probe(struct amba_device *adev, const struct amba_id *id)  {  	struct device *dev = &adev->dev;  	struct pl061_platform_data *pdata = dev->platform_data;  	struct pl061_gpio *chip; -	int ret, irq, i; +	int ret, irq, i, irq_base;  	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);  	if (chip == NULL) @@ -224,24 +269,32 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)  	if (pdata) {  		chip->gc.base = pdata->gpio_base; -		chip->irq_base = pdata->irq_base; -	} else if (adev->dev.of_node) { +		irq_base = pdata->irq_base; +		if (irq_base <= 0) +			return -ENODEV; +	} else {  		chip->gc.base = -1; -		chip->irq_base = 0; -	} else -		return -ENODEV; +		irq_base = 0; +	}  	if (!devm_request_mem_region(dev, adev->res.start, -				resource_size(&adev->res), "pl061")) +				     resource_size(&adev->res), "pl061"))  		return -EBUSY;  	chip->base = devm_ioremap(dev, adev->res.start, -				resource_size(&adev->res)); -	if (chip->base == NULL) +				  resource_size(&adev->res)); +	if (!chip->base)  		return -ENOMEM; +	chip->domain = irq_domain_add_simple(adev->dev.of_node, PL061_GPIO_NR, +					     irq_base, &pl061_domain_ops, chip); +	if (!chip->domain) +		return -ENODEV; +  	spin_lock_init(&chip->lock); +	chip->gc.request = pl061_gpio_request; +	chip->gc.free = pl061_gpio_free;  	chip->gc.direction_input = pl061_direction_input;  	chip->gc.direction_output = pl061_direction_output;  	chip->gc.get = pl061_get_value; @@ -259,12 +312,6 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)  	/*  	 * irq_chip support  	 */ - -	if (chip->irq_base <= 0) -		return 0; - -	pl061_init_gc(chip, chip->irq_base); -  	writeb(0, chip->base + GPIOIE); /* disable irqs */  	irq = adev->irq[0];  	if (irq < 0) diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 9cc108d2b77..8325f580c0f 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -642,7 +642,12 @@ static struct platform_driver pxa_gpio_driver = {  		.of_match_table = of_match_ptr(pxa_gpio_dt_ids),  	},  }; -module_platform_driver(pxa_gpio_driver); + +static int __init pxa_gpio_init(void) +{ +	return platform_driver_register(&pxa_gpio_driver); +} +postcore_initcall(pxa_gpio_init);  #ifdef CONFIG_PM  static int pxa_gpio_suspend(void) diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index 770476a9da8..3ce5bc38ac3 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c @@ -307,11 +307,15 @@ static const struct irq_domain_ops stmpe_gpio_irq_simple_ops = {  	.xlate = irq_domain_xlate_twocell,  }; -static int stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio) +static int stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio, +		struct device_node *np)  { -	int base = stmpe_gpio->irq_base; +	int base = 0; -	stmpe_gpio->domain = irq_domain_add_simple(NULL, +	if (!np) +		base = stmpe_gpio->irq_base; + +	stmpe_gpio->domain = irq_domain_add_simple(np,  				stmpe_gpio->chip.ngpio, base,  				&stmpe_gpio_irq_simple_ops, stmpe_gpio);  	if (!stmpe_gpio->domain) { @@ -346,6 +350,9 @@ static int stmpe_gpio_probe(struct platform_device *pdev)  	stmpe_gpio->chip = template_chip;  	stmpe_gpio->chip.ngpio = stmpe->num_gpios;  	stmpe_gpio->chip.dev = &pdev->dev; +#ifdef CONFIG_OF +	stmpe_gpio->chip.of_node = np; +#endif  	stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1;  	if (pdata) @@ -366,7 +373,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev)  		goto out_free;  	if (irq >= 0) { -		ret = stmpe_gpio_irq_init(stmpe_gpio); +		ret = stmpe_gpio_irq_init(stmpe_gpio, np);  		if (ret)  			goto out_disable; diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index a71a54a3e3f..465f4ca57e8 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -193,7 +193,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)  	if (!np)  		return; -	do { +	for (;; index++) {  		ret = of_parse_phandle_with_args(np, "gpio-ranges",  				"#gpio-range-cells", index, &pinspec);  		if (ret) @@ -203,27 +203,15 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)  		if (!pctldev)  			break; -		/* -		 * This assumes that the n GPIO pins are consecutive in the -		 * GPIO number space, and that the pins are also consecutive -		 * in their local number space. Currently it is not possible -		 * to add different ranges for one and the same GPIO chip, -		 * as the code assumes that we have one consecutive range -		 * on both, mapping 1-to-1. -		 * -		 * TODO: make the OF bindings handle multiple sparse ranges -		 * on the same GPIO chip. -		 */  		ret = gpiochip_add_pin_range(chip,  					     pinctrl_dev_get_devname(pctldev), -					     0, /* offset in gpiochip */  					     pinspec.args[0], -					     pinspec.args[1]); +					     pinspec.args[1], +					     pinspec.args[2]);  		if (ret)  			break; - -	} while (index++); +	}  }  #else diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index fff9786cdc6..c2534d62911 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -88,13 +88,14 @@ 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_get_direction(const struct gpio_desc *desc);  static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce); -static int gpiod_get_value_cansleep(struct gpio_desc *desc); +static int gpiod_get_value_cansleep(const 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 int gpiod_get_value(const 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_cansleep(const struct gpio_desc *desc); +static int gpiod_to_irq(const 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); @@ -171,12 +172,12 @@ static int gpio_ensure_requested(struct gpio_desc *desc)  	return 0;  } -/* caller holds gpio_lock *OR* gpio is marked as requested */ -static struct gpio_chip *gpiod_to_chip(struct gpio_desc *desc) +static struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)  { -	return desc->chip; +	return desc ? desc->chip : NULL;  } +/* caller holds gpio_lock *OR* gpio is marked as requested */  struct gpio_chip *gpio_to_chip(unsigned gpio)  {  	return gpiod_to_chip(gpio_to_desc(gpio)); @@ -207,7 +208,7 @@ static int gpiochip_find_base(int ngpio)  }  /* caller ensures gpio is valid and requested, chip->get_direction may sleep  */ -static int gpiod_get_direction(struct gpio_desc *desc) +static int gpiod_get_direction(const struct gpio_desc *desc)  {  	struct gpio_chip	*chip;  	unsigned		offset; @@ -223,11 +224,13 @@ static int gpiod_get_direction(struct gpio_desc *desc)  	if (status > 0) {  		/* GPIOF_DIR_IN, or other positive */  		status = 1; -		clear_bit(FLAG_IS_OUT, &desc->flags); +		/* FLAG_IS_OUT is just a cache of the result of get_direction(), +		 * so it does not affect constness per se */ +		clear_bit(FLAG_IS_OUT, &((struct gpio_desc *)desc)->flags);  	}  	if (status == 0) {  		/* GPIOF_DIR_OUT */ -		set_bit(FLAG_IS_OUT, &desc->flags); +		set_bit(FLAG_IS_OUT, &((struct gpio_desc *)desc)->flags);  	}  	return status;  } @@ -263,7 +266,7 @@ static DEFINE_MUTEX(sysfs_lock);  static ssize_t gpio_direction_show(struct device *dev,  		struct device_attribute *attr, char *buf)  { -	struct gpio_desc	*desc = dev_get_drvdata(dev); +	const struct gpio_desc	*desc = dev_get_drvdata(dev);  	ssize_t			status;  	mutex_lock(&sysfs_lock); @@ -654,6 +657,11 @@ static ssize_t export_store(struct class *class,  		goto done;  	desc = gpio_to_desc(gpio); +	/* reject invalid GPIOs */ +	if (!desc) { +		pr_warn("%s: invalid GPIO %ld\n", __func__, gpio); +		return -EINVAL; +	}  	/* No extra locking here; FLAG_SYSFS just signifies that the  	 * request and export were done by on behalf of userspace, so @@ -690,12 +698,14 @@ static ssize_t unexport_store(struct class *class,  	if (status < 0)  		goto done; -	status = -EINVAL; -  	desc = gpio_to_desc(gpio);  	/* reject bogus commands (gpio_unexport ignores them) */ -	if (!desc) -		goto done; +	if (!desc) { +		pr_warn("%s: invalid GPIO %ld\n", __func__, gpio); +		return -EINVAL; +	} + +	status = -EINVAL;  	/* No extra locking here; FLAG_SYSFS just signifies that the  	 * request and export were done by on behalf of userspace, so @@ -846,8 +856,10 @@ static int gpiod_export_link(struct device *dev, const char *name,  {  	int			status = -EINVAL; -	if (!desc) -		goto done; +	if (!desc) { +		pr_warn("%s: invalid GPIO\n", __func__); +		return -EINVAL; +	}  	mutex_lock(&sysfs_lock); @@ -865,7 +877,6 @@ static int gpiod_export_link(struct device *dev, const char *name,  	mutex_unlock(&sysfs_lock); -done:  	if (status)  		pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc),  			 status); @@ -896,8 +907,10 @@ static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)  	struct device		*dev = NULL;  	int			status = -EINVAL; -	if (!desc) -		goto done; +	if (!desc) { +		pr_warn("%s: invalid GPIO\n", __func__); +		return -EINVAL; +	}  	mutex_lock(&sysfs_lock); @@ -914,7 +927,6 @@ static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)  unlock:  	mutex_unlock(&sysfs_lock); -done:  	if (status)  		pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc),  			 status); @@ -940,8 +952,8 @@ static void gpiod_unexport(struct gpio_desc *desc)  	struct device		*dev = NULL;  	if (!desc) { -		status = -EINVAL; -		goto done; +		pr_warn("%s: invalid GPIO\n", __func__); +		return;  	}  	mutex_lock(&sysfs_lock); @@ -962,7 +974,7 @@ static void gpiod_unexport(struct gpio_desc *desc)  		device_unregister(dev);  		put_device(dev);  	} -done: +  	if (status)  		pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc),  			 status); @@ -1384,12 +1396,13 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)  	int			status = -EPROBE_DEFER;  	unsigned long		flags; -	spin_lock_irqsave(&gpio_lock, flags); -  	if (!desc) { -		status = -EINVAL; -		goto done; +		pr_warn("%s: invalid GPIO\n", __func__); +		return -EINVAL;  	} + +	spin_lock_irqsave(&gpio_lock, flags); +  	chip = desc->chip;  	if (chip == NULL)  		goto done; @@ -1432,8 +1445,7 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)  done:  	if (status)  		pr_debug("_gpio_request: gpio-%d (%s) status %d\n", -			 desc ? desc_to_gpio(desc) : -1, -			 label ? : "?", status); +			 desc_to_gpio(desc), label ? : "?", status);  	spin_unlock_irqrestore(&gpio_lock, flags);  	return status;  } @@ -1616,10 +1628,13 @@ static int gpiod_direction_input(struct gpio_desc *desc)  	int			status = -EINVAL;  	int			offset; +	if (!desc) { +		pr_warn("%s: invalid GPIO\n", __func__); +		return -EINVAL; +	} +  	spin_lock_irqsave(&gpio_lock, flags); -	if (!desc) -		goto fail;  	chip = desc->chip;  	if (!chip || !chip->get || !chip->direction_input)  		goto fail; @@ -1655,13 +1670,9 @@ lose:  	return status;  fail:  	spin_unlock_irqrestore(&gpio_lock, flags); -	if (status) { -		int gpio = -1; -		if (desc) -			gpio = desc_to_gpio(desc); -		pr_debug("%s: gpio-%d status %d\n", -			__func__, gpio, status); -	} +	if (status) +		pr_debug("%s: gpio-%d status %d\n", __func__, +			 desc_to_gpio(desc), status);  	return status;  } @@ -1678,6 +1689,11 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value)  	int			status = -EINVAL;  	int offset; +	if (!desc) { +		pr_warn("%s: invalid GPIO\n", __func__); +		return -EINVAL; +	} +  	/* Open drain pin should not be driven to 1 */  	if (value && test_bit(FLAG_OPEN_DRAIN,  &desc->flags))  		return gpiod_direction_input(desc); @@ -1688,8 +1704,6 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value)  	spin_lock_irqsave(&gpio_lock, flags); -	if (!desc) -		goto fail;  	chip = desc->chip;  	if (!chip || !chip->set || !chip->direction_output)  		goto fail; @@ -1725,13 +1739,9 @@ lose:  	return status;  fail:  	spin_unlock_irqrestore(&gpio_lock, flags); -	if (status) { -		int gpio = -1; -		if (desc) -			gpio = desc_to_gpio(desc); -		pr_debug("%s: gpio-%d status %d\n", -			__func__, gpio, status); -	} +	if (status) +		pr_debug("%s: gpio-%d status %d\n", __func__, +			 desc_to_gpio(desc), status);  	return status;  } @@ -1753,10 +1763,13 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)  	int			status = -EINVAL;  	int			offset; +	if (!desc) { +		pr_warn("%s: invalid GPIO\n", __func__); +		return -EINVAL; +	} +  	spin_lock_irqsave(&gpio_lock, flags); -	if (!desc) -		goto fail;  	chip = desc->chip;  	if (!chip || !chip->set || !chip->set_debounce)  		goto fail; @@ -1776,13 +1789,9 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)  fail:  	spin_unlock_irqrestore(&gpio_lock, flags); -	if (status) { -		int gpio = -1; -		if (desc) -			gpio = desc_to_gpio(desc); -		pr_debug("%s: gpio-%d status %d\n", -			__func__, gpio, status); -	} +	if (status) +		pr_debug("%s: gpio-%d status %d\n", __func__, +			 desc_to_gpio(desc), status);  	return status;  } @@ -1824,12 +1833,14 @@ 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.   */ -static int gpiod_get_value(struct gpio_desc *desc) +static int gpiod_get_value(const struct gpio_desc *desc)  {  	struct gpio_chip	*chip;  	int value;  	int offset; +	if (!desc) +		return 0;  	chip = desc->chip;  	offset = gpio_chip_hwgpio(desc);  	/* Should be using gpio_get_value_cansleep() */ @@ -1912,6 +1923,8 @@ static void gpiod_set_value(struct gpio_desc *desc, int value)  {  	struct gpio_chip	*chip; +	if (!desc) +		return;  	chip = desc->chip;  	/* Should be using gpio_set_value_cansleep() */  	WARN_ON(chip->can_sleep); @@ -1938,8 +1951,10 @@ 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.   */ -static int gpiod_cansleep(struct gpio_desc *desc) +static int gpiod_cansleep(const struct gpio_desc *desc)  { +	if (!desc) +		return 0;  	/* only call this on GPIOs that are valid! */  	return desc->chip->can_sleep;  } @@ -1959,11 +1974,13 @@ EXPORT_SYMBOL_GPL(__gpio_cansleep);   * It returns the number of the IRQ signaled by this (input) GPIO,   * or a negative errno.   */ -static int gpiod_to_irq(struct gpio_desc *desc) +static int gpiod_to_irq(const struct gpio_desc *desc)  {  	struct gpio_chip	*chip;  	int			offset; +	if (!desc) +		return -EINVAL;  	chip = desc->chip;  	offset = gpio_chip_hwgpio(desc);  	return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO; @@ -1980,13 +1997,15 @@ EXPORT_SYMBOL_GPL(__gpio_to_irq);   * Common examples include ones connected to I2C or SPI chips.   */ -static int gpiod_get_value_cansleep(struct gpio_desc *desc) +static int gpiod_get_value_cansleep(const struct gpio_desc *desc)  {  	struct gpio_chip	*chip;  	int value;  	int offset;  	might_sleep_if(extra_checks); +	if (!desc) +		return 0;  	chip = desc->chip;  	offset = gpio_chip_hwgpio(desc);  	value = chip->get ? chip->get(chip, offset) : 0; @@ -2005,6 +2024,8 @@ static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)  	struct gpio_chip	*chip;  	might_sleep_if(extra_checks); +	if (!desc) +		return;  	chip = desc->chip;  	trace_gpio_value(desc_to_gpio(desc), 0, value);  	if (test_bit(FLAG_OPEN_DRAIN,  &desc->flags))  |