您的位置:首页 > 运维架构 > Linux

linux SPI驱动——spidev之driver(六)

2016-11-04 16:28 471 查看
[code]staticint__initspidev_init(void)
{

intstatus;


/*Claimour256reserveddevicenumbers.Thenregisteraclass

*thatwillkeyudev/mdevtoadd/remove/devnodes.Last,register

*thedriverwhichmanagesthosedevicenumbers.

*/

BUILD_BUG_ON(N_SPI_MINORS>256);

/*注册spi字符设备*/

status=register_chrdev(SPIDEV_MAJOR,"spi",&spidev_fops);

if(status<0){

returnstatus;

}

/*为该设备创建一个classspidev*/

spidev_class=class_create(THIS_MODULE,"spidev");

if(IS_ERR(spidev_class)){

unregister_chrdev(SPIDEV_MAJOR,spidev_spi_driver.driver.name);

returnPTR_ERR(spidev_class);

}

/*register匹配到device,最终调用prob函数*/

status=spi_register_driver(&spidev_spi_driver);

if(status<0){

class_destroy(spidev_class);

unregister_chrdev(SPIDEV_MAJOR,spidev_spi_driver.driver.name);

}

returnstatus;

}

module_init(spidev_init);


staticvoid__exitspidev_exit(void)

{

spi_unregister_driver(&spidev_spi_driver);

class_destroy(spidev_class);

unregister_chrdev(SPIDEV_MAJOR,spidev_spi_driver.driver.name);

}

module_exit(spidev_exit);


MODULE_AUTHOR("AndreaPaterniani,<a.paterniani@swapp-eng.it>");

MODULE_DESCRIPTION("UsermodeSPIdeviceinterface");

MODULE_LICENSE("GPL");

MODULE_ALIAS("spi:spidev");

