[PATCH v8 17/24] gpio/omap: fix debounce clock handling
Tarun Kanti DebBarma
tarun.kanti at ti.com
Wed Oct 5 04:33:06 EDT 2011
Currently debounce clock state is not tracked in the system. The bank->dbck
is enabled/disabled in suspend/idle paths irrespective of whether debounce
interval has been set or not. Ideally, it should be handled only for those
gpio banks where the debounce is enabled.
Signed-off-by: Tarun Kanti DebBarma <tarun.kanti at ti.com>
---
drivers/gpio/gpio-omap.c | 50 ++++++++++++++++++++++++++++++++++-----------
1 files changed, 38 insertions(+), 12 deletions(-)
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index fa6c9c5..1ec35a1 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -65,6 +65,7 @@ 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;
@@ -156,6 +157,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
@@ -200,6 +217,10 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
bank->dbck_enable_mask = val;
__raw_writel(val, reg);
+ if (bank->dbck_enable_mask) {
+ clk_disable(bank->dbck);
+ bank->dbck_enabled = false;
+ }
}
static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,
@@ -485,8 +506,10 @@ 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->mod_usage) {
+ _gpio_dbck_enable(bank);
pm_runtime_get_sync(bank->dev);
+ }
spin_lock_irqsave(&bank->lock, flags);
/* Set trigger to none. You need to enable the desired trigger with
@@ -549,8 +572,10 @@ 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->mod_usage) {
pm_runtime_put_sync(bank->dev);
+ _gpio_dbck_disable(bank);
+ }
}
/*
@@ -1086,6 +1111,8 @@ static int omap_gpio_suspend(struct device *dev)
bank->saved_wakeup = __raw_readl(wake_status);
_gpio_rmw(base, bank->regs->wkup_en, bank->suspend_wakeup, 1);
spin_unlock_irqrestore(&bank->lock, flags);
+
+ _gpio_dbck_disable(bank);
}
return 0;
@@ -1102,6 +1129,8 @@ static int omap_gpio_resume(struct device *dev)
if (!bank->regs->wkup_en)
return 0;
+ _gpio_dbck_enable(bank);
+
spin_lock_irqsave(&bank->lock, flags);
_gpio_rmw(base, bank->regs->wkup_en, bank->saved_wakeup, 1);
spin_unlock_irqrestore(&bank->lock, flags);
@@ -1120,16 +1149,14 @@ void omap2_gpio_prepare_for_idle(int off_mode)
list_for_each_entry(bank, &omap_gpio_list, node) {
u32 l1 = 0, l2 = 0;
- int j;
if (!bank->loses_context)
continue;
- for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
- clk_disable(bank->dbck);
-
- if (!off_mode)
+ if (!off_mode) {
+ _gpio_dbck_disable(bank);
continue;
+ }
/* If going to OFF, remove triggering for all
* non-wakeup GPIOs. Otherwise spurious IRQs will be
@@ -1151,15 +1178,16 @@ void omap2_gpio_prepare_for_idle(int off_mode)
__raw_writel(l2, bank->base + bank->regs->risingdetect);
save_gpio_context:
-
if (bank->get_context_loss_count)
bank->context_loss_count =
bank->get_context_loss_count(bank->dev);
omap_gpio_save_context(bank);
- if (!pm_runtime_suspended(bank->dev))
+ if (!pm_runtime_suspended(bank->dev)) {
pm_runtime_put_sync(bank->dev);
+ _gpio_dbck_disable(bank);
+ }
}
}
@@ -1170,13 +1198,11 @@ void omap2_gpio_resume_after_idle(void)
list_for_each_entry(bank, &omap_gpio_list, node) {
u32 context_lost_cnt_after;
u32 l = 0, gen, gen0, gen1;
- int j;
if (!bank->loses_context)
continue;
- for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
- clk_enable(bank->dbck);
+ _gpio_dbck_enable(bank);
if (pm_runtime_suspended(bank->dev))
pm_runtime_get_sync(bank->dev);
--
1.7.0.4
More information about the linux-arm-kernel
mailing list