linux spi主设备号,Linux SPI框架(上)

Linux的SPI子系统采用主机驱动和外设驱动分离的思想,首先主机SPI控制器是一种平台设备,因此它以platform的方式注册进内核,外设的信息是以boardinfo形式静态定义的,在创建spi_master时,会根据外设的bus_num和主机的bus_num是否相等,来选择是否将该外设挂接在该SPI主控制器下。先看SPI子系统中几个关键的数据结构:

struct spi_master用来描述一个SPI主控制器

struct spi_master {

struct device dev;

s16 bus_num; /*总线编号*/

u16 num_chipselect;/*支持的外设数量*/

u16 dma_alignment;

int (*transfer)(struct spi_device *spi, struct spi_message *mesg);/*用于将消息添加到队列*/

void (*cleanup)(struct spi_device *spi);

};

struct spi_device用来描述一个SPI从设备

struct spi_device {

struct devicedev;

struct spi_master*master; /*从设备所属的SPI主控器*/

u32max_speed_hz; /*最大传输频率*/

u8chip_select; /*片选号,用于区别其他从设备*/

u8mode; /*传输模式*/

/*各个mode的定义*/

#defineSPI_CPHA0x01 /* clock phase */

#defineSPI_CPOL0x02 /* clock polarity */

#defineSPI_MODE_0(0|0) /* (original MicroWire) */

#defineSPI_MODE_1(0|SPI_CPHA)

#defineSPI_MODE_2(SPI_CPOL|0)

#defineSPI_MODE_3(SPI_CPOL|SPI_CPHA)

#defineSPI_CS_HIGH0x04 /* chipselect active high? */

#defineSPI_LSB_FIRST0x08 /* per-word bits-on-wire */

#defineSPI_3WIRE0x10 /* SI/SO signals shared */

#defineSPI_LOOP0x20 /* loopback mode */

u8bits_per_word; /*每个字的比特数*/

intirq; /*所使用的中断*/

void*controller_state;

void*controller_data;

charmodalias[32]; /*设备名,在和从设备驱动匹配时会用到*/

};

struct spi_driver用来描述一个SPI从设备的驱动,它的形式和struct platform_driver是一致的

struct spi_driver {

int(*probe)(struct spi_device *spi);

int(*remove)(struct spi_device *spi);

void(*shutdown)(struct spi_device *spi);

int(*suspend)(struct spi_device *spi, pm_message_t mesg);

int(*resume)(struct spi_device *spi);

struct device_driverdriver;

};

SPI子系统初始化的第一步就是将SPI总线注册进内核,并且在/sys下创建一个spi_master的类,以后注册的从设备都将挂接在该总线下

static int __init spi_init(void)

{

intstatus;

buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);

if (!buf) {

status = -ENOMEM;

goto err0;

}

status = bus_register(&spi_bus_type);//注册SPI总线

if (status < 0)

goto err1;

status = class_register(&spi_master_class);//注册spi_master类

if (status < 0)

goto err2;

return 0;

err2:

bus_unregister(&spi_bus_type);

err1:

kfree(buf);

buf = NULL;

err0:

return status;

}

我们来看spi_bus_type的定义

struct bus_type spi_bus_type = {

.name= "spi",

.dev_attrs= spi_dev_attrs,

.match= spi_match_device,

.uevent= spi_uevent,

.suspend= spi_suspend,

.resume= spi_resume,

};

来看挂接在SPI总线下的从设备和从设备驱动是如何匹配的,也就是spi_match_device函数

static const struct spi_device_id *spi_match_id(const struct spi_device_id *id,

const struct spi_device *sdev)

{

while (id->name[0]) {

if (!strcmp(sdev->modalias, id->name))

return id;

id++;

}

return NULL;

}

static int spi_match_device(struct device *dev, struct device_driver *drv)

{

const struct spi_device    *spi = to_spi_device(dev);

const struct spi_driver    *sdrv = to_spi_driver(drv);

/* Attempt an OF style match */

if (of_driver_match_device(dev, drv))

return 1;

//如果驱动中定义id_table,查看driver结构体id_table->name与 平台设备结构体dev->modalias 是否相同

if (sdrv->id_table)

return !!spi_match_id(sdrv->id_table, spi);

//如果驱动中没有定义id_table,则对比drv->name 与 dev->modalias是否相同

return strcmp(spi->modalias, drv->name) == 0;

}

这里可以看到是将struct device_driver中的name字段与struct spi_device中的modalias字段进行匹配

这里已经完成了SPI子系统初始化的第一步,也就是注册SPI总线,这一步是和平台无关的,第二步是和平台相关的初始化,下一节再做介绍。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值