高通msm8909对gpio的使用@TOC
- msm8909-pinctrl.dtsi文件中定义了诸多节点,用于设置pin组合的功能,例如:
pmx_i2c_5 { //该名称可以随便起,无实际作用 i2c_5_active: i2c_5_active { //i2c_5_active是该子节点的别名,被别处引用是会用到 mux { pins = "gpio19", "gpio18"; function = "blsp_i2c5"; //定义上面两个引脚的复用功能 }; config { //对pin脚的基本特性设置,如:输出电流,上拉/下拉/无上下拉 pins = "gpio19", "gpio18"; drive-strength = <2>; /* 2 MA */ bias-disable; /* No PULL */ }; }; i2c_5_sleep: i2c_5_sleep { mux { pins = "gpio19", "gpio18"; function = "blsp_i2c5"; }; config { pins = "gpio19", "gpio18"; drive-strength = <2>; /* 2 MA */ bias-disable; /* No PULL */ }; }; };
- 假如我们要把gpio20,gpio21,gpio22作为通用gpio输出使用。
2.1 首先,我们需要在我们的工程dtsi(msm8909-pinctrl.dtsi作为公共文件,尽量不要对其修改)中设置其复用功能,如在msm8909-mtp.dtsi中做如下定义:
msm8909-pinctrl.dtsi的节点框架:
&soc { **msm_gpio**: pinctrl@1000000 { compatible = "qcom,msm8909-pinctrl"; reg = <0x1000000 0x300000>; interrupts = <0 208 0>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; ........ tlmm_gpio_key { gpio_key_active: gpio_key_active { mux { pins = "gpio90", "gpio91", "gpio92", "gpio22"; function = "gpio"; }; config { pins = "gpio90", "gpio91", "gpio92", "gpio22"; drive-strength = <2>; bias-pull-up; }; }; }; ...... }; };
&**msm_gpio** { //这是对msm8909-pinctrl.dtsi节点的引用 cup_gpios { //加入自己要用的节点 cup_led_gpios: cup_led_gpios { //cup_led_gpios该别名会被其他节点引用到 mux { pins = "gpio20", "gpio21", "gpio22"; function = "gpio"; }; config { pins = "gpio20", "gpio21", "gpio22"; drive-strength = <2>; /* 2 MA */ bias-pull-down; /* PULL DOWN */ }; }; }; };
2.2 对2.1中自定义节点的引用
我们还是在msm8909-mtp.dtsi中定义要和platform_driver驱动匹配的节点,如下:
cup-leds { compatible = "cup-leds"; pinctrl-names = "jeejio_cup_led_gpios"; //该名称在驱动程序中pinctrl_lookup_state函数会使用 pinctrl-0 = <&cup_led_gpios>; //引用2.1中定义的节点,pinctrl-0对应上面的第一个pinctrl-names,pinctrl-names可以由多个字符串组成,用逗号分割开。 gpios = <&msm_gpio 22 0x1>, /* R */ //定义一个gpio序列 <&msm_gpio 21 0x1>, /* G */ <&msm_gpio 20 0x1>; /* B */ };
2.3 驱动程序中对gpio的使用
/* Get pinctrl if target uses pinctrl */ cup_pinctrl = devm_pinctrl_get(&pdev->dev); //获取pinctrl句柄 if (IS_ERR(cup_pinctrl)) { if (PTR_ERR(cup_pinctrl) == -EPROBE_DEFER) return -EPROBE_DEFER; pr_debug("Jeejio cup does not use pinctrl\n"); cup_pinctrl = NULL; } set_state = pinctrl_lookup_state(cup_pinctrl, "jeejio_cup_led_gpios"); //获得cup_led_gpios if (IS_ERR(set_state)) { pr_err( "cannot get jeejio cup pinctrl active state\n"); return PTR_ERR(set_state); } ret = pinctrl_select_state(cup_pinctrl, set_state); //对cup_led_gpios里的每个gpio进行设置 if (ret) { pr_err( "cannot set jeejio cup pinctrl active state\n"); return ret; } for(i = 0; i < GPIO_NUM; i++) { cup_gpio[i] = of_get_gpio(pdev->dev.of_node, i); //2.2中的gpio序列定义的3个gpio,其索引为:0,1,2 ret = gpio_request(cup_gpio[i], "rgb_gpio"); if(ret) { pr_err("request gpio err!\n"); } else { pr_err("request gpio success!\n"); } ret = gpio_direction_output(cup_gpio[i], 1); if(ret) { pr_err("set gpio direction err!\n"); } else { pr_err("set gpio direction success!\n"); } }
- 另一种gpio的使用方法:
pinctrl-names = "pmx_ts_active","pmx_ts_suspend","pmx_ts_release"; pinctrl-0 = <&ts_int_active &ts_reset_active>; pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; pinctrl-2 = <&ts_release>; atmel,reset-gpio = <&msm_gpio 12 0x00>; atmel,irq-gpio = <&msm_gpio 13 0x00>;
上面设备树中对gpio的使用,在驱动程序中的获取方法是:
/* reset, irq gpio info */ pdata->gpio_reset = of_get_named_gpio_flags(np, "atmel,reset-gpio", 0, &temp_val); pdata->gpio_irq = of_get_named_gpio_flags(np, "atmel,irq-gpio", 0, &temp_val);
文章来源: https://blog.csdn.net/tasawen/article/details/89791344