diff mbox series

[V1,1/1] mmc: sdhci-pci-o2micro: Fix Bayhub SD host hardware tuning compatibility issue for BanQ card

Message ID 20230927122652.4969-1-liuchang_125125@163.com (mailing list archive)
State New, archived
Headers show
Series [V1,1/1] mmc: sdhci-pci-o2micro: Fix Bayhub SD host hardware tuning compatibility issue for BanQ card | expand

Commit Message

liuchang_125125@163.com Sept. 27, 2023, 12:26 p.m. UTC
From: Charl Liu <liuchang_125125@163.com>

1.Driver get the card's MID and OID by init_card callback
function to judge whether the card is BanQ card
2.Update tuning setting to make sure tuning done can be set
3.Stop transfer for CMD19 after tuning done is set to avoid data
line inhibit and then set input phase manually for BanQ card

Signed-off-by: Charl Liu <liuchang_125125@163.com>
---
Change in V1:
Update the tuning process to be compatibility with BanQ card.
---
 drivers/mmc/host/sdhci-pci-o2micro.c | 204 ++++++++++++++++++++++++---
 1 file changed, 182 insertions(+), 22 deletions(-)


base-commit: 0e945134b680040b8613e962f586d91b6d40292d

Comments

kernel test robot Sept. 28, 2023, 12:37 a.m. UTC | #1
Hi,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 0e945134b680040b8613e962f586d91b6d40292d]

