Skip to content

Commit 1ede5cb

Browse files
yong maostorulf
authored andcommitted
mmc: mediatek: Use data tune for CMD line tune
If we don't select a set of better parameters for our emmc host, It may easily occur CMD response CRC error. And also it may cause cannot boot up issue. Fot getting a set of better parameters, our emmc host supports data tune mechanism.Therefore, our emmc driver also should change to use data tune for CMD line. Because our emmc host use the different clock source to sample the CMD signal between HS200 and HS400 mode, the parameters are also different between these two modes. Separate cmd internal delay for HS200/HS400 mode. This change can fix "System can not boot up" issue. Signed-off-by: Yong Mao <yong.mao@mediatek.com> Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
1 parent 50fde56 commit 1ede5cb

File tree

1 file changed

+152
-16
lines changed

1 file changed

+152
-16
lines changed

drivers/mmc/host/mtk-sd.c

Lines changed: 152 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
#define MSDC_PATCH_BIT1 0xb4
7777
#define MSDC_PAD_TUNE 0xec
7878
#define PAD_DS_TUNE 0x188
79+
#define PAD_CMD_TUNE 0x18c
7980
#define EMMC50_CFG0 0x208
8081

8182
/*--------------------------------------------------------------------------*/
@@ -211,13 +212,18 @@
211212
#define MSDC_PATCH_BIT_SPCPUSH (0x1 << 29) /* RW */
212213
#define MSDC_PATCH_BIT_DECRCTMO (0x1 << 30) /* RW */
213214

215+
#define MSDC_PAD_TUNE_DATWRDLY (0x1f << 0) /* RW */
214216
#define MSDC_PAD_TUNE_DATRRDLY (0x1f << 8) /* RW */
215217
#define MSDC_PAD_TUNE_CMDRDLY (0x1f << 16) /* RW */
218+
#define MSDC_PAD_TUNE_CMDRRDLY (0x1f << 22) /* RW */
219+
#define MSDC_PAD_TUNE_CLKTDLY (0x1f << 27) /* RW */
216220

217221
#define PAD_DS_TUNE_DLY1 (0x1f << 2) /* RW */
218222
#define PAD_DS_TUNE_DLY2 (0x1f << 7) /* RW */
219223
#define PAD_DS_TUNE_DLY3 (0x1f << 12) /* RW */
220224

225+
#define PAD_CMD_TUNE_RX_DLY3 (0x1f << 1) /* RW */
226+
221227
#define EMMC50_CFG_PADCMD_LATCHCK (0x1 << 0) /* RW */
222228
#define EMMC50_CFG_CRCSTS_EDGE (0x1 << 3) /* RW */
223229
#define EMMC50_CFG_CFCSTS_SEL (0x1 << 4) /* RW */
@@ -285,12 +291,14 @@ struct msdc_save_para {
285291
u32 patch_bit0;
286292
u32 patch_bit1;
287293
u32 pad_ds_tune;
294+
u32 pad_cmd_tune;
288295
u32 emmc50_cfg0;
289296
};
290297

291298
struct msdc_tune_para {
292299
u32 iocon;
293300
u32 pad_tune;
301+
u32 pad_cmd_tune;
294302
};
295303

296304
struct msdc_delay_phase {
@@ -332,6 +340,10 @@ struct msdc_host {
332340
unsigned char timing;
333341
bool vqmmc_enabled;
334342
u32 hs400_ds_delay;
343+
u32 hs200_cmd_int_delay; /* cmd internal delay for HS200/SDR104 */
344+
u32 hs400_cmd_int_delay; /* cmd internal delay for HS400 */
345+
bool hs400_cmd_resp_sel_rising;
346+
/* cmd response sample selection for HS400 */
335347
bool hs400_mode; /* current eMMC will run at hs400 mode */
336348
struct msdc_save_para save_para; /* used when gate HCLK */
337349
struct msdc_tune_para def_tune_para; /* default tune setting */
@@ -601,8 +613,14 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
601613
} else {
602614
writel(host->saved_tune_para.iocon, host->base + MSDC_IOCON);
603615
writel(host->saved_tune_para.pad_tune, host->base + MSDC_PAD_TUNE);
616+
writel(host->saved_tune_para.pad_cmd_tune,
617+
host->base + PAD_CMD_TUNE);
604618
}
605619

620+
if (timing == MMC_TIMING_MMC_HS400)
621+
sdr_set_field(host->base + PAD_CMD_TUNE,
622+
MSDC_PAD_TUNE_CMDRRDLY,
623+
host->hs400_cmd_int_delay);
606624
dev_dbg(host->dev, "sclk: %d, timing: %d\n", host->sclk, timing);
607625
}
608626

