lkml.org 
[lkml]   [2019]   [Mar]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.9 074/118] clk: clk-twl6040: Fix imprecise external abort for pdmclk
    Date
    4.9-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Tony Lindgren <tony@atomide.com>

    commit 5ae51d67aec95f6f9386aa8dd5db424964895575 upstream.

    I noticed that modprobe clk-twl6040 can fail after a cold boot with:
    abe_cm:clk:0010:0: failed to enable
    ...
    Unhandled fault: imprecise external abort (0x1406) at 0xbe896b20

    WARNING: CPU: 1 PID: 29 at drivers/clk/clk.c:828 clk_core_disable_lock+0x18/0x24
    ...
    (clk_core_disable_lock) from [<c0123534>] (_disable_clocks+0x18/0x90)
    (_disable_clocks) from [<c0124040>] (_idle+0x17c/0x244)
    (_idle) from [<c0125ad4>] (omap_hwmod_idle+0x24/0x44)
    (omap_hwmod_idle) from [<c053a038>] (sysc_runtime_suspend+0x48/0x108)
    (sysc_runtime_suspend) from [<c06084c4>] (__rpm_callback+0x144/0x1d8)
    (__rpm_callback) from [<c0608578>] (rpm_callback+0x20/0x80)
    (rpm_callback) from [<c0607034>] (rpm_suspend+0x120/0x694)
    (rpm_suspend) from [<c0607a78>] (__pm_runtime_idle+0x60/0x84)
    (__pm_runtime_idle) from [<c053aaf0>] (sysc_probe+0x874/0xf2c)
    (sysc_probe) from [<c05fecd4>] (platform_drv_probe+0x48/0x98)

    After searching around for a similar issue, I came across an earlier fix
    that never got merged upstream in the Android tree for glass-omap-xrr02.
    There is patch "MFD: twl6040-codec: Implement PDMCLK cold temp errata"
    by Misael Lopez Cruz <misael.lopez@ti.com>.

    Based on my observations, this fix is also needed when cold booting
    devices, and not just for deeper idle modes. Since we now have a clock
    driver for pdmclk, let's fix the issue in twl6040_pdmclk_prepare().

    Cc: Misael Lopez Cruz <misael.lopez@ti.com>
    Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
    Signed-off-by: Tony Lindgren <tony@atomide.com>
    Acked-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
    Cc: <stable@vger.kernel.org>
    Signed-off-by: Stephen Boyd <sboyd@kernel.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/clk/clk-twl6040.c | 53 ++++++++++++++++++++++++++++++++++++++++++++--
    1 file changed, 51 insertions(+), 2 deletions(-)

    --- a/drivers/clk/clk-twl6040.c
    +++ b/drivers/clk/clk-twl6040.c
    @@ -41,6 +41,43 @@ static int twl6040_pdmclk_is_prepared(st
    return pdmclk->enabled;
    }

    +static int twl6040_pdmclk_reset_one_clock(struct twl6040_pdmclk *pdmclk,
    + unsigned int reg)
    +{
    + const u8 reset_mask = TWL6040_HPLLRST; /* Same for HPPLL and LPPLL */
    + int ret;
    +
    + ret = twl6040_set_bits(pdmclk->twl6040, reg, reset_mask);
    + if (ret < 0)
    + return ret;
    +
    + ret = twl6040_clear_bits(pdmclk->twl6040, reg, reset_mask);
    + if (ret < 0)
    + return ret;
    +
    + return 0;
    +}
    +
    +/*
    + * TWL6040A2 Phoenix Audio IC erratum #6: "PDM Clock Generation Issue At
    + * Cold Temperature". This affects cold boot and deeper idle states it
    + * seems. The workaround consists of resetting HPPLL and LPPLL.
    + */
    +static int twl6040_pdmclk_quirk_reset_clocks(struct twl6040_pdmclk *pdmclk)
    +{
    + int ret;
    +
    + ret = twl6040_pdmclk_reset_one_clock(pdmclk, TWL6040_REG_HPPLLCTL);
    + if (ret)
    + return ret;
    +
    + ret = twl6040_pdmclk_reset_one_clock(pdmclk, TWL6040_REG_LPPLLCTL);
    + if (ret)
    + return ret;
    +
    + return 0;
    +}
    +
    static int twl6040_pdmclk_prepare(struct clk_hw *hw)
    {
    struct twl6040_pdmclk *pdmclk = container_of(hw, struct twl6040_pdmclk,
    @@ -48,8 +85,20 @@ static int twl6040_pdmclk_prepare(struct
    int ret;

    ret = twl6040_power(pdmclk->twl6040, 1);
    - if (!ret)
    - pdmclk->enabled = 1;
    + if (ret)
    + return ret;
    +
    + ret = twl6040_pdmclk_quirk_reset_clocks(pdmclk);
    + if (ret)
    + goto out_err;
    +
    + pdmclk->enabled = 1;
    +
    + return 0;
    +
    +out_err:
    + dev_err(pdmclk->dev, "%s: error %i\n", __func__, ret);
    + twl6040_power(pdmclk->twl6040, 0);

    return ret;
    }

    \
     
     \ /
      Last update: 2019-03-22 14:02    [W:4.118 / U:0.392 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site