Beispiel #1
0
/*			-1 -- Tuning failed. Maybe slow down the clock and call this function again */
static int mshci_hi_tuning_find_condition(struct mshci_host *ms_host)
{
	struct himci_host *hi_host;
	int sample_min, sample_max;
	/*int begin, end;*/
	int i, j;
	int ret = 0;
	int mask,mask_lenth;

	hi_host = mshci_priv(ms_host);

	if (hi_host->init_tuning_config[4 + (ms_host->mmc->ios.timing + 1) * TUNING_INIT_CONFIG_NUM] ==
		hi_host->init_tuning_config[3 + (ms_host->mmc->ios.timing + 1) * TUNING_INIT_CONFIG_NUM]) {
		hi_host->tuning_init_sample =
			(hi_host->init_tuning_config[4 + (ms_host->mmc->ios.timing + 1) * TUNING_INIT_CONFIG_NUM] +
			hi_host->init_tuning_config[3 + (ms_host->mmc->ios.timing + 1) * TUNING_INIT_CONFIG_NUM]) / 2;
		mshci_hi_set_timing(hi_host, hi_host->tuning_init_sample, -1, -1);
		hi_host_trace(HIMCI_TRACE_SIGNIFICANT,
			"no need tuning: timing is %d, tuning sample = %d",
			ms_host->mmc->ios.timing, hi_host->tuning_init_sample);
		return 0;
	}
	if (-1 == hi_host->tuning_current_sample) {

		mshci_hi_tuning_clear_flags(hi_host);

		/* set the first sam del as the min_sam_del */
		hi_host->tuning_current_sample =
			hi_host->init_tuning_config[4 + (ms_host->mmc->ios.timing + 1) * TUNING_INIT_CONFIG_NUM];
		/* a trick for next "++" */
		hi_host->tuning_current_sample--;
	}

	if (hi_host->tuning_current_sample >=
			hi_host->init_tuning_config[3 + (ms_host->mmc->ios.timing + 1) * TUNING_INIT_CONFIG_NUM]) {
		/* tuning finish, select the best sam_del */

		/* set sam del to -1, for next tuning */
		hi_host->tuning_current_sample = -1;

		sample_min =
			hi_host->init_tuning_config[4 + (ms_host->mmc->ios.timing + 1) * TUNING_INIT_CONFIG_NUM];
		sample_max =
			hi_host->init_tuning_config[3 + (ms_host->mmc->ios.timing + 1) * TUNING_INIT_CONFIG_NUM];

#if 0
		begin = -1;
		end = -1;
		for (i = sample_min; i <= sample_max; i++) {
			if (-1 == begin) {
				/* no begin, find begin */
				if (mshci_hi_tuning_get_flags(hi_host, i)) {
					begin = i;
				} else {
					continue;
				}
			} else if (-1 == end) {
				/* no end, find end */
				if (mshci_hi_tuning_get_flags(hi_host, i)) {
					if (i == sample_max) {
						end = sample_max;
					} else {
						continue;
					}
				} else {
					end = i - 1;
				}
			} else {
				/* has begin & end, break */
				break;
			}
		}

		if (-1 == begin) {
			hi_host->tuning_init_sample = (sample_min + sample_max) / 2;
			hi_host_trace(HIMCI_TRACE_SIGNIFICANT,
				"tuning err: no good sam_del, timing is %d, tuning_flag = 0x%x",
				ms_host->mmc->ios.timing, hi_host->tuning_sample_flag);
			ret = -1;
		} else if (-1 == end) {
			hi_host->tuning_init_sample = (begin + sample_max) / 2;
			hi_host_trace(HIMCI_TRACE_SIGNIFICANT,
					"tuning err: no end! arithmetic error, timing is %d, begin = %d; tuning_flag = 0x%x",
					ms_host->mmc->ios.timing, begin, hi_host->tuning_sample_flag);
			ret = -1;
		} else {
			hi_host->tuning_init_sample = (begin + end) / 2;
			hi_host_trace(HIMCI_TRACE_SIGNIFICANT,
				"tuning OK: timing is %d, tuning sample = %d, tuning_flag = 0x%x",
				ms_host->mmc->ios.timing, hi_host->tuning_init_sample, hi_host->tuning_sample_flag);
			ret = 0;
		}
#else
		hi_host->tuning_init_sample = -1;
		for (mask_lenth = (((sample_max - sample_min) >> 1) << 1) + 1;
			mask_lenth >= 1; mask_lenth -= 2) {

				mask = (1 << mask_lenth) - 1;
				for (i = (sample_min + sample_max - mask_lenth + 1) / 2, j = 1;
					(i <= sample_max - mask_lenth + 1) && (i >= sample_min);
					i = ((sample_min + sample_max - mask_lenth + 1) / 2) + ((j % 2) ? -1 : 1) * (j / 2)) {
					if ((hi_host->tuning_sample_flag & (mask << i)) == (mask << i)) {
						hi_host->tuning_init_sample = i + mask_lenth / 2 ;
						break;
					}

					j++;
				}

				if (hi_host->tuning_init_sample != -1) {
					hi_host_trace(HIMCI_TRACE_SIGNIFICANT,
						"tuning OK: timing is %d, tuning sample = %d, tuning_flag = 0x%x",
						ms_host->mmc->ios.timing, hi_host->tuning_init_sample, hi_host->tuning_sample_flag);
					ret = 0;
					break;
				}
		}

		if (-1 == hi_host->tuning_init_sample) {
			hi_host->tuning_init_sample = (sample_min + sample_max) / 2;
			hi_host_trace(HIMCI_TRACE_SIGNIFICANT,
				"tuning err: no good sam_del, timing is %d, tuning_flag = 0x%x",
				ms_host->mmc->ios.timing, hi_host->tuning_sample_flag);
			ret = -1;
		}
#endif

		mshci_hi_set_timing(hi_host, hi_host->tuning_init_sample, -1, -1);
		return ret;
	} else {
Beispiel #2
0
/*			-1 -- Tuning failed. Maybe slow down the clock and call this function again */
static int mshci_hi_tuning_find_condition(struct mshci_host *ms_host)
{
	struct himci_host *hi_host;
	struct mmc_host *mmc;
	int sample_min, sample_max;
	/*int begin, end;*/
	int i, j;
	int ret;
	int mask,mask_lenth;

	hi_host = mshci_priv(ms_host);
	mmc = ms_host->mmc;

	if (hi_host->init_tuning_config[4 + (ms_host->mmc->ios.timing + 1) * TUNING_INIT_CONFIG_NUM] ==
		hi_host->init_tuning_config[3 + (ms_host->mmc->ios.timing + 1) * TUNING_INIT_CONFIG_NUM]) {
		hi_host->tuning_init_sample =
			(hi_host->init_tuning_config[4 + (ms_host->mmc->ios.timing + 1) * TUNING_INIT_CONFIG_NUM] +
			hi_host->init_tuning_config[3 + (ms_host->mmc->ios.timing + 1) * TUNING_INIT_CONFIG_NUM]) / 2;
		mshci_hi_set_timing(hi_host, hi_host->tuning_init_sample, -1, -1);
		hi_host_trace(HIMCI_TRACE_SIGNIFICANT,
			"no need tuning: timing is %d, tuning sample = %d",
			ms_host->mmc->ios.timing, hi_host->tuning_init_sample);
		return 0;
	}
	if (-1 == hi_host->tuning_current_sample) {

		mshci_hi_tuning_clear_flags(hi_host);

		/* set the first sam del as the min_sam_del */
		hi_host->tuning_current_sample =
			hi_host->init_tuning_config[4 + (ms_host->mmc->ios.timing + 1) * TUNING_INIT_CONFIG_NUM];
		/* a trick for next "++" */
		hi_host->tuning_current_sample--;
	}

	if (hi_host->tuning_current_sample >=
			hi_host->init_tuning_config[3 + (ms_host->mmc->ios.timing + 1) * TUNING_INIT_CONFIG_NUM]) {
		/* tuning finish, select the best sam_del */

		/* set sam del to -1, for next tuning */
		hi_host->tuning_current_sample = -1;

		sample_min =
			hi_host->init_tuning_config[4 + (ms_host->mmc->ios.timing + 1) * TUNING_INIT_CONFIG_NUM];
		sample_max =
			hi_host->init_tuning_config[3 + (ms_host->mmc->ios.timing + 1) * TUNING_INIT_CONFIG_NUM];

#if 0
		begin = -1;
		end = -1;
		for (i = sample_min; i <= sample_max; i++) {
			if (-1 == begin) {
				/* no begin, find begin */
				if (mshci_hi_tuning_get_flags(hi_host, i)) {
					begin = i;
				} else {
					continue;
				}
			} else if (-1 == end) {
				/* no end, find end */
				if (mshci_hi_tuning_get_flags(hi_host, i)) {
					if (i == sample_max) {
						end = sample_max;
					} else {
						continue;
					}
				} else {
					end = i - 1;
				}
			} else {
				/* has begin & end, break */
				break;
			}
		}

		if (-1 == begin) {
			hi_host->tuning_init_sample = (sample_min + sample_max) / 2;
			hi_host_trace(HIMCI_TRACE_SIGNIFICANT,
				"tuning err: no good sam_del, timing is %d, tuning_flag = 0x%x",
				ms_host->mmc->ios.timing, hi_host->tuning_sample_flag);
			ret = -1;
		} else if (-1 == end) {
			hi_host->tuning_init_sample = (begin + sample_max) / 2;
			hi_host_trace(HIMCI_TRACE_SIGNIFICANT,
					"tuning err: no end! arithmetic error, timing is %d, begin = %d; tuning_flag = 0x%x",
					ms_host->mmc->ios.timing, begin, hi_host->tuning_sample_flag);
			ret = -1;
		} else {
			hi_host->tuning_init_sample = (begin + end) / 2;
			hi_host_trace(HIMCI_TRACE_SIGNIFICANT,
				"tuning OK: timing is %d, tuning sample = %d, tuning_flag = 0x%x",
				ms_host->mmc->ios.timing, hi_host->tuning_init_sample, hi_host->tuning_sample_flag);
			ret = 0;
		}
#else
#define SD_DDR50_TUNNING_WIDTH		8
		/* begin: different delay sel for SD card in DDR50 */
		if ((MMC_TYPE_SD == mmc->card->type) &&
			(MMC_TIMING_UHS_DDR50 == mmc->ios.timing) &&
			(hi_host->init_tuning_config[4 + (ms_host->mmc->ios.timing + 1) * TUNING_INIT_CONFIG_NUM] > 8)) {
			sample_min = sample_min - SD_DDR50_TUNNING_WIDTH;
			hi_host->tuning_sample_flag |= hi_host->tuning_sample_flag >> SD_DDR50_TUNNING_WIDTH;
		}