spi的驱动框架主要分为:
cpu<—platform bus—>spi master 端 <-----spi bus—>spi slave 端
spi master 指的是spi控制器,spi master device是平台设备,spi master driver是平台驱动,它们都挂载在平台总线上
spi slave指的是spi设备,spi device和spi driver分别挂载在spi bus上
drivers/spi/spi.c是spi的主要框架部分,实现的代码跟平台无关:
struct bus_type spi_bus_type = {
.name = "spi",
.dev_groups = spi_dev_groups,
.match = spi_match_device,
.uevent = spi_uevent,
};
static int __init spi_init(void)
{
status = bus_register(&spi_bus_type); //注册spi bus
}
注册spi 控制器设备,跟平台相关,通过解析dts:
platform_device_register(&sprd_spi_controller_device[0]);
注册spi控制器驱动,这里以amlogic的spi控制器为例:
//drivers/amlogic/spicc/spicc.c
static struct platform_driver spicc_driver = {
.probe = spicc_probe,
.remove = spicc_remove,
.suspend = spicc_suspend,
.resume = spicc_resume,
.driver = {
.name = "spicc",
.of_match_table = spicc_of_match,
.owner = THIS_MODULE,
},
};
static int __init spicc_init(void)
{
return platform_driver_register(&spicc_driver);
}
static int spicc_probe(struct platform_device *pdev)
{
...
master = spi_alloc_master(&pdev->dev, sizeof(*spicc)); //spi控制器设备
master->dev.of_node = pdev->dev.of_node; //spi控制器设备相关的信息
master->bus_num = spicc->device_id;
master->setup = spicc_setup; //实际调用的是spi具体的控制器驱动
master->transfer = spicc_transfer;
master->cleanup = spicc_cleanup;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
spi_register_master(master); //注册master
}
每个master都对应一个bus num。
注册spi slave设备,由dts解析得到,dts会指定spi slave 挂载在哪个bus num下,由bus num就可以得到对应的spi master 了:
//1.由dts中描述的slave device挂载的bus_num得到master
struct spi_master * spi_busnum_to_master(u16 bus_num)
//2. 在该master下alloc一个设备
struct spi_device *spi_alloc_device(struct spi_master *master)
//3.注册设备
spi_add_device()
struct spi_device {
struct device dev;
struct spi_master *master; //该设备在哪个master下
u32 max_speed_hz;
u8 chip_select;
u8 bits_per_word;
u16 mode;
...
}
注册spi slave驱动:
spi_register_driver(&rv3049_driver);
spi slave设备驱动只是实现了数据的逻辑操作,不实现接口相关,当要进行接口数据传输时,调用struct spi_device中的master进行,这样就能做到驱动和接口解耦,这样驱动更通用,在不同的总线上都可以使用。