加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

Linux BSP實(shí)戰(zhàn)課(pin 驅(qū)動(dòng)篇):pinctrl 驅(qū)動(dòng)和client device使用過(guò)程

2023/12/25
4427
閱讀需 22 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

通過(guò)前面硬件原理的介紹,我們知道配置一個(gè)pin需要經(jīng)過(guò)mux控制寄存器和pad控制寄存器,對(duì)于輸入引腳的配置,還需要另外配置輸入選擇寄存器。那么把這些概念用軟件來(lái)實(shí)現(xiàn)就是 pin 驅(qū)動(dòng)控制器的本質(zhì)。在了解驅(qū)動(dòng)前我們先來(lái)看幾個(gè)關(guān)鍵結(jié)構(gòu)體。

pinctrl_desc 結(jié)構(gòu)體

使用 struct pinctrl_desc 抽象一個(gè) pin controller,包含控制器的名字、pin腳的數(shù)量、pinmux功能、pinconf功能和pinctl功能。其中結(jié)構(gòu)體 pinmux_opspinconf_ops 分別用于配置mux模式和pad電氣屬性,而 pinctrl_ops 則是控制一組pin,如uart、i2c、spi等外設(shè)的pin組。該結(jié)構(gòu)的定義如下:

struct?pinctrl_desc?{
?const?char?*name;//pin控制器名字
?const?struct?pinctrl_pin_desc?*pins;//描述芯片的物理引腳pad資源
?unsigned?int?npins;
?const?struct?pinctrl_ops?*pctlops;//全局pin配置
?const?struct?pinmux_ops?*pmxops;?//mux配置
?const?struct?pinconf_ops?*confops;//電氣屬性配置
?struct?module?*owner;
?bool?link_consumers;
};

其中:

    pins

變量 pins 和 npins 把系統(tǒng)中所有的 pin 描述出來(lái),并建立索引。驅(qū)動(dòng)為了和具體的 pin 對(duì)應(yīng)上,再將這些描述的這些 pin 組織成一個(gè) struct pinctrl_pin_desc 類型的數(shù)組,該類型的定義為:

struct?pinctrl_pin_desc?{
?unsigned?number;
?const?char?*name;
?void?*drv_data;
};

SoC中,有時(shí)需要將很多 pin 組合在一起,以實(shí)現(xiàn)特定的功能,例如 eqos 接口、i2c 接口等。因此 pin controller 需要以 group 為單位,訪問(wèn)、控制多個(gè) pin,這就是 pin groups。

struct?group_desc?{
?const?char?*name;
?int?*pins;
?int?num_pins;
?void?*data;
};

在設(shè)備樹(shù)里表示就是:

pinctrl_eqos:?eqosgrp?{
?fsl,pins?=?<
??MX93_PAD_ENET1_MDC__ENET_QOS_MDC???0x57e
??MX93_PAD_ENET1_MDIO__ENET_QOS_MDIO???0x57e
??MX93_PAD_ENET1_RD0__ENET_QOS_RGMII_RD0???0x57e
??MX93_PAD_ENET1_RD1__ENET_QOS_RGMII_RD1???0x57e
??MX93_PAD_ENET1_RD2__ENET_QOS_RGMII_RD2???0x57e
??MX93_PAD_ENET1_RD3__ENET_QOS_RGMII_RD3???0x57e
??MX93_PAD_ENET1_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK?0x5fe
??MX93_PAD_ENET1_RX_CTL__ENET_QOS_RGMII_RX_CTL??0x57e
??MX93_PAD_ENET1_TD0__ENET_QOS_RGMII_TD0???0x57e
??MX93_PAD_ENET1_TD1__ENET_QOS_RGMII_TD1???0x57e
??MX93_PAD_ENET1_TD2__ENET_QOS_RGMII_TD2???0x57e
??MX93_PAD_ENET1_TD3__ENET_QOS_RGMII_TD3???0x57e
??MX93_PAD_ENET1_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK?0x5fe
??MX93_PAD_ENET1_TX_CTL__ENET_QOS_RGMII_TX_CTL??0x57e
?>;
};

pinctrl core 會(huì)在 struct pinctrl_ops 中抽象出三個(gè)回調(diào)函數(shù),用來(lái)獲取 pin groups 相關(guān)信息,如下:

pinctrl_ops

