1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46#include <linux/module.h>
47#include <linux/pci.h>
48#include <linux/spinlock.h>
49#include <linux/gpio.h>
50
51
52#include "../media/video/bt8xx/bt848.h"
53
54
55#define BT8XXGPIO_NR_GPIOS 24
56
57
58struct bt8xxgpio {
59 spinlock_t lock;
60
61 void __iomem *mmio;
62 struct pci_dev *pdev;
63 struct gpio_chip gpio;
64
65#ifdef CONFIG_PM
66 u32 saved_outen;
67 u32 saved_data;
68#endif
69};
70
71#define bgwrite(dat, adr) writel((dat), bg->mmio+(adr))
72#define bgread(adr) readl(bg->mmio+(adr))
73
74
75static int modparam_gpiobase = -1;
76module_param_named(gpiobase, modparam_gpiobase, int, 0444);
77MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the default.");
78
79
80static int bt8xxgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
81{
82 struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
83 unsigned long flags;
84 u32 outen, data;
85
86 spin_lock_irqsave(&bg->lock, flags);
87
88 data = bgread(BT848_GPIO_DATA);
89 data &= ~(1 << nr);
90 bgwrite(data, BT848_GPIO_DATA);
91
92 outen = bgread(BT848_GPIO_OUT_EN);
93 outen &= ~(1 << nr);
94 bgwrite(outen, BT848_GPIO_OUT_EN);
95
96 spin_unlock_irqrestore(&bg->lock, flags);
97
98 return 0;
99}
100
101static int bt8xxgpio_gpio_get(struct gpio_chip *gpio, unsigned nr)
102{
103 struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
104 unsigned long flags;
105 u32 val;
106
107 spin_lock_irqsave(&bg->lock, flags);
108 val = bgread(BT848_GPIO_DATA);
109 spin_unlock_irqrestore(&bg->lock, flags);
110
111 return !!(val & (1 << nr));
112}
113
114static int bt8xxgpio_gpio_direction_output(struct gpio_chip *gpio,
115 unsigned nr, int val)
116{
117 struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
118 unsigned long flags;
119 u32 outen, data;
120
121 spin_lock_irqsave(&bg->lock, flags);
122
123 outen = bgread(BT848_GPIO_OUT_EN);
124 outen |= (1 << nr);
125 bgwrite(outen, BT848_GPIO_OUT_EN);
126
127 data = bgread(BT848_GPIO_DATA);
128 if (val)
129 data |= (1 << nr);
130 else
131 data &= ~(1 << nr);
132 bgwrite(data, BT848_GPIO_DATA);
133
134 spin_unlock_irqrestore(&bg->lock, flags);
135
136 return 0;
137}
138
139static void bt8xxgpio_gpio_set(struct gpio_chip *gpio,
140 unsigned nr, int val)
141{
142 struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
143 unsigned long flags;
144 u32 data;
145
146 spin_lock_irqsave(&bg->lock, flags);
147
148 data = bgread(BT848_GPIO_DATA);
149 if (val)
150 data |= (1 << nr);
151 else
152 data &= ~(1 << nr);
153 bgwrite(data, BT848_GPIO_DATA);
154
155 spin_unlock_irqrestore(&bg->lock, flags);
156}
157
158static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg)
159{
160 struct gpio_chip *c = &bg->gpio;
161
162 c->label = dev_name(&bg->pdev->dev);
163 c->owner = THIS_MODULE;
164 c->direction_input = bt8xxgpio_gpio_direction_input;
165 c->get = bt8xxgpio_gpio_get;
166 c->direction_output = bt8xxgpio_gpio_direction_output;
167 c->set = bt8xxgpio_gpio_set;
168 c->dbg_show = NULL;
169 c->base = modparam_gpiobase;
170 c->ngpio = BT8XXGPIO_NR_GPIOS;
171 c->can_sleep = 0;
172}
173
174static int bt8xxgpio_probe(struct pci_dev *dev,
175 const struct pci_device_id *pci_id)
176{
177 struct bt8xxgpio *bg;
178 int err;
179
180 bg = kzalloc(sizeof(*bg), GFP_KERNEL);
181 if (!bg)
182 return -ENOMEM;
183
184 bg->pdev = dev;
185 spin_lock_init(&bg->lock);
186
187 err = pci_enable_device(dev);
188 if (err) {
189 printk(KERN_ERR "bt8xxgpio: Can't enable device.\n");
190 goto err_freebg;
191 }
192 if (!request_mem_region(pci_resource_start(dev, 0),
193 pci_resource_len(dev, 0),
194 "bt8xxgpio")) {
195 printk(KERN_WARNING "bt8xxgpio: Can't request iomem (0x%llx).\n",
196 (unsigned long long)pci_resource_start(dev, 0));
197 err = -EBUSY;
198 goto err_disable;
199 }
200 pci_set_master(dev);
201 pci_set_drvdata(dev, bg);
202
203 bg->mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
204 if (!bg->mmio) {
205 printk(KERN_ERR "bt8xxgpio: ioremap() failed\n");
206 err = -EIO;
207 goto err_release_mem;
208 }
209
210
211 bgwrite(0, BT848_INT_MASK);
212
213
214 bgwrite(0, BT848_GPIO_DMA_CTL);
215 bgwrite(0, BT848_GPIO_REG_INP);
216 bgwrite(0, BT848_GPIO_OUT_EN);
217
218 bt8xxgpio_gpio_setup(bg);
219 err = gpiochip_add(&bg->gpio);
220 if (err) {
221 printk(KERN_ERR "bt8xxgpio: Failed to register GPIOs\n");
222 goto err_release_mem;
223 }
224
225 printk(KERN_INFO "bt8xxgpio: Abusing BT8xx card for GPIOs %d to %d\n",
226 bg->gpio.base, bg->gpio.base + BT8XXGPIO_NR_GPIOS - 1);
227
228 return 0;
229
230err_release_mem:
231 release_mem_region(pci_resource_start(dev, 0),
232 pci_resource_len(dev, 0));
233 pci_set_drvdata(dev, NULL);
234err_disable:
235 pci_disable_device(dev);
236err_freebg:
237 kfree(bg);
238
239 return err;
240}
241
242static void bt8xxgpio_remove(struct pci_dev *pdev)
243{
244 struct bt8xxgpio *bg = pci_get_drvdata(pdev);
245
246 gpiochip_remove(&bg->gpio);
247
248 bgwrite(0, BT848_INT_MASK);
249 bgwrite(~0x0, BT848_INT_STAT);
250 bgwrite(0x0, BT848_GPIO_OUT_EN);
251
252 iounmap(bg->mmio);
253 release_mem_region(pci_resource_start(pdev, 0),
254 pci_resource_len(pdev, 0));
255 pci_disable_device(pdev);
256
257 pci_set_drvdata(pdev, NULL);
258 kfree(bg);
259}
260
261#ifdef CONFIG_PM
262static int bt8xxgpio_suspend(struct pci_dev *pdev, pm_message_t state)
263{
264 struct bt8xxgpio *bg = pci_get_drvdata(pdev);
265 unsigned long flags;
266
267 spin_lock_irqsave(&bg->lock, flags);
268
269 bg->saved_outen = bgread(BT848_GPIO_OUT_EN);
270 bg->saved_data = bgread(BT848_GPIO_DATA);
271
272 bgwrite(0, BT848_INT_MASK);
273 bgwrite(~0x0, BT848_INT_STAT);
274 bgwrite(0x0, BT848_GPIO_OUT_EN);
275
276 spin_unlock_irqrestore(&bg->lock, flags);
277
278 pci_save_state(pdev);
279 pci_disable_device(pdev);
280 pci_set_power_state(pdev, pci_choose_state(pdev, state));
281
282 return 0;
283}
284
285static int bt8xxgpio_resume(struct pci_dev *pdev)
286{
287 struct bt8xxgpio *bg = pci_get_drvdata(pdev);
288 unsigned long flags;
289 int err;
290
291 pci_set_power_state(pdev, 0);
292 err = pci_enable_device(pdev);
293 if (err)
294 return err;
295 pci_restore_state(pdev);
296
297 spin_lock_irqsave(&bg->lock, flags);
298
299 bgwrite(0, BT848_INT_MASK);
300 bgwrite(0, BT848_GPIO_DMA_CTL);
301 bgwrite(0, BT848_GPIO_REG_INP);
302 bgwrite(bg->saved_outen, BT848_GPIO_OUT_EN);
303 bgwrite(bg->saved_data & bg->saved_outen,
304 BT848_GPIO_DATA);
305
306 spin_unlock_irqrestore(&bg->lock, flags);
307
308 return 0;
309}
310#else
311#define bt8xxgpio_suspend NULL
312#define bt8xxgpio_resume NULL
313#endif
314
315static struct pci_device_id bt8xxgpio_pci_tbl[] = {
316 { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) },
317 { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) },
318 { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) },
319 { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879) },
320 { 0, },
321};
322MODULE_DEVICE_TABLE(pci, bt8xxgpio_pci_tbl);
323
324static struct pci_driver bt8xxgpio_pci_driver = {
325 .name = "bt8xxgpio",
326 .id_table = bt8xxgpio_pci_tbl,
327 .probe = bt8xxgpio_probe,
328 .remove = bt8xxgpio_remove,
329 .suspend = bt8xxgpio_suspend,
330 .resume = bt8xxgpio_resume,
331};
332
333static int __init bt8xxgpio_init(void)
334{
335 return pci_register_driver(&bt8xxgpio_pci_driver);
336}
337module_init(bt8xxgpio_init)
338
339static void __exit bt8xxgpio_exit(void)
340{
341 pci_unregister_driver(&bt8xxgpio_pci_driver);
342}
343module_exit(bt8xxgpio_exit)
344
345MODULE_LICENSE("GPL");
346MODULE_AUTHOR("Michael Buesch");
347MODULE_DESCRIPTION("Abuse a BT8xx framegrabber card as generic GPIO card");
348