本文共 8525 字,大约阅读时间需要 28 分钟。
drivers/mmc里面结构很清晰,三个目录 card core hostcard 是 卡 // 如果要开发 sd卡驱动,此目录不用关注,因为 sd 卡 的协议是标准的,所以sd卡的驱动也是标准的,几个文件可以代表所有的卡host 是 sdio 控制器(适配器)// 如果要开发 sd卡驱动,此目录需要关注,此目录为sd host 的驱动core 是 card 和 host 中用的函数 //如果要开发 sd卡 驱动,此目录不用关注所以我们说的sd卡驱动开发,其实本质是 sd host 驱动开发
1/ mmc core 子系统的初始化 // 唯一的一个 drivers/mmc/core/core.c subsys_initcall(mmc_init); 2/ card 初始化 // 所有的卡的过程都是相同的,所以此文件不需要变化 drivers/mmc/card/block.c module_init(mmc_blk_init); 3/ host 初始化 // 根据host 不同而不同 drivers/mmc/host/mmci.c module_amba_driver(mmci_driver);
// 设备树 在 mmci_probe->mmci_of_parse->mmc_of_parse 被解析vexpress-v2p-ca9.dtsvexpress-v2m.dtsi mmci@05000 { compatible = "arm,pl180", "arm,primecell"; reg = <0x05000 0x1000>; interrupts = <9 10>; cd-gpios = <&v2m_mmc_gpios 0 0>; wp-gpios = <&v2m_mmc_gpios 1 0>; max-frequency = <12000000>; vmmc-supply = <&v2m_fixed_3v3>; clocks = <&v2m_clk24mhz>, <&smbclk>; clock-names = "mclk", "apb_pclk"; };// vexpress 其他核心板vexpress-v2p-ca15_a7.dts vexpress-v2p-ca15-tc1.dts vexpress-v2p-ca5s.dtsvexpress-v2m-rs1.dtsi mmci@050000 { compatible = "arm,pl180", "arm,primecell"; reg = <0x050000 0x1000>; interrupts = <9 10>; cd-gpios = <&v2m_mmc_gpios 0 0>; wp-gpios = <&v2m_mmc_gpios 1 0>; max-frequency = <12000000>; vmmc-supply = <&v2m_fixed_3v3>; clocks = <&v2m_clk24mhz>, <&smbclk>; clock-names = "mclk", "apb_pclk"; };
mmc初始化后到启动前的mmc 相关过程都是 从 mmc_rescan 开始的.mmc_rescan 是mmc_alloc_host时 INIT_DELAYED_WORK(&host->detect, mmc_rescan); 做出来的任务该任务会被后的这一句被分配任务队列上去,mmc_schedule_delayed_work(&host->detect, delay);至于 谁调用的 mmc_schedule_delayed_work ,以及 调用了之后流程是怎么走的(在mmc_start_request中加dump_stack),是需要关注的,下面就是答案// mmci 模块(drivers/mmc/host/mmci.c)中的函数 mmci_probe mmc_add_host mmc_start_host _mmc_detect_change mmc_schedule_delayed_work(&host->detect, delay); // 开始调度任务. // 此行的dealy 为 0 0延时之后开始任务任务(该任务做sd卡的初始化cmd0->cmd8->acmd41->cmd2->cmd3->cmd9->cmd7) 实际做的初始化包括(CMD52 CMD52 CMD0 CMD8 CMD5 CMD55 CMD41 CMD0 CMD8 CMD55 CMD41 CMD2 CMD3 CMD9 CMD7 CMD55 CMD51 CMD55 CMD13 ) 做完初始化之后,任务退出之前,恰好上层主动做了一次 cmd18. 在任务的最后,mmc_schedule_delayed_work(&host->detect, delay);开始做下一次预约.下一次的时候 mmc_rescan仍然会执行,但是mmc_rescan 执行还没到初始化就退出了, 第三次也是这样子...所以只能初始化一次 // 此行的 dealy为 1s.
linux 中没有实现单块读(?),单块读实现(但是单块读肯定是必要的)的本质是多块读.(cmd18,cmd12)实际上走的命令包括(CMD18 CMD12)[22:47:09][] (unwind_backtrace) from [ ] (show_stack+0x2c/0x38)[22:47:09][ ] (show_stack) from [ ] (__dump_stack+0x1c/0x24)[22:47:09][ ] (__dump_stack) from [ ] (dump_stack+0xd0/0xf8)[22:47:09][ ] (dump_stack) from [ ] (mmc_start_request+0x14/0x57c)[22:47:09][ ] (mmc_start_request) from [ ] (__mmc_start_data_req+0x38/0x70)[22:47:09][ ] (__mmc_start_data_req) from [ ] (mmc_start_req+0x1e4/0x2a0)[22:47:09][ ] (mmc_start_req) from [ ] (mmc_blk_issue_rw_rq+0x184/0x7d4)[22:47:09][ ] (mmc_blk_issue_rw_rq) from [ ] (mmc_blk_issue_rq+0x304/0x364)[22:47:09][ ] (mmc_blk_issue_rq) from [ ] (mmc_queue_thread+0x17c/0x2a0)[22:47:09][ ] (mmc_queue_thread) from [ ] (kthread+0x240/0x24c)[22:47:09][ ] (kthread) from [ ] (ret_from_fork+0x14/0x34)mmc_queue_thread 是什么时候 做出来的.mmc_blk_probe(drivers/mmc/card/block.c) md = mmc_blk_alloc // 创建了一个md,其中包含一个线程 mmc_blk_alloc_req mmc_init_queue mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd/%d%s", host->index, subname ? subname : ""); mmc_add_disk(md) // 向系统注册这个线程.
1.subsys_initcall(mmc_init); 对mmc设备进行初始化2.module_init(mmc_blk_init); 对mmc块模块进行初始化3.挂载mmc设备驱动 驱动程序中的xx_mmc_probe 检测host设备中挂载的sd设备 mmc_alloc_host // 创建一个host设备 INIT_DELAYED_WORK(&host->detect, mmc_rescan) 1.mmc_attach_sd // 对卡进行初始化 2.mmc_add_card // 把存储卡加到系统中。正式与系统驱动连接在一起。 3.mmc_blk_probe // 通知mmc块设备驱动。
host/mmci.c:1712: ret = devm_request_irq(&dev->dev, dev->irq[0], mmci_irq, IRQF_SHARED,host/mmci.c:1720: ret = devm_request_irq(&dev->dev, dev->irq[1], mmci_pio_irq,# cat /proc/interrupts CPU0 34: 729 GIC 41 mmci-pl18x (cmd) 35: 43778 GIC 42 mmci-pl18x (pio)
2235 pr_info("%s: %s %s partition %u %s\n", 2236 part_md->disk->disk_name, mmc_card_id(card), 2237 mmc_card_name(card), part_md->part_type, cap_str); /* 2441 pr_info("%s: %s %s %s %s\n", 2442 md->disk->disk_name /*mmcblk0*/, mmc_card_id(card)/*mmc0:4567*/, mmc_card_name(card)/*QEMU!*/, 2443 cap_str/*25.0 MiB*/, md->read_only ? "(ro)" : ""); */ mmcblk0: mmc0:4567 QEMU! 25.0 MiBmmc_blk_probe pr_info("%s: %s %s %s %s\n", md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), cap_str, md->read_only ? "(ro)" : ""); mmc_blk_alloc_parts mmc_blk_alloc_part pr_info("%s: %s %s partition %u %s\n", part_md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), part_md->part_type, cap_str);
[07:19:04]mmc0: starting CMD18 arg 01000c00 flags 000000b5[07:19:04]mmc0: blksz 512 blocks 2 flags 00000200 tsac 100 ms nsac 0[07:19:04]mmc0: CMD12 arg 00000000 flags 00000095[07:19:04]mmci-pl18x 10005000.mmci: blksz 0200 blks 0002 flags 00000200[07:19:04]mmci-pl18x 10005000.mmci: op 12 arg 01000c00 flags 000000b5[07:19:04]mmci-pl18x 10005000.mmci: irq0 (data+cmd) 00000040[07:19:04]mmci-pl18x 10005000.mmci: irq0 (data+cmd) 00000000[07:19:04]mmci-pl18x 10005000.mmci: irq1 (pio) 0022a400[07:19:04]mmci-pl18x 10005000.mmci: irq1 (pio) 0022a400[07:19:04]mmci-pl18x 10005000.mmci: irq1 (pio) 0022a400[07:19:04]mmci-pl18x 10005000.mmci: irq1 (pio) 0022a400[07:19:04]mmci-pl18x 10005000.mmci: irq1 (pio) 0022a400[07:19:04]mmci-pl18x 10005000.mmci: irq1 (pio) 0022a400[07:19:04]mmci-pl18x 10005000.mmci: irq1 (pio) 0022a400[07:19:04]mmci-pl18x 10005000.mmci: irq1 (pio) 0022a400[07:19:04]mmci-pl18x 10005000.mmci: irq1 (pio) 0022a400[07:19:04]mmci-pl18x 10005000.mmci: irq1 (pio) 0022a400[07:19:04]mmci-pl18x 10005000.mmci: irq1 (pio) 0022a400[07:19:04]mmci-pl18x 10005000.mmci: irq1 (pio) 0022a400[07:19:04]mmci-pl18x 10005000.mmci: irq1 (pio) 0022a400[07:19:04]mmci-pl18x 10005000.mmci: irq1 (pio) 0022a400[07:19:04]mmci-pl18x 10005000.mmci: irq1 (pio) 0022a400[07:19:04]mmci-pl18x 10005000.mmci: irq1 (pio) 0022a500[07:19:04]mmci-pl18x 10005000.mmci: irq0 (data+cmd) 00000100[07:19:04]mmci-pl18x 10005000.mmci: op 0c arg 00000000 flags 00000095[07:19:04]mmci-pl18x 10005000.mmci: irq0 (data+cmd) 00000140[07:19:04]mmc0: req done (CMD18): 0: 00000900 00000000 00000000 00000000[07:19:04]mmc0: 1024 bytes transferred: 0[07:19:04]mmc0: (CMD12): 0: 00000b00 00000000 00000000 00000000[07:19:04]mmci-pl18x 10005000.mmci: irq0 (data+cmd) 00000000
[07:19:02]suws_kernel sd drivers/mmc/host/mmci.c,mmci_probe,1519[07:19:02]mmci-pl18x 10005000.mmci: "bus-width" property is missing, assuming 1 bit.[07:19:02]mmci-pl18x 10005000.mmci: Got CD GPIO[07:19:02]mmci-pl18x 10005000.mmci: Got WP GPIO[07:19:02]mmci-pl18x 10005000.mmci: designer ID = 0x41[07:19:02]mmci-pl18x 10005000.mmci: revision = 0x0[07:19:02]mmci-pl18x 10005000.mmci: clocking block at 12000000 Hz[07:19:02]mmci-pl18x 10005000.mmci: No vqmmc regulator found[07:19:02]mmci-pl18x 10005000.mmci: mmc0: PL181 manf 41 rev0 at 0x10005000 irq 34,35 (pio)[07:19:02]mmc0: clock 0Hz busmode 2 powermode 1 cs 0 Vdd 21 width 0 timing 0[07:19:02]suws_kernel sd drivers/mmc/host/mmci.c,mmci_probe,1743
转载地址:http://hengi.baihongyu.com/