復用¶
如何定義 gpio 有哪些功能可以復用,在執行時又如何切換功能呢?以 i2c4 為例作簡單的介紹。
查規格表可知,i2c4_sda 與 i2c4_scl 的功能定義如下:
pad# func0 func1
i2c4_sda/gpio1_b3 gpio1b3 i2c4_sda
i2c4_scl/gpio1_b4 gpio1b4 i2c4_scl
在 kernel/arch/arm64/boot/dts/rockchip/rk3399.dtsi 裡有:
i2c4: i2c@ff3d0000{
compatible = "rockchip,rk3399-i2c";
reg = <0x0 0xff3d0000 0x0 0x1000>;
clocks = , ;
clock-names = "i2c", "pclk";
interrupts = ;
pinctrl-names = "default", "gpio";
pinctrl-0 = ;
pinctrl-1 = ; //此處原始碼未新增
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
pinctrl-names 定義了狀態名稱列表: default (i2c 功能) 和 gpio 兩種狀態。
pinctrl-0 定義了狀態 0 (即 default)時需要設定的 pinctrl: &i2c4_xfer
pinctrl-1 定義了狀態 1 (即 gpio)時需要設定的 pinctrl: &i2c4_gpio
這些 pinctrl 在 kernel/arch/arm64/boot/dts/rockchip/rk3399.dtsi 中這樣定義:
pinctrl: pinctrl {
compatible = "rockchip,rk3399-pinctrl";
rockchip,grf = ;
rockchip,pmu = ;
#address-cells = <0x2>;
#size-cells = <0x2>;
ranges;
i2c4{
i2c4_xfer: i2c4-xfer{
rockchip,pins = <1 12 rk_func_1 &pcfg_pull_none>, <1 11 rk_func_1 &pcfg_pull_none>;
i2c4_gpio: i2c4-gpio {
rockchip,pins = <1 12 rk_func_gpio &pcfg_pull_none>, <1 11 rk_func_gpio &pcfg_pull_none>;
rk_func_1,rk_func_gpio 的定義在 kernel/include/dt-bindings/pinctrl/rk.h 中:
#define rk_func_gpio 0
#define rk_func_1 1
#define rk_func_2 2
#define rk_func_3 3
#define rk_func_4 4
#define rk_func_5 5
#define rk_func_6 6
#define rk_func_7 7
另外,像 「1 11」,」1 12」 這樣的值是有編碼規則的,編碼方式與上一小節 「輸入輸出」 描述的一樣,」1 11」 代表 gpio1_b3,」1 12」 代表 gpio1_b4。
在復用時,如果選擇了 default (即 i2c 功能),系統會應用 i2c4_xfer 這個 pinctrl,最終將 gpio1_b3 和 gpio1_b4 兩個針腳切換成對應的 i2c 功能;而如果選擇了 gpio ,系統會應用 i2c4_gpio 這個 pinctrl,將 gpio1_b3 和 gpio1_b4 兩個針腳還原為 gpio 功能。
我們看看 i2c 的驅動程式 kernel/drivers/i2c/busses/i2c-rockchip.c 是如何切換復用功能的:
static int rockchip_i2c_probe(struct platform_device *pdev)
struct rockchip_i2c *i2c = null; struct resource *res;
struct device_node *np = pdev->dev.of_node; int ret;//
i2c->sda_gpio = of_get_gpio(np, 0);
if (!gpio_is_valid(i2c->sda_gpio)) {
dev_err(&pdev->dev, "sda gpio is invalid\n");
return -einval;
ret = devm_gpio_request(&pdev->dev, i2c->sda_gpio, dev_name(&i2c->adap.dev));
if (ret) {
dev_err(&pdev->dev, "failed to request sda gpio\n");
return ret;
i2c->scl_gpio = of_get_gpio(np, 1);
if (!gpio_is_valid(i2c->scl_gpio)) {
dev_err(&pdev->dev, "scl gpio is invalid\n");
return -einval;
ret = devm_gpio_request(&pdev->dev, i2c->scl_gpio, dev_name(&i2c->adap.dev));
if (ret) {
dev_err(&pdev->dev, "failed to request scl gpio\n");
return ret;
i2c->gpio_state = pinctrl_lookup_state(i2c->dev->pins->p, "gpio");
if (is_err(i2c->gpio_state)) {
dev_err(&pdev->dev, "no gpio pinctrl state\n");
return ptr_err(i2c->gpio_state);
pinctrl_select_state(i2c->dev->pins->p, i2c->gpio_state);
gpio_direction_input(i2c->sda_gpio);
gpio_direction_input(i2c->scl_gpio);
pinctrl_select_state(i2c->dev->pins->p, i2c->dev->pins->default_state);
首先是呼叫 of_get_gpio 取出裝置樹中 i2c4 結點的 gpios 屬於所定義的兩個 gpio:
gpios = , ;
然後是呼叫 devm_gpio_request 來申請 gpio,接著是呼叫 pinctrl_lookup_state 來查詢 gpio 狀態,而預設狀態 default 已經由框架儲存到 i2c->dev-pins->default_state 中了。
最後呼叫 pinctrl_select_state 來選擇是 default 還是 gpio 功能。
下面是常用的復用 api 定義:
#include
struct device {
#ifdef config_pinctrl
struct dev_pin_info*pins;
#endif
struct dev_pin_info {
struct pinctrl *p;
struct pinctrl_state *default_state;
#ifdef config_pm
struct pinctrl_state *sleep_state;
struct pinctrl_state *idle_state;
#endif
struct pinctrl_state * pinctrl_lookup_state(struct pinctrl *p, const char *name);
int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *s);
RK3399RO 4G 乙太網 WIFI共存
rk3399ro 4g 乙太網 wifi共存 系統 android8.1 基於此文章的修改點,直接按此文件,sepolicy會報neverallow不相容問題。修改點 1.te檔案目錄修改到 device rockchip comm sepolicy 修改對應的file contexts 2.ro ...
RK3399核心板與人臉識別機櫃控制之間的「聯絡」
一 產品背景 i cabinetc是一款基於物聯網技術為完善物品溯源管理而生的智慧型儲存終端,旨在解決當前高值備品管理的弊端。配套的智慧型管理系統可實時記錄人員資訊,物品有效期,領還記錄等管理資訊,為精細化管理提供有力的基礎性保障。由電腦和微控制器組成的多功能備品管理控制系統終端裝置,是工具管理現代...
Oracle控制檔案 10g
作用 二進位制檔案 記錄了資料庫當前例項的結構和行為,資料檔案日誌檔案的資訊,維護資料庫一致性 引數檔案中定義了控制檔案的位置和大小 很小的二進位制檔案,一般不超過100m mount階段open以後,一直在用 一套控制檔案只能連線乙個database 分散放置,至少乙份,至多八份 相關檢視 v c...