linuxSPI驅動框架源碼分析

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

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

0 積分

下載資源

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

資源描述:

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

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

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

3、有個主機控制器,n個外設,分離的結構是需要m+n個驅動,不分離則需要m*n個驅動。 下面介紹spi子系統(tǒng)的數(shù)據結構: 在Linux中,使用spi_master結構來描述一個SPI主機控制器的驅動。 view plain 1. struct?spi_master?{?? 2. struct?device????dev;/*總線編號,從0開始*/?? 3. s16????bus_num;/*支持的片選的數(shù)量,從設備的片選號不能大于這個數(shù)量*/?? 4. u16?num_chipselect;?? 5. u16??dma_a

4、lignment;/*改變spi_device的特性如:傳輸模式,字長,時鐘頻率*/?? 6. int??(*setup)(struct?spi_device?*spi);/*添加消息到隊列的方法,這個函數(shù)不可睡眠,他的任務是安排發(fā)生的傳送并且調用注冊的回調函數(shù)complete()*/?? 7. int?(*transfer)(struct?spi_device?*spi,struct?spi_message?*mesg);?? 8. void???(*cleanup)(struct?spi_device?*spi);?? 9. };?? 分配,注冊和注銷的SPI主機的

5、API由SPI核心提供: view plain 1. struct?spi_master?*spi_alloc_master(struct?device?*host,?unsigned?size);?? 2. int?spi_register_master(struct?spi_master?*master);?? 3. void?spi_unregister_master(struct?spi_master?*master);???? 在Linux中用spi_driver來描述一個SPI外設驅動。 view plain 1. struct?spi_driver?{?? 2

6、. int???(*probe)(struct?spi_device?*spi);?? 3. int???(*remove)(struct?spi_device?*spi);?? 4. void??(*shutdown)(struct?spi_device?*spi);?? 5. int???(*suspend)(struct?spi_device?*spi,?pm_message_t?mesg);?? 6. int???(*resume)(struct?spi_device?*spi);?? 7. struct?device_driver??driver;?? 8. };???

