|
85 | 85 | #define ESDHC_TUNE_CTRL_MAX ((1 << 7) - 1)
|
86 | 86 | #define ESDHC_TUNE_CTRL_STATUS_TAP_SEL_PRE_MASK GENMASK(30, 24)
|
87 | 87 | #define ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE_MASK GENMASK(14, 8)
|
88 |
| - |
| 88 | +#define ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_OUT_MASK GENMASK(7, 4) |
| 89 | +#define ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_POST_MASK GENMASK(3, 0) |
89 | 90 | /* strobe dll register */
|
90 | 91 | #define ESDHC_STROBE_DLL_CTRL 0x70
|
91 | 92 | #define ESDHC_STROBE_DLL_CTRL_ENABLE (1 << 0)
|
@@ -243,6 +244,7 @@ struct esdhc_platform_data {
|
243 | 244 | unsigned int tuning_start_tap; /* The start delay cell point in tuning procedure */
|
244 | 245 | unsigned int strobe_dll_delay_target; /* The delay cell for strobe pad (read clock) */
|
245 | 246 | unsigned int saved_tuning_delay_cell; /* save the value of tuning delay cell */
|
| 247 | + unsigned int saved_auto_tuning_window; /* save the auto tuning window width */ |
246 | 248 | };
|
247 | 249 |
|
248 | 250 | struct esdhc_soc_data {
|
@@ -1211,6 +1213,7 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
|
1211 | 1213 | {
|
1212 | 1214 | int min, max, avg, ret;
|
1213 | 1215 | int win_length, target_min, target_max, target_win_length;
|
| 1216 | + u32 clk_tune_ctrl_status; |
1214 | 1217 |
|
1215 | 1218 | min = ESDHC_TUNE_CTRL_MIN;
|
1216 | 1219 | max = ESDHC_TUNE_CTRL_MIN;
|
@@ -1250,6 +1253,23 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
|
1250 | 1253 | /* use average delay to get the best timing */
|
1251 | 1254 | avg = (target_min + target_max) / 2;
|
1252 | 1255 | esdhc_prepare_tuning(host, avg);
|
| 1256 | + |
| 1257 | + /* |
| 1258 | + * adjust the delay according to tuning window, make preparation |
| 1259 | + * for the auto-tuning logic. According to hardware suggest, need |
| 1260 | + * to config the auto tuning window width to 3, to make the auto |
| 1261 | + * tuning logic have enough space to handle the sample point shift |
| 1262 | + * caused by temperature change. |
| 1263 | + */ |
| 1264 | + clk_tune_ctrl_status = FIELD_PREP(ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE_MASK, |
| 1265 | + avg - ESDHC_AUTO_TUNING_WINDOW) | |
| 1266 | + FIELD_PREP(ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_OUT_MASK, |
| 1267 | + ESDHC_AUTO_TUNING_WINDOW) | |
| 1268 | + FIELD_PREP(ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_POST_MASK, |
| 1269 | + ESDHC_AUTO_TUNING_WINDOW); |
| 1270 | + |
| 1271 | + writel(clk_tune_ctrl_status, host->ioaddr + ESDHC_TUNE_CTRL_STATUS); |
| 1272 | + |
1253 | 1273 | ret = mmc_send_tuning(host->mmc, opcode, NULL);
|
1254 | 1274 | esdhc_post_tuning(host);
|
1255 | 1275 |
|
@@ -1652,7 +1672,11 @@ static void sdhc_esdhc_tuning_restore(struct sdhci_host *host)
|
1652 | 1672 | writel(reg, host->ioaddr + ESDHC_MIX_CTRL);
|
1653 | 1673 |
|
1654 | 1674 | writel(FIELD_PREP(ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE_MASK,
|
1655 |
| - imx_data->boarddata.saved_tuning_delay_cell), |
| 1675 | + imx_data->boarddata.saved_tuning_delay_cell) | |
| 1676 | + FIELD_PREP(ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_OUT_MASK, |
| 1677 | + ESDHC_AUTO_TUNING_WINDOW) | |
| 1678 | + FIELD_PREP(ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_POST_MASK, |
| 1679 | + ESDHC_AUTO_TUNING_WINDOW), |
1656 | 1680 | host->ioaddr + ESDHC_TUNE_CTRL_STATUS);
|
1657 | 1681 | }
|
1658 | 1682 | }
|
|
0 commit comments