linuxSPI驅(qū)動框架源碼分析

上傳人:文*** 文檔編號:62217716 上傳時間:2022-03-14 格式:DOCX 頁數(shù):32 大?。?96.24KB
收藏 版權(quán)申訴 舉報 下載
linuxSPI驅(qū)動框架源碼分析_第1頁
第1頁 / 共32頁
linuxSPI驅(qū)動框架源碼分析_第2頁
第2頁 / 共32頁
linuxSPI驅(qū)動框架源碼分析_第3頁
第3頁 / 共32頁

下載文檔到電腦,查找使用更方便

0 積分

下載資源

還剩頁未讀,繼續(xù)閱讀

資源描述:

《linuxSPI驅(qū)動框架源碼分析》由會員分享,可在線閱讀,更多相關(guān)《linuxSPI驅(qū)動框架源碼分析(32頁珍藏版)》請在裝配圖網(wǎng)上搜索。

1、文檔供參考,可復(fù)制、編制,期待您的好評與關(guān)注! SPI協(xié)議是一種同步的串行數(shù)據(jù)連接標準,由摩托羅拉公司命名,可工作于全雙工模式。相關(guān)通訊設(shè)備可工作于m/s模式。主設(shè)備發(fā)起數(shù)據(jù)幀,允許多個從設(shè)備的存在。每個從設(shè)備有獨立的片選信號,SPI一般來說是四線串行總線結(jié)構(gòu)。接口:SCLKSerial Clock(output from master)時鐘(主設(shè)備發(fā)出)MOSI/SIMOMaster Output, Slave Input(output from master)數(shù)據(jù)信號線mosi(主設(shè)備發(fā)出)MISO/SOMIMaster Input,Slave Outpu(output from slav

2、e)數(shù)據(jù)信號線(從設(shè)備)SSSlave Select(active low;output from master)片選信號下面來看一下Linux中的SPI驅(qū)動。在Linux設(shè)備驅(qū)動框架的設(shè)計中,有一個重要的主機,外設(shè)驅(qū)動框架分離的思想,如下圖。外設(shè)a,b,c的驅(qū)動與主機控制器A,B,C的驅(qū)動不相關(guān),主機控制器驅(qū)動不關(guān)心外設(shè),而外設(shè)驅(qū)動也不關(guān)心主機,外設(shè)只是訪問核心層的通用的API進行數(shù)據(jù)的傳輸,主機和外設(shè)之間可以進行任意的組合。如果我們不進行如圖的主機和外設(shè)分離,外設(shè)a,b,c和主機A,B,C進行組合的時候,需要9種不同的驅(qū)動。設(shè)想一共有個主機控制器,n個外設(shè),分離的結(jié)構(gòu)是需要m+n個驅(qū)動,不

3、分離則需要m*n個驅(qū)動。下面介紹spi子系統(tǒng)的數(shù)據(jù)結(jié)構(gòu):在Linux中,使用spi_master結(jié)構(gòu)來描述一個SPI主機控制器的驅(qū)動。view plain1. structspi_master2. structdevicedev;/*總線編號,從0開始*/3. s16bus_num;/*支持的片選的數(shù)量,從設(shè)備的片選號不能大于這個數(shù)量*/4. u16num_chipselect;5. u16dma_alignment;/*改變spi_device的特性如:傳輸模式,字長,時鐘頻率*/6. int(*setup)(structspi_device*spi);/*添加消息到隊列的方法,這個函數(shù)不可

4、睡眠,他的任務(wù)是安排發(fā)生的傳送并且調(diào)用注冊的回調(diào)函數(shù)complete()*/7. int(*transfer)(structspi_device*spi,structspi_message*mesg);8. void(*cleanup)(structspi_device*spi);9. ;分配,注冊和注銷的SPI主機的API由SPI核心提供:view plain1. structspi_master*spi_alloc_master(structdevice*host,unsignedsize);2. intspi_register_master(structspi_master*master

5、);3. voidspi_unregister_master(structspi_master*master);在Linux中用spi_driver來描述一個SPI外設(shè)驅(qū)動。view plain1. structspi_driver2. int(*probe)(structspi_device*spi);3. int(*remove)(structspi_device*spi);4. void(*shutdown)(structspi_device*spi);5. int(*suspend)(structspi_device*spi,pm_message_tmesg);6. int(*resu

6、me)(structspi_device*spi);7. structdevice_driverdriver;8. ;可以看出,spi_driver結(jié)構(gòu)體和platform_driver結(jié)構(gòu)體有極大的相似性,都有probe(),remove(),suspend(),resume()這樣的接口。Linux用spi_device來描述一個SPI外設(shè)設(shè)備。view plain1. structspi_device2. structdevicedev;3. structspi_master*master;/對應(yīng)的控制器指針u324. max_speed_hz;/spi通信的時鐘u85. chip_se