url:    https://github.com/intel-lab-lkp/linux/commits/liuchang_125125-163-com/mmc-sdhci-pci-o2micro-Fix-Bayhub-SD-host-hardware-tuning-compatibility-issue-for-BanQ-card/20230927-203005
base:   0e945134b680040b8613e962f586d91b6d40292d
patch link:    https://lore.kernel.org/r/20230927122652.4969-1-liuchang_125125%40163.com
patch subject: [PATCH V1 1/1] mmc: sdhci-pci-o2micro: Fix Bayhub SD host hardware tuning compatibility issue for BanQ card
config: alpha-allyesconfig (https://download.01.org/0day-ci/archive/20230928/202309280818.XQbiYALu-lkp@intel.com/config)
compiler: alpha-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20230928/202309280818.XQbiYALu-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202309280818.XQbiYALu-lkp@intel.com/

All warnings (new ones prefixed by >>):

   drivers/mmc/host/sdhci-pci-o2micro.c: In function 'sdhci_o2_tuning_setting':
>> drivers/mmc/host/sdhci-pci-o2micro.c:343:25: warning: unused variable 'o2_host' [-Wunused-variable]
     343 |         struct o2_host *o2_host = sdhci_pci_priv(slot);
         |                         ^~~~~~~
   drivers/mmc/host/sdhci-pci-o2micro.c: In function 'sdhci_o2_configure_banq_best_input_phase':
>> drivers/mmc/host/sdhci-pci-o2micro.c:370:13: warning: unused variable 'response' [-Wunused-variable]
     370 |         u32 response = 0;
         |             ^~~~~~~~
   drivers/mmc/host/sdhci-pci-o2micro.c: In function 'sdhci_o2_execute_tuning':
>> drivers/mmc/host/sdhci-pci-o2micro.c:407:26: warning: unused variable 'card' [-Wunused-variable]
     407 |         struct mmc_card *card = mmc->card;
         |                          ^~~~


vim +/o2_host +343 drivers/mmc/host/sdhci-pci-o2micro.c

   337	
   338	static void sdhci_o2_tuning_setting(struct mmc_host *mmc, bool isbanq, u8 phase_num)
   339	{
   340		struct sdhci_host *host = mmc_priv(mmc);
   341		struct sdhci_pci_slot *slot = sdhci_priv(host);
   342		struct sdhci_pci_chip *chip = slot->chip;
 > 343		struct o2_host *o2_host = sdhci_pci_priv(slot);
   344		u32 reg_val;
   345	
   346		if (isbanq) {
   347			/* update tuning command times for BanQ card */
   348			pci_read_config_dword(chip->pdev, O2_SD_TUNING_CTRL, &reg_val);
   349			reg_val &= 0x00FFFFFF;
   350			reg_val |= 0x02000000;
   351			pci_write_config_dword(chip->pdev, O2_SD_TUNING_CTRL, reg_val);
   352		} else {
   353			reg_val = sdhci_readl(host, O2_SD_DLL_CTRL);
   354			reg_val &= ~BIT(28);
   355			sdhci_writel(host, reg_val, O2_SD_DLL_CTRL);
   356	
   357			/* Update tuning command times for normal card */
   358			pci_read_config_dword(chip->pdev, O2_SD_TUNING_CTRL, &reg_val);
   359			reg_val &= 0x00FFFFFF;
   360			reg_val |= (phase_num * 3) << 24;
   361			pci_write_config_dword(chip->pdev, O2_SD_TUNING_CTRL, reg_val);
   362		}
   363	}
   364	
   365	static void sdhci_o2_configure_banq_best_input_phase(struct sdhci_host *host)
   366	{
   367		struct sdhci_pci_slot *slot = sdhci_priv(host);
   368		struct sdhci_pci_chip *chip = slot->chip;
   369	
 > 370		u32 response = 0;
   371		u16 dll_phase_configure = 0;
   372		u16 best_input_phase = 0;
   373	
   374		switch (chip->pdev->device) {
   375		case PCI_DEVICE_ID_O2_FUJIN2:
   376			best_input_phase = 0x0;
   377			break;
   378	
   379		case PCI_DEVICE_ID_O2_SEABIRD0:
   380		case PCI_DEVICE_ID_O2_SEABIRD1:
   381			best_input_phase = 0x0;
   382			break;
   383	
   384		case PCI_DEVICE_ID_O2_GG8_9860:
   385		case PCI_DEVICE_ID_O2_GG8_9861:
   386		case PCI_DEVICE_ID_O2_GG8_9862:
   387		case PCI_DEVICE_ID_O2_GG8_9863:
   388			best_input_phase = 0xB;
   389			break;
   390	
   391		default:
   392			break;
   393		}
   394	
   395		/* configure the best input phase (0xB) for BanQ card */
   396		dll_phase_configure = sdhci_readw(host, 0x1B2);
   397		dll_phase_configure = (dll_phase_configure & (u16)0xF0FF) |
   398			(best_input_phase << 8) | BIT(12);
   399		sdhci_writew(host, dll_phase_configure, 0x1B2);
   400	}
   401	
   402	static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode)
   403	{
   404		struct sdhci_host *host = mmc_priv(mmc);
   405		struct sdhci_pci_slot *slot = sdhci_priv(host);
   406		struct sdhci_pci_chip *chip = slot->chip;
 > 407		struct mmc_card *card = mmc->card;
   408		struct o2_host *o2_host = sdhci_pci_priv(slot);
   409		int current_bus_width = 0;
   410		u32 scratch32 = 0;
   411		u16 data_timeout_counter_value = 0;
   412		u16 scratch = 0;
   413		u8 phase_num = 0;
   414		u8  scratch_8 = 0;
   415		u32 reg_val;
   416	
   417		/*
   418		 * This handler implements the hardware tuning that is specific to
   419		 * this controller.  Fall back to the standard method for other TIMING.
   420		 */
   421		if ((host->timing != MMC_TIMING_MMC_HS200) &&
   422			(host->timing != MMC_TIMING_UHS_SDR104) &&
   423			(host->timing != MMC_TIMING_UHS_SDR50))
   424			return sdhci_execute_tuning(mmc, opcode);
   425	
   426		if (WARN_ON(!mmc_op_tuning(opcode)))
   427			return -EINVAL;
   428	
   429		if ((chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9860) ||
   430			(chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9861) ||
   431			(chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9862) ||
   432			(chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9863)) {
   433			phase_num = 14;
   434		} else {
   435			phase_num = 11;
   436		}
   437	
   438		/* UnLock WP */
   439		pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8);
   440		scratch_8 &= 0x7f;
   441		pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8);
   442	
   443		sdhci_o2_tuning_setting(mmc, (bool)o2_host->banq_card_setting, phase_num);
   444	
   445		if (o2_host->banq_card_setting) {
   446			/*
   447			 * set data timeout counter value to 0 to ensure that
   448			 * the tuning process can be completed
   449			 */
   450			data_timeout_counter_value = sdhci_readw(host, SDHCI_TIMEOUT_CONTROL);
   451			sdhci_writew(host, data_timeout_counter_value & (u16)0xFFF0, SDHCI_TIMEOUT_CONTROL);
   452		}
   453	
   454		/* Force power mode enter L0 */
   455		scratch = sdhci_readw(host, O2_SD_MISC_CTRL);
   456		scratch |= O2_SD_PWR_FORCE_L0;
   457		sdhci_writew(host, scratch, O2_SD_MISC_CTRL);
   458	
   459		/* Update output phase */
   460		switch (chip->pdev->device) {
   461		case PCI_DEVICE_ID_O2_SDS0:
   462		case PCI_DEVICE_ID_O2_SEABIRD0:
   463		case PCI_DEVICE_ID_O2_SEABIRD1:
   464		case PCI_DEVICE_ID_O2_SDS1:
   465		case PCI_DEVICE_ID_O2_FUJIN2:
   466			/* Stop clk */
   467			reg_val = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
   468			reg_val &= ~SDHCI_CLOCK_CARD_EN;
   469			sdhci_writew(host, reg_val, SDHCI_CLOCK_CONTROL);
   470	
   471			if ((host->timing == MMC_TIMING_MMC_HS200) ||
   472				(host->timing == MMC_TIMING_UHS_SDR104)) {
   473				/* Set pcr 0x354[16] to choose dll clock, and set the default phase */
   474				pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, &reg_val);
   475				reg_val &= ~(O2_SD_SEL_DLL | O2_SD_PHASE_MASK);
   476				reg_val |= (O2_SD_SEL_DLL | O2_SD_FIX_PHASE);
   477				pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, reg_val);
   478			}
   479	
   480			/* Start clk */
   481			reg_val = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
   482			reg_val |= SDHCI_CLOCK_CARD_EN;
   483			sdhci_writew(host, reg_val, SDHCI_CLOCK_CONTROL);
   484			break;
   485		case PCI_DEVICE_ID_O2_GG8_9860:
   486		case PCI_DEVICE_ID_O2_GG8_9861:
   487		case PCI_DEVICE_ID_O2_GG8_9862:
   488		case PCI_DEVICE_ID_O2_GG8_9863:
   489		default:
   490			break;
   491		}
   492	
   493		/* Lock WP */
   494		pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8);
   495		scratch_8 |= 0x80;
   496		pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8);
   497	
   498		/* wait DLL lock, timeout value 5ms */
   499		if (readx_poll_timeout(sdhci_o2_pll_dll_wdt_control, host,
   500			scratch32, (scratch32 & O2_DLL_LOCK_STATUS), 1, 5000))
   501			pr_warn("%s: DLL can't lock in 5ms after force L0 during tuning.\n",
   502					mmc_hostname(host->mmc));
   503		/*
   504		 * Judge the tuning reason, whether caused by dll shift
   505		 * If cause by dll shift, should call sdhci_o2_dll_recovery
   506		 */
   507		if (!sdhci_o2_wait_dll_detect_lock(host))
   508			if (!sdhci_o2_dll_recovery(host)) {
   509				pr_err("%s: o2 dll recovery failed\n",
   510					mmc_hostname(host->mmc));
   511				return -EINVAL;
   512			}
   513		/*
   514		 * o2 sdhci host didn't support 8bit emmc tuning
   515		 */
   516		if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) {
   517			current_bus_width = mmc->ios.bus_width;
   518			mmc->ios.bus_width = MMC_BUS_WIDTH_4;
   519			sdhci_set_bus_width(host, MMC_BUS_WIDTH_4);
   520		}
   521	
   522		sdhci_o2_set_tuning_mode(host);
   523	
   524		sdhci_start_tuning(host);
   525	
   526		__sdhci_o2_execute_tuning(host, opcode);
   527	
   528		sdhci_end_tuning(host);
   529	
   530		if (current_bus_width == MMC_BUS_WIDTH_8) {
   531			mmc->ios.bus_width = MMC_BUS_WIDTH_8;
   532			sdhci_set_bus_width(host, current_bus_width);
   533		}
   534	
   535		/* update input phase for BanQ card */
   536		if (o2_host->banq_card_setting) {
   537			/* recover the data timeout counter value */
   538			sdhci_writew(host, data_timeout_counter_value, SDHCI_TIMEOUT_CONTROL);
   539	
   540			/*
   541			 * Stop transfer for CMD19 after tuning done is set to
   542			 * avoid data line inhibit
   543			 */
   544			sdhci_o2_send_stop_transmission(host);
   545	
   546			sdhci_o2_configure_banq_best_input_phase(host);
   547		}
   548	
   549		/* Cancel force power mode enter L0 */
   550		scratch = sdhci_readw(host, O2_SD_MISC_CTRL);
   551		scratch &= ~(O2_SD_PWR_FORCE_L0);
   552		sdhci_writew(host, scratch, O2_SD_MISC_CTRL);
   553	
   554		sdhci_reset(host, SDHCI_RESET_CMD);
   555		sdhci_reset(host, SDHCI_RESET_DATA);
   556	
   557		host->flags &= ~SDHCI_HS400_TUNING;
   558		return 0;
   559	}
   560
