linux SPI驱动——spidev之driver(六)
2016-11-04 16:28
471 查看
{
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}
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}
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}
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}
if(drv->bus->p->drivers_autoprobe){
.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}
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}
.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}
相关文章推荐
- Linux spi驱动分析(二)----SPI核心(bus、device_driver和device)
- linux spi驱动开发学习-----spidev.c和spi test app
- Linux spi驱动分析(二)----SPI核心(bus、device_driver和device)
- LINUX驱动之SPI子系统之六spi_driver的注册和挂载流程
- Linux spi驱动分析(二)----SPI核心(bus、device_driver和device)
- 在Zynq 7000平台上使用Linux spidev.c驱动,调试spi设备
- linux spi驱动开发学习-----spidev.c和spi test app
- linux spi驱动开发学习-----spidev.c和spi test app
- Linux spi驱动分析(二)----SPI核心(bus、device_driver和device)
- Linux device driver-(C)SPI(中文)
- linux驱动结构之device_driver
- linux spi驱动分析
- linux spi驱动分析
- linux 内核驱动--Platform Device和Platform_driver注册过程
- Linux下SPI驱动分析(5)
- Linux下SPI驱动分析(3)
- LINUX设备驱动之设备模型三--device&driver&bus(一)
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】PowerPC + Linux2.6.25平台下的SPI驱动架构分析
- linux spi子系统 驱动分析续
- Linux 下串口驱动头文件之tty_driver.h