ARM9 ADS8344 SPI驱动移植 (二)

来源:互联网 发布:mysql 删除重复值 编辑:程序博客网 时间:2024/06/06 03:32

 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主控制驱动。下一讲我们对此进行分析。


0 0
原创粉丝点击