分析代码可以在内核中看相关驱动代码和驱动框架。
static const struct of_device_id spi_virtual_dt_ids[] = {
{ .compatible = "my,spidev", },
{ /* sentinel */ }
};
static int spi_virtual_probe(struct platform_device *pdev)
{
return 0;
}
static int spi_virtual_remove(struct platform_device *pdev)
{
return 0;
}
static struct platform_driver spi_virtual_driver = {
.probe = spi_virtual_probe,
.remove = spi_virtual_remove,
.driver = {
.name = "virtual_spi",
.of_match_table = spi_virtual_dt_ids,
},
};
static int virtual_master_init(void)
{
printk("***virtual_master_init***\r\n");
return platform_driver_register(&spi_virtual_driver);
}
static void virtual_master_exit(void)
{
printk("***virtual_master_exit***\r\n");
platform_driver_unregister(&spi_virtual_driver);
}
module_init(virtual_master_init);
module_exit(virtual_master_exit);
MODULE_DESCRIPTION("Virtual SPI bus driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lljwork2021");
/* 针对ST芯片 */
static struct completion g_xfer_done;
static int spi_virtual_probe(struct platform_device *pdev)
{
struct spi_master *master;
master = spi_alloc_master(&pdev->dev, sizeof(struct spi_bitbang));
init_completion(&g_xfer_done);
return 0;
}
/* 针对NXP芯片 */
static struct spi_master *g_virtual_master;
static struct spi_bitbang *g_virtual_bitbang;
static struct completion g_xfer_done;
static int spi_virtual_probe(struct platform_device *pdev)
{
struct spi_master *master;
g_virtual_master = master = spi_alloc_master(&pdev->dev, sizeof(struct spi_bitbang));
if (!master)
return -ENOMEM;
g_virtual_bitbang = spi_master_get_devdata(master);
init_completion(&g_xfer_done);
return 0;
}
/*
* 针对ST芯片
* linux/drivers/spi/spi-stm32.c
*/
/* 注册代码 */
ret = spi_register_master(master); /* 注册函数 */
if (ret) {
printk("spi_register_master fail\n");
spi_master_put(master);
return ret;
}
/* 注销代码 */
spi_unregister_master(g_virtual_master); /* 注销函数 */
/*
* 方法二: 针对NXP芯片
* linux-kernel/drivers/spi/spi-imx.c
* linux-kernel/include/linux/spi/spi.h
* linux-kernel/include/linux/spi/spi_bitbang.h
* linux-kernel/drivers/spi/spi-bitbang.c
*/
函数:
int spi_bitbang_start(struct spi_bitbang *bitbang); /* 注册函数 */
void spi_bitbang_stop(struct spi_bitbang *bitbang); /* 注销函数 */
spi_master_put(_ctlr) /* 释放内存 */
#define spi_master_put(_ctlr) spi_controller_put(_ctlr)
static inline void spi_controller_put(struct spi_controller *ctlr)
参考代码:
/* 注册代码 */
ret = spi_bitbang_start(g_virtual_bitbang);
if (ret) {
printk("spi_bitbang_start fail\n");
return ret;
/* 注销代码 */
spi_bitbang_stop(g_virtual_bitbang);
spi_master_put(g_virtual_master);
static int spi_virtual_transfer(struct spi_device *spi, struct spi_transfer *transfer)
{
int timeout;
reinit_completion(&g_xfer_done);
complete(&g_xfer_done);
timeout = wait_for_completion_timeout(&g_xfer_done, 100);
if (!timeout) {
dev_err(&spi->dev, "I/O Error in PIO\n");
return -ETIMEDOUT;
}
return transfer->len;
}
static void spi_virtual_chipselect(struct spi_device *spi, int is_on)
{
}
/* 针对NXP
* linux-kernel/include/linux/spi/spi_bitbang.h
*/
g_virtual_bitbang->master = master;
g_virtual_bitbang->txrx_bufs = spi_virtual_transfer;
g_virtual_bitbang->chipselect = spi_virtual_chipselect;
/*
针对ST
linux-kernel/include/spi/spi.h
#define spi_master spi_controller
struct spi_controller {
......
}
*/
master->dev.of_node = pdev->dev.of_node;
/* linux-kernel/Documentation/scheduler/completion.rst */
init_completion
reinit_completion
unsigned long wait_for_completion_timeout(struct completion *done, unsigned long timeout);