LINUX MDIO模塊分析 (四)mdio總線及phy驅動模型及其開發流程

前三篇文章完成了mdio子系統概述、mdio子系統驅動模型概述、mii_bus子模塊方法及驅動實現分析,本篇文章我們主要進行mdio總線驅動實現分析、phy驅動實現分析等部分,涉及的內容如下:

一、mdio總線實現及相應方法分析


二、phy驅動實現相應方法的分析


三、phy驅動開發步驟說明


一、mdio總線實現及相應方法分析


既然mdio子模塊屬於總線型驅動,因此mdio子模塊也是繼承於linux設備-總線-驅動模型,從而實現自己的驅動模型,這在第二篇文章中也已經進行了說明,但第二篇文章主要介紹數據結構間的關聯,本篇我們將介紹實現mdio總線、phy驅動等數據結構間關聯的方法。下面我們看下mdio總線的定義及相應驅動接口的定義說明。


mdio_bus_type定義及說明

如下為mdio_bus_type的定義,mdio總線的實現相對也比較簡單,連probe、remove接口都沒有實現,而直接由phy_driver->probe/remove接口進行實現,mdio_bus_type主要實現如下兩個功能:

  1. 定義dev_atrrs變量,針對所有註冊在mdio_bus_type上的phy_device,均會創建該dev_attrs上定義的屬性文件,該屬性文件的名稱為phy_id,該屬性文件為只讀屬性文件,可獲取該phy_device的phy id;
  2. 定義了match方法,用於進行phy_device、phy_driver的匹配檢測操作。


LINUX MDIO模塊分析 (四)mdio總線及phy驅動模型及其開發流程

mdio總線的device、driver註冊與註銷相關方法的實現流程說明

由於mdio_bus_type沒有提供probe、remove方法,因此針對mdio_bus_type而言,其device、driver的註冊與註銷方法的處理流程有些許的不同。針對linux設備-總線-驅動模型而言,其提供了device_register/driver_register、device_unregister/driver_unregister方法,用於進行設備與驅動綁定與解綁操作,從而實現設備的探測與移除操作。

如下圖為mdio總線實現中device_register/driver_register、device_unregister/driver_unregister接口的處

