diff mbox series

[V1,1/1] mmc:sdhci-pci-o2micro: Bug fix for SDR104 HW tuning failure

Message ID 20210206014051.3418-1-shirley.her@bayhubtech.com
State New
Headers show
Series [V1,1/1] mmc:sdhci-pci-o2micro: Bug fix for SDR104 HW tuning failure | expand

Commit Message

Shirley Her Feb. 6, 2021, 1:40 a.m. UTC
Force chip enter L0 power state during SDR104 HW tuning to avoid tuning failure

Signed-off-by: Shirley Her <shirley.her@bayhubtech.com>
---
change in V1:
1. Force chip enter L0 power mode before HW tuning
2. Cancel force chip enter L0 power mode after HW tuning
---
---
 drivers/mmc/host/sdhci-pci-o2micro.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

Comments

Ulf Hansson Feb. 12, 2021, 12:20 p.m. UTC | #1
On Sat, 6 Feb 2021 at 02:40, Shirley Her <shirley.her@bayhubtech.com> wrote:
>

> Force chip enter L0 power state during SDR104 HW tuning to avoid tuning failure

>

> Signed-off-by: Shirley Her <shirley.her@bayhubtech.com>


Applied for next, thanks!

Please tell, if you'd like me to tag this for stable?

Kind regards
Uffe


> ---

> change in V1:

> 1. Force chip enter L0 power mode before HW tuning

> 2. Cancel force chip enter L0 power mode after HW tuning

> ---

> ---

>  drivers/mmc/host/sdhci-pci-o2micro.c | 20 ++++++++++++++++++++

>  1 file changed, 20 insertions(+)

>

> diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c

> index fa76748d8929..94e3f72f6405 100644

> --- a/drivers/mmc/host/sdhci-pci-o2micro.c

> +++ b/drivers/mmc/host/sdhci-pci-o2micro.c

> @@ -33,6 +33,8 @@

>  #define O2_SD_ADMA2            0xE7

>  #define O2_SD_INF_MOD          0xF1

>  #define O2_SD_MISC_CTRL4       0xFC

> +#define O2_SD_MISC_CTRL                0x1C0

> +#define O2_SD_PWR_FORCE_L0     0x0002

>  #define O2_SD_TUNING_CTRL      0x300

>  #define O2_SD_PLL_SETTING      0x304

>  #define O2_SD_MISC_SETTING     0x308

> @@ -300,6 +302,8 @@ static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode)

>  {

>         struct sdhci_host *host = mmc_priv(mmc);

>         int current_bus_width = 0;

> +       u32 scratch32 = 0;

> +       u16 scratch = 0;

>

>         /*

>          * This handler only implements the eMMC tuning that is specific to

> @@ -312,6 +316,17 @@ static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode)

>         if (WARN_ON((opcode != MMC_SEND_TUNING_BLOCK_HS200) &&

>                         (opcode != MMC_SEND_TUNING_BLOCK)))

>                 return -EINVAL;

> +

> +       /* Force power mode enter L0 */

> +       scratch = sdhci_readw(host, O2_SD_MISC_CTRL);

> +       scratch |= O2_SD_PWR_FORCE_L0;

> +       sdhci_writew(host, scratch, O2_SD_MISC_CTRL);

> +

> +       /* wait DLL lock, timeout value 5ms */

> +       if (readx_poll_timeout(sdhci_o2_pll_dll_wdt_control, host,

> +               scratch32, (scratch32 & O2_DLL_LOCK_STATUS), 1, 5000))

> +               pr_warn("%s: DLL can't lock in 5ms after force L0 during tuning.\n",

> +                               mmc_hostname(host->mmc));

>         /*

>          * Judge the tuning reason, whether caused by dll shift

>          * If cause by dll shift, should call sdhci_o2_dll_recovery

> @@ -344,6 +359,11 @@ static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode)

>                 sdhci_set_bus_width(host, current_bus_width);

>         }

>

> +       /* Cancel force power mode enter L0 */

> +       scratch = sdhci_readw(host, O2_SD_MISC_CTRL);

> +       scratch &= ~(O2_SD_PWR_FORCE_L0);

> +       sdhci_writew(host, scratch, O2_SD_MISC_CTRL);

> +

>         sdhci_reset(host, SDHCI_RESET_CMD);

>         sdhci_reset(host, SDHCI_RESET_DATA);

>

> --

> 2.17.1

>
diff mbox series

Patch

diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c
index fa76748d8929..94e3f72f6405 100644
--- a/drivers/mmc/host/sdhci-pci-o2micro.c
+++ b/drivers/mmc/host/sdhci-pci-o2micro.c
@@ -33,6 +33,8 @@ 
 #define O2_SD_ADMA2		0xE7
 #define O2_SD_INF_MOD		0xF1
 #define O2_SD_MISC_CTRL4	0xFC
+#define O2_SD_MISC_CTRL		0x1C0
+#define O2_SD_PWR_FORCE_L0	0x0002
 #define O2_SD_TUNING_CTRL	0x300
 #define O2_SD_PLL_SETTING	0x304
 #define O2_SD_MISC_SETTING	0x308
@@ -300,6 +302,8 @@  static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode)
 {
 	struct sdhci_host *host = mmc_priv(mmc);
 	int current_bus_width = 0;
+	u32 scratch32 = 0;
+	u16 scratch = 0;
 
 	/*
 	 * This handler only implements the eMMC tuning that is specific to
@@ -312,6 +316,17 @@  static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode)
 	if (WARN_ON((opcode != MMC_SEND_TUNING_BLOCK_HS200) &&
 			(opcode != MMC_SEND_TUNING_BLOCK)))
 		return -EINVAL;
+
+	/* Force power mode enter L0 */
+	scratch = sdhci_readw(host, O2_SD_MISC_CTRL);
+	scratch |= O2_SD_PWR_FORCE_L0;
+	sdhci_writew(host, scratch, O2_SD_MISC_CTRL);
+
+	/* wait DLL lock, timeout value 5ms */
+	if (readx_poll_timeout(sdhci_o2_pll_dll_wdt_control, host,
+		scratch32, (scratch32 & O2_DLL_LOCK_STATUS), 1, 5000))
+		pr_warn("%s: DLL can't lock in 5ms after force L0 during tuning.\n",
+				mmc_hostname(host->mmc));
 	/*
 	 * Judge the tuning reason, whether caused by dll shift
 	 * If cause by dll shift, should call sdhci_o2_dll_recovery
@@ -344,6 +359,11 @@  static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode)
 		sdhci_set_bus_width(host, current_bus_width);
 	}
 
+	/* Cancel force power mode enter L0 */
+	scratch = sdhci_readw(host, O2_SD_MISC_CTRL);
+	scratch &= ~(O2_SD_PWR_FORCE_L0);
+	sdhci_writew(host, scratch, O2_SD_MISC_CTRL);
+
 	sdhci_reset(host, SDHCI_RESET_CMD);
 	sdhci_reset(host, SDHCI_RESET_DATA);