在本文中,我们将介绍关于spi-mem Linux内核框架的工作,该框架将允许在SPI NOR设备和常规SPI设备以及SPI NAND设备上复用SPI控制器驱动程序。

从SPI到双线、四线、八线SPI

在过去,SPI是一个简单的协议,总线上的所有设备只共享3根信号线:

  • MISO: Master In Slave Out,主设备输入从设备输出线
  • MOSI: Master Out Slave In,主设备输出从设备输入线
  • SCLK: Serial Clock,时钟线

另外每个设备有一个独立信号线,用于选择我们想要通信的设备:

  • SS: Slave Select,从设备选择线 (有时也称为片选线CS,Chip Select)

但随后SPI存储出现了。它从较小且相对较慢的SPI NORs开始,如dataflash、EEPROMs和SRAMs,然后逐渐发展到较大的SPI NORs和SPI NANDs。像往常一样,当涉及到处理存储时,我们希望得到最佳性能表现。SPI总线的限制很快成为瓶颈,因此供应商决定添加更多的I/O线路,并使 MISO/MOSI 线可以双向通信。现在我们看到SPI控制器支持最多8路I/O。这就是业内所说的DualSPI QuadSPI和OctoSPI。

为了在主从设备的数据传输中用上所有的I/O线,必须有某种主从设备之间的协议,这样双方才能知道,何时可以在I/O线上收发数据,应该使用多少根I/O线等。这些由一组从设备预定义的操作规定了如何进行,主设备必须遵循这组操作的规定,进入特定的发送或接收状态。SPI存储器操作通常包括:

  • 1字节的操作码,表示将要进行从操作 (未来将很快会将出现2字节的操作码,请做好准备)
  • 0-N 字节的地址,其含义取决于操作码(可以是绝对内存地址,或其他含义)
  • 0-N 字节的哑字节,使得从设备有足够的时间来进入操作码请求的特定状态,同样,哑字节的数量时取决于操作码的
  • 0-N 字节的输入或输出数据,方向是取决于操作码

请注意,虽然这个协议倾向于被用于存储设备,但并没有什么能限制它只能用于存储设备,如果一些FPGA使用相同的协议来操作非存储设备,我也不会感到惊讶。

Linux SPI 生态

Linux支持双线SPI和四线SPI模式已经有一段时间了(v3.12), SPI设备驱动程序可以为每个SPI传输指定I/O通道的数量。使用这种方式,对SPI存储的操作可以被分为多次SPI传输,每次SPI传输使用预定义数量的I/O通道进行传输。

这种方式可以正常工作,直到一些IP供应商决定让它们的SPI控制器更加智能,嵌入某种高级接口,可以在单个的步骤中执行SPI存储器的操作,而不是使用分开的多次传输操作。(事实上,大多数SPI控制器甚至比这更加智能,可以允许你直接将SPI存储映射到CPU的地址空间,但让我们先把这种情况留待以后处理吧)。在这种情况下,我们需要赋予SPI控制器更多的控制权,这样它就可以决定具体该做什么,而不必从一组分散的SPI传输命令中,重建SPI存储器操作。

当时的决定是,将这些控制器专门用于一个任务,控制SPI NORs(当时这是唯一会用到双线和四线模式的情况),SPI NOR框架就是为此而创建的。

由于这个决定,我们现在在Linux中有一个SPI NOR框架用于连接SPI NOR控制器驱动和SPI NOR的逻辑代码(spi-nor 子系统),同时我们有常规的SPI控制器驱动,可以进行基础的SPI传输(spi 子系统)。然而,从硬件的角度看,能为SPI NOR提供特殊特性的SPI控制器,一般也拥有进行基本传输的能力,即可用于控制常规的SPI设备。不幸的是,基于当前的spi-nor 子系统和spi 子系统是分裂开来的情况,如果一个SPI控制器被spi-nor子系统的驱动支持了,它将无法被用于与spi子系统中的常规设备进行通信。

作为一个针对这个问题的部分的解决方案,->spi_flash_read()操作被添加到结构体 spi_controller中,这允许spi子系统中的常规spi控制器驱动提供一个较优的方式,来从SPI NOR存储中读取数据,这种方式被通用SPI NOR驱动m25p80所使用。然而,这个解决方案是部分的,因为它只优化了读取,并且仅限于SPI NORs。

在当前的架构中,我们有

  • SPI NOR框架,它包含与SPI NOR存储器通讯的协议。这个框架依赖于结构体spi_nor中列出的接口,这些接口的实现是:
  • 专用的SPI NOR控制器,支持专用于SPI NORs的高级SPI控制器
  • m25p80驱动,提供同样的接口,但基于常规SPI控制器驱动,可能具有->spi_flash_read()的优化

是什么促使我们提出SPI存储器接口?