diff mbox series

Patch

diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c
index 7bfee28116af..ab898c583323 100644
--- a/drivers/mmc/host/sdhci-pci-o2micro.c
+++ b/drivers/mmc/host/sdhci-pci-o2micro.c
@@ -36,6 +36,7 @@ 
 #define O2_SD_MISC_CTRL2	0xF0
 #define O2_SD_INF_MOD		0xF1
 #define O2_SD_MISC_CTRL4	0xFC
+#define O2_SD_DLL_CTRL		0x1B0
 #define O2_SD_MISC_CTRL		0x1C0
 #define O2_SD_EXP_INT_REG	0x1E0
 #define O2_SD_PWR_FORCE_L0	0x0002
@@ -78,7 +79,8 @@  static const u32 dmdn_table[] = {0x2B1C0000,
 #define DMDN_SZ ARRAY_SIZE(dmdn_table)
 
 struct o2_host {
-	u8 dll_adjust_count;
+	u8 dll_adjust_count: 4;
+	u8 banq_card_setting: 4;
 };
 
 static void sdhci_o2_wait_card_detect_stable(struct sdhci_host *host)
@@ -311,14 +313,104 @@  static int sdhci_o2_dll_recovery(struct sdhci_host *host)
 	return ret;
 }
 
+static void sdhci_o2_send_stop_transmission(struct sdhci_host *host)
+{
+	struct mmc_host *mmc = host->mmc;
+	struct mmc_command cmd = {};
+	struct mmc_request mrq = {};
+
+	cmd.opcode = MMC_STOP_TRANSMISSION;
+	cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+	cmd.busy_timeout = 150;
+
+	mrq.cmd = &cmd;
+
+	mmc_wait_for_req(mmc, &mrq);
+
+	/*
+	 * Command CRC error may occur due to compatibility issue.
+	 * It is normal and ignore it here.
+	 */
+	if ((cmd.error != 0) && (cmd.error != -EILSEQ))
+		pr_err("%s: CMD12 error: %d\n", mmc_hostname(mmc), cmd.error);
+}
+
+static void sdhci_o2_tuning_setting(struct mmc_host *mmc, bool isbanq, u8 phase_num)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+	struct sdhci_pci_slot *slot = sdhci_priv(host);
+	struct sdhci_pci_chip *chip = slot->chip;
+	struct o2_host *o2_host = sdhci_pci_priv(slot);
+	u32 reg_val;
+
+	if (isbanq) {
+		/* update tuning command times for BanQ card */
+		pci_read_config_dword(chip->pdev, O2_SD_TUNING_CTRL, &reg_val);
+		reg_val &= 0x00FFFFFF;
+		reg_val |= 0x02000000;
+		pci_write_config_dword(chip->pdev, O2_SD_TUNING_CTRL, reg_val);
+	} else {
+		reg_val = sdhci_readl(host, O2_SD_DLL_CTRL);
+		reg_val &= ~BIT(28);
+		sdhci_writel(host, reg_val, O2_SD_DLL_CTRL);
+
+		/* Update tuning command times for normal card */
+		pci_read_config_dword(chip->pdev, O2_SD_TUNING_CTRL, &reg_val);
+		reg_val &= 0x00FFFFFF;
+		reg_val |= (phase_num * 3) << 24;
+		pci_write_config_dword(chip->pdev, O2_SD_TUNING_CTRL, reg_val);
+	}
+}
+
+static void sdhci_o2_configure_banq_best_input_phase(struct sdhci_host *host)
+{
+	struct sdhci_pci_slot *slot = sdhci_priv(host);
+	struct sdhci_pci_chip *chip = slot->chip;
+
+	u32 response = 0;
+	u16 dll_phase_configure = 0;
+	u16 best_input_phase = 0;
+
+	switch (chip->pdev->device) {
+	case PCI_DEVICE_ID_O2_FUJIN2:
+		best_input_phase = 0x0;
+		break;
+
+	case PCI_DEVICE_ID_O2_SEABIRD0:
+	case PCI_DEVICE_ID_O2_SEABIRD1:
+		best_input_phase = 0x0;
+		break;
+
+	case PCI_DEVICE_ID_O2_GG8_9860:
+	case PCI_DEVICE_ID_O2_GG8_9861:
+	case PCI_DEVICE_ID_O2_GG8_9862:
+	case PCI_DEVICE_ID_O2_GG8_9863:
+		best_input_phase = 0xB;
+		break;
+
+	default:
+		break;
+	}
+
+	/* configure the best input phase (0xB) for BanQ card */
+	dll_phase_configure = sdhci_readw(host, 0x1B2);
+	dll_phase_configure = (dll_phase_configure & (u16)0xF0FF) |
+		(best_input_phase << 8) | BIT(12);
+	sdhci_writew(host, dll_phase_configure, 0x1B2);
+}
+
 static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode)
 {
 	struct sdhci_host *host = mmc_priv(mmc);
 	struct sdhci_pci_slot *slot = sdhci_priv(host);
 	struct sdhci_pci_chip *chip = slot->chip;
+	struct mmc_card *card = mmc->card;
+	struct o2_host *o2_host = sdhci_pci_priv(slot);
 	int current_bus_width = 0;
 	u32 scratch32 = 0;
+	u16 data_timeout_counter_value = 0;
 	u16 scratch = 0;
+	u8 phase_num = 0;
 	u8  scratch_8 = 0;
 	u32 reg_val;
 
@@ -334,6 +426,31 @@  static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode)
 	if (WARN_ON(!mmc_op_tuning(opcode)))
 		return -EINVAL;
 