[/code].csharpcode,.csharpcodepre{font-size:small;color:black;font-family:consolas,"CourierNew",courier,monospace;background-color:#ffffff}
.csharpcodepre{margin:0em}
.csharpcode.rem{color:#008000}
.csharpcode.kwrd{color:#0000ff}
.csharpcode.str{color:#006080}
.csharpcode.op{color:#0000c0}
.csharpcode.preproc{color:#cc6633}
.csharpcode.asp{background-color:#ffff00}
.csharpcode.html{color:#800000}
.csharpcode.attr{color:#ff0000}
.csharpcode.alt{background-color:#f4f4f4;width:100%;margin:0em}
.csharpcode.lnum{color:#606060}
总结:1)注册一个字符设备,cat/proc/device会查看到“153spi”主设备号位153的设备2)创建一个classspidev,”/sys/class/spidev/”3)spi_register_driver注册spidriver。二:spidev_probe函数
staticint__devinitspidev_probe(structspi_device*spi)

[code]{
structspidev_data*spidev;

intstatus;

unsignedlongminor;


/*Allocatedriverdata*/

spidev=kzalloc(sizeof(*spidev),GFP_KERNEL);

if(!spidev)

return-ENOMEM;


/*Initializethedriverdata*/

spidev->spi=spi;

spin_lock_init(&spidev->spi_lock);

mutex_init(&spidev->buf_lock);


INIT_LIST_HEAD(&spidev->device_entry);


/*Ifwecanallocateaminornumber,hookupthisdevice.

*Reusingminorsisfinesolongasudevormdevisworking.

*/

mutex_lock(&device_list_lock);


minor=find_first_zero_bit(minors,N_SPI_MINORS);

if(minor<N_SPI_MINORS){

structdevice*dev;


spidev->devt=MKDEV(SPIDEV_MAJOR,minor);

dev=device_create(spidev_class,&spi->dev,spidev->devt,

spidev,"spidev%d.%d",

spi->master->bus_num,spi->chip_select);

status=IS_ERR(dev)?PTR_ERR(dev):0;

}else{

dev_dbg(&spi->dev,"nominornumberavailable!\n");

status=-ENODEV;

}

if(status==0){

set_bit(minor,minors);

list_add(&spidev->device_entry,&device_list);

}


mutex_unlock(&device_list_lock);


if(status==0)

spi_set_drvdata(spi,spidev);

else

kfree(spidev);


returnstatus;

}

[/code].csharpcode,.csharpcodepre{font-size:small;color:black;font-family:consolas,"CourierNew",courier,monospace;background-color:#ffffff}
.csharpcodepre{margin:0em}
.csharpcode.rem{color:#008000}
.csharpcode.kwrd{color:#0000ff}
.csharpcode.str{color:#006080}
.csharpcode.op{color:#0000c0}
.csharpcode.preproc{color:#cc6633}
.csharpcode.asp{background-color:#ffff00}
.csharpcode.html{color:#800000}
.csharpcode.attr{color:#ff0000}
.csharpcode.alt{background-color:#f4f4f4;width:100%;margin:0em}
.csharpcode.lnum{color:#606060}
总结:1.spidev_prob函数很简单,调用device_create创界字符设备的结点名为"spidev%d.%d"2.将spidev作为spi->dev->p->driver_data的data



三:spidev_probe函数是如何被调用的,以及什么时候被调用的追踪status=spi_register_driver(&spidev_spi_driver)调用

intspi_register_driver(structspi_driver*sdrv)

[code]{
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;

returndriver_register(&sdrv->driver);

}

[/code].csharpcode,.csharpcodepre{font-size:small;color:black;font-family:consolas,"CourierNew",courier,monospace;background-color:#ffffff}
.csharpcodepre{margin:0em}
.csharpcode.rem{color:#008000}
.csharpcode.kwrd{color:#0000ff}
.csharpcode.str{color:#006080}
.csharpcode.op{color:#0000c0}
.csharpcode.preproc{color:#cc6633}
.csharpcode.asp{background-color:#ffff00}
.csharpcode.html{color:#800000}
.csharpcode.attr{color:#ff0000}
.csharpcode.alt{background-color:#f4f4f4;width:100%;margin:0em}
.csharpcode.lnum{color:#606060}
//sdrv->driver.probe=spi_drv_probe;函数

staticintspi_drv_probe(structdevice*dev)

[code]{
conststructspi_driver*sdrv=to_spi_driver(dev->driver);


returnsdrv->probe(to_spi_device(dev));

}

[/code].csharpcode,.csharpcodepre{font-size:small;color:black;font-family:consolas,"CourierNew",courier,monospace;background-color:#ffffff}
.csharpcodepre{margin:0em}
.csharpcode.rem{color:#008000}
.csharpcode.kwrd{color:#0000ff}
.csharpcode.str{color:#006080}
.csharpcode.op{color:#0000c0}
.csharpcode.preproc{color:#cc6633}
.csharpcode.asp{background-color:#ffff00}
.csharpcode.html{color:#800000}
.csharpcode.attr{color:#ff0000}
.csharpcode.alt{background-color:#f4f4f4;width:100%;margin:0em}
.csharpcode.lnum{color:#606060}
.csharpcode,.csharpcodepre{font-size:small;color:black;font-family:consolas,"CourierNew",courier,monospace;background-color:#ffffff}
.csharpcodepre{margin:0em}
.csharpcode.rem{color:#008000}
.csharpcode.kwrd{color:#0000ff}
.csharpcode.str{color:#006080}
.csharpcode.op{color:#0000c0}
.csharpcode.preproc{color:#cc6633}
.csharpcode.asp{background-color:#ffff00}
.csharpcode.html{color:#800000}
.csharpcode.attr{color:#ff0000}
.csharpcode.alt{background-color:#f4f4f4;width:100%;margin:0em}
.csharpcode.lnum{color:#606060}
.csharpcode,.csharpcodepre{font-size:small;color:black;font-family:consolas,"CourierNew",courier,monospace;background-color:#ffffff}
.csharpcodepre{margin:0em}
.csharpcode.rem{color:#008000}
.csharpcode.kwrd{color:#0000ff}
.csharpcode.str{color:#006080}
.csharpcode.op{color:#0000c0}
.csharpcode.preproc{color:#cc6633}
.csharpcode.asp{background-color:#ffff00}
.csharpcode.html{color:#800000}
.csharpcode.attr{color:#ff0000}
.csharpcode.alt{background-color:#f4f4f4;width:100%;margin:0em}
.csharpcode.lnum{color:#606060}
可以看出调用spi_drv_prob就是调用sdrv->probe,即spidev_probe函数

2)追踪driver_register(&sdrv->driver);[code]intdriver_register(structdevice_driver*drv)
{

intret;

structdevice_driver*other;


BUG_ON(!drv->bus->p);


if((drv->bus->probe&&drv->probe)||

(drv->bus->remove&&drv->remove)||

(drv->bus->shutdown&&drv->shutdown))

printk(KERN_WARNING"Driver'%s'needsupdating-pleaseuse"

"bus_typemethods\n",drv->name);


other=driver_find(drv->name,drv->bus);

if(other){

put_driver(other);

printk(KERN_ERR"Error:Driver'%s'isalreadyregistered,"

"aborting...\n",drv->name);

return-EBUSY;

}


ret=bus_add_driver(drv);

if(ret)

returnret;

ret=driver_add_groups(drv,drv->groups);

if(ret)

bus_remove_driver(drv);

returnret;

}

[/code].csharpcode,.csharpcodepre{font-size:small;color:black;font-family:consolas,"CourierNew",courier,monospace;background-color:#ffffff}
.csharpcodepre{margin:0em}
.csharpcode.rem{color:#008000}
.csharpcode.kwrd{color:#0000ff}
.csharpcode.str{color:#006080}
.csharpcode.op{color:#0000c0}
.csharpcode.preproc{color:#cc6633}
.csharpcode.asp{background-color:#ffff00}
.csharpcode.html{color:#800000}
.csharpcode.attr{color:#ff0000}
.csharpcode.alt{background-color:#f4f4f4;width:100%;margin:0em}
.csharpcode.lnum{color:#606060}
查看bus_add_driver(drv)函数调用,有一段代码
if(drv->bus->p->drivers_autoprobe){
error=driver_attach(drv);
if(error)gotoout_unregister;
}.csharpcode,.csharpcodepre{font-size:small;color:black;font-family:consolas,"CourierNew",courier,monospace;background-color:#ffffff}
.csharpcodepre{margin:0em}
.csharpcode.rem{color:#008000}
.csharpcode.kwrd{color:#0000ff}
.csharpcode.str{color:#006080}
.csharpcode.op{color:#0000c0}
.csharpcode.preproc{color:#cc6633}
.csharpcode.asp{background-color:#ffff00}
.csharpcode.html{color:#800000}
.csharpcode.attr{color:#ff0000}
.csharpcode.alt{background-color:#f4f4f4;width:100%;margin:0em}
.csharpcode.lnum{color:#606060}

再看一下driver_attach函数[code]intdriver_attach(structdevice_driver*drv)
{

returnbus_for_each_dev(drv->bus,NULL,drv,__driver_attach);

}

[/code].csharpcode,.csharpcodepre{font-size:small;color:black;font-family:consolas,"CourierNew",courier,monospace;background-color:#ffffff}
.csharpcodepre{margin:0em}
.csharpcode.rem{color:#008000}
.csharpcode.kwrd{color:#0000ff}
.csharpcode.str{color:#006080}
.csharpcode.op{color:#0000c0}
.csharpcode.preproc{color:#cc6633}
.csharpcode.asp{background-color:#ffff00}
.csharpcode.html{color:#800000}
.csharpcode.attr{color:#ff0000}
.csharpcode.alt{background-color:#f4f4f4;width:100%;margin:0em}
.csharpcode.lnum{color:#606060}
.csharpcode,.csharpcodepre{font-size:small;color:black;font-family:consolas,"CourierNew",courier,monospace;background-color:#ffffff}
.csharpcodepre{margin:0em}
.csharpcode.rem{color:#008000}
.csharpcode.kwrd{color:#0000ff}
.csharpcode.str{color:#006080}
.csharpcode.op{color:#0000c0}
.csharpcode.preproc{color:#cc6633}
.csharpcode.asp{background-color:#ffff00}
.csharpcode.html{color:#800000}
.csharpcode.attr{color:#ff0000}
.csharpcode.alt{background-color:#f4f4f4;width:100%;margin:0em}
.csharpcode.lnum{color:#606060}


intbus_for_each_dev(structbus_type*bus,structdevice*start,

[code]void*data,int(*fn)(structdevice*,void*))
{

structklist_iteri;

structdevice*dev;

interror=0;


if(!bus)

return-EINVAL;


klist_iter_init_node(&bus->p->klist_devices,&i,

(start?&start->p->knode_bus:NULL));

while((dev=next_device(&i))&&!error)

error=fn(dev,data);

klist_iter_exit(&i);

returnerror;

}

[/code].csharpcode,.csharpcodepre{font-size:small;color:black;font-family:consolas,"CourierNew",courier,monospace;background-color:#ffffff}
.csharpcodepre{margin:0em}
.csharpcode.rem{color:#008000}
.csharpcode.kwrd{color:#0000ff}
.csharpcode.str{color:#006080}
.csharpcode.op{color:#0000c0}
.csharpcode.preproc{color:#cc6633}
.csharpcode.asp{background-color:#ffff00}
.csharpcode.html{color:#800000}
.csharpcode.attr{color:#ff0000}
.csharpcode.alt{background-color:#f4f4f4;width:100%;margin:0em}
.csharpcode.lnum{color:#606060}
从上面两段代码可以看出bus_for_each_dev会遍历总线上所有设备并设用__driver_attach。我们再看一下__driver_attach所做的工作:
1.driver_match_device(drv,dev);device与drivername时候strncmp
2.driver_probe_device(drv,dev);函数调用prob
staticint__driver_attach(structdevice*dev,void*data)

[code]{
structdevice_driver*drv=data;



if(!driver_match_device(drv,dev))

return0;


if(dev->parent)/*NeededforUSB*/

device_lock(dev->parent);

device_lock(dev);

if(!dev->driver)

driver_probe_device(drv,dev);

device_unlock(dev);

if(dev->parent)

device_unlock(dev->parent);


return0;

}

[/code].csharpcode,.csharpcodepre{font-size:small;color:black;font-family:consolas,"CourierNew",courier,monospace;background-color:#ffffff}
.csharpcodepre{margin:0em}
.csharpcode.rem{color:#008000}
.csharpcode.kwrd{color:#0000ff}
.csharpcode.str{color:#006080}
.csharpcode.op{color:#0000c0}
.csharpcode.preproc{color:#cc6633}
.csharpcode.asp{background-color:#ffff00}
.csharpcode.html{color:#800000}
.csharpcode.attr{color:#ff0000}
.csharpcode.alt{background-color:#f4f4f4;width:100%;margin:0em}
.csharpcode.lnum{color:#606060}

我们再继续查看一下driver_probe_device函数的调用:[code]intdriver_probe_device(structdevice_driver*drv,structdevice*dev)
{

intret=0;


if(!device_is_registered(dev))

return-ENODEV;


pr_debug("bus:'%s':%s:matcheddevice%swithdriver%s\n",

drv->bus->name,__func__,dev_name(dev),drv->name);


pm_runtime_get_noresume(dev);

pm_runtime_barrier(dev);


ret=really_probe(dev,drv);
pm_runtime_put_sync(dev);


returnret;

}

[/code].csharpcode,.csharpcodepre{font-size:small;color:black;font-family:consolas,"CourierNew",courier,monospace;background-color:#ffffff}
.csharpcodepre{margin:0em}
.csharpcode.rem{color:#008000}
.csharpcode.kwrd{color:#0000ff}
.csharpcode.str{color:#006080}
.csharpcode.op{color:#0000c0}
.csharpcode.preproc{color:#cc6633}
.csharpcode.asp{background-color:#ffff00}
.csharpcode.html{color:#800000}
.csharpcode.attr{color:#ff0000}
.csharpcode.alt{background-color:#f4f4f4;width:100%;margin:0em}
.csharpcode.lnum{color:#606060}

总结:通过代码最终我们最终看到了spidev_prob函数是怎样被调用的

.csharpcode,.csharpcodepre{font-size:small;color:black;font-family:consolas,"CourierNew",courier,monospace;background-color:#ffffff}
.csharpcodepre{margin:0em}
.csharpcode.rem{color:#008000}
.csharpcode.kwrd{color:#0000ff}
.csharpcode.str{color:#006080}
.csharpcode.op{color:#0000c0}
.csharpcode.preproc{color:#cc6633}
.csharpcode.asp{background-color:#ffff00}
.csharpcode.html{color:#800000}
.csharpcode.attr{color:#ff0000}
.csharpcode.alt{background-color:#f4f4f4;width:100%;margin:0em}
.csharpcode.lnum{color:#606060}
.csharpcode,.csharpcodepre{font-size:small;color:black;font-family:consolas,"CourierNew",courier,monospace;background-color:#ffffff}
.csharpcodepre{margin:0em}
.csharpcode.rem{color:#008000}
.csharpcode.kwrd{color:#0000ff}
.csharpcode.str{color:#006080}
.csharpcode.op{color:#0000c0}
.csharpcode.preproc{color:#cc6633}
.csharpcode.asp{background-color:#ffff00}
.csharpcode.html{color:#800000}
.csharpcode.attr{color:#ff0000}
.csharpcode.alt{background-color:#f4f4f4;width:100%;margin:0em}
.csharpcode.lnum{color:#606060}
.csharpcode,.csharpcodepre{font-size:small;color:black;font-family:consolas,"CourierNew",courier,monospace;background-color:#ffffff}
.csharpcodepre{margin:0em}
.csharpcode.rem{color:#008000}
.csharpcode.kwrd{color:#0000ff}
.csharpcode.str{color:#006080}
.csharpcode.op{color:#0000c0}
.csharpcode.preproc{color:#cc6633}
.csharpcode.asp{background-color:#ffff00}
.csharpcode.html{color:#800000}
.csharpcode.attr{color:#ff0000}
.csharpcode.alt{background-color:#f4f4f4;width:100%;margin:0em}
.csharpcode.lnum{color:#606060}
.csharpcode,.csharpcodepre{font-size:small;color:black;font-family:consolas,"CourierNew",courier,monospace;background-color:#ffffff}
.csharpcodepre{margin:0em}
.csharpcode.rem{color:#008000}
.csharpcode.kwrd{color:#0000ff}
.csharpcode.str{color:#006080}
.csharpcode.op{color:#0000c0}
.csharpcode.preproc{color:#cc6633}
.csharpcode.asp{background-color:#ffff00}
.csharpcode.html{color:#800000}
.csharpcode.attr{color:#ff0000}
.csharpcode.alt{background-color:#f4f4f4;width:100%;margin:0em}
.csharpcode.lnum{color:#606060}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: