spi-mem: 为SPI存储器生态系统带来一些一致性

在本文中,我们将介绍关于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://bootlin.com/blog/spi-mem-bringing-some-consistency-to-the-spi-memory-ecosystem/

原作者 Boris Brezillon

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

时间: 2024-10-16 07:06:19

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

SPI(1)——Documentation/spi/spi_summary.txt翻译

Linux内核SPI支持概述==================================== 02 - 2012 1.什么是SPI?------------ "Serial Peripheral Interface" (SPI) 是同步四线串行接口,用于将微控制器连接到传感器,存储器和外围设备的链路.这是一个简单的“事实上的”标准,并不足以获得标准化机构. SPI使用主/从配置. 三条信号线中有一个是时钟(SCK,通常在10 MHz的数量级),以及具有"Master

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

Controlling a Digital Potentiometer Using SPI In this tutorial you will learn how to control the AD5206 digital potentiometer(数字电位计) using Serial Peripheral Interface (SPI). For an explanation of SPI see the SPI Library reference. Digital potentiomet

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

Using SPI to read a Barometric Pressure Sensor This example shows how to use the SPI (Serial Peripheral Interface) Communications Library to read data from a SCP1000 Barometric Pressure sensor. Please click here for more information on SPI. Hardware

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

SPI 全称为 Service Provider Interface,是一种服务发现机制.当程序运行调用接口时,会根据配置文件或默认规则信息加载对应的实现类.所以在程序中并没有直接指定使用接口的哪个实现,而是在外部进行装配. 要想了解 Dubbo 的设计与实现,其中 Dubbo SPI 加载机制是必须了解的,在 Dubbo 中有大量功能的实现都是基于 Dubbo SPI 实现解耦,同时也使得 Dubbo 获得如此好的可扩展性. Java SPI 通过完成一个 Java SPI 的操作来了解它的机

linux enc28j60网卡驱动移植(硬件spi和模拟spi)

本来想移植DM9000网卡的驱动,无奈硬件出了点问题,通过杜邦线链接开发板和DM9000网卡模块,系统上电,还没加载网卡驱动就直接崩溃了,找不到原因...刚好手上有一个enc28j60的网卡模块,于是就着手移植enc28j60的驱动. 其实移植enc28j60的驱动也十分简单,网上有现成的,只需要分配一些硬件资源即可. 由于我的内核版本老到掉牙,没有自带enc28j60的驱动,只能在网上找一个: enc28j60.c http://git.ti.com/ti-linux-kernel/ti-li

SPI学习(SPI总线读写FLASH)

总体概述: (1)W25X16/32/64:256-bytes/页(Page),4K-bytes/扇区(Sector),64K-bytes/块(block) W25X16:16M-bit(2M-byte) |   W25X32:32M-bit(4M-byte)  |    W25X64:64M-bit(8M-byte) (2)SPI支持单一或双重输出:四个引脚 clock.chip select.data I/O.data out (3)数据传输速率的支持:最大150M-bits/S clock

19、SPI 和 SST25VF016B

一.SPI总线 1.SPI简介 SPI,是Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口.是Motorola首先在其MC68HCXX系列处理器上定义的.SPI接口主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间.SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通

[SPI]SPI协议详解

转自:https://my.oschina.net/freeblues/blog/67400 1.SPI协议简介 1.1.SPI协议概括 SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口.是Motorola首先在其MC68HCXX系列处理器上定义的.SPI接口主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间.SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了

SPI、I2C、UART、I2S、GPIO、SDIO、CAN

总线,总线,总要陷进里面.这世界上的信号都一样,但是总线却成千上万,让人头疼. 总的来说,总线有三种:内部总线.系统总线和外部总线.内部总线是微机内部各外围芯片与处理器之间的总线,用于芯片一级的互连:而系统总线是微机中各插件板与系统板之间的总线,用于插件板一级的互连:外部总线则是微机和外部设备之间的总线,微机作为一种设备,通过该总线和其他设备进行信息与数据交换,它用于设备一级的互连. 除了总线外,还有一些接口,它们是多种总线的集合体,或者说来者不拒. SPI (Serial Peripheral