Skip to content

Commit 05d8af4

Browse files
Marek Vasutlinusw
Marek Vasut
authored andcommitted
pinctrl: stm32: Keep pinctrl block clock enabled when LEVEL IRQ requested
The current EOI handler for LEVEL triggered interrupts calls clk_enable(), register IO, clk_disable(). The clock manipulation requires locking which happens with IRQs disabled in clk_enable_lock(). Instead of turning the clock on and off all the time, enable the clock in case LEVEL interrupt is requested and keep the clock enabled until all LEVEL interrupts are freed. The LEVEL interrupts are an exception on this platform and seldom used, so this does not affect the common case. This simplifies the LEVEL interrupt handling considerably and also fixes the following splat found when using preempt-rt: ------------[ cut here ]------------ WARNING: CPU: 0 PID: 0 at kernel/locking/rtmutex.c:2040 __rt_mutex_trylock+0x37/0x62 Modules linked in: CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.10.109-rt65-stable-standard-00068-g6a5afc4b1217 #85 Hardware name: STM32 (Device Tree Support) [<c010a45d>] (unwind_backtrace) from [<c010766f>] (show_stack+0xb/0xc) [<c010766f>] (show_stack) from [<c06353ab>] (dump_stack+0x6f/0x84) [<c06353ab>] (dump_stack) from [<c01145e3>] (__warn+0x7f/0xa4) [<c01145e3>] (__warn) from [<c063386f>] (warn_slowpath_fmt+0x3b/0x74) [<c063386f>] (warn_slowpath_fmt) from [<c063b43d>] (__rt_mutex_trylock+0x37/0x62) [<c063b43d>] (__rt_mutex_trylock) from [<c063c053>] (rt_spin_trylock+0x7/0x16) [<c063c053>] (rt_spin_trylock) from [<c036a2f3>] (clk_enable_lock+0xb/0x80) [<c036a2f3>] (clk_enable_lock) from [<c036ba69>] (clk_core_enable_lock+0x9/0x18) [<c036ba69>] (clk_core_enable_lock) from [<c034e9f3>] (stm32_gpio_get+0x11/0x24) [<c034e9f3>] (stm32_gpio_get) from [<c034ef43>] (stm32_gpio_irq_trigger+0x1f/0x48) [<c034ef43>] (stm32_gpio_irq_trigger) from [<c014aa53>] (handle_fasteoi_irq+0x71/0xa8) [<c014aa53>] (handle_fasteoi_irq) from [<c0147111>] (generic_handle_irq+0x19/0x22) [<c0147111>] (generic_handle_irq) from [<c014752d>] (__handle_domain_irq+0x55/0x64) [<c014752d>] (__handle_domain_irq) from [<c0346f13>] (gic_handle_irq+0x53/0x64) [<c0346f13>] (gic_handle_irq) from [<c0100ba5>] (__irq_svc+0x65/0xc0) Exception stack(0xc0e01f18 to 0xc0e01f60) 1f00: 0000300c 00000000 1f20: 0000300c c010ff01 00000000 00000000 c0e00000 c0e07714 00000001 c0e01f78 1f40: c0e07758 00000000 ef7cd0ff c0e01f68 c010554b c0105542 40000033 ffffffff [<c0100ba5>] (__irq_svc) from [<c0105542>] (arch_cpu_idle+0xc/0x1e) [<c0105542>] (arch_cpu_idle) from [<c063be95>] (default_idle_call+0x21/0x3c) [<c063be95>] (default_idle_call) from [<c01324f7>] (do_idle+0xe3/0x1e4) [<c01324f7>] (do_idle) from [<c01327b3>] (cpu_startup_entry+0x13/0x14) [<c01327b3>] (cpu_startup_entry) from [<c0a00c13>] (start_kernel+0x397/0x3d4) [<c0a00c13>] (start_kernel) from [<00000000>] (0x0) ---[ end trace 0000000000000002 ]--- Power consumption measured on STM32MP157C DHCOM SoM is not increased or is below noise threshold. Fixes: 47beed5 ("pinctrl: stm32: Add level interrupt support to gpio irq chip") Signed-off-by: Marek Vasut <[email protected]> Cc: Alexandre Torgue <[email protected]> Cc: Fabien Dessenne <[email protected]> Cc: Linus Walleij <[email protected]> Cc: Marc Zyngier <[email protected]> Cc: [email protected] Cc: [email protected] To: [email protected] Reviewed-by: Fabien Dessenne <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Linus Walleij <[email protected]>
1 parent 7c4cffc commit 05d8af4

File tree

1 file changed

+17
-2
lines changed

1 file changed

+17
-2
lines changed

drivers/pinctrl/stm32/pinctrl-stm32.c

+17-2
Original file line numberDiff line numberDiff line change
@@ -225,14 +225,21 @@ static void stm32_gpio_free(struct gpio_chip *chip, unsigned offset)
225225
pinctrl_gpio_free(chip->base + offset);
226226
}
227227

228+
static int stm32_gpio_get_noclk(struct gpio_chip *chip, unsigned int offset)
229+
{
230+
struct stm32_gpio_bank *bank = gpiochip_get_data(chip);
231+
232+
return !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset));
233+
}
234+
228235
static int stm32_gpio_get(struct gpio_chip *chip, unsigned offset)
229236
{
230237
struct stm32_gpio_bank *bank = gpiochip_get_data(chip);
231238
int ret;
232239

233240
clk_enable(bank->clk);
234241

235-
ret = !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset));
242+
ret = stm32_gpio_get_noclk(chip, offset);
236243

237244
clk_disable(bank->clk);
238245

@@ -316,7 +323,7 @@ static void stm32_gpio_irq_trigger(struct irq_data *d)
316323
return;
317324

318325
/* If level interrupt type then retrig */
319-
level = stm32_gpio_get(&bank->gpio_chip, d->hwirq);
326+
level = stm32_gpio_get_noclk(&bank->gpio_chip, d->hwirq);
320327
if ((level == 0 && bank->irq_type[d->hwirq] == IRQ_TYPE_LEVEL_LOW) ||
321328
(level == 1 && bank->irq_type[d->hwirq] == IRQ_TYPE_LEVEL_HIGH))
322329
irq_chip_retrigger_hierarchy(d);
@@ -358,6 +365,7 @@ static int stm32_gpio_irq_request_resources(struct irq_data *irq_data)
358365
{
359366
struct stm32_gpio_bank *bank = irq_data->domain->host_data;
360367
struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
368+
unsigned long flags;
361369
int ret;
362370

363371
ret = stm32_gpio_direction_input(&bank->gpio_chip, irq_data->hwirq);
@@ -371,13 +379,20 @@ static int stm32_gpio_irq_request_resources(struct irq_data *irq_data)
371379
return ret;
372380
}
373381

382+
flags = irqd_get_trigger_type(irq_data);
383+
if (flags & IRQ_TYPE_LEVEL_MASK)
384+
clk_enable(bank->clk);
385+
374386
return 0;
375387
}
376388

377389
static void stm32_gpio_irq_release_resources(struct irq_data *irq_data)
378390
{
379391
struct stm32_gpio_bank *bank = irq_data->domain->host_data;
380392

393+
if (bank->irq_type[irq_data->hwirq] & IRQ_TYPE_LEVEL_MASK)
394+
clk_disable(bank->clk);
395+
381396
gpiochip_unlock_as_irq(&bank->gpio_chip, irq_data->hwirq);
382397
}
383398

0 commit comments

Comments
 (0)