itop4412 驱动 利用pinctrl和新的gpio函数 点灯
配置设备树
- 在arch/arm/boot/dts/exynos4412-pinctrl.dtsi这个文件下添加
// 添加到 pinctrl_1节点下 第437行
// 这个我添加了在 619 行
led_text: led_text {
samsung,pins = "gpl2-0";
samsung,pin-function = < EXYNOS_PIN_FUNC_OUTPUT>;
samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
samsung,pin-val = <0>;
};
- 在arch/arm/boot/dts/exynos4412-itop-elite.dts这个文件下添加
// 这个可以随便放置,首先要查看有没有引用gpl2 0 这个引脚,如果引用应当注释
haha_led {
compatible = "leds_test";
pinctrl-names = "default";
pinctrl-0 = <&led_text>;
gpios = <&gpl2 0 GPIO_ACTIVE_HIGH>;
status = "okay";
};
- 编译设备树
原理分析
-
在上面我们已经配置完设备树,这里需要有设备树的基础和pinctrl子系统的概念,引入设备树和pinctrl大大降低了代码的编写,我们只需要配置完设备树,就可以在platform里面生成相对应的设备,在这个地方要注意,pinctrl-0 的属性要和 pinctrl_1里面的相对应。
-
使用到的主要的API函数
// 这个函数主要利用pinctrl 子系统配置led灯的相关引脚的电气属性 #include <linux/pinctrl/consumer.h> // 头文件 devm_pinctrl_get_select_default( struct device *dev) /* 这个函数主要获取gpio的句柄 * 第二个参数con_id,这个参数就有点意思了,在上区域代码我们可以看到 * gpios = <&gpl2 0 GPIO_ACTIVE_HIGH>; * 这个gpios前面没有多余的字符,如果没有这个字符,应该传入 NULL * 如果改成 led-gpios = <***> ,应该传入 led, 那个'-'是必须要添加的 * 我在这个地方没有添加前缀,所以我传入的参数为NULL */ #include <linux/gpio/consumer.h> // 头文件 devm_gpiod_get(struct device *dev, const char *con_id, enum gpiod_flags flags) // 这个函数设置gpio的属性值 gpiod_set_value(struct gpio_desc *desc, int value) // 这个函数就是释放gpio devm_gpiod_put(struct device *dev, struct gpio_desc *desc) // 释放pinctrl 子系统 devm_pinctrl_put(struct pinctrl *p); /* 看到devm_开头的函数,是Linux内核提供的,自动申请内存的函数 * 我们应该尽量使用这类函数 */
代码编写
-
我这里只贴出部分代码,就是注册平台设备后,进入probe函数之后执行的代码,还有释放的代码
// probe函数 static int ledpinctrl_probe(struct platform_device *pdev) { printk("enter ledpinctrl_probe function\n"); // 利用pinctrl 来配置Led 引脚的电气属性 leds_pin_ctrl = devm_pinctrl_get_select_default(&pdev->dev); // 这个地方传入NULL,代表是默认的名字 gpios gpio = devm_gpiod_get(&pdev->dev, NULL, 0); if(IS_ERR(gpio)){ printk("获取gpio节点属性失败\n"); return PTR_ERR(gpio); }else{ printk("获取gpio节点属性成功\n"); } /* 这个地方 可以不用配置为输出模式, * 因为在pinctrl 里面已经配置过为输出模式 */ // gpiod_direction_output(gpio, 0); printk("init ok\n"); return 0; }
// remove函数 static int ledpinctrl_remove(struct platform_device *pdev) { devm_gpiod_put(&pdev->dev,gpio); devm_pinctrl_put(leds_pin_ctrl); printk("enter ledpinctrl_remove function\n"); return 0; }
-
剩下的代码,就是字符设备操作的那种套路,调用gpiod_set_value(),设置gpio的数值