主要平台imx6,wifi芯片为博通
写数据
dhd_start_xmit(struct sk_buff *skb, struct net_device *net)
{
....dhd_sendpkt(&dhd->pub, ifidx, pktbuf);
}
dhd_sendpkt(&dhd->pub, ifidx, pktbuf);dhd_bus_txdata(dhdp->bus, pktbuf);dhdsdio_txpkt(bus, chan, &pkt, 1, TRUE);dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,PKTDATA(osh, head_pkt), total_len, pkt_chain, NULL, NULL, TXRETRIES);
bcmsdh_send_buf(bus->sdh, addr, fn, flags, buf, nbytes,pkt, complete, handle);bcmsdhsdio_set_sbaddr_window(bcmsdh, addr, FALSE)sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, incr_fix,SDIOH_WRITE, fn, addr, width, nbytes, buf, pkt);sdioh_buffer_tofrom_bus(sd, fix_inc, write, func, addr,PKTDATA(sd->osh, tmppkt), ROUNDUP(buf_len, (DMA_ALIGN_MASK+1)));sdio_memcpy_toio(sd->func[func], addr, buf, len);
以上主要描述了驱动主要写数据流程,下面具体分析
最后主要调用
int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz)
{struct mmc_request mrq = {0};struct mmc_command cmd = {0};struct mmc_data data = {0};struct scatterlist sg;BUG_ON(!card);BUG_ON(fn > 7);BUG_ON(blocks == 1 && blksz > 512);WARN_ON(blocks == 0);WARN_ON(blksz == 0);/* sanity check */if (addr & ~0x1FFFF)return -d = &cmd;mrq.data = &data;cmd.opcode = SD_IO_RW_EXTENDED; //cmd53cmd.arg = write ? 0x80000000 : 0x00000000; //读写cmd.arg |= fn << 28;//func->numcmd.arg |= incr_addr ? 0x04000000 : 0x00000000;cmd.arg |= addr << 9;//地址if (blocks == 1 && blksz <= 512)cmd.arg |= (blksz == 512) ? 0 : blksz; /* byte mode */elsecmd.arg |= 0x08000000 | blocks; /* block mode */cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;data.blksz = blksz;data.blocks = blocks;data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;data.sg = &sg;data.sg_len = 1;sg_init_one(&sg, buf, blksz * blocks);//初始化sg,找到buf对应的物理页地址,为DMA传输做准备mmc_set_data_timeout(&data, card);mmc_wait_for_req(card->host, &mrq);//发送数据,并且等待返回if () ;if ();if (mmc_host_is_spi(card->host)) {/* host driver already reported errors */} else { //返回数据处理R5if (sp[0] & R5_ERROR)return -EIO;if (sp[0] & R5_FUNCTION_NUMBER)return -EINVAL;if (sp[0] & R5_OUT_OF_RANGE)return -ERANGE;}return 0;
}
调用host->ops->request(host, mrq);
即sdhci_request发送数据
sdhci_send_command(host, mrq->cmd);调用
static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
{sdhci_prepare_data(host, cmd);//准备DMA数据,设置需要的寄存器sdhci_set_transfer_mode(host, cmd);//设置传输mo
void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd);
//0x02190000
sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);//用于传输数据
}
//
void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
{sdhci_pre_dma_transfer(host, data, NULL);
sdhci_clear_set_irqs(host, dma_irqs, pio_irqs);
/* Set the DMA boundary value and block size */
sdhci_writew(host, SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG,data->blksz), SDHCI_BLOCK_SIZE);sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT);}
static void sdhci_set_transfer_irqs(struct sdhci_host *host)
{sdhci_clear_set_irqs(host, dma_irqs, pio_irqs);
}
static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set)
{//02000008 0x00000030 110000u32 ier;ier = sdhci_readl(host, SDHCI_INT_ENABLE);ier &= ~clear;ier |= set; //02000008 0000 0010 0000 0000 0000 0000 0000 1000sdhci_writel(host, ier, SDHCI_INT_ENABLE);//清中断sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE);//产生中断,使能中断了//sdhci_irq
}
sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
准备好DMA数据以后,写SDHCI_COMMAND为触发中断,调用host DMA中断处理数据sdhci_irq,
static irqreturn_t sdhci_irq(int irq, void *dev_id)
{irqreturn_t result;struct sdhci_host* host = dev_id;u32 intmask;int cardint = 0;spin_lock(&host->lock);intmask = sdhci_readl(host, SDHCI_INT_STATUS);if (!intmask || intmask == 0xffffffff) {result = IRQ_NONE;goto out;}printk("*** %s got interrupt: 0x%08xn",mmc_hostname(host->mmc), intmask);if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { //卡插入或者拔出,热插拔sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);tasklet_schedule(&host->card_tasklet);}intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
if (intmask & SDHCI_INT_CMD_MASK) {//cmdsdhci_writel(host, intmask & SDHCI_INT_CMD_MASK,SDHCI_INT_STATUS);sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);}if (intmask & SDHCI_INT_DATA_MASK) {//data sdhci_writel(host, intmask & SDHCI_INT_DATA_MASK,SDHCI_INT_STATUS);sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);//DMA数据处理}intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK);intmask &= ~SDHCI_INT_ERROR;if (intmask & SDHCI_INT_BUS_POWER) {printk(KERN_ERR "%s: Card is consuming too much power!n",mmc_hostname(host->mmc));sdhci_writel(host, SDHCI_INT_BUS_POWER, SDHCI_INT_STATUS);}mmiowb();
mmiowb();//是为了保证编译器顺序编译,防止编译器优化打乱执行顺序
读数据和该流程类似。
本文发布于:2024-02-05 03:46:16,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170723308662784.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |