目录
前言
在 正点原子阿尔法Linux开发板LED灯驱动开发(自动创建设备节点+通过设备树获取寄存器信息)基础上,通过设备树 pinctrl子系统来设置pin的复用功能(复用为GPIO)和电气属性(上 /下拉、速度、驱动能力等),通过gpio子系统来完成led所用GPIO的配置和读写。
一、pinctrl子系统添加pin信息
在 imx6ull-alientek-emmc.dts 设备树的根节点下 iomuxc 节点中 添加如下子节点
&iomuxc {
...
pinctrl_gpio_leds: gpio-leds {
fsl,pins = <
MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x10B0
>;
};
...
};
二、gpio子系统节点添加
在 imx6ull-alientek-emmc.dts 设备树的根节点下 添加如下子节点
/*led节点(通过pinctrl子系统和GPIO子系统)*/
gpioled{
compatible = "alientek-gpioled";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio_leds>;/*pinctrl子系统*/
led-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;/*GPIO子系统*/
status = "okay";
}
三、驱动修改
1、在设备结构体 gpioled_dev 中增加 led_gpio 字段
struct gpioled_dev
{
struct cdev cdev; /*字符设备*/
struct class *class;/*类*/
struct device *device;/*设备*/
dev_t devid; /*设备号*/
int major; /*主设备号*/
int minor; /*次设备号*/
struct device_node *nd; /*设备节点*/
int led_gpio; /*led所使用的GPIO编号*/
};
2、在 gpioled_fops.gpioled_open 中添加获取设备树节点信息,通过gpio子系统函数设置GPIO为输出。pin的复用功能设置和GPIO的电气属性设置已经在pinctrl子系统中完成了,所以这里不再需要手动再设置了
static int gpioled_open(struct inode *inode, struct file *file)
{
int ret = 0;
file->private_data = &gpioled;
/*1、找到节点 gpioled,路径是 /gpioled */
gpioled.nd = of_find_node_by_path("/gpioled");
if (gpioled.nd == NULL){
printk("gpioled node can not found!\r\n");
return -EINVAL;
} else {
printk("gpioled node has been found!\r\n");
}
/*2、获取设备树中的gpio属性,得到LED所使用的LED编号*/
gpioled.led_gpio = of_get_named_gpio(gpioled.nd, "led-gpio", 0);
if (gpioled.led_gpio < 0){
printk("can't get led-gpio \r\n");
return -EINVAL;
}
printk("led-gpio num = %d \r\n", gpioled.led_gpio);
/*3、设置GPIO_IO03为输出,并且输出高电平,默认关闭LED灯*/
ret = gpio_direction_output(gpioled.led_gpio, 1);
if (ret < 0){
printk("can't set gpio \r\n");
}
return ret;
}
3、在 gpioled_fops.gpioled_write 中通过 gpio_set_value 设置GPIO的高低电平
int ret = 0;
uint8_t data[1], ledsta;
struct gpioled_dev *dev = file->private_data;
ret = copy_from_user(data, buf, count);
if (ret < 0){
printk("kernel write failed!\r\n");
return -EFAULT;
}
ledsta = data[0];
if (ledsta == LEDOFF){
gpio_set_value(dev->led_gpio, 0);
}
else if (ledsta == LEDON){
gpio_set_value(dev->led_gpio, 1);
}
else
printk("led para error\r\n");
return ret;