Linux SPI/QSPI nor flash相关驱动代码

对于 spi 接口,本身是可以接很多种类的外设的,比如用于接带有SPI通信协议的芯片,通常是将其作为字符设备类型注册。

对于接SPI/QSPI Flash时,又通常作为mtd设备(memory technology device内存技术设备)。MTD的主要目的是为了使新的memory设备的驱动更加简单,为此它在硬件和上层之间提供了一个抽象的接口,主要是读写擦接口。

在芯片厂家设计接口时,有时会把接SPI/QSPI flash接口的单独封装成独立于SPI的专用接口,这就会出现两种情况外设接的是Flash。造就了在SPI 控制器(master)侧的驱动放的位置不一样。

1. 通用SPI 接口,通常通过drivers/mtd/devices/m25p80.c 注册mtd设备

2.SPI/QSPI flash 专用接口控制器

通用SPI 接口文件关系

参考:https://blog.csdn.net/kickxxx/article/details/68924170

Linux kernel中QSPI nor flash相关驱动文件:

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-nor/spi-nor.c: m25p80.c和spi-nor.c都是linux spi nor驱动框架的一部分

SPI/QSPI flash 专用接口文件关系

1. drivers/mtd/spi-nor/fsl-quadspi.c: fsl qspi专用flash主控制器驱动,不同平台使用不同的主控制器驱动。mtd设备注册也是在这主流程中。

2. drivers/mtd/spi-nor/spi-nor.c: 提供通用扫描接口,并封装向上mtd层提供的spi-nor的读写擦接口

系统框架

mtd :  mtd->_read,

spi-nor: spi_nor_read

控制器:nor->read = fsl_qspi_read

spi-nor.c

从架构图可以看出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    

驱动分析

一个现实的设备通常都需要挂接在一种总线上,比较常见的总线有USBPCI总线等。但是,在嵌入式系统里面,SoC系统中集成的独立的外设控制器、挂接在SoC内存空间的外设却不依附与此类总线。基于这样的背景下,2.6内核加入了platform虚拟总线。platform机制将设备本身的资源注册进内核,由内核统一管理,在驱动程序使用这些资源时使用统一的接口platform总线对加入到该总线的设备和驱动分别封装了两个结构体——platform_deviceplatform_driver。并且提供了对应的注册函数

SPI控制器依附platform bus,驱动采用platform driver描述。

SPI 设备(SPI Flash)依附SPI 总线,是实体存在的总线机制,对应驱动采用spi driver描述。


Platform总线、设备、 驱动

platform总线注册由内核管理,平台设备platform_device描述的SPI控制器的信息(数据),platform_driver对应提供控制器的使用方法(策略)支持。

之前的内核platform_device描述一般如下

static struct platform_device qt2410_cs89x0 = {
    .name        = "cirrus-cs89x0",
    .num_resources    = ARRAY_SIZE(qt2410_cs89x0_resources),
    .resource    = qt2410_cs89x0_resources,

};

通过以下两个函数中之一注册设备

int platform_device_register(struct platform_device *);
int platform_add_devices(struct platform_device **, int); //针对的是1个或多个

支持dts的内核版本,platform_device描述直接在dts中描述,有内核解析dts时统一生成platform_device

在初始化先后顺序上,从左到右是:平台总线 --》平台设备 --》平台驱动。实际上所有的总线类型,平台总线总是要较早初始化的。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值