diff options
Diffstat (limited to 'drivers/mmc/host/rtsx_pci_sdmmc.c')
| -rw-r--r-- | drivers/mmc/host/rtsx_pci_sdmmc.c | 155 | 
1 files changed, 40 insertions, 115 deletions
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index 375a880e0c5..0d519649b57 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c @@ -31,16 +31,6 @@  #include <linux/mfd/rtsx_pci.h>  #include <asm/unaligned.h> -/* SD Tuning Data Structure - * Record continuous timing phase path - */ -struct timing_phase_path { -	int start; -	int end; -	int mid; -	int len; -}; -  struct realtek_pci_sdmmc {  	struct platform_device	*pdev;  	struct rtsx_pcr		*pcr; @@ -246,6 +236,9 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host,  	case MMC_RSP_R1:  		rsp_type = SD_RSP_TYPE_R1;  		break; +	case MMC_RSP_R1 & ~MMC_RSP_CRC: +		rsp_type = SD_RSP_TYPE_R1 | SD_NO_CHECK_CRC7; +		break;  	case MMC_RSP_R1B:  		rsp_type = SD_RSP_TYPE_R1b;  		break; @@ -364,7 +357,7 @@ static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq)  	struct mmc_host *mmc = host->mmc;  	struct mmc_card *card = mmc->card;  	struct mmc_data *data = mrq->data; -	int uhs = mmc_sd_card_uhs(card); +	int uhs = mmc_card_uhs(card);  	int read = (data->flags & MMC_DATA_READ) ? 1 : 0;  	u8 cfg2, trans_mode;  	int err; @@ -511,85 +504,47 @@ static int sd_change_phase(struct realtek_pci_sdmmc *host,  	return 0;  } -static u8 sd_search_final_phase(struct realtek_pci_sdmmc *host, u32 phase_map) +static inline u32 test_phase_bit(u32 phase_map, unsigned int bit)  { -	struct timing_phase_path path[MAX_PHASE + 1]; -	int i, j, cont_path_cnt; -	int new_block, max_len, final_path_idx; -	u8 final_phase = 0xFF; +	bit %= RTSX_PHASE_MAX; +	return phase_map & (1 << bit); +} -	/* Parse phase_map, take it as a bit-ring */ -	cont_path_cnt = 0; -	new_block = 1; -	j = 0; -	for (i = 0; i < MAX_PHASE + 1; i++) { -		if (phase_map & (1 << i)) { -			if (new_block) { -				new_block = 0; -				j = cont_path_cnt++; -				path[j].start = i; -				path[j].end = i; -			} else { -				path[j].end = i; -			} -		} else { -			new_block = 1; -			if (cont_path_cnt) { -				/* Calculate path length and middle point */ -				int idx = cont_path_cnt - 1; -				path[idx].len = -					path[idx].end - path[idx].start + 1; -				path[idx].mid = -					path[idx].start + path[idx].len / 2; -			} -		} -	} +static int sd_get_phase_len(u32 phase_map, unsigned int start_bit) +{ +	int i; -	if (cont_path_cnt == 0) { -		dev_dbg(sdmmc_dev(host), "No continuous phase path\n"); -		goto finish; -	} else { -		/* Calculate last continuous path length and middle point */ -		int idx = cont_path_cnt - 1; -		path[idx].len = path[idx].end - path[idx].start + 1; -		path[idx].mid = path[idx].start + path[idx].len / 2; +	for (i = 0; i < RTSX_PHASE_MAX; i++) { +		if (test_phase_bit(phase_map, start_bit + i) == 0) +			return i;  	} +	return RTSX_PHASE_MAX; +} -	/* Connect the first and last continuous paths if they are adjacent */ -	if (!path[0].start && (path[cont_path_cnt - 1].end == MAX_PHASE)) { -		/* Using negative index */ -		path[0].start = path[cont_path_cnt - 1].start - MAX_PHASE - 1; -		path[0].len += path[cont_path_cnt - 1].len; -		path[0].mid = path[0].start + path[0].len / 2; -		/* Convert negative middle point index to positive one */ -		if (path[0].mid < 0) -			path[0].mid += MAX_PHASE + 1; -		cont_path_cnt--; +static u8 sd_search_final_phase(struct realtek_pci_sdmmc *host, u32 phase_map) +{ +	int start = 0, len = 0; +	int start_final = 0, len_final = 0; +	u8 final_phase = 0xFF; + +	if (phase_map == 0) { +		dev_err(sdmmc_dev(host), "phase error: [map:%x]\n", phase_map); +		return final_phase;  	} -	/* Choose the longest continuous phase path */ -	max_len = 0; -	final_phase = 0; -	final_path_idx = 0; -	for (i = 0; i < cont_path_cnt; i++) { -		if (path[i].len > max_len) { -			max_len = path[i].len; -			final_phase = (u8)path[i].mid; -			final_path_idx = i; +	while (start < RTSX_PHASE_MAX) { +		len = sd_get_phase_len(phase_map, start); +		if (len_final < len) { +			start_final = start; +			len_final = len;  		} - -		dev_dbg(sdmmc_dev(host), "path[%d].start = %d\n", -				i, path[i].start); -		dev_dbg(sdmmc_dev(host), "path[%d].end = %d\n", -				i, path[i].end); -		dev_dbg(sdmmc_dev(host), "path[%d].len = %d\n", -				i, path[i].len); -		dev_dbg(sdmmc_dev(host), "path[%d].mid = %d\n", -				i, path[i].mid); +		start += len ? len : 1;  	} -finish: -	dev_dbg(sdmmc_dev(host), "Final chosen phase: %d\n", final_phase); +	final_phase = (start_final + len_final / 2) % RTSX_PHASE_MAX; +	dev_dbg(sdmmc_dev(host), "phase: [map:%x] [maxlen:%d] [final:%d]\n", +		phase_map, len_final, final_phase); +  	return final_phase;  } @@ -635,7 +590,7 @@ static int sd_tuning_phase(struct realtek_pci_sdmmc *host,  	int err, i;  	u32 raw_phase_map = 0; -	for (i = MAX_PHASE; i >= 0; i--) { +	for (i = 0; i < RTSX_PHASE_MAX; i++) {  		err = sd_tuning_rx_cmd(host, opcode, (u8)i);  		if (err == 0)  			raw_phase_map |= 1 << i; @@ -864,6 +819,7 @@ static int sd_set_timing(struct realtek_pci_sdmmc *host, unsigned char timing)  		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0);  		break; +	case MMC_TIMING_MMC_DDR52:  	case MMC_TIMING_UHS_DDR50:  		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1,  				0x0C | SD_ASYNC_FIFO_NOT_RST, @@ -944,6 +900,7 @@ static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)  		host->vpclk = true;  		host->double_clk = false;  		break; +	case MMC_TIMING_MMC_DDR52:  	case MMC_TIMING_UHS_DDR50:  	case MMC_TIMING_UHS_SDR25:  		host->ssc_depth = RTSX_SSC_DEPTH_1M; @@ -1197,37 +1154,6 @@ static const struct mmc_host_ops realtek_pci_sdmmc_ops = {  	.execute_tuning = sdmmc_execute_tuning,  }; -#ifdef CONFIG_PM -static int rtsx_pci_sdmmc_suspend(struct platform_device *pdev, -		pm_message_t state) -{ -	struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); -	struct mmc_host *mmc = host->mmc; -	int err; - -	dev_dbg(sdmmc_dev(host), "--> %s\n", __func__); - -	err = mmc_suspend_host(mmc); -	if (err) -		return err; - -	return 0; -} - -static int rtsx_pci_sdmmc_resume(struct platform_device *pdev) -{ -	struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); -	struct mmc_host *mmc = host->mmc; - -	dev_dbg(sdmmc_dev(host), "--> %s\n", __func__); - -	return mmc_resume_host(mmc); -} -#else /* CONFIG_PM */ -#define rtsx_pci_sdmmc_suspend NULL -#define rtsx_pci_sdmmc_resume NULL -#endif /* CONFIG_PM */ -  static void init_extra_caps(struct realtek_pci_sdmmc *host)  {  	struct mmc_host *mmc = host->mmc; @@ -1328,7 +1254,6 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)  	pcr->slots[RTSX_SD_CARD].p_dev = NULL;  	pcr->slots[RTSX_SD_CARD].card_event = NULL;  	mmc = host->mmc; -	host->eject = true;  	mutex_lock(&host->host_mutex);  	if (host->mrq) { @@ -1346,6 +1271,8 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)  	mutex_unlock(&host->host_mutex);  	mmc_remove_host(mmc); +	host->eject = true; +  	mmc_free_host(mmc);  	dev_dbg(&(pdev->dev), @@ -1367,8 +1294,6 @@ static struct platform_driver rtsx_pci_sdmmc_driver = {  	.probe		= rtsx_pci_sdmmc_drv_probe,  	.remove		= rtsx_pci_sdmmc_drv_remove,  	.id_table       = rtsx_pci_sdmmc_ids, -	.suspend	= rtsx_pci_sdmmc_suspend, -	.resume		= rtsx_pci_sdmmc_resume,  	.driver		= {  		.owner	= THIS_MODULE,  		.name	= DRV_NAME_RTSX_PCI_SDMMC,  | 
