mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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