Message ID | 20190129054039.15278-1-marek.vasut@gmail.com (mailing list archive) |
---|---|
State | Accepted |
Delegated to: | Geert Uytterhoeven |
Headers | show |
Series | mmc: renesas_sdhi: Fix card initialization failure in high speed mode | expand |
On Tue, Jan 29, 2019 at 06:40:39AM +0100, marek.vasut@gmail.com wrote: > From: Takeshi Saito <takeshi.saito.xv@renesas.com> > > This fixes card initialization failure in high speed mode. > > If U-Boot uses SDR or HS200/400 mode before starting Linux and Linux > DT does not enable SDR/HS200/HS400 mode, card initialization fails in > high speed mode. > > It is necessary to initialize SCC registers during card initialization > phase. HW reset function is registered only for a port with either of > SDR/HS200/HS400 properties in device tree. If SDR/HS200/HS400 properties > are not present in device tree, SCC registers will not be reset. In SoC > that support SCC registers, HW reset function should be registered > regardless of the configuration of device tree. > > Reproduction procedure: > - Use U-Boot that support MMC HS200/400 mode. > - Delete HS200/HS400 properties in device tree. > (Delete mmc-hs200-1_8v and mmc-hs400-1_8v) > - MMC port works high speed mode and all commands fail. > > Signed-off-by: Takeshi Saito <takeshi.saito.xv@renesas.com> > Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com> > Cc: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> > Cc: Simon Horman <horms+renesas@verge.net.au> > Cc: Ulf Hansson <ulf.hansson@linaro.org> > Cc: Wolfram Sang <wsa+renesas@sang-engineering.com> > Cc: linux-renesas-soc@vger.kernel.org > To: linux-mmc@vger.kernel.org Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
On Tue, 29 Jan 2019 at 06:40, <marek.vasut@gmail.com> wrote: > > From: Takeshi Saito <takeshi.saito.xv@renesas.com> > > This fixes card initialization failure in high speed mode. > > If U-Boot uses SDR or HS200/400 mode before starting Linux and Linux > DT does not enable SDR/HS200/HS400 mode, card initialization fails in > high speed mode. > > It is necessary to initialize SCC registers during card initialization > phase. HW reset function is registered only for a port with either of > SDR/HS200/HS400 properties in device tree. If SDR/HS200/HS400 properties > are not present in device tree, SCC registers will not be reset. In SoC > that support SCC registers, HW reset function should be registered > regardless of the configuration of device tree. > > Reproduction procedure: > - Use U-Boot that support MMC HS200/400 mode. > - Delete HS200/HS400 properties in device tree. > (Delete mmc-hs200-1_8v and mmc-hs400-1_8v) > - MMC port works high speed mode and all commands fail. > > Signed-off-by: Takeshi Saito <takeshi.saito.xv@renesas.com> > Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com> > Cc: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> > Cc: Simon Horman <horms+renesas@verge.net.au> > Cc: Ulf Hansson <ulf.hansson@linaro.org> > Cc: Wolfram Sang <wsa+renesas@sang-engineering.com> > Cc: linux-renesas-soc@vger.kernel.org > To: linux-mmc@vger.kernel.org Is this a regression? Should it be tagged for stable? Kind regards Uffe > -- > NOTE: Marek: - Reworded commit message > - Updated patch to next/master > --- > drivers/mmc/host/renesas_sdhi_core.c | 11 +++++++---- > 1 file changed, 7 insertions(+), 4 deletions(-) > > diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c > index 31a351a20dc0..7e2a75c4f36f 100644 > --- a/drivers/mmc/host/renesas_sdhi_core.c > +++ b/drivers/mmc/host/renesas_sdhi_core.c > @@ -723,6 +723,13 @@ int renesas_sdhi_probe(struct platform_device *pdev, > host->ops.start_signal_voltage_switch = > renesas_sdhi_start_signal_voltage_switch; > host->sdcard_irq_setbit_mask = TMIO_STAT_ALWAYS_SET_27; > + > + /* SDR and HS200/400 registers requires HW reset */ > + if (of_data && of_data->scc_offset) { > + priv->scc_ctl = host->ctl + of_data->scc_offset; > + host->mmc->caps |= MMC_CAP_HW_RESET; > + host->hw_reset = renesas_sdhi_hw_reset; > + } > } > > /* Orginally registers were 16 bit apart, could be 32 or 64 nowadays */ > @@ -775,8 +782,6 @@ int renesas_sdhi_probe(struct platform_device *pdev, > const struct renesas_sdhi_scc *taps = of_data->taps; > bool hit = false; > > - host->mmc->caps |= MMC_CAP_HW_RESET; > - > for (i = 0; i < of_data->taps_num; i++) { > if (taps[i].clk_rate == 0 || > taps[i].clk_rate == host->mmc->f_max) { > @@ -789,12 +794,10 @@ int renesas_sdhi_probe(struct platform_device *pdev, > if (!hit) > dev_warn(&host->pdev->dev, "Unknown clock rate for SDR104\n"); > > - priv->scc_ctl = host->ctl + of_data->scc_offset; > host->init_tuning = renesas_sdhi_init_tuning; > host->prepare_tuning = renesas_sdhi_prepare_tuning; > host->select_tuning = renesas_sdhi_select_tuning; > host->check_scc_error = renesas_sdhi_check_scc_error; > - host->hw_reset = renesas_sdhi_hw_reset; > host->prepare_hs400_tuning = > renesas_sdhi_prepare_hs400_tuning; > host->hs400_downgrade = renesas_sdhi_disable_scc; > -- > 2.19.2 >
On 1/29/19 9:05 AM, Ulf Hansson wrote: > On Tue, 29 Jan 2019 at 06:40, <marek.vasut@gmail.com> wrote: >> >> From: Takeshi Saito <takeshi.saito.xv@renesas.com> >> >> This fixes card initialization failure in high speed mode. >> >> If U-Boot uses SDR or HS200/400 mode before starting Linux and Linux >> DT does not enable SDR/HS200/HS400 mode, card initialization fails in >> high speed mode. >> >> It is necessary to initialize SCC registers during card initialization >> phase. HW reset function is registered only for a port with either of >> SDR/HS200/HS400 properties in device tree. If SDR/HS200/HS400 properties >> are not present in device tree, SCC registers will not be reset. In SoC >> that support SCC registers, HW reset function should be registered >> regardless of the configuration of device tree. >> >> Reproduction procedure: >> - Use U-Boot that support MMC HS200/400 mode. >> - Delete HS200/HS400 properties in device tree. >> (Delete mmc-hs200-1_8v and mmc-hs400-1_8v) >> - MMC port works high speed mode and all commands fail. >> >> Signed-off-by: Takeshi Saito <takeshi.saito.xv@renesas.com> >> Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com> >> Cc: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> >> Cc: Simon Horman <horms+renesas@verge.net.au> >> Cc: Ulf Hansson <ulf.hansson@linaro.org> >> Cc: Wolfram Sang <wsa+renesas@sang-engineering.com> >> Cc: linux-renesas-soc@vger.kernel.org >> To: linux-mmc@vger.kernel.org > > Is this a regression? No, because this was broken since the beginning. But U-Boot HS200/HS400 support is now, so this bug was hidden. > Should it be tagged for stable? I am tempted to say yes.
> > Should it be tagged for stable? > > I am tempted to say yes. I agree.
On Tue, 29 Jan 2019 at 06:40, <marek.vasut@gmail.com> wrote: > > From: Takeshi Saito <takeshi.saito.xv@renesas.com> > > This fixes card initialization failure in high speed mode. > > If U-Boot uses SDR or HS200/400 mode before starting Linux and Linux > DT does not enable SDR/HS200/HS400 mode, card initialization fails in > high speed mode. > > It is necessary to initialize SCC registers during card initialization > phase. HW reset function is registered only for a port with either of > SDR/HS200/HS400 properties in device tree. If SDR/HS200/HS400 properties > are not present in device tree, SCC registers will not be reset. In SoC > that support SCC registers, HW reset function should be registered > regardless of the configuration of device tree. > > Reproduction procedure: > - Use U-Boot that support MMC HS200/400 mode. > - Delete HS200/HS400 properties in device tree. > (Delete mmc-hs200-1_8v and mmc-hs400-1_8v) > - MMC port works high speed mode and all commands fail. > > Signed-off-by: Takeshi Saito <takeshi.saito.xv@renesas.com> > Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com> > Cc: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> > Cc: Simon Horman <horms+renesas@verge.net.au> > Cc: Ulf Hansson <ulf.hansson@linaro.org> > Cc: Wolfram Sang <wsa+renesas@sang-engineering.com> > Cc: linux-renesas-soc@vger.kernel.org > To: linux-mmc@vger.kernel.org Applied for next and added a stable tag, thanks! Kind regards Uffe > -- > NOTE: Marek: - Reworded commit message > - Updated patch to next/master > --- > drivers/mmc/host/renesas_sdhi_core.c | 11 +++++++---- > 1 file changed, 7 insertions(+), 4 deletions(-) > > diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c > index 31a351a20dc0..7e2a75c4f36f 100644 > --- a/drivers/mmc/host/renesas_sdhi_core.c > +++ b/drivers/mmc/host/renesas_sdhi_core.c > @@ -723,6 +723,13 @@ int renesas_sdhi_probe(struct platform_device *pdev, > host->ops.start_signal_voltage_switch = > renesas_sdhi_start_signal_voltage_switch; > host->sdcard_irq_setbit_mask = TMIO_STAT_ALWAYS_SET_27; > + > + /* SDR and HS200/400 registers requires HW reset */ > + if (of_data && of_data->scc_offset) { > + priv->scc_ctl = host->ctl + of_data->scc_offset; > + host->mmc->caps |= MMC_CAP_HW_RESET; > + host->hw_reset = renesas_sdhi_hw_reset; > + } > } > > /* Orginally registers were 16 bit apart, could be 32 or 64 nowadays */ > @@ -775,8 +782,6 @@ int renesas_sdhi_probe(struct platform_device *pdev, > const struct renesas_sdhi_scc *taps = of_data->taps; > bool hit = false; > > - host->mmc->caps |= MMC_CAP_HW_RESET; > - > for (i = 0; i < of_data->taps_num; i++) { > if (taps[i].clk_rate == 0 || > taps[i].clk_rate == host->mmc->f_max) { > @@ -789,12 +794,10 @@ int renesas_sdhi_probe(struct platform_device *pdev, > if (!hit) > dev_warn(&host->pdev->dev, "Unknown clock rate for SDR104\n"); > > - priv->scc_ctl = host->ctl + of_data->scc_offset; > host->init_tuning = renesas_sdhi_init_tuning; > host->prepare_tuning = renesas_sdhi_prepare_tuning; > host->select_tuning = renesas_sdhi_select_tuning; > host->check_scc_error = renesas_sdhi_check_scc_error; > - host->hw_reset = renesas_sdhi_hw_reset; > host->prepare_hs400_tuning = > renesas_sdhi_prepare_hs400_tuning; > host->hs400_downgrade = renesas_sdhi_disable_scc; > -- > 2.19.2 >
diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 31a351a20dc0..7e2a75c4f36f 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -723,6 +723,13 @@ int renesas_sdhi_probe(struct platform_device *pdev, host->ops.start_signal_voltage_switch = renesas_sdhi_start_signal_voltage_switch; host->sdcard_irq_setbit_mask = TMIO_STAT_ALWAYS_SET_27; + + /* SDR and HS200/400 registers requires HW reset */ + if (of_data && of_data->scc_offset) { + priv->scc_ctl = host->ctl + of_data->scc_offset; + host->mmc->caps |= MMC_CAP_HW_RESET; + host->hw_reset = renesas_sdhi_hw_reset; + } } /* Orginally registers were 16 bit apart, could be 32 or 64 nowadays */ @@ -775,8 +782,6 @@ int renesas_sdhi_probe(struct platform_device *pdev, const struct renesas_sdhi_scc *taps = of_data->taps; bool hit = false; - host->mmc->caps |= MMC_CAP_HW_RESET; - for (i = 0; i < of_data->taps_num; i++) { if (taps[i].clk_rate == 0 || taps[i].clk_rate == host->mmc->f_max) { @@ -789,12 +794,10 @@ int renesas_sdhi_probe(struct platform_device *pdev, if (!hit) dev_warn(&host->pdev->dev, "Unknown clock rate for SDR104\n"); - priv->scc_ctl = host->ctl + of_data->scc_offset; host->init_tuning = renesas_sdhi_init_tuning; host->prepare_tuning = renesas_sdhi_prepare_tuning; host->select_tuning = renesas_sdhi_select_tuning; host->check_scc_error = renesas_sdhi_check_scc_error; - host->hw_reset = renesas_sdhi_hw_reset; host->prepare_hs400_tuning = renesas_sdhi_prepare_hs400_tuning; host->hs400_downgrade = renesas_sdhi_disable_scc;