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