platform device

北極皎狐發表於2013-01-15
platform device
=================
  標頭檔案:linux/platform_device.h
  
為什麼使用 platform device?
--------------------------
    
  從硬體的角度來說,整合在嵌入式晶片內部的外設離CPU最近,它們不依附於GPIO或者PCI,I2C此類的
  匯流排,它們掛接在soc記憶體空間,cpu靠操作這些soc記憶體空間來控制這些片內的外設。
  從驅動的角度,為了獲取這些掛接在soc記憶體空間的外設的資源,linux系統專門定義了一類匯流排來
  掛接它們。這就是platform匯流排,掛接在此匯流排上的裝置稱為platform device,操作裝置的驅動
  叫做platform driver。
  platform device的作用就是描述片內外設的資源,結構體的定義如下
  struct platform_device{
    const char *name;// 裝置號
    struct device *dev;
    u32 num_resources;// 裝置使用的資源的數量
    struct resource *resource;// 資源陣列
  };

  而platform driver的作用就是獲得platform device描述的這些資源,並加以利用。結構體的定義
  如下
  struct platform_driver {
    int (*probe)(struct platform_device *); //平臺探測函式
    int (*remove)(struct platform_device *);//平臺移除函式
    void (*shutdown)(struct platform_device *);//關閉
    int (*suspend)(struct platform_device *, pm_message_t state);//掛起
    int (*resume)(struct platform_device *);//恢復
    struct device_driver driver;//裝置驅動
    const struct platform_device_id *id_table;//描述支援的裝置的名單
  };  
  其中probe函式--平臺探測函式,就是平臺裝置驅動存在的首要目的,它的作用就是獲取平臺裝置的資源
  然後用這些資源坐其他的工作。比如,LCD platform driver的probe函式就是要獲得LCD控制器的
  資源,還有其他的諸如分配顯示記憶體等準備工作,然後再註冊framebuffer裝置。I2C也是一樣,在平臺
  探測函式中初始化I2C裝置的資源,然後註冊i2c_adapter。

如何使用platform device
-----------------------
  首先,platform device描述的是cpu的片內外設的資源,,屬於板級配置,所以習慣上需要在系統初
  始化階段(一般在arch init階段)被註冊。有兩種方式
  -->int platform_add_devices(struct platform_device device_array[], int 
     array_size);
     定義一個platform_device陣列,然後一舉進行註冊,一塊板子可以定義多個陣列在不同的初始化
     階段註冊
  -->int platform_device_register(struct platform_device *);
     單獨對某個platform device進行註冊
  
  platform data: platform_device結構體中的dev成員,它的型別為struct device,在這個結
  構體中定義了一個void* platform_data,它被用來指向平臺的裝置需要的資料。比如LCD控制器需要
  驅動具體的LCD螢幕,這個螢幕有諸多引數如同步訊號引腳的訊號極性,螢幕的解析度即畫素位等
  等。驅動程式不知道當前的系統用的是什麼顯示裝置(可能還不是LCD)以及這些LCD屏的引數都是些什麼
  ,所以這些引數在板級資料裡面定義起來,並且被被platform_data指向以便於驅動程式讀取。

  其次,如何進行匹配,基一個platform device怎樣對應一個platform driver去驅動它。稍微細心
  一點就會想到platform_device中的name該不會真的就只是個name而已吧。形象地說它是一個type!
  當有一個platform driver被註冊的時候,platform匯流排首先會遍歷匯流排上的裝置並對其name進行
  匹配,如果匹配成功,那麼就會傳入這個裝置的指標並呼叫裝置驅動的probe函式進行...這裡是遍歷,
  遍歷的意思就是可能全部找完,隱含意思就是可能這個name會匹配多次-那麼就進行多次的probe呼叫!
  在設計probe函式的時候應注意此項特性,一般會在platform_device成員dev(struct device)
  的子成員id中進行區別,當系統有多個同類裝置時(比如多個LCD控制器)dev.id會被設定成不同的值
  以區別不同的裝置。從而也看出,platform_driver中id_table(struct platform_device_id)

  成員存在的意義了,表明它可以支援的裝置嘛。


probe函式
---------
  probe函式即平臺探測函式,作用就是獲取平臺裝置的資源,然後幹一些其他的事情,總之就是為某一項
  功能模組做好準備工作。常見的步驟如下(對於軟硬體資源的獲取,都會有錯誤檢測,一般有錯誤就返回
  一個錯誤碼錶示失敗了)
  
  -->首先獲取platform data(如果需要)
  -->獲得需要的平臺裝置的IO資源且ioremap
  -->獲得中斷號(如果需要)並申請中斷(在恰當時)
  -->獲得裝置時鐘,並使能時鐘(如果需要對暫存器進行設定)
  -->設定其他資源,引數(需要分配記憶體,初始化鎖...)以及自己的結構體
  -->初始化平臺裝置
  -->向系統註冊某項功能(如framebuffer裝置,i2c adapter)
  
platform_driver其他成員  
----------------------
  suspend:用於掛起裝置(sleep模式),即系統sleep的時候會呼叫此函式。對於一般的裝置,所做的
          工作就是停止裝置的時鐘,或者是讓裝置的時鐘率降到很低的值,然後儲存一定的引數(有時
          時鐘停止時,有些暫存器的值需要重新設定,軟體定義的狀態...)
  shutdown:用於關閉裝置,系統處於shut-down time的時候會呼叫此函式
  resume:用於從sleep模式將裝置喚醒,執行與sleep相反的動作,恢復裝置sleep前的狀態
  remove:裝置被移除的時候呼叫(嚴格來說是變成一個未繫結驅動的裝置),然後會涉及到與probe函式
          大致相反的動作,一般來說就是probe函式所有錯誤處理時釋放資源的處理的集合,不過要注
          意順序。

相關文章