日期:2014-05-16  浏览次数:20743 次

一 linux spi子系统(框架)

一.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;
	ba