SPI子系统驱动架构 – 简介
SPI子系统驱动架构 – 驱动框架
SPI子系统驱动架构 – 具体实现
SPI设备注册流程同I2C驱动的设备注册流程类似,遵从platform_bus_register->spi_bus_register->spi设备的流程
spi主控制器设备是挂载在platform总线上的,所以要通过platform bus子系统的注册方法来注册设备,遵从device-bus-driver的规律,首先要进行platform_device的注册,这是通过在系统初始化的时候,根据设备树的解析来进行的,具体参考linux设备树的解释。
接着进行platform_driver的注册,这是通过函数platform_driver_register()来进行注册,之后匹配成功后就进入driver->probe函数,‘probe’函数会做一些初始化工作,主要是初始化结构体struct spi_master和struct spi_bitbang,之后就进入spi主控制器设备的注册函数,在文章系列2中有介绍相关函数,本文主要介绍函数spi_bitbang_start
int spi_bitbang_start(struct spi_bitbang *bitbang)
{
struct spi_master *master = bitbang->master;
int ret;
if (!master || !bitbang->chipselect)
return -EINVAL;
spin_lock_init(&bitbang->lock);
if (!master->mode_bits)
master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags;
if (master->transfer || master->transfer_one_message)
return -EINVAL;
master->prepare_transfer_hardware = spi_bitbang_prepare_hardware;------初始化相关函数字段
master->unprepare_transfer_hardware = spi_bitbang_unprepare_hardware;--初始化相关函数字段
master->transfer_one_message = spi_bitbang_transfer_one;---------------初始化相关函数字段
if (!bitbang->txrx_bufs) {
bitbang->use_dma = 0;
bitbang->txrx_bufs = spi_bitbang_bufs;
if (!master->setup) {
if (!bitbang->setup_transfer)
bitbang->setup_transfer =
spi_bitbang_setup_transfer;
master->setup = spi_bitbang_setup;----------初始化相关函数字段
master->cleanup = spi_bitbang_cleanup;------初始化相关函数字段
}
}
/* driver may get busy before register() returns, especially
* if someone registered boardinfo for devices
*/
ret = spi_register_master(spi_master_get(master));-----主控制器注册
if (ret)
spi_master_put(master);
return 0;
}
上面的一些‘初始化相关函数字段‘工作,是函数默认的用法,当然自己有特殊需求可以自定义另一套函数,下面看看函数spi_register_master
int spi_register_master(struct spi_master *master)
{
static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1);
struct device *dev = master->dev.parent;
struct boardinfo *bi;
int status = -ENODEV;
int dynamic = 0;
if (!dev)
return -ENODEV;
status = of_spi_register_master(master);
if (status)
return status;
/* even if it's just one always-selected device, there must * be at least one chipselect */
if (master->num_chipselect == 0)
return -EINVAL;
if ((master->bus_num < 0) && master->dev.of_node)
master->bus_num = of_alias_get_id(master->dev.of_node, "spi");
/* convention: dynamically assigned bus IDs count down from the max */
if (master->bus_num < 0) {
/* FIXME switch to an IDR based scheme, something like * I2C now uses, so we can't run out of "dynamic" IDs */
master->bus_num = atomic_dec_return(&dyn_bus_id);
dynamic = 1;
}
spin_lock_init(&master->bus_lock_spinlock);
mutex_init(&master->bus_lock_mutex);
master->bus_lock_flag = 0;
init_completion(&master->xfer_completion);
if (!master->max_dma_len)
master->max_dma_len = INT_MAX;
/* register the device, then userspace will see it. * registration fails if the bus ID is in use. */
dev_set_name(&master->dev, "spi%u", master->bus_num);
status = device_add(&master->dev);-------spi主控制器设备注册
if (status < 0)
goto done;
dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev),
dynamic ? " (dynamic)" : "");
/* If we're using a queued driver, start the queue */
if (master->transfer)
dev_info(dev, "master is unqueued, this is deprecated\n");
else {
status = spi_master_initialize_queue(master);------初始化spi工作队列,下面会介绍此函数
if (status) {
device_del(&master->dev);
goto done;
}
}
mutex_lock(&board_lock);
list_add_tail(&master->list, &spi_master_list);
list_for_each_entry(bi, &board_list, list)
spi_match_master_to_boardinfo(master, &bi->board_info);
mutex_unlock(&board_lock);
/* Register devices from the device tree and ACPI */
of_register_spi_devices(master);-------spi从设备进行device注册
acpi_register_spi_devices(master);
done:
return status;
}
spi主控制器注册完成后,就会把挂载在总线上的从设备进行device注册,在函数of_register_spi_devices中进行,下面主要介绍上面提及的函数spi_master_initialize_queue
static int spi_master_initialize_queue(struct spi_master *master)
{
int ret;
master->transfer = spi_queued_transfer;---------初始化字段master->transfer,重要!
if (!master->transfer_one_message)--------------初始化字段transfer_one_message
master->transfer_one_message = spi_transfer_one_message;
/* Initialize and start queue */
ret = spi_init_queue(master);-------------------初始化工作队列
if (ret) {
dev_err(&master->dev, "problem initializing queue\n");
goto err_init_queue;
}
master->queued = true;
ret = spi_start_queue(master);------------------队列开始工作
if (ret) {
dev_err(&master->dev, "problem starting queue\n");
goto err_start_queue;
}
return 0;
err_start_queue:
spi_destroy_queue(master);
err_init_queue:
return ret;
}
上面的一些初始化字段工作都是为后面的数据传输过程做准备,在‘SPI数据传输流程‘这一节会有详细介绍,在上面的spi_init_queue这一初始化工作中会初始化工作队列函数,如下
init_kthread_work(&master->pump_messages, spi_pump_messages);
其中函数spi_pump_messages就是一直进行数据传输的主要工作详情见‘SPI数据传输流程‘这一节
在文章系列2中关于spi从设备device注册函数主要有3个,其中spi_new_device会分别调用spi_alloc_device和spi_add_device这两个函数,这两函数分别实现不同的功能,如下介绍
struct spi_device *spi_alloc_device(struct spi_master *master)
{
struct spi_device *spi;
if (!spi_master_get(master))
return NULL;
spi = kzalloc(sizeof(*spi), GFP_KERNEL);
if (!spi) {
spi_master_put(master);
return NULL;
}
spi->master = master;
spi->dev.parent = &master->dev;
spi->dev.bus = &spi_bus_type;--------设置总线类型
spi->dev.release = spidev_release;
spi->cs_gpio = -ENOENT;
device_initialize(&spi->dev);
return spi;
}
int spi_add_device(struct spi_device *spi)
{
static DEFINE_MUTEX(spi_add_lock);
struct spi_master *master = spi->master;
struct device *dev = master->dev.parent;
int status;
/* Chipselects are numbered 0..max; validate. */
if (spi->chip_select >= master->num_chipselect) {
dev_err(dev, "cs%d >= max %d\n",
spi->chip_select,
master->num_chipselect);
return -EINVAL;
}
/* Set the bus ID string */
spi_dev_set_name(spi);
/* We need to make sure there's no other device with this
* chipselect **BEFORE** we call setup(), else we'll trash
* its configuration. Lock against concurrent add() calls.
*/
mutex_lock(&spi_add_lock);
status = bus_for_each_dev(&spi_bus_type, NULL, spi, spi_dev_check);
if (status) {
dev_err(dev, "chipselect %d already in use\n",
spi->chip_select);
goto done;
}
if (master->cs_gpios)
spi->cs_gpio = master->cs_gpios[spi->chip_select];
/* Drivers may modify this initial i/o setup, but will
* normally rely on the device being setup. Devices
* using SPI_CS_HIGH can't coexist well otherwise...
*/
status = spi_setup(spi);
if (status <0) {
dev_err(dev, "can't setup %s, status %d\n",
dev_name(&spi->dev), status);
goto done;
}
/* Device may be bound to an active driver when this returns */
status = device_add(&spi->dev);-------设备注册
if (status <0)
dev_err(dev, "can't add %s, status %d\n",
dev_name(&spi->dev), status);
else
dev_dbg(dev, "registered child %s\n", dev_name(&spi->dev));
done:
mutex_unlock(&spi_add_lock);
return status;
}
完成spi主控制器的device注册后,就driver的注册,注册函数如下
int spi_register_driver(struct spi_driver *sdrv)
{
sdrv->driver.bus = &spi_bus_type;
if (sdrv->probe)
sdrv->driver.probe = spi_drv_probe;
if (sdrv->remove)
sdrv->driver.remove = spi_drv_remove;
if (sdrv->shutdown)
sdrv->driver.shutdown = spi_drv_shutdown;
return driver_register(&sdrv->driver);--------驱动注册
}
上面的工作匹配完成后,就进入spi_driver->probe函数,一般此函数的功能是向用户空间提供操作接口来对spi设备进行读写操作,具体数据传输流程下面介绍
SPI数据传输流程在include/linux/spi/spi.h中定义了许多数据传输函数,列举如下:
一个数据传输总图
spi_write(struct spi_device *spi, const void *buf, size_t len)
spi_read(struct spi_device *spi, void *buf, size_t len)
spi_w8r8(struct spi_device *spi, u8 cmd)
spi_w8r16(struct spi_device *spi, u8 cmd)
spi_w8r16be(struct spi_device *spi, u8 cmd)
.
.
.
extern int spi_setup(struct spi_device *spi);
extern int spi_async(struct spi_device *spi, struct spi_message *message);
extern int spi_async_locked(struct spi_device *spi,struct spi_message *message);
extern int spi_sync(struct spi_device *spi, struct spi_message *message);
extern int spi_sync_locked(struct spi_device *spi, struct spi_message *message);
extern int spi_bus_lock(struct spi_master *master);
extern int spi_bus_unlock(struct spi_master *master);
总结上面所有的数据传输函数,总体上分两种:同步传输和异步传输,对应的函数为:spi_sync和spi_async,而这两个函数最终都会调用函数__spi_async
static int __spi_async(struct spi_device *spi, struct spi_message *message)
{
struct spi_master *master = spi->master;
message->spi = spi;
trace_spi_message_submit(message);
return master->transfer(spi, message);-----调用字段transfer函数
}
可见最终是调用具体spi控制器的transfer函数,在注册的时候要初始化对应的字段
不管是带bitbang还是不带,数据传输流程使用的函数都是上面列举的一些函数,所以在bitbang的传输流程中最后也会调用master->transfer
在上面我们介绍spi主控制器注册流程的时候提到了函数spi_master_initialize_queue,里面有一步是初始化master->transfer字段,初始化相应的函数为spi_queued_transfer
static int spi_queued_transfer(struct spi_device *spi, struct spi_message *msg)
{
struct spi_master *master = spi->master;
unsigned long flags;
spin_lock_irqsave(&master->queue_lock, flags);
if (!master->running) {
spin_unlock_irqrestore(&master->queue_lock, flags);
return -ESHUTDOWN;
}
msg->actual_length = 0;
msg->status = -EINPROGRESS;
list_add_tail(&msg->queue, &master->queue);-------------------------将msg加入到master的队列
if (!master->busy)
queue_kthread_work(&master->kworker, &master->pump_messages);---启动队列工作
spin_unlock_irqrestore(&master->queue_lock, flags);
return 0;
}
上面做完后数据开始传输,数据传输的函数为master->pump_messages,而上面已经介绍过队列开启的函数字段为spi_pump_messages
static void spi_pump_messages(struct kthread_work *work)
{
struct spi_master *master =
container_of(work, struct spi_master, pump_messages);
unsigned long flags;
bool was_busy = false;
int ret;
/* Lock queue and check for queue work */
spin_lock_irqsave(&master->queue_lock, flags);
if (list_empty(&master->queue) || !master->running) {
if (!master->busy) {
spin_unlock_irqrestore(&master->queue_lock, flags);
return;
}
master->busy = false;
spin_unlock_irqrestore(&master->queue_lock, flags);
kfree(master->dummy_rx);
master->dummy_rx = NULL;
kfree(master->dummy_tx);
master->dummy_tx = NULL;
if (master->unprepare_transfer_hardware &&
master->unprepare_transfer_hardware(master))
dev_err(&master->dev,
"failed to unprepare transfer hardware\n");
if (master->auto_runtime_pm) {
pm_runtime_mark_last_busy(master->dev.parent);
pm_runtime_put_autosuspend(master->dev.parent);
}
trace_spi_master_idle(master);
return;
}
/* Make sure we are not already running a message */
if (master->cur_msg) {
spin_unlock_irqrestore(&master->queue_lock, flags);
return;
}
/* Extract head of queue */
master->cur_msg =
list_first_entry(&master->queue, struct spi_message, queue);
list_del_init(&master->cur_msg->queue);
if (master->busy)
was_busy = true;
else
master->busy = true;
spin_unlock_irqrestore(&master->queue_lock, flags);
if (!was_busy && master->auto_runtime_pm) {
ret = pm_runtime_get_sync(master->dev.parent);
if (ret < 0) {
dev_err(&master->dev, "Failed to power device: %d\n",
ret);
return;
}
}
if (!was_busy)
trace_spi_master_busy(master);
if (!was_busy && master->prepare_transfer_hardware) {
ret = master->prepare_transfer_hardware(master);
if (ret) {
dev_err(&master->dev,
"failed to prepare transfer hardware\n");
if (master->auto_runtime_pm)
pm_runtime_put(master->dev.parent);
return;
}
}
trace_spi_message_start(master->cur_msg);
if (master->prepare_message) {
ret = master->prepare_message(master, master->cur_msg);
if (ret) {
dev_err(&master->dev,
"failed to prepare message: %d\n", ret);
master->cur_msg->status = ret;
spi_finalize_current_message(master);
return;
}
master->cur_msg_prepared = true;
}
ret = spi_map_msg(master, master->cur_msg);
if (ret) {
master->cur_msg->status = ret;
spi_finalize_current_message(master);
return;
}
ret = master->transfer_one_message(master, master->cur_msg);
if (ret) {
dev_err(&master->dev,
"failed to transfer one message from queue\n");
return;
}
}
spi_pump_messages函数就是进行数据传输的工作,结合总图可以了解的清晰明白