03.pinctrl和gpio子系统
pinctrl子系统¶
pinctrl 子系统主要工作内容如下: 1、获取设备树中 pin 信息。 2、根据获取到的 pin 信息来设置 pin 的复用功能 3、根据获取到的 pin 信息来设置 pin 的电气特性,比如上/下拉、速度、驱动能力等。对于我们使用者来讲,只需要在设备树里面设置好某个 pin 的相关属性即可,其他的初始化工作均由 pinctrl 子系统来完成,pinctrl 子系统源码目录为 drivers/pinctrl。
主要配置的是&iomuxc中的参数
GPIO子系统¶
pinctrl 配置好以后就是设置 gpio 了
如在节点信息中,配置某个属性
检查 PIN 是否被其他外设使用,全局搜索GPIO1_IO03和&gpio1 3,注释相关信息
开发步骤¶
添加设备节点¶
在根节点“/”下创建 LED 灯节点,节点名为“mini_led”,节点内容如下:
mini_led {
compatible = "mini-led";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_led>;
led-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
status = "okay";
};
第 4 行,pinctrl-0 属性设置 LED 灯所使用的 PIN 对应的 pinctrl 节点。 第 5 行,led-gpio 属性指定了 LED 灯所使用的 GPIO,在这里就是 GPIO1 的 IO03,低电平有效。
添加pinctrl相关配置¶
在 iomuxc 节点的 imx6ul-evk 子节点下创建一个名为“pinctrl_led”的子节点,节点内容如下所示:
编译dts,然后用新的dts文件启动Linux
可以进入到/proc/device-tree/base下查看是否有mini_led这个节点信息。
可以进入到/sys/firmware/devicetree/base/alphaled下查看是否有mini_led这个节点的相关信息,可以查看一下 compatible、status 等属性值是否和我们设置的一致。
驱动框架api¶
在初始化的时候,先获得设备节点
然后获得led的编号
int led_gpio; /* led所使用的GPIO编号 */
/*获取设备树中的gpio属性,得到LED所使用的LED编号 */
led_gpio = of_get_named_gpio(nd, "led-gpio", 0);
通过编号控制gpio的输出,这个可以在文件打开的时候掉用
然后就是控制gpio的输出电平,可以在write的时候使用
驱动主要代码¶
一般有两种写法,一种使用gpiod,一种使用gpio
gpio写法¶
struct led_dev{
struct class *class;
struct device *device;
struct device_node *nd;
int led_gpio;
int major;
int minor;
};
struct led_dev led; /* led设备 */
static int led_drv_open(struct inode *inode, struct file *file)
{
gpio_direction_output(led.led_gpio, 1);
return 0;
}
static ssize_t led_drv_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
int err;
char val;
err = copy_from_user(&val, buf, 1);
gpio_set_value(led.led_gpio, val);
return 0;
}
static int led_probe(struct platform_device *dev)
{
led.nd = of_find_node_by_path("/mini_led");
led.led_gpio = of_get_named_gpio(nd, "led-gpio", 0);
/*创建字符设备*/
return 0;
}
static int led_remove(struct platform_device *dev)
{
/*删除字符设备*/
return 0;
}
gpiod写法¶
struct led_dev{
struct class *class;
struct device *device;
struct device_node *nd;
struct gpio_desc *led_gpiod;
int major;
int minor;
};
struct led_dev led; /* led设备 */
static int led_drv_open(struct inode *inode, struct file *file)
{
gpiod_direction_output(led.led_gpiod, 1);
return 0;
}
static ssize_t led_drv_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
int err;
char val;
err = copy_from_user(&val, buf, 1);
gpiod_set_value(led.led_gpiod, val);
return 0;
}
static int led_probe(struct platform_device *dev)
{
led.led_gpiod = gpiod_get(&dev->dev, "led", 0);
/*创建字符设备*/
return 0;
}
static int led_remove(struct platform_device *dev)
{
/*删除字符设备*/
//释放gpio
gpiod_put(led.led_gpiod);
return 0;
}