前段时间同事调试 SPI 驱动, 遇到个问题来问我, 帮忙澄清了并顺便看了下SPI bitbang的驱动代码流程, 小结在此. 内核版本 3.6.4
本文所有文字都是原创, 转发请注明出处.
她的问题是这样的" 如果bitbang结构体不是排在第一个的话, 会有kernel warning出现." 以s3c24xx_spi 为例.
struct s3c24xx_spi{
/* bitbang has to be first */
struct spi_bitbang bitbang;
struct completion done;
void __iomem *regs;
int irq;
int len;
int count;
struct fiq_handler fiq_handler;
enum spi_fiq_mode fiq_mode;
unsigned char fiq_inuse;
unsigned char fiq_claimed;
void (*set_cs)(struct s3c2410_spi_info *spi,
int cs, int pol);
/* data buffers */
const unsigned char *tx;
unsigned char *rx;
struct clk *clk;
struct resource *ioarea;
struct spi_master *master;
struct spi_device *curdev;
struct device *dev;
struct s3c2410_spi_info *pdata;
};
如果不放在结构体中第一个成员的位置的话, 就会出kernel warning.
------------[ cut here ]------------
WARNING: at kernel/workqueue.c:991 __queue_work+0x338/0x36c()
Modules linked in:
Call Trace:
[<806ac75c>] dump_stack+0x8/0x34
[<80123e6c>] warn_slowpath_common+0x78/0xa4
[<80123eb0>] warn_slowpath_null+0x18/0x24
[<80143714>] __queue_work+0x338/0x36c
[<801437b4>] queue_work_on+0x44/0x8c
[<803c230c>] spi_bitbang_transfer+0xa4/0xd8
[<803c02b0>] spi_async_locked+0x20/0x4c
[<803c0700>] __spi_sync+0x54/0xbc
[<803d3e1c>] mmc_spi_readbytes+0x54/0xc8
[<803d3ee8>] mmc_spi_skip+0x58/0xf4
[<803d40d0>] mmc_spi_set_ios+0x14c/0x434
[<803c6520>] mmc_power_up+0x1e0/0x268
[<803c68b8>] mmc_start_host+0x30/0x58
[<803c742c>] mmc_add_host+0x64/0xa0
[<803d5ec8>] mmc_spi_probe+0x3bc/0x60c
[<8038d5e4>] driver_probe_device+0x118/0x498
[<8038da20>] __driver_attach+0xbc/0xc4
[<8038b808>] bus_for_each_dev+0x70/0xac
[<8038c1e0>] bus_add_driver+0x1d0/0x2bc
[<8038e204>] driver_register+0x74/0x17c
[<80100440>] do_one_initcall+0x40/0x1e0
---[ end trace fe3505dcf96ad417 ]---
分析方式不外乎顺推和倒推, 从workqueue倒退, 检查这个flag, 但是这个flag根本不会被置起来, 说明不是workqueue机制的问题.
那就顺推, 检查spi_bitbang的驱动, 结果发现在spi-bitbang.c的驱动中, 函数spi_bitbang_setup和spi_bitbang_transfer都调用到了
spi_master_get_devdata 去得到spi_bitbang, 但是实际上在spi_master_set_devdata的时候, 是整个结构体的.
int spi_bitbang_setup(struct spi_device *spi)
{
struct spi_bitbang_cs *cs = spi->controller_state;
struct spi_bitbang *bitbang;
int retval;
unsigned long flags;
bitbang = spi_master_get_devdata(spi->master);
if (!cs) {
cs = kzalloc(sizeof *cs, GFP_KERNEL);
if (!cs)
return -ENOMEM;
spi->controller_state = cs;
}
...
}
struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
{
struct spi_master *master;
if (!dev)
return NULL;
master = kzalloc(size + sizeof *master, GFP_KERNEL);
if (!master)
return NULL;
device_initialize(&master->dev);
master->bus_num = -1;
master->num_chipselect = 1;
master->dev.class = &spi_master_class;
master->dev.parent = get_device(dev);
spi_master_set_devdata(master, &master[1]); // 这个master[1] 其实就是struct s3c24xx_spi, 所以要求bitbang是第一个成员
return master;
}
static int __devinit s3c24xx_spi_probe(struct platform_device *pdev)
{
struct s3c2410_spi_info *pdata;
struct s3c24xx_spi *hw;
struct spi_master *master;
struct resource *res;
int err = 0;
master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi));
if (master == NULL) {
dev_err(&pdev->dev, "No memory for spi_master\n");
err = -ENOMEM;
goto err_nomem;
}
...
}
由于这个隐式转换的问题, 所以要求spi_bitbang是结构体内的第一个成员, 否则就会出各种意料不到的问题.
当然也可以自己修改下代码, 避免这个问题.
2. spi部分代码阅读
重要的结构体有: spi_device, spi_driver, spi_master, spi_transfer, spi_message
spi device和spi master的挂载是通过bus_num的匹配来实现的.
3. probe部分的流程
driver_probe_device
real_probe
spi_drv_probe(sdrv->driver.probe ) //是device_driver结构体里面的probe
sdrv->probe (spidev_probe) //是spi_driver结构体里面的probe
device_release_driver
__device_release_driver
drv->remove(dev); //spi_drv_remove
sdrv->remove //spidev_remove
4. transfer 流程
spi_read/spi_write
spi_sync
spi_async
master->transfer //可以是自己的transfer, 也可以是spi_bitbang_transfer(驱动没有赋值的系统默认)
5. spi_bitbang_transfer 流程
queue_work(bitbang->workqueue, &bitbang->work); //bitbang_work
bitbang->txrx_bufs(spi, t);
spi_bitbang_bufs //默认
cs->txrx_bufs
bitbang_txrx_8 // 16 //32
cs->txrx_word //bitbang->txrx_word[spi->mode & (SPI_CPOL|SPI_CPHA)] 函数指针数组
spi_gpio_txrx_word_mode0
bitbang_txrx_be_cpha0