174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2c103de24SGrant Likely /*
3c103de24SGrant Likely
4c103de24SGrant Likely bt8xx GPIO abuser
5c103de24SGrant Likely
6d3ec4844SLinus Torvalds Copyright (C) 2008 Michael Buesch <m@bues.ch>
7c103de24SGrant Likely
8c103de24SGrant Likely Please do _only_ contact the people listed _above_ with issues related to this driver.
9c103de24SGrant Likely All the other people listed below are not related to this driver. Their names
10c103de24SGrant Likely are only here, because this driver is derived from the bt848 driver.
11c103de24SGrant Likely
12c103de24SGrant Likely
13c103de24SGrant Likely Derived from the bt848 driver:
14c103de24SGrant Likely
15c103de24SGrant Likely Copyright (C) 1996,97,98 Ralph Metzler
16c103de24SGrant Likely & Marcus Metzler
17c103de24SGrant Likely (c) 1999-2002 Gerd Knorr
18c103de24SGrant Likely
19c103de24SGrant Likely some v4l2 code lines are taken from Justin's bttv2 driver which is
20c103de24SGrant Likely (c) 2000 Justin Schoeman
21c103de24SGrant Likely
22c103de24SGrant Likely V4L1 removal from:
23c103de24SGrant Likely (c) 2005-2006 Nickolay V. Shmyrev
24c103de24SGrant Likely
25c103de24SGrant Likely Fixes to be fully V4L2 compliant by
26c103de24SGrant Likely (c) 2006 Mauro Carvalho Chehab
27c103de24SGrant Likely
28c103de24SGrant Likely Cropping and overscan support
29c103de24SGrant Likely Copyright (C) 2005, 2006 Michael H. Schimek
30c103de24SGrant Likely Sponsored by OPQ Systems AB
31c103de24SGrant Likely
32c103de24SGrant Likely */
33c103de24SGrant Likely
34c103de24SGrant Likely #include <linux/module.h>
35c103de24SGrant Likely #include <linux/pci.h>
36c103de24SGrant Likely #include <linux/spinlock.h>
37e88a2ae2SLinus Walleij #include <linux/gpio/driver.h>
38c103de24SGrant Likely #include <linux/slab.h>
39c103de24SGrant Likely
40c103de24SGrant Likely /* Steal the hardware definitions from the bttv driver. */
4152d32258SAxel Lin #include "../media/pci/bt8xx/bt848.h"
42c103de24SGrant Likely
43c103de24SGrant Likely
44c103de24SGrant Likely #define BT8XXGPIO_NR_GPIOS 24 /* We have 24 GPIO pins */
45c103de24SGrant Likely
46c103de24SGrant Likely
47c103de24SGrant Likely struct bt8xxgpio {
48c103de24SGrant Likely spinlock_t lock;
49c103de24SGrant Likely
50c103de24SGrant Likely void __iomem *mmio;
51c103de24SGrant Likely struct pci_dev *pdev;
52c103de24SGrant Likely struct gpio_chip gpio;
53c103de24SGrant Likely
54c103de24SGrant Likely #ifdef CONFIG_PM
55c103de24SGrant Likely u32 saved_outen;
56c103de24SGrant Likely u32 saved_data;
57c103de24SGrant Likely #endif
58c103de24SGrant Likely };
59c103de24SGrant Likely
60c103de24SGrant Likely #define bgwrite(dat, adr) writel((dat), bg->mmio+(adr))
61c103de24SGrant Likely #define bgread(adr) readl(bg->mmio+(adr))
62c103de24SGrant Likely
63c103de24SGrant Likely
64c103de24SGrant Likely static int modparam_gpiobase = -1/* dynamic */;
65c103de24SGrant Likely module_param_named(gpiobase, modparam_gpiobase, int, 0444);
66c103de24SGrant Likely MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the default.");
67c103de24SGrant Likely
68c103de24SGrant Likely
bt8xxgpio_gpio_direction_input(struct gpio_chip * gpio,unsigned nr)69c103de24SGrant Likely static int bt8xxgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
70c103de24SGrant Likely {
71e51b5523SLinus Walleij struct bt8xxgpio *bg = gpiochip_get_data(gpio);
72c103de24SGrant Likely unsigned long flags;
73c103de24SGrant Likely u32 outen, data;
74c103de24SGrant Likely
75c103de24SGrant Likely spin_lock_irqsave(&bg->lock, flags);
76c103de24SGrant Likely
77c103de24SGrant Likely data = bgread(BT848_GPIO_DATA);
78c103de24SGrant Likely data &= ~(1 << nr);
79c103de24SGrant Likely bgwrite(data, BT848_GPIO_DATA);
80c103de24SGrant Likely
81c103de24SGrant Likely outen = bgread(BT848_GPIO_OUT_EN);
82c103de24SGrant Likely outen &= ~(1 << nr);
83c103de24SGrant Likely bgwrite(outen, BT848_GPIO_OUT_EN);
84c103de24SGrant Likely
85c103de24SGrant Likely spin_unlock_irqrestore(&bg->lock, flags);
86c103de24SGrant Likely
87c103de24SGrant Likely return 0;
88c103de24SGrant Likely }
89c103de24SGrant Likely
bt8xxgpio_gpio_get(struct gpio_chip * gpio,unsigned nr)90c103de24SGrant Likely static int bt8xxgpio_gpio_get(struct gpio_chip *gpio, unsigned nr)
91c103de24SGrant Likely {
92e51b5523SLinus Walleij struct bt8xxgpio *bg = gpiochip_get_data(gpio);
93c103de24SGrant Likely unsigned long flags;
94c103de24SGrant Likely u32 val;
95c103de24SGrant Likely
96c103de24SGrant Likely spin_lock_irqsave(&bg->lock, flags);
97c103de24SGrant Likely val = bgread(BT848_GPIO_DATA);
98c103de24SGrant Likely spin_unlock_irqrestore(&bg->lock, flags);
99c103de24SGrant Likely
100c103de24SGrant Likely return !!(val & (1 << nr));
101c103de24SGrant Likely }
102c103de24SGrant Likely
bt8xxgpio_gpio_direction_output(struct gpio_chip * gpio,unsigned nr,int val)103c103de24SGrant Likely static int bt8xxgpio_gpio_direction_output(struct gpio_chip *gpio,
104c103de24SGrant Likely unsigned nr, int val)
105c103de24SGrant Likely {
106e51b5523SLinus Walleij struct bt8xxgpio *bg = gpiochip_get_data(gpio);
107c103de24SGrant Likely unsigned long flags;
108c103de24SGrant Likely u32 outen, data;
109c103de24SGrant Likely
110c103de24SGrant Likely spin_lock_irqsave(&bg->lock, flags);
111c103de24SGrant Likely
112c103de24SGrant Likely outen = bgread(BT848_GPIO_OUT_EN);
113c103de24SGrant Likely outen |= (1 << nr);
114c103de24SGrant Likely bgwrite(outen, BT848_GPIO_OUT_EN);
115c103de24SGrant Likely
116c103de24SGrant Likely data = bgread(BT848_GPIO_DATA);
117c103de24SGrant Likely if (val)
118c103de24SGrant Likely data |= (1 << nr);
119c103de24SGrant Likely else
120c103de24SGrant Likely data &= ~(1 << nr);
121c103de24SGrant Likely bgwrite(data, BT848_GPIO_DATA);
122c103de24SGrant Likely
123c103de24SGrant Likely spin_unlock_irqrestore(&bg->lock, flags);
124c103de24SGrant Likely
125c103de24SGrant Likely return 0;
126c103de24SGrant Likely }
127c103de24SGrant Likely
bt8xxgpio_gpio_set(struct gpio_chip * gpio,unsigned nr,int val)128c103de24SGrant Likely static void bt8xxgpio_gpio_set(struct gpio_chip *gpio,
129c103de24SGrant Likely unsigned nr, int val)
130c103de24SGrant Likely {
131e51b5523SLinus Walleij struct bt8xxgpio *bg = gpiochip_get_data(gpio);
132c103de24SGrant Likely unsigned long flags;
133c103de24SGrant Likely u32 data;
134c103de24SGrant Likely
135c103de24SGrant Likely spin_lock_irqsave(&bg->lock, flags);
136c103de24SGrant Likely
137c103de24SGrant Likely data = bgread(BT848_GPIO_DATA);
138c103de24SGrant Likely if (val)
139c103de24SGrant Likely data |= (1 << nr);
140c103de24SGrant Likely else
141c103de24SGrant Likely data &= ~(1 << nr);
142c103de24SGrant Likely bgwrite(data, BT848_GPIO_DATA);
143c103de24SGrant Likely
144c103de24SGrant Likely spin_unlock_irqrestore(&bg->lock, flags);
145c103de24SGrant Likely }
146c103de24SGrant Likely
bt8xxgpio_gpio_setup(struct bt8xxgpio * bg)147c103de24SGrant Likely static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg)
148c103de24SGrant Likely {
149c103de24SGrant Likely struct gpio_chip *c = &bg->gpio;
150c103de24SGrant Likely
151c103de24SGrant Likely c->label = dev_name(&bg->pdev->dev);
152c103de24SGrant Likely c->owner = THIS_MODULE;
153c103de24SGrant Likely c->direction_input = bt8xxgpio_gpio_direction_input;
154c103de24SGrant Likely c->get = bt8xxgpio_gpio_get;
155c103de24SGrant Likely c->direction_output = bt8xxgpio_gpio_direction_output;
156c103de24SGrant Likely c->set = bt8xxgpio_gpio_set;
157c103de24SGrant Likely c->dbg_show = NULL;
158c103de24SGrant Likely c->base = modparam_gpiobase;
159c103de24SGrant Likely c->ngpio = BT8XXGPIO_NR_GPIOS;
1609fb1f39eSLinus Walleij c->can_sleep = false;
161c103de24SGrant Likely }
162c103de24SGrant Likely
bt8xxgpio_probe(struct pci_dev * dev,const struct pci_device_id * pci_id)163c103de24SGrant Likely static int bt8xxgpio_probe(struct pci_dev *dev,
164c103de24SGrant Likely const struct pci_device_id *pci_id)
165c103de24SGrant Likely {
166c103de24SGrant Likely struct bt8xxgpio *bg;
167c103de24SGrant Likely int err;
168c103de24SGrant Likely
169a435e180Sabdoulaye berthe bg = devm_kzalloc(&dev->dev, sizeof(struct bt8xxgpio), GFP_KERNEL);
170c103de24SGrant Likely if (!bg)
171c103de24SGrant Likely return -ENOMEM;
172c103de24SGrant Likely
173c103de24SGrant Likely bg->pdev = dev;
174c103de24SGrant Likely spin_lock_init(&bg->lock);
175c103de24SGrant Likely
176c103de24SGrant Likely err = pci_enable_device(dev);
177c103de24SGrant Likely if (err) {
178*3bf1d26cSEnrico Weigelt, metux IT consult dev_err(&dev->dev, "can't enable device.\n");
179a435e180Sabdoulaye berthe return err;
180c103de24SGrant Likely }
181a435e180Sabdoulaye berthe if (!devm_request_mem_region(&dev->dev, pci_resource_start(dev, 0),
182c103de24SGrant Likely pci_resource_len(dev, 0),
183c103de24SGrant Likely "bt8xxgpio")) {
184*3bf1d26cSEnrico Weigelt, metux IT consult dev_warn(&dev->dev, "can't request iomem (0x%llx).\n",
185c103de24SGrant Likely (unsigned long long)pci_resource_start(dev, 0));
186c103de24SGrant Likely err = -EBUSY;
187c103de24SGrant Likely goto err_disable;
188c103de24SGrant Likely }
189c103de24SGrant Likely pci_set_master(dev);
190c103de24SGrant Likely pci_set_drvdata(dev, bg);
191c103de24SGrant Likely
192a435e180Sabdoulaye berthe bg->mmio = devm_ioremap(&dev->dev, pci_resource_start(dev, 0), 0x1000);
193c103de24SGrant Likely if (!bg->mmio) {
194*3bf1d26cSEnrico Weigelt, metux IT consult dev_err(&dev->dev, "ioremap() failed\n");
195c103de24SGrant Likely err = -EIO;
196a435e180Sabdoulaye berthe goto err_disable;
197c103de24SGrant Likely }
198c103de24SGrant Likely
199c103de24SGrant Likely /* Disable interrupts */
200c103de24SGrant Likely bgwrite(0, BT848_INT_MASK);
201c103de24SGrant Likely
202c103de24SGrant Likely /* gpio init */
203c103de24SGrant Likely bgwrite(0, BT848_GPIO_DMA_CTL);
204c103de24SGrant Likely bgwrite(0, BT848_GPIO_REG_INP);
205c103de24SGrant Likely bgwrite(0, BT848_GPIO_OUT_EN);
206c103de24SGrant Likely
207c103de24SGrant Likely bt8xxgpio_gpio_setup(bg);
208e51b5523SLinus Walleij err = gpiochip_add_data(&bg->gpio, bg);
209c103de24SGrant Likely if (err) {
210*3bf1d26cSEnrico Weigelt, metux IT consult dev_err(&dev->dev, "failed to register GPIOs\n");
211a435e180Sabdoulaye berthe goto err_disable;
212c103de24SGrant Likely }
213c103de24SGrant Likely
214c103de24SGrant Likely return 0;
215c103de24SGrant Likely
216c103de24SGrant Likely err_disable:
217c103de24SGrant Likely pci_disable_device(dev);
218c103de24SGrant Likely
219c103de24SGrant Likely return err;
220c103de24SGrant Likely }
221c103de24SGrant Likely
bt8xxgpio_remove(struct pci_dev * pdev)222c103de24SGrant Likely static void bt8xxgpio_remove(struct pci_dev *pdev)
223c103de24SGrant Likely {
224c103de24SGrant Likely struct bt8xxgpio *bg = pci_get_drvdata(pdev);
225c103de24SGrant Likely
226c103de24SGrant Likely gpiochip_remove(&bg->gpio);
227c103de24SGrant Likely
228c103de24SGrant Likely bgwrite(0, BT848_INT_MASK);
229c103de24SGrant Likely bgwrite(~0x0, BT848_INT_STAT);
230c103de24SGrant Likely bgwrite(0x0, BT848_GPIO_OUT_EN);
231c103de24SGrant Likely
232c103de24SGrant Likely pci_disable_device(pdev);
233c103de24SGrant Likely }
234c103de24SGrant Likely
235c103de24SGrant Likely #ifdef CONFIG_PM
bt8xxgpio_suspend(struct pci_dev * pdev,pm_message_t state)236c103de24SGrant Likely static int bt8xxgpio_suspend(struct pci_dev *pdev, pm_message_t state)
237c103de24SGrant Likely {
238c103de24SGrant Likely struct bt8xxgpio *bg = pci_get_drvdata(pdev);
239c103de24SGrant Likely unsigned long flags;
240c103de24SGrant Likely
241c103de24SGrant Likely spin_lock_irqsave(&bg->lock, flags);
242c103de24SGrant Likely
243c103de24SGrant Likely bg->saved_outen = bgread(BT848_GPIO_OUT_EN);
244c103de24SGrant Likely bg->saved_data = bgread(BT848_GPIO_DATA);
245c103de24SGrant Likely
246c103de24SGrant Likely bgwrite(0, BT848_INT_MASK);
247c103de24SGrant Likely bgwrite(~0x0, BT848_INT_STAT);
248c103de24SGrant Likely bgwrite(0x0, BT848_GPIO_OUT_EN);
249c103de24SGrant Likely
250c103de24SGrant Likely spin_unlock_irqrestore(&bg->lock, flags);
251c103de24SGrant Likely
252c103de24SGrant Likely pci_save_state(pdev);
253c103de24SGrant Likely pci_disable_device(pdev);
254c103de24SGrant Likely pci_set_power_state(pdev, pci_choose_state(pdev, state));
255c103de24SGrant Likely
256c103de24SGrant Likely return 0;
257c103de24SGrant Likely }
258c103de24SGrant Likely
bt8xxgpio_resume(struct pci_dev * pdev)259c103de24SGrant Likely static int bt8xxgpio_resume(struct pci_dev *pdev)
260c103de24SGrant Likely {
261c103de24SGrant Likely struct bt8xxgpio *bg = pci_get_drvdata(pdev);
262c103de24SGrant Likely unsigned long flags;
263c103de24SGrant Likely int err;
264c103de24SGrant Likely
265038f0babSYijing Wang pci_set_power_state(pdev, PCI_D0);
266c103de24SGrant Likely err = pci_enable_device(pdev);
267c103de24SGrant Likely if (err)
268c103de24SGrant Likely return err;
269c103de24SGrant Likely pci_restore_state(pdev);
270c103de24SGrant Likely
271c103de24SGrant Likely spin_lock_irqsave(&bg->lock, flags);
272c103de24SGrant Likely
273c103de24SGrant Likely bgwrite(0, BT848_INT_MASK);
274c103de24SGrant Likely bgwrite(0, BT848_GPIO_DMA_CTL);
275c103de24SGrant Likely bgwrite(0, BT848_GPIO_REG_INP);
276c103de24SGrant Likely bgwrite(bg->saved_outen, BT848_GPIO_OUT_EN);
277c103de24SGrant Likely bgwrite(bg->saved_data & bg->saved_outen,
278c103de24SGrant Likely BT848_GPIO_DATA);
279c103de24SGrant Likely
280c103de24SGrant Likely spin_unlock_irqrestore(&bg->lock, flags);
281c103de24SGrant Likely
282c103de24SGrant Likely return 0;
283c103de24SGrant Likely }
284c103de24SGrant Likely #else
285c103de24SGrant Likely #define bt8xxgpio_suspend NULL
286c103de24SGrant Likely #define bt8xxgpio_resume NULL
287c103de24SGrant Likely #endif /* CONFIG_PM */
288c103de24SGrant Likely
28914f4a883SJingoo Han static const struct pci_device_id bt8xxgpio_pci_tbl[] = {
290c103de24SGrant Likely { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) },
291c103de24SGrant Likely { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) },
292c103de24SGrant Likely { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) },
293c103de24SGrant Likely { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879) },
294c103de24SGrant Likely { 0, },
295c103de24SGrant Likely };
296c103de24SGrant Likely MODULE_DEVICE_TABLE(pci, bt8xxgpio_pci_tbl);
297c103de24SGrant Likely
298c103de24SGrant Likely static struct pci_driver bt8xxgpio_pci_driver = {
299c103de24SGrant Likely .name = "bt8xxgpio",
300c103de24SGrant Likely .id_table = bt8xxgpio_pci_tbl,
301c103de24SGrant Likely .probe = bt8xxgpio_probe,
302c103de24SGrant Likely .remove = bt8xxgpio_remove,
303c103de24SGrant Likely .suspend = bt8xxgpio_suspend,
304c103de24SGrant Likely .resume = bt8xxgpio_resume,
305c103de24SGrant Likely };
306c103de24SGrant Likely
30793baa65fSAxel Lin module_pci_driver(bt8xxgpio_pci_driver);
308c103de24SGrant Likely
309c103de24SGrant Likely MODULE_LICENSE("GPL");
310c103de24SGrant Likely MODULE_AUTHOR("Michael Buesch");
311c103de24SGrant Likely MODULE_DESCRIPTION("Abuse a BT8xx framegrabber card as generic GPIO card");
312