[PATCH linux dev-4.13] clk: aspeed: Prevent reset and enable if clock is already enabled

Lei YU mine260309 at gmail.com
Wed Mar 7 13:33:14 AEDT 2018


With the patch, the hang issue in ISTEPS (openbmc/openbmc#2948) is gone, in both
cold and warm boot.

Tested-by: Lei YU <mine260309 at gmail.com>

On Wed, Mar 7, 2018 at 4:24 AM, Eddie James <eajames at linux.vnet.ibm.com> wrote:
> Systems are seeing some issues where the LPC clock gets into a bad state
> when the ASPEED clock driver resets and enables the clock during
> startup. The LPC clock (according to AST2500 spec) is enabled by default,
> so resetting and re-enabling is not desired. Add a simple check before the
> enable procedure to see if the clock is already enabled.
>
> Signed-off-by: Eddie James <eajames at linux.vnet.ibm.com>
> ---
>  drivers/clk/clk-aspeed.c | 42 ++++++++++++++++++++++++------------------
>  1 file changed, 24 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/clk/clk-aspeed.c b/drivers/clk/clk-aspeed.c
> index b67ba14..3d12f7a 100644
> --- a/drivers/clk/clk-aspeed.c
> +++ b/drivers/clk/clk-aspeed.c
> @@ -221,27 +221,33 @@ static int aspeed_clk_enable(struct clk_hw *hw)
>         u32 clk = BIT(gate->clock_idx);
>         u32 rst = BIT(gate->reset_idx);
>         u32 enval;
> +       u32 reg;
>

I would prefer to call aspeed_clk_is_enabled() to check if it's
enabled and return
before spin_lock_irqsave().

>         spin_lock_irqsave(gate->lock, flags);
>
> -       if (gate->reset_idx >= 0) {
> -               /* Put IP in reset */
> -               regmap_update_bits(gate->map, ASPEED_RESET_CTRL, rst, rst);
> -
> -               /* Delay 100us */
> -               udelay(100);
> -       }
> -
> -       /* Enable clock */
> -       enval = (gate->flags & CLK_GATE_SET_TO_DISABLE) ? 0 : clk;
> -       regmap_update_bits(gate->map, ASPEED_CLK_STOP_CTRL, clk, enval);
> -
> -       if (gate->reset_idx >= 0) {
> -               /* A delay of 10ms is specified by the ASPEED docs */
> -               mdelay(10);
> -
> -               /* Take IP out of reset */
> -               regmap_update_bits(gate->map, ASPEED_RESET_CTRL, rst, 0);
> +       /* Only reset/enable/unreset if clock isn't already enabled */
> +       regmap_read(gate->map, ASPEED_CLK_STOP_CTRL, &reg);
> +       if (reg & clk) {
> +               if (gate->reset_idx >= 0) {
> +                       /* Put IP in reset */
> +                       regmap_update_bits(gate->map, ASPEED_RESET_CTRL, rst,
> +                                          rst);
> +
> +                       /* Delay 100us */
> +                       udelay(100);
> +               }
> +
> +               /* Enable clock */
> +               enval = (gate->flags & CLK_GATE_SET_TO_DISABLE) ? 0 : clk;
> +               regmap_update_bits(gate->map, ASPEED_CLK_STOP_CTRL, clk, enval);
> +
> +               if (gate->reset_idx >= 0) {
> +                       /* A delay of 10ms is specified by the ASPEED docs */
> +                       mdelay(10);
> +
> +                       /* Take IP out of reset */
> +                       regmap_update_bits(gate->map, ASPEED_RESET_CTRL, rst,                                              0);

Remove the extra blanks or put it in next line.

> +               }
>         }
>
>         spin_unlock_irqrestore(gate->lock, flags);
> --
> 1.8.3.1
>


More information about the openbmc mailing list