linux spi设备使用,linux spi驱动开发学习(一)-----spi子系统架构

linux spi驱动开发学习(一)-----spi子系统架构

一.spi设备(各定义在include/linux/spi.h)

structspi_device {

structdevice   dev;//设备文件

structspi_master   *master;//spi主机

u32 max_speed_hz;   //最大速率

u8  chip_select;    //片选

u8  mode;   //模式

u8  bits_per_word;  //一个字有多少位

intirq;//中断号

void*controller_state;//控制器状态

void*controller_data;//控制器数据

charmodalias[SPI_NAME_SIZE];//名字

};

2.spi传输模式:

#define SPI_CPHA        0x01            //时钟相位

#define SPI_CPOL        0x02            //时钟继续

#define SPI_MODE_0  (0|0)           //模式0

#define SPI_MODE_1  (0|SPI_CPHA)    //模式1

#define SPI_MODE_2  (SPI_CPOL|0)    //模式2

#define SPI_MODE_3  (SPI_CPOL|SPI_CPHA) //模式3

#define SPI_CS_HIGH 0x04            //片选高电平

#define SPI_LSB_FIRST   0x08            //LSB

#define SPI_3WIRE       0x10            //3线模式 SI和SO同一根线

#define SPI_LOOP        0x20            //回送模式

#define SPI_NO_CS       0x40            //单个设备占用一根SPI总线,所以没片选

#define SPI_READY       0x80            //从机拉低电平停止数据传输

3.spi设备的添加spi_new_device

structspi_device *spi_new_device(structspi_master *master,structspi_board_info *chip)

{

structspi_device   *proxy;

intstatus;

proxy = spi_alloc_device(master);   //3.1 spi设备初始化

if(!proxy)

returnNULL;

WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias));

proxy->chip_select = chip->chip_select;   //片选

proxy->max_speed_hz = chip->max_speed_hz; //最大速率

proxy->mode = chip->mode; //模式

proxy->irq = chip->irq;   //中断号

strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias));

proxy->dev.platform_data = (void*) chip->platform_data;

proxy->controller_data = chip->controller_data;

proxy->controller_state = NULL;

status = spi_add_device(proxy); //3.2 添加spi设备

if(status < 0) {

spi_dev_put(proxy); //增加spi设备引用计数

returnNULL;

}

returnproxy;

}

EXPORT_SYMBOL_GPL(spi_new_device);

3.1.分配spi设备

structspi_device *spi_alloc_device(structspi_master *master)

{

structspi_device   *spi;

structdevice       *dev = master->dev.parent;

if(!spi_master_get(master))//判断spi主机是否存在

returnNULL;

spi = kzalloc(sizeof*spi, GFP_KERNEL);//分配内存

if(!spi) {

dev_err(dev, "cannot alloc spi_device\n");

spi_master_put(master); //增加主机引用计数

returnNULL;

}

spi->master = master;    //设置spi主机

spi->dev.parent = dev;   //spi设备文件的父设备为spi主机设备文件的父设备

spi->dev.bus = &spi_bus_type;    //总线类型

spi->dev.release = spidev_release;   //释放方法

device_initialize(&spi->dev);    //设备初始化

returnspi;

}

EXPORT_SYMBOL_GPL(spi_alloc_device);

3.2 添加spi设备

intspi_add_device(structspi_device *spi)

{

staticDEFINE_MUTEX(spi_add_lock);

structdevice *dev = spi->master->dev.parent;

structdevice *d;

intstatus;

if(spi->chip_select >= spi->master->num_chipselect) {

dev_err(dev, "cs%d >= max %d\n",spi->chip_select,spi->master->num_chipselect);

return-EINVAL;

}

dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->master->dev),spi->chip_select);

mutex_lock(&spi_add_lock);

d = bus_find_device_by_name(&spi_bus_type, NULL, dev_name(&spi->dev));   //查找总线上的spi设备

if(d != NULL) {//判断是否已经在使用了

dev_err(dev, "chipselect %d already in use\n",spi->chip_select);

put_device(d);

status = -EBUSY;

gotodone;

}

status = spi_setup(spi);    //调用spi主机 setup方法

if(status < 0) {

dev_err(dev, "can't setup %s, status %d\n",dev_name(&spi->dev), status);

gotodone;

}

status = device_add(&spi->dev);  //添加设备

if(status < 0)

dev_err(dev, "can't add %s, status %d\n",dev_name(&spi->dev), status);

else

dev_dbg(dev, "registered child %s\n", dev_name(&spi->dev));

done:

mutex_unlock(&spi_add_lock);

returnstatus;

}

EXPORT_SYMBOL_GPL(spi_add_device);

3.2.1 spi setup方法

intspi_setup(structspi_device *spi)

{

unsigned    bad_bits;

intstatus;

bad_bits = spi->mode & ~spi->master->mode_bits;    //比较spi设备的模式和spi主机支持的模式

if(bad_bits) {//存在不支持的模式

dev_err(&spi->dev, 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值