天天看点

Linux pinctrl之驱动使用实例

既然是使用实例,就只关心API的使用,API里面的具体实现就不多赘述了。

举例:在dts文件里配置GPIO5作为复位管脚,在驱动里面会调用这个复位管脚,现从dts文件到驱动文件分开描述。

一、dts文件

/ {
	model = "CPU";
	compatible = "Vendor,CPU";
	interrupt-parent = <&gic>;
	#address-cells = <2>;
	#size-cells = <2>;
	chosen {
		bootargs = "console=tty0 console=ttyMT0,921600n1 root=/dev/ram initrd=0x84000000,0x400000 loglevel=8";
	};
	/*cpu{};pmu{};等加在这里*/
	bus {
		compatible = "simple-bus";
		#address-cells = <1>;
		#size-cells = <1>;
		ranges = <0 0 0 0xffffffff>;
		/*i2c、spi等总线相关的信息可加在这里*/
		pio: [email protected] {
			compatible = "mediatek,mt6580-pinctrl";
			reg = <0x10005000 0x1000>;
			mediatek,pctl-regmap = <&syscfg_pctl_a>;
			pins-are-numbered;
			gpio-controller;
			#gpio-cells = <2>;
		};
	};
	gpio_rst: gpio_rst {
		compatible = "mediatek,gpio_rst";/*也可以放在外面的&gpio_rst节点下,一样的效果*/
	};
};
&pio {
	gpio_rst_enable: [email protected] {
		pins_cmd_dat {
			pins = <PINMUX_GPIO5__FUNC_GPIO5>;
			slew-rate = <1>; /*输出方向 0:in, 1:out*/
			output-high; /*仅作输出时有效,输出为高电平*/
		};
	};
	gpio_rst_disable: [email protected] {
	    pins_cmd_dat {
			pins = <PINMUX_GPIO5__FUNC_GPIO5>;
			slew-rate = <1>;
			output-low;
		};
	};
};
&gpio_rst {
		pinctrl-names = "gpio_rst_on", "gpio_rst_off";
		pinctrl-1 = <&gpio_rst_enable>;
		pinctrl-2 = <&gpio_rst_disable>;
}
           

二、驱动文件

/*
struct pinctrl_state { 
    struct list_head node;//挂入链表头的节点
    const char *name;//该state的名字
    struct list_head settings;//属于该状态的所有的settings
};*/
static int xxx_probe(struct platform_device *dev)
{
	/*先申请内存、注册创建相关节点*/
	/*下面直接进入gpio ctrl部分*/
	struct pinctrl_state *xxx_pin_ctrl,*xxx_rst_on,*xxx_rst_off;
	
	xxx_pin_ctrl = devm_pinctrl_get(&pdev->dev); /*Resource managed pinctrl_get()*/
	if (IS_ERR(xxx_pin_ctrl)) {
		printk("failed\n");
		ret = PTR_ERR(xxx_pin_ctrl);
		return ret;
	}
	
	xxx_rst_on = pinctrl_lookup_state(xxx_pin_ctrl, "gpio_rst_on");
	if (IS_ERR(xxx_rst_on)) {
		printk("failed\n");
		ret = PTR_ERR(xxx_rst_on);
		return ret;
	}
	
	xxx_rst_off = pinctrl_lookup_state(xxx_pin_ctrl, "gpio_rst_off");
	if (IS_ERR(xxx_rst_off)) {
		printk("failed\n");
		ret = PTR_ERR(xxx_rst_off);
		return ret;
	}
	
	/*下面就是直接调用gpio5,可以单独封装为一个函数*/
	pinctrl_select_state(xxx_pin_ctrl, xxx_rst_on);/*gpio5输出高电平*/
	delay(20);
	pinctrl_select_state(xxx_pin_ctrl, xxx_rst_off);/*gpio5输出低电平*/
	delay(20);
}
static int xxx_remove(struct platform_device *dev){
	/*************/
}
#ifdef CONFIG_OF
static const struct of_device_id xxx_gpio_of_id[] = {
	{.compatible = "mediatek,gpio_rst",},
	{}
};
#endif
static struct platform_driver caotuo_platform_driver = {
	.probe = xxx_probe,
	.remove = xxx_remove,
	.driver = {
		   .name = my_name,
		   .owner = THIS_MODULE,
	#ifdef CONFIG_OF/*增加宏判断,低版本内核不带dts*/
		   .of_match_table = xxx_gpio_of_id, 	  
	#endif
	},
};
static int __init caotuo_init(void)
{
	int ret=0;
	ret = platform_driver_register(&caotuo_platform_driver);
	if (ret) {
		printk("failed\n");
		return ret;
	}
	return ret;
}
static void __exit caotuo_exit(void)
{
	platform_driver_unregister(&caotuo_platform_driver);
}
module_init(caotuo_init);
module_exit(caotuo_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("xxxx");
MODULE_DESCRIPTION("xxxx");
           

三、总结

驱动里面主要是要掌握三个API,按顺序调用,即:

devm_pinctrl_get(); //在定义时会调用devres_alloc()动态申请内存空间

pinctrl_lookup_state();

pinctrl_select_state();

转载请注明出处!