基于S3C2440的嵌入式Linux驅(qū)動——SPI子系統(tǒng)解讀(一)
本文將介紹SPI子系統(tǒng)。內(nèi)核版本為2.6.30。如有錯誤歡迎指正。
預(yù)備知識要求:1.SPI總線
2. platfrom平臺
3. sysfs子系統(tǒng)
4. 閱讀過LDD3第3,5,6,7,9,10,11章的內(nèi)容。
NOTE:如果沒有看過LDD3的相關(guān)內(nèi)容,直接看內(nèi)核源碼將非常吃力!?。?/p>
PC主機:Ubuntu 和 redhat 9.0
目標板:TQ2440開發(fā)板 cpu:s3c2440 linux內(nèi)核:2.6.30
0.引言
本系列文章對Linux設(shè)備模型中的SPI子系統(tǒng)進行講解。SPI子系統(tǒng)的講解將分為4個部分。
第一部分,即本篇文章,將對SPI子系統(tǒng)整體進行描述,同時給出SPI的相關(guān)數(shù)據(jù)結(jié)構(gòu),最后描述SPI總線的注冊。
第二部分,該文將對SPI的主控制器(master)驅(qū)動進行描述。 基于S3C2440的嵌入式Linux驅(qū)動——SPI子系統(tǒng)解讀(二)
第三部分,該文將對SPI設(shè)備驅(qū)動,也稱protocol 驅(qū)動,進行講解?;赟3C2440的嵌入式Linux驅(qū)動——SPI子系統(tǒng)解讀(三)
第四部分,通過SPI設(shè)備驅(qū)動留給用戶層的API,我們將從上到下描述數(shù)據(jù)是如何通過SPI的protocol 驅(qū)動,由bitbang中轉(zhuǎn),最后由master驅(qū)動將數(shù)據(jù)傳輸出去。
基于S3C2440的嵌入式Linux驅(qū)動——SPI子系統(tǒng)解讀(四)
1.SPI子系統(tǒng)綜述
SPI子系統(tǒng)從上到下分為:spi設(shè)備驅(qū)動層,核心層和master驅(qū)動層。其中master驅(qū)動抽象出spi控制器的相關(guān)操作,而spi設(shè)備驅(qū)動層抽象出了用戶空間API。
platform_device結(jié)構(gòu)中描述了SPI控制器的相關(guān)資源,同時在板級信息中將會添加spi設(shè)備的相關(guān)信息。master驅(qū)動將以platform_driver形式體現(xiàn)出來,也就是說
在主控制器(master)和主控制器驅(qū)動將掛載到platform總線上。platform_driver的probe函數(shù)中將注冊spi_master,同時將會獲取在板級信息中添加的spi設(shè)備,將該
信息轉(zhuǎn)換成spi_device,然后注冊spi_device到spi總線上。spi_driver結(jié)構(gòu)用于描述spi設(shè)備驅(qū)動,也將掛載到spi總線上。連同spi_driver一起注冊的是字符設(shè)備,該
字符設(shè)備將提供5個API給用戶空間。通過API,用戶空間可以執(zhí)行半雙工讀、半雙工寫和全雙工讀寫。
2. SPI的相關(guān)數(shù)據(jù)結(jié)構(gòu)
這里將介紹內(nèi)核所用到的關(guān)鍵數(shù)據(jù)結(jié)構(gòu),還有些結(jié)構(gòu)將在用到時加以說明。
2.1 spi_master
該結(jié)構(gòu)用于描述SOC的SPI控制器,S3C2440共有兩個SPI控制器。
/**
*structspi_master-interfacetoSPImastercontroller
*@dev:deviceinterfacetothisdriver
*@bus_num:board-specific(andoftenSOC-specific)identifierfora
*givenSPIcontroller.
*@num_chipselect:chipselectsareusedtodistinguishindividual
*SPIslaves,andarenumberedfromzerotonum_chipselects.
*eachslavehasachipselectsignal,butit'scommonthatnot
*everychipselectisconnectedtoaslave.
*@dma_alignment:SPIcontrollerconstraintonDMAbuffersalignment.
*@setup:updatesthedevicemodeandclockingrecordsusedbya
*device'sSPIcontroller;protocolcodemaycallthis.This
*mustfailifanunrecognizedorunsupportedmodeisrequested.
*It'salwayssafetocallthisunlesstransfersarependingon
*thedevicewhosesettingsarebeingmodified.
*@transfer:addsamessagetothecontroller'stransferqueue.
*@cleanup:freescontroller-specificstate
*
*EachSPImastercontrollercancommunicatewithoneormore@spi_device
*children.Thesemakeasmallbus,sharingMOSI,MISOandSCKsignals
*butnotchipselectsignals.Eachdevicemaybeconfiguredtousea
*differentclockrate,sincethosesharedsignalsareignoredunless
*thechipisselected.
*
*ThedriverforanSPIcontrollermanagesaccesstothosedevicesthrough
*aqueueofspi_messagetransactions,copyingdatabetweenCPUmemoryand
*anSPIslavedevice.Foreachsuchmessageitqueues,itcallsthe
*message'scompletionfunctionwhenthetransactioncompletes.
*/
structspi_master{
structdevicedev;
/*otherthannegative(==assignonedynamically),bus_numisfully
*board-specific.usuallythatsimplifiestobeingSOC-specific.
*example:oneSOChasthreeSPIcontrollers,numbered0..2,
*andoneboard'sschematicsmightshowitusingSPI-2.software
*wouldnormallyusebus_num=2forthatcontroller.
*/
s16bus_num;
/*chipselectswillbeintegraltomanycontrollers;someothers
*mightuseboard-specificGPIOs.
*/
u16num_chipselect;//該值不能為0,否則會注冊失敗
/*someSPIcontrollersposealignmentrequirementsonDMAable
*buffers;letprotocoldriversknowabouttheserequirements.
*/
u16dma_alignment;
/*Setupmodeandclock,etc(spidrivermaycallmanytimes).
*
*IMPORTANT:thismaybecalledwhentransferstoanother
*deviceareactive.DONOTUPDATESHAREDREGISTERSinways
*whichcouldbreakthosetransfers.
*/
int(*setup)(structspi_device*spi);
/*bidirectionalbulktransfers
*
*+Thetransfer()methodmaynotsleep;itsmainroleis
*justtoaddthemessagetothequeue.
*+Fornowthere'snoremove-from-queueoperation,or
*anyotherrequestmanagement
*+Toagivenspi_device,messagequeueingispurefifo
*
*+Themaster'smainjobistoprocessitsmessagequeue,
*selectingachipthentransferringdata
*+Iftherearemultiplespi_devicechildren,thei/oqueue
* arbitration algorithm is unspecified (round