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