0 总线私有资源
struct subsys_private {
struct kset subsys;
struct kset *devices_kset;
struct list_head interfaces;
struct mutex mutex;
struct kset *drivers_kset;
struct klist klist_devices;
struct klist klist_drivers;
struct blocking_notifier_head bus_notifier;
unsigned int drivers_autoprobe:1;
struct bus_type *bus;
struct kset glue_dirs;
struct class *class;
};
1 SPI的主机和从机通信接口,也就是SPI总线
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;
};
2 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的匹配
};
3 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;
};
4 SPI主控制器 :
struct spi_master {
struct device dev; //驱动的设备接口
struct list_head list; //SPI控制器的链表头
s16 bus_num; //总线号
u16 num_chipselect; //SPI设备的片选号
u16 dma_alignment; //dma模式
u16 mode_bits;
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 */
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);
int (*transfer)(struct spi_device *spi,
struct spi_message *mesg);
};
struct spi_transfer {
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
};
6 spi 对SPI控制器的抽象,SPI控制器接口
struct spi_message {
struct list_head transfers; //挂接在本 message下的transfers链表头
struct spi_device *spi; //加到传输队列中的spi设备
unsigned is_dma_mapped:1; //DMA传输控制位
void (*complete)(void *context); //传输完成 回调函数
void *context; //complete函数的参数
unsigned actual_length; //所有成功传输字段的总长度
int status; //传输成功返回0,否则返回错误
struct list_head queue; //链表字段queue用于把该挂在代表控制器的spi_message的queue字段上,
void *state;
};
void spi_message_init(structspi_message *m); 初始化
spi_message_add_tail() 向 spi_message 添加 spi_transfers
spi_async() 准备好了spi_message,就可以使用spi_async来向SPI系统提交了
异步通信,提交之后马上返回,使用spi_async 需要注意的是:
在complete()没有返回之前不要轻易访问你提交的 spi_transfer 中的buffer。
也不要释放SPI系统正在使用的buffer,一谈你的complete返回了,这些buffe就又
不是你的了
使用完成回调机制有些复杂,可以使用SPI系统提供的另一种同步版本
; spi_sync
int spi_sync(struct spi_device *spi,struct spi_message *message);
因为是同步的,spi_sync 提交完 spi_message 后不会立即返回,会一直等待被处理,
一旦返回就可以重新使用buffer了,
7
在SPI控制器里面最常用的用来处理传输的结构体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);
};