• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/gpio/
1/*
2
3    bt8xx GPIO abuser
4
5    Copyright (C) 2008 Michael Buesch <mb@bu3sch.de>
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	printk(KERN_INFO "bt8xxgpio: Abusing BT8xx card for GPIOs %d to %d\n",
227	       bg->gpio.base, bg->gpio.base + BT8XXGPIO_NR_GPIOS - 1);
228
229	return 0;
230
231err_release_mem:
232	release_mem_region(pci_resource_start(dev, 0),
233			   pci_resource_len(dev, 0));
234	pci_set_drvdata(dev, NULL);
235err_disable:
236	pci_disable_device(dev);
237err_freebg:
238	kfree(bg);
239
240	return err;
241}
242
243static void bt8xxgpio_remove(struct pci_dev *pdev)
244{
245	struct bt8xxgpio *bg = pci_get_drvdata(pdev);
246
247	gpiochip_remove(&bg->gpio);
248
249	bgwrite(0, BT848_INT_MASK);
250	bgwrite(~0x0, BT848_INT_STAT);
251	bgwrite(0x0, BT848_GPIO_OUT_EN);
252
253	iounmap(bg->mmio);
254	release_mem_region(pci_resource_start(pdev, 0),
255			   pci_resource_len(pdev, 0));
256	pci_disable_device(pdev);
257
258	pci_set_drvdata(pdev, NULL);
259	kfree(bg);
260}
261
262#ifdef CONFIG_PM
263static int bt8xxgpio_suspend(struct pci_dev *pdev, pm_message_t state)
264{
265	struct bt8xxgpio *bg = pci_get_drvdata(pdev);
266	unsigned long flags;
267
268	spin_lock_irqsave(&bg->lock, flags);
269
270	bg->saved_outen = bgread(BT848_GPIO_OUT_EN);
271	bg->saved_data = bgread(BT848_GPIO_DATA);
272
273	bgwrite(0, BT848_INT_MASK);
274	bgwrite(~0x0, BT848_INT_STAT);
275	bgwrite(0x0, BT848_GPIO_OUT_EN);
276
277	spin_unlock_irqrestore(&bg->lock, flags);
278
279	pci_save_state(pdev);
280	pci_disable_device(pdev);
281	pci_set_power_state(pdev, pci_choose_state(pdev, state));
282
283	return 0;
284}
285
286static int bt8xxgpio_resume(struct pci_dev *pdev)
287{
288	struct bt8xxgpio *bg = pci_get_drvdata(pdev);
289	unsigned long flags;
290	int err;
291
292	pci_set_power_state(pdev, 0);
293	err = pci_enable_device(pdev);
294	if (err)
295		return err;
296	pci_restore_state(pdev);
297
298	spin_lock_irqsave(&bg->lock, flags);
299
300	bgwrite(0, BT848_INT_MASK);
301	bgwrite(0, BT848_GPIO_DMA_CTL);
302	bgwrite(0, BT848_GPIO_REG_INP);
303	bgwrite(bg->saved_outen, BT848_GPIO_OUT_EN);
304	bgwrite(bg->saved_data & bg->saved_outen,
305		BT848_GPIO_DATA);
306
307	spin_unlock_irqrestore(&bg->lock, flags);
308
309	return 0;
310}
311#else
312#define bt8xxgpio_suspend NULL
313#define bt8xxgpio_resume NULL
314#endif /* CONFIG_PM */
315
316static struct pci_device_id bt8xxgpio_pci_tbl[] = {
317	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) },
318	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) },
319	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) },
320	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879) },
321	{ 0, },
322};
323MODULE_DEVICE_TABLE(pci, bt8xxgpio_pci_tbl);
324
325static struct pci_driver bt8xxgpio_pci_driver = {
326	.name		= "bt8xxgpio",
327	.id_table	= bt8xxgpio_pci_tbl,
328	.probe		= bt8xxgpio_probe,
329	.remove		= bt8xxgpio_remove,
330	.suspend	= bt8xxgpio_suspend,
331	.resume		= bt8xxgpio_resume,
332};
333
334static int __init bt8xxgpio_init(void)
335{
336	return pci_register_driver(&bt8xxgpio_pci_driver);
337}
338module_init(bt8xxgpio_init)
339
340static void __exit bt8xxgpio_exit(void)
341{
342	pci_unregister_driver(&bt8xxgpio_pci_driver);
343}
344module_exit(bt8xxgpio_exit)
345
346MODULE_LICENSE("GPL");
347MODULE_AUTHOR("Michael Buesch");
348MODULE_DESCRIPTION("Abuse a BT8xx framegrabber card as generic GPIO card");
349