(一)spi总线设备驱动框架:
app: open() read() write()
------------------------------------------------------------------
系统调用
--------------------------------------------------------------------
spi设备驱动:xxx_open() 、xxx_write()、xxx_read()
--------------------------------------------------------------------
核心层: 向上提供统一的接口,向下提供管理函数
--------------------------------------------------------------------
spi总线驱动
---------------------------------------------------------------------
硬件:spi控制器1、spi控制器2... | 从设备1、从设备2....
(二)spi_s3c24xx.c文件分析:(\drivers\spi)
这个文件用到了 platform总线驱动模型,在platform_driver结构体的probe()函数中注册了spi总线驱动,既然内核已经帮助我们完成了spi总线驱动模型,那么我们要做的就是编写spi设备驱动了,当然,我们也可以不用内核提供的总线驱动,自己编写spi总线设备驱动。
s3c24xx_spi_init()
platform_driver_register
driver_register
bus_add_driver // bus_add_driver - Add a driver to the bus.
kobject_register
driver_attach // try to bind driver to devices.
bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
//__driver_attach是一个函数指针,在该函数里,会调用driver_probe_device()函数
driver_probe_device()
match()
really_probe()
drv->probe() //就会调用到s3c24xx_spi_probe(),在该函数里面我们做真正的工作。
klist_iter_init_node
klist_add_tail
module_add_driver
driver_add_attrs
(三)s3c24xx_spi_probe() 函数分析:
struct spi_master *master;
struct spi_board_info *bi; //定义相关变量
spi_alloc_master()
spi_master_get_devdata()
spi_master_get()
相关设置
spi_bitbang_start() /* register our spi controller */
spi_new_device() /* register all the devices associated */
spi_master_put(hw->master);; //和spi_master_get()相对
3.1)spi_bitbang_start() 函数分析:
spi_register_master //总线驱动
class_device_add
class_device_get
class_device_add_attrs
class_device_add_groups
make_deprecated_class_device_links
list_add_tail
list_for_each_entry
scan_boardinfo
list_for_each_entry // chip->bus_num == master->bus_num
spi_new_device
device_register
device_add
device_add_attrs
bus_add_device //add device to bus
bus_attach_device //Try to attach to driver.
device_attach // try to attach device to a driver
bus_for_each_drv(dev->bus, NULL, dev, __device_attach)
__device_attach(struct device_driver * drv, void * data)
driver_probe_device(drv, dev);
drv->bus->match
really_probe
drv->probe
list_add_tail
list_for_each_entry
由此可见,当我们注册spi总线驱动时,会自动的向内核添加设备。
(四)spi设备驱动程序编写:
xxx_spi_dev.c
1、设置spi_board_info结构体
2、spi_register_board_info()
spi_match_master_to_boardinfo //master->bus_num == bi->bus_num,看数量是否相等
spi_new_device
xxx_spi_drv.c //纯软件概念,它的作用就是提供设备读写函数,设备挂接到总线上
1、分配 spi_driver 结构体
2、设置
3、注册 spi_register_driver()
注:to_spi_device(struct device *dev) 得到 spi_device 结构体,spi_read()和spi_write()函数有可能要用到
probe函数传进来的参数就是 spi_device结构体指针。
核心层提供的消息传递函数为:spi_read()、spi_write()。
(五)spi总线驱动程序编写(一般内核都有提供,不过我们也可以自己编写)
xxx_spi_bus.c
1、分配 spi_master 结构体
2、设置 结构体成员
struct class_device cdev;
s16 bus_num;
u16 num_chipselect;
int (*setup)(struct spi_device *spi);
int (*transfer)(struct spi_device *spi,struct spi_message *mesg);
//这个成员函数很重要,spi核心层提供的读写函数最终都会调用到它。
void (*cleanup)(struct spi_device *spi);
3、注册 spi_register_master()