一 linux spi子系统(框架)

本文详细介绍了Linux SPI子系统的各个组件,包括SPI设备、板级设备、设备驱动、主机、总线、消息和传输的原理及操作。内容涵盖设备添加、匹配、驱动注册与注销,以及SPI读写操作的API实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.spi设备

struct spi_device {
	struct device	dev;	//设备文件
	struct spi_master	*master;	//spi主机
	u32	max_speed_hz;	//最大速率
	u8	chip_select;	//片选
	u8	mode;	//模式
	u8	bits_per_word;	//一个字有多少位
	int	irq;	//中断号
	void	*controller_state;	//控制器状态
	void	*controller_data;	//控制器数据
	char	modalias[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

struct spi_device *spi_new_device(struct spi_master *master,struct spi_board_info *chip)
{
	struct spi_device	*proxy;
	int	status;
	
	proxy = spi_alloc_device(master);	//3.1 spi设备初始化
	if (!proxy)
		return NULL;
	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设备引用计数
		return NULL;
	}
	return proxy;
}
EXPORT_SYMBOL_GPL(spi_new_device);

 

3.1.分配spi设备

struct spi_device *spi_alloc_device(struct spi_master *master)
{
	struct spi_device	*spi;
	struct device		*dev = master->dev.parent;

	if (!spi_master_get(master))	//判断spi主机是否存在
		return NULL;
	spi = kzalloc(sizeof *spi, GFP_KERNEL);	//分配内存
	if (!spi) {
		dev_err(dev, "cannot alloc spi_device\n");
		spi_master_put(master);	//增加主机引用计数
		return NULL;
	}
	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);	//设备初始化
	return spi;
}
EXPORT_SYMBOL_GPL(spi_alloc_device);


3.2 添加spi设备

int spi_add_device(struct spi_device *spi)
{
	static DEFINE_MUTEX(spi_add_lock);
	struct device *dev = spi->master->dev.parent;
	struct device *d;
	int status;

	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;
		goto done;
	}
	status = spi_setup(spi);	//调用spi主机 setup方法
	if (status < 0) {
		dev_err(dev, "can't setup %s, status %d\n",dev_name(&spi->dev), status);
		goto done;
	}
	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);
	return status;
}
EXPORT_SYMBOL_GPL(spi_add_device);


3.2.1 spi setup方法

int spi_setup(struct spi_device *spi)
{
	unsigned	bad_bits;
	int	status;
	bad_bits = spi->mode & ~spi->master->mode_bits;	//比较spi设备的模式和spi主机支持的模式
	if (bad_bits) {	//存在不支持的模式
		dev_err(&spi->dev, "setup: unsupported mode bits %x\n",bad_bits);
		return -EINVAL;
	}
	if (!spi->bits_per_word)	//若没设置设备的每个字含多少位
		spi->bits_per_word = 8;	//则默认设置为8

	status = spi->master->setup(spi);	//调用spi主机的setup方法

	dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s""%u bits/w, %u Hz max --> %d\n",
			(int) (spi->mode & (SPI_CPOL | SPI_CP
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值