Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gpio-bt8xx.c
Go to the documentation of this file.
1 /*
2 
3  bt8xx GPIO abuser
4 
5  Copyright (C) 2008 Michael Buesch <[email protected]>
6 
7  Please do _only_ contact the people listed _above_ with issues related to this driver.
8  All the other people listed below are not related to this driver. Their names
9  are only here, because this driver is derived from the bt848 driver.
10 
11 
12  Derived from the bt848 driver:
13 
14  Copyright (C) 1996,97,98 Ralph Metzler
15  & Marcus Metzler
16  (c) 1999-2002 Gerd Knorr
17 
18  some v4l2 code lines are taken from Justin's bttv2 driver which is
19  (c) 2000 Justin Schoeman
20 
21  V4L1 removal from:
22  (c) 2005-2006 Nickolay V. Shmyrev
23 
24  Fixes to be fully V4L2 compliant by
25  (c) 2006 Mauro Carvalho Chehab
26 
27  Cropping and overscan support
28  Copyright (C) 2005, 2006 Michael H. Schimek
29  Sponsored by OPQ Systems AB
30 
31  This program is free software; you can redistribute it and/or modify
32  it under the terms of the GNU General Public License as published by
33  the Free Software Foundation; either version 2 of the License, or
34  (at your option) any later version.
35 
36  This program is distributed in the hope that it will be useful,
37  but WITHOUT ANY WARRANTY; without even the implied warranty of
38  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39  GNU General Public License for more details.
40 
41  You should have received a copy of the GNU General Public License
42  along with this program; if not, write to the Free Software
43  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
44 */
45 
46 #include <linux/module.h>
47 #include <linux/pci.h>
48 #include <linux/spinlock.h>
49 #include <linux/gpio.h>
50 #include <linux/slab.h>
51 
52 /* Steal the hardware definitions from the bttv driver. */
53 #include "../media/pci/bt8xx/bt848.h"
54 
55 
56 #define BT8XXGPIO_NR_GPIOS 24 /* We have 24 GPIO pins */
57 
58 
59 struct bt8xxgpio {
61 
62  void __iomem *mmio;
63  struct pci_dev *pdev;
64  struct gpio_chip gpio;
65 
66 #ifdef CONFIG_PM
67  u32 saved_outen;
68  u32 saved_data;
69 #endif
70 };
71 
72 #define bgwrite(dat, adr) writel((dat), bg->mmio+(adr))
73 #define bgread(adr) readl(bg->mmio+(adr))
74 
75 
76 static int modparam_gpiobase = -1/* dynamic */;
77 module_param_named(gpiobase, modparam_gpiobase, int, 0444);
78 MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the default.");
79 
80 
81 static int bt8xxgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
82 {
83  struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
84  unsigned long flags;
85  u32 outen, data;
86 
87  spin_lock_irqsave(&bg->lock, flags);
88 
89  data = bgread(BT848_GPIO_DATA);
90  data &= ~(1 << nr);
91  bgwrite(data, BT848_GPIO_DATA);
92 
93  outen = bgread(BT848_GPIO_OUT_EN);
94  outen &= ~(1 << nr);
95  bgwrite(outen, BT848_GPIO_OUT_EN);
96 
97  spin_unlock_irqrestore(&bg->lock, flags);
98 
99  return 0;
100 }
101 
102 static int bt8xxgpio_gpio_get(struct gpio_chip *gpio, unsigned nr)
103 {
104  struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
105  unsigned long flags;
106  u32 val;
107 
108  spin_lock_irqsave(&bg->lock, flags);
109  val = bgread(BT848_GPIO_DATA);
110  spin_unlock_irqrestore(&bg->lock, flags);
111 
112  return !!(val & (1 << nr));
113 }
114 
115 static int bt8xxgpio_gpio_direction_output(struct gpio_chip *gpio,
116  unsigned nr, int val)
117 {
118  struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
119  unsigned long flags;
120  u32 outen, data;
121 
122  spin_lock_irqsave(&bg->lock, flags);
123 
124  outen = bgread(BT848_GPIO_OUT_EN);
125  outen |= (1 << nr);
126  bgwrite(outen, BT848_GPIO_OUT_EN);
127 
128  data = bgread(BT848_GPIO_DATA);
129  if (val)
130  data |= (1 << nr);
131  else
132  data &= ~(1 << nr);
133  bgwrite(data, BT848_GPIO_DATA);
134 
135  spin_unlock_irqrestore(&bg->lock, flags);
136 
137  return 0;
138 }
139 
140 static void bt8xxgpio_gpio_set(struct gpio_chip *gpio,
141  unsigned nr, int val)
142 {
143  struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
144  unsigned long flags;
145  u32 data;
146 
147  spin_lock_irqsave(&bg->lock, flags);
148 
149  data = bgread(BT848_GPIO_DATA);
150  if (val)
151  data |= (1 << nr);
152  else
153  data &= ~(1 << nr);
154  bgwrite(data, BT848_GPIO_DATA);
155 
156  spin_unlock_irqrestore(&bg->lock, flags);
157 }
158 
159 static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg)
160 {
161  struct gpio_chip *c = &bg->gpio;
162 
163  c->label = dev_name(&bg->pdev->dev);
164  c->owner = THIS_MODULE;
165  c->direction_input = bt8xxgpio_gpio_direction_input;
166  c->get = bt8xxgpio_gpio_get;
167  c->direction_output = bt8xxgpio_gpio_direction_output;
168  c->set = bt8xxgpio_gpio_set;
169  c->dbg_show = NULL;
170  c->base = modparam_gpiobase;
171  c->ngpio = BT8XXGPIO_NR_GPIOS;
172  c->can_sleep = 0;
173 }
174 
175 static int bt8xxgpio_probe(struct pci_dev *dev,
176  const struct pci_device_id *pci_id)
177 {
178  struct bt8xxgpio *bg;
179  int err;
180 
181  bg = kzalloc(sizeof(*bg), GFP_KERNEL);
182  if (!bg)
183  return -ENOMEM;
184 
185  bg->pdev = dev;
186  spin_lock_init(&bg->lock);
187 
188  err = pci_enable_device(dev);
189  if (err) {
190  printk(KERN_ERR "bt8xxgpio: Can't enable device.\n");
191  goto err_freebg;
192  }
194  pci_resource_len(dev, 0),
195  "bt8xxgpio")) {
196  printk(KERN_WARNING "bt8xxgpio: Can't request iomem (0x%llx).\n",
197  (unsigned long long)pci_resource_start(dev, 0));
198  err = -EBUSY;
199  goto err_disable;
200  }
201  pci_set_master(dev);
202  pci_set_drvdata(dev, bg);
203 
204  bg->mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
205  if (!bg->mmio) {
206  printk(KERN_ERR "bt8xxgpio: ioremap() failed\n");
207  err = -EIO;
208  goto err_release_mem;
209  }
210 
211  /* Disable interrupts */
213 
214  /* gpio init */
218 
219  bt8xxgpio_gpio_setup(bg);
220  err = gpiochip_add(&bg->gpio);
221  if (err) {
222  printk(KERN_ERR "bt8xxgpio: Failed to register GPIOs\n");
223  goto err_release_mem;
224  }
225 
226  return 0;
227 
228 err_release_mem:
230  pci_resource_len(dev, 0));
231  pci_set_drvdata(dev, NULL);
232 err_disable:
233  pci_disable_device(dev);
234 err_freebg:
235  kfree(bg);
236 
237  return err;
238 }
239 
240 static void bt8xxgpio_remove(struct pci_dev *pdev)
241 {
242  struct bt8xxgpio *bg = pci_get_drvdata(pdev);
243 
244  gpiochip_remove(&bg->gpio);
245 
247  bgwrite(~0x0, BT848_INT_STAT);
249 
250  iounmap(bg->mmio);
252  pci_resource_len(pdev, 0));
253  pci_disable_device(pdev);
254 
255  pci_set_drvdata(pdev, NULL);
256  kfree(bg);
257 }
258 
259 #ifdef CONFIG_PM
260 static int bt8xxgpio_suspend(struct pci_dev *pdev, pm_message_t state)
261 {
262  struct bt8xxgpio *bg = pci_get_drvdata(pdev);
263  unsigned long flags;
264 
265  spin_lock_irqsave(&bg->lock, flags);
266 
267  bg->saved_outen = bgread(BT848_GPIO_OUT_EN);
268  bg->saved_data = bgread(BT848_GPIO_DATA);
269 
271  bgwrite(~0x0, BT848_INT_STAT);
273 
274  spin_unlock_irqrestore(&bg->lock, flags);
275 
276  pci_save_state(pdev);
277  pci_disable_device(pdev);
278  pci_set_power_state(pdev, pci_choose_state(pdev, state));
279 
280  return 0;
281 }
282 
283 static int bt8xxgpio_resume(struct pci_dev *pdev)
284 {
285  struct bt8xxgpio *bg = pci_get_drvdata(pdev);
286  unsigned long flags;
287  int err;
288 
289  pci_set_power_state(pdev, 0);
290  err = pci_enable_device(pdev);
291  if (err)
292  return err;
293  pci_restore_state(pdev);
294 
295  spin_lock_irqsave(&bg->lock, flags);
296 
300  bgwrite(bg->saved_outen, BT848_GPIO_OUT_EN);
301  bgwrite(bg->saved_data & bg->saved_outen,
303 
304  spin_unlock_irqrestore(&bg->lock, flags);
305 
306  return 0;
307 }
308 #else
309 #define bt8xxgpio_suspend NULL
310 #define bt8xxgpio_resume NULL
311 #endif /* CONFIG_PM */
312 
313 static DEFINE_PCI_DEVICE_TABLE(bt8xxgpio_pci_tbl) = {
318  { 0, },
319 };
320 MODULE_DEVICE_TABLE(pci, bt8xxgpio_pci_tbl);
321 
322 static struct pci_driver bt8xxgpio_pci_driver = {
323  .name = "bt8xxgpio",
324  .id_table = bt8xxgpio_pci_tbl,
325  .probe = bt8xxgpio_probe,
326  .remove = bt8xxgpio_remove,
327  .suspend = bt8xxgpio_suspend,
328  .resume = bt8xxgpio_resume,
329 };
330 
331 module_pci_driver(bt8xxgpio_pci_driver);
332 
333 MODULE_LICENSE("GPL");
334 MODULE_AUTHOR("Michael Buesch");
335 MODULE_DESCRIPTION("Abuse a BT8xx framegrabber card as generic GPIO card");