linuxSPI驅(qū)動(dòng)框架源碼分析
《linuxSPI驅(qū)動(dòng)框架源碼分析》由會(huì)員分享,可在線閱讀,更多相關(guān)《linuxSPI驅(qū)動(dòng)框架源碼分析(32頁(yè)珍藏版)》請(qǐng)?jiān)谘b配圖網(wǎng)上搜索。
1、文檔供參考,可復(fù)制、編制,期待您的好評(píng)與關(guān)注! SPI協(xié)議是一種同步的串行數(shù)據(jù)連接標(biāo)準(zhǔn),由摩托羅拉公司命名,可工作于全雙工模式。相關(guān)通訊設(shè)備可工作于m/s模式。主設(shè)備發(fā)起數(shù)據(jù)幀,允許多個(gè)從設(shè)備的存在。每個(gè)從設(shè)備 有獨(dú)立的片選信號(hào),SPI一般來(lái)說(shuō)是四線串行總線結(jié)構(gòu)。 接口: SCLK——Serial Clock(output from master)時(shí)鐘(主設(shè)備發(fā)出) MOSI/SIMO——Master Output, Slave Input(output from master)數(shù)據(jù)信號(hào)線mosi(主設(shè)備發(fā)出) MISO/SOMI——Master Input,Slave Out
2、pu(output from slave)數(shù)據(jù)信號(hào)線(從設(shè)備) SS——Slave Select(active low;output from master)片選信號(hào) 下面來(lái)看一下Linux中的SPI驅(qū)動(dòng)。在Linux設(shè)備驅(qū)動(dòng)框架的設(shè)計(jì)中,有一個(gè)重要的主機(jī),外設(shè)驅(qū)動(dòng)框架分離的思想,如下圖。 外設(shè)a,b,c的驅(qū)動(dòng)與主機(jī)控制器A,B,C的驅(qū)動(dòng)不相關(guān),主機(jī)控制器驅(qū)動(dòng)不關(guān)心外設(shè),而外設(shè)驅(qū)動(dòng)也不關(guān)心主機(jī),外設(shè)只是訪問(wèn)核心層的通用的API進(jìn)行數(shù)據(jù)的傳輸,主機(jī)和外設(shè)之間可以進(jìn)行任意的組合。如果我們不進(jìn)行如圖的主機(jī)和外設(shè)分離,外設(shè)a,b,c和主機(jī)A,B,C進(jìn)行組合的時(shí)候,需要9種不同的驅(qū)動(dòng)。設(shè)想一共
3、有個(gè)主機(jī)控制器,n個(gè)外設(shè),分離的結(jié)構(gòu)是需要m+n個(gè)驅(qū)動(dòng),不分離則需要m*n個(gè)驅(qū)動(dòng)。 下面介紹spi子系統(tǒng)的數(shù)據(jù)結(jié)構(gòu): 在Linux中,使用spi_master結(jié)構(gòu)來(lái)描述一個(gè)SPI主機(jī)控制器的驅(qū)動(dòng)。 view plain 1. struct?spi_master?{?? 2. struct?device????dev;/*總線編號(hào),從0開始*/?? 3. s16????bus_num;/*支持的片選的數(shù)量,從設(shè)備的片選號(hào)不能大于這個(gè)數(shù)量*/?? 4. u16?num_chipselect;?? 5. u16??dma_a
4、lignment;/*改變spi_device的特性如:傳輸模式,字長(zhǎng),時(shí)鐘頻率*/?? 6. int??(*setup)(struct?spi_device?*spi);/*添加消息到隊(duì)列的方法,這個(gè)函數(shù)不可睡眠,他的任務(wù)是安排發(fā)生的傳送并且調(diào)用注冊(cè)的回調(diào)函數(shù)complete()*/?? 7. int?(*transfer)(struct?spi_device?*spi,struct?spi_message?*mesg);?? 8. void???(*cleanup)(struct?spi_device?*spi);?? 9. };?? 分配,注冊(cè)和注銷的SPI主機(jī)的
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來(lái)描述一個(gè)SPI外設(shè)驅(qū)動(dòng)。 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結(jié)構(gòu)體和platform_driver結(jié)構(gòu)體有極大的相似性,都有probe(),remove(),suspend(),resume()這樣的接口。 Linux用spi_device來(lái)描述一個(gè)SPI外設(shè)設(shè)備。 view plain 1. struct?spi_device?{?? 2. struct?device????????dev;?? 3. struct?spi_master???*master;???????//對(duì)應(yīng)的控制器指針u32?????? 4. max_speed_hz;??//spi通信的時(shí)鐘u8????????? 5. chip_
8、select;???//片選,用于區(qū)分同一總線上的不同設(shè)備?? 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;????//每個(gè)字長(zhǎng)的比特?cái)?shù)?? 16. int??????irq;??????????????//使用的中斷?? 17. void?????*controller_state;?? 18. void?????*controller_data;?? 19. char?????modalias[32];????//名字?? 20. };???? 如下圖,看這三個(gè)結(jié)構(gòu)的關(guān)系,這里spi_device與spi_master是同一個(gè)父設(shè)備,這是
11、在spi_new_device函數(shù)中設(shè)定的,一般這個(gè)設(shè)備是一個(gè)物理設(shè)備。 這里的spi_master_class,spi_bus_type又是什么呢,看下邊兩個(gè)結(jié)構(gòu)體: 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對(duì)應(yīng)spi中的spi bus總線,spidev的類定義
13、如下: view plain 1. static?struct?class?*spidev_class;??? 創(chuàng)建這個(gè)類的主要目的是使mdev/udev能在/dev下創(chuàng)建設(shè)備節(jié)點(diǎn)/dev/spiB.C。B代表總線,C代表片外設(shè)備的片選號(hào)。 下邊來(lái)看兩個(gè)板級(jí)的結(jié)構(gòu),其中spi_board_info用來(lái)初始化spi_device,s3c2410_spi_info用來(lái)初始化spi_master。這兩個(gè)板級(jí)的結(jié)構(gòu)需要在移植的時(shí)候在arch/arm/mach-s3c2440/mach-smdk2440.c中初始化。 view plain 1. struct?spi_board_info?{
14、?? 2. char?????modalias[32];???//設(shè)備與驅(qū)動(dòng)匹配的唯一標(biāo)識(shí)?? 3. const?void????*platform_data;?? 4. void?????*controller_data;?? 5. int????????irq;?? 6. u32?????max_speed_hz;?? 7. u16????????bus_num;???????//設(shè)備所歸屬的總線編號(hào)?? 8. u16??????chip_select;?? 9. u8??????mode;?? 10. };?? 11. struct?s3c2410_spi_info?
15、{?? 12. int?????pin_cs;?????????//芯片選擇管腳?? 13. unsigned?int????num_cs;?????????//總線上的設(shè)備數(shù)?? 14. int????????bus_num;????????//總線號(hào)?? 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是用來(lái)管理spi_board_info的結(jié)構(gòu),spi_board_info通過(guò)spi_register_board_info(struct spi_board_info const *info, unsigned n)交由boardinfo來(lái)管理,并掛到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. /*存放結(jié)構(gòu)體spi_board_info*/?? 7. struct?spi_board_info????board_info[0];?? 8. };??? s3c24xx_spi是S3C2440的SPI控制器在Linux內(nèi)核中的具體描述,該結(jié)構(gòu)包含spi_bitbang內(nèi)嵌結(jié)構(gòu),控制器時(shí)鐘頻率和占用的中斷資源等重要成員,其中spi_bitbang具體負(fù)責(zé)SPI數(shù)據(jù)的傳輸。 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. };?? 為了解決多個(gè)不同的SPI設(shè)備共享S
20、PI控制器而帶來(lái)的訪問(wèn)沖突,spi_bitbang使用內(nèi)核提供的工作隊(duì)列(workqueue)。workqueue是Linux內(nèi)核中定義的一種回調(diào)處理方式。采用這種方式需要傳輸數(shù)據(jù)時(shí),不直接完成數(shù)據(jù)的傳輸,而是將要傳輸?shù)墓ぷ鞣盅b成相應(yīng)的消息(spi_message),發(fā)送給對(duì)應(yīng)的workqueue,由與workqueue關(guān)聯(lián)的內(nèi)核守護(hù)線程(daemon)負(fù)責(zé)具體的執(zhí)行。由于workqueue會(huì)將收到的消息按時(shí)間先后順序排列,這樣就是對(duì)設(shè)備的訪問(wèn)嚴(yán)格串行化,解決了沖突。 view plain 1. struct?spi_bitban
21、g?{?? 2. struct?workqueue_struct?*workqueue;??????//工作隊(duì)列頭?? 3. struct?work_struct??work;????????????//每一次傳輸都傳遞下來(lái)一個(gè)spi_message,都向工作隊(duì)列頭添加一個(gè)?? 4. workspinlock_t????????lock;?? 5. struct?list_head???queue;???????????//掛接spi_message,如果上一次的spi_message還沒(méi)有處理完,接下來(lái)的spi_message就掛接在queue上等待處理?? 6. u8??????
22、??????busy;????????????//忙碌標(biāo)志?? 7. u8???????????use_dma;?? 8. u8??????????flags;?? 9. struct?spi_master?*master;/*一下3個(gè)函數(shù)都是在函數(shù)s3c24xx_spi_probe()中被初始化*/?? 10. int??(*setup_transfer)(struct?spi_device?*spi,struct?spi_transfer?*t);???//設(shè)置傳輸模式?? 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來(lái)實(shí)現(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. };?? 下面來(lái)看看spi_message: view plain 1. struct?spi_message?{?? 2. struct?list_head????transfers;???//此次消息的傳輸隊(duì)列,一個(gè)消息可以包含多個(gè)傳輸段?? 3. struct?spi_device?*spi;????????//傳輸?shù)哪康脑O(shè)備?? 4. unsigned??????is_dma_mapped:1;??//如果為真,此次調(diào)用提供dma和cpu虛擬地址?? 5. void???
25、???????(*complete)(void?*context);??//異步調(diào)用完成后的回調(diào)函數(shù)?? 6. void?????????*context;????????????????????//回調(diào)函數(shù)的參數(shù)?? 7. unsigned??????actual_length;???????????????//此次傳輸?shù)膶?shí)際長(zhǎng)度?? 8. int?????????status;??????????????????????//執(zhí)行的結(jié)果,成功被置0,否則是一個(gè)負(fù)的錯(cuò)誤碼?? 9. struct?list_head???queue;?? 10. void??????????*stat
26、e;?? 11. };???? 在有消息需要傳遞的時(shí)候,會(huì)將spi_transfer通過(guò)自己的transfer_list字段掛到spi_message的transfers鏈表頭上。spi_message用來(lái)原子的執(zhí)行spi_transfer表示的一串?dāng)?shù)組傳輸請(qǐng)求。這個(gè)傳輸隊(duì)列是原子的,這意味著在這個(gè)消息完成之前不會(huì)有其他消息占用總線。消息的執(zhí)行總是按照FIFO的順序。 下面看一看spi_transfer: view plain 1. struct?spi_transfer?{?? 2. const?void?*tx_buf;??//要寫入設(shè)備的數(shù)據(jù)(必須是dma_safe),或者為
27、NULL?? 3. void???????*rx_buf;??//要讀取的數(shù)據(jù)緩沖(必須是dma_safe),或者為NULL?? 4. unsigned???len;??????//tx和rx的大小(字節(jié)數(shù)),這里不是指它的和,而是各自的長(zhǎng)度,他們總是相等的?? 5. dma_addr_t????tx_dma;???//如果spi_message.is_dma_mapped是真,這個(gè)是tx的dma地址?? 6. dma_addr_t?rx_dma;???//如果spi_message.is_dma_mapped是真,這個(gè)是rx的dma地址?? 7. unsigned???cs_cha
28、nge:1;????//影響此次傳輸之后的片選,指示本次tranfer結(jié)束之后是否要重新片選并調(diào)用setup改變?cè)O(shè)置,這個(gè)標(biāo)志可以較少系統(tǒng)開銷u8?????? 8. bits_per_word;??//每個(gè)字長(zhǎng)的比特?cái)?shù),如果是0,使用默認(rèn)值?? 9. u16????????delay_usecs;????//此次傳輸結(jié)束和片選改變之間的延時(shí),之后就會(huì)啟動(dòng)另一個(gè)傳輸或者結(jié)束整個(gè)消息?? 10. u32???????speed_hz;???????//通信時(shí)鐘。如果是0,使用默認(rèn)值?? 11. struct?list_head?transfer_list;?//用來(lái)連接的雙向鏈表節(jié)點(diǎn)??
29、 12. };?? 嵌入式微處理器訪問(wèn)SPI設(shè)備有兩種方式:使用GPIO模擬SPI接口的工作時(shí)序或者使用SPI控制器。使用GPIO模擬SPI接口的工作時(shí)序是非常容易實(shí)現(xiàn)的,但是會(huì)導(dǎo)致大量的時(shí)間耗費(fèi)在模擬SPI接口的時(shí)序上,訪問(wèn)效率比較低,容易成為系統(tǒng)瓶頸。這里主要分析使用SPI控制器的情況。 這個(gè)是由sys文件系統(tǒng)導(dǎo)出的spi子系統(tǒng)在內(nèi)核中的視圖了。 首先了解一下Linux內(nèi)核中的幾個(gè)文件:spi.c也就是spi子系統(tǒng)的核心了,spi_s3c24xx.c是s3c24xx系列芯片的SPI controller驅(qū)動(dòng),它向更上層的SPI核心層(spi.c)提供接口用來(lái)控制芯片的SPI co
30、ntroller,是一個(gè)被其他驅(qū)動(dòng)使用的驅(qū)動(dòng)。而spidev.c是在核心層基礎(chǔ)之上將SPI controller模擬成一個(gè)字符型的驅(qū)動(dòng),向文件系統(tǒng)提供標(biāo)準(zhǔn)的文件系統(tǒng)接口,用來(lái)操作對(duì)應(yīng)的SPI controller。 下面我們來(lái)看看spi子系統(tǒng)是怎么注冊(cè)進(jìn)內(nèi)核的: 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?0)?? 11. ????????goto?err1;?? 12. ????status?=?class_register(&spi_master_class);?? 13. ????if?(status?0)?? 14. ????????goto?err2;?? 15. ????return?0;?? 16. err2:?? 17
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);?? 這里注冊(cè)了一個(gè)spi_bus_type,也就是一個(gè)spi總線,和一個(gè)spi_master的class。分別對(duì)應(yīng)上圖中sys/bus/下的spi目錄和sys/class/下的spi_master目錄。 下面來(lái)分析SPI control
33、ler驅(qū)動(dòng)的注冊(cè)與初始化過(guò)程,首先執(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這個(gè)平臺(tái)驅(qū)動(dòng)的注冊(cè),相應(yīng)的平臺(tái)設(shè)備在devs.c中定義,在smdk2440_devices中添加&s3c_devic
34、e_spi0,&s3c_device_spi1,這就生成了圖中所示的s3c24xx-spi.0與s3c24xx-spi.1,當(dāng)然了這圖是在網(wǎng)上找的,不是我畫的,所以是6410的。這里s3c24xx-spi.0表示s3c2440的spi controller的0號(hào)接口,s3c24xx-spi.1表示s3c2440的spi controller的1號(hào)接口。注冊(cè)了s3c24xx_spi_driver后,賦值了平臺(tái)驅(qū)動(dòng)的probe函數(shù)為s3c24xx_spi_probe。所以當(dāng)match成功后,調(diào)用s3c24xx_spi_probe,這里看其實(shí)現(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ù)據(jù),把s3c24xx_spi設(shè)為spi_master的私有數(shù)據(jù)*/??
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. ????/*驅(qū)動(dòng)移植的時(shí)候需要實(shí)現(xiàn)的重要結(jié)構(gòu),初始化為&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è)置平臺(tái)的私有數(shù)據(jù)為s3c24xx_spi*/??
32. ????platform_ 39、set_drvdata(pdev,?hw);??
33. ????init_completion(&hw->done);??
34. ??
35. ??
36. ????/*?setup?the?master?state.?*/??
37. ????/*該總線上的設(shè)備數(shù)*/??
38. ????master->num_chipselect?=?hw->pdata->num_cs;??
39. ????/*總線號(hào)*/????
40. ????master->bus_num?=?pdata->bus_num;??
41. ??
42. ??
43. ????/*?setup? 40、the?state?for?the?bitbang?driver?*/??
44. ????/*spi_bitbang專門負(fù)責(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. ????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. ????/*初始化設(shè)置寄存器,包括對(duì)SPIMOSI,SPIMISO,SPICLK引腳的設(shè)置*/??
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ù)中實(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. ????/*動(dòng)態(tài)創(chuàng)建一個(gè)work_struct結(jié)構(gòu),它的處理函數(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ù)據(jù)傳輸就是用這個(gè)方法*/??
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)用*/ 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中被調(diào)用*/??
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. ????/調(diào)用create_singlethread_workqueue創(chuàng)建單個(gè)工作線程/??
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?0)??
108. ????????goto?err2;??
109. ????return?status;??
110. err2:??
111. ????destroy_workqueue(bitbang->workqueue);??
112. err1:??
113. ????return?s 49、tatus;??
114. }
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. ????????/*遍歷每個(gè)boardinfo管理的spi_board_info,如果設(shè)備的總線號(hào)與控制器的總線好相等,則創(chuàng)建新設(shè)備*/?? 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. }?? 在移植的時(shí)候我們會(huì)在mach-smdk2440.c中的smdk2440_machine_init中添加spi_register_board_info 這個(gè)函數(shù)完成了將spi_board_info交由board
53、info管理,并把boardinfo掛載到board_list鏈表上。也就是說(shuō)在系統(tǒng)初始化的時(shí)候?qū)pi_device交由到掛在board_list上的boardinfo管理,在spi controller的driver注冊(cè)的時(shí)候不但注冊(cè)這個(gè)主機(jī)控制器的驅(qū)動(dòng),還要遍歷這個(gè)主機(jī)控制器的總線上的spi_device,將總線上的spi_device全部注冊(cè)進(jìn)內(nèi)核。當(dāng)注冊(cè)進(jìn)內(nèi)核并且spi_driver已經(jīng)注冊(cè)的時(shí)候,如果總線match成功,則會(huì)調(diào)用spi_driver的probe函數(shù),這個(gè)將在后邊進(jìn)行分析。 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è)備的函數(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的各個(gè)字段*/?? 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的名字,這個(gè)modalias也是在我們移植時(shí)在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_
59、state?=?NULL;?? 22. ????/*主要完成將spi_device添加到內(nèi)核*/?? 23. ????status?=?spi_add_device(proxy);?? 24. ????if?(status?0)?{?? 25. ????????spi_dev_put(proxy);?? 26. ????????return?NULL;?? 27. ????}?? 28. ?? 29. ?? 30. ????return?proxy;?? 31. }?? 下面來(lái)看分配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. ????/*設(shè)置總線是spi_bus_type,下面會(huì)講到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. }?? 下面來(lái)看分配的這個(gè)spi_device是怎樣注冊(cè)進(jìn)內(nèi)核的: 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的片選號(hào)不能大于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. ????/*這里設(shè)置是spi_device在Linux設(shè)備驅(qū)動(dòng)模型中的name,也就是圖中的spi0.0,而在/dev/下設(shè)備節(jié)點(diǎn)的名字是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. ????/*如果總線上掛的設(shè)備已經(jīng)有這個(gè)名字,則設(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?%d?already?in?use\n",?? 21. ????????????????spi->chip_select);?? 22. ???
66、?????status?=?-EBUSY;?? 23. ????????goto?done;?? 24. ????}?? 25. ????/對(duì)spi_device的時(shí)鐘等進(jìn)行設(shè)置/?? 26. ????status?=?spi->master->setup(spi);?? 27. ????if?(status?0)?{?? 28. ????????dev_err(dev,?"can't?%s?%s,?status?%d\n",?? 29. ????????????????"setup",?dev_name(&spi->dev),?status);?? 30. ????????goto?done;?? 31. ????}?? 32. ????/*添加到內(nèi)核*/?? 33. ????status?=?device_add(&spi->dev);?? 34. ????if?(status?0)?? 35. ????????dev_err(dev,?"can't?%s?%s,?status?%d\n",?? 36. ????????????????"add"
- 溫馨提示:
1: 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 市教育局冬季運(yùn)動(dòng)會(huì)安全工作預(yù)案
- 2024年秋季《思想道德與法治》大作業(yè)及答案3套試卷
- 2024年教師年度考核表個(gè)人工作總結(jié)(可編輯)
- 2024年xx村兩委涉案資金退還保證書
- 2024年憲法宣傳周活動(dòng)總結(jié)+在機(jī)關(guān)“弘揚(yáng)憲法精神推動(dòng)發(fā)改工作高質(zhì)量發(fā)展”專題宣講報(bào)告會(huì)上的講話
- 2024年XX村合作社年報(bào)總結(jié)
- 2024-2025年秋季第一學(xué)期初中歷史上冊(cè)教研組工作總結(jié)
- 2024年小學(xué)高級(jí)教師年終工作總結(jié)匯報(bào)
- 2024-2025年秋季第一學(xué)期初中物理上冊(cè)教研組工作總結(jié)
- 2024年xx鎮(zhèn)交通年度總結(jié)
- 2024-2025年秋季第一學(xué)期小學(xué)語(yǔ)文教師工作總結(jié)
- 2024年XX村陳規(guī)陋習(xí)整治報(bào)告
- 2025年學(xué)校元旦迎新盛典活動(dòng)策劃方案
- 2024年學(xué)校周邊安全隱患自查報(bào)告
- 2024年XX鎮(zhèn)農(nóng)村規(guī)劃管控述職報(bào)告