LINUX SPI设备驱动模型分析之五 SPI通用字符设备模型介绍(SPI模块分析结束篇)

       在前面几篇文章我们分析了SPI驱动框架模型、SPI总线、SPI MASTER、SPI DEVICE、SPI通信接口等内容,本篇是SPI总线的最后一篇,主要介绍SPI通用字符设备。

 

 

spi通用字符设备说明

在SPI驱动模块提供了通用字符设备驱动以及注册接口,我们知道I2C模块的通用字符设备也提

供了通用字符设备,在分析SPI通用字符设备模型之前,我们先来说明下I2C通用字符设备模型与SPI通用字符设备模型的区别,以便我们对SPI通用字符设备模型有一个感性的认识。

  1. i2c通用字符设备是与i2c adapter所关联(通过该字符设备可访问该控制器下所有挂载的设备);
  2. 针对每一个i2c adapter,待其注册/注销到i2c总线上时,则借助通知链实现对应字符设备的创建,此为i2c模块已完成的操作,针对每一个注册的i2c adapter,均会为其进行;
  3. spi通用字符设备代表的是一个spi 设备(该字符设备包含了对应spi设备的片选引脚以及所绑定的spi master);
  4. spi通用字符设备文件并不会随着spi master或者spi device的注册/注销而创建或消除,该spi通用字符设备需使用者创建特定的spi device方可以实现通用字符设备的创建。
  5. spi模块为通用字符设备模型注册了一个spi driver,而spi驱动的名称为“spidev”,其针对设备树节点的匹配名称为“rohm,dh2228fv”,spi模块借助该spi driver、名为“spidev”或

 

以上便是spi通用字符设备与i2c通用字符设备的区别,简单点说就是:spi通用字符设备需自行

创建,且与挂载至spi控制器上的spi设备绑定。

 

为Spi 通用字符设备创建而注册的spi driver

spi模块为通用字符设备创建的spi driver如下,该驱动实现的功能如下:

  1. 该驱动可匹配的spi设备有两种:
    1. spi_device->modalias的值为“spidev”
    2. 针对支持设备树的内核,设备节点的compatible为“rohm,dh2228fv”的spi设备
    3. 在spidev_probe接口中,根据传递的spi device参数,完成对应spi通用字符设备的注册,字符设备名称为“"spidevX.Y"”(其中X为spi总线号,Y为spi设备对应的片选序号)
    4. 在spidev_remove接口中,完成字符设备的注销操作。
static const struct of_device_id spidev_dt_ids[] = {
	{ .compatible = "rohm,dh2228fv" },
	{},
};

MODULE_DEVICE_TABLE(of, spidev_dt_ids);

	static struct spi_driver spidev_spi_driver = {
		.driver = {
			.name =		"spidev",
			.owner =	THIS_MODULE,
			.of_match_table = of_match_ptr(spidev_dt_ids),
		},
		.probe =	spidev_probe,
		.remove =	spidev_remove,
	
		/* NOTE:  suspend/resume methods are not necessary here.
		 * We don't do anything except pass the requests to/from
		 * the underlying controller.  The refrigerator handles
		 * most issues; the controller driver handles the rest.
		 */
};

spi通用字符设备驱动创建流程

      SPI 模块提供的通用字符设备是与具体的spi设备向关联的,即我们必须创建一个设备名称或者设备节点名称固定的spi device(spi 设备名称为“spidev”或设备节点名称为“rohm,dh2228fv”),然后与spi驱动模块注册的spi 驱动匹配,方才触发spi 通用字符设备的创建。我们下面来分析下spi通用字符设备的创建流程。

       其实spi通用字符设备与我们自己在spi驱动中实现字符设备的流程基本上是一致的,区别是我们会在spi驱动的probe接口进行一些spi设备的初始化操作,而spi通用字符设备创建所对应的spi驱动的probe仅用来创建字符设备。如下图所示,为我们自己创建spi 字符设备的创建流程,将这个流程图中的红色虚线框中的内容去除,即为spi通用字符设备驱动的创建流程。

spi通用字符设备的操作接口

 

在接口spidev_init中,完成了主设备号为SPIDEV_MAJOR,次设备号为0的spi字符设备的创建,该字符设备文件对应的处理接口为spidev_fops,其定义如下:

static const struct file_operations spidev_fops = {
	.owner =	THIS_MODULE,
	/* REVISIT switch to aio primitives, so that userspace
	 * gets more complete API coverage.  It'll simplify things
	 * too, except for the locking.
	 */
	.write =	spidev_write,
	.read =		spidev_read,
	.unlocked_ioctl = spidev_ioctl,
	.compat_ioctl = spidev_compat_ioctl,
	.open =		spidev_open,
	.release =	spidev_release,
	.llseek =	no_llseek,
};

spidev_open

         spidev_open接口主要用于判断所要打开的spi通用字符设备文件,并根据字符设备文件的设备号在device_list链表上查找对应的spidev_data类型的变量,并将其绑定至文件描述的私有变量指针上。(当进行通用字符设备文件节点的创建前,通过注册spidevice并与spidev_spi_driver绑定时,通过调用spidev_probe时,将该spidevice对应的spidev_data类型的变量添加到device_list链表上,同时通过调用device_create接口完成device类型变量的创建,同时向应用层发送uevent,由应用层的udev或mdev完成字符设备节点的创建(通过mknod系统调用))。

如下是struct spidev_data类型的变量,该变量实现了spi通用字符设备节点对应的文件描述符与spi模块的关联:

  1. 通过spi_device类型的变量,完成了与spi device的关联,从而也完成了与对应spi master的绑定;
  2. dev_t类型的变量说明了该spi通用字符设备节点的设备号;
  3. buffer为进行spi通信的buffer。

 

struct spidev_data {
	dev_t			devt;
	spinlock_t		spi_lock;
	struct spi_device	*spi;
	struct list_head	device_entry;

	/* buffer is NULL unless this device is open (users > 0) */
	struct mutex		buf_lock;
	unsigned		users;
	u8			*buffer;
};

spidev_read、spidev_write

     这两个接口主要通过调用spi通信接口spi_async,完成与具体的spidevice的通信(同步通信)。当spidev_read、spidev_write接口调用spi_async时,借助完成量接口,完成了同步通信(调用wait_for_completion使本进程进入sleep状态,待spi-core完成通信后,则通过执行spidev_complete将该进程唤醒,从而完成了同步通信操作)。

 

spidev_ioctl、spidev_compat_ioctl

      这两个接口主要进行通信速率、通信模式等设置操作,包括SPI_IOC_WR_MODE、SPI_IOC_WR_LSB_FIRST、SPI_IOC_WR_BITS_PER_WORD、SPI_IOC_WR_MAX_SPEED_HZ等接口,也支持与spi device的读写通信等。

 

 

      以上为spi模块通用字符设备模型相关的内容,个人认为该模型被低估了,该模型为我们实现了字符设备模型接口,而且支持读、写、ioctl等功能,若我们需要编写驱动的spi device,仅仅用于读写状态等信息,并不需要进行特殊的初始化,可以完全使用该通用字符设备模型,而不需要重新编写驱动,只需要注册对应的spidev即可,

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值