7、lect;/片選,用于區(qū)分同一總線上的不同設(shè)備6. u8mode;7. #defineSPI_CPHA0x01/*clockphase*/8. #defineSPI_CPOL0x02/*clockpolarity*/9. #defineSPI_MODE_0(0|0)/*(originalMicroWire)*/#defineSPI_MODE_1(0|SPI_CPHA)10. #defineSPI_MODE_2(SPI_CPOL|0)11. #defineSPI_MODE_3(SPI_CPOL|SPI_CPHA)#defineSPI_CS_HIGH0x04/*chipselectactivehi

8、gh?*/12. #defineSPI_LSB_FIRST0x08/*per-wordbits-on-wire*/13. #defineSPI_3WIRE0x10/*SI/SOsignalsshared*/14. #defineSPI_LOOP0x20/*loopbackmode*/15. u8bits_per_word;/每個字長的比特數(shù)16. intirq;/使用的中斷17. void*controller_state;18. void*controller_data;19. charmodalias32;/名字20. ;如下圖,看這三個結(jié)構(gòu)的關(guān)系,這里spi_device與spi_mas

9、ter是同一個父設(shè)備,這是在spi_new_device函數(shù)中設(shè)定的,一般這個設(shè)備是一個物理設(shè)備。這里的spi_master_class,spi_bus_type又是什么呢,看下邊兩個結(jié)構(gòu)體:view plain1. structbus_typespi_bus_type=2. .name=spi,3. .dev_attrs=spi_dev_attrs,4. .match=spi_match_device,5. .uevent=spi_uevent,6. .suspend=spi_suspend,7. .resume=spi_resume,8. ;9. staticstructclassspi_

10、master_class=10. .name=spi_master,11. .owner=THIS_MODULE,12. .dev_release=spi_master_release,13. ;spi_bus_type對應(yīng)spi中的spi bus總線,spidev的類定義如下:view plain1. staticstructclass*spidev_class;創(chuàng)建這個類的主要目的是使mdev/udev能在/dev下創(chuàng)建設(shè)備節(jié)點/dev/spiB.C。B代表總線,C代表片外設(shè)備的片選號。下邊來看兩個板級的結(jié)構(gòu),其中spi_board_info用來初始化spi_device,s3c2410_

11、spi_info用來初始化spi_master。這兩個板級的結(jié)構(gòu)需要在移植的時候在arch/arm/mach-s3c2440/mach-smdk2440.c中初始化。view plain1. structspi_board_info2. charmodalias32;/設(shè)備與驅(qū)動匹配的唯一標識3. constvoid*platform_data;4. void*controller_data;5. intirq;6. u32max_speed_hz;7. u16bus_num;/設(shè)備所歸屬的總線編號8. u16chip_select;9. u8mode;10. ;11. structs3c24

12、10_spi_info12. intpin_cs;/芯片選擇管腳13. unsignedintnum_cs;/總線上的設(shè)備數(shù)14. intbus_num;/總線號15. void(*gpio_setup)(structs3c2410_spi_info*spi,intenable);/spi管腳配置函數(shù)16. void(*set_cs)(structs3c2410_spi_info*spi,intcs,intpol);17. ;boardinfo是用來管理spi_board_info的結(jié)構(gòu),spi_board_info通過spi_register_board_info(struct spi_bo

13、ard_info const *info, unsigned n)交由boardinfo來管理,并掛到board_list鏈表上,list_add_tail(&bi-list,&board_list);view plain1. structboardinfo2. /*用于掛到鏈表頭board_list上*/3. structlist_headlist;4. /*管理的spi_board_info的數(shù)量*/5. unsignedn_board_info;6. /*存放結(jié)構(gòu)體spi_board_info*/7. structspi_board_infoboard_info0;8. ;s3c24xx

