forked from mirrors/linux
		
	gpio/omap: convert gpio irq domain to linear mapping
Currently the OMAP GPIO driver uses a legacy mapping for the GPIO IRQ domain. This is not necessary because we do not need to assign a specific interrupt number to the GPIO IRQ domain. Therefore, convert the OMAP GPIO driver to use a linear mapping instead. Please note that this also allows to simplify the logic in the OMAP gpio_irq_handler() routine, by using irq_find_mapping() to obtain the virtual irq number from the GPIO bank and bank index. Reported-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Jon Hunter <jon-hunter@ti.com> Reviewed-by: Felipe Balbi <balbi@ti.com> Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Acked-by: Kevin Hilman <khilman@linaro.org> Tested-by: Javier Martinez Canillas <javier@dowhile0.org> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
This commit is contained in:
		
							parent
							
								
									165b6c2f33
								
							
						
					
					
						commit
						ede4d7a5b9
					
				
					 1 changed files with 31 additions and 41 deletions
				
			
		|  | @ -53,7 +53,6 @@ struct gpio_bank { | ||||||
| 	struct list_head node; | 	struct list_head node; | ||||||
| 	void __iomem *base; | 	void __iomem *base; | ||||||
| 	u16 irq; | 	u16 irq; | ||||||
| 	int irq_base; |  | ||||||
| 	struct irq_domain *domain; | 	struct irq_domain *domain; | ||||||
| 	u32 non_wakeup_gpios; | 	u32 non_wakeup_gpios; | ||||||
| 	u32 enabled_non_wakeup_gpios; | 	u32 enabled_non_wakeup_gpios; | ||||||
|  | @ -89,7 +88,14 @@ struct gpio_bank { | ||||||
| 
 | 
 | ||||||
| static int irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq) | static int irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq) | ||||||
| { | { | ||||||
| 	return gpio_irq - bank->irq_base + bank->chip.base; | 	return bank->chip.base + gpio_irq; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int omap_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||||||
|  | { | ||||||
|  | 	struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip); | ||||||
|  | 
 | ||||||
|  | 	return irq_find_mapping(bank->domain, offset); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) | static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) | ||||||
|  | @ -427,7 +433,7 @@ static int gpio_irq_type(struct irq_data *d, unsigned type) | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 	if (!gpio) | 	if (!gpio) | ||||||
| 		gpio = irq_to_gpio(bank, d->irq); | 		gpio = irq_to_gpio(bank, d->hwirq); | ||||||
| 
 | 
 | ||||||
