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