从start_srmboot开始,第一个处理iNand/SD卡的函数在\drivers\mmc中。mmc_initialize()在start_armboot中被调用。
初始化开发板上的mmc系统包括两个部分:1.SOC的mmc控制器,mmc相关时钟初始化。2.SD/iNand芯片初始化(给sd卡时序和命令)。
INIT_LIST_HEAD(内核链表初始化)(&mmc_devices)。mmc_devices是链表全局变量,用于记录系统中所有已经注册的SD/iNand。
cup_mmc_init()位于uboot/cpu/s5pv210/cpu.c主要内容为:
setup_hsmmc_clock();
setup_hsmmc_gpio();
smdk_s3c_hsmmc_init();
setup_hsmmc_clock()设置高速mmc时钟。其中包括:
MMC0 clock src=SCLKMPLL 设置时钟源
MMC0 clock div 设置分频
USE_MMC x 使用x通道
setup_hsmmc_gpio()设置高速mmc的gpio其中包括:
USE_MMCx_1/4/8BIT 设置x通道的1/4/8bit模式。
smdk_s3c_hsmmc_init()三星开发板_s3c_hsmmc就是SOC端的MMC微控制器初始化:
err=s3c_hsmmc_initialize(n);
有几个通道就要注册几个通道(iNand一个,SD卡一个)。
mmc_init SD/iNand卡外部初始化开始:
find_mmc_device(n); 通道设备编号在系统中查找设备,找struct mmc对象(dev_num)对比什么类型设备的几号设备。
进行mmc后半部分mmc初始化:mmc_go_idle()对mmc卡发生初始化指令->mmc_send_cmd(host,&cmd,NULL)命令发送->mmc_send_if_cmd()->......->通过对mmc卡发送指令达到初始化的目的(cmd0什么的)。
其实每一个驱动都对应了一个相关的结构体,变量用于记录驱动的属性,函数指针记录操作方法,用结构体抽象为面向对象的方式。
所以驱动分为两个部分:1.初始化(构建结构体并进行填充)<-构建。2.驱动运行时进行函数指针的调用。
分离思想:在驱动中将方法与数据进行分离。优势:便于移植,驱动移植过程只有数据进行变动,操作方式基本不用改动。
分层思想:整个驱动分开多个层次,直观就体现于多个源文件在多个文件夹中。如:在mmc中,分为drivers/mmc.c(与mmc卡有直接关系)、cpu/s5pc11x多个文件(与soc对mmc操作有直接关系(初始化))。
在drivers中,mmc.c与s3c_hsmmc.c构成了分层,mmc.c调用了s3c_hsmmc.c。mmc.c不涉及硬件操作只是mmc/sd卡相关(什么卡),s3c_hsmmc.c不涉及与驱动时序的操作,只是s3c与soc相关的内容(怎么操作)。
soc层初始化->mmc层初始化->mmc操作,这三层是相连的。cpu/s5pc11x多个文件,soc因怎么设置时钟、gpio、构建相关结构体、构建框架。
下一章将针对x210继续进行说明。