SDIO wifi总线分析

一:sdio wifi接口 使用imx6,三个host,这里使用第三个


1 :clk:主要用于时钟信号,传输数据时,同步作用

2:cmd用于传输命令和应答,SDIO为主从模式,host主要发送命令,device端接收命令,应答或者处理命令; 

3:SDIO_DAT_0-DAT_4主要用于数据传输


二:SDIO命令:

SDIO总线上都是HOST端发起请求,然后DEVICE端回应请求。SDIO命令由6个字节组成,如下图


/* SDIO commands                         type  argument     response */
#define SD_IO_SEND_OP_COND          5 /* bcr  [23:0] OCR         R4  */
#define SD_IO_RW_DIRECT            52 /* ac   [31:0] See below   R5  */
#define SD_IO_RW_EXTENDED          53 /* adtc [31:0] See below   R5  */
  1.  SD_IO_SEND_OP_COND CMD5 命令  主要用于HOST端扫描是否有sdio卡
int mmc_attach_sdio(struct mmc_host *host)
{
.....
	err = mmc_send_io_op_cond(host, 0, &ocr);
.....
}

   通过mmc_send-io_cond函数代码,发送cmd5命令,返回值为ocr,也就是R4


ocr为long类型,长度为32位,R4为48位,所以去除R4前8bit后8bit

Numbei of I/O functions :记录sdio卡功能块,3bit,最多有7个func

Memory Present:如果是1代表是功能块加存储,0代表功能块

S18A: 1bit :用于设置电压1.8V

I/O OCR:支持的电压,下表


2.配置电压

host->ocr = mmc_select_voltage(host, ocr);

3.初始化卡

err = mmc_sdio_init_card(host, host->ocr, NULL, 0);
    
	card = mmc_alloc_card(host, NULL);

	if ((ocr & R4_MEMORY_PRESENT) &&
	    mmc_sd_get_cid(host, host->ocr & ocr, card->raw_cid, NULL) == 0) {
		card->type = MMC_TYPE_SD_COMBO;
		}
	} else {
		card->type = MMC_TYPE_SDIO;
	}

    分配一个卡,根据OCR第27位设置卡类型 

    err = mmc_send_relative_addr(host, &card->rca);
    err = mmc_select_card(card);
    mmc_set_clock(host, card->cis.max_dtr);
    sdio_enable_4bit_bus(card);

    1、通过发送CMD3命令获取设备的从地址(relative addr),并且存放在变量card->rca中。笔者使用的WIFI模块的card->rca = 1

    2、通过发送CMD7,选中相应从地址的卡

    3. 通过调用函数mmc_set_clock设置卡工作的时钟频率

    4. 通过发送CMD6命令,设置4位数据传输模式

二. SD_IO_RW_DIRECT CMD52 


       [31] R/W flag
       [30:28] Function number
       [27] RAW flag
       [25:9] Register address

       [7:0] Data

static int mmc_io_rw_direct_host(struct mmc_host *host, int write, unsigned fn,
	unsigned addr, u8 in, u8 *out)
{
	struct mmc_command cmd = {0};
	int err;

	BUG_ON(!host);
	BUG_ON(fn > 7);

	/* sanity check */
	if (addr & ~0x1FFFF)
		return -EINVAL;

	cmd.opcode = SD_IO_RW_DIRECT;//cmd52
	cmd.arg = write ? 0x80000000 : 0x00000000;
	cmd.arg |= fn << 28;
	cmd.arg |= (write && out) ? 0x08000000 : 0x00000000;
	cmd.arg |= addr << 9;
	cmd.arg |= in;
	cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC;

	err = mmc_wait_for_cmd(host, &cmd, 0);
	return 0;
}

1:BUG_ON(fn > 7); 

if (addr & ~0x1FFFF)

return -EINVAL;

对应cmd52配置,超出bit位数,出现bug

2:mmc_command

struct mmc_command {
	u32			opcode;
	u32			arg;
	u32			resp[4];
	unsigned int		flags;		/* expected response type */
	unsigned int		retries;	/* max number of retries */
	unsigned int		error;		/* command error */
	unsigned int		cmd_timeout_ms;	/* in milliseconds */
	struct mmc_data		*data;		/* data segment associated with cmd */
	struct mmc_request	*mrq;		/* associated request */
};
成员arg 代表如下图:

 

3:mmc_command发送

int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries)
{
	struct mmc_request mrq = {0};
	WARN_ON(!host->claimed);

	memset(cmd->resp, 0, sizeof(cmd->resp));
	cmd->retries = retries;
	mrq.cmd = cmd;
	cmd->data = NULL;
	mmc_wait_for_req(host, &mrq);

	return cmd->error;
}
void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
{
	__mmc_start_req(host, mrq);
	mmc_wait_for_req_done(host, mrq);
}
static void __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
{
	init_completion(&mrq->completion);
	mrq->done = mmc_wait_done;
	mmc_start_request(host, mrq);
}

初始化mrq->completion,开始发送命令

static void mmc_wait_for_req_done(struct mmc_host *host,
				  struct mmc_request *mrq)
{
	struct mmc_command *cmd;

	while (1) {
		wait_for_completion(&mrq->completion);

		cmd = mrq->cmd;
		if (!cmd->error || !cmd->retries)
			break;

		pr_debug("%s: req failed (CMD%u): %d, retrying...\n",
			 mmc_hostname(host), cmd->opcode, cmd->error);
		cmd->retries--;
		cmd->error = 0;
		host->ops->request(host, mrq);
	}
}

wait_for_completion(&mrq->completion);等待,mrq->completion

执行完以后,out 指向cmd52的返回值

*out = cmd.resp[0] & 0xFF;

对应上图的Response Flags

Response Flags 8 Bits of flag data indicating the status of the SDIO card. T

  • 4
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值