diff options
author | Grygorii Strashko <grygorii.strashko@ti.com> | 2015-08-18 07:10:56 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2015-08-26 03:52:57 -0400 |
commit | 5d9452e7c52a106c9efdeb6c72fc73b184a6543f (patch) | |
tree | 0d08d160aa82706573c533c58bd80dcae0e6bbd4 /drivers/gpio/gpio-omap.c | |
parent | 235f1eb1ab93a8e30a66c38949e6d2aeda136aec (diff) |
gpio: omap: fix clk_prepare/unprepare usage
As per CCF documentation (clk.txt) the clk_prepare/unprepare APIs
are not allowed in atomic context. But now OMAP GPIO driver
uses them while applying debounce settings and as part
of PM runtime irqsafe operations:
- omap_gpio_debounce() is holding the lock with IRQs off.
+ omap2_set_gpio_debounce()
+ clk_prepare_enable()
+ clk_prepare() this one might sleep.
- pm_runtime_get_sync() is holding the lock with IRQs off
+ omap_gpio_runtime_suspend()
+ raw_spin_lock_irqsave()
+ omap_gpio_dbck_disable()
+ clk_disable_unprepare()
Hence, fix it by moeving dbclk prepare/unprepare in OMAP GPIO
omap_gpio_probe/omap_gpio_remove. Also, while here, ensure that
debounce functionality is disabled if clk_get() failed,
because otherwise kernel will carsh in omap2_set_gpio_debounce().
Reported-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Acked-by: Santosh Shilimkar <ssantosh@kernel.org>
Tested-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpio-omap.c')
-rw-r--r-- | drivers/gpio/gpio-omap.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 1f02acd577e3..2ae0d47e9554 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c | |||
@@ -176,7 +176,7 @@ static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set | |||
176 | static inline void omap_gpio_dbck_enable(struct gpio_bank *bank) | 176 | static inline void omap_gpio_dbck_enable(struct gpio_bank *bank) |
177 | { | 177 | { |
178 | if (bank->dbck_enable_mask && !bank->dbck_enabled) { | 178 | if (bank->dbck_enable_mask && !bank->dbck_enabled) { |
179 | clk_prepare_enable(bank->dbck); | 179 | clk_enable(bank->dbck); |
180 | bank->dbck_enabled = true; | 180 | bank->dbck_enabled = true; |
181 | 181 | ||
182 | writel_relaxed(bank->dbck_enable_mask, | 182 | writel_relaxed(bank->dbck_enable_mask, |
@@ -194,7 +194,7 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank) | |||
194 | */ | 194 | */ |
195 | writel_relaxed(0, bank->base + bank->regs->debounce_en); | 195 | writel_relaxed(0, bank->base + bank->regs->debounce_en); |
196 | 196 | ||
197 | clk_disable_unprepare(bank->dbck); | 197 | clk_disable(bank->dbck); |
198 | bank->dbck_enabled = false; | 198 | bank->dbck_enabled = false; |
199 | } | 199 | } |
200 | } | 200 | } |
@@ -227,7 +227,7 @@ static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset, | |||
227 | 227 | ||
228 | l = BIT(offset); | 228 | l = BIT(offset); |
229 | 229 | ||
230 | clk_prepare_enable(bank->dbck); | 230 | clk_enable(bank->dbck); |
231 | reg = bank->base + bank->regs->debounce; | 231 | reg = bank->base + bank->regs->debounce; |
232 | writel_relaxed(debounce, reg); | 232 | writel_relaxed(debounce, reg); |
233 | 233 | ||
@@ -241,7 +241,7 @@ static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset, | |||
241 | bank->dbck_enable_mask = val; | 241 | bank->dbck_enable_mask = val; |
242 | 242 | ||
243 | writel_relaxed(val, reg); | 243 | writel_relaxed(val, reg); |
244 | clk_disable_unprepare(bank->dbck); | 244 | clk_disable(bank->dbck); |
245 | /* | 245 | /* |
246 | * Enable debounce clock per module. | 246 | * Enable debounce clock per module. |
247 | * This call is mandatory because in omap_gpio_request() when | 247 | * This call is mandatory because in omap_gpio_request() when |
@@ -286,7 +286,7 @@ static void omap_clear_gpio_debounce(struct gpio_bank *bank, unsigned offset) | |||
286 | bank->context.debounce = 0; | 286 | bank->context.debounce = 0; |
287 | writel_relaxed(bank->context.debounce, bank->base + | 287 | writel_relaxed(bank->context.debounce, bank->base + |
288 | bank->regs->debounce); | 288 | bank->regs->debounce); |
289 | clk_disable_unprepare(bank->dbck); | 289 | clk_disable(bank->dbck); |
290 | bank->dbck_enabled = false; | 290 | bank->dbck_enabled = false; |
291 | } | 291 | } |
292 | } | 292 | } |
@@ -1070,10 +1070,6 @@ static void omap_gpio_mod_init(struct gpio_bank *bank) | |||
1070 | /* Initialize interface clk ungated, module enabled */ | 1070 | /* Initialize interface clk ungated, module enabled */ |
1071 | if (bank->regs->ctrl) | 1071 | if (bank->regs->ctrl) |
1072 | writel_relaxed(0, base + bank->regs->ctrl); | 1072 | writel_relaxed(0, base + bank->regs->ctrl); |
1073 | |||
1074 | bank->dbck = clk_get(bank->dev, "dbclk"); | ||
1075 | if (IS_ERR(bank->dbck)) | ||
1076 | dev_err(bank->dev, "Could not get gpio dbck\n"); | ||
1077 | } | 1073 | } |
1078 | 1074 | ||
1079 | static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) | 1075 | static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) |
@@ -1234,6 +1230,17 @@ static int omap_gpio_probe(struct platform_device *pdev) | |||
1234 | return PTR_ERR(bank->base); | 1230 | return PTR_ERR(bank->base); |
1235 | } | 1231 | } |
1236 | 1232 | ||
1233 | if (bank->dbck_flag) { | ||
1234 | bank->dbck = devm_clk_get(bank->dev, "dbclk"); | ||
1235 | if (IS_ERR(bank->dbck)) { | ||
1236 | dev_err(bank->dev, | ||
1237 | "Could not get gpio dbck. Disable debounce\n"); | ||
1238 | bank->dbck_flag = false; | ||
1239 | } else { | ||
1240 | clk_prepare(bank->dbck); | ||
1241 | } | ||
1242 | } | ||
1243 | |||
1237 | platform_set_drvdata(pdev, bank); | 1244 | platform_set_drvdata(pdev, bank); |
1238 | 1245 | ||
1239 | pm_runtime_enable(bank->dev); | 1246 | pm_runtime_enable(bank->dev); |
@@ -1265,6 +1272,8 @@ static int omap_gpio_remove(struct platform_device *pdev) | |||
1265 | list_del(&bank->node); | 1272 | list_del(&bank->node); |
1266 | gpiochip_remove(&bank->chip); | 1273 | gpiochip_remove(&bank->chip); |
1267 | pm_runtime_disable(bank->dev); | 1274 | pm_runtime_disable(bank->dev); |
1275 | if (bank->dbck_flag) | ||
1276 | clk_unprepare(bank->dbck); | ||
1268 | 1277 | ||
1269 | return 0; | 1278 | return 0; |
1270 | } | 1279 | } |