+	if ((chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9860) ||
+		(chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9861) ||
+		(chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9862) ||
+		(chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9863)) {
+		phase_num = 14;
+	} else {
+		phase_num = 11;
+	}
+
+	/* UnLock WP */
+	pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8);
+	scratch_8 &= 0x7f;
+	pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8);
+
+	sdhci_o2_tuning_setting(mmc, (bool)o2_host->banq_card_setting, phase_num);
+
+	if (o2_host->banq_card_setting) {
+		/*
+		 * set data timeout counter value to 0 to ensure that
+		 * the tuning process can be completed
+		 */
+		data_timeout_counter_value = sdhci_readw(host, SDHCI_TIMEOUT_CONTROL);
+		sdhci_writew(host, data_timeout_counter_value & (u16)0xFFF0, SDHCI_TIMEOUT_CONTROL);
+	}
+
 	/* Force power mode enter L0 */
 	scratch = sdhci_readw(host, O2_SD_MISC_CTRL);
 	scratch |= O2_SD_PWR_FORCE_L0;
@@ -351,23 +468,13 @@  static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode)
 		reg_val &= ~SDHCI_CLOCK_CARD_EN;
 		sdhci_writew(host, reg_val, SDHCI_CLOCK_CONTROL);
 
-		if (host->timing == MMC_TIMING_MMC_HS200 ||
-		    host->timing == MMC_TIMING_UHS_SDR104) {
-			/* UnLock WP */
-			pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8);
-			scratch_8 &= 0x7f;
-			pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8);
-
+		if ((host->timing == MMC_TIMING_MMC_HS200) ||
+			(host->timing == MMC_TIMING_UHS_SDR104)) {
 			/* Set pcr 0x354[16] to choose dll clock, and set the default phase */
 			pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, &reg_val);
 			reg_val &= ~(O2_SD_SEL_DLL | O2_SD_PHASE_MASK);
 			reg_val |= (O2_SD_SEL_DLL | O2_SD_FIX_PHASE);
 			pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, reg_val);
