Skip to content

Commit

Permalink
mfd: mmc: rtsx: Change default tx phase
Browse files Browse the repository at this point in the history
The default phase can meet most cards' requirement, but it is not the
optimal one. In some extreme situation, the rx phase point produced by
the following tuning process will drift quite a distance.
Before tuning UHS card, this patch will set a more proper initial tx
phase point, which is calculated from statistic data, and can achieve
a much better tx signal quality.

Signed-off-by: Wei WANG <wei_wang@realsil.com.cn>
Acked-by: Lee Jones <lee.jones@linaro.org>
Acked-by: Chris Ball <cjb@laptop.org>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
  • Loading branch information
Wei WANG authored and Samuel Ortiz committed Aug 30, 2013
1 parent 828fa1e commit 84d72f9
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 16 deletions.
4 changes: 4 additions & 0 deletions drivers/mfd/rtl8411.c
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,8 @@ void rtl8411_init_params(struct rtsx_pcr *pcr)
pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
pcr->aspm_en = ASPM_L1_EN;
pcr->tx_initial_phase = SET_CLOCK_PHASE(23, 7, 14);
pcr->rx_initial_phase = SET_CLOCK_PHASE(4, 3, 10);

pcr->ic_version = rtl8411_get_ic_version(pcr);
pcr->sd_pull_ctl_enable_tbl = rtl8411_sd_pull_ctl_enable_tbl;
Expand All @@ -471,6 +473,8 @@ void rtl8411b_init_params(struct rtsx_pcr *pcr)
pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
pcr->aspm_en = ASPM_L1_EN;
pcr->tx_initial_phase = SET_CLOCK_PHASE(23, 7, 14);
pcr->rx_initial_phase = SET_CLOCK_PHASE(4, 3, 10);

pcr->ic_version = rtl8411_get_ic_version(pcr);

Expand Down
2 changes: 2 additions & 0 deletions drivers/mfd/rts5209.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,8 @@ void rts5209_init_params(struct rtsx_pcr *pcr)
pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
pcr->aspm_en = ASPM_L1_EN;
pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 16);
pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5);

pcr->ic_version = rts5209_get_ic_version(pcr);
pcr->sd_pull_ctl_enable_tbl = rts5209_sd_pull_ctl_enable_tbl;
Expand Down
2 changes: 2 additions & 0 deletions drivers/mfd/rts5227.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,8 @@ void rts5227_init_params(struct rtsx_pcr *pcr)
pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_B;
pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B;
pcr->aspm_en = ASPM_L1_EN;
pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 15);
pcr->rx_initial_phase = SET_CLOCK_PHASE(30, 7, 7);

pcr->sd_pull_ctl_enable_tbl = rts5227_sd_pull_ctl_enable_tbl;
pcr->sd_pull_ctl_disable_tbl = rts5227_sd_pull_ctl_disable_tbl;
Expand Down
2 changes: 2 additions & 0 deletions drivers/mfd/rts5229.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@ void rts5229_init_params(struct rtsx_pcr *pcr)
pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
pcr->aspm_en = ASPM_L1_EN;
pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 15);
pcr->rx_initial_phase = SET_CLOCK_PHASE(30, 6, 6);

pcr->ic_version = rts5229_get_ic_version(pcr);
if (pcr->ic_version == IC_VER_C) {
Expand Down
2 changes: 2 additions & 0 deletions drivers/mfd/rts5249.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,8 @@ void rts5249_init_params(struct rtsx_pcr *pcr)
pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_C;
pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B;
pcr->aspm_en = ASPM_L1_EN;
pcr->tx_initial_phase = SET_CLOCK_PHASE(1, 29, 16);
pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5);

