diff options
Diffstat (limited to 'drivers/gpio/gpio-omap.c')
| -rw-r--r-- | drivers/gpio/gpio-omap.c | 170 | 
1 files changed, 99 insertions, 71 deletions
| diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index b0c57d505be7..5236db161e76 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -29,6 +29,7 @@  #include <linux/platform_data/gpio-omap.h>  #define OFF_MODE	1 +#define OMAP4_GPIO_DEBOUNCINGTIME_MASK 0xFF  static LIST_HEAD(omap_gpio_list); @@ -57,7 +58,7 @@ struct gpio_bank {  	u32 saved_datain;  	u32 level_mask;  	u32 toggle_mask; -	spinlock_t lock; +	raw_spinlock_t lock;  	struct gpio_chip chip;  	struct clk *dbck;  	u32 mod_usage; @@ -175,7 +176,7 @@ static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set  static inline void omap_gpio_dbck_enable(struct gpio_bank *bank)  {  	if (bank->dbck_enable_mask && !bank->dbck_enabled) { -		clk_prepare_enable(bank->dbck); +		clk_enable(bank->dbck);  		bank->dbck_enabled = true;  		writel_relaxed(bank->dbck_enable_mask, @@ -193,7 +194,7 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)  		 */  		writel_relaxed(0, bank->base + bank->regs->debounce_en); -		clk_disable_unprepare(bank->dbck); +		clk_disable(bank->dbck);  		bank->dbck_enabled = false;  	}  } @@ -204,8 +205,9 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)   * @offset: the gpio number on this @bank   * @debounce: debounce time to use   * - * OMAP's debounce time is in 31us steps so we need - * to convert and round up to the closest unit. + * OMAP's debounce time is in 31us steps + *   <debounce time> = (GPIO_DEBOUNCINGTIME[7:0].DEBOUNCETIME + 1) x 31 + * so we need to convert and round up to the closest unit.   */  static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,  				    unsigned debounce) @@ -213,34 +215,33 @@ static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,  	void __iomem		*reg;  	u32			val;  	u32			l; +	bool			enable = !!debounce;  	if (!bank->dbck_flag)  		return; -	if (debounce < 32) -		debounce = 0x01; -	else if (debounce > 7936) -		debounce = 0xff; -	else -		debounce = (debounce / 0x1f) - 1; +	if (enable) { +		debounce = DIV_ROUND_UP(debounce, 31) - 1; +		debounce &= OMAP4_GPIO_DEBOUNCINGTIME_MASK; +	}  	l = BIT(offset); -	clk_prepare_enable(bank->dbck); +	clk_enable(bank->dbck);  	reg = bank->base + bank->regs->debounce;  	writel_relaxed(debounce, reg);  	reg = bank->base + bank->regs->debounce_en;  	val = readl_relaxed(reg); -	if (debounce) +	if (enable)  		val |= l;  	else  		val &= ~l;  	bank->dbck_enable_mask = val;  	writel_relaxed(val, reg); -	clk_disable_unprepare(bank->dbck); +	clk_disable(bank->dbck);  	/*  	 * Enable debounce clock per module.  	 * This call is mandatory because in omap_gpio_request() when @@ -285,7 +286,7 @@ static void omap_clear_gpio_debounce(struct gpio_bank *bank, unsigned offset)  		bank->context.debounce = 0;  		writel_relaxed(bank->context.debounce, bank->base +  			     bank->regs->debounce); -		clk_disable_unprepare(bank->dbck); +		clk_disable(bank->dbck);  		bank->dbck_enabled = false;  	}  } @@ -498,22 +499,24 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type)  	if (!BANK_USED(bank))  		pm_runtime_get_sync(bank->dev); -	spin_lock_irqsave(&bank->lock, flags); +	raw_spin_lock_irqsave(&bank->lock, flags);  	retval = omap_set_gpio_triggering(bank, offset, type); -	if (retval) +	if (retval) { +		raw_spin_unlock_irqrestore(&bank->lock, flags);  		goto error; +	}  	omap_gpio_init_irq(bank, offset);  	if (!omap_gpio_is_input(bank, offset)) { -		spin_unlock_irqrestore(&bank->lock, flags); +		raw_spin_unlock_irqrestore(&bank->lock, flags);  		retval = -EINVAL;  		goto error;  	} -	spin_unlock_irqrestore(&bank->lock, flags); +	raw_spin_unlock_irqrestore(&bank->lock, flags);  	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) -		__irq_set_handler_locked(d->irq, handle_level_irq); +		irq_set_handler_locked(d, handle_level_irq);  	else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) -		__irq_set_handler_locked(d->irq, handle_edge_irq); +		irq_set_handler_locked(d, handle_edge_irq);  	return 0; @@ -634,14 +637,14 @@ static int omap_set_gpio_wakeup(struct gpio_bank *bank, unsigned offset,  		return -EINVAL;  	} -	spin_lock_irqsave(&bank->lock, flags); +	raw_spin_lock_irqsave(&bank->lock, flags);  	if (enable)  		bank->context.wake_en |= gpio_bit;  	else  		bank->context.wake_en &= ~gpio_bit;  	writel_relaxed(bank->context.wake_en, bank->base + bank->regs->wkup_en); -	spin_unlock_irqrestore(&bank->lock, flags); +	raw_spin_unlock_irqrestore(&bank->lock, flags);  	return 0;  } @@ -667,10 +670,10 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)  	if (!BANK_USED(bank))  		pm_runtime_get_sync(bank->dev); -	spin_lock_irqsave(&bank->lock, flags); +	raw_spin_lock_irqsave(&bank->lock, flags);  	omap_enable_gpio_module(bank, offset);  	bank->mod_usage |= BIT(offset); -	spin_unlock_irqrestore(&bank->lock, flags); +	raw_spin_unlock_irqrestore(&bank->lock, flags);  	return 0;  } @@ -680,14 +683,14 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)  	struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);  	unsigned long flags; -	spin_lock_irqsave(&bank->lock, flags); +	raw_spin_lock_irqsave(&bank->lock, flags);  	bank->mod_usage &= ~(BIT(offset));  	if (!LINE_USED(bank->irq_usage, offset)) {  		omap_set_gpio_direction(bank, offset, 1);  		omap_clear_gpio_debounce(bank, offset);  	}  	omap_disable_gpio_module(bank, offset); -	spin_unlock_irqrestore(&bank->lock, flags); +	raw_spin_unlock_irqrestore(&bank->lock, flags);  	/*  	 * If this is the last gpio to be freed in the bank, @@ -706,7 +709,7 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)   * line's interrupt handler has been run, we may miss some nested   * interrupts.   */ -static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) +static void omap_gpio_irq_handler(struct irq_desc *desc)  {  	void __iomem *isr_reg = NULL;  	u32 isr; @@ -714,7 +717,8 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)  	struct gpio_bank *bank;  	int unmasked = 0;  	struct irq_chip *irqchip = irq_desc_get_chip(desc); -	struct gpio_chip *chip = irq_get_handler_data(irq); +	struct gpio_chip *chip = irq_desc_get_handler_data(desc); +	unsigned long lock_flags;  	chained_irq_enter(irqchip, desc); @@ -729,6 +733,8 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)  		u32 isr_saved, level_mask = 0;  		u32 enabled; +		raw_spin_lock_irqsave(&bank->lock, lock_flags); +  		enabled = omap_get_gpio_irqbank_mask(bank);  		isr_saved = isr = readl_relaxed(isr_reg) & enabled; @@ -742,6 +748,8 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)  		omap_clear_gpio_irqbank(bank, isr_saved & ~level_mask);  		omap_enable_gpio_irqbank(bank, isr_saved & ~level_mask); +		raw_spin_unlock_irqrestore(&bank->lock, lock_flags); +  		/* if there is only edge sensitive GPIO pin interrupts  		configured, we could unmask GPIO bank interrupt immediately */  		if (!level_mask && !unmasked) { @@ -756,6 +764,7 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)  			bit = __ffs(isr);  			isr &= ~(BIT(bit)); +			raw_spin_lock_irqsave(&bank->lock, lock_flags);  			/*  			 * Some chips can't respond to both rising and falling  			 * at the same time.  If this irq was requested with @@ -766,6 +775,8 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)  			if (bank->toggle_mask & (BIT(bit)))  				omap_toggle_gpio_edge_triggering(bank, bit); +			raw_spin_unlock_irqrestore(&bank->lock, lock_flags); +  			generic_handle_irq(irq_find_mapping(bank->chip.irqdomain,  							    bit));  		} @@ -789,7 +800,7 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d)  	if (!BANK_USED(bank))  		pm_runtime_get_sync(bank->dev); -	spin_lock_irqsave(&bank->lock, flags); +	raw_spin_lock_irqsave(&bank->lock, flags);  	if (!LINE_USED(bank->mod_usage, offset))  		omap_set_gpio_direction(bank, offset, 1); @@ -798,12 +809,12 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d)  	omap_enable_gpio_module(bank, offset);  	bank->irq_usage |= BIT(offset); -	spin_unlock_irqrestore(&bank->lock, flags); +	raw_spin_unlock_irqrestore(&bank->lock, flags);  	omap_gpio_unmask_irq(d);  	return 0;  err: -	spin_unlock_irqrestore(&bank->lock, flags); +	raw_spin_unlock_irqrestore(&bank->lock, flags);  	if (!BANK_USED(bank))  		pm_runtime_put(bank->dev);  	return -EINVAL; @@ -815,7 +826,7 @@ static void omap_gpio_irq_shutdown(struct irq_data *d)  	unsigned long flags;  	unsigned offset = d->hwirq; -	spin_lock_irqsave(&bank->lock, flags); +	raw_spin_lock_irqsave(&bank->lock, flags);  	bank->irq_usage &= ~(BIT(offset));  	omap_set_gpio_irqenable(bank, offset, 0);  	omap_clear_gpio_irqstatus(bank, offset); @@ -823,7 +834,7 @@ static void omap_gpio_irq_shutdown(struct irq_data *d)  	if (!LINE_USED(bank->mod_usage, offset))  		omap_clear_gpio_debounce(bank, offset);  	omap_disable_gpio_module(bank, offset); -	spin_unlock_irqrestore(&bank->lock, flags); +	raw_spin_unlock_irqrestore(&bank->lock, flags);  	/*  	 * If this is the last IRQ to be freed in the bank, @@ -847,10 +858,10 @@ static void omap_gpio_mask_irq(struct irq_data *d)  	unsigned offset = d->hwirq;  	unsigned long flags; -	spin_lock_irqsave(&bank->lock, flags); +	raw_spin_lock_irqsave(&bank->lock, flags);  	omap_set_gpio_irqenable(bank, offset, 0);  	omap_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE); -	spin_unlock_irqrestore(&bank->lock, flags); +	raw_spin_unlock_irqrestore(&bank->lock, flags);  }  static void omap_gpio_unmask_irq(struct irq_data *d) @@ -860,7 +871,7 @@ static void omap_gpio_unmask_irq(struct irq_data *d)  	u32 trigger = irqd_get_trigger_type(d);  	unsigned long flags; -	spin_lock_irqsave(&bank->lock, flags); +	raw_spin_lock_irqsave(&bank->lock, flags);  	if (trigger)  		omap_set_gpio_triggering(bank, offset, trigger); @@ -872,7 +883,7 @@ static void omap_gpio_unmask_irq(struct irq_data *d)  	}  	omap_set_gpio_irqenable(bank, offset, 1); -	spin_unlock_irqrestore(&bank->lock, flags); +	raw_spin_unlock_irqrestore(&bank->lock, flags);  }  /*---------------------------------------------------------------------*/ @@ -885,9 +896,9 @@ static int omap_mpuio_suspend_noirq(struct device *dev)  					OMAP_MPUIO_GPIO_MASKIT / bank->stride;  	unsigned long		flags; -	spin_lock_irqsave(&bank->lock, flags); +	raw_spin_lock_irqsave(&bank->lock, flags);  	writel_relaxed(0xffff & ~bank->context.wake_en, mask_reg); -	spin_unlock_irqrestore(&bank->lock, flags); +	raw_spin_unlock_irqrestore(&bank->lock, flags);  	return 0;  } @@ -900,9 +911,9 @@ static int omap_mpuio_resume_noirq(struct device *dev)  					OMAP_MPUIO_GPIO_MASKIT / bank->stride;  	unsigned long		flags; -	spin_lock_irqsave(&bank->lock, flags); +	raw_spin_lock_irqsave(&bank->lock, flags);  	writel_relaxed(bank->context.wake_en, mask_reg); -	spin_unlock_irqrestore(&bank->lock, flags); +	raw_spin_unlock_irqrestore(&bank->lock, flags);  	return 0;  } @@ -948,9 +959,9 @@ static int omap_gpio_get_direction(struct gpio_chip *chip, unsigned offset)  	bank = container_of(chip, struct gpio_bank, chip);  	reg = bank->base + bank->regs->direction; -	spin_lock_irqsave(&bank->lock, flags); +	raw_spin_lock_irqsave(&bank->lock, flags);  	dir = !!(readl_relaxed(reg) & BIT(offset)); -	spin_unlock_irqrestore(&bank->lock, flags); +	raw_spin_unlock_irqrestore(&bank->lock, flags);  	return dir;  } @@ -960,9 +971,9 @@ static int omap_gpio_input(struct gpio_chip *chip, unsigned offset)  	unsigned long flags;  	bank = container_of(chip, struct gpio_bank, chip); -	spin_lock_irqsave(&bank->lock, flags); +	raw_spin_lock_irqsave(&bank->lock, flags);  	omap_set_gpio_direction(bank, offset, 1); -	spin_unlock_irqrestore(&bank->lock, flags); +	raw_spin_unlock_irqrestore(&bank->lock, flags);  	return 0;  } @@ -984,10 +995,10 @@ static int omap_gpio_output(struct gpio_chip *chip, unsigned offset, int value)  	unsigned long flags;  	bank = container_of(chip, struct gpio_bank, chip); -	spin_lock_irqsave(&bank->lock, flags); +	raw_spin_lock_irqsave(&bank->lock, flags);  	bank->set_dataout(bank, offset, value);  	omap_set_gpio_direction(bank, offset, 0); -	spin_unlock_irqrestore(&bank->lock, flags); +	raw_spin_unlock_irqrestore(&bank->lock, flags);  	return 0;  } @@ -999,9 +1010,9 @@ static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset,  	bank = container_of(chip, struct gpio_bank, chip); -	spin_lock_irqsave(&bank->lock, flags); +	raw_spin_lock_irqsave(&bank->lock, flags);  	omap2_set_gpio_debounce(bank, offset, debounce); -	spin_unlock_irqrestore(&bank->lock, flags); +	raw_spin_unlock_irqrestore(&bank->lock, flags);  	return 0;  } @@ -1012,9 +1023,9 @@ static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value)  	unsigned long flags;  	bank = container_of(chip, struct gpio_bank, chip); -	spin_lock_irqsave(&bank->lock, flags); +	raw_spin_lock_irqsave(&bank->lock, flags);  	bank->set_dataout(bank, offset, value); -	spin_unlock_irqrestore(&bank->lock, flags); +	raw_spin_unlock_irqrestore(&bank->lock, flags);  }  /*---------------------------------------------------------------------*/ @@ -1059,10 +1070,6 @@ static void omap_gpio_mod_init(struct gpio_bank *bank)  	 /* Initialize interface clk ungated, module enabled */  	if (bank->regs->ctrl)  		writel_relaxed(0, base + bank->regs->ctrl); - -	bank->dbck = clk_get(bank->dev, "dbclk"); -	if (IS_ERR(bank->dbck)) -		dev_err(bank->dev, "Could not get gpio dbck\n");  }  static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) @@ -1091,7 +1098,6 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)  	} else {  		bank->chip.label = "gpio";  		bank->chip.base = gpio; -		gpio += bank->width;  	}  	bank->chip.ngpio = bank->width; @@ -1101,6 +1107,9 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)  		return ret;  	} +	if (!bank->is_mpuio) +		gpio += bank->width; +  #ifdef CONFIG_ARCH_OMAP1  	/*  	 * REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop @@ -1176,15 +1185,19 @@ static int omap_gpio_probe(struct platform_device *pdev)  	irqc->irq_set_wake = omap_gpio_wake_enable,  	irqc->name = dev_name(&pdev->dev); -	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); -	if (unlikely(!res)) { -		dev_err(dev, "Invalid IRQ resource\n"); -		return -ENODEV; +	bank->irq = platform_get_irq(pdev, 0); +	if (bank->irq <= 0) { +		if (!bank->irq) +			bank->irq = -ENXIO; +		if (bank->irq != -EPROBE_DEFER) +			dev_err(dev, +				"can't get irq resource ret=%d\n", bank->irq); +		return bank->irq;  	} -	bank->irq = res->start;  	bank->dev = dev;  	bank->chip.dev = dev; +	bank->chip.owner = THIS_MODULE;  	bank->dbck_flag = pdata->dbck_flag;  	bank->stride = pdata->bank_stride;  	bank->width = pdata->bank_width; @@ -1210,16 +1223,26 @@ static int omap_gpio_probe(struct platform_device *pdev)  	else  		bank->set_dataout = omap_set_gpio_dataout_mask; -	spin_lock_init(&bank->lock); +	raw_spin_lock_init(&bank->lock);  	/* Static mapping, never released */  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	bank->base = devm_ioremap_resource(dev, res);  	if (IS_ERR(bank->base)) { -		irq_domain_remove(bank->chip.irqdomain);  		return PTR_ERR(bank->base);  	} +	if (bank->dbck_flag) { +		bank->dbck = devm_clk_get(bank->dev, "dbclk"); +		if (IS_ERR(bank->dbck)) { +			dev_err(bank->dev, +				"Could not get gpio dbck. Disable debounce\n"); +			bank->dbck_flag = false; +		} else { +			clk_prepare(bank->dbck); +		} +	} +  	platform_set_drvdata(pdev, bank);  	pm_runtime_enable(bank->dev); @@ -1232,8 +1255,11 @@ static int omap_gpio_probe(struct platform_device *pdev)  	omap_gpio_mod_init(bank);  	ret = omap_gpio_chip_init(bank, irqc); -	if (ret) +	if (ret) { +		pm_runtime_put_sync(bank->dev); +		pm_runtime_disable(bank->dev);  		return ret; +	}  	omap_gpio_show_rev(bank); @@ -1251,6 +1277,8 @@ static int omap_gpio_remove(struct platform_device *pdev)  	list_del(&bank->node);  	gpiochip_remove(&bank->chip);  	pm_runtime_disable(bank->dev); +	if (bank->dbck_flag) +		clk_unprepare(bank->dbck);  	return 0;  } @@ -1268,7 +1296,7 @@ static int omap_gpio_runtime_suspend(struct device *dev)  	unsigned long flags;  	u32 wake_low, wake_hi; -	spin_lock_irqsave(&bank->lock, flags); +	raw_spin_lock_irqsave(&bank->lock, flags);  	/*  	 * Only edges can generate a wakeup event to the PRCM. @@ -1321,7 +1349,7 @@ update_gpio_context_count:  				bank->get_context_loss_count(bank->dev);  	omap_gpio_dbck_disable(bank); -	spin_unlock_irqrestore(&bank->lock, flags); +	raw_spin_unlock_irqrestore(&bank->lock, flags);  	return 0;  } @@ -1336,7 +1364,7 @@ static int omap_gpio_runtime_resume(struct device *dev)  	unsigned long flags;  	int c; -	spin_lock_irqsave(&bank->lock, flags); +	raw_spin_lock_irqsave(&bank->lock, flags);  	/*  	 * On the first resume during the probe, the context has not @@ -1372,14 +1400,14 @@ static int omap_gpio_runtime_resume(struct device *dev)  			if (c != bank->context_loss_count) {  				omap_gpio_restore_context(bank);  			} else { -				spin_unlock_irqrestore(&bank->lock, flags); +				raw_spin_unlock_irqrestore(&bank->lock, flags);  				return 0;  			}  		}  	}  	if (!bank->workaround_enabled) { -		spin_unlock_irqrestore(&bank->lock, flags); +		raw_spin_unlock_irqrestore(&bank->lock, flags);  		return 0;  	} @@ -1434,7 +1462,7 @@ static int omap_gpio_runtime_resume(struct device *dev)  	}  	bank->workaround_enabled = false; -	spin_unlock_irqrestore(&bank->lock, flags); +	raw_spin_unlock_irqrestore(&bank->lock, flags);  	return 0;  } |