我们之前已经看到,基于SPI NOR框架,SPI NOR存储器已经得到了适当的支持。但NORs 并非SPI总线上唯一的存储设备,SPI NANDs 正在变得越来越流行。
Peter Pan提出了一个遵循SPI NOR模型的,用于支持SPI NAND设备的框架: SPI控制器必须实现SPI NAND控制器接口才能控制SPI NAND。但是当我们更深入地参与到这个开发中时,我们很快意识到沿着这条路走会有多么麻烦,因为这意味着,如果SPI控制器想要同时控制两种设备,就必须同时实现SPI NOR和SPI NAND接口。当SPI NVRAM或任何其他类型的存储制造商决定采用SPI总线时,将会发生什么?再添加一个SPI控制器必须实现的接口?这听起来不是个好主意。

因此我们决定用另外的方式解决这个问题,尝试找出SPI NANDs和SPI NORs的共同点。SPI NORs和SPI NANDs 指令集不同,行为和约束也不同(主要是由于NOR和NAND本身的不同),但当与设备交互时,都遵循同样的SPI存储器操作语义,这也是高级控制器都在尝试优化的部分。

SPI 存储器层只是提供一种方式给SPI控制器驱动,用于传递高级SPI存储器操作,而不是让它们处理SPI传输细节并自行尝试优化它们。这同样简化了SPI存储器驱动,因为它们只需要按照SPI存储器规范发送SPI存储器操作指令,不需要关心复杂的、不断发展的、依赖具体存储器的接口。

有了这个新的架构,SPI NOR和SPI NAND都可以基于相同的SPI控制器驱动进行支持了。m25p80驱动将被修改成,使用spi-mem接口,取代具有局限性的->spi_flash_read()接口。目前,我们仍然有专用的SPI NOR控制器驱动,但最终目标是移除它们,并将它们移植为 drivers/spi 下的普通SPI控制器驱动。非常欢迎这方面的帮助和贡献。

SPI存储器API是什么样子的?

SPI存储器的API 由 include/linux/spi/spi-mem.h 描述。

希望使用SPI存储器API的SPI设备驱动程序,应该将自己声明为spi_mem_drivers,并实现->probe()和->remove()函数。
它们将被传入一个spi_mem对象,它只是一个围绕spi_device对象的简单包装,我们引入一个不同的对象的原因是,我们希望能够拓展spi_mem对象,并在需要时附加更多的信息(例如存储器类型,存储器组织方式和其他的高级SPI控制器可能需要的信息)。
当驱动想要执行SPI存储器操作时,它将填充spi_mem_op结构并调用spi_mem_exec_op()。另外,可以使用spi_mem_supports_op(),测试一个SPI控制器是否支持特定的存储器操作,使用spi_mem_adjust_op_size(),获取控制器支持的最大传输大小,并尝试拆分数据传输以避免超出限制。

现在让我们看下控制器端。一个希望优化SPI存储器操作的SPI控制器,可以实现spi_mem_ops接口,该接口包含三个直接对应用户API的方法:

  • ->exec_op():执行存储器操作,如果不支持则返回-ENOTSUPP。
  • ->supports_op(): 检查这个存储器操作是否支持。
  • ->adjust_op_size(): 调整存储器操作的数据传输大小,以符合对齐要求和最大FIFO大小的约束。

注意,当spi_mem_ops 没有实现时,core层将通过创建由多个SPI传输组成的SPI消息,来添加对该特性的通用支持,就像以前通用SPI NOR控制器驱动程序(名为m25p80)所做的那样。

如你所见,这些API非常直截了当,所以希望有更多的SPI存储器驱动能够转换为使用它,而不是手动创建包含多个SPI传输的SPI消息。

当前状态

一部分已经被贡献出去并合并,计划成为Linux 4.18的一部分:

下一步是什么?

先进的SPI控制器不仅能够优化SPI存储器操作的执行,它们可以进一步将所有存储器访问的复杂性隐藏起来,提供一个直接映射的IOMEM区域,对此区域的访问会自动在总线上触发SPI存储器操作,为你完成数据的收发,这样的行为就像一个连接在并行的内存总线上的内存。可以想象,这将允许更高的吞吐量和更少的用于SPI存储器操作管理的CPU时间,但这同时也是一个难以通过常规的方式进行支持的功能。我们已经在linux-mtd邮件列表上发布了一个支持这种直接映射功能的建议

如前所述,另一个具有挑战性的主题是,将所有的SPI NOR控制器驱动转换为基于SPI mem模型,以便所有的QSPI控制器都真正表现为SPI控制器而非SPI NOR控制器。这可能需要一些时间,因为目前在driver/mtd/spi-nor 下有10个驱动,我们只知道其中2个被转换为了SPI mem方法(fsl-quadspi和atmel-quadspi)。

本文地址 https://www.cnblogs.com/zqb-all/p/10810054.html

译自 https://bootlin.com/blog/spi-mem-bringing-some-consistency-to-the-spi-memory-ecosystem/

原作者 Boris Brezillon

