首页 > 编程知识 正文

sdio 驱动

时间:2023-05-03 21:21:59 阅读:259132 作者:3153

SDIO驱动(1)Host端驱动框架提到:

static int __devinit s3cmci_probe(struct platform_device *pdev) { struct mmc_host *mmc; // 创建mmc_host(对象),在mmc_alloc_host()中进行一些通用设置的初始化 mmc = mmc_alloc_host(sizeof(struct s3cmci_host), &pdev->dev); mmc->ops = &s3cmci_ops; // operations // 其他成员初始化 // Host注册 ret = mmc_add_host(mmc); return 0; } 1、Host的创建 mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev);

这里创建一个host并对其某些成员进行初始化,如:
host->rescan_disable = 1; –>禁止扫描探测card
host->index = 2; –>该host的编号
host->parent = dev; –>该host的父设备,这里是注册该host的那个platform设备
host->class_dev.parent = dev; host->class_dev.class = &mmc_host_class; –>该host在设备模型class中的体现,即该设备从属于某一个class-mmc_host_class
host->clk_requests、host->clk_delay、host->clkgate_delay、host->clk_gated、host->clk_gate_work、host->clk_lock、host->clk_gate_mutex –>设置host的clk相关的参数并初始化访问这些参数需要的lock
host->slot.cd_irq = -EINVAL; –>初始化card detect中断
host->lock –>初始化自旋锁lock(lock for claim and bus ops)
host->wq –>初始化等待队列
host->detect–>关键参数!在需要的时候扫描卡(mmc_rescan),后文详述。
max_seg_size、max_segs、max_req_size、max_blk_size、max_blk_count、max_busy_timeout–>和块设备(如MMC、SD、eMMC等)有关的参数,在古老的磁盘时代,这些参数比较重要。对基于MMC技术的块设备来说,硬件的性能大大提升,这些参数就没有太大的意义了。

2、Host的操作 mmc->ops = &s3cmci_ops;

提供访问Host的方式,由MMC core调用:

static struct mmc_host_ops s3cmci_ops = { .request = s3cmci_request, .set_ios = s3cmci_set_ios, .get_ro = s3cmci_get_ro, .get_cd = s3cmci_card_present, .enable_sdio_irq = s3cmci_enable_sdio_irq,}; 3、卡的扫描流程

系统在完成Host的添加后,要进行卡的扫描:

mmc_add_host(host)-->mmc_start_host(host)---->_mmc_detect_change(host, 0, false)------>mmc_schedule_delayed_work(&host->detect, delay);

在第1小节层提到过host->detect参数,它的初始化代码:

INIT_DELAYED_WORK(&host->detect, mmc_rescan);

所以,在指定delay时间后调用mmc_rescan()进行卡的扫描。

core.c (driversmmccore)static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };void mmc_rescan(struct work_struct *work){ ... mmc_claim_host(host); -------------------> a for (i = 0; i < ARRAY_SIZE(freqs); i++) { ----------> b if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min))) { extend_wakelock = true; break; } if (freqs[i] <= host->f_min) break; } mmc_release_host(host); -------------------> c ...}

a,以独占的方式访问该host。
题外话:记得在USB通信中,使用之前也需要执行相似的操作,如:

android_src/frameworks/base/core/jni/android_hardware_UsbDeviceConnection.cppusb_device_claim_interface(device, interfaceID);....usb_device_release_interface(device, interfaceID);

c,相应的,用完需要release。
b,这里是进行实际scan的地方。
虽然SDIO的数据传输速率可达100Mb/s以上,但在对卡进行激活的时候,必须在Low-Speed模式(400KHz)下进行。

mmc_rescan_try_freq(host, max(freqs[i], host->f_min))

这里就通过400KHz、300KHz、200KHz、100KHz依次进行卡的扫描:

core.c (driversmmccore)static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq){ host->f_init = freq; /* * sdio_reset sends CMD52 to reset card. Since we do not know * if the card is being re-initialized, just send it. CMD52 * should be ignored by SD/eMMC cards. */ sdio_reset(host); mmc_go_idle(host); mmc_send_if_cond(host, host->ocr_avail); /* Order's important: probe SDIO, then SD, then MMC */ if (!mmc_attach_sdio(host)) return 0; if (!mmc_attach_sd(host)) return 0; if (!mmc_attach_mmc(host)) return 0; return -EIO;}

以上是在注册Host时由Host发起的扫描过程。
卡本身在插拔时,也应该有能力启动扫描动作。这个扫描动过通过终端实现:

ret = gpio_request(host->pdata->gpio_detect, "s3cmci detect");host->irq_cd = gpio_to_irq(host->pdata->gpio_detect);// 监测卡detect引脚的上升沿、下降沿跳变request_irq(host->irq_cd, s3cmci_irq_cd, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,DRIVER_NAME, host);irqreturn_t s3cmci_irq_cd(int irq, void *dev_id)-->mmc_detect_change(host->mmc, msecs_to_jiffies(500));-->--mmc_schedule_delayed_work(&host->detect, delay);

同样调用mmc_rescan()扫描card。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。

  •  标签:  
  • sdio