mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-09-04 20:19:47 +08:00 
			
		
		
		
	gpio: Initialize the irqchip valid_mask with a callback
After changing the valid_mask for the struct gpio_chip to detect the need and presence of a valid mask with the presence of a .init_valid_mask() callback to fill it in, we augment the gpio_irq_chip to use the same logic. Switch all driver using the gpio_irq_chio valid_mask over to this new method. This makes sure the valid_mask for the gpio_irq_chip gets filled in when we add the gpio_chip, which makes it a little easier to switch over drivers using the old way of setting up gpio_irq_chip over to the new method of passing the gpio_irq_chip along with the gpio_chip. (See drivers/gpio/TODO for details.) Cc: Joel Stanley <joel@jms.id.au> Cc: Thierry Reding <treding@nvidia.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Tested-by: Hans de Goede <hdegoede@redhat.com> Reviewed-by: Andrew Jeffery <andrew@aj.id.au> Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Reviewed-by: Patrice Chotard <patrice.chotard@st.com> Link: https://lore.kernel.org/r/20190904140104.32426-1-linus.walleij@linaro.org
This commit is contained in:
		
							parent
							
								
									4f78d91c72
								
							
						
					
					
						commit
						5fbe5b5883
					
				| @ -689,8 +689,11 @@ static struct irq_chip aspeed_gpio_irqchip = { | |||||||
| 	.irq_set_type	= aspeed_gpio_set_type, | 	.irq_set_type	= aspeed_gpio_set_type, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static void set_irq_valid_mask(struct aspeed_gpio *gpio) | static void aspeed_init_irq_valid_mask(struct gpio_chip *gc, | ||||||
|  | 				       unsigned long *valid_mask, | ||||||
|  | 				       unsigned int ngpios) | ||||||
| { | { | ||||||
|  | 	struct aspeed_gpio *gpio = gpiochip_get_data(gc); | ||||||
| 	const struct aspeed_bank_props *props = gpio->config->props; | 	const struct aspeed_bank_props *props = gpio->config->props; | ||||||
| 
 | 
 | ||||||
| 	while (!is_bank_props_sentinel(props)) { | 	while (!is_bank_props_sentinel(props)) { | ||||||
| @ -704,7 +707,7 @@ static void set_irq_valid_mask(struct aspeed_gpio *gpio) | |||||||
| 			if (i >= gpio->config->nr_gpios) | 			if (i >= gpio->config->nr_gpios) | ||||||
| 				break; | 				break; | ||||||
| 
 | 
 | ||||||
| 			clear_bit(i, gpio->chip.irq.valid_mask); | 			clear_bit(i, valid_mask); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		props++; | 		props++; | ||||||
| @ -1203,7 +1206,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) | |||||||
| 		girq->parents[0] = gpio->irq; | 		girq->parents[0] = gpio->irq; | ||||||
| 		girq->default_type = IRQ_TYPE_NONE; | 		girq->default_type = IRQ_TYPE_NONE; | ||||||
| 		girq->handler = handle_bad_irq; | 		girq->handler = handle_bad_irq; | ||||||
| 		girq->need_valid_mask = true; | 		girq->init_valid_mask = aspeed_init_irq_valid_mask; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	gpio->offset_timer = | 	gpio->offset_timer = | ||||||
| @ -1215,10 +1218,6 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) | |||||||
| 	if (rc < 0) | 	if (rc < 0) | ||||||
| 		return rc; | 		return rc; | ||||||
| 
 | 
 | ||||||
| 	/* Now the valid mask is allocated */ |  | ||||||
| 	if (gpio->irq) |  | ||||||
| 		set_irq_valid_mask(gpio); |  | ||||||
| 
 |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -429,6 +429,23 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev) | |||||||
| 	return IRQ_HANDLED; | 	return IRQ_HANDLED; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void stmpe_init_irq_valid_mask(struct gpio_chip *gc, | ||||||
|  | 				      unsigned long *valid_mask, | ||||||
|  | 				      unsigned int ngpios) | ||||||
|  | { | ||||||
|  | 	struct stmpe_gpio *stmpe_gpio = gpiochip_get_data(gc); | ||||||
|  | 	int i; | ||||||
|  | 
 | ||||||
|  | 	if (!stmpe_gpio->norequest_mask) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	/* Forbid unused lines to be mapped as IRQs */ | ||||||
|  | 	for (i = 0; i < sizeof(u32); i++) { | ||||||
|  | 		if (stmpe_gpio->norequest_mask & BIT(i)) | ||||||
|  | 			clear_bit(i, valid_mask); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int stmpe_gpio_probe(struct platform_device *pdev) | static int stmpe_gpio_probe(struct platform_device *pdev) | ||||||
| { | { | ||||||
| 	struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); | 	struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); | ||||||
| @ -454,14 +471,21 @@ static int stmpe_gpio_probe(struct platform_device *pdev) | |||||||
| 	stmpe_gpio->chip.parent = &pdev->dev; | 	stmpe_gpio->chip.parent = &pdev->dev; | ||||||
| 	stmpe_gpio->chip.of_node = np; | 	stmpe_gpio->chip.of_node = np; | ||||||
| 	stmpe_gpio->chip.base = -1; | 	stmpe_gpio->chip.base = -1; | ||||||
|  | 	/*
 | ||||||
|  | 	 * REVISIT: this makes sure the valid mask gets allocated and | ||||||
|  | 	 * filled in when adding the gpio_chip, but the rest of the | ||||||
|  | 	 * gpio_irqchip is still filled in using the old method | ||||||
|  | 	 * in gpiochip_irqchip_add_nested() so clean this up once we | ||||||
|  | 	 * get the gpio_irqchip to initialize while adding the | ||||||
|  | 	 * gpio_chip also for threaded irqchips. | ||||||
|  | 	 */ | ||||||
|  | 	stmpe_gpio->chip.irq.init_valid_mask = stmpe_init_irq_valid_mask; | ||||||
| 
 | 
 | ||||||
| 	if (IS_ENABLED(CONFIG_DEBUG_FS)) | 	if (IS_ENABLED(CONFIG_DEBUG_FS)) | ||||||
|                 stmpe_gpio->chip.dbg_show = stmpe_dbg_show; |                 stmpe_gpio->chip.dbg_show = stmpe_dbg_show; | ||||||
| 
 | 
 | ||||||
| 	of_property_read_u32(np, "st,norequest-mask", | 	of_property_read_u32(np, "st,norequest-mask", | ||||||
| 			&stmpe_gpio->norequest_mask); | 			&stmpe_gpio->norequest_mask); | ||||||
| 	if (stmpe_gpio->norequest_mask) |  | ||||||
| 		stmpe_gpio->chip.irq.need_valid_mask = true; |  | ||||||
| 
 | 
 | ||||||
| 	irq = platform_get_irq(pdev, 0); | 	irq = platform_get_irq(pdev, 0); | ||||||
| 	if (irq < 0) | 	if (irq < 0) | ||||||
| @ -487,14 +511,6 @@ static int stmpe_gpio_probe(struct platform_device *pdev) | |||||||
| 			dev_err(&pdev->dev, "unable to get irq: %d\n", ret); | 			dev_err(&pdev->dev, "unable to get irq: %d\n", ret); | ||||||
| 			goto out_disable; | 			goto out_disable; | ||||||
| 		} | 		} | ||||||
| 		if (stmpe_gpio->norequest_mask) { |  | ||||||
| 			int i; |  | ||||||
| 
 |  | ||||||
| 			/* Forbid unused lines to be mapped as IRQs */ |  | ||||||
| 			for (i = 0; i < sizeof(u32); i++) |  | ||||||
| 				if (stmpe_gpio->norequest_mask & BIT(i)) |  | ||||||
| 					clear_bit(i, stmpe_gpio->chip.irq.valid_mask); |  | ||||||
| 		} |  | ||||||
| 		ret =  gpiochip_irqchip_add_nested(&stmpe_gpio->chip, | 		ret =  gpiochip_irqchip_add_nested(&stmpe_gpio->chip, | ||||||
| 						   &stmpe_gpio_irq_chip, | 						   &stmpe_gpio_irq_chip, | ||||||
| 						   0, | 						   0, | ||||||
|  | |||||||
| @ -214,6 +214,17 @@ static const struct dev_pm_ops tqmx86_gpio_dev_pm_ops = { | |||||||
| 			   tqmx86_gpio_runtime_resume, NULL) | 			   tqmx86_gpio_runtime_resume, NULL) | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | static void tqmx86_init_irq_valid_mask(struct gpio_chip *chip, | ||||||
|  | 				       unsigned long *valid_mask, | ||||||
|  | 				       unsigned int ngpios) | ||||||
|  | { | ||||||
|  | 	/* Only GPIOs 4-7 are valid for interrupts. Clear the others */ | ||||||
|  | 	clear_bit(0, valid_mask); | ||||||
|  | 	clear_bit(1, valid_mask); | ||||||
|  | 	clear_bit(2, valid_mask); | ||||||
|  | 	clear_bit(3, valid_mask); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int tqmx86_gpio_probe(struct platform_device *pdev) | static int tqmx86_gpio_probe(struct platform_device *pdev) | ||||||
| { | { | ||||||
| 	struct device *dev = &pdev->dev; | 	struct device *dev = &pdev->dev; | ||||||
| @ -260,7 +271,6 @@ static int tqmx86_gpio_probe(struct platform_device *pdev) | |||||||
| 	chip->get = tqmx86_gpio_get; | 	chip->get = tqmx86_gpio_get; | ||||||
| 	chip->set = tqmx86_gpio_set; | 	chip->set = tqmx86_gpio_set; | ||||||
| 	chip->ngpio = TQMX86_NGPIO; | 	chip->ngpio = TQMX86_NGPIO; | ||||||
| 	chip->irq.need_valid_mask = true; |  | ||||||
| 	chip->parent = pdev->dev.parent; | 	chip->parent = pdev->dev.parent; | ||||||
| 
 | 
 | ||||||
| 	pm_runtime_enable(&pdev->dev); | 	pm_runtime_enable(&pdev->dev); | ||||||
| @ -296,6 +306,7 @@ static int tqmx86_gpio_probe(struct platform_device *pdev) | |||||||
| 		girq->parents[0] = irq; | 		girq->parents[0] = irq; | ||||||
| 		girq->default_type = IRQ_TYPE_NONE; | 		girq->default_type = IRQ_TYPE_NONE; | ||||||
| 		girq->handler = handle_simple_irq; | 		girq->handler = handle_simple_irq; | ||||||
|  | 		girq->init_valid_mask = tqmx86_init_irq_valid_mask; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	ret = devm_gpiochip_add_data(dev, chip, gpio); | 	ret = devm_gpiochip_add_data(dev, chip, gpio); | ||||||
| @ -304,14 +315,6 @@ static int tqmx86_gpio_probe(struct platform_device *pdev) | |||||||
| 		goto out_pm_dis; | 		goto out_pm_dis; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Only GPIOs 4-7 are valid for interrupts. Clear the others */ |  | ||||||
| 	if (irq) { |  | ||||||
| 		clear_bit(0, girq->valid_mask); |  | ||||||
| 		clear_bit(1, girq->valid_mask); |  | ||||||
| 		clear_bit(2, girq->valid_mask); |  | ||||||
| 		clear_bit(3, girq->valid_mask); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	dev_info(dev, "GPIO functionality initialized with %d pins\n", | 	dev_info(dev, "GPIO functionality initialized with %d pins\n", | ||||||
| 		 chip->ngpio); | 		 chip->ngpio); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1615,15 +1615,19 @@ static struct gpio_chip *find_chip_by_name(const char *name) | |||||||
|  * The following is irqchip helper code for gpiochips. |  * The following is irqchip helper code for gpiochips. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip) | static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gc) | ||||||
| { | { | ||||||
| 	if (!gpiochip->irq.need_valid_mask) | 	struct gpio_irq_chip *girq = &gc->irq; | ||||||
|  | 
 | ||||||
|  | 	if (!girq->init_valid_mask) | ||||||
| 		return 0; | 		return 0; | ||||||
| 
 | 
 | ||||||
| 	gpiochip->irq.valid_mask = gpiochip_allocate_mask(gpiochip); | 	girq->valid_mask = gpiochip_allocate_mask(gc); | ||||||
| 	if (!gpiochip->irq.valid_mask) | 	if (!girq->valid_mask) | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 
 | 
 | ||||||
|  | 	girq->init_valid_mask(gc, girq->valid_mask, gc->ngpio); | ||||||
|  | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1455,6 +1455,20 @@ static void byt_gpio_irq_handler(struct irq_desc *desc) | |||||||
| 	chip->irq_eoi(data); | 	chip->irq_eoi(data); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void byt_init_irq_valid_mask(struct gpio_chip *chip, | ||||||
|  | 				    unsigned long *valid_mask, | ||||||
|  | 				    unsigned int ngpios) | ||||||
|  | { | ||||||
|  | 	/*
 | ||||||
|  | 	 * FIXME: currently the valid_mask is filled in as part of | ||||||
|  | 	 * initializing the irq_chip below in byt_gpio_irq_init_hw(). | ||||||
|  | 	 * when converting this driver to the new way of passing the | ||||||
|  | 	 * gpio_irq_chip along when adding the gpio_chip, move the | ||||||
|  | 	 * mask initialization into this callback instead. Right now | ||||||
|  | 	 * this callback is here to make sure the mask gets allocated. | ||||||
|  | 	 */ | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static void byt_gpio_irq_init_hw(struct byt_gpio *vg) | static void byt_gpio_irq_init_hw(struct byt_gpio *vg) | ||||||
| { | { | ||||||
| 	struct gpio_chip *gc = &vg->chip; | 	struct gpio_chip *gc = &vg->chip; | ||||||
| @ -1525,7 +1539,7 @@ static int byt_gpio_probe(struct byt_gpio *vg) | |||||||
| 	gc->can_sleep	= false; | 	gc->can_sleep	= false; | ||||||
| 	gc->parent	= &vg->pdev->dev; | 	gc->parent	= &vg->pdev->dev; | ||||||
| 	gc->ngpio	= vg->soc_data->npins; | 	gc->ngpio	= vg->soc_data->npins; | ||||||
| 	gc->irq.need_valid_mask	= true; | 	gc->irq.init_valid_mask	= byt_init_irq_valid_mask; | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_PM_SLEEP | #ifdef CONFIG_PM_SLEEP | ||||||
| 	vg->saved_context = devm_kcalloc(&vg->pdev->dev, gc->ngpio, | 	vg->saved_context = devm_kcalloc(&vg->pdev->dev, gc->ngpio, | ||||||
|  | |||||||
| @ -1543,6 +1543,30 @@ static const struct dmi_system_id chv_no_valid_mask[] = { | |||||||
| 	{} | 	{} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | static void chv_init_irq_valid_mask(struct gpio_chip *chip, | ||||||
|  | 				    unsigned long *valid_mask, | ||||||
|  | 				    unsigned int ngpios) | ||||||
|  | { | ||||||
|  | 	struct chv_pinctrl *pctrl = gpiochip_get_data(chip); | ||||||
|  | 	const struct chv_community *community = pctrl->community; | ||||||
|  | 	int i; | ||||||
|  | 
 | ||||||
|  | 	/* Do not add GPIOs that can only generate GPEs to the IRQ domain */ | ||||||
|  | 	for (i = 0; i < community->npins; i++) { | ||||||
|  | 		const struct pinctrl_pin_desc *desc; | ||||||
|  | 		u32 intsel; | ||||||
|  | 
 | ||||||
|  | 		desc = &community->pins[i]; | ||||||
|  | 
 | ||||||
|  | 		intsel = readl(chv_padreg(pctrl, desc->number, CHV_PADCTRL0)); | ||||||
|  | 		intsel &= CHV_PADCTRL0_INTSEL_MASK; | ||||||
|  | 		intsel >>= CHV_PADCTRL0_INTSEL_SHIFT; | ||||||
|  | 
 | ||||||
|  | 		if (intsel >= community->nirqs) | ||||||
|  | 			clear_bit(i, valid_mask); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq) | static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq) | ||||||
| { | { | ||||||
| 	const struct chv_gpio_pinrange *range; | 	const struct chv_gpio_pinrange *range; | ||||||
| @ -1557,7 +1581,8 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq) | |||||||
| 	chip->label = dev_name(pctrl->dev); | 	chip->label = dev_name(pctrl->dev); | ||||||
| 	chip->parent = pctrl->dev; | 	chip->parent = pctrl->dev; | ||||||
| 	chip->base = -1; | 	chip->base = -1; | ||||||
| 	chip->irq.need_valid_mask = need_valid_mask; | 	if (need_valid_mask) | ||||||
|  | 		chip->irq.init_valid_mask = chv_init_irq_valid_mask; | ||||||
| 
 | 
 | ||||||
| 	ret = devm_gpiochip_add_data(pctrl->dev, chip, pctrl); | 	ret = devm_gpiochip_add_data(pctrl->dev, chip, pctrl); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
| @ -1576,21 +1601,6 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Do not add GPIOs that can only generate GPEs to the IRQ domain */ |  | ||||||
| 	for (i = 0; i < community->npins; i++) { |  | ||||||
| 		const struct pinctrl_pin_desc *desc; |  | ||||||
| 		u32 intsel; |  | ||||||
| 
 |  | ||||||
| 		desc = &community->pins[i]; |  | ||||||
| 
 |  | ||||||
| 		intsel = readl(chv_padreg(pctrl, desc->number, CHV_PADCTRL0)); |  | ||||||
| 		intsel &= CHV_PADCTRL0_INTSEL_MASK; |  | ||||||
| 		intsel >>= CHV_PADCTRL0_INTSEL_SHIFT; |  | ||||||
| 
 |  | ||||||
| 		if (need_valid_mask && intsel >= community->nirqs) |  | ||||||
| 			clear_bit(i, chip->irq.valid_mask); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * The same set of machines in chv_no_valid_mask[] have incorrectly | 	 * The same set of machines in chv_no_valid_mask[] have incorrectly | ||||||
| 	 * configured GPIOs that generate spurious interrupts so we use | 	 * configured GPIOs that generate spurious interrupts so we use | ||||||
|  | |||||||
| @ -152,6 +152,13 @@ static const struct x86_cpu_id int0002_cpu_ids[] = { | |||||||
| 	{} | 	{} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | static void int0002_init_irq_valid_mask(struct gpio_chip *chip, | ||||||
|  | 					unsigned long *valid_mask, | ||||||
|  | 					unsigned int ngpios) | ||||||
|  | { | ||||||
|  | 	bitmap_clear(valid_mask, 0, GPE0A_PME_B0_VIRT_GPIO_PIN); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int int0002_probe(struct platform_device *pdev) | static int int0002_probe(struct platform_device *pdev) | ||||||
| { | { | ||||||
| 	struct device *dev = &pdev->dev; | 	struct device *dev = &pdev->dev; | ||||||
| @ -184,7 +191,7 @@ static int int0002_probe(struct platform_device *pdev) | |||||||
| 	chip->direction_output = int0002_gpio_direction_output; | 	chip->direction_output = int0002_gpio_direction_output; | ||||||
| 	chip->base = -1; | 	chip->base = -1; | ||||||
| 	chip->ngpio = GPE0A_PME_B0_VIRT_GPIO_PIN + 1; | 	chip->ngpio = GPE0A_PME_B0_VIRT_GPIO_PIN + 1; | ||||||
| 	chip->irq.need_valid_mask = true; | 	chip->irq.init_valid_mask = int0002_init_irq_valid_mask; | ||||||
| 
 | 
 | ||||||
| 	ret = devm_gpiochip_add_data(&pdev->dev, chip, NULL); | 	ret = devm_gpiochip_add_data(&pdev->dev, chip, NULL); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
| @ -192,8 +199,6 @@ static int int0002_probe(struct platform_device *pdev) | |||||||
| 		return ret; | 		return ret; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	bitmap_clear(chip->irq.valid_mask, 0, GPE0A_PME_B0_VIRT_GPIO_PIN); |  | ||||||
| 
 |  | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * We manually request the irq here instead of passing a flow-handler | 	 * We manually request the irq here instead of passing a flow-handler | ||||||
| 	 * to gpiochip_set_chained_irqchip, because the irq is shared. | 	 * to gpiochip_set_chained_irqchip, because the irq is shared. | ||||||
|  | |||||||
| @ -202,11 +202,17 @@ struct gpio_irq_chip { | |||||||
| 	bool threaded; | 	bool threaded; | ||||||
| 
 | 
 | ||||||
| 	/**
 | 	/**
 | ||||||
| 	 * @need_valid_mask: | 	 * @init_valid_mask: optional routine to initialize @valid_mask, to be | ||||||
| 	 * | 	 * used if not all GPIO lines are valid interrupts. Sometimes some | ||||||
| 	 * If set core allocates @valid_mask with all bits set to one. | 	 * lines just cannot fire interrupts, and this routine, when defined, | ||||||
|  | 	 * is passed a bitmap in "valid_mask" and it will have ngpios | ||||||
|  | 	 * bits from 0..(ngpios-1) set to "1" as in valid. The callback can | ||||||
|  | 	 * then directly set some bits to "0" if they cannot be used for | ||||||
|  | 	 * interrupts. | ||||||
| 	 */ | 	 */ | ||||||
| 	bool need_valid_mask; | 	void (*init_valid_mask)(struct gpio_chip *chip, | ||||||
|  | 				unsigned long *valid_mask, | ||||||
|  | 				unsigned int ngpios); | ||||||
| 
 | 
 | ||||||
| 	/**
 | 	/**
 | ||||||
| 	 * @valid_mask: | 	 * @valid_mask: | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Linus Walleij
						Linus Walleij