既然知道了协议了,那么就可以开始去瞧瞧linux kenerl中的spi的驱动代码了,代码中有很多的结构体,还是对主要的结构体先做个了解吧,那样才可以很好的理解驱动。主要是include/linux/spi.h

 

首先是SPI的主机和从机通信接口,也就是SPI总线,



extern struct bus_type spi_bus_type;

bus_type定义在linux/device.h中

 



struct bus_type {
const char *name; //总线的名字
struct bus_attribute *bus_attrs;
struct device_attribute *dev_attrs;
struct driver_attribute *drv_attrs;

//总线上的device和driver的匹配,匹配成功返回非0值
int (*match)(struct device *dev, struct device_driver *drv);
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
//当新的device或driver加到总线上的时候,调用driver中的probe函数经行匹配
int (*probe)(struct device *dev);
int (*remove)(struct device *dev);
void (*shutdown)(struct device *dev);
int (*suspend)(struct device *dev, pm_message_t state);
int (*resume)(struct device *dev);
const struct dev_pm_ops *pm;
struct subsys_private *p;
};

 

SPI设备




struct spi_device {
struct device dev;
struct spi_master *master; //SPI控制器
u32 max_speed_hz; //最大时钟频率
u8 chip_select; //片选
u8 mode; //SPI模式
#define SPI_CPHA 0x01 /* clock phase */
#define SPI_CPOL 0x02 /* clock polarity */
#define SPI_MODE_0 (0|0) /* (original MicroWire) */
#define SPI_MODE_1 (0|SPI_CPHA)
#define SPI_MODE_2 (SPI_CPOL|0)
#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
#define SPI_CS_HIGH 0x04 /* chipselect active high? */
#define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */
#define SPI_3WIRE 0x10 /* SI/SO signals shared */
#define SPI_LOOP 0x20 /* loopback mode */
#define SPI_NO_CS 0x40 /* 1 dev/bus, no chipselect */
#define SPI_READY 0x80 /* slave pulls low to pause */
u8 bits_per_word; //一次传输的bits,可以是8、16、32,默认是8
int irq;
void *controller_state;
void *controller_data;
char modalias[SPI_NAME_SIZE]; //别名,用于device和driver的匹配
};

 

 

SPI驱动

 



struct spi_driver {
const struct spi_device_id *id_table;
int (*probe)(struct spi_device *spi); //绑定驱动和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_driver driver;
};

 

SPI主控制器

 



struct spi_master {
struct device dev; //驱动的设备接口
struct list_head list; //SPI控制器的链表头
s16 bus_num; //总线号

/* chipselects will be integral to many controllers; some others
* might use board-specific GPIOs.
*/
u16 num_chipselect; //SPI设备的片选号
u16 dma_alignment; //dma模式

/* spi_device.mode flags understood by this controller driver */
u16 mode_bits;

/* other constraints relevant to this driver */
u16 flags;

#define SPI_MASTER_HALF_DUPLEX BIT(0) /* can't do full duplex */
#define SPI_MASTER_NO_RX BIT(1) /* can't do buffer read */
#define SPI_MASTER_NO_TX BIT(2) /* can't do buffer write */

/* lock and mutex for SPI bus locking */
spinlock_t bus_lock_spinlock;
struct mutex bus_lock_mutex;

bool bus_lock_flag;
int (*setup)(struct spi_device *spi); //更新SPI设备的模式和SPI设备的采样时钟
int (*transfer)(struct spi_device *spi, //添加一个消息到控制器的传输队列
struct spi_message *mesg);
void (*cleanup)(struct spi_device *spi);

};

 

SPI传输

 



struct spi_transfer {
/* it's ok if tx_buf == rx_buf (right?)
* for MicroWire, one buffer must be null
* buffers must work with dma_*map_single() calls, unless
* spi_message.is_dma_mapped reports a pre-existing mapping
*/

const void *tx_buf; //要写的数据
void *rx_buf; //要读的数据
unsigned len; //数据长度



dma_addr_t tx_dma; //tx_buf的DMA地址
dma_addr_t rx_dma; //rx_buf的DMA地址

unsigned cs_change:1;
u8 bits_per_word; //传输的bytes数,不选就用默认的
u16 delay_usecs; //微秒延时,用以传输数据后,改变片选信号前
u32 speed_hz; //传输速率,不选就用默认的

struct list_head transfer_list; //传输链表,用以传输spi_message

};

 

SPI消息

 



struct spi_message {
struct list_head transfers; //

struct spi_device *spi; //加到传输队列中的spi设备
unsigned is_dma_mapped:1; //DMA传输控制位

/* completion is reported through a callback */
void (*complete)(void *context); //传输完成
void *context; //complete函数的参数
unsigned actual_length; //所有成功传输字段的总长度
int status; //传输成功返回0,否则返回错误



/* for optional use by whatever driver currently owns the
* spi_message ... between calls to spi_async and then later
* complete(), that's the spi_master controller driver.
*/

struct list_head queue;
void *state;

};

 

SPI bitbang

 



struct spi_bitbang {
struct workqueue_struct *workqueue;
struct work_struct work;

spinlock_t lock;
struct list_head queue;

u8 busy;
u8 use_dma;
u8 flags; /* extra spi->mode support */

struct spi_master *master;

/* setup_transfer() changes clock and/or wordsize to match settings
* for this transfer; zeroes restore defaults from spi_device.
*/
int (*setup_transfer)(struct spi_device *spi,
struct spi_transfer *t);

void (*chipselect)(struct spi_device *spi, int is_on);
#define BITBANG_CS_ACTIVE 1 /* normally nCS, active low */
#define BITBANG_CS_INACTIVE 0



/* txrx_bufs() may handle dma mapping for transfers that don't
* already have one (transfer.{tx,rx}_dma is zero), or use PIO
*/
int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t);

/* txrx_word[SPI_MODE_*]() just looks like a shift register */
u32 (*txrx_word[4])(struct spi_device *spi,
unsigned nsecs,
u32 word, u8 bits);

};

SPI控制器里面最常用的用来处理传输的结构体spi_bitbang了。

 

SPI borad info

struct spi_board_info {
/* the device name and module name are coupled, like platform_bus;
* "modalias" is normally the driver name.
*
* platform_data goes to spi_device.dev.platform_data,
* controller_data goes to spi_device.controller_data,
* irq is copied too
*/
char modalias[SPI_NAME_SIZE];
const void *platform_data;
void *controller_data;
int irq;

/* slower signaling on noisy or low voltage boards */
u32 max_speed_hz;


/* bus_num is board specific and matches the bus_num of some
* spi_master that will probably be registered later.
*
* chip_select reflects how this chip is wired to that master;
* it's less than num_chipselect.
*/
u16 bus_num;
u16 chip_select;

/* mode becomes spi_device.mode, and is essential for chips
* where the default of SPI_CS_HIGH = 0 is wrong.
*/
u8 mode;

/* ... may need additional spi_device chip config data here.
* avoid stuff protocol drivers can set; but include stuff
* needed to behave without being bound to a driver:
* - quirks like clock rate mattering when not selected
*/
};

       控制器里会读取borad info里的参数

 

SPI gpio_platform_data

 



struct spi_gpio_platform_data {
unsigned sck;
unsigned mosi;
unsigned miso;

u16 num_chipselect;

};

GPIO模拟的,所以还是记录下这个从platform传进来的管脚号。


       OK,对于SPI用到的结构体基本上已经介绍完了,那么接下来就介绍其主要函数了。