14、_spi是S3C2440的SPI控制器在Linux內(nèi)核中的具體描述,該結(jié)構(gòu)包含spi_bitbang內(nèi)嵌結(jié)構(gòu),控制器時鐘頻率和占用的中斷資源等重要成員,其中spi_bitbang具體負責(zé)SPI數(shù)據(jù)的傳輸。view plain1. structs3c24xx_spi2. /*bitbanghastobefirst*/3. structspi_bitbangbitbang;4. structcompletiondone;5. void_iomem*regs;6. intirq;7. intlen;8. intcount;9. void(*set_cs)(structs3c2410_spi_info

15、*spi,intcs,intpol);10. /*databuffers*/constunsignedchar*tx;11. unsignedchar*rx;12. structclk*clk;13. structresource*ioarea;14. structspi_master*master;15. structspi_device*curdev;16. structdevice*dev;17. structs3c2410_spi_info*pdata;18. ;為了解決多個不同的SPI設(shè)備共享SPI控制器而帶來的訪問沖突,spi_bitbang使用內(nèi)核提供的工作隊列(workqueu

16、e)。workqueue是Linux內(nèi)核中定義的一種回調(diào)處理方式。采用這種方式需要傳輸數(shù)據(jù)時,不直接完成數(shù)據(jù)的傳輸,而是將要傳輸?shù)墓ぷ鞣盅b成相應(yīng)的消息(spi_message),發(fā)送給對應(yīng)的workqueue,由與workqueue關(guān)聯(lián)的內(nèi)核守護線程(daemon)負責(zé)具體的執(zhí)行。由于workqueue會將收到的消息按時間先后順序排列,這樣就是對設(shè)備的訪問嚴格串行化,解決了沖突。view plain1. structspi_bitbang2. structworkqueue_struct*workqueue;/工作隊列頭3. structwork_structwork;/每一次傳輸都傳遞下來一

17、個spi_message,都向工作隊列頭添加一個4. workspinlock_tlock;5. structlist_headqueue;/掛接spi_message,如果上一次的spi_message還沒有處理完,接下來的spi_message就掛接在queue上等待處理6. u8busy;/忙碌標志7. u8use_dma;8. u8flags;9. structspi_master*master;/*一下3個函數(shù)都是在函數(shù)s3c24xx_spi_probe()中被初始化*/10. int(*setup_transfer)(structspi_device*spi,structspi_t

18、ransfer*t);/設(shè)置傳輸模式11. void(*chipselect)(structspi_device*spi,intis_on);/片選12. #defineBITBANG_CS_ACTIVE1/*normallynCS,activelow*/13. #defineBITBANG_CS_INACTIVE0/*傳輸函數(shù),由s3c24xx_spi_txrx來實現(xiàn)*/14. int(*txrx_bufs)(structspi_device*spi,structspi_transfer*t);15. u32(*txrx_word4)(structspi_device*spi,unsigne

19、dnsecs,u32word,u8bits);16. ;下面來看看spi_message:view plain1. structspi_message2. structlist_headtransfers;/此次消息的傳輸隊列,一個消息可以包含多個傳輸段3. structspi_device*spi;/傳輸?shù)哪康脑O(shè)備4. unsignedis_dma_mapped:1;/如果為真,此次調(diào)用提供dma和cpu虛擬地址5. void(*complete)(void*context);/異步調(diào)用完成后的回調(diào)函數(shù)6. void*context;/回調(diào)函數(shù)的參數(shù)7. unsignedactual_len

20、gth;/此次傳輸?shù)膶嶋H長度8. intstatus;/執(zhí)行的結(jié)果,成功被置0,否則是一個負的錯誤碼9. structlist_headqueue;10. void*state;11. ;在有消息需要傳遞的時候,會將spi_transfer通過自己的transfer_list字段掛到spi_message的transfers鏈表頭上。spi_message用來原子的執(zhí)行spi_transfer表示的一串?dāng)?shù)組傳輸請求。這個傳輸隊列是原子的,這意味著在這個消息完成之前不會有其他消息占用總線。消息的執(zhí)行總是按照FIFO的順序。下面看一看spi_transfer:view plain1. struct

