diff options
Diffstat (limited to 'drivers/gpio/gpio-omap.c')
| -rw-r--r-- | drivers/gpio/gpio-omap.c | 1293 | 
1 files changed, 620 insertions, 673 deletions
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 0b056297917..1adc2ec1e38 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -19,8 +19,12 @@  #include <linux/err.h>  #include <linux/clk.h>  #include <linux/io.h> -#include <linux/slab.h> +#include <linux/device.h>  #include <linux/pm_runtime.h> +#include <linux/pm.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/irqdomain.h>  #include <mach/hardware.h>  #include <asm/irq.h> @@ -28,19 +32,36 @@  #include <asm/gpio.h>  #include <asm/mach/irq.h> +#define OFF_MODE	1 + +static LIST_HEAD(omap_gpio_list); + +struct gpio_regs { +	u32 irqenable1; +	u32 irqenable2; +	u32 wake_en; +	u32 ctrl; +	u32 oe; +	u32 leveldetect0; +	u32 leveldetect1; +	u32 risingdetect; +	u32 fallingdetect; +	u32 dataout; +	u32 debounce; +	u32 debounce_en; +}; +  struct gpio_bank { -	unsigned long pbase; +	struct list_head node;  	void __iomem *base;  	u16 irq; -	u16 virtual_irq_start; -	int method; +	int irq_base; +	struct irq_domain *domain;  	u32 suspend_wakeup; -#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)  	u32 saved_wakeup; -#endif  	u32 non_wakeup_gpios;  	u32 enabled_non_wakeup_gpios; - +	struct gpio_regs context;  	u32 saved_datain;  	u32 saved_fallingdetect;  	u32 saved_risingdetect; @@ -51,44 +72,31 @@ struct gpio_bank {  	struct clk *dbck;  	u32 mod_usage;  	u32 dbck_enable_mask; +	bool dbck_enabled;  	struct device *dev; +	bool is_mpuio;  	bool dbck_flag; +	bool loses_context;  	int stride;  	u32 width; +	int context_loss_count; +	int power_mode; +	bool workaround_enabled;  	void (*set_dataout)(struct gpio_bank *bank, int gpio, int enable); +	int (*get_context_loss_count)(struct device *dev);  	struct omap_gpio_reg_offs *regs;  }; -#ifdef CONFIG_ARCH_OMAP3 -struct omap3_gpio_regs { -	u32 irqenable1; -	u32 irqenable2; -	u32 wake_en; -	u32 ctrl; -	u32 oe; -	u32 leveldetect0; -	u32 leveldetect1; -	u32 risingdetect; -	u32 fallingdetect; -	u32 dataout; -}; - -static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS]; -#endif - -/* - * TODO: Cleanup gpio_bank usage as it is having information - * related to all instances of the device - */ -static struct gpio_bank *gpio_bank; - -/* TODO: Analyze removing gpio_bank_count usage from driver code */ -int gpio_bank_count; -  #define GPIO_INDEX(bank, gpio) (gpio % bank->width)  #define GPIO_BIT(bank, gpio) (1 << GPIO_INDEX(bank, gpio)) +#define GPIO_MOD_CTRL_BIT	BIT(0) + +static int irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq) +{ +	return gpio_irq - bank->irq_base + bank->chip.base; +}  static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)  { @@ -102,6 +110,7 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)  	else  		l &= ~(1 << gpio);  	__raw_writel(l, reg); +	bank->context.oe = l;  } @@ -111,10 +120,13 @@ static void _set_gpio_dataout_reg(struct gpio_bank *bank, int gpio, int enable)  	void __iomem *reg = bank->base;  	u32 l = GPIO_BIT(bank, gpio); -	if (enable) +	if (enable) {  		reg += bank->regs->set_dataout; -	else +		bank->context.dataout |= l; +	} else {  		reg += bank->regs->clr_dataout; +		bank->context.dataout &= ~l; +	}  	__raw_writel(l, reg);  } @@ -132,27 +144,28 @@ static void _set_gpio_dataout_mask(struct gpio_bank *bank, int gpio, int enable)  	else  		l &= ~gpio_bit;  	__raw_writel(l, reg); +	bank->context.dataout = l;  } -static int _get_gpio_datain(struct gpio_bank *bank, int gpio) +static int _get_gpio_datain(struct gpio_bank *bank, int offset)  {  	void __iomem *reg = bank->base + bank->regs->datain; -	return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0; +	return (__raw_readl(reg) & (1 << offset)) != 0;  } -static int _get_gpio_dataout(struct gpio_bank *bank, int gpio) +static int _get_gpio_dataout(struct gpio_bank *bank, int offset)  {  	void __iomem *reg = bank->base + bank->regs->dataout; -	return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0; +	return (__raw_readl(reg) & (1 << offset)) != 0;  }  static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)  {  	int l = __raw_readl(base + reg); -	if (set)  +	if (set)  		l |= mask;  	else  		l &= ~mask; @@ -160,6 +173,22 @@ static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)  	__raw_writel(l, base + reg);  } +static inline void _gpio_dbck_enable(struct gpio_bank *bank) +{ +	if (bank->dbck_enable_mask && !bank->dbck_enabled) { +		clk_enable(bank->dbck); +		bank->dbck_enabled = true; +	} +} + +static inline void _gpio_dbck_disable(struct gpio_bank *bank) +{ +	if (bank->dbck_enable_mask && bank->dbck_enabled) { +		clk_disable(bank->dbck); +		bank->dbck_enabled = false; +	} +} +  /**   * _set_gpio_debounce - low level gpio debounce time   * @bank: the gpio bank we're acting upon @@ -188,70 +217,74 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,  	l = GPIO_BIT(bank, gpio); +	clk_enable(bank->dbck);  	reg = bank->base + bank->regs->debounce;  	__raw_writel(debounce, reg);  	reg = bank->base + bank->regs->debounce_en;  	val = __raw_readl(reg); -	if (debounce) { +	if (debounce)  		val |= l; -		clk_enable(bank->dbck); -	} else { +	else  		val &= ~l; -		clk_disable(bank->dbck); -	}  	bank->dbck_enable_mask = val;  	__raw_writel(val, reg); +	clk_disable(bank->dbck); +	/* +	 * Enable debounce clock per module. +	 * This call is mandatory because in omap_gpio_request() when +	 * *_runtime_get_sync() is called,  _gpio_dbck_enable() within +	 * runtime callbck fails to turn on dbck because dbck_enable_mask +	 * used within _gpio_dbck_enable() is still not initialized at +	 * that point. Therefore we have to enable dbck here. +	 */ +	_gpio_dbck_enable(bank); +	if (bank->dbck_enable_mask) { +		bank->context.debounce = debounce; +		bank->context.debounce_en = val; +	}  } -#ifdef CONFIG_ARCH_OMAP2PLUS -static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, -						int trigger) +static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio, +						unsigned trigger)  {  	void __iomem *base = bank->base;  	u32 gpio_bit = 1 << gpio; -	if (cpu_is_omap44xx()) { -		_gpio_rmw(base, OMAP4_GPIO_LEVELDETECT0, gpio_bit, -			  trigger & IRQ_TYPE_LEVEL_LOW); -		_gpio_rmw(base, OMAP4_GPIO_LEVELDETECT1, gpio_bit, -			  trigger & IRQ_TYPE_LEVEL_HIGH); -		_gpio_rmw(base, OMAP4_GPIO_RISINGDETECT, gpio_bit, -			  trigger & IRQ_TYPE_EDGE_RISING); -		_gpio_rmw(base, OMAP4_GPIO_FALLINGDETECT, gpio_bit, -			  trigger & IRQ_TYPE_EDGE_FALLING); -	} else { -		_gpio_rmw(base, OMAP24XX_GPIO_LEVELDETECT0, gpio_bit, -			  trigger & IRQ_TYPE_LEVEL_LOW); -		_gpio_rmw(base, OMAP24XX_GPIO_LEVELDETECT1, gpio_bit, -			  trigger & IRQ_TYPE_LEVEL_HIGH); -		_gpio_rmw(base, OMAP24XX_GPIO_RISINGDETECT, gpio_bit, -			  trigger & IRQ_TYPE_EDGE_RISING); -		_gpio_rmw(base, OMAP24XX_GPIO_FALLINGDETECT, gpio_bit, -			  trigger & IRQ_TYPE_EDGE_FALLING); -	} +	_gpio_rmw(base, bank->regs->leveldetect0, gpio_bit, +		  trigger & IRQ_TYPE_LEVEL_LOW); +	_gpio_rmw(base, bank->regs->leveldetect1, gpio_bit, +		  trigger & IRQ_TYPE_LEVEL_HIGH); +	_gpio_rmw(base, bank->regs->risingdetect, gpio_bit, +		  trigger & IRQ_TYPE_EDGE_RISING); +	_gpio_rmw(base, bank->regs->fallingdetect, gpio_bit, +		  trigger & IRQ_TYPE_EDGE_FALLING); + +	bank->context.leveldetect0 = +			__raw_readl(bank->base + bank->regs->leveldetect0); +	bank->context.leveldetect1 = +			__raw_readl(bank->base + bank->regs->leveldetect1); +	bank->context.risingdetect = +			__raw_readl(bank->base + bank->regs->risingdetect); +	bank->context.fallingdetect = +			__raw_readl(bank->base + bank->regs->fallingdetect); +  	if (likely(!(bank->non_wakeup_gpios & gpio_bit))) { -		if (cpu_is_omap44xx()) { -			_gpio_rmw(base, OMAP4_GPIO_IRQWAKEN0, gpio_bit, -				  trigger != 0); -		} else { -			/* -			 * GPIO wakeup request can only be generated on edge -			 * transitions -			 */ -			if (trigger & IRQ_TYPE_EDGE_BOTH) -				__raw_writel(1 << gpio, bank->base -					+ OMAP24XX_GPIO_SETWKUENA); -			else -				__raw_writel(1 << gpio, bank->base -					+ OMAP24XX_GPIO_CLEARWKUENA); -		} +		_gpio_rmw(base, bank->regs->wkup_en, gpio_bit, trigger != 0); +		bank->context.wake_en = +			__raw_readl(bank->base + bank->regs->wkup_en);  	} +  	/* This part needs to be executed always for OMAP{34xx, 44xx} */ -	if (cpu_is_omap34xx() || cpu_is_omap44xx() || -			(bank->non_wakeup_gpios & gpio_bit)) { +	if (!bank->regs->irqctrl) { +		/* On omap24xx proceed only when valid GPIO bit is set */ +		if (bank->non_wakeup_gpios) { +			if (!(bank->non_wakeup_gpios & gpio_bit)) +				goto exit; +		} +  		/*  		 * Log the edge gpio and manually trigger the IRQ  		 * after resume if the input level changes @@ -264,17 +297,11 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,  			bank->enabled_non_wakeup_gpios &= ~gpio_bit;  	} -	if (cpu_is_omap44xx()) { -		bank->level_mask = -			__raw_readl(bank->base + OMAP4_GPIO_LEVELDETECT0) | -			__raw_readl(bank->base + OMAP4_GPIO_LEVELDETECT1); -	} else { -		bank->level_mask = -			__raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0) | -			__raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1); -	} +exit: +	bank->level_mask = +		__raw_readl(bank->base + bank->regs->leveldetect0) | +		__raw_readl(bank->base + bank->regs->leveldetect1);  } -#endif  #ifdef CONFIG_ARCH_OMAP1  /* @@ -286,23 +313,10 @@ static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)  	void __iomem *reg = bank->base;  	u32 l = 0; -	switch (bank->method) { -	case METHOD_MPUIO: -		reg += OMAP_MPUIO_GPIO_INT_EDGE / bank->stride; -		break; -#ifdef CONFIG_ARCH_OMAP15XX -	case METHOD_GPIO_1510: -		reg += OMAP1510_GPIO_INT_CONTROL; -		break; -#endif -#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) -	case METHOD_GPIO_7XX: -		reg += OMAP7XX_GPIO_INT_CONTROL; -		break; -#endif -	default: +	if (!bank->regs->irqctrl)  		return; -	} + +	reg += bank->regs->irqctrl;  	l = __raw_readl(reg);  	if ((l >> gpio) & 1) @@ -312,31 +326,22 @@ static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)  	__raw_writel(l, reg);  } +#else +static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) {}  #endif -static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) +static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, +							unsigned trigger)  {  	void __iomem *reg = bank->base; +	void __iomem *base = bank->base;  	u32 l = 0; -	switch (bank->method) { -#ifdef CONFIG_ARCH_OMAP1 -	case METHOD_MPUIO: -		reg += OMAP_MPUIO_GPIO_INT_EDGE / bank->stride; -		l = __raw_readl(reg); -		if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) -			bank->toggle_mask |= 1 << gpio; -		if (trigger & IRQ_TYPE_EDGE_RISING) -			l |= 1 << gpio; -		else if (trigger & IRQ_TYPE_EDGE_FALLING) -			l &= ~(1 << gpio); -		else -			goto bad; -		break; -#endif -#ifdef CONFIG_ARCH_OMAP15XX -	case METHOD_GPIO_1510: -		reg += OMAP1510_GPIO_INT_CONTROL; +	if (bank->regs->leveldetect0 && bank->regs->wkup_en) { +		set_gpio_trigger(bank, gpio, trigger); +	} else if (bank->regs->irqctrl) { +		reg += bank->regs->irqctrl; +  		l = __raw_readl(reg);  		if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)  			bank->toggle_mask |= 1 << gpio; @@ -345,15 +350,15 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)  		else if (trigger & IRQ_TYPE_EDGE_FALLING)  			l &= ~(1 << gpio);  		else -			goto bad; -		break; -#endif -#ifdef CONFIG_ARCH_OMAP16XX -	case METHOD_GPIO_1610: +			return -EINVAL; + +		__raw_writel(l, reg); +	} else if (bank->regs->edgectrl1) {  		if (gpio & 0x08) -			reg += OMAP1610_GPIO_EDGE_CTRL2; +			reg += bank->regs->edgectrl2;  		else -			reg += OMAP1610_GPIO_EDGE_CTRL1; +			reg += bank->regs->edgectrl1; +  		gpio &= 0x07;  		l = __raw_readl(reg);  		l &= ~(3 << (gpio << 1)); @@ -361,45 +366,19 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)  			l |= 2 << (gpio << 1);  		if (trigger & IRQ_TYPE_EDGE_FALLING)  			l |= 1 << (gpio << 1); -		if (trigger) -			/* Enable wake-up during idle for dynamic tick */ -			__raw_writel(1 << gpio, bank->base + OMAP1610_GPIO_SET_WAKEUPENA); -		else -			__raw_writel(1 << gpio, bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA); -		break; -#endif -#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) -	case METHOD_GPIO_7XX: -		reg += OMAP7XX_GPIO_INT_CONTROL; -		l = __raw_readl(reg); -		if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) -			bank->toggle_mask |= 1 << gpio; -		if (trigger & IRQ_TYPE_EDGE_RISING) -			l |= 1 << gpio; -		else if (trigger & IRQ_TYPE_EDGE_FALLING) -			l &= ~(1 << gpio); -		else -			goto bad; -		break; -#endif -#ifdef CONFIG_ARCH_OMAP2PLUS -	case METHOD_GPIO_24XX: -	case METHOD_GPIO_44XX: -		set_24xx_gpio_triggering(bank, gpio, trigger); -		return 0; -#endif -	default: -		goto bad; + +		/* Enable wake-up during idle for dynamic tick */ +		_gpio_rmw(base, bank->regs->wkup_en, 1 << gpio, trigger); +		bank->context.wake_en = +			__raw_readl(bank->base + bank->regs->wkup_en); +		__raw_writel(l, reg);  	} -	__raw_writel(l, reg);  	return 0; -bad: -	return -EINVAL;  }  static int gpio_irq_type(struct irq_data *d, unsigned type)  { -	struct gpio_bank *bank; +	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);  	unsigned gpio;  	int retval;  	unsigned long flags; @@ -407,17 +386,15 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)  	if (!cpu_class_is_omap2() && d->irq > IH_MPUIO_BASE)  		gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);  	else -		gpio = d->irq - IH_GPIO_BASE; +		gpio = irq_to_gpio(bank, d->irq);  	if (type & ~IRQ_TYPE_SENSE_MASK)  		return -EINVAL; -	/* OMAP1 allows only only edge triggering */ -	if (!cpu_class_is_omap2() -			&& (type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH))) +	if (!bank->regs->leveldetect0 && +		(type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH)))  		return -EINVAL; -	bank = irq_data_get_irq_chip_data(d);  	spin_lock_irqsave(&bank->lock, flags);  	retval = _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), type);  	spin_unlock_irqrestore(&bank->lock, flags); @@ -474,6 +451,7 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)  	if (bank->regs->set_irqenable) {  		reg += bank->regs->set_irqenable;  		l = gpio_mask; +		bank->context.irqenable1 |= gpio_mask;  	} else {  		reg += bank->regs->irqenable;  		l = __raw_readl(reg); @@ -481,6 +459,7 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)  			l &= ~gpio_mask;  		else  			l |= gpio_mask; +		bank->context.irqenable1 = l;  	}  	__raw_writel(l, reg); @@ -494,6 +473,7 @@ static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)  	if (bank->regs->clr_irqenable) {  		reg += bank->regs->clr_irqenable;  		l = gpio_mask; +		bank->context.irqenable1 &= ~gpio_mask;  	} else {  		reg += bank->regs->irqenable;  		l = __raw_readl(reg); @@ -501,6 +481,7 @@ static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)  			l |= gpio_mask;  		else  			l &= ~gpio_mask; +		bank->context.irqenable1 = l;  	}  	__raw_writel(l, reg); @@ -508,7 +489,10 @@ static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)  static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable)  { -	_enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio)); +	if (enable) +		_enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio)); +	else +		_disable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));  }  /* @@ -525,7 +509,7 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)  	unsigned long flags;  	if (bank->non_wakeup_gpios & gpio_bit) { -		dev_err(bank->dev,  +		dev_err(bank->dev,  			"Unable to modify wakeup on non-wakeup GPIO%d\n", gpio);  		return -EINVAL;  	} @@ -536,6 +520,7 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)  	else  		bank->suspend_wakeup &= ~gpio_bit; +	__raw_writel(bank->suspend_wakeup, bank->base + bank->regs->wkup_en);  	spin_unlock_irqrestore(&bank->lock, flags);  	return 0; @@ -552,14 +537,10 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio)  /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */  static int gpio_wake_enable(struct irq_data *d, unsigned int enable)  { -	unsigned int gpio = d->irq - IH_GPIO_BASE; -	struct gpio_bank *bank; -	int retval; - -	bank = irq_data_get_irq_chip_data(d); -	retval = _set_gpio_wakeup(bank, gpio, enable); +	struct gpio_bank *bank = irq_data_get_irq_chip_data(d); +	unsigned int gpio = irq_to_gpio(bank, d->irq); -	return retval; +	return _set_gpio_wakeup(bank, gpio, enable);  }  static int omap_gpio_request(struct gpio_chip *chip, unsigned offset) @@ -567,38 +548,39 @@ static int omap_gpio_request(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); +	/* +	 * If this is the first gpio_request for the bank, +	 * enable the bank module. +	 */ +	if (!bank->mod_usage) +		pm_runtime_get_sync(bank->dev); +	spin_lock_irqsave(&bank->lock, flags);  	/* Set trigger to none. You need to enable the desired trigger with  	 * request_irq() or set_irq_type().  	 */  	_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE); -#ifdef CONFIG_ARCH_OMAP15XX -	if (bank->method == METHOD_GPIO_1510) { -		void __iomem *reg; +	if (bank->regs->pinctrl) { +		void __iomem *reg = bank->base + bank->regs->pinctrl;  		/* Claim the pin for MPU */ -		reg = bank->base + OMAP1510_GPIO_PIN_CONTROL;  		__raw_writel(__raw_readl(reg) | (1 << offset), reg);  	} -#endif -	if (!cpu_class_is_omap1()) { -		if (!bank->mod_usage) { -			void __iomem *reg = bank->base; -			u32 ctrl; -			if (cpu_is_omap24xx() || cpu_is_omap34xx()) -				reg += OMAP24XX_GPIO_CTRL; -			else if (cpu_is_omap44xx()) -				reg += OMAP4_GPIO_CTRL; -			ctrl = __raw_readl(reg); -			/* Module is enabled, clocks are not gated */ -			ctrl &= 0xFFFFFFFE; -			__raw_writel(ctrl, reg); -		} -		bank->mod_usage |= 1 << offset; +	if (bank->regs->ctrl && !bank->mod_usage) { +		void __iomem *reg = bank->base + bank->regs->ctrl; +		u32 ctrl; + +		ctrl = __raw_readl(reg); +		/* Module is enabled, clocks are not gated */ +		ctrl &= ~GPIO_MOD_CTRL_BIT; +		__raw_writel(ctrl, reg); +		bank->context.ctrl = ctrl;  	} + +	bank->mod_usage |= 1 << offset; +  	spin_unlock_irqrestore(&bank->lock, flags);  	return 0; @@ -607,48 +589,40 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)  static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)  {  	struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip); +	void __iomem *base = bank->base;  	unsigned long flags;  	spin_lock_irqsave(&bank->lock, flags); -#ifdef CONFIG_ARCH_OMAP16XX -	if (bank->method == METHOD_GPIO_1610) { -		/* Disable wake-up during idle for dynamic tick */ -		void __iomem *reg = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA; -		__raw_writel(1 << offset, reg); -	} -#endif -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) -	if (bank->method == METHOD_GPIO_24XX) { -		/* Disable wake-up during idle for dynamic tick */ -		void __iomem *reg = bank->base + OMAP24XX_GPIO_CLEARWKUENA; -		__raw_writel(1 << offset, reg); -	} -#endif -#ifdef CONFIG_ARCH_OMAP4 -	if (bank->method == METHOD_GPIO_44XX) { + +	if (bank->regs->wkup_en) {  		/* Disable wake-up during idle for dynamic tick */ -		void __iomem *reg = bank->base + OMAP4_GPIO_IRQWAKEN0; -		__raw_writel(1 << offset, reg); +		_gpio_rmw(base, bank->regs->wkup_en, 1 << offset, 0); +		bank->context.wake_en = +			__raw_readl(bank->base + bank->regs->wkup_en);  	} -#endif -	if (!cpu_class_is_omap1()) { -		bank->mod_usage &= ~(1 << offset); -		if (!bank->mod_usage) { -			void __iomem *reg = bank->base; -			u32 ctrl; -			if (cpu_is_omap24xx() || cpu_is_omap34xx()) -				reg += OMAP24XX_GPIO_CTRL; -			else if (cpu_is_omap44xx()) -				reg += OMAP4_GPIO_CTRL; -			ctrl = __raw_readl(reg); -			/* Module is disabled, clocks are gated */ -			ctrl |= 1; -			__raw_writel(ctrl, reg); -		} +	bank->mod_usage &= ~(1 << offset); + +	if (bank->regs->ctrl && !bank->mod_usage) { +		void __iomem *reg = bank->base + bank->regs->ctrl; +		u32 ctrl; + +		ctrl = __raw_readl(reg); +		/* Module is disabled, clocks are gated */ +		ctrl |= GPIO_MOD_CTRL_BIT; +		__raw_writel(ctrl, reg); +		bank->context.ctrl = ctrl;  	} +  	_reset_gpio(bank, bank->chip.base + offset);  	spin_unlock_irqrestore(&bank->lock, flags); + +	/* +	 * If this is the last gpio to be freed in the bank, +	 * disable the bank module. +	 */ +	if (!bank->mod_usage) +		pm_runtime_put(bank->dev);  }  /* @@ -674,6 +648,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)  	bank = irq_get_handler_data(irq);  	isr_reg = bank->base + bank->regs->irqstatus; +	pm_runtime_get_sync(bank->dev);  	if (WARN_ON(!isr_reg))  		goto exit; @@ -685,12 +660,8 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)  		enabled = _get_gpio_irqbank_mask(bank);  		isr_saved = isr = __raw_readl(isr_reg) & enabled; -		if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO)) -			isr &= 0x0000ffff; - -		if (cpu_class_is_omap2()) { +		if (bank->level_mask)  			level_mask = bank->level_mask & enabled; -		}  		/* clear edge sensitive interrupts before handler(s) are  		called so that we don't miss any interrupt occurred while @@ -711,14 +682,15 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)  		if (!isr)  			break; -		gpio_irq = bank->virtual_irq_start; +		gpio_irq = bank->irq_base;  		for (; isr != 0; isr >>= 1, gpio_irq++) { -			gpio_index = GPIO_INDEX(bank, irq_to_gpio(gpio_irq)); +			int gpio = irq_to_gpio(bank, gpio_irq);  			if (!(isr & 1))  				continue; -#ifdef CONFIG_ARCH_OMAP1 +			gpio_index = GPIO_INDEX(bank, gpio); +  			/*  			 * Some chips can't respond to both rising and falling  			 * at the same time.  If this irq was requested with @@ -728,7 +700,6 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)  			 */  			if (bank->toggle_mask & (1 << gpio_index))  				_toggle_gpio_edge_triggering(bank, gpio_index); -#endif  			generic_handle_irq(gpio_irq);  		} @@ -740,12 +711,13 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)  exit:  	if (!unmasked)  		chained_irq_exit(chip, desc); +	pm_runtime_put(bank->dev);  }  static void gpio_irq_shutdown(struct irq_data *d)  { -	unsigned int gpio = d->irq - IH_GPIO_BASE;  	struct gpio_bank *bank = irq_data_get_irq_chip_data(d); +	unsigned int gpio = irq_to_gpio(bank, d->irq);  	unsigned long flags;  	spin_lock_irqsave(&bank->lock, flags); @@ -755,16 +727,16 @@ static void gpio_irq_shutdown(struct irq_data *d)  static void gpio_ack_irq(struct irq_data *d)  { -	unsigned int gpio = d->irq - IH_GPIO_BASE;  	struct gpio_bank *bank = irq_data_get_irq_chip_data(d); +	unsigned int gpio = irq_to_gpio(bank, d->irq);  	_clear_gpio_irqstatus(bank, gpio);  }  static void gpio_mask_irq(struct irq_data *d)  { -	unsigned int gpio = d->irq - IH_GPIO_BASE;  	struct gpio_bank *bank = irq_data_get_irq_chip_data(d); +	unsigned int gpio = irq_to_gpio(bank, d->irq);  	unsigned long flags;  	spin_lock_irqsave(&bank->lock, flags); @@ -775,8 +747,8 @@ static void gpio_mask_irq(struct irq_data *d)  static void gpio_unmask_irq(struct irq_data *d)  { -	unsigned int gpio = d->irq - IH_GPIO_BASE;  	struct gpio_bank *bank = irq_data_get_irq_chip_data(d); +	unsigned int gpio = irq_to_gpio(bank, d->irq);  	unsigned int irq_mask = GPIO_BIT(bank, gpio);  	u32 trigger = irqd_get_trigger_type(d);  	unsigned long flags; @@ -808,14 +780,6 @@ static struct irq_chip gpio_irq_chip = {  /*---------------------------------------------------------------------*/ -#ifdef CONFIG_ARCH_OMAP1 - -#define bank_is_mpuio(bank)	((bank)->method == METHOD_MPUIO) - -#ifdef CONFIG_ARCH_OMAP16XX - -#include <linux/platform_device.h> -  static int omap_mpuio_suspend_noirq(struct device *dev)  {  	struct platform_device *pdev = to_platform_device(dev); @@ -869,32 +833,16 @@ static struct platform_device omap_mpuio_device = {  	/* could list the /proc/iomem resources */  }; -static inline void mpuio_init(void) +static inline void mpuio_init(struct gpio_bank *bank)  { -	struct gpio_bank *bank = &gpio_bank[0];  	platform_set_drvdata(&omap_mpuio_device, bank);  	if (platform_driver_register(&omap_mpuio_driver) == 0)  		(void) platform_device_register(&omap_mpuio_device);  } -#else -static inline void mpuio_init(void) {} -#endif	/* 16xx */ - -#else - -#define bank_is_mpuio(bank)	0 -static inline void mpuio_init(void) {} - -#endif -  /*---------------------------------------------------------------------*/ -/* REVISIT these are stupid implementations!  replace by ones that - * don't switch on METHOD_* and which mostly avoid spinlocks - */ -  static int gpio_input(struct gpio_chip *chip, unsigned offset)  {  	struct gpio_bank *bank; @@ -917,19 +865,15 @@ static int gpio_is_input(struct gpio_bank *bank, int mask)  static int gpio_get(struct gpio_chip *chip, unsigned offset)  {  	struct gpio_bank *bank; -	void __iomem *reg; -	int gpio;  	u32 mask; -	gpio = chip->base + offset;  	bank = container_of(chip, struct gpio_bank, chip); -	reg = bank->base; -	mask = GPIO_BIT(bank, gpio); +	mask = (1 << offset);  	if (gpio_is_input(bank, mask)) -		return _get_gpio_datain(bank, gpio); +		return _get_gpio_datain(bank, offset);  	else -		return _get_gpio_dataout(bank, gpio); +		return _get_gpio_dataout(bank, offset);  }  static int gpio_output(struct gpio_chip *chip, unsigned offset, int value) @@ -982,7 +926,7 @@ static int gpio_2irq(struct gpio_chip *chip, unsigned offset)  	struct gpio_bank *bank;  	bank = container_of(chip, struct gpio_bank, chip); -	return bank->virtual_irq_start + offset; +	return bank->irq_base + offset;  }  /*---------------------------------------------------------------------*/ @@ -1007,81 +951,35 @@ static void __init omap_gpio_show_rev(struct gpio_bank *bank)   */  static struct lock_class_key gpio_lock_class; -static inline int init_gpio_info(struct platform_device *pdev) -{ -	/* TODO: Analyze removing gpio_bank_count usage from driver code */ -	gpio_bank = kzalloc(gpio_bank_count * sizeof(struct gpio_bank), -				GFP_KERNEL); -	if (!gpio_bank) { -		dev_err(&pdev->dev, "Memory alloc failed for gpio_bank\n"); -		return -ENOMEM; -	} -	return 0; -} - -/* TODO: Cleanup cpu_is_* checks */ -static void omap_gpio_mod_init(struct gpio_bank *bank, int id) +static void omap_gpio_mod_init(struct gpio_bank *bank)  { -	if (cpu_class_is_omap2()) { -		if (cpu_is_omap44xx()) { -			__raw_writel(0xffffffff, bank->base + -					OMAP4_GPIO_IRQSTATUSCLR0); -			__raw_writel(0x00000000, bank->base + -					 OMAP4_GPIO_DEBOUNCENABLE); -			/* Initialize interface clk ungated, module enabled */ -			__raw_writel(0, bank->base + OMAP4_GPIO_CTRL); -		} else if (cpu_is_omap34xx()) { -			__raw_writel(0x00000000, bank->base + -					OMAP24XX_GPIO_IRQENABLE1); -			__raw_writel(0xffffffff, bank->base + -					OMAP24XX_GPIO_IRQSTATUS1); -			__raw_writel(0x00000000, bank->base + -					OMAP24XX_GPIO_DEBOUNCE_EN); +	void __iomem *base = bank->base; +	u32 l = 0xffffffff; -			/* Initialize interface clk ungated, module enabled */ -			__raw_writel(0, bank->base + OMAP24XX_GPIO_CTRL); -		} else if (cpu_is_omap24xx()) { -			static const u32 non_wakeup_gpios[] = { -				0xe203ffc0, 0x08700040 -			}; -			if (id < ARRAY_SIZE(non_wakeup_gpios)) -				bank->non_wakeup_gpios = non_wakeup_gpios[id]; -		} -	} else if (cpu_class_is_omap1()) { -		if (bank_is_mpuio(bank)) -			__raw_writew(0xffff, bank->base + -				OMAP_MPUIO_GPIO_MASKIT / bank->stride); -		if (cpu_is_omap15xx() && bank->method == METHOD_GPIO_1510) { -			__raw_writew(0xffff, bank->base -						+ OMAP1510_GPIO_INT_MASK); -			__raw_writew(0x0000, bank->base -						+ OMAP1510_GPIO_INT_STATUS); -		} -		if (cpu_is_omap16xx() && bank->method == METHOD_GPIO_1610) { -			__raw_writew(0x0000, bank->base -						+ OMAP1610_GPIO_IRQENABLE1); -			__raw_writew(0xffff, bank->base -						+ OMAP1610_GPIO_IRQSTATUS1); -			__raw_writew(0x0014, bank->base -						+ OMAP1610_GPIO_SYSCONFIG); +	if (bank->width == 16) +		l = 0xffff; -			/* -			 * Enable system clock for GPIO module. -			 * The CAM_CLK_CTRL *is* really the right place. -			 */ -			omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, -						ULPD_CAM_CLK_CTRL); -		} -		if (cpu_is_omap7xx() && bank->method == METHOD_GPIO_7XX) { -			__raw_writel(0xffffffff, bank->base -						+ OMAP7XX_GPIO_INT_MASK); -			__raw_writel(0x00000000, bank->base -						+ OMAP7XX_GPIO_INT_STATUS); -		} +	if (bank->is_mpuio) { +		__raw_writel(l, bank->base + bank->regs->irqenable); +		return;  	} + +	_gpio_rmw(base, bank->regs->irqenable, l, bank->regs->irqenable_inv); +	_gpio_rmw(base, bank->regs->irqstatus, l, +					bank->regs->irqenable_inv == false); +	_gpio_rmw(base, bank->regs->irqenable, l, bank->regs->debounce_en != 0); +	_gpio_rmw(base, bank->regs->irqenable, l, bank->regs->ctrl != 0); +	if (bank->regs->debounce_en) +		_gpio_rmw(base, bank->regs->debounce_en, 0, 1); + +	/* Save OE default value (0xffffffff) in the context */ +	bank->context.oe = __raw_readl(bank->base + bank->regs->direction); +	 /* Initialize interface clk ungated, module enabled */ +	if (bank->regs->ctrl) +		_gpio_rmw(base, bank->regs->ctrl, 0, 1);  } -static __init void +static __devinit void  omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,  		    unsigned int num)  { @@ -1101,8 +999,8 @@ omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,  	ct->chip.irq_mask = irq_gc_mask_set_bit;  	ct->chip.irq_unmask = irq_gc_mask_clr_bit;  	ct->chip.irq_set_type = gpio_irq_type; -	/* REVISIT: assuming only 16xx supports MPUIO wake events */ -	if (cpu_is_omap16xx()) + +	if (bank->regs->wkup_en)  		ct->chip.irq_set_wake = gpio_wake_enable,  	ct->regs.mask = OMAP_MPUIO_GPIO_INT / bank->stride; @@ -1115,7 +1013,6 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)  	int j;  	static int gpio; -	bank->mod_usage = 0;  	/*  	 * REVISIT eventually switch from OMAP-specific gpio structs  	 * over to the generic ones @@ -1128,11 +1025,10 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)  	bank->chip.set_debounce = gpio_debounce;  	bank->chip.set = gpio_set;  	bank->chip.to_irq = gpio_2irq; -	if (bank_is_mpuio(bank)) { +	if (bank->is_mpuio) {  		bank->chip.label = "mpuio"; -#ifdef CONFIG_ARCH_OMAP16XX -		bank->chip.dev = &omap_mpuio_device.dev; -#endif +		if (bank->regs->wkup_en) +			bank->chip.dev = &omap_mpuio_device.dev;  		bank->chip.base = OMAP_MPUIO(0);  	} else {  		bank->chip.label = "gpio"; @@ -1143,11 +1039,10 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)  	gpiochip_add(&bank->chip); -	for (j = bank->virtual_irq_start; -		     j < bank->virtual_irq_start + bank->width; j++) { +	for (j = bank->irq_base; j < bank->irq_base + bank->width; j++) {  		irq_set_lockdep_class(j, &gpio_lock_class);  		irq_set_chip_data(j, bank); -		if (bank_is_mpuio(bank)) { +		if (bank->is_mpuio) {  			omap_mpuio_alloc_gc(bank, j, bank->width);  		} else {  			irq_set_chip(j, &gpio_irq_chip); @@ -1159,45 +1054,58 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)  	irq_set_handler_data(bank->irq, bank);  } +static const struct of_device_id omap_gpio_match[]; +  static int __devinit omap_gpio_probe(struct platform_device *pdev)  { -	static int gpio_init_done; +	struct device *dev = &pdev->dev; +	struct device_node *node = dev->of_node; +	const struct of_device_id *match;  	struct omap_gpio_platform_data *pdata;  	struct resource *res; -	int id;  	struct gpio_bank *bank; +	int ret = 0; -	if (!pdev->dev.platform_data) -		return -EINVAL; - -	pdata = pdev->dev.platform_data; +	match = of_match_device(of_match_ptr(omap_gpio_match), dev); -	if (!gpio_init_done) { -		int ret; +	pdata = match ? match->data : dev->platform_data; +	if (!pdata) +		return -EINVAL; -		ret = init_gpio_info(pdev); -		if (ret) -			return ret; +	bank = devm_kzalloc(&pdev->dev, sizeof(struct gpio_bank), GFP_KERNEL); +	if (!bank) { +		dev_err(dev, "Memory alloc failed\n"); +		return -ENOMEM;  	} -	id = pdev->id; -	bank = &gpio_bank[id]; -  	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);  	if (unlikely(!res)) { -		dev_err(&pdev->dev, "GPIO Bank %i Invalid IRQ resource\n", id); +		dev_err(dev, "Invalid IRQ resource\n");  		return -ENODEV;  	}  	bank->irq = res->start; -	bank->virtual_irq_start = pdata->virtual_irq_start; -	bank->method = pdata->bank_type; -	bank->dev = &pdev->dev; +	bank->dev = dev;  	bank->dbck_flag = pdata->dbck_flag;  	bank->stride = pdata->bank_stride;  	bank->width = pdata->bank_width; - +	bank->is_mpuio = pdata->is_mpuio; +	bank->non_wakeup_gpios = pdata->non_wakeup_gpios; +	bank->loses_context = pdata->loses_context; +	bank->get_context_loss_count = pdata->get_context_loss_count;  	bank->regs = pdata->regs; +#ifdef CONFIG_OF_GPIO +	bank->chip.of_node = of_node_get(node); +#endif + +	bank->irq_base = irq_alloc_descs(-1, 0, bank->width, 0); +	if (bank->irq_base < 0) { +		dev_err(dev, "Couldn't allocate IRQ numbers\n"); +		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)  		bank->set_dataout = _set_gpio_dataout_reg; @@ -1209,369 +1117,422 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)  	/* Static mapping, never released */  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (unlikely(!res)) { -		dev_err(&pdev->dev, "GPIO Bank %i Invalid mem resource\n", id); +		dev_err(dev, "Invalid mem resource\n");  		return -ENODEV;  	} -	bank->base = ioremap(res->start, resource_size(res)); +	if (!devm_request_mem_region(dev, res->start, resource_size(res), +				     pdev->name)) { +		dev_err(dev, "Region already claimed\n"); +		return -EBUSY; +	} + +	bank->base = devm_ioremap(dev, res->start, resource_size(res));  	if (!bank->base) { -		dev_err(&pdev->dev, "Could not ioremap gpio bank%i\n", id); +		dev_err(dev, "Could not ioremap\n");  		return -ENOMEM;  	} +	platform_set_drvdata(pdev, bank); +  	pm_runtime_enable(bank->dev); +	pm_runtime_irq_safe(bank->dev);  	pm_runtime_get_sync(bank->dev); -	omap_gpio_mod_init(bank, id); +	if (bank->is_mpuio) +		mpuio_init(bank); + +	omap_gpio_mod_init(bank);  	omap_gpio_chip_init(bank);  	omap_gpio_show_rev(bank); -	if (!gpio_init_done) -		gpio_init_done = 1; +	pm_runtime_put(bank->dev); -	return 0; +	list_add_tail(&bank->node, &omap_gpio_list); + +	return ret;  } -#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS) -static int omap_gpio_suspend(void) +#ifdef CONFIG_ARCH_OMAP2PLUS + +#if defined(CONFIG_PM_SLEEP) +static int omap_gpio_suspend(struct device *dev)  { -	int i; +	struct platform_device *pdev = to_platform_device(dev); +	struct gpio_bank *bank = platform_get_drvdata(pdev); +	void __iomem *base = bank->base; +	void __iomem *wakeup_enable; +	unsigned long flags; -	if (!cpu_class_is_omap2() && !cpu_is_omap16xx()) +	if (!bank->mod_usage || !bank->loses_context)  		return 0; -	for (i = 0; i < gpio_bank_count; i++) { -		struct gpio_bank *bank = &gpio_bank[i]; -		void __iomem *wake_status; -		void __iomem *wake_clear; -		void __iomem *wake_set; -		unsigned long flags; +	if (!bank->regs->wkup_en || !bank->suspend_wakeup) +		return 0; -		switch (bank->method) { -#ifdef CONFIG_ARCH_OMAP16XX -		case METHOD_GPIO_1610: -			wake_status = bank->base + OMAP1610_GPIO_WAKEUPENABLE; -			wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA; -			wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA; -			break; -#endif -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) -		case METHOD_GPIO_24XX: -			wake_status = bank->base + OMAP24XX_GPIO_WAKE_EN; -			wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA; -			wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA; -			break; -#endif -#ifdef CONFIG_ARCH_OMAP4 -		case METHOD_GPIO_44XX: -			wake_status = bank->base + OMAP4_GPIO_IRQWAKEN0; -			wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0; -			wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0; -			break; -#endif -		default: -			continue; -		} +	wakeup_enable = bank->base + bank->regs->wkup_en; -		spin_lock_irqsave(&bank->lock, flags); -		bank->saved_wakeup = __raw_readl(wake_status); -		__raw_writel(0xffffffff, wake_clear); -		__raw_writel(bank->suspend_wakeup, wake_set); -		spin_unlock_irqrestore(&bank->lock, flags); -	} +	spin_lock_irqsave(&bank->lock, flags); +	bank->saved_wakeup = __raw_readl(wakeup_enable); +	_gpio_rmw(base, bank->regs->wkup_en, 0xffffffff, 0); +	_gpio_rmw(base, bank->regs->wkup_en, bank->suspend_wakeup, 1); +	spin_unlock_irqrestore(&bank->lock, flags);  	return 0;  } -static void omap_gpio_resume(void) +static int omap_gpio_resume(struct device *dev)  { -	int i; +	struct platform_device *pdev = to_platform_device(dev); +	struct gpio_bank *bank = platform_get_drvdata(pdev); +	void __iomem *base = bank->base; +	unsigned long flags; -	if (!cpu_class_is_omap2() && !cpu_is_omap16xx()) -		return; +	if (!bank->mod_usage || !bank->loses_context) +		return 0; -	for (i = 0; i < gpio_bank_count; i++) { -		struct gpio_bank *bank = &gpio_bank[i]; -		void __iomem *wake_clear; -		void __iomem *wake_set; -		unsigned long flags; +	if (!bank->regs->wkup_en || !bank->saved_wakeup) +		return 0; -		switch (bank->method) { -#ifdef CONFIG_ARCH_OMAP16XX -		case METHOD_GPIO_1610: -			wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA; -			wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA; -			break; -#endif -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) -		case METHOD_GPIO_24XX: -			wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA; -			wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA; -			break; -#endif -#ifdef CONFIG_ARCH_OMAP4 -		case METHOD_GPIO_44XX: -			wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0; -			wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0; -			break; -#endif -		default: -			continue; -		} +	spin_lock_irqsave(&bank->lock, flags); +	_gpio_rmw(base, bank->regs->wkup_en, 0xffffffff, 0); +	_gpio_rmw(base, bank->regs->wkup_en, bank->saved_wakeup, 1); +	spin_unlock_irqrestore(&bank->lock, flags); -		spin_lock_irqsave(&bank->lock, flags); -		__raw_writel(0xffffffff, wake_clear); -		__raw_writel(bank->saved_wakeup, wake_set); -		spin_unlock_irqrestore(&bank->lock, flags); -	} +	return 0;  } +#endif /* CONFIG_PM_SLEEP */ -static struct syscore_ops omap_gpio_syscore_ops = { -	.suspend	= omap_gpio_suspend, -	.resume		= omap_gpio_resume, -}; +#if defined(CONFIG_PM_RUNTIME) +static void omap_gpio_restore_context(struct gpio_bank *bank); -#endif +static int omap_gpio_runtime_suspend(struct device *dev) +{ +	struct platform_device *pdev = to_platform_device(dev); +	struct gpio_bank *bank = platform_get_drvdata(pdev); +	u32 l1 = 0, l2 = 0; +	unsigned long flags; +	u32 wake_low, wake_hi; -#ifdef CONFIG_ARCH_OMAP2PLUS +	spin_lock_irqsave(&bank->lock, flags); -static int workaround_enabled; +	/* +	 * Only edges can generate a wakeup event to the PRCM. +	 * +	 * Therefore, ensure any wake-up capable GPIOs have +	 * edge-detection enabled before going idle to ensure a wakeup +	 * to the PRCM is generated on a GPIO transition. (c.f. 34xx +	 * NDA TRM 25.5.3.1) +	 * +	 * The normal values will be restored upon ->runtime_resume() +	 * by writing back the values saved in bank->context. +	 */ +	wake_low = bank->context.leveldetect0 & bank->context.wake_en; +	if (wake_low) +		__raw_writel(wake_low | bank->context.fallingdetect, +			     bank->base + bank->regs->fallingdetect); +	wake_hi = bank->context.leveldetect1 & bank->context.wake_en; +	if (wake_hi) +		__raw_writel(wake_hi | bank->context.risingdetect, +			     bank->base + bank->regs->risingdetect); -void omap2_gpio_prepare_for_idle(int off_mode) -{ -	int i, c = 0; -	int min = 0; +	if (bank->power_mode != OFF_MODE) { +		bank->power_mode = 0; +		goto update_gpio_context_count; +	} +	/* +	 * If going to OFF, remove triggering for all +	 * non-wakeup GPIOs.  Otherwise spurious IRQs will be +	 * generated.  See OMAP2420 Errata item 1.101. +	 */ +	bank->saved_datain = __raw_readl(bank->base + +						bank->regs->datain); +	l1 = __raw_readl(bank->base + bank->regs->fallingdetect); +	l2 = __raw_readl(bank->base + bank->regs->risingdetect); -	if (cpu_is_omap34xx()) -		min = 1; +	bank->saved_fallingdetect = l1; +	bank->saved_risingdetect = l2; +	l1 &= ~bank->enabled_non_wakeup_gpios; +	l2 &= ~bank->enabled_non_wakeup_gpios; -	for (i = min; i < gpio_bank_count; i++) { -		struct gpio_bank *bank = &gpio_bank[i]; -		u32 l1 = 0, l2 = 0; -		int j; +	__raw_writel(l1, bank->base + bank->regs->fallingdetect); +	__raw_writel(l2, bank->base + bank->regs->risingdetect); -		for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++) -			clk_disable(bank->dbck); +	bank->workaround_enabled = true; -		if (!off_mode) -			continue; +update_gpio_context_count: +	if (bank->get_context_loss_count) +		bank->context_loss_count = +				bank->get_context_loss_count(bank->dev); -		/* If going to OFF, remove triggering for all -		 * non-wakeup GPIOs.  Otherwise spurious IRQs will be -		 * generated.  See OMAP2420 Errata item 1.101. */ -		if (!(bank->enabled_non_wakeup_gpios)) -			continue; - -		if (cpu_is_omap24xx() || cpu_is_omap34xx()) { -			bank->saved_datain = __raw_readl(bank->base + -					OMAP24XX_GPIO_DATAIN); -			l1 = __raw_readl(bank->base + -					OMAP24XX_GPIO_FALLINGDETECT); -			l2 = __raw_readl(bank->base + -					OMAP24XX_GPIO_RISINGDETECT); -		} +	_gpio_dbck_disable(bank); +	spin_unlock_irqrestore(&bank->lock, flags); -		if (cpu_is_omap44xx()) { -			bank->saved_datain = __raw_readl(bank->base + -						OMAP4_GPIO_DATAIN); -			l1 = __raw_readl(bank->base + -						OMAP4_GPIO_FALLINGDETECT); -			l2 = __raw_readl(bank->base + -						OMAP4_GPIO_RISINGDETECT); -		} +	return 0; +} -		bank->saved_fallingdetect = l1; -		bank->saved_risingdetect = l2; -		l1 &= ~bank->enabled_non_wakeup_gpios; -		l2 &= ~bank->enabled_non_wakeup_gpios; +static int omap_gpio_runtime_resume(struct device *dev) +{ +	struct platform_device *pdev = to_platform_device(dev); +	struct gpio_bank *bank = platform_get_drvdata(pdev); +	int context_lost_cnt_after; +	u32 l = 0, gen, gen0, gen1; +	unsigned long flags; -		if (cpu_is_omap24xx() || cpu_is_omap34xx()) { -			__raw_writel(l1, bank->base + -					OMAP24XX_GPIO_FALLINGDETECT); -			__raw_writel(l2, bank->base + -					OMAP24XX_GPIO_RISINGDETECT); -		} +	spin_lock_irqsave(&bank->lock, flags); +	_gpio_dbck_enable(bank); -		if (cpu_is_omap44xx()) { -			__raw_writel(l1, bank->base + OMAP4_GPIO_FALLINGDETECT); -			__raw_writel(l2, bank->base + OMAP4_GPIO_RISINGDETECT); -		} +	/* +	 * In ->runtime_suspend(), level-triggered, wakeup-enabled +	 * GPIOs were set to edge trigger also in order to be able to +	 * generate a PRCM wakeup.  Here we restore the +	 * pre-runtime_suspend() values for edge triggering. +	 */ +	__raw_writel(bank->context.fallingdetect, +		     bank->base + bank->regs->fallingdetect); +	__raw_writel(bank->context.risingdetect, +		     bank->base + bank->regs->risingdetect); -		c++; +	if (!bank->workaround_enabled) { +		spin_unlock_irqrestore(&bank->lock, flags); +		return 0;  	} -	if (!c) { -		workaround_enabled = 0; -		return; + +	if (bank->get_context_loss_count) { +		context_lost_cnt_after = +			bank->get_context_loss_count(bank->dev); +		if (context_lost_cnt_after != bank->context_loss_count || +						!context_lost_cnt_after) { +			omap_gpio_restore_context(bank); +		} else { +			spin_unlock_irqrestore(&bank->lock, flags); +			return 0; +		}  	} -	workaround_enabled = 1; -} -void omap2_gpio_resume_after_idle(void) -{ -	int i; -	int min = 0; +	__raw_writel(bank->saved_fallingdetect, +			bank->base + bank->regs->fallingdetect); +	__raw_writel(bank->saved_risingdetect, +			bank->base + bank->regs->risingdetect); +	l = __raw_readl(bank->base + bank->regs->datain); -	if (cpu_is_omap34xx()) -		min = 1; -	for (i = min; i < gpio_bank_count; i++) { -		struct gpio_bank *bank = &gpio_bank[i]; -		u32 l = 0, gen, gen0, gen1; -		int j; +	/* +	 * Check if any of the non-wakeup interrupt GPIOs have changed +	 * state.  If so, generate an IRQ by software.  This is +	 * horribly racy, but it's the best we can do to work around +	 * this silicon bug. +	 */ +	l ^= bank->saved_datain; +	l &= bank->enabled_non_wakeup_gpios; -		for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++) -			clk_enable(bank->dbck); +	/* +	 * No need to generate IRQs for the rising edge for gpio IRQs +	 * configured with falling edge only; and vice versa. +	 */ +	gen0 = l & bank->saved_fallingdetect; +	gen0 &= bank->saved_datain; -		if (!workaround_enabled) -			continue; +	gen1 = l & bank->saved_risingdetect; +	gen1 &= ~(bank->saved_datain); -		if (!(bank->enabled_non_wakeup_gpios)) -			continue; +	/* FIXME: Consider GPIO IRQs with level detections properly! */ +	gen = l & (~(bank->saved_fallingdetect) & ~(bank->saved_risingdetect)); +	/* Consider all GPIO IRQs needed to be updated */ +	gen |= gen0 | gen1; + +	if (gen) { +		u32 old0, old1; + +		old0 = __raw_readl(bank->base + bank->regs->leveldetect0); +		old1 = __raw_readl(bank->base + bank->regs->leveldetect1);  		if (cpu_is_omap24xx() || cpu_is_omap34xx()) { -			__raw_writel(bank->saved_fallingdetect, -				 bank->base + OMAP24XX_GPIO_FALLINGDETECT); -			__raw_writel(bank->saved_risingdetect, -				 bank->base + OMAP24XX_GPIO_RISINGDETECT); -			l = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN); +			__raw_writel(old0 | gen, bank->base + +						bank->regs->leveldetect0); +			__raw_writel(old1 | gen, bank->base + +						bank->regs->leveldetect1);  		}  		if (cpu_is_omap44xx()) { -			__raw_writel(bank->saved_fallingdetect, -				 bank->base + OMAP4_GPIO_FALLINGDETECT); -			__raw_writel(bank->saved_risingdetect, -				 bank->base + OMAP4_GPIO_RISINGDETECT); -			l = __raw_readl(bank->base + OMAP4_GPIO_DATAIN); +			__raw_writel(old0 | l, bank->base + +						bank->regs->leveldetect0); +			__raw_writel(old1 | l, bank->base + +						bank->regs->leveldetect1);  		} +		__raw_writel(old0, bank->base + bank->regs->leveldetect0); +		__raw_writel(old1, bank->base + bank->regs->leveldetect1); +	} -		/* Check if any of the non-wakeup interrupt GPIOs have changed -		 * state.  If so, generate an IRQ by software.  This is -		 * horribly racy, but it's the best we can do to work around -		 * this silicon bug. */ -		l ^= bank->saved_datain; -		l &= bank->enabled_non_wakeup_gpios; - -		/* -		 * No need to generate IRQs for the rising edge for gpio IRQs -		 * configured with falling edge only; and vice versa. -		 */ -		gen0 = l & bank->saved_fallingdetect; -		gen0 &= bank->saved_datain; +	bank->workaround_enabled = false; +	spin_unlock_irqrestore(&bank->lock, flags); -		gen1 = l & bank->saved_risingdetect; -		gen1 &= ~(bank->saved_datain); +	return 0; +} +#endif /* CONFIG_PM_RUNTIME */ -		/* FIXME: Consider GPIO IRQs with level detections properly! */ -		gen = l & (~(bank->saved_fallingdetect) & -				~(bank->saved_risingdetect)); -		/* Consider all GPIO IRQs needed to be updated */ -		gen |= gen0 | gen1; +void omap2_gpio_prepare_for_idle(int pwr_mode) +{ +	struct gpio_bank *bank; -		if (gen) { -			u32 old0, old1; +	list_for_each_entry(bank, &omap_gpio_list, node) { +		if (!bank->mod_usage || !bank->loses_context) +			continue; -			if (cpu_is_omap24xx() || cpu_is_omap34xx()) { -				old0 = __raw_readl(bank->base + -					OMAP24XX_GPIO_LEVELDETECT0); -				old1 = __raw_readl(bank->base + -					OMAP24XX_GPIO_LEVELDETECT1); -				__raw_writel(old0 | gen, bank->base + -					OMAP24XX_GPIO_LEVELDETECT0); -				__raw_writel(old1 | gen, bank->base + -					OMAP24XX_GPIO_LEVELDETECT1); -				__raw_writel(old0, bank->base + -					OMAP24XX_GPIO_LEVELDETECT0); -				__raw_writel(old1, bank->base + -					OMAP24XX_GPIO_LEVELDETECT1); -			} +		bank->power_mode = pwr_mode; -			if (cpu_is_omap44xx()) { -				old0 = __raw_readl(bank->base + -						OMAP4_GPIO_LEVELDETECT0); -				old1 = __raw_readl(bank->base + -						OMAP4_GPIO_LEVELDETECT1); -				__raw_writel(old0 | l, bank->base + -						OMAP4_GPIO_LEVELDETECT0); -				__raw_writel(old1 | l, bank->base + -						OMAP4_GPIO_LEVELDETECT1); -				__raw_writel(old0, bank->base + -						OMAP4_GPIO_LEVELDETECT0); -				__raw_writel(old1, bank->base + -						OMAP4_GPIO_LEVELDETECT1); -			} -		} +		pm_runtime_put_sync_suspend(bank->dev);  	} -  } -#endif - -#ifdef CONFIG_ARCH_OMAP3 -/* save the registers of bank 2-6 */ -void omap_gpio_save_context(void) +void omap2_gpio_resume_after_idle(void)  { -	int i; +	struct gpio_bank *bank; -	/* saving banks from 2-6 only since GPIO1 is in WKUP */ -	for (i = 1; i < gpio_bank_count; i++) { -		struct gpio_bank *bank = &gpio_bank[i]; -		gpio_context[i].irqenable1 = -			__raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1); -		gpio_context[i].irqenable2 = -			__raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE2); -		gpio_context[i].wake_en = -			__raw_readl(bank->base + OMAP24XX_GPIO_WAKE_EN); -		gpio_context[i].ctrl = -			__raw_readl(bank->base + OMAP24XX_GPIO_CTRL); -		gpio_context[i].oe = -			__raw_readl(bank->base + OMAP24XX_GPIO_OE); -		gpio_context[i].leveldetect0 = -			__raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0); -		gpio_context[i].leveldetect1 = -			__raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1); -		gpio_context[i].risingdetect = -			__raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT); -		gpio_context[i].fallingdetect = -			__raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT); -		gpio_context[i].dataout = -			__raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT); +	list_for_each_entry(bank, &omap_gpio_list, node) { +		if (!bank->mod_usage || !bank->loses_context) +			continue; + +		pm_runtime_get_sync(bank->dev);  	}  } -/* restore the required registers of bank 2-6 */ -void omap_gpio_restore_context(void) +#if defined(CONFIG_PM_RUNTIME) +static void omap_gpio_restore_context(struct gpio_bank *bank)  { -	int i; +	__raw_writel(bank->context.wake_en, +				bank->base + bank->regs->wkup_en); +	__raw_writel(bank->context.ctrl, bank->base + bank->regs->ctrl); +	__raw_writel(bank->context.leveldetect0, +				bank->base + bank->regs->leveldetect0); +	__raw_writel(bank->context.leveldetect1, +				bank->base + bank->regs->leveldetect1); +	__raw_writel(bank->context.risingdetect, +				bank->base + bank->regs->risingdetect); +	__raw_writel(bank->context.fallingdetect, +				bank->base + bank->regs->fallingdetect); +	if (bank->regs->set_dataout && bank->regs->clr_dataout) +		__raw_writel(bank->context.dataout, +				bank->base + bank->regs->set_dataout); +	else +		__raw_writel(bank->context.dataout, +				bank->base + bank->regs->dataout); +	__raw_writel(bank->context.oe, bank->base + bank->regs->direction); -	for (i = 1; i < gpio_bank_count; i++) { -		struct gpio_bank *bank = &gpio_bank[i]; -		__raw_writel(gpio_context[i].irqenable1, -				bank->base + OMAP24XX_GPIO_IRQENABLE1); -		__raw_writel(gpio_context[i].irqenable2, -				bank->base + OMAP24XX_GPIO_IRQENABLE2); -		__raw_writel(gpio_context[i].wake_en, -				bank->base + OMAP24XX_GPIO_WAKE_EN); -		__raw_writel(gpio_context[i].ctrl, -				bank->base + OMAP24XX_GPIO_CTRL); -		__raw_writel(gpio_context[i].oe, -				bank->base + OMAP24XX_GPIO_OE); -		__raw_writel(gpio_context[i].leveldetect0, -				bank->base + OMAP24XX_GPIO_LEVELDETECT0); -		__raw_writel(gpio_context[i].leveldetect1, -				bank->base + OMAP24XX_GPIO_LEVELDETECT1); -		__raw_writel(gpio_context[i].risingdetect, -				bank->base + OMAP24XX_GPIO_RISINGDETECT); -		__raw_writel(gpio_context[i].fallingdetect, -				bank->base + OMAP24XX_GPIO_FALLINGDETECT); -		__raw_writel(gpio_context[i].dataout, -				bank->base + OMAP24XX_GPIO_DATAOUT); +	if (bank->dbck_enable_mask) { +		__raw_writel(bank->context.debounce, bank->base + +					bank->regs->debounce); +		__raw_writel(bank->context.debounce_en, +					bank->base + bank->regs->debounce_en);  	} + +	__raw_writel(bank->context.irqenable1, +				bank->base + bank->regs->irqenable); +	__raw_writel(bank->context.irqenable2, +				bank->base + bank->regs->irqenable2);  } +#endif /* CONFIG_PM_RUNTIME */ +#else +#define omap_gpio_suspend NULL +#define omap_gpio_resume NULL +#define omap_gpio_runtime_suspend NULL +#define omap_gpio_runtime_resume NULL +#endif + +static const struct dev_pm_ops gpio_pm_ops = { +	SET_SYSTEM_SLEEP_PM_OPS(omap_gpio_suspend, omap_gpio_resume) +	SET_RUNTIME_PM_OPS(omap_gpio_runtime_suspend, omap_gpio_runtime_resume, +									NULL) +}; + +#if defined(CONFIG_OF) +static struct omap_gpio_reg_offs omap2_gpio_regs = { +	.revision =		OMAP24XX_GPIO_REVISION, +	.direction =		OMAP24XX_GPIO_OE, +	.datain =		OMAP24XX_GPIO_DATAIN, +	.dataout =		OMAP24XX_GPIO_DATAOUT, +	.set_dataout =		OMAP24XX_GPIO_SETDATAOUT, +	.clr_dataout =		OMAP24XX_GPIO_CLEARDATAOUT, +	.irqstatus =		OMAP24XX_GPIO_IRQSTATUS1, +	.irqstatus2 =		OMAP24XX_GPIO_IRQSTATUS2, +	.irqenable =		OMAP24XX_GPIO_IRQENABLE1, +	.irqenable2 =		OMAP24XX_GPIO_IRQENABLE2, +	.set_irqenable =	OMAP24XX_GPIO_SETIRQENABLE1, +	.clr_irqenable =	OMAP24XX_GPIO_CLEARIRQENABLE1, +	.debounce =		OMAP24XX_GPIO_DEBOUNCE_VAL, +	.debounce_en =		OMAP24XX_GPIO_DEBOUNCE_EN, +	.ctrl =			OMAP24XX_GPIO_CTRL, +	.wkup_en =		OMAP24XX_GPIO_WAKE_EN, +	.leveldetect0 =		OMAP24XX_GPIO_LEVELDETECT0, +	.leveldetect1 =		OMAP24XX_GPIO_LEVELDETECT1, +	.risingdetect =		OMAP24XX_GPIO_RISINGDETECT, +	.fallingdetect =	OMAP24XX_GPIO_FALLINGDETECT, +}; + +static struct omap_gpio_reg_offs omap4_gpio_regs = { +	.revision =		OMAP4_GPIO_REVISION, +	.direction =		OMAP4_GPIO_OE, +	.datain =		OMAP4_GPIO_DATAIN, +	.dataout =		OMAP4_GPIO_DATAOUT, +	.set_dataout =		OMAP4_GPIO_SETDATAOUT, +	.clr_dataout =		OMAP4_GPIO_CLEARDATAOUT, +	.irqstatus =		OMAP4_GPIO_IRQSTATUS0, +	.irqstatus2 =		OMAP4_GPIO_IRQSTATUS1, +	.irqenable =		OMAP4_GPIO_IRQSTATUSSET0, +	.irqenable2 =		OMAP4_GPIO_IRQSTATUSSET1, +	.set_irqenable =	OMAP4_GPIO_IRQSTATUSSET0, +	.clr_irqenable =	OMAP4_GPIO_IRQSTATUSCLR0, +	.debounce =		OMAP4_GPIO_DEBOUNCINGTIME, +	.debounce_en =		OMAP4_GPIO_DEBOUNCENABLE, +	.ctrl =			OMAP4_GPIO_CTRL, +	.wkup_en =		OMAP4_GPIO_IRQWAKEN0, +	.leveldetect0 =		OMAP4_GPIO_LEVELDETECT0, +	.leveldetect1 =		OMAP4_GPIO_LEVELDETECT1, +	.risingdetect =		OMAP4_GPIO_RISINGDETECT, +	.fallingdetect =	OMAP4_GPIO_FALLINGDETECT, +}; + +static struct omap_gpio_platform_data omap2_pdata = { +	.regs = &omap2_gpio_regs, +	.bank_width = 32, +	.dbck_flag = false, +}; + +static struct omap_gpio_platform_data omap3_pdata = { +	.regs = &omap2_gpio_regs, +	.bank_width = 32, +	.dbck_flag = true, +}; + +static struct omap_gpio_platform_data omap4_pdata = { +	.regs = &omap4_gpio_regs, +	.bank_width = 32, +	.dbck_flag = true, +}; + +static const struct of_device_id omap_gpio_match[] = { +	{ +		.compatible = "ti,omap4-gpio", +		.data = &omap4_pdata, +	}, +	{ +		.compatible = "ti,omap3-gpio", +		.data = &omap3_pdata, +	}, +	{ +		.compatible = "ti,omap2-gpio", +		.data = &omap2_pdata, +	}, +	{ }, +}; +MODULE_DEVICE_TABLE(of, omap_gpio_match);  #endif  static struct platform_driver omap_gpio_driver = {  	.probe		= omap_gpio_probe,  	.driver		= {  		.name	= "omap_gpio", +		.pm	= &gpio_pm_ops, +		.of_match_table = of_match_ptr(omap_gpio_match),  	},  }; @@ -1585,17 +1546,3 @@ static int __init omap_gpio_drv_reg(void)  	return platform_driver_register(&omap_gpio_driver);  }  postcore_initcall(omap_gpio_drv_reg); - -static int __init omap_gpio_sysinit(void) -{ -	mpuio_init(); - -#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS) -	if (cpu_is_omap16xx() || cpu_class_is_omap2()) -		register_syscore_ops(&omap_gpio_syscore_ops); -#endif - -	return 0; -} - -arch_initcall(omap_gpio_sysinit);  |