timed_gpio探测函数 static int timed_gpio_probe(struct platform_device *pdev) { struct timed_gpio_platform_data *pdata = pdev->dev.platform_data; struct timed_gpio *cur_gpio; struct timed_gpio_data *gpio_data, *gpio_dat; int i, j, ret = 0; if (!pdata) return -EBUSY; //为pdata->num_gpios个GPIO分配内存空间 gpio_data = kzalloc(sizeof(struct timed_gpio_data) * pdata->num_gpios, GFP_KERNEL); if (!gpio_data) return -ENOMEM; for (i = 0; i < pdata->num_gpios; i++) { cur_gpio = &pdata->gpios; gpio_dat = &gpio_data; hrtimer_init(&gpio_dat->timer, CLOCK_MONOTONIC,//初始化定时器 HRTIMER_MODE_REL); gpio_dat->timer.function = gpio_timer_func;//定时器回调函数 spin_lock_init(&gpio_dat->lock); gpio_dat->dev.name = cur_gpio->name; gpio_dat->dev.get_time = gpio_get_time; gpio_dat->dev.enable = gpio_enable; ret = gpio_request(cur_gpio->gpio, cur_gpio->name);//申请GPIO if (ret >= 0) { ret = timed_output_dev_register(&gpio_dat->dev);//调用timed_output框架注册函数 if (ret < 0) gpio_free(cur_gpio->gpio); } if (ret < 0) { for (j = 0; j < i; j++) { timed_output_dev_unregister(&gpio_data.dev); gpio_free(gpio_data.gpio); } kfree(gpio_data); return ret; } gpio_dat->gpio = cur_gpio->gpio; gpio_dat->max_timeout = cur_gpio->max_timeout; gpio_dat->active_low = cur_gpio->active_low; gpio_direction_output(gpio_dat->gpio, gpio_dat->active_low);//初始化GPIO的输出值 } platform_set_drvdata(pdev, gpio_data); return 0; }
初始化过程: 1. 首先调用kzalloc函数为 GPIO分配内存空间 2. 调用hrtimer_init函数初始化化内核定时器 3. 设置GPIO的enable函数为gpio_enable 4. 设置GPIO的get_time函数为gpio_get_time 5. 调用timed_output_dev_register函数注册设备驱动。 6. 初始化timed_gpio_data结构体 7. 调用gpio_direction_output函数设置GPIO的初始值。
GPIO驱动移除函数,调用timed_output_dev_unregister卸载驱动程序 static int timed_gpio_remove(struct platform_device *pdev) { struct timed_gpio_platform_data *pdata = pdev->dev.platform_data; struct timed_gpio_data *gpio_data = platform_get_drvdata(pdev); int i; for (i = 0; i < pdata->num_gpios; i++) { timed_output_dev_unregister(&gpio_data.dev); gpio_free(gpio_data.gpio); } kfree(gpio_data); return 0; }
功能回调函数gpio_timer_func分析:定时器超时后将执行此函数,此函数根据active_low的值来设置GPIO的高低电平。 static enum hrtimer_restart gpio_timer_func(struct hrtimer *timer) { struct timed_gpio_data *data = container_of(timer, struct timed_gpio_data, timer);
gpio_direction_output(data->gpio, data->active_low ? 1 : 0); return HRTIMER_NORESTART; }
gpio_enable函数为关键函数接受用户空间传过来的value值用于在一定时间里控制GPIO static void gpio_enable(struct timed_output_dev *dev, int value) { struct timed_gpio_data *data = container_of(dev, struct timed_gpio_data, dev); unsigned long flags;
spin_lock_irqsave(&data->lock, flags);
/* cancel previous timer and set GPIO according to value */ hrtimer_cancel(&data->timer); gpio_direction_output(data->gpio, data->active_low ? !value : !!value);
if (value > 0) { if (value > data->max_timeout) value = data->max_timeout; //启动定时器函数 hrtimer_start(&data->timer, ktime_set(value / 1000, (value % 1000) * 1000000), HRTIMER_MODE_REL); } spin_unlock_irqrestore(&data->lock, flags); } |