【平台开发】SD速度切换调研

1.速度切换框图

在这里插入图片描述

2.电压切换时序

(1) 主机发送 CMD11 来启动电压切换序列。
(2) 卡返回 R1 响应。
(3) 卡返回响应后,立即驱动 CMD 和 DAT[3:0]信号为低电平。
(4) 主机停止 SDCLK,卡应在主机停止 SDCLK 后开始切换电压。停止 SDCLK 的时间没有说明。主机可以检查任一 CMD 或 DAT[3:0]信号来确认切换序列是否开始,检查哪个信号由主机功能决定。如果主机没有检测到低电平信号,则应中端切换序列,并执行电源周期。
(5) SD 1.8V 输出电压调节器(voltage regulator)应在 5ms 内稳定下来。主机保持 SDCLK
为低至少 5ms。这说明 5ms 对卡是最大时间而对主机是最小时间。
(6) 在(4)之后 5ms 且主机电压稳定后,主机开始在产生 1.8V 的 SDCLK。卡可以检查 SDCLK是否为 1.8V。
(7) 卡在检测到 SDCLK 后,则驱动 CMD 信号为 1.8V 高电平并维持至少一个时钟周期,然后停止驱动(三态)。CMD 在 SDCLK 上升沿被触发(SDR 时序)。
(8) 卡可以通过主机的 pull-up register 检测主机是否将 CMD 驱动到 1.8V。(9) 如果 1.8V 切换成功,则卡驱动 DAT[3:0]到 1.8V 高电平并维持至少一个时钟周期,然后停止驱动(三态)。DAT[3:0]在 SDCLK 上升沿触发(SDR 时序)。DAT[3:0]应该在 SDCLK 产生后1ms 内变为高电平,而主机在 SDCLK 开始后 1ms 检查DAT[3:0]是否变为高电平,也就是说 1ms对卡是最大时间而对主机是最小时间。

2.1示例代码
if(S18A){
			host = mmc->priv;

			//驱动 CMD 和 DAT[3:0]信号为1.8V
			signal_vol(0XD1);
			//主机发送 CMD11 来启动电压切换序列。
			err = send_cmd11(mmc, S18R);
			if(err){
				return err;
			}
			mdelay(1);
			//驱动 CMD 和 DAT[3:0]信号为低电平
			signal_vol(0XC0);
			//主机停止 SDCLK,卡应在主机停止 SDCLK 后开始切换电压
			//dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL);
			//dwmci_writel(host, DWMCI_CLKENA, 0);
			printf("after cmd 11 mmc->clock = %d \r\n", mmc->clock);
			clock = mmc->clock;
			mmc->clock = 0;
			mmc_set_ios(mmc);
			//主机保持 SDCLK 为低至少 5ms。
			mdelay(10);
			//主机开始在产生 1.8V 的 SDCLK。卡可以检查 SDCLK 是否为 1.8V。
			signal_vol(0XD1);
			mmc->clock = clock;
			mmc_set_ios(mmc);
			//biwin_clock_on(mmc->priv);
			mdelay(1);
			start = get_timer(0);
			while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) {
				if (get_timer(start) > timeout) {
					debug("%s: Timeout on data busy\n", __func__);
					printf("%s: Timeout on data busy\n", __func__);
					return -ETIMEDOUT;
				}
			}
		}

3.驱动强度,电流以及速度模式的关系

在这里插入图片描述

3.1示例代码:
int mmc_sd_init_uhs_card(struct mmc *mmc, u8 * sd_status)
{
    int err;
	struct mmc_cmd cmd;
	struct mmc_data data;

	mmc_select_mode(mmc, SPEED_MODE);

	switch(SPEED_MODE){
		case UHS_SDR104:
			mmc_select_mode(mmc, UHS_SDR104);
			err = sd_select_current_type(mmc, CURRENT_LIMIT_800);
			if(err){
				printf("cmd6 select current fail!\r\n");
				return err;
			}
			send_cmd12(mmc);	
			err = sd_select_speed_type(mmc, SDR104);
			if(err){
				printf("cmd6 select speed fail!\r\n");
				return err;
			}
			break;
			···
}
int mmc_tuning(struct mmc *mmc){
	int ret,i,cycle;
	int start_time, end_time,time;
	u8 start_smpl, smpl, candiates = 0;
	struct dwmci_host * host = mmc->priv;
	s8 found = -1;
	mmc->ddr_mode = 0;
	set_pms(3, 200, 1);
	set_clksel(mmc, CLK400_default);
	mdelay(100);
	mmc_set_clock(mmc, 200000000);
	mdelay(100);
	start_smpl = dw_mci_exynos_get_clksmpl(host);
	do {
		smpl = dw_mci_exynos_move_next_clksmpl(host,mmc);
		ret = mmc_send_tuning(mmc, MMC_CMD_SEND_TUNING_BLOCK);
		if (!ret)
			candiates |= (1 << smpl);
		mdelay(50);
	} while (start_smpl != smpl);
	found = dw_mci_exynos_get_best_clksmpl(candiates);
	if (found >= 0) {
		dw_mci_exynos_set_clksmpl(host, found);
	} else {
		ret = -EIO;
	}
	printf("Success!\n");
	return 0;
}
  • 24
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Blank_time

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值