高通msm8909对gpio的使用(包括pinctrl的功能设置,gpio在节点中的引用,驱动程序获取gpio的方法)

匿名 (未验证) 提交于 2019-12-02 23:32:01

高通msm8909对gpio的使用@TOC

  1. 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 */ 				}; 			}; 		}; 
  1. 假如我们要把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"); 		} 	}   
  1. 另一种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
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!