lkml.org 
[lkml]   [2022]   [Jan]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.15 013/846] mtd: rawnand: gpmi: Add ERR007117 protection for nfc_apply_timings
    Date
    From: Christian Eggers <ceggers@arri.de>

    commit f53d4c109a666bf1a4883b45d546fba079258717 upstream.

    gpmi_io clock needs to be gated off when changing the parent/dividers of
    enfc_clk_root (i.MX6Q/i.MX6UL) respectively qspi2_clk_root (i.MX6SX).
    Otherwise this rate change can lead to an unresponsive GPMI core which
    results in DMA timeouts and failed driver probe:

    [ 4.072318] gpmi-nand 112000.gpmi-nand: DMA timeout, last DMA
    ...
    [ 4.370355] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -110
    ...
    [ 4.375988] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
    [ 4.381524] gpmi-nand 112000.gpmi-nand: Error in ECC-based read: -22
    [ 4.387988] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
    [ 4.393535] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
    ...

    Other than stated in i.MX 6 erratum ERR007117, it should be sufficient
    to gate only gpmi_io because all other bch/nand clocks are derived from
    different clock roots.

    The i.MX6 reference manuals state that changing clock muxers can cause
    glitches but are silent about changing dividers. But tests showed that
    these glitches can definitely happen on i.MX6ULL. For i.MX7D/8MM in turn,
    the manual guarantees that no glitches can happen when changing
    dividers.

    Co-developed-by: Stefan Riedmueller <s.riedmueller@phytec.de>
    Signed-off-by: Stefan Riedmueller <s.riedmueller@phytec.de>
    Signed-off-by: Christian Eggers <ceggers@arri.de>
    Cc: stable@vger.kernel.org
    Acked-by: Han Xu <han.xu@nxp.com>
    Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
    Link: https://lore.kernel.org/linux-mtd/20211102202022.15551-2-ceggers@arri.de
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 28 +++++++++++++++++++++++++---
    1 file changed, 25 insertions(+), 3 deletions(-)

    --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
    +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
    @@ -713,14 +713,32 @@ static void gpmi_nfc_compute_timings(str
    (use_half_period ? BM_GPMI_CTRL1_HALF_PERIOD : 0);
    }

    -static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
    +static int gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
    {
    struct gpmi_nfc_hardware_timing *hw = &this->hw;
    struct resources *r = &this->resources;
    void __iomem *gpmi_regs = r->gpmi_regs;
    unsigned int dll_wait_time_us;
    + int ret;
    +
    + /* Clock dividers do NOT guarantee a clean clock signal on its output
    + * during the change of the divide factor on i.MX6Q/UL/SX. On i.MX7/8,
    + * all clock dividers provide these guarantee.
    + */
    + if (GPMI_IS_MX6Q(this) || GPMI_IS_MX6SX(this))
    + clk_disable_unprepare(r->clock[0]);
    +
    + ret = clk_set_rate(r->clock[0], hw->clk_rate);
    + if (ret) {
    + dev_err(this->dev, "cannot set clock rate to %lu Hz: %d\n", hw->clk_rate, ret);
    + return ret;
    + }

    - clk_set_rate(r->clock[0], hw->clk_rate);
    + if (GPMI_IS_MX6Q(this) || GPMI_IS_MX6SX(this)) {
    + ret = clk_prepare_enable(r->clock[0]);
    + if (ret)
    + return ret;
    + }

    writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
    writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);
    @@ -739,6 +757,8 @@ static void gpmi_nfc_apply_timings(struc

    /* Wait for the DLL to settle. */
    udelay(dll_wait_time_us);
    +
    + return 0;
    }

    static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
    @@ -2280,7 +2300,9 @@ static int gpmi_nfc_exec_op(struct nand_
    */
    if (this->hw.must_apply_timings) {
    this->hw.must_apply_timings = false;
    - gpmi_nfc_apply_timings(this);
    + ret = gpmi_nfc_apply_timings(this);
    + if (ret)
    + return ret;
    }

    dev_dbg(this->dev, "%s: %d instructions\n", __func__, op->ninstrs);

    \
     
     \ /
      Last update: 2022-01-24 23:04    [W:4.019 / U:0.028 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site