GPIO配置使用

GPIO配置使用

Posted by Joey on August 20, 2020

概述

本文主要描述Linux内核关于GPIO的DTS配置以及gpiolib,pinctrl驱动框架和接口的介绍使用。

GPIO

gpio配置流程

st=>start: DTS配置解析
op=>operation: 其它模块驱动
con=>condition: pinctrl or gpiolib?
op_pinctrl=>operation: Linux pinctrl
op_gpiolib=>operation: Linux gpiolib
op_platform=>operation: platform pinctrl or gpiolib
op_reg=>operation: 读写平台GPIO寄存器
e=>end: end

st->op->con
con(yes)->op_pinctrl->op_platform->op_reg
con(no)->op_gpiolib->op_platform->op_reg

GPIO配置

devicetree->其它驱动模块:
其它驱动模块->Linux pinctrl: pinctrl
其它驱动模块->Linux gpiolib: gpiolib
Linux pinctrl->平台pinctrl:平台pinctrl
Linux gpiolib->平台gpiolib:平台gpiolib
平台pinctrl->平台GPIO寄存器:
平台gpiolib->平台GPIO寄存器:

pinctrl接口

/* 获取pinctrl结构
 *
 */
struct pinctrl * devm_pinctrl_get(struct device *dev);

/*
 *
 */
struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p, const char *name);

/*
 *
 */
int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state);

gpiolib接口

/*
 *
 */
int gpio_request(unsigned gpio, const char *label);

/*
 *
 */
void gpio_free(unsigned gpio);

/*
 *
 */
int gpio_direction_input(unsigned gpio);

/*
 *
 */
int gpio_direction_output(unsigned gpio);

/*
 *
 */
void gpio_set_value(unsigned int gpio, int value);

/*
 *
 */
int gpio_get_value(unsigned int gpio);

/*
 *
 */
int of_get_named_gpio(struct device_node *np, const char *propname, int index);

pinctrl devicetree配置

pinctrl用于控制GPIO,但是无法获取GPIO输入值。 关于pinctrl在devicetree中的配置有三个部分:pin controller node(GPIO控制器节点),pinctrl node(pinctrl节点) and device node(设备节点)。

  • pin controller node: 主要描述的是芯片GPIO控制器。
      pio:pinctrl@10005000 {
          compatible="pinctrl-test";
          reg=<0 0x10005000 0 0x1000>;
          gpio-controller;
          #gpio-cells=<2>;
      };
    
  • pinctrl node: 描述需要配置的GPIO信息,属于pin controller子节点。
      &pio{
          test_cfg:alspspincfg {
              pins_cmd_dat {
                  pins = <gpio6>;
                  bias-pull-up=<00>;
              };
          };
          test_default:alspsdefaultcgf{
    		
          };
      };
    
  • device node: 描述设备信息控制GPIO, pinctrl-names配置pinctrl state name,用于匹配pinctrl节点的设置。pinctr-0…匹配pinctrl node label
      &als {
          pinctrl-names="pin_default", "pin_cfg";
          pinctrl-0=<&test_default>;
          pinctrl-1=<&test_cfg>;
      };
    

pinctrl 驱动代码示例

  1. 通过驱动设备节点获取pinctrl devm_pinctrl_get()
  2. 通过获取的pinctrl查找pinctrl state pinctrl_lookup_state()
  3. 选择要设置的pinctrl state pinctrl_select_state()
    int gpio_setting(struct device *dev)
    {
     int ret = 0;
     struct pinctrl *pinctrl;
     struct pinctrl_state *pins_default;
     struct pinctrl_cfg *pins_cfg;
    
     pinctrl = devm_pinctrl_get(dev);
     if(IS_ERR(pinctrl))
         return ERROR;
    
     //"pin_default"对应devicetree中pinctrl-names 中 state
     pins_default = pinctrl_lookup_state(pinctrl, "pin_default");
     if (IS_ERR(pins_default))
         return ERROR;
    
     pins_cfg = pinctrl_lookup_state(pinctrl, "pin_cfg");
     if (IS_ERR(pins_cfg))
         return ERROR;
    
     pinctrl_select_state(pinctrl, pins_cfg);
    }
    

gpiolib devicetree配置

	gpiolibtest:gpio_test {
		compatible="gpiolib_test";
		gpio_num=<&pio 10 0>;
		state="okay";
	};

gpiolib驱动代码示例

  • get gpio number
  • request gpio
  • control gpio
  • free gpio
int gpio_op_test(void)
{
	struct device_node *np = NULL;
	int gpio = 0;
	int ret = 0;
	int value = 0;

	np = of_find_compatible_node(NULL, NULL, "gpiolib_test");
	if (np == NULL)
		return ERROR;

	//gpio_num对应devicetree中配置
	gpio = of_get_named_gpio(np, "gpio_num", 0);

	ret = gpio_request(gpio, "gpiolib_test");

	gpio_direction_output(gpio, 0);
	gpio_set_value(gpio, 1);
	gpio_direction_input(gpio);
	value = gpio_get_value(gpio);

	gpio_free(gpio);

	return ret;
}