21、spi_transfer2. constvoid*tx_buf;/要寫入設(shè)備的數(shù)據(jù)(必須是dma_safe),或者為NULL3. void*rx_buf;/要讀取的數(shù)據(jù)緩沖(必須是dma_safe),或者為NULL4. unsignedlen;/tx和rx的大小(字節(jié)數(shù)),這里不是指它的和,而是各自的長度,他們總是相等的5. dma_addr_ttx_dma;/如果spi_message.is_dma_mapped是真,這個是tx的dma地址6. dma_addr_trx_dma;/如果spi_message.is_dma_mapped是真,這個是rx的dma地址7. unsignedcs_c

22、hange:1;/影響此次傳輸之后的片選,指示本次tranfer結(jié)束之后是否要重新片選并調(diào)用setup改變設(shè)置,這個標志可以較少系統(tǒng)開銷u88. bits_per_word;/每個字長的比特數(shù),如果是0,使用默認值9. u16delay_usecs;/此次傳輸結(jié)束和片選改變之間的延時,之后就會啟動另一個傳輸或者結(jié)束整個消息10. u32speed_hz;/通信時鐘。如果是0,使用默認值11. structlist_headtransfer_list;/用來連接的雙向鏈表節(jié)點12. ;嵌入式微處理器訪問SPI設(shè)備有兩種方式:使用GPIO模擬SPI接口的工作時序或者使用SPI控制器。使用GPIO模

23、擬SPI接口的工作時序是非常容易實現(xiàn)的,但是會導(dǎo)致大量的時間耗費在模擬SPI接口的時序上,訪問效率比較低,容易成為系統(tǒng)瓶頸。這里主要分析使用SPI控制器的情況。這個是由sys文件系統(tǒng)導(dǎo)出的spi子系統(tǒng)在內(nèi)核中的視圖了。首先了解一下Linux內(nèi)核中的幾個文件:spi.c也就是spi子系統(tǒng)的核心了,spi_s3c24xx.c是s3c24xx系列芯片的SPI controller驅(qū)動,它向更上層的SPI核心層(spi.c)提供接口用來控制芯片的SPI controller,是一個被其他驅(qū)動使用的驅(qū)動。而spidev.c是在核心層基礎(chǔ)之上將SPI controller模擬成一個字符型的驅(qū)動,向文件系統(tǒng)

24、提供標準的文件系統(tǒng)接口,用來操作對應(yīng)的SPI controller。下面我們來看看spi子系統(tǒng)是怎么注冊進內(nèi)核的:view plain1. staticint_initspi_init(void)2. 3. intstatus;4. buf=kmalloc(SPI_BUFSIZ,GFP_KERNEL);5. if(!buf)6. status=-ENOMEM;7. gotoerr0;8. 9. status=bus_register(&spi_bus_type);10. if(status0)11. gotoerr1;12. status=class_register(&spi_master_

25、class);13. if(status0)14. gotoerr2;15. return0;16. err2:17. bus_unregister(&spi_bus_type);18. err1:19. kfree(buf);20. buf=NULL;21. err0:22. returnstatus;23. 24. postcore_initcall(spi_init);這里注冊了一個spi_bus_type,也就是一個spi總線,和一個spi_master的class。分別對應(yīng)上圖中sys/bus/下的spi目錄和sys/class/下的spi_master目錄。下面來分析SPI con

26、troller驅(qū)動的注冊與初始化過程,首先執(zhí)行的是s3c24xx_spi_init。view plain1. staticint_inits3c24xx_spi_init(void)2. 3. returnplatform_driver_probe(&s3c24xx_spi_driver,s3c24xx_spi_probe);4. platform_driver_probe中完成了s3c24xx_spi_driver這個平臺驅(qū)動的注冊,相應(yīng)的平臺設(shè)備在devs.c中定義,在smdk2440_devices中添加&s3c_device_spi0,&s3c_device_spi1,這就生成了圖中所

