xref: /openbmc/linux/drivers/gpio/gpio-bt8xx.c (revision cdd38c5f1ce4398ec58fec95904b75824daab7b5)
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