spi-mem: 为SPI存储器生态带来一些一致性的更多相关文章

  1. Linux驱动 - SPI驱动 之三 SPI控制器驱动

    通过第一篇文章,我们已经知道,整个SPI驱动架构可以分为协议驱动.通用接口层和控制器驱动三大部分.其中,控制器驱动负责最底层的数据收发工作,为了完成数据的收发工作,控制器驱动需要完成以下这些功能:1. ...

  2. Java spi 和Spring spi

    service provider framework是一个系统, 实现了SPI, 在系统里多个服务提供者模块可以提供一个服务的实现, 系统让客户端可以使用这些实现, 从而实现解耦. 一个service ...

  3. Dubbo 扩展点加载机制:从 Java SPI 到 Dubbo SPI

    SPI 全称为 Service Provider Interface,是一种服务发现机制.当程序运行调用接口时,会根据配置文件或默认规则信息加载对应的实现类.所以在程序中并没有直接指定使用接口的哪个实 ...

  4. SPI应用 用SPI总线读取气压传感器SCP1000的数据

    Using SPI to read a Barometric Pressure Sensor This example shows how to use the SPI (Serial Periphe ...

  5. SPI应用 用SPI控制一个数字电位器

    Controlling a Digital Potentiometer Using SPI In this tutorial you will learn how to control the AD5 ...

  6. Java SPI 与 Dubbo SPI

    SPI(Service Provider Interface)是JDK内置的一种服务提供发现机制.本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类.这样可以在运行时,动 ...

  7. 联盛德 HLK-W806 (四): 软件SPI和硬件SPI驱动ST7735液晶LCD

    目录 联盛德 HLK-W806 (一): Ubuntu20.04下的开发环境配置, 编译和烧录说明 联盛德 HLK-W806 (二): Win10下的开发环境配置, 编译和烧录说明 联盛德 HLK-W ...

  8. 联盛德 HLK-W806 (九): 软件SPI和硬件SPI驱动ST7789V液晶LCD

    目录 联盛德 HLK-W806 (一): Ubuntu20.04下的开发环境配置, 编译和烧录说明 联盛德 HLK-W806 (二): Win10下的开发环境配置, 编译和烧录说明 联盛德 HLK-W ...

  9. 联盛德 HLK-W806 (十一): 软件SPI和硬件SPI驱动ST7567液晶LCD

    目录 联盛德 HLK-W806 (一): Ubuntu20.04下的开发环境配置, 编译和烧录说明 联盛德 HLK-W806 (二): Win10下的开发环境配置, 编译和烧录说明 联盛德 HLK-W ...

随机推荐

  1. 在开发Thinkphp5.0智慧软文个人微信个人支付宝企业支付宝接口时遇到的坑

    在开发Thinkphp5.0智慧软文个人微信个人支付宝企业支付宝接口时遇到回调后提示成功但是不能自动充值的情况,现在记录一下: 两种情况 1.个人支付宝  个人微信遇到的情况 因为个人支付宝 个人微信 ...

  2. 解决mysql java.sql.SQLException: The server time zone value‘XXXXXX' is unrecognized or represents...

    解决 java.sql.SQLException: The server time zone value 'XXXXXX' is unrecognized or represents more tha ...

  3. iNeuOS 工业互联网 从网关到云端一体化解决方案。教你如何做PPT。

          iNeuOS 专注打造云端操作系统,提供全新解决方案   (凑够150字) 核心组件包括:边缘网关(iNeuLink).设备容器(iNeuKernel).视图建模(iNeuView).机器 ...

  4. luogu P2860 [USACO06JAN]冗余路径Redundant Paths |Tarjan

    题目描述 In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1. ...

  5. luogu P1850 换教室

    题目描述 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程. 在可以选择的课程中,有 2n 节课程安排在 n 个时间段上.在第 i (1 ≤ i ≤ n)个时间段上,两节内容 ...

  6. 自学python中的心得

    以后的日子里我将与可爱的亲们一起度过我自学python的岁月,请博客园里的大佬们监督与见证.

  7. iOS apns推送

    前言:推送分为本地推送以及远程推送. 两者的区别为本地推送一般为定时推送.定期推送或者位置推送.而远程推送更为多样化,能满足较高的要求.当然远程推送需要服务器端开发,开发流程较复杂. 1.本地推送只需 ...

  8. React、React Native面试题

    1.React Native相对于原生的ios和Android有哪些优势. react native一套代码可以开发出跨平台app, 减少了人力.节省了时间.避免了 iOS 与 Android 版本发 ...

  9. seaborn 数据可视化(二)带有类别属性的数据可视化

    Seaborn的分类图分为三类,将分类变量每个级别的每个观察结果显示出来,显示每个观察分布的抽象表示,以及应用统计估计显示的权重趋势和置信区间: 第一个包括函数swarmplot()和stripplo ...

  10. RT-Thread的位图调度算法分析(最新版)

    RT-Thread的内核调度算法 rt-thread的调度算法为基于优先级调度和基于时间片轮转调度共存的策略.rt-thread内核中存在多个线程优先级,并且支持多个线程具有同样的线程优先级.线程级别 ...