| 	if (type & ~IRQ_TYPE_SENSE_MASK) | 	if (type & ~IRQ_TYPE_SENSE_MASK) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
|  | @ -580,7 +586,7 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio) | ||||||
| static int gpio_wake_enable(struct irq_data *d, unsigned int enable) | static int gpio_wake_enable(struct irq_data *d, unsigned int enable) | ||||||
| { | { | ||||||
| 	struct gpio_bank *bank = irq_data_get_irq_chip_data(d); | 	struct gpio_bank *bank = irq_data_get_irq_chip_data(d); | ||||||
| 	unsigned int gpio = irq_to_gpio(bank, d->irq); | 	unsigned int gpio = irq_to_gpio(bank, d->hwirq); | ||||||
| 
 | 
 | ||||||
| 	return _set_gpio_wakeup(bank, gpio, enable); | 	return _set_gpio_wakeup(bank, gpio, enable); | ||||||
| } | } | ||||||
|  | @ -680,7 +686,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | ||||||
| { | { | ||||||
| 	void __iomem *isr_reg = NULL; | 	void __iomem *isr_reg = NULL; | ||||||
| 	u32 isr; | 	u32 isr; | ||||||
| 	unsigned int gpio_irq, gpio_index; | 	unsigned int i; | ||||||
| 	struct gpio_bank *bank; | 	struct gpio_bank *bank; | ||||||
| 	int unmasked = 0; | 	int unmasked = 0; | ||||||
| 	struct irq_chip *chip = irq_desc_get_chip(desc); | 	struct irq_chip *chip = irq_desc_get_chip(desc); | ||||||
|  | @ -721,15 +727,10 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | ||||||
| 		if (!isr) | 		if (!isr) | ||||||
| 			break; | 			break; | ||||||
| 
 | 
 | ||||||
| 		gpio_irq = bank->irq_base; | 		for (i = 0; isr != 0; isr >>= 1, i++) { | ||||||
| 		for (; isr != 0; isr >>= 1, gpio_irq++) { |  | ||||||
| 			int gpio = irq_to_gpio(bank, gpio_irq); |  | ||||||
| 
 |  | ||||||
| 			if (!(isr & 1)) | 			if (!(isr & 1)) | ||||||
| 				continue; | 				continue; | ||||||
| 
 | 
 | ||||||
| 			gpio_index = GPIO_INDEX(bank, gpio); |  | ||||||
| 
 |  | ||||||
| 			/*
 | 			/*
 | ||||||
| 			 * Some chips can't respond to both rising and falling | 			 * Some chips can't respond to both rising and falling | ||||||
| 			 * at the same time.  If this irq was requested with | 			 * at the same time.  If this irq was requested with | ||||||
|  | @ -737,10 +738,10 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | ||||||
| 			 * to respond to the IRQ for the opposite direction. | 			 * to respond to the IRQ for the opposite direction. | ||||||
| 			 * This will be indicated in the bank toggle_mask. | 			 * This will be indicated in the bank toggle_mask. | ||||||
| 			 */ | 			 */ | ||||||
| 			if (bank->toggle_mask & (1 << gpio_index)) | 			if (bank->toggle_mask & (1 << i)) | ||||||
| 				_toggle_gpio_edge_triggering(bank, gpio_index); | 				_toggle_gpio_edge_triggering(bank, i); | ||||||
| 
 | 
 | ||||||
| 			generic_handle_irq(gpio_irq); | 			generic_handle_irq(irq_find_mapping(bank->domain, i)); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	/* if bank has any level sensitive GPIO pin interrupt
 | 	/* if bank has any level sensitive GPIO pin interrupt
 | ||||||
|  | @ -756,7 +757,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | ||||||
| static void gpio_irq_shutdown(struct irq_data *d) | static void gpio_irq_shutdown(struct irq_data *d) | ||||||
| { | { | ||||||
| 	struct gpio_bank *bank = irq_data_get_irq_chip_data(d); | 	struct gpio_bank *bank = irq_data_get_irq_chip_data(d); | ||||||
| 	unsigned int gpio = irq_to_gpio(bank, d->irq); | 	unsigned int gpio = irq_to_gpio(bank, d->hwirq); | ||||||
| 	unsigned long flags; | 	unsigned long flags; | ||||||
| 
 | 
 | ||||||
| 	spin_lock_irqsave(&bank->lock, flags); | 	spin_lock_irqsave(&bank->lock, flags); | ||||||
|  | @ -767,7 +768,7 @@ static void gpio_irq_shutdown(struct irq_data *d) | ||||||
| static void gpio_ack_irq(struct irq_data *d) | static void gpio_ack_irq(struct irq_data *d) | ||||||
| { | { | ||||||
| 	struct gpio_bank *bank = irq_data_get_irq_chip_data(d); | 	struct gpio_bank *bank = irq_data_get_irq_chip_data(d); | ||||||
| 	unsigned int gpio = irq_to_gpio(bank, d->irq); | 	unsigned int gpio = irq_to_gpio(bank, d->hwirq); | ||||||
| 
 | 
 | ||||||
| 	_clear_gpio_irqstatus(bank, gpio); | 	_clear_gpio_irqstatus(bank, gpio); | ||||||
| } | } | ||||||
|  | @ -775,7 +776,7 @@ static void gpio_ack_irq(struct irq_data *d) | ||||||
| static void gpio_mask_irq(struct irq_data *d) | static void gpio_mask_irq(struct irq_data *d) | ||||||
| { | { | ||||||
| 	struct gpio_bank *bank = irq_data_get_irq_chip_data(d); | 	struct gpio_bank *bank = irq_data_get_irq_chip_data(d); | ||||||
| 	unsigned int gpio = irq_to_gpio(bank, d->irq); | 	unsigned int gpio = irq_to_gpio(bank, d->hwirq); | ||||||
| 	unsigned long flags; | 	unsigned long flags; | ||||||
| 
 | 
 | ||||||
| 	spin_lock_irqsave(&bank->lock, flags); | 	spin_lock_irqsave(&bank->lock, flags); | ||||||
|  | @ -787,7 +788,7 @@ static void gpio_mask_irq(struct irq_data *d) | ||||||
| static void gpio_unmask_irq(struct irq_data *d) | static void gpio_unmask_irq(struct irq_data *d) | ||||||
| { | { | ||||||
| 	struct gpio_bank *bank = irq_data_get_irq_chip_data(d); | 	struct gpio_bank *bank = irq_data_get_irq_chip_data(d); | ||||||
| 	unsigned int gpio = irq_to_gpio(bank, d->irq); | 	unsigned int gpio = irq_to_gpio(bank, d->hwirq); | ||||||
| 	unsigned int irq_mask = GPIO_BIT(bank, gpio); | 	unsigned int irq_mask = GPIO_BIT(bank, gpio); | ||||||
| 	u32 trigger = irqd_get_trigger_type(d); | 	u32 trigger = irqd_get_trigger_type(d); | ||||||
| 	unsigned long flags; | 	unsigned long flags; | ||||||
|  | @ -953,14 +954,6 @@ static void gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||||||
| 	spin_unlock_irqrestore(&bank->lock, flags); | 	spin_unlock_irqrestore(&bank->lock, flags); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int gpio_2irq(struct gpio_chip *chip, unsigned offset) |  | ||||||
| { |  | ||||||
| 	struct gpio_bank *bank; |  | ||||||
| 
 |  | ||||||
| 	bank = container_of(chip, struct gpio_bank, chip); |  | ||||||
| 	return bank->irq_base + offset; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /*---------------------------------------------------------------------*/ | /*---------------------------------------------------------------------*/ | ||||||
| 
 | 
 | ||||||
| static void __init omap_gpio_show_rev(struct gpio_bank *bank) | static void __init omap_gpio_show_rev(struct gpio_bank *bank) | ||||||
|  | @ -1057,7 +1050,7 @@ static void omap_gpio_chip_init(struct gpio_bank *bank) | ||||||
| 	bank->chip.direction_output = gpio_output; | 	bank->chip.direction_output = gpio_output; | ||||||
| 	bank->chip.set_debounce = gpio_debounce; | 	bank->chip.set_debounce = gpio_debounce; | ||||||
| 	bank->chip.set = gpio_set; | 	bank->chip.set = gpio_set; | ||||||
| 	bank->chip.to_irq = gpio_2irq; | 	bank->chip.to_irq = omap_gpio_to_irq; | ||||||
| 	if (bank->is_mpuio) { | 	if (bank->is_mpuio) { | ||||||
| 		bank->chip.label = "mpuio"; | 		bank->chip.label = "mpuio"; | ||||||
| 		if (bank->regs->wkup_en) | 		if (bank->regs->wkup_en) | ||||||
|  | @ -1072,15 +1065,16 @@ static void omap_gpio_chip_init(struct gpio_bank *bank) | ||||||
| 
 | 
 | ||||||
| 	gpiochip_add(&bank->chip); | 	gpiochip_add(&bank->chip); | ||||||
| 
 | 
 | ||||||
| 	for (j = bank->irq_base; j < bank->irq_base + bank->width; j++) { | 	for (j = 0; j < bank->width; j++) { | ||||||
| 		irq_set_lockdep_class(j, &gpio_lock_class); | 		int irq = irq_create_mapping(bank->domain, j); | ||||||
| 		irq_set_chip_data(j, bank); | 		irq_set_lockdep_class(irq, &gpio_lock_class); | ||||||
|  | 		irq_set_chip_data(irq, bank); | ||||||
| 		if (bank->is_mpuio) { | 		if (bank->is_mpuio) { | ||||||
| 			omap_mpuio_alloc_gc(bank, j, bank->width); | 			omap_mpuio_alloc_gc(bank, irq, bank->width); | ||||||
| 		} else { | 		} else { | ||||||
| 			irq_set_chip(j, &gpio_irq_chip); | 			irq_set_chip_and_handler(irq, &gpio_irq_chip, | ||||||
| 			irq_set_handler(j, handle_simple_irq); | 						 handle_simple_irq); | ||||||
| 			set_irq_flags(j, IRQF_VALID); | 			set_irq_flags(irq, IRQF_VALID); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	irq_set_chained_handler(bank->irq, gpio_irq_handler); | 	irq_set_chained_handler(bank->irq, gpio_irq_handler); | ||||||
|  | @ -1130,14 +1124,10 @@ static int omap_gpio_probe(struct platform_device *pdev) | ||||||
| 	bank->chip.of_node = of_node_get(node); | 	bank->chip.of_node = of_node_get(node); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 	bank->irq_base = irq_alloc_descs(-1, 0, bank->width, 0); | 	bank->domain = irq_domain_add_linear(node, bank->width, | ||||||
| 	if (bank->irq_base < 0) { | 					     &irq_domain_simple_ops, NULL); | ||||||
| 		dev_err(dev, "Couldn't allocate IRQ numbers\n"); | 	if (!bank->domain) | ||||||
| 		return -ENODEV; | 		return -ENODEV; | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	bank->domain = irq_domain_add_legacy(node, bank->width, bank->irq_base, |  | ||||||
| 					     0, &irq_domain_simple_ops, NULL); |  | ||||||
| 
 | 
 | ||||||
| 	if (bank->regs->set_dataout && bank->regs->clr_dataout) | 	if (bank->regs->set_dataout && bank->regs->clr_dataout) | ||||||
| 		bank->set_dataout = _set_gpio_dataout_reg; | 		bank->set_dataout = _set_gpio_dataout_reg; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Jon Hunter
						Jon Hunter