@@ -1303,7 +1321,7 @@ static struct msdc_delay_phase get_best_delay(struct msdc_host *host, u32 delay)
13031321
len_final = len;
13041322
}
13051323
start += len ? len : 1;
1306-
if (len >= 8 && start_final < 4)
1324+
if (len >= 12 && start_final < 4)
13071325
break;
13081326
}
13091327

@@ -1326,36 +1344,67 @@ static int msdc_tune_response(struct mmc_host *mmc, u32 opcode)
13261344
struct msdc_host *host = mmc_priv(mmc);
13271345
u32 rise_delay = 0, fall_delay = 0;
13281346
struct msdc_delay_phase final_rise_delay, final_fall_delay = { 0,};
1347+
struct msdc_delay_phase internal_delay_phase;
13291348
u8 final_delay, final_maxlen;
1349+
u32 internal_delay = 0;
13301350
int cmd_err;
1331-
int i;
1351+
int i, j;
1352+
1353+
if (mmc->ios.timing == MMC_TIMING_MMC_HS200 ||
1354+
mmc->ios.timing == MMC_TIMING_UHS_SDR104)
1355+
sdr_set_field(host->base + MSDC_PAD_TUNE,
1356+
MSDC_PAD_TUNE_CMDRRDLY,
1357+
host->hs200_cmd_int_delay);
13321358

13331359
sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
13341360
for (i = 0 ; i < PAD_DELAY_MAX; i++) {
13351361
sdr_set_field(host->base + MSDC_PAD_TUNE,
13361362
MSDC_PAD_TUNE_CMDRDLY, i);
1337-
mmc_send_tuning(mmc, opcode, &cmd_err);
1338-
if (!cmd_err)
1339-
rise_delay |= (1 << i);
1363+
/*
1364+
* Using the same parameters, it may sometimes pass the test,
1365+
* but sometimes it may fail. To make sure the parameters are
1366+
* more stable, we test each set of parameters 3 times.
1367+
*/
1368+
for (j = 0; j < 3; j++) {
1369+
mmc_send_tuning(mmc, opcode, &cmd_err);
1370+
if (!cmd_err) {
1371+
rise_delay |= (1 << i);
1372+
} else {
1373+
rise_delay &= ~(1 << i);
1374+
break;
1375+
}
1376+
}
13401377
}
13411378
final_rise_delay = get_best_delay(host, rise_delay);
13421379
/* if rising edge has enough margin, then do not scan falling edge */
1343-
if (final_rise_delay.maxlen >= 10 ||
1344-
(final_rise_delay.start == 0 && final_rise_delay.maxlen >= 4))
1380+
if (final_rise_delay.maxlen >= 12 && final_rise_delay.start < 4)
13451381
goto skip_fall;
13461382

13471383
sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
13481384
for (i = 0; i < PAD_DELAY_MAX; i++) {
13491385
sdr_set_field(host->base + MSDC_PAD_TUNE,
13501386
MSDC_PAD_TUNE_CMDRDLY, i);
1351-
mmc_send_tuning(mmc, opcode, &cmd_err);
1352-
if (!cmd_err)
1353-
fall_delay |= (1 << i);
1387+
/*
1388+
* Using the same parameters, it may sometimes pass the test,
1389+
* but sometimes it may fail. To make sure the parameters are
1390+
* more stable, we test each set of parameters 3 times.
1391+
*/
1392+
for (j = 0; j < 3; j++) {
1393+
mmc_send_tuning(mmc, opcode, &cmd_err);
1394+
if (!cmd_err) {
1395+
fall_delay |= (1 << i);
1396+
} else {
1397+
fall_delay &= ~(1 << i);
1398+
break;
1399+
}
1400+
}
13541401
}
13551402
final_fall_delay = get_best_delay(host, fall_delay);
13561403

