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