gpio-bt8xx.c (7183B)
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 47struct 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 64static int modparam_gpiobase = -1/* dynamic */; 65module_param_named(gpiobase, modparam_gpiobase, int, 0444); 66MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the default."); 67 68 69static 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 90static 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 103static 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 128static 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 147static 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 163static 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 dev_err(&dev->dev, "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 dev_warn(&dev->dev, "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 dev_err(&dev->dev, "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 dev_err(&dev->dev, "failed to register GPIOs\n"); 211 goto err_disable; 212 } 213 214 return 0; 215 216err_disable: 217 pci_disable_device(dev); 218 219 return err; 220} 221 222static 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 236static 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 259static 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 289static 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}; 296MODULE_DEVICE_TABLE(pci, bt8xxgpio_pci_tbl); 297 298static 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 307module_pci_driver(bt8xxgpio_pci_driver); 308 309MODULE_LICENSE("GPL"); 310MODULE_AUTHOR("Michael Buesch"); 311MODULE_DESCRIPTION("Abuse a BT8xx framegrabber card as generic GPIO card");