13571404
skip_fall:
13581405
final_maxlen = max(final_rise_delay.maxlen, final_fall_delay.maxlen);
1406+
if (final_fall_delay.maxlen >= 12 && final_fall_delay.start < 4)
1407+
final_maxlen = final_fall_delay.maxlen;
13591408
if (final_maxlen == final_rise_delay.maxlen) {
13601409
sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
13611410
sdr_set_field(host->base + MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRDLY,
@@ -1367,7 +1416,71 @@ static int msdc_tune_response(struct mmc_host *mmc, u32 opcode)
13671416
final_fall_delay.final_phase);
13681417
final_delay = final_fall_delay.final_phase;
13691418
}
1419+
if (host->hs200_cmd_int_delay)
1420+
goto skip_internal;
1421+
1422+
for (i = 0; i < PAD_DELAY_MAX; i++) {
1423+
sdr_set_field(host->base + MSDC_PAD_TUNE,
1424+
MSDC_PAD_TUNE_CMDRRDLY, i);
1425+
mmc_send_tuning(mmc, opcode, &cmd_err);
1426+
if (!cmd_err)
1427+
internal_delay |= (1 << i);
1428+
}
1429+
dev_dbg(host->dev, "Final internal delay: 0x%x\n", internal_delay);
1430+
internal_delay_phase = get_best_delay(host, internal_delay);
1431+
sdr_set_field(host->base + MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRRDLY,
1432+
internal_delay_phase.final_phase);
1433+
skip_internal:
1434+
dev_dbg(host->dev, "Final cmd pad delay: %x\n", final_delay);
1435+
return final_delay == 0xff ? -EIO : 0;
1436+
}
1437+
1438+
static int hs400_tune_response(struct mmc_host *mmc, u32 opcode)
1439+
{
1440+
struct msdc_host *host = mmc_priv(mmc);
1441+
u32 cmd_delay = 0;
1442+
struct msdc_delay_phase final_cmd_delay = { 0,};
1443+
u8 final_delay;
1444+
int cmd_err;
1445+
int i, j;
1446+
1447+
/* select EMMC50 PAD CMD tune */
1448+
sdr_set_bits(host->base + PAD_CMD_TUNE, BIT(0));
1449+
1450+
if (mmc->ios.timing == MMC_TIMING_MMC_HS200 ||
1451+
mmc->ios.timing == MMC_TIMING_UHS_SDR104)
1452+
sdr_set_field(host->base + MSDC_PAD_TUNE,
1453+
MSDC_PAD_TUNE_CMDRRDLY,
1454+
host->hs200_cmd_int_delay);
1455+
1456+
if (host->hs400_cmd_resp_sel_rising)
1457+
sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
1458+
else
1459+
sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
1460+
for (i = 0 ; i < PAD_DELAY_MAX; i++) {
1461+
sdr_set_field(host->base + PAD_CMD_TUNE,
1462+
PAD_CMD_TUNE_RX_DLY3, i);
1463+
/*
1464+
* Using the same parameters, it may sometimes pass the test,
1465+
* but sometimes it may fail. To make sure the parameters are
1466+
* more stable, we test each set of parameters 3 times.
1467+
*/
1468+
for (j = 0; j < 3; j++) {
1469+
mmc_send_tuning(mmc, opcode, &cmd_err);
1470+
if (!cmd_err) {
1471+
cmd_delay |= (1 << i);
1472+
} else {
1473+
cmd_delay &= ~(1 << i);
1474+
break;
1475+
}
1476+
}
1477+
}
1478+
final_cmd_delay = get_best_delay(host, cmd_delay);
1479+
sdr_set_field(host->base + PAD_CMD_TUNE, PAD_CMD_TUNE_RX_DLY3,
1480+
final_cmd_delay.final_phase);
1481+
final_delay = final_cmd_delay.final_phase;
13701482

1483+
dev_dbg(host->dev, "Final cmd pad delay: %x\n", final_delay);
13711484
return final_delay == 0xff ? -EIO : 0;
13721485
}
13731486

@@ -1390,7 +1503,7 @@ static int msdc_tune_data(struct mmc_host *mmc, u32 opcode)
13901503
}
13911504
final_rise_delay = get_best_delay(host, rise_delay);
13921505
/* if rising edge has enough margin, then do not scan falling edge */
1393-
if (final_rise_delay.maxlen >= 10 ||
1506+
if (final_rise_delay.maxlen >= 12 ||
13941507
(final_rise_delay.start == 0 && final_rise_delay.maxlen >= 4))
13951508
goto skip_fall;
13961509

@@ -1423,6 +1536,7 @@ static int msdc_tune_data(struct mmc_host *mmc, u32 opcode)
14231536
final_delay = final_fall_delay.final_phase;
14241537
}
14251538

