1. drivers/spi/spi.c: 是linux spi通用框架代码, 向下适配ti mcspi以及ti qspi控制器驱动.
2. drivers/spi/spi-ti-qspi.c: TI qspi主控器驱动, 不同平台使用不同的主控驱动
3. drivers/mtd/devices/m25p80.c: m25p80.c和spi-nor.c都是linux spi nor驱动框架的一部分
4. drivers/mtd/spi/spi-nor/spi-nor.c: m25p80.c和spi-nor.c都是linux spi nor驱动框架的一部分
系统架构
从架构图可以看出spi-nor是简单的粘合层, 把mtd调用转换为m25p80接口. spi-nor还包含了qspi芯片检测, 通过芯片ID, 确定spi nor的参数:sector size, nsectors, pagesize, flags.
spi-nor驱动适配多种spi nor flash, 这些flash的驱动层代码差异, 由flash_info的几个参数表示.
spi-nor.c为mtd子系统服务, 为mtd层提供如下几个接口:
- spi_nor_write
- spi_nor_erase
- spi_nor_read
spi_nor_scan调用spi_nor_read_id从chip获取ID, 根据chip ID得到该芯片的flash_info
1. 设置mtd_info的type, writesize, size等参数
2. 设置mtd_info的_erase, _read, _write回调函数
3. 设置mtd_info 的erasesize
m25p80.c
这个驱动最初为M25Pxx系列使用, 现在已经成为一个通用的spi nor实现, 实际上完全可以和spi-nor.c合二为一.
m25p80.c主要实现了如下几个函数:
- m25p80_read, 实现数据读
- m25p80_write, 实现数据写
- m25p80_erase, 实现数据擦除
- m25p80_write_reg, 写opcode到nor flash, 比如write_enable, erase chip
- m25p80_read_reg, 设置QSPI特定寄存器, 比如读取chip ID, status register等
m25p80.c底层接口为common的spi调用接口, common spi接口会调用qspi master.
驱动初始化流程
Linux spi子系统中, 存在两个角色
- spi master, 比如TI平台的mcspi, 和ti_qspi
- spi device, 比如挂在mcspi上的spi设备, 以及挂在ti_qspi上的qspi nor flash
spi master
系统要访问spi device, 必须通过spi master设备访问, 通常spi master和spi device是一对多的关系, 一个spi master上挂载多个spi device, 通过chip select选取操作哪个spi device
一个spi master对应一个spi bus num, 系统有几个spi master就有几条spi bus. 参见spi_register_master
Linux操作系统会为每一个spi master创建相应的设备节点, 比如ti mcspi对应/dev/spi1, ti qspi对应/dev/spi32766
在spi_register_master的最后阶段, 会扫描device tree中master的子节点(master子节点就是挂在它下面的spi device).
spi bus
spi_init首先初始化注册spi_bus_type, 这是所有spi初始化的起点, 没有spi_bus_type就无法就进行spi device和spi bus的匹配.
spi bus使用spi_match_device作为driver和device的匹配函数
1. 首先尝试匹配driver的of_match_table
2. 然后是id_table
3. 最后会尝试匹配spi device的modalias和driver->name
spi device
m25p80.c定义了一个spi driver m25p80_driver.
在系统初始化阶段module_spi_driver(m25p80_driver)会注册一个spi driver, 在注册过程中, kernel会查看spi_bus上的spi device是否match这个m25p80_driver, 如果match则调用m25p80_dirver的probe函数.