-
-			/* Lock WP */
-			pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8);
-			scratch_8 |= 0x80;
-			pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8);
 		}
 
 		/* Start clk */
@@ -375,10 +482,19 @@  static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode)
 		reg_val |= SDHCI_CLOCK_CARD_EN;
 		sdhci_writew(host, reg_val, SDHCI_CLOCK_CONTROL);
 		break;
+	case PCI_DEVICE_ID_O2_GG8_9860:
+	case PCI_DEVICE_ID_O2_GG8_9861:
+	case PCI_DEVICE_ID_O2_GG8_9862:
+	case PCI_DEVICE_ID_O2_GG8_9863:
 	default:
 		break;
 	}
 
+	/* Lock WP */
+	pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8);
+	scratch_8 |= 0x80;
+	pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8);
+
 	/* 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))
@@ -416,6 +532,20 @@  static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode)
 		sdhci_set_bus_width(host, current_bus_width);
 	}
 
+	/* update input phase for BanQ card */
+	if (o2_host->banq_card_setting) {
+		/* recover the data timeout counter value */
+		sdhci_writew(host, data_timeout_counter_value, SDHCI_TIMEOUT_CONTROL);
+
+		/*
+		 * Stop transfer for CMD19 after tuning done is set to
+		 * avoid data line inhibit
+		 */
+		sdhci_o2_send_stop_transmission(host);
+
+		sdhci_o2_configure_banq_best_input_phase(host);
+	}
+
 	/* Cancel force power mode enter L0 */
 	scratch = sdhci_readw(host, O2_SD_MISC_CTRL);
 	scratch &= ~(O2_SD_PWR_FORCE_L0);