理流程如下圖所示。

  1. 針對device_register/driver_register而言,主要涉及將device、driver添加至mdio_bus_type,並進行device與driver的匹配檢測,待匹配成功後,則通過driver->probe接口最終調用phy_driver->probe接口(這一點可以理解為面向對象中的多態,而phy_driver為device_driver的子類,即通過父類device_driver->probe方法調用至子類phy_driver->probe方法)。
  2. 針對device_unregister/driver_unregister而言,主要用於將device或driver從mdio_bus_type上移除,並調用driver->remove接口實現移除工作(而driver->remove接口最終調用phy_driver->remove接口(這一點可以理解為面向對象中的多態,而phy_driver為device_driver的子類,即通過父類device_driver->remove方法調用至子類phy_driver->remove方法)


LINUX MDIO模塊分析 (四)mdio總線及phy驅動模型及其開發流程

phy_device_register/phy_driver_register


LINUX MDIO模塊分析 (四)mdio總線及phy驅動模型及其開發流程

phy_driver_unregister/device_unregister

mdio總線的match方法說明

mdio總線的match方法為mdio_bus_match,mdio_bus_match的實現流程如下圖所示,其主要實現如下三方面的匹配檢測功能:

  1. 先進行設備樹驅動模型的支持(若系統支持設備樹,則先調用該接口進行匹配檢測,主要是將phy_driver與phy_device設備樹節點的compatible變量進行匹配檢測),若匹配則返回匹配成功;
  2. 若a沒有匹配成功,則確認phy_driver是否提供了匹配檢測方法,若提供匹配檢測方法,則再次進行匹配檢測,若匹配成功,則返回成功;
  3. 若以上均沒有匹配成功,則判斷phy_device的phyid與phy_driver支持的phyid進行匹配檢測,若匹配成功則返回成功。


LINUX MDIO模塊分析 (四)mdio總線及phy驅動模型及其開發流程

mdio_bus_match

phy驅動實現相應方法的分析

在前面我們也說了,可以將phy_driver理解為device_driver的子類,並實現了probe、remove接口,用以實現上一章節所說的多態。若下圖所示,即為phy_driver與device_driver關聯,針對phy_device與phy_driver而言,也提供了phy_device與phy_driver的註銷方法,分別為phy_device_register、phy_drivers_register、phy_driver_unregister(因phy_device的註冊是由mii_bus註冊時通過調用mdiobus_register時完成phy_device的註冊的,因此phy_device的註銷也是在mdiobus_unregister中完成了,因此mdio子系統沒有額外定義phy_device的註銷接口)。


LINUX MDIO模塊分析 (四)mdio總線及phy驅動模型及其開發流程

phy_device_register、phy_drivers_register接口分析


下圖是這兩個接口的處理流程圖,下面進行詳細說明:

針對phy_driver_register,主要完成如下工作:

  1. 設置phy_driver->driver的probe為phy_probe、remove為phy_remove,所依附的總線為mdio_bus_type,從而可將該phy_driver註冊至mdio總線上;
  2. 調用driver_register接口,將該phy_driver->driver註冊至mdio總線上,而關於driver_register的調用流程已經在上述mdio總線的device、driver註冊與註銷方法中說明。

針對phy_device_register而言,主要完成工作如下:

  1. 若phy_device已經與mii_bus完成綁定,則返回失敗;
  2. 若該phy_device需要進行fixup,則調用phy_scan_fixups進行修正,一般在phy 芯片存在errata時,才進行修正;
  3. 調用device_add將該phy_device->dev註冊至mdio總線(在調用phy_device_create創建一個phy_device時,已經設置phy_device->dev.bus為mdio_bus_type,因此在phy_device_register中無需再設置phy_device->dev.bus)


LINUX MDIO模塊分析 (四)mdio總線及phy驅動模型及其開發流程

針對phy_device_register、phy_driver_register接口而言,也就是對device_register、driver_register的封

裝,以便作為mdio子模塊的phy_device、phy_driver的註冊接口


phy_driver_unregister接口分析

該接口就是對driver_unregister的封裝,此處不再贅述。


三、phy驅動開發步驟說明


針對phy 驅動而言,主要實現兩部分的內容:

  1. 實現probe、remove、suspend、resume接口,用於完成phy_driver的註冊與註銷,以及針對linux設備-總線-驅動模型的基礎;
  2. 實現phy device處理相關的接口

config_init、config_aneg、read_status、ack_interrupt、config_intr、did_interrupt、match_phy_device、ts_info、hwtstamp、rxtstamp、txtstamp、set_wol、get_wol。

  1. 其中config_init主要是對phy device進行一些初始化配置;
  2. 而config_aneg、read_status主要用於設置phy device的自適應機制已經獲取phy的狀態(主要用於獲取適配速率、雙工模式等),一般這兩個接口直接使用genphy_config_aneg、genphy_read_status即可,觸發該phy device有特殊的定義;
  3. 而ack_interrupt、config_intr、did_interrupt主要用於phy device的link up/down相關的中斷處理,這個與具體的phy device有關,查看相應的芯片手冊說明即可;
  4. 而針對ts_info、hwtstamp、rxtstamp、txtstamp、set_wol、get_wol主要是時間戳相關的處理,大多數phy device均不需實現這幾個接口。
  5. match_phy_device主要用於實現phy_device與phy_driver的匹配檢測,若一個phy_driver支持多個類型的phy_device,則最好實現該接口,若該phy_driver只適配某一個型號的phy_device,則不需要實現該接口,只需要設置支持的phy_id與phy_mask即可。


以上即是實現phy driver的大體步驟,一般情況下若phy device不是很特殊,完全可以不實現phy driver,而在mdiobus_register時針對沒有匹配phy_driver的設備,會將其與genphy_driver進行綁定,而genphy_driver基本上對大多數phy device而言,均可以正常驅動。但若我們僅需要在phy driver的probe接口中進行一些配置(如設置phy device的led mode 等),則完全可以將config_ange、read_status等接口使用genphy_driver中的接口,僅實現probe接口即可。


以上便是本篇文章的主要內容,主要介紹mdio_bus_type的定義;phy_device與phy_driver的註冊與註銷流程以及phy_driver編寫需實現的接口等內容,下一篇文章主要介紹mdio模型實現的phy 狀態機,以及phy_device與net_device的綁定與解綁相關的內容。


分享到:


相關文章: