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);
}
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) | Powered by Discuz! 7.0.0 |