SPI子系统驱动架构 - 驱动框架
来源:互联网 发布:网络推广效果评估 编辑:程序博客网 时间:2024/06/12 19:42
文章系列
SPI子系统驱动架构 - 简介
SPI子系统驱动架构 - 驱动框架
SPI子系统驱动架构 - 具体实现
SPI驱动框架
spi驱动框架如图所示,驱动框架分用户层、核心层和硬件层,用户层主要向上层开发人员提供接口,硬件层是spi模块和spi设备的硬件描述,我们主要认识核心层spi-core。
核心层中分设备层和控制器层,设备层提供spi从设备的注册,控制器层提供芯片spi控制模块的注册,一般控制器层的驱动在内核中都已经提供了,我们主要是编写自己的设备驱动,具体编写就可以参考别的器件的驱动。从图中我们可以看到控制器层有spi_master和spi_bitbang两个结构体代表控制器模块,区别在于spi_bitbang会提供一种机制,而这种机制是spi_master注册时没有的,具体下文介绍。在整个设备的注册流程中,系统驱动后会先注册控制器的驱动,然后会注册挂在spi总线上的设备层的驱动。
spi驱动的代码都在drivers/spi/目录下,进去后感觉乱糟糟的,不像i2c那样分的清楚,不过代码看多了之后就清楚了,呵呵。主要的文件是spi.c和spi-bitbang.c,这些都是核心文件,spidev.c是一个设备层的文件,其他大多是控制器代码文件。
SPI主控制器(总线)驱动介绍
spi主控制器的注册是通过platform bus来进行的,在系统初始化时会进行spi的platform_device的注册,然后具体SoC上的spi模块的platform_driver的注册在各自的文件中,注册匹配后就会进入probe函数来进行spi主控制器spi_master的注册,相关结构体下面介绍
结构体介绍
spi_master定义了SPI主控制器,spi_transfer 和spi_message 是数据传输时使用的结构体,spi_transfer的链表挂在spi_message 的链表中,所以每次数据传输时,一个spi_message 会有多个spi_transfer来进行传输,每次进行数据传输时,都会检查spi_message 的状态,看是否合适进行传输
struct spi_master { struct device dev; struct list_head list; s16 bus_num; /* chipselects will be integral to many controllers; some others * might use board-specific GPIOs. */ u16 num_chipselect; /* some SPI controllers pose alignment requirements on DMAable * buffers; let protocol drivers know about these requirements. */ u16 dma_alignment; /* spi_device.mode flags understood by this controller driver */ u16 mode_bits; /* bitmask of supported bits_per_word for transfers */ u32 bits_per_word_mask; /* limits on transfer speed */ u32 min_speed_hz; u32 max_speed_hz; /* other constraints relevant to this driver */ u16 flags; /* * on some hardware transfer size may be constrained * the limit may depend on device transfer settings */ size_t (*max_transfer_size)(struct spi_device *spi); /* lock and mutex for SPI bus locking */ spinlock_t bus_lock_spinlock; struct mutex bus_lock_mutex; /* flag indicating that the SPI bus is locked for exclusive use */ bool bus_lock_flag; int (*setup)(struct spi_device *spi); int (*transfer)(struct spi_device *spi, struct spi_message *mesg); /* called on release() to free memory provided by spi_master */ void (*cleanup)(struct spi_device *spi); bool (*can_dma)(struct spi_master *master, struct spi_device *spi, struct spi_transfer *xfer); bool queued; struct kthread_worker kworker; struct task_struct *kworker_task; struct kthread_work pump_messages; spinlock_t queue_lock; struct list_head queue; struct spi_message *cur_msg; bool idling; bool busy; bool running; bool rt; bool auto_runtime_pm; bool cur_msg_prepared; bool cur_msg_mapped; struct completion xfer_completion; size_t max_dma_len; int (*prepare_transfer_hardware)(struct spi_master *master); int (*transfer_one_message)(struct spi_master *master, struct spi_message *mesg); int (*unprepare_transfer_hardware)(struct spi_master *master); int (*prepare_message)(struct spi_master *master, struct spi_message *message); int (*unprepare_message)(struct spi_master *master, struct spi_message *message); int (*spi_flash_read)(struct spi_device *spi, struct spi_flash_read_message *msg); /* * These hooks are for drivers that use a generic implementation * of transfer_one_message() provied by the core. */ void (*set_cs)(struct spi_device *spi, bool enable); int (*transfer_one)(struct spi_master *master, struct spi_device *spi, struct spi_transfer *transfer); void (*handle_err)(struct spi_master *master, struct spi_message *message); /* gpio chip select */ int *cs_gpios; /* statistics */ struct spi_statistics statistics; /* DMA channels for use with core dmaengine helpers */ struct dma_chan *dma_tx; struct dma_chan *dma_rx; /* dummy data for full duplex devices */ void *dummy_rx; void *dummy_tx; int (*fw_translate_cs)(struct spi_master *master, unsigned cs);};
struct spi_transfer { const void *tx_buf; void *rx_buf; unsigned len; dma_addr_t tx_dma; dma_addr_t rx_dma; struct sg_table tx_sg; struct sg_table rx_sg; unsigned cs_change:1; unsigned tx_nbits:3; unsigned rx_nbits:3; u8 bits_per_word; u16 delay_usecs; u32 speed_hz; struct list_head transfer_list;};
struct spi_message { struct list_head transfers; struct spi_device *spi; unsigned is_dma_mapped:1; /* completion is reported through a callback */ void (*complete)(void *context); void *context; unsigned frame_length; unsigned actual_length; int status; struct list_head queue; void *state; /* list of spi_res reources when the spi message is processed */ struct list_head resources;};
spi_bitbang是另一套主控制器结构体,它提供一种数据传输机制,struct spi_bitbang其实就是包装了spi_maser
struct spi_bitbang { spinlock_t lock; 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主控制器设备驱动注册与卸载函数
extern int spi_register_master(struct spi_master *master);extern void spi_unregister_master(struct spi_master *master);
现在进行spi主控制器设备的注册一般使用下面的函数,对应于struct spi_bitbang,使用这个函数进行注册会开启开启线程来进行spi数据传输
extern int spi_bitbang_start(struct spi_bitbang *spi);extern void spi_bitbang_stop(struct spi_bitbang *spi);
SPI设备驱动介绍
结构体介绍
spi_device 等同于驱动模型中的device
struct spi_device { struct device dev; struct spi_master *master; u32 max_speed_hz; u8 chip_select; u8 bits_per_word; u16 mode; int irq; void *controller_state; void *controller_data; char modalias[SPI_NAME_SIZE]; int cs_gpio; /* chip select gpio */ /* the statistics */ struct spi_statistics statistics;};
spi_driver 等同于驱动模型中的driver
struct spi_driver { const struct spi_device_id *id_table; int (*probe)(struct spi_device *spi); int (*remove)(struct spi_device *spi); void (*shutdown)(struct spi_device *spi); struct device_driver driver;};
函数介绍
spi从设备驱动driver注册与卸载函数
spi_register_driver(driver)spi_unregister_driver()
spi从设备device注册与卸载函数
extern struct spi_device *spi_alloc_device(struct spi_master *master);extern intspi_add_device(struct spi_device *spi);extern struct spi_device *spi_new_device(struct spi_master *, struct spi_board_info *);extern void spi_unregister_device(struct spi_device *spi);
- SPI子系统驱动架构 - 驱动框架
- SPI子系统驱动架构 - 简介
- SPI子系统驱动架构 - 具体实现
- I2C子系统驱动架构 - 驱动框架
- linux spi驱动开发学习(一)-----spi子系统架构
- 视频驱动V4L2子系统驱动架构 - 驱动框架
- linux spi子系统驱动分析
- linux spi子系统驱动分析
- linux spi子系统驱动分析
- linux spi子系统驱动分析
- linux spi子系统驱动分析
- linux spi子系统驱动分析
- linux spi子系统驱动分析
- linux spi子系统驱动分析
- Linux SPI 子系统 驱动设计
- spi驱动框架分析
- spi驱动框架
- 2.6.24 spi 驱动,linux spi子系统驱动分析
- Linux文件系统
- C语言输入输出函数
- transform知识【学习总结】
- Android下面打印进程函数调用堆栈(dump backtrace)的方法(http://blog.sina.com.cn/happychang2007)
- 记忆化搜索简介
- SPI子系统驱动架构 - 驱动框架
- jQueryValidate 插件(表单验证功能)
- java this 子类调父类,父类再调用子类已覆盖的方法及属性(又一次理解)
- android WIFI to unity
- 数组特点
- 史上最严高考年,指纹、人脸识别成焦点
- -TreeMap
- XtraGrid 的格式设置
- Description Resource Path Location Type Java compiler level does not match the version of the insta