@@ -428,6 +558,24 @@  static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode)
 	return 0;
 }
 
+static void sdhci_o2_init_card(struct mmc_host *mmc, struct mmc_card *card)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+	struct sdhci_pci_slot *slot = sdhci_priv(host);
+	struct o2_host *o2_host = sdhci_pci_priv(slot);
+	unsigned int manfid;
+	unsigned short oemid;
+
+	manfid = card->raw_cid[0] >> 24;
+	oemid = (card->raw_cid[0] >> 8) & 0xFFFF;
+
+	/* judge whether the card is BanQ card */
+	if (manfid == 0x89 && oemid == 0x303)
+		o2_host->banq_card_setting = 1;
+	else
+		o2_host->banq_card_setting = 0;
+}
+
 static void o2_pci_led_enable(struct sdhci_pci_chip *chip)
 {
 	int ret;
@@ -596,15 +744,20 @@  static void sdhci_pci_o2_set_clock(struct sdhci_host *host, unsigned int clock)
 	scratch &= 0x7f;
 	pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
 
-	if (chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9860 ||
-	    chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9861 ||
-	    chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9862 ||
-	    chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9863) {
+	if ((chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9860) ||
+		(chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9861) ||
+		(chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9862) ||
+		(chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9863)) {
 		dmdn_208m = 0x2c500000;
 		dmdn_200m = 0x25200000;
 	} else {
 		dmdn_208m = 0x2c280000;
 		dmdn_200m = 0x25100000;
+
+		/* open-clock for old project */
+		pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, &scratch_32);
+		scratch_32 &= ~(O2_SD_SEL_DLL | O2_SD_PHASE_MASK);
+		pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, scratch_32);
 	}
 
 	if ((host->timing == MMC_TIMING_UHS_SDR104) && (clock == 200000000)) {
@@ -619,10 +772,6 @@  static void sdhci_pci_o2_set_clock(struct sdhci_host *host, unsigned int clock)
 			o2_pci_set_baseclk(chip, dmdn_200m);
 	}
 
