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 |
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 --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);
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(+)