1539+
dev_dbg(host->dev, "Final data pad delay: %x\n", final_delay);
14261540
return final_delay == 0xff ? -EIO : 0;
14271541
}
14281542

@@ -1431,7 +1545,10 @@ static int msdc_execute_tuning(struct mmc_host *mmc, u32 opcode)
14311545
struct msdc_host *host = mmc_priv(mmc);
14321546
int ret;
14331547

1434-
ret = msdc_tune_response(mmc, opcode);
1548+
if (host->hs400_mode)
1549+
ret = hs400_tune_response(mmc, opcode);
1550+
else
1551+
ret = msdc_tune_response(mmc, opcode);
14351552
if (ret == -EIO) {
14361553
dev_err(host->dev, "Tune response fail!\n");
14371554
return ret;
@@ -1444,6 +1561,7 @@ static int msdc_execute_tuning(struct mmc_host *mmc, u32 opcode)
14441561

14451562
host->saved_tune_para.iocon = readl(host->base + MSDC_IOCON);
14461563
host->saved_tune_para.pad_tune = readl(host->base + MSDC_PAD_TUNE);
1564+
host->saved_tune_para.pad_cmd_tune = readl(host->base + PAD_CMD_TUNE);
14471565
return ret;
14481566
}
14491567

@@ -1478,6 +1596,25 @@ static struct mmc_host_ops mt_msdc_ops = {
14781596
.hw_reset = msdc_hw_reset,
14791597
};
14801598

1599+
static void msdc_of_property_parse(struct platform_device *pdev,
1600+
struct msdc_host *host)
1601+
{
1602+
of_property_read_u32(pdev->dev.of_node, "hs400-ds-delay",
1603+
&host->hs400_ds_delay);
1604+
1605+
of_property_read_u32(pdev->dev.of_node, "mediatek,hs200-cmd-int-delay",
1606+
&host->hs200_cmd_int_delay);
1607+
1608+
of_property_read_u32(pdev->dev.of_node, "mediatek,hs400-cmd-int-delay",
1609+
&host->hs400_cmd_int_delay);
1610+
1611+
if (of_property_read_bool(pdev->dev.of_node,
1612+
"mediatek,hs400-cmd-resp-sel-rising"))
1613+
host->hs400_cmd_resp_sel_rising = true;
1614+
else
1615+
host->hs400_cmd_resp_sel_rising = false;
1616+
}
1617+
14811618
static int msdc_drv_probe(struct platform_device *pdev)
14821619
{
14831620
struct mmc_host *mmc;
@@ -1549,10 +1686,7 @@ static int msdc_drv_probe(struct platform_device *pdev)
15491686
goto host_free;
15501687
}
15511688

1552-
if (!of_property_read_u32(pdev->dev.of_node, "hs400-ds-delay",
1553-
&host->hs400_ds_delay))
1554-
dev_dbg(&pdev->dev, "hs400-ds-delay: %x\n",
1555-
host->hs400_ds_delay);
1689+
msdc_of_property_parse(pdev, host);
15561690

15571691
host->dev = &pdev->dev;
15581692
host->mmc = mmc;
@@ -1664,6 +1798,7 @@ static void msdc_save_reg(struct msdc_host *host)
16641798
host->save_para.patch_bit0 = readl(host->base + MSDC_PATCH_BIT);
16651799
host->save_para.patch_bit1 = readl(host->base + MSDC_PATCH_BIT1);
16661800
host->save_para.pad_ds_tune = readl(host->base + PAD_DS_TUNE);
1801+
host->save_para.pad_cmd_tune = readl(host->base + PAD_CMD_TUNE);
16671802
host->save_para.emmc50_cfg0 = readl(host->base + EMMC50_CFG0);
16681803
}
16691804

@@ -1676,6 +1811,7 @@ static void msdc_restore_reg(struct msdc_host *host)
16761811
writel(host->save_para.patch_bit0, host->base + MSDC_PATCH_BIT);
16771812
writel(host->save_para.patch_bit1, host->base + MSDC_PATCH_BIT1);
16781813
writel(host->save_para.pad_ds_tune, host->base + PAD_DS_TUNE);
1814+
writel(host->save_para.pad_cmd_tune, host->base + PAD_CMD_TUNE);
16791815
writel(host->save_para.emmc50_cfg0, host->base + EMMC50_CFG0);
16801816
}
16811817

0 commit comments

Comments
 (0)