-	pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, &scratch_32);
-	scratch_32 &= ~(O2_SD_SEL_DLL | O2_SD_PHASE_MASK);
-	pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, scratch_32);
-
 	/* Lock WP */
 	pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch);
 	scratch |= 0x80;
@@ -632,6 +781,11 @@  static void sdhci_pci_o2_set_clock(struct sdhci_host *host, unsigned int clock)
 	sdhci_o2_enable_clk(host, clk);
 }
 
+static void sdhci_o2_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
+{
+	sdhci_writeb(host, 0x0E, SDHCI_TIMEOUT_CONTROL);
+}
+
 static int sdhci_pci_o2_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct sdhci_host *host = mmc_priv(mmc);
@@ -705,6 +859,7 @@  static int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
 	host = slot->host;
 
 	o2_host->dll_adjust_count = 0;
+	o2_host->banq_card_setting = 0;
 	caps = sdhci_readl(host, SDHCI_CAPABILITIES);
 
 	/*
@@ -718,7 +873,9 @@  static int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
 
 	sdhci_pci_o2_enable_msi(chip, host);
 
+	host->mmc_host_ops.init_card = sdhci_o2_init_card;
 	host->mmc_host_ops.execute_tuning = sdhci_o2_execute_tuning;
+
 	switch (chip->pdev->device) {
 	case PCI_DEVICE_ID_O2_SDS0:
 	case PCI_DEVICE_ID_O2_SEABIRD0:
@@ -770,6 +927,8 @@  static int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
 		host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
 		slot->host->mmc_host_ops.get_cd = sdhci_o2_get_cd;
 		host->mmc_host_ops.init_sd_express = sdhci_pci_o2_init_sd_express;
+
+		sdhci_writel(host, 0xFFFFFFFF, SDHCI_INT_STATUS);
 		break;
 	default:
 		break;
@@ -1022,7 +1181,7 @@  static int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
 		/* Set output delay*/
 		pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, &scratch_32);
 		scratch_32 &= 0xFF0FFF00;
-		scratch_32 |= 0x00B0003B;
+		scratch_32 |= 0x00B000CB;
 		pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, scratch_32);
 
 		/* Lock WP */
@@ -1051,6 +1210,7 @@  static const struct sdhci_ops sdhci_pci_o2_ops = {
 	.set_bus_width = sdhci_set_bus_width,
 	.reset = sdhci_reset,
 	.set_uhs_signaling = sdhci_set_uhs_signaling,
+	.set_timeout = sdhci_o2_set_timeout,
 };
 
 const struct sdhci_pci_fixes sdhci_o2 = {