天天看點

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();

轉載請注明出處!