7、 可以看出,spi_driver結構體和platform_driver結構體有極大的相似性,都有probe(),remove(),suspend(),resume()這樣的接口。 Linux用spi_device來描述一個SPI外設設備。 view plain 1. struct?spi_device?{?? 2. struct?device????????dev;?? 3. struct?spi_master???*master;???????//對應的控制器指針u32?????? 4. max_speed_hz;??//spi通信的時鐘u8????????? 5. chip_

8、select;???//片選,用于區(qū)分同一總線上的不同設備?? 6. u8??mode;?? 7. #define????SPI_CPHA????0x01????????????/*?clock?phase?*/?? 8. #define????SPI_CPOL????0x02????????????/*?clock?polarity?*/?? 9. #define?SPI_MODE_0??(0|0)???????????/*?(original?MicroWire)?*/#define???SPI_MODE_1??(0|SPI_CPHA)?? 10. #define?SPI_MOD

9、E_2??(SPI_CPOL|0)?? 11. #define?SPI_MODE_3??(SPI_CPOL|SPI_CPHA)#define??SPI_CS_HIGH?0x04????????????/*?chipselect?active?high??*/?? 12. #define????SPI_LSB_FIRST???0x08????????????/*?per-word?bits-on-wire?*/?? 13. #define??SPI_3WIRE???0x10????????????/*?SI/SO?signals?shared?*/?? 14. #define???SPI

10、_LOOP????0x20????????????/*?loopback?mode?*/?? 15. u8??????bits_per_word;????//每個字長的比特數(shù)?? 16. int??????irq;??????????????//使用的中斷?? 17. void?????*controller_state;?? 18. void?????*controller_data;?? 19. char?????modalias[32];????//名字?? 20. };???? 如下圖,看這三個結構的關系,這里spi_device與spi_master是同一個父設備,這是

11、在spi_new_device函數(shù)中設定的,一般這個設備是一個物理設備。 這里的spi_master_class,spi_bus_type又是什么呢,看下邊兩個結構體: view plain 1. struct?bus_type?spi_bus_type?=?{????? 2. ???.name???????=?"spi",?? 3. ???.dev_attrs??=?spi_dev_attrs,?? 4. ???.match????=?spi_match_device,?? 5. ???.uevent???=?spi_uevent,??? 6. ???.suspend??

12、=?spi_suspend,?? 7. ???.resume???=?spi_resume,?? 8. };??? 9. static?struct?class?spi_master_class?=?{????? 10. ????.name?????????????=?"spi_master",??? 11. ????.owner???????????=?THIS_MODULE,?? 12. ????.dev_release????=?spi_master_release,?? 13. };???? spi_bus_type對應spi中的spi bus總線,spidev的類定義

13、如下: view plain 1. static?struct?class?*spidev_class;??? 創(chuàng)建這個類的主要目的是使mdev/udev能在/dev下創(chuàng)建設備節(jié)點/dev/spiB.C。B代表總線,C代表片外設備的片選號。 下邊來看兩個板級的結構,其中spi_board_info用來初始化spi_device,s3c2410_spi_info用來初始化spi_master。這兩個板級的結構需要在移植的時候在arch/arm/mach-s3c2440/mach-smdk2440.c中初始化。 view plain 1. struct?spi_board_info?{

14、?? 2. char?????modalias[32];???//設備與驅動匹配的唯一標識?? 3. const?void????*platform_data;?? 4. void?????*controller_data;?? 5. int????????irq;?? 6. u32?????max_speed_hz;?? 7. u16????????bus_num;???????//設備所歸屬的總線編號?? 8. u16??????chip_select;?? 9. u8??????mode;?? 10. };?? 11. struct?s3c2410_spi_info?

15、{?? 12. int?????pin_cs;?????????//芯片選擇管腳?? 13. unsigned?int????num_cs;?????????//總線上的設備數(shù)?? 14. int????????bus_num;????????//總線號?? 15. void?(*gpio_setup)(struct?s3c2410_spi_info?*spi,?int?enable);?????//spi管腳配置函數(shù)?? 16. void?(*set_cs)(struct?s3c2410_spi_info?*spi,?int?cs,?int?pol);?? 17. };????

16、 boardinfo是用來管理spi_board_info的結構,spi_board_info通過spi_register_board_info(struct spi_board_info const *info, unsigned n)交由boardinfo來管理,并掛到board_list鏈表上,list_add_tail(&bi->list,&board_list); view plain 1. struct?boardinfo?{??? 2. ?/*用于掛到鏈表頭board_list上*/?? 3. struct?list_head??list;?? 4. /*管理的spi_

17、board_info的數(shù)量*/?? 5. unsigned??n_board_info;?? 6. /*存放結構體spi_board_info*/?? 7. struct?spi_board_info????board_info[0];?? 8. };??? s3c24xx_spi是S3C2440的SPI控制器在Linux內核中的具體描述,該結構包含spi_bitbang內嵌結構,控制器時鐘頻率和占用的中斷資源等重要成員,其中spi_bitbang具體負責SPI數(shù)據的傳輸。 view plain 1. struct?s3c24xx_spi?{?? 2. /*?bitbang?h

18、as?to?be?first?*/?? 3. struct?spi_bitbang??bitbang;?? 4. struct?completion???done;?? 5. void?__iomem??????*regs;?? 6. int????????????irq;?? 7. int?????????????len;?? 8. int?????????????count;?? 9. void?????????(*set_cs)(struct?s3c2410_spi_info?*spi,??int?cs,?int?pol);?? 10. /*?data?buffers?*

19、/const?unsigned?char?*tx;?? 11. unsigned?char???????*rx;?? 12. struct?clk??????*clk;?? 13. struct?resource????????*ioarea;?? 14. struct?spi_master???*master;?? 15. struct?spi_device???*curdev;?? 16. struct?device???????*dev;?? 17. struct?s3c2410_spi_info?*pdata;?? 18. };?? 為了解決多個不同的SPI設備共享S

20、PI控制器而帶來的訪問沖突,spi_bitbang使用內核提供的工作隊列(workqueue)。workqueue是Linux內核中定義的一種回調處理方式。采用這種方式需要傳輸數(shù)據時,不直接完成數(shù)據的傳輸,而是將要傳輸?shù)墓ぷ鞣盅b成相應的消息(spi_message),發(fā)送給對應的workqueue,由與workqueue關聯(lián)的內核守護線程(daemon)負責具體的執(zhí)行。由于workqueue會將收到的消息按時間先后順序排列,這樣就是對設備的訪問嚴格串行化,解決了沖突。 view plain 1. struct?spi_bitban

21、g?{?? 2. struct?workqueue_struct?*workqueue;??????//工作隊列頭?? 3. struct?work_struct??work;????????????//每一次傳輸都傳遞下來一個spi_message,都向工作隊列頭添加一個?? 4. workspinlock_t????????lock;?? 5. struct?list_head???queue;???????????//掛接spi_message,如果上一次的spi_message還沒有處理完,接下來的spi_message就掛接在queue上等待處理?? 6. u8??????

22、??????busy;????????????//忙碌標志?? 7. u8???????????use_dma;?? 8. u8??????????flags;?? 9. struct?spi_master?*master;/*一下3個函數(shù)都是在函數(shù)s3c24xx_spi_probe()中被初始化*/?? 10. int??(*setup_transfer)(struct?spi_device?*spi,struct?spi_transfer?*t);???//設置傳輸模式?? 11. void????(*chipselect)(struct?spi_device?*spi,?int

23、?is_on);????????????????????//片選?? 12. #define????BITBANG_CS_ACTIVE???1???/*?normally?nCS,?active?low?*/?? 13. #define???BITBANG_CS_INACTIVE?0/*傳輸函數(shù),由s3c24xx_spi_txrx來實現(xiàn)*/?? 14. int???(*txrx_bufs)(struct?spi_device?*spi,?struct?spi_transfer?*t);?? 15. u32????(*txrx_word[4])(struct?spi_device?*sp

24、i,unsigned?nsecs,u32?word,?u8?bits);?? 16. };?? 下面來看看spi_message: view plain 1. struct?spi_message?{?? 2. struct?list_head????transfers;???//此次消息的傳輸隊列,一個消息可以包含多個傳輸段?? 3. struct?spi_device?*spi;????????//傳輸?shù)哪康脑O備?? 4. unsigned??????is_dma_mapped:1;??//如果為真,此次調用提供dma和cpu虛擬地址?? 5. void???

25、???????(*complete)(void?*context);??//異步調用完成后的回調函數(shù)?? 6. void?????????*context;????????????????????//回調函數(shù)的參數(shù)?? 7. unsigned??????actual_length;???????????????//此次傳輸?shù)膶嶋H長度?? 8. int?????????status;??????????????????????//執(zhí)行的結果,成功被置0,否則是一個負的錯誤碼?? 9. struct?list_head???queue;?? 10. void??????????*stat

26、e;?? 11. };???? 在有消息需要傳遞的時候,會將spi_transfer通過自己的transfer_list字段掛到spi_message的transfers鏈表頭上。spi_message用來原子的執(zhí)行spi_transfer表示的一串數(shù)組傳輸請求。這個傳輸隊列是原子的,這意味著在這個消息完成之前不會有其他消息占用總線。消息的執(zhí)行總是按照FIFO的順序。 下面看一看spi_transfer: view plain 1. struct?spi_transfer?{?? 2. const?void?*tx_buf;??//要寫入設備的數(shù)據(必須是dma_safe),或者為

27、NULL?? 3. void???????*rx_buf;??//要讀取的數(shù)據緩沖(必須是dma_safe),或者為NULL?? 4. unsigned???len;??????//tx和rx的大小(字節(jié)數(shù)),這里不是指它的和,而是各自的長度,他們總是相等的?? 5. dma_addr_t????tx_dma;???//如果spi_message.is_dma_mapped是真,這個是tx的dma地址?? 6. dma_addr_t?rx_dma;???//如果spi_message.is_dma_mapped是真,這個是rx的dma地址?? 7. unsigned???cs_cha

28、nge:1;????//影響此次傳輸之后的片選,指示本次tranfer結束之后是否要重新片選并調用setup改變設置,這個標志可以較少系統(tǒng)開銷u8?????? 8. bits_per_word;??//每個字長的比特數(shù),如果是0,使用默認值?? 9. u16????????delay_usecs;????//此次傳輸結束和片選改變之間的延時,之后就會啟動另一個傳輸或者結束整個消息?? 10. u32???????speed_hz;???????//通信時鐘。如果是0,使用默認值?? 11. struct?list_head?transfer_list;?//用來連接的雙向鏈表節(jié)點??

29、 12. };?? 嵌入式微處理器訪問SPI設備有兩種方式:使用GPIO模擬SPI接口的工作時序或者使用SPI控制器。使用GPIO模擬SPI接口的工作時序是非常容易實現(xiàn)的,但是會導致大量的時間耗費在模擬SPI接口的時序上,訪問效率比較低,容易成為系統(tǒng)瓶頸。這里主要分析使用SPI控制器的情況。 這個是由sys文件系統(tǒng)導出的spi子系統(tǒng)在內核中的視圖了。 首先了解一下Linux內核中的幾個文件:spi.c也就是spi子系統(tǒng)的核心了,spi_s3c24xx.c是s3c24xx系列芯片的SPI controller驅動,它向更上層的SPI核心層(spi.c)提供接口用來控制芯片的SPI co

30、ntroller,是一個被其他驅動使用的驅動。而spidev.c是在核心層基礎之上將SPI controller模擬成一個字符型的驅動,向文件系統(tǒng)提供標準的文件系統(tǒng)接口,用來操作對應的SPI controller。 下面我們來看看spi子系統(tǒng)是怎么注冊進內核的: view plain 1. static?int?__init?spi_init(void)?? 2. {?? 3. ????int?status;?? 4. ????buf?=?kmalloc(SPI_BUFSIZ,?GFP_KERNEL);?? 5. ????if?(!buf)?{?? 6. ????????sta

31、tus?=?-ENOMEM;?? 7. ????????goto?err0;?? 8. ????}?? 9. ????status?=?bus_register(&spi_bus_type);?? 10. ????if?(status?

32、. ????bus_unregister(&spi_bus_type);?? 18. err1:?? 19. ????kfree(buf);?? 20. ????buf?=?NULL;?? 21. err0:?? 22. ????return?status;?? 23. }?? 24. postcore_initcall(spi_init);?? 這里注冊了一個spi_bus_type,也就是一個spi總線,和一個spi_master的class。分別對應上圖中sys/bus/下的spi目錄和sys/class/下的spi_master目錄。 下面來分析SPI control

33、ler驅動的注冊與初始化過程,首先執(zhí)行的是s3c24xx_spi_init。 view plain 1. static?int?__init?s3c24xx_spi_init(void)?? 2. {?? 3. ????????return?platform_driver_probe(&s3c24xx_spi_driver,?s3c24xx_spi_probe);?? 4. }?? platform_driver_probe中完成了s3c24xx_spi_driver這個平臺驅動的注冊,相應的平臺設備在devs.c中定義,在smdk2440_devices中添加&s3c_devic

34、e_spi0,&s3c_device_spi1,這就生成了圖中所示的s3c24xx-spi.0與s3c24xx-spi.1,當然了這圖是在網上找的,不是我畫的,所以是6410的。這里s3c24xx-spi.0表示s3c2440的spi controller的0號接口,s3c24xx-spi.1表示s3c2440的spi controller的1號接口。注冊了s3c24xx_spi_driver后,賦值了平臺驅動的probe函數(shù)為s3c24xx_spi_probe。所以當match成功后,調用s3c24xx_spi_probe,這里看其實現(xiàn): view plain 1.

35、e="font-size:18px;">static?int?__init?s3c24xx_spi_probe(struct?platform_device?*pdev)?? 2. {?? 3. ????struct?s3c2410_spi_info?*pdata;?? 4. ????struct?s3c24xx_spi?*hw;?? 5. ????struct?spi_master?*master;?? 6. ????struct?resource?*res;?? 7. ????int?err?=?0;?? 8. ????/*分配struct?spi_master+struct

36、?s3c24xx_spi大小的數(shù)據,把s3c24xx_spi設為spi_master的私有數(shù)據*/?? 9. ????master?=?spi_alloc_master(&pdev->dev,?sizeof(struct?s3c24xx_spi));?? 10. ????if?(master?==?NULL)?{?? 11. ????????dev_err(&pdev->dev,?"No?memory?for?spi_master\n");?? 12. ????????err?=?-ENOMEM;?? 13. ????????goto?err_nomem;?? 14. ????}?

37、? 15. ????/*從master中獲得s3c24xx_spi*/?? 16. ????hw?=?spi_master_get_devdata(master);?? 17. ????memset(hw,?0,?sizeof(struct?s3c24xx_spi));?? 18. ?? 19. ?? 20. ????hw->master?=?spi_master_get(master);?? 21. ????/*驅動移植的時候需要實現(xiàn)的重要結構,初始化為&s3c2410_spi0_platdata*/?? 22. ????hw->pdata?=?pdata?=?pdev->d

38、ev.platform_data;?? 23. ????hw->dev?=?&pdev->dev;?? 24. ?? 25. ?? 26. ????if?(pdata?==?NULL)?{?? 27. ????????dev_err(&pdev->dev,?"No?platform?data?supplied\n");?? 28. ????????err?=?-ENOENT;?? 29. ????????goto?err_no_pdata;?? 30. ????}?? 31. ????/*設置平臺的私有數(shù)據為s3c24xx_spi*/?? 32. ????platform_

39、set_drvdata(pdev,?hw);?? 33. ????init_completion(&hw->done);?? 34. ?? 35. ?? 36. ????/*?setup?the?master?state.?*/?? 37. ????/*該總線上的設備數(shù)*/?? 38. ????master->num_chipselect?=?hw->pdata->num_cs;?? 39. ????/*總線號*/???? 40. ????master->bus_num?=?pdata->bus_num;?? 41. ?? 42. ?? 43. ????/*?setup?

40、the?state?for?the?bitbang?driver?*/?? 44. ????/*spi_bitbang專門負責數(shù)據的傳輸*/?? 45. ????hw->bitbang.master?????????=?hw->master;?? 46. ????hw->bitbang.setup_transfer?=?s3c24xx_spi_setupxfer;?? 47. ????hw->bitbang.chipselect?????=?s3c24xx_spi_chipsel;?? 48. ????hw->bitbang.txrx_bufs??????=?s3c24xx_spi_

41、txrx;?? 49. ????hw->bitbang.master->setup??=?s3c24xx_spi_setup;?? 50. ?? 51. ?? 52. ????dev_dbg(hw->dev,?"bitbang?at?%p\n",?&hw->bitbang);?? 53. ??????? 54. ????。。。。。。。。。。。。。。。。。。。。。。。。?? 55. ?????? 56. ????/*初始化設置寄存器,包括對SPIMOSI,SPIMISO,SPICLK引腳的設置*/?? 57. ????s3c24xx_spi_initialsetup(hw);?

42、? 58. ?? 59. ?? 60. ????/*?register?our?spi?controller?*/?? 61. ?? 62. ?? 63. ????err?=?spi_bitbang_start(&hw->bitbang);?? 64. ????????。。。。。。。。。。。。。。。。。。。。。?? 65. }?? 66. spi?controller的register在spi_bitbang_start函數(shù)中實現(xiàn):?? 67. int?spi_bitbang_start(struct?spi_bitbang?*bitbang)?? 68. {?? 69

43、. ????int?status;?? 70. ?? 71. ?? 72. ????if?(!bitbang->master?||?!bitbang->chipselect)?? 73. ????????return?-EINVAL;?? 74. ????/*動態(tài)創(chuàng)建一個work_struct結構,它的處理函數(shù)是bitbang_work*/?? 75. ????INIT_WORK(&bitbang->work,?bitbang_work);?? 76. ????spin_lock_init(&bitbang->lock);?? 77. ????INIT_LIST_HEAD(&b

44、itbang->queue);?? 78. ????/*spi的數(shù)據傳輸就是用這個方法*/?? 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中被調用*/

45、?? 84. ????????bitbang->txrx_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的處理

46、方法,在spi_new_device中被調用*/?? 90. ????????????bitbang->master->setup?=?spi_bitbang_setup;?? 91. ????????????bitbang->master->cleanup?=?spi_bitbang_cleanup;?? 92. ????????}?? 93. ????}?else?if?(!bitbang->master->setup)?? 94. ????????return?-EINVAL;?? 95. ?? 96. ?? 97. ????/*?this?task?is?the?onl

47、y?thing?to?touch?the?SPI?bits?*/?? 98. ????bitbang->busy?=?0;?? 99. ????/調用create_singlethread_workqueue創(chuàng)建單個工作線程/?? 100. ????bitbang->workqueue?=?create_singlethread_workqueue(?? 101. ????????????dev_name(bitbang->master->dev.parent));?? 102. ????if?(bitbang->workqueue?==?NULL)?{?? 103. ??????

48、??status?=?-EBUSY;?? 104. ????????goto?err1;?? 105. ????}?? 106. ????status?=?spi_register_master(bitbang->master);?? 107. ????if?(status?workqueue);?? 112. err1:?? 113. ????return?s

49、tatus;?? 114. }?? 然后看這里是怎樣注冊spi主機控制器驅動的: view plain 1. int?spi_register_master(struct?spi_master?*master)?? 2. {?? 3. ????。。。。。。。。。。。。。。。。?? 4. ????/*將spi添加到內核,這也是sys/class/Spi_master下產生Spi0,Spi1的原因*/?? 5. ????dev_set_name(&master->dev,?"spi%u",?master->bus_num);?? 6. ????status?=?de

50、vice_add(&master->dev);?? 7. ????scan_boardinfo(master);?? 8. }?? 這里跟蹤scan_boardinfo函數(shù): view plain 1. static?void?scan_boardinfo(struct?spi_master?*master)?? 2. {?? 3. ????struct?boardinfo????*bi;?? 4. mutex_lock(&board_lock);?? 5. ????/*遍歷所有掛在board_list上的struct?boardinfo*/?? 6. ????list_f

51、or_each_entry(bi,?&board_list,?list)?{?? 7. ????????struct?spi_board_info???*chip?=?bi->board_info;?? 8. ????????unsigned????n;?? 9. ????????/*遍歷每個boardinfo管理的spi_board_info,如果設備的總線號與控制器的總線好相等,則創(chuàng)建新設備*/?? 10. ????????for?(n?=?bi->n_board_info;?n?>?0;?n--,?chip++)?{?? 11. ????????????if?(chip->bu

52、s_num?!=?master->bus_num)?? 12. ????????????????continue;?? 13. ????????????(void)?spi_new_device(master,?chip);?? 14. ????????}?? 15. ????}?? 16. ????mutex_unlock(&board_lock);?? 17. }?? 在移植的時候我們會在mach-smdk2440.c中的smdk2440_machine_init中添加spi_register_board_info 這個函數(shù)完成了將spi_board_info交由board