pcr->ic_version = rts5249_get_ic_version(pcr);
pcr->sd_pull_ctl_enable_tbl = rts5249_sd_pull_ctl_enable_tbl;
Expand Down
58 changes: 42 additions & 16 deletions drivers/mmc/host/rtsx_pci_sdmmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ struct realtek_pci_sdmmc {
bool double_clk;
bool eject;
bool initial_mode;
bool ddr_mode;
int power_state;
#define SDMMC_POWER_ON 1
#define SDMMC_POWER_OFF 0
Expand Down Expand Up @@ -475,18 +474,24 @@ static void sd_normal_rw(struct realtek_pci_sdmmc *host,
kfree(buf);
}

static int sd_change_phase(struct realtek_pci_sdmmc *host, u8 sample_point)
static int sd_change_phase(struct realtek_pci_sdmmc *host,
u8 sample_point, bool rx)
{
struct rtsx_pcr *pcr = host->pcr;
int err;

dev_dbg(sdmmc_dev(host), "%s: sample_point = %d\n",
__func__, sample_point);
dev_dbg(sdmmc_dev(host), "%s(%s): sample_point = %d\n",
__func__, rx ? "RX" : "TX", sample_point);

rtsx_pci_init_cmd(pcr);

rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CHANGE_CLK, CHANGE_CLK);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPRX_CTL, 0x1F, sample_point);
if (rx)
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
SD_VPRX_CTL, 0x1F, sample_point);
else
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
SD_VPTX_CTL, 0x1F, sample_point);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL,
PHASE_NOT_RESET, PHASE_NOT_RESET);
Expand Down Expand Up @@ -602,7 +607,7 @@ static int sd_tuning_rx_cmd(struct realtek_pci_sdmmc *host,
int err;
u8 cmd[5] = {0};

err = sd_change_phase(host, sample_point);
err = sd_change_phase(host, sample_point, true);
if (err < 0)
return err;

Expand Down Expand Up @@ -664,7 +669,7 @@ static int sd_tuning_rx(struct realtek_pci_sdmmc *host, u8 opcode)
if (final_phase == 0xFF)
return -EINVAL;

err = sd_change_phase(host, final_phase);
err = sd_change_phase(host, final_phase, true);
if (err < 0)
return err;
} else {
Expand Down Expand Up @@ -833,14 +838,11 @@ static int sd_set_power_mode(struct realtek_pci_sdmmc *host,
return err;
}

static int sd_set_timing(struct realtek_pci_sdmmc *host,
unsigned char timing, bool *ddr_mode)
static int sd_set_timing(struct realtek_pci_sdmmc *host, unsigned char timing)
{
struct rtsx_pcr *pcr = host->pcr;
int err = 0;

*ddr_mode = false;

rtsx_pci_init_cmd(pcr);

switch (timing) {
Expand All @@ -857,8 +859,6 @@ static int sd_set_timing(struct realtek_pci_sdmmc *host,
break;

case MMC_TIMING_UHS_DDR50:
*ddr_mode = true;

rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1,
0x0C | SD_ASYNC_FIFO_NOT_RST,
SD_DDR_MODE | SD_ASYNC_FIFO_NOT_RST);
Expand Down Expand Up @@ -926,7 +926,7 @@ static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)

sd_set_bus_width(host, ios->bus_width);
sd_set_power_mode(host, ios->power_mode);
sd_set_timing(host, ios->timing, &host->ddr_mode);
sd_set_timing(host, ios->timing);

host->vpclk = false;
host->double_clk = true;
Expand Down Expand Up @@ -1148,9 +1148,35 @@ static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode)

rtsx_pci_start_run(pcr);

if (!host->ddr_mode)
err = sd_tuning_rx(host, MMC_SEND_TUNING_BLOCK);
/* Set initial TX phase */
switch (mmc->ios.timing) {
case MMC_TIMING_UHS_SDR104:
err = sd_change_phase(host, SDR104_TX_PHASE(pcr), false);
break;

case MMC_TIMING_UHS_SDR50:
err = sd_change_phase(host, SDR50_TX_PHASE(pcr), false);
break;

case MMC_TIMING_UHS_DDR50:
err = sd_change_phase(host, DDR50_TX_PHASE(pcr), false);
break;

default:
err = 0;
}

if (err)
goto out;

/* Tuning RX phase */
if ((mmc->ios.timing == MMC_TIMING_UHS_SDR104) ||
(mmc->ios.timing == MMC_TIMING_UHS_SDR50))
err = sd_tuning_rx(host, opcode);
else if (mmc->ios.timing == MMC_TIMING_UHS_DDR50)
err = sd_change_phase(host, DDR50_RX_PHASE(pcr), true);

out:
mutex_unlock(&pcr->pcr_mutex);

return err;
Expand Down
15 changes: 15 additions & 0 deletions include/linux/mfd/rtsx_pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,9 @@ struct rtsx_pcr {
#define PCR_REVERSE_SOCKET (1 << 1)
u32 flags;

u32 tx_initial_phase;
u32 rx_initial_phase;

const u32 *sd_pull_ctl_enable_tbl;
const u32 *sd_pull_ctl_disable_tbl;
const u32 *ms_pull_ctl_enable_tbl;
Expand All @@ -863,6 +866,18 @@ struct rtsx_pcr {
#define PCI_VID(pcr) ((pcr)->pci->vendor)
#define PCI_PID(pcr) ((pcr)->pci->device)

#define SDR104_PHASE(val) ((val) & 0xFF)
#define SDR50_PHASE(val) (((val) >> 8) & 0xFF)
#define DDR50_PHASE(val) (((val) >> 16) & 0xFF)
#define SDR104_TX_PHASE(pcr) SDR104_PHASE((pcr)->tx_initial_phase)
#define SDR50_TX_PHASE(pcr) SDR50_PHASE((pcr)->tx_initial_phase)
#define DDR50_TX_PHASE(pcr) DDR50_PHASE((pcr)->tx_initial_phase)
#define SDR104_RX_PHASE(pcr) SDR104_PHASE((pcr)->rx_initial_phase)
#define SDR50_RX_PHASE(pcr) SDR50_PHASE((pcr)->rx_initial_phase)
#define DDR50_RX_PHASE(pcr) DDR50_PHASE((pcr)->rx_initial_phase)
#define SET_CLOCK_PHASE(sdr104, sdr50, ddr50) \
(((ddr50) << 16) | ((sdr50) << 8) | (sdr104))

void rtsx_pci_start_run(struct rtsx_pcr *pcr);
int rtsx_pci_write_register(struct rtsx_pcr *pcr, u16 addr, u8 mask, u8 data);
int rtsx_pci_read_register(struct rtsx_pcr *pcr, u16 addr, u8 *data);
Expand Down

0 comments on commit 84d72f9

Please sign in to comment.