Root/drivers/gpio/gpio-bt8xx.c

1/*
2
3    bt8xx GPIO abuser
4
5    Copyright (C) 2008 Michael Buesch <m@bues.ch>
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/video/bt8xx/bt848.h"
54
55
56#define BT8XXGPIO_NR_GPIOS 24 /* We have 24 GPIO pins */
57
58
59struct bt8xxgpio {
60    spinlock_t lock;
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
76static int modparam_gpiobase = -1/* dynamic */;
77module_param_named(gpiobase, modparam_gpiobase, int, 0444);
78MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the default.");
79
80
81static 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
102static 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
115static 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
140static 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
159static 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
175static 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    }
193    if (!request_mem_region(pci_resource_start(dev, 0),
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 */
212    bgwrite(0, BT848_INT_MASK);
213
214    /* gpio init */
215    bgwrite(0, BT848_GPIO_DMA_CTL);
216    bgwrite(0, BT848_GPIO_REG_INP);
217    bgwrite(0, BT848_GPIO_OUT_EN);
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
228err_release_mem:
229    release_mem_region(pci_resource_start(dev, 0),
230               pci_resource_len(dev, 0));
231    pci_set_drvdata(dev, NULL);
232err_disable:
233    pci_disable_device(dev);
234err_freebg:
235    kfree(bg);
236
237    return err;
238}
239
240static void bt8xxgpio_remove(struct pci_dev *pdev)
241{
242    struct bt8xxgpio *bg = pci_get_drvdata(pdev);
243
244    gpiochip_remove(&bg->gpio);
245
246    bgwrite(0, BT848_INT_MASK);
247    bgwrite(~0x0, BT848_INT_STAT);
248    bgwrite(0x0, BT848_GPIO_OUT_EN);
249
250    iounmap(bg->mmio);
251    release_mem_region(pci_resource_start(pdev, 0),
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
260static 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
270    bgwrite(0, BT848_INT_MASK);
271    bgwrite(~0x0, BT848_INT_STAT);
272    bgwrite(0x0, BT848_GPIO_OUT_EN);
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
283static 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
297    bgwrite(0, BT848_INT_MASK);
298    bgwrite(0, BT848_GPIO_DMA_CTL);
299    bgwrite(0, BT848_GPIO_REG_INP);
300    bgwrite(bg->saved_outen, BT848_GPIO_OUT_EN);
301    bgwrite(bg->saved_data & bg->saved_outen,
302        BT848_GPIO_DATA);
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
313static struct pci_device_id bt8xxgpio_pci_tbl[] = {
314    { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) },
315    { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) },
316    { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) },
317    { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879) },
318    { 0, },
319};
320MODULE_DEVICE_TABLE(pci, bt8xxgpio_pci_tbl);
321
322static 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
331module_pci_driver(bt8xxgpio_pci_driver);
332
333MODULE_LICENSE("GPL");
334MODULE_AUTHOR("Michael Buesch");
335MODULE_DESCRIPTION("Abuse a BT8xx framegrabber card as generic GPIO card");
336

Archive Download this file



interactive