Qiang Li - Mpu Se

Why clk_enable and clk_disable can't be called in interrupt context for freescale Linux BSP -blog archive

Discussion created by Qiang Li - Mpu Se Employee on Feb 21, 2012

    In Freescale Linux BSP code, clk_enable() in clock.c (in folder /kernel_imx/arch/arm/plat-mxc) is not allowed to be used in ISR context as attached real code below.

 if (in_interrupt()) {
  printk(KERN_ERR " clk_enable cannot be called in an interrupt context\n");
  dump_stack();
  BUG();
 }

 

    The main reason behind doing this is to allow for voltage scaling as part of clk_enable()/clk_disable() functions. Voltage scaling uses the Regulator APIs which cannot be called in an ISR context.
For example, in clk_enable/clk_disable, set_low_bus_freq() and set_high_bus_freq() have chance to be called, and in these functions, regulator_set_voltage() sometimes will be called.

    For a temp solution, If you wants to call clk_enable/clk_disable in UART ISR context, I think you can define two new functions, just remove the bus_freq related codes. (Because the UART clock is not DVFS or bus freq related, and other BSP driver will continue to use the original clk apis, there will be no impact)

 

int clk_enable2(struct clk *clk)
{
 unsigned long flags;
 int ret = 0;

 if (clk == NULL || IS_ERR(clk))
  return -EINVAL;

 spin_lock_irqsave(&clockfw_lock, flags);

 ret = __clk_enable(clk);

 spin_unlock_irqrestore(&clockfw_lock, flags);

 return ret;
}
EXPORT_SYMBOL(clk_enable2);

 

void clk_disable2(struct clk *clk)
{
 unsigned long flags;

 if (clk == NULL || IS_ERR(clk))
  return;

 spin_lock_irqsave(&clockfw_lock, flags);

 __clk_disable(clk);

 spin_unlock_irqrestore(&clockfw_lock, flags);
}

EXPORT_SYMBOL(clk_disable2);

Outcomes