Skip to content

Commit

Permalink
gpio/omap: maintain GPIO and IRQ usage separately
Browse files Browse the repository at this point in the history
The GPIO OMAP controller pins can be used as IRQ and GPIO
independently so is necessary to keep track GPIO pins and
IRQ lines usage separately to make sure that the bank will
always be enabled while being used.

Also move gpio_is_input() definition in preparation for the
next patch that setups the controller's irq_chip driver when
a caller requests an interrupt line.

Cc: stable@vger.kernel.org
Acked-by: Stephen Warren <swarren@nvidia.com>
Tested-by: George Cherian <george.cherian@ti.com>
Tested-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Tested-by: Lars Poeschel <poeschel@lemonage.de>
Reviewed-by: Kevin Hilman <khilman@linaro.org>
Tested-by: Kevin Hilman <khilman@linaro.org>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
  • Loading branch information
Javier Martinez Canillas authored and Linus Walleij committed Oct 1, 2013
1 parent 272b98c commit fa365e4
Showing 1 changed file with 21 additions and 14 deletions.
35 changes: 21 additions & 14 deletions drivers/gpio/gpio-omap.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ struct gpio_bank {
struct gpio_chip chip;
struct clk *dbck;
u32 mod_usage;
u32 irq_usage;
u32 dbck_enable_mask;
bool dbck_enabled;
struct device *dev;
Expand All @@ -86,6 +87,9 @@ struct gpio_bank {
#define GPIO_BIT(bank, gpio) (1 << GPIO_INDEX(bank, gpio))
#define GPIO_MOD_CTRL_BIT BIT(0)

#define BANK_USED(bank) (bank->mod_usage || bank->irq_usage)
#define LINE_USED(line, offset) (line & (1 << offset))

static int irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq)
{
return bank->chip.base + gpio_irq;
Expand Down Expand Up @@ -420,14 +424,21 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio,
return 0;
}

static int gpio_is_input(struct gpio_bank *bank, int mask)
{
void __iomem *reg = bank->base + bank->regs->direction;

return __raw_readl(reg) & mask;
}

static int gpio_irq_type(struct irq_data *d, unsigned type)
{
struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
unsigned gpio = 0;
int retval;
unsigned long flags;

if (WARN_ON(!bank->mod_usage))
if (WARN_ON(!BANK_USED(bank)))
return -EINVAL;

#ifdef CONFIG_ARCH_OMAP1
Expand All @@ -447,6 +458,7 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)

spin_lock_irqsave(&bank->lock, flags);
retval = _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), type);
bank->irq_usage |= 1 << GPIO_INDEX(bank, gpio);
spin_unlock_irqrestore(&bank->lock, flags);

if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
Expand Down Expand Up @@ -603,7 +615,7 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
* If this is the first gpio_request for the bank,
* enable the bank module.
*/
if (!bank->mod_usage)
if (!BANK_USED(bank))
pm_runtime_get_sync(bank->dev);

spin_lock_irqsave(&bank->lock, flags);
Expand All @@ -619,7 +631,7 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
__raw_writel(__raw_readl(reg) | (1 << offset), reg);
}

if (bank->regs->ctrl && !bank->mod_usage) {
if (bank->regs->ctrl && !BANK_USED(bank)) {
void __iomem *reg = bank->base + bank->regs->ctrl;
u32 ctrl;

Expand Down Expand Up @@ -654,7 +666,7 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)

bank->mod_usage &= ~(1 << offset);

if (bank->regs->ctrl && !bank->mod_usage) {
if (bank->regs->ctrl && !BANK_USED(bank)) {
void __iomem *reg = bank->base + bank->regs->ctrl;
u32 ctrl;

Expand All @@ -672,7 +684,7 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
* If this is the last gpio to be freed in the bank,
* disable the bank module.
*/
if (!bank->mod_usage)
if (!BANK_USED(bank))
pm_runtime_put(bank->dev);
}

Expand Down Expand Up @@ -762,8 +774,10 @@ static void gpio_irq_shutdown(struct irq_data *d)
struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
unsigned int gpio = irq_to_gpio(bank, d->hwirq);
unsigned long flags;
unsigned offset = GPIO_INDEX(bank, gpio);

spin_lock_irqsave(&bank->lock, flags);
bank->irq_usage &= ~(1 << offset);
_reset_gpio(bank, gpio);
spin_unlock_irqrestore(&bank->lock, flags);
}
Expand Down Expand Up @@ -897,13 +911,6 @@ static int gpio_input(struct gpio_chip *chip, unsigned offset)
return 0;
}

static int gpio_is_input(struct gpio_bank *bank, int mask)
{
void __iomem *reg = bank->base + bank->regs->direction;

return __raw_readl(reg) & mask;
}

static int gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct gpio_bank *bank;
Expand Down Expand Up @@ -1400,7 +1407,7 @@ void omap2_gpio_prepare_for_idle(int pwr_mode)
struct gpio_bank *bank;

list_for_each_entry(bank, &omap_gpio_list, node) {
if (!bank->mod_usage || !bank->loses_context)
if (!BANK_USED(bank) || !bank->loses_context)
continue;

bank->power_mode = pwr_mode;
Expand All @@ -1414,7 +1421,7 @@ void omap2_gpio_resume_after_idle(void)
struct gpio_bank *bank;

list_for_each_entry(bank, &omap_gpio_list, node) {
if (!bank->mod_usage || !bank->loses_context)
if (!BANK_USED(bank) || !bank->loses_context)
continue;

pm_runtime_get_sync(bank->dev);
Expand Down

0 comments on commit fa365e4

Please sign in to comment.