step1:
接着上一篇讲的,我的ADS8344驱动属于总线驱动设备模型当中的驱动,第一个问题就是spi总线在何处进行注册。在spi核心完成了对spi总线的注册。代码在spi.c中
struct bus_type spi_bus_type = {
.name = "spi",
.dev_attrs = spi_dev_attrs,
.match = spi_match_device,
.uevent = spi_uevent,
.suspend = spi_suspend,
.resume = spi_resume,
};
static int __init spi_init(void)
{
int status;
buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
if (!buf) {
status = -ENOMEM;
goto err0;
}
status = bus_register(&spi_bus_type); //完成spi总线的注册
if (status < 0)
goto err1;
status = class_register(&spi_master_class);
if (status < 0)
goto err2;
return 0;
err2:
bus_unregister(&spi_bus_type);
err1:
kfree(buf);
buf = NULL;
err0:
return status;
}
step2:
spi设备在何处完成的注册。事实上内核当中并没有spi设备的信息,这部分需要我们去添加。所以我们在机器配置文件mach-tq2440.c当中添加了spi设备的信息。
static struct spi_board_info s3c2410_spi0_board[] =
{
[0] = {
.modalias = "ads8344", //设备的名称用来和驱动进行匹配,一定要和ADS8344驱动中 ads8344_driver中的名字相同,
.bus_num = 0, //总线的编号,实际指对应的SPI寄存器
.chip_select = 0, //反映了这个芯片是不是被连接到SPI上
.irq = IRQ_EINT9, //设备的中断号
.max_speed_hz = 500 * 1000, //SPI的最大速率
}
};
spi_register_board_info(s3c2410_spi0_board, ARRAY_SIZE(s3c2410_spi0_board)).
spi_register_board_info函数将你填写到机器配置文件当中 spi_board_info数据添加到board_list链表当中。当对spi主控制器进行注册时调用spi_register_master(bitbang->master)函数。spi_register_master(bitbang->master)函数又将调用时scan_boardinfo(master),在scan_boardinfo(master)中
对board_list链表进行遍历。将链表上每个spi_board_info信息写入spi设备spi_device.然后对spi设备spi_device进行注册。
spi_register_board_info(struct spi_board_info const *info, unsigned n)
{
struct boardinfo*bi;
bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL);
if (!bi)
return -ENOMEM;
bi->n_board_info = n;
memcpy(bi->board_info, info, n * sizeof *info);将info的内容复制到bi->board_info当中。
mutex_lock(&board_lock);
list_add_tail(&bi->list, &board_list); //将info 添加到链表board_list当中
mutex_unlock(&board_lock);
return 0;
}
static void scan_boardinfo(struct spi_master *master)
{
struct boardinfo*bi;
mutex_lock(&board_lock);
list_for_each_entry(bi, &board_list, list) { /*遍历board_lis链表调用spi_new_device(master, chip)。
将spi_board_info信息填入SPI设备spi_device.并将其注册。
struct spi_board_info*chip = bi->board_info;
unsigned n;
for (n = bi->n_board_info; n > 0; n--, chip++) {
if (chip->bus_num != master->bus_num)
continue;
(void) spi_new_device(master, chip);
}
}
mutex_unlock(&board_lock);
}
/*spi_new_device()函数完成将 将spi_board_info信息填入SPI设备spi_device.
并将其注册*/
struct spi_device *spi_new_device(struct spi_master *master,
struct spi_board_info *chip)
{
struct spi_device*proxy;
int status;
proxy = spi_alloc_device(master);
if (!proxy)
return NULL;
WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias));
proxy->chip_select = chip->chip_select;
proxy->max_speed_hz = chip->max_speed_hz;
proxy->mode = chip->mode;
proxy->irq = chip->irq;
strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias));
proxy->dev.platform_data = (void *) chip->platform_data;
proxy->controller_data = chip->controller_data;
proxy->controller_state = NULL;
status = spi_add_device(proxy); //完成对SPI设备spi_device的注册
if (status < 0) {
spi_dev_put(proxy);
return NULL;
}
return proxy;
}
step3:
step 1和step2 完成了SPI总线和SPI设备信息的注册。当我们加载的ADS8344驱动到内核,SPi总线调用spi_match_device(struct device *dev, struct device_driver *drv)函数就会对驱动和设备进行匹配。
static int spi_match_device(struct device *dev, struct device_driver *drv)
{
const struct spi_device*spi = to_spi_device(dev);
return strcmp(spi->modalias, drv->name) == 0;
}
所以一旦spi->modalias和drv->name的名字相同就会调用我们ADS8344驱动当中的proble函数ads8344_probe(struct spi_device *spi) 。这样我们的ADS8344驱动就可以正常工作了
step5 :
我们看一下ads8344_probe(struct spi_device *spi)做了什么事情。
主要调用register_chrdev(ads8344_data.major, "ads8344", &ads8344_fops)函数注册一个一个字符设备。
在ads8344_fops当中定义了read ,write,ioctl等设备调用的方法。
调用class_create(THIS_MODULE, "ads8344")函数
和device_create(ads8344_data.ads8344_class, NULL,MKDEV(ads8344_data.major, 0), NULL, "ads8344")函数在/dev下添加了一个名为ads8344设备文件。原本设备文件需要我们使用nkmod命令手动加载。这里调用这两个函数内核自动加载。
static int ads8344_probe(struct spi_device *spi) //监测系统是否有ads8344设备,并进行设备注册
{
printk("we has find spi dev\n");
int ret = 0;
struct device *dev;
printk("we find spi dev! \n");
mutex_init(&ads8344_data.lock); //初始化lock信号量
ads8344_data.spi = spi_dev_get(spi); //获取SPI设备
aads8344_data.major = 0; //定义主设备号
ret = register_chrdev(ads8344_data.major, "ads8344", &ads8344_fops);//注册字符设备
if (ret < 0)
return ret;
if (ads8344_data.major == 0)
{
ads8344_data.major = ret;
printk(KERN_INFO "ads8344: major number %d\n", ads8344_data.major);
}
ad7490_data.ads8344_class = class_create(THIS_MODULE, "ads8344"); //创建ad7490设备类
if (IS_ERR(ads8344_data.ads8344_class))
{
dev_err(&ads8344_data.spi->dev, "ads8344: failed to create ads8344 class\n");
goto char_dev_remove;
}
dev = device_create(ads8344_data.ads8344_class, NULL,
MKDEV(ads8344_data.major, 0), NULL, "ads8344");//创建设备节点
if (IS_ERR(dev)) {
dev_err(&ads8344_data.spi->dev,
"ads8344: failed to create class device\n");
goto class_remove;
}
return 0;
class_remove:
class_destroy(ads8344_data.ads8344_class);
char_dev_remove:
unregister_chrdev(ads8344_data.major, "ads8344");//注销字符设备
return -ENODEV;
}
step6:
我们知道要想一个spi接口设备驱动正常工作,还需要注册SPI主控制驱动。下一讲我们对此进行分析。