xref: /linux/drivers/gpio/gpio-bt8xx.c (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
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 	void __iomem *mmio;
158 	int err;
159 
160 	mmio = devm_ioremap_resource(&dev->dev, pci_resource_n(dev, 0));
161 	if (IS_ERR(mmio))
162 		return PTR_ERR(mmio);
163 
164 	bg = devm_kzalloc(&dev->dev, sizeof(struct bt8xxgpio), GFP_KERNEL);
165 	if (!bg)
166 		return -ENOMEM;
167 
168 	bg->mmio = mmio;
169 	bg->pdev = dev;
170 	spin_lock_init(&bg->lock);
171 
172 	err = pci_enable_device(dev);
173 	if (err) {
174 		dev_err(&dev->dev, "can't enable device.\n");
175 		return err;
176 	}
177 	pci_set_master(dev);
178 	pci_set_drvdata(dev, bg);
179 
180 	/* Disable interrupts */
181 	bgwrite(0, BT848_INT_MASK);
182 
183 	/* gpio init */
184 	bgwrite(0, BT848_GPIO_DMA_CTL);
185 	bgwrite(0, BT848_GPIO_REG_INP);
186 	bgwrite(0, BT848_GPIO_OUT_EN);
187 
188 	bt8xxgpio_gpio_setup(bg);
189 	err = gpiochip_add_data(&bg->gpio, bg);
190 	if (err) {
191 		dev_err(&dev->dev, "failed to register GPIOs\n");
192 		goto err_disable;
193 	}
194 
195 	return 0;
196 
197 err_disable:
198 	pci_disable_device(dev);
199 
200 	return err;
201 }
202 
203 static void bt8xxgpio_remove(struct pci_dev *pdev)
204 {
205 	struct bt8xxgpio *bg = pci_get_drvdata(pdev);
206 
207 	gpiochip_remove(&bg->gpio);
208 
209 	bgwrite(0, BT848_INT_MASK);
210 	bgwrite(~0x0, BT848_INT_STAT);
211 	bgwrite(0x0, BT848_GPIO_OUT_EN);
212 
213 	pci_disable_device(pdev);
214 }
215 
216 
217 static int bt8xxgpio_suspend(struct device *dev)
218 {
219 	struct pci_dev *pdev = to_pci_dev(dev);
220 	struct bt8xxgpio *bg = pci_get_drvdata(pdev);
221 
222 	scoped_guard(spinlock_irqsave, &bg->lock) {
223 		bg->saved_outen = bgread(BT848_GPIO_OUT_EN);
224 		bg->saved_data = bgread(BT848_GPIO_DATA);
225 
226 		bgwrite(0, BT848_INT_MASK);
227 		bgwrite(~0x0, BT848_INT_STAT);
228 		bgwrite(0x0, BT848_GPIO_OUT_EN);
229 	}
230 
231 	return 0;
232 }
233 
234 static int bt8xxgpio_resume(struct device *dev)
235 {
236 	struct pci_dev *pdev = to_pci_dev(dev);
237 	struct bt8xxgpio *bg = pci_get_drvdata(pdev);
238 
239 	guard(spinlock_irqsave)(&bg->lock);
240 
241 	bgwrite(0, BT848_INT_MASK);
242 	bgwrite(0, BT848_GPIO_DMA_CTL);
243 	bgwrite(0, BT848_GPIO_REG_INP);
244 	bgwrite(bg->saved_outen, BT848_GPIO_OUT_EN);
245 	bgwrite(bg->saved_data & bg->saved_outen,
246 		BT848_GPIO_DATA);
247 
248 	return 0;
249 }
250 
251 static DEFINE_SIMPLE_DEV_PM_OPS(bt8xxgpio_pm_ops, bt8xxgpio_suspend, bt8xxgpio_resume);
252 
253 static const struct pci_device_id bt8xxgpio_pci_tbl[] = {
254 	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) },
255 	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) },
256 	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) },
257 	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879) },
258 	{ 0, },
259 };
260 MODULE_DEVICE_TABLE(pci, bt8xxgpio_pci_tbl);
261 
262 static struct pci_driver bt8xxgpio_pci_driver = {
263 	.name		= "bt8xxgpio",
264 	.id_table	= bt8xxgpio_pci_tbl,
265 	.probe		= bt8xxgpio_probe,
266 	.remove		= bt8xxgpio_remove,
267 	.driver.pm	= &bt8xxgpio_pm_ops,
268 };
269 
270 module_pci_driver(bt8xxgpio_pci_driver);
271 
272 MODULE_LICENSE("GPL");
273 MODULE_AUTHOR("Michael Buesch");
274 MODULE_DESCRIPTION("Abuse a BT8xx framegrabber card as generic GPIO card");
275