53、info管理,并把boardinfo掛載到board_list鏈表上。也就是說在系統(tǒng)初始化的時候將spi_device交由到掛在board_list上的boardinfo管理,在spi controller的driver注冊的時候不但注冊這個主機控制器的驅動,還要遍歷這個主機控制器的總線上的spi_device,將總線上的spi_device全部注冊進內核。當注冊進內核并且spi_driver已經注冊的時候,如果總線match成功,則會調用spi_driver的probe函數(shù),這個將在后邊進行分析。 view plain 1. i

54、nt?__init?? 2. spi_register_board_info(struct?spi_board_info?const?*info,?unsigned?n)?? 3. {?? 4. ????struct?boardinfo????*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.

55、 ????memcpy(bi->board_info,?info,?n?*?sizeof?*info);?? 12. ?? 13. ?? 14. ????mutex_lock(&board_lock);?? 15. ????list_add_tail(&bi->list,?&board_list);?? 16. ????mutex_unlock(&board_lock);?? 17. ????return?0;?? 18. }?? 看一下創(chuàng)建新設備的函數(shù): view plain 1. struct

56、?spi_device?*spi_new_device(struct?spi_master?*master,?? 2. ??????????????????struct?spi_board_info?*chip)?? 3. {?? 4. ????struct?spi_device???*proxy;?? 5. ????int?????????status;?? 6. ????proxy?=?spi_alloc_device(master);?? 7. ????if?(!proxy)?? 8. ????????return?NULL;?? 9. ?? 10. ?? 11. ?

57、???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_devic

58、e的名字,這個modalias也是在我們移植時在mach-smdk2440.c中的s3c2410_spi0_board中設定的*/?? 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_

59、state?=?NULL;?? 22. ????/*主要完成將spi_device添加到內核*/?? 23. ????status?=?spi_add_device(proxy);?? 24. ????if?(status??? 下面來看分配spi_alloc_device的函數(shù),主要完成了分配spi_devic

60、e,并初始化spi->dev的一些字段。 view plain 1. struct?spi_device?*spi_alloc_device(struct?spi_master?*master)?? 2. {?? 3. ????struct?spi_device???*spi;?? 4. ????struct?device???????*dev?=?master->dev.parent;?? 5. ????if?(!spi_master_get(master))?? 6. ????????return?NULL;?? 7. ????spi?=?kzalloc(sizeof?

61、*spi,?GFP_KERNEL);?? 8. ????if?(!spi)?{?? 9. ????????dev_err(dev,?"cannot?alloc?spi_device\n");?? 10. ????????spi_master_put(master);?? 11. ????????return?NULL;?? 12. ????}?? 13. ????spi->master?=?master;?? 14. ????spi->dev.parent?=?dev;?? 15. ????/*設置總線是spi_bus_type,下面會講到spi_device與spi_driv

62、er是怎樣match上的*/?? 16. ????spi->dev.bus?=?&spi_bus_type;?? 17. ????spi->dev.release?=?spidev_release;?? 18. ????device_initialize(&spi->dev);?? 19. ????return?spi;?? 20. }?? 下面來看分配的這個spi_device是怎樣注冊進內核的: view plain 1. int?spi_add_device(struct?spi_device?*spi)?? 2. {?? 3. ????static?DEFINE

63、_MUTEX(spi_add_lock);?? 4. ????struct?device?*dev?=?spi->master->dev.parent;?? 5. ????int?status;?? 6. ????/*spi_device的片選號不能大于spi控制器的片選數(shù)*/?? 7. ????if?(spi->chip_select?>=?spi->master->num_chipselect)?{?? 8. ????????dev_err(dev,?"cs%d?>=?max?%d\n",?? 9. ????????????spi->chip_select,?? 10. ??

64、??????????spi->master->num_chipselect);?? 11. ????????return?-EINVAL;?? 12. ????}?? 13. ????/*這里設置是spi_device在Linux設備驅動模型中的name,也就是圖中的spi0.0,而在/dev/下設備節(jié)點的名字是proxy->modalias中的名字*/?? 14. ????dev_set_name(&spi->dev,?"%s.%u",?dev_name(&spi->master->dev),?? 15. ????????????spi->chip_select);?? 16.

65、????mutex_lock(&spi_add_lock);?? 17. ????/*如果總線上掛的設備已經有這個名字,則設置狀態(tài)忙碌,并退出*/?? 18. ????if?(bus_find_device_by_name(&spi_bus_type,?NULL,?dev_name(&spi->dev))?? 19. ????????????!=?NULL)?{?? 20. ????????dev_err(dev,?"chipselect?%d?already?in?use\n",?? 21. ????????????????spi->chip_select);?? 22. ???

66、?????status?=?-EBUSY;?? 23. ????????goto?done;?? 24. ????}?? 25. ????/對spi_device的時鐘等進行設置/?? 26. ????status?=?spi->master->setup(spi);?? 27. ????if?(status?dev),?status);?? 30. ????????goto?done;?? 31. ????}?? 32. ????/*添加到內核*/?? 33. ????status?=?device_add(&spi->dev);?? 34. ????if?(status?

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

相關資源

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

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

備案號:ICP2024067431-1 川公網安備51140202000466號


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