27、示的s3c24xx-spi.0與s3c24xx-spi.1,當(dāng)然了這圖是在網(wǎng)上找的,不是我畫的,所以是6410的。這里s3c24xx-spi.0表示s3c2440的spi controller的0號接口,s3c24xx-spi.1表示s3c2440的spi controller的1號接口。注冊了s3c24xx_spi_driver后,賦值了平臺驅(qū)動的probe函數(shù)為s3c24xx_spi_probe。所以當(dāng)match成功后,調(diào)用s3c24xx_spi_probe,這里看其實現(xiàn):view plain1. staticint_inits3c24xx_spi_probe(structplatform

28、_device*pdev)2. 3. structs3c2410_spi_info*pdata;4. structs3c24xx_spi*hw;5. structspi_master*master;6. structresource*res;7. interr=0;8. /*分配structspi_master+structs3c24xx_spi大小的數(shù)據(jù),把s3c24xx_spi設(shè)為spi_master的私有數(shù)據(jù)*/9. master=spi_alloc_master(&pdev-dev,sizeof(structs3c24xx_spi);10. if(master=NULL)11. dev

29、_err(&pdev-dev,Nomemoryforspi_mastern);12. err=-ENOMEM;13. gotoerr_nomem;14. 15. /*從master中獲得s3c24xx_spi*/16. hw=spi_master_get_devdata(master);17. memset(hw,0,sizeof(structs3c24xx_spi);18. 19. 20. hw-master=spi_master_get(master);21. /*驅(qū)動移植的時候需要實現(xiàn)的重要結(jié)構(gòu),初始化為&s3c2410_spi0_platdata*/22. hw-pdata=pdata

30、=pdev-dev.platform_data;23. hw-dev=&pdev-dev;24. 25. 26. if(pdata=NULL)27. dev_err(&pdev-dev,Noplatformdatasuppliedn);28. err=-ENOENT;29. gotoerr_no_pdata;30. 31. /*設(shè)置平臺的私有數(shù)據(jù)為s3c24xx_spi*/32. platform_set_drvdata(pdev,hw);33. init_completion(&hw-done);34. 35. 36. /*setupthemasterstate.*/37. /*該總線上的設(shè)

31、備數(shù)*/38. master-num_chipselect=hw-pdata-num_cs;39. /*總線號*/40. master-bus_num=pdata-bus_num;41. 42. 43. /*setupthestateforthebitbangdriver*/44. /*spi_bitbang專門負責(zé)數(shù)據(jù)的傳輸*/45. hw-bitbang.master=hw-master;46. hw-bitbang.setup_transfer=s3c24xx_spi_setupxfer;47. hw-bitbang.chipselect=s3c24xx_spi_chipsel;48.

32、hw-bitbang.txrx_bufs=s3c24xx_spi_txrx;49. hw-bitbang.master-setup=s3c24xx_spi_setup;50. 51. 52. dev_dbg(hw-dev,bitbangat%pn,&hw-bitbang);53. 54. 。55. 56. /*初始化設(shè)置寄存器,包括對SPIMOSI,SPIMISO,SPICLK引腳的設(shè)置*/57. s3c24xx_spi_initialsetup(hw);58. 59. 60. /*registerourspicontroller*/61. 62. 63. err=spi_bitbang_st

33、art(&hw-bitbang);64. 。65. 66. spicontroller的register在spi_bitbang_start函數(shù)中實現(xiàn):67. intspi_bitbang_start(structspi_bitbang*bitbang)68. 69. intstatus;70. 71. 72. if(!bitbang-master|!bitbang-chipselect)73. return-EINVAL;74. /*動態(tài)創(chuàng)建一個work_struct結(jié)構(gòu),它的處理函數(shù)是bitbang_work*/75. INIT_WORK(&bitbang-work,bitbang_wor

34、k);76. spin_lock_init(&bitbang-lock);77. INIT_LIST_HEAD(&bitbang-queue);78. /*spi的數(shù)據(jù)傳輸就是用這個方法*/79. if(!bitbang-master-transfer)80. bitbang-master-transfer=spi_bitbang_transfer;81. if(!bitbang-txrx_bufs)82. bitbang-use_dma=0;83. /*spi_s3c24xx.c中有spi_bitbang_bufs方法,在bitbang_work中被調(diào)用*/84. bitbang-txrx_

35、bufs=spi_bitbang_bufs;85. if(!bitbang-master-setup)86. if(!bitbang-setup_transfer)87. bitbang-setup_transfer=88. spi_bitbang_setup_transfer;89. /*在spi_s3c24xx.c中有setup的處理方法,在spi_new_device中被調(diào)用*/90. bitbang-master-setup=spi_bitbang_setup;91. bitbang-master-cleanup=spi_bitbang_cleanup;92. 93. elseif(!

36、bitbang-master-setup)94. return-EINVAL;95. 96. 97. /*thistaskistheonlythingtotouchtheSPIbits*/98. bitbang-busy=0;99. /調(diào)用create_singlethread_workqueue創(chuàng)建單個工作線程/100. bitbang-workqueue=create_singlethread_workqueue(101. dev_name(bitbang-master-dev.parent);102. if(bitbang-workqueue=NULL)103. status=-EBUS

37、Y;104. gotoerr1;105. 106. status=spi_register_master(bitbang-master);107. if(statusworkqueue);112. err1:113. returnstatus;114. 然后看這里是怎樣注冊spi主機控制器驅(qū)動的:view plain1. intspi_register_master(structspi_master*master)2. 3. 。4. /*將spi添加到內(nèi)核,這也是sys/class/Spi_master下產(chǎn)生Spi0,Spi1的原因*/5. dev_set_name(&master-dev,s

38、pi%u,master-bus_num);6. status=device_add(&master-dev);7. scan_boardinfo(master);8. 這里跟蹤scan_boardinfo函數(shù):view plain1. staticvoidscan_boardinfo(structspi_master*master)2. 3. structboardinfo*bi;4. mutex_lock(&board_lock);5. /*遍歷所有掛在board_list上的structboardinfo*/6. list_for_each_entry(bi,&board_list,lis

39、t)7. structspi_board_info*chip=bi-board_info;8. unsignedn;9. /*遍歷每個boardinfo管理的spi_board_info,如果設(shè)備的總線號與控制器的總線好相等,則創(chuàng)建新設(shè)備*/10. for(n=bi-n_board_info;n0;n-,chip+)11. if(chip-bus_num!=master-bus_num)12. continue;13. (void)spi_new_device(master,chip);14. 15. 16. mutex_unlock(&board_lock);17. 在移植的時候我們會在ma

40、ch-smdk2440.c中的smdk2440_machine_init中添加spi_register_board_info這個函數(shù)完成了將spi_board_info交由boardinfo管理,并把boardinfo掛載到board_list鏈表上。也就是說在系統(tǒng)初始化的時候?qū)pi_device交由到掛在board_list上的boardinfo管理,在spi controller的driver注冊的時候不但注冊這個主機控制器的驅(qū)動,還要遍歷這個主機控制器的總線上的spi_device,將總線上的spi_device全部注冊進內(nèi)核。當(dāng)注冊進內(nèi)核并且spi_driver已經(jīng)注冊的時候,如果總

41、線match成功,則會調(diào)用spi_driver的probe函數(shù),這個將在后邊進行分析。view plain1. int_init2. spi_register_board_info(structspi_board_infoconst*info,unsignedn)3. 4. structboardinfo*bi;5. 6. 7. bi=kmalloc(sizeof(*bi)+n*sizeof*info,GFP_KERNEL);8. if(!bi)9. return-ENOMEM;10. bi-n_board_info=n;11. memcpy(bi-board_info,info,n*size

42、of*info);12. 13. 14. mutex_lock(&board_lock);15. list_add_tail(&bi-list,&board_list);16. mutex_unlock(&board_lock);17. return0;18. 看一下創(chuàng)建新設(shè)備的函數(shù):view plain1. structspi_device*spi_new_device(structspi_master*master,2. structspi_board_info*chip)3. 4. structspi_device*proxy;5. intstatus;6. proxy=spi_allo

43、c_device(master);7. if(!proxy)8. returnNULL;9. 10. 11. WARN_ON(strlen(chip-modalias)=sizeof(proxy-modalias);12. /*初始化spi_device的各個字段*/13. proxy-chip_select=chip-chip_select;14. proxy-max_speed_hz=chip-max_speed_hz;15. proxy-mode=chip-mode;16. proxy-irq=chip-irq;17. /*這里獲得了spi_device的名字,這個modalias也是在

44、我們移植時在mach-smdk2440.c中的s3c2410_spi0_board中設(shè)定的*/18. strlcpy(proxy-modalias,chip-modalias,sizeof(proxy-modalias);19. proxy-dev.platform_data=(void*)chip-platform_data;20. proxy-controller_data=chip-controller_data;21. proxy-controller_state=NULL;22. /*主要完成將spi_device添加到內(nèi)核*/23. status=spi_add_device(pr

45、oxy);24. if(status0)25. spi_dev_put(proxy);26. returnNULL;27. 28. 29. 30. returnproxy;31. 下面來看分配spi_alloc_device的函數(shù),主要完成了分配spi_device,并初始化spi-dev的一些字段。view plain1. structspi_device*spi_alloc_device(structspi_master*master)2. 3. structspi_device*spi;4. structdevice*dev=master-dev.parent;5. if(!spi_ma

46、ster_get(master)6. returnNULL;7. spi=kzalloc(sizeof*spi,GFP_KERNEL);8. if(!spi)9. dev_err(dev,cannotallocspi_devicen);10. spi_master_put(master);11. returnNULL;12. 13. spi-master=master;14. spi-dev.parent=dev;15. /*設(shè)置總線是spi_bus_type,下面會講到spi_device與spi_driver是怎樣match上的*/16. spi-dev.bus=&spi_bus_type

47、;17. spi-dev.release=spidev_release;18. device_initialize(&spi-dev);19. returnspi;20. 下面來看分配的這個spi_device是怎樣注冊進內(nèi)核的:view plain1. intspi_add_device(structspi_device*spi)2. 3. staticDEFINE_MUTEX(spi_add_lock);4. structdevice*dev=spi-master-dev.parent;5. intstatus;6. /*spi_device的片選號不能大于spi控制器的片選數(shù)*/7. i

48、f(spi-chip_select=spi-master-num_chipselect)8. dev_err(dev,cs%d=max%dn,9. spi-chip_select,10. spi-master-num_chipselect);11. return-EINVAL;12. 13. /*這里設(shè)置是spi_device在Linux設(shè)備驅(qū)動模型中的name,也就是圖中的spi0.0,而在/dev/下設(shè)備節(jié)點的名字是proxy-modalias中的名字*/14. dev_set_name(&spi-dev,%s.%u,dev_name(&spi-master-dev),15. spi-ch

49、ip_select);16. mutex_lock(&spi_add_lock);17. /*如果總線上掛的設(shè)備已經(jīng)有這個名字,則設(shè)置狀態(tài)忙碌,并退出*/18. if(bus_find_device_by_name(&spi_bus_type,NULL,dev_name(&spi-dev)19. !=NULL)20. dev_err(dev,chipselect%dalreadyinusen,21. spi-chip_select);22. status=-EBUSY;23. gotodone;24. 25. /對spi_device的時鐘等進行設(shè)置/26. status=spi-master-setup(spi);27. if(statusdev),status);30. gotodone;31. 32. /*添加到內(nèi)核*/33. status=device_add(&spi-dev);34. if(status0)35. dev_err(dev,cant%s%s,status%dn,36. add

展開閱讀全文
溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

相關(guān)資源

更多
正為您匹配相似的精品文檔
關(guān)于我們 - 網(wǎng)站聲明 - 網(wǎng)站地圖 - 資源地圖 - 友情鏈接 - 網(wǎng)站客服 - 聯(lián)系我們

copyright@ 2023-2025  zhuangpeitu.com 裝配圖網(wǎng)版權(quán)所有   聯(lián)系電話:18123376007

備案號:ICP2024067431-1 川公網(wǎng)安備51140202000466號


本站為文檔C2C交易模式,即用戶上傳的文檔直接被用戶下載,本站只是中間服務(wù)平臺,本站所有文檔下載所得的收益歸上傳人(含作者)所有。裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對上載內(nèi)容本身不做任何修改或編輯。若文檔所含內(nèi)容侵犯了您的版權(quán)或隱私,請立即通知裝配圖網(wǎng),我們立即給予刪除!