struct?pinctrl_ops?{
??//獲取系統(tǒng)中pin?groups的個(gè)數(shù),后續(xù)的操作,將以相應(yīng)的索引為單位(類似數(shù)組的下標(biāo),個(gè)數(shù)為數(shù)組的大?。?
?int?(*get_groups_count)?(struct?pinctrl_dev?*pctldev);
??//獲取指定group(由索引selector指定)的名稱
?const?char?*(*get_group_name)?(struct?pinctrl_dev?*pctldev,?unsigned?selector);
??//獲取指定group的所有pins(由索引selector指定),結(jié)果保存在pins(指針數(shù)組)和num_pins(指針)中
?int?(*get_group_pins)?(struct?pinctrl_dev?*pctldev,?unsigned?selector,?const?unsigned?**pins,?unsigned?*num_pins);
?void?(*pin_dbg_show)?(struct?pinctrl_dev?*pctldev,?struct?seq_file?*s,?unsigned?offset);
??//用于將device?tree中的pin?state信息轉(zhuǎn)換為pin?map
?int?(*dt_node_to_map)?(struct?pinctrl_dev?*pctldev,?struct?device_node?*np_config,?struct?pinctrl_map?**map,?unsigned?*num_maps);
?void?(*dt_free_map)?(struct?pinctrl_dev?*pctldev,?struct?pinctrl_map?*map,?unsigned?num_maps);
};

pinmux_ops

為了兼容不同的應(yīng)用場(chǎng)景,有很多管腳可以配置為不同的功能,例如A和B兩個(gè)管腳,既可以當(dāng)作普通的GPIO使用,又可以配置為I2C的的SCL和SDA,也可以配置為UART的TX和RX,這稱作管腳的復(fù)用(簡(jiǎn)稱 pin mux)。使用 struct pinmux_ops 來(lái)抽象 pin mux 有關(guān)的操作,如下:

struct?pinmux_ops?{
??//檢查某個(gè)pin是否已作它用,用于管腳復(fù)用時(shí)的互斥
?int?(*request)?(struct?pinctrl_dev?*pctldev,?unsigned?offset);
??//request的反操作
?int?(*free)?(struct?pinctrl_dev?*pctldev,?unsigned?offset);
??//獲取系統(tǒng)中function的個(gè)數(shù)
?int?(*get_functions_count)?(struct?pinctrl_dev?*pctldev);
??//獲取指定function的名稱
?const?char?*(*get_function_name)?(struct?pinctrl_dev?*pctldev,?unsigned?selector);
??//獲取指定function所占用的pin?group
?int?(*get_function_groups)?(struct?pinctrl_dev?*pctldev,?unsigned?selector,?const?char?*?const?**groups,?unsigned?*num_groups);
??//將指定的pin?group(group_selector)設(shè)置為指定的function(func_selector)
?int?(*set_mux)?(struct?pinctrl_dev?*pctldev,?unsigned?func_selector,?unsigned?group_selector);
??//以下是gpio相關(guān)的操作
?int?(*gpio_request_enable)?(struct?pinctrl_dev?*pctldev,?struct?pinctrl_gpio_range?*range,?unsigned?offset);
?void?(*gpio_disable_free)?(struct?pinctrl_dev?*pctldev,?struct?pinctrl_gpio_range?*range,?unsigned?offset);
?int?(*gpio_set_direction)?(struct?pinctrl_dev?*pctldev,?struct?pinctrl_gpio_range?*range,?unsigned?offset,?bool?input);
??//為true時(shí),說(shuō)明該pin?controller不允許某個(gè)pin作為gpio和其它功能同時(shí)使用
?bool?strict;
};

pinconf_ops

除了上面的 pin 和 pin group,有些管腳可以配置,比如上拉,下拉,高阻等。具體體現(xiàn)在 struct pinconf_ops 數(shù)據(jù)結(jié)構(gòu)中,如下:

struct?pinconf_ops?{
#ifdef?CONFIG_GENERIC_PINCONF
?bool?is_generic;
#endif
??//獲取指定?pin?的當(dāng)前配置,保存在?config?指針中
?int?(*pin_config_get)?(struct?pinctrl_dev?*pctldev,?unsigned?pin,?unsigned?long?*config);
??//設(shè)置指定pin的配置
?int?(*pin_config_set)?(struct?pinctrl_dev?*pctldev,?unsigned?pin,?unsigned?long?*configs,?unsigned?num_configs);
??//獲取指定pin?group的配置項(xiàng)
?int?(*pin_config_group_get)?(struct?pinctrl_dev?*pctldev,?unsigned?selector,?unsigned?long?*config);
??//設(shè)置指定pin?group的配置項(xiàng)
?int?(*pin_config_group_set)?(struct?pinctrl_dev?*pctldev,?unsigned?selector,?unsigned?long?*configs,?unsigned?num_configs);
??......
    pin state

根據(jù)前面的描述,pinctrl driver 抽象出來(lái)了一些離散的對(duì)象,并實(shí)現(xiàn)了這些對(duì)象的控制和配置方式。然后我們回到某一個(gè)具體的 device 上(如 lpuart,usdhc)。一個(gè)設(shè)備在某一狀態(tài)下(如工作狀態(tài)、休眠狀態(tài)、等等),所使用的pin(pin group)、pin(pin group)的 function 和 configuration,是唯一確定的。所以固定的組合可以確定固定的狀態(tài),在設(shè)備樹(shù)里用 pinctrl-names 指明狀態(tài)名字,pinctrl-x 指明狀態(tài)引腳。

    pin map

pin state 有關(guān)的信息是通過(guò) pin map 收集,相關(guān)的數(shù)據(jù)結(jié)構(gòu)如下:

struct?pinctrl_map?{
??//device的名稱
?const?char?*dev_name;
??//pin?state的名稱
?const?char?*name;
??//該map的類型
?enum?pinctrl_map_type?type;
??//pin?controller?device的名字
?const?char?*ctrl_dev_name;
?union?{
??struct?pinctrl_map_mux?mux;
??struct?pinctrl_map_configs?configs;
?}?data;
};

enum?pinctrl_map_type?{
?PIN_MAP_TYPE_INVALID,
?//不需要任何配置,僅僅為了表示state的存在
?PIN_MAP_TYPE_DUMMY_STATE,
?//配置管腳復(fù)用
?PIN_MAP_TYPE_MUX_GROUP,
?//配置pin
?PIN_MAP_TYPE_CONFIGS_PIN,
?//配置pin?group
?PIN_MAP_TYPE_CONFIGS_GROUP,
};

struct?pinctrl_map_mux?{
?//group的名字
?const?char?*group;
?//function的名字
?const?char?*function;
};

struct?pinctrl_map_configs?{
?//該pin或者pin?group的名字
?const?char?*group_or_pin;
?//configuration數(shù)組
?unsigned?long?*configs;
?//配置項(xiàng)的個(gè)數(shù)
?unsigned?num_configs;
};

pinctrl driver 確定了 pin map 各個(gè)字段的格式之后,就可以在 dts 文件中維護(hù) pin state 以及相應(yīng)的 mapping table。pinctrl core 在初始化的時(shí)候,會(huì)讀取并解析 dts,并生成 pin map。

而各個(gè) client device 可以在自己的 dts node 中,直接引用 pinctrl driver 定義的 pin state,并在設(shè)備驅(qū)動(dòng)的相應(yīng)的位置,調(diào)用 pinctrl subsystem 提供的 API(pinctrl_lookup_state,pinctrl_select_state),active 或者 deactive 這些 state。

pin controller 驅(qū)動(dòng)初始化

pin controller 的設(shè)備樹(shù)如下所示:

iomuxc:?pinctrl@443c0000?{
?compatible?=?"fsl,imx93-iomuxc";
?reg?=?<0x443c0000?0x10000>;
?status?=?"okay";
};

&iomuxc?{
?pinctrl_eqos:?eqosgrp?{
??fsl,pins?=?<
???......
??>;
?};

?pinctrl_eqos_sleep:?eqosgrpsleep?{
??fsl,pins?=?<
???......
??>;
?};

?pinctrl_fec:?fecgrp?{
??fsl,pins?=?<
???......
??>;
?};

?pinctrl_fec_sleep:?fecsleepgrp?{
??fsl,pins?=?<
???......
??>;
?};
?......
?pinctrl_sai1:?sai1grp?{
??fsl,pins?=?<
???......
??>;
?};

?pinctrl_sai1_sleep:?sai1grpsleep?{
??fsl,pins?=?<
???......
??>;
?};
?......
};

pin controller驅(qū)動(dòng)的初始化大致如下:

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊(cè) ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
FOD420SV 1 Fairchild Semiconductor Corporation Triac Output Optocoupler, 1-Element, 5000V Isolation, LEAD FREE, SURFACE MOUNT PACKAGE-6
$2.89 查看
SIT9001AI-83-XXXX-000.FP000X 1 SiTime Corporation LVCMOS Output Clock Oscillator,
暫無(wú)數(shù)據(jù) 查看
TLP291(GB,SE 1 Toshiba America Electronic Components 1 CHANNEL TRANSISTOR OUTPUT OPTOCOUPLER

ECAD模型

下載ECAD模型
$0.34 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

針對(duì)嵌入式人工智能,物聯(lián)網(wǎng)等專業(yè)技術(shù)分享和交流平臺(tái),內(nèi)容涉及arm,linux,android等各方面。

Arm64 ?;厮?>
				</a>
							</li>
						<li id= 查看更多