Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
timed_gpio.c
Go to the documentation of this file.
1 /* drivers/misc/timed_gpio.c
2  *
3  * Copyright (C) 2008 Google, Inc.
4  * Author: Mike Lockwood <[email protected]>
5  *
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  */
16 
17 #include <linux/module.h>
18 #include <linux/platform_device.h>
19 #include <linux/slab.h>
20 #include <linux/hrtimer.h>
21 #include <linux/err.h>
22 #include <linux/gpio.h>
23 
24 #include "timed_output.h"
25 #include "timed_gpio.h"
26 
27 
30  struct hrtimer timer;
32  unsigned gpio;
35 };
36 
37 static enum hrtimer_restart gpio_timer_func(struct hrtimer *timer)
38 {
39  struct timed_gpio_data *data =
40  container_of(timer, struct timed_gpio_data, timer);
41 
42  gpio_direction_output(data->gpio, data->active_low ? 1 : 0);
43  return HRTIMER_NORESTART;
44 }
45 
46 static int gpio_get_time(struct timed_output_dev *dev)
47 {
48  struct timed_gpio_data *data =
49  container_of(dev, struct timed_gpio_data, dev);
50 
51  if (hrtimer_active(&data->timer)) {
53  struct timeval t = ktime_to_timeval(r);
54  return t.tv_sec * 1000 + t.tv_usec / 1000;
55  } else
56  return 0;
57 }
58 
59 static void gpio_enable(struct timed_output_dev *dev, int value)
60 {
61  struct timed_gpio_data *data =
62  container_of(dev, struct timed_gpio_data, dev);
63  unsigned long flags;
64 
65  spin_lock_irqsave(&data->lock, flags);
66 
67  /* cancel previous timer and set GPIO according to value */
68  hrtimer_cancel(&data->timer);
69  gpio_direction_output(data->gpio, data->active_low ? !value : !!value);
70 
71  if (value > 0) {
72  if (value > data->max_timeout)
73  value = data->max_timeout;
74 
75  hrtimer_start(&data->timer,
76  ktime_set(value / 1000, (value % 1000) * 1000000),
78  }
79 
80  spin_unlock_irqrestore(&data->lock, flags);
81 }
82 
83 static int timed_gpio_probe(struct platform_device *pdev)
84 {
85  struct timed_gpio_platform_data *pdata = pdev->dev.platform_data;
86  struct timed_gpio *cur_gpio;
87  struct timed_gpio_data *gpio_data, *gpio_dat;
88  int i, ret;
89 
90  if (!pdata)
91  return -EBUSY;
92 
93  gpio_data = kzalloc(sizeof(struct timed_gpio_data) * pdata->num_gpios,
94  GFP_KERNEL);
95  if (!gpio_data)
96  return -ENOMEM;
97 
98  for (i = 0; i < pdata->num_gpios; i++) {
99  cur_gpio = &pdata->gpios[i];
100  gpio_dat = &gpio_data[i];
101 
102  hrtimer_init(&gpio_dat->timer, CLOCK_MONOTONIC,
104  gpio_dat->timer.function = gpio_timer_func;
105  spin_lock_init(&gpio_dat->lock);
106 
107  gpio_dat->dev.name = cur_gpio->name;
108  gpio_dat->dev.get_time = gpio_get_time;
109  gpio_dat->dev.enable = gpio_enable;
110  ret = gpio_request(cur_gpio->gpio, cur_gpio->name);
111  if (ret < 0)
112  goto err_out;
113  ret = timed_output_dev_register(&gpio_dat->dev);
114  if (ret < 0) {
115  gpio_free(cur_gpio->gpio);
116  goto err_out;
117  }
118 
119  gpio_dat->gpio = cur_gpio->gpio;
120  gpio_dat->max_timeout = cur_gpio->max_timeout;
121  gpio_dat->active_low = cur_gpio->active_low;
122  gpio_direction_output(gpio_dat->gpio, gpio_dat->active_low);
123  }
124 
125  platform_set_drvdata(pdev, gpio_data);
126 
127  return 0;
128 
129 err_out:
130  while (--i >= 0) {
131  timed_output_dev_unregister(&gpio_data[i].dev);
132  gpio_free(gpio_data[i].gpio);
133  }
134  kfree(gpio_data);
135 
136  return ret;
137 }
138 
139 static int timed_gpio_remove(struct platform_device *pdev)
140 {
141  struct timed_gpio_platform_data *pdata = pdev->dev.platform_data;
142  struct timed_gpio_data *gpio_data = platform_get_drvdata(pdev);
143  int i;
144 
145  for (i = 0; i < pdata->num_gpios; i++) {
146  timed_output_dev_unregister(&gpio_data[i].dev);
147  gpio_free(gpio_data[i].gpio);
148  }
149 
150  kfree(gpio_data);
151 
152  return 0;
153 }
154 
155 static struct platform_driver timed_gpio_driver = {
156  .probe = timed_gpio_probe,
157  .remove = timed_gpio_remove,
158  .driver = {
159  .name = TIMED_GPIO_NAME,
160  .owner = THIS_MODULE,
161  },
162 };
163 
164 module_platform_driver(timed_gpio_driver);
165 
166 MODULE_AUTHOR("Mike Lockwood <[email protected]>");
167 MODULE_DESCRIPTION("timed gpio driver");
168 MODULE_LICENSE("GPL");