diff options
| author | Sang-Heon Jeon <ekffu200098@gmail.com> | 2026-08-24 01:18:14 +0900 |
|---|---|---|
| committer | Julia Lawall <Julia.Lawall@inria.fr> | 2026-08-23 22:12:11 +0200 |
| commit | 2bd30b8dc75b823dd7bbef9d7bc68e1fd7ecee5c (patch) | |
| tree | dcc4da1d99f17541c5590ac63c77da4bf372a4ab /drivers/gpio/gpio-bt8xx.c | |
| download | linux-stable-2bd30b8dc75b823dd7bbef9d7bc68e1fd7ecee5c.tar.gz linux-stable-2bd30b8dc75b823dd7bbef9d7bc68e1fd7ecee5c.zip | |
coccinelle: alloc_cast: drop removed allocatorsgrafted
- pci_alloc_consistent() and pci_zalloc_consistent() were removed by
commit 7968778914e5
("PCI: Remove the deprecated "pci-dma-compat.h" API")
- kmem_alloc() was removed by commit f078d4ea8276
("xfs: convert kmem_alloc() to kmalloc()")
- kmem_zalloc() was removed by commit 10634530f7ba
("xfs: convert kmem_zalloc() to kzalloc()")
- kmem_zone_alloc() and kmem_zone_zalloc() were removed by commit
bae633a4a283 ("xfs: remove xfs_zone_{alloc,zalloc} helpers")
So drop them from the rules.
No functional change.
Signed-off-by: Sang-Heon Jeon <ekffu200098@gmail.com>
Signed-off-by: Julia Lawall <Julia.Lawall@inria.fr>
Diffstat (limited to 'drivers/gpio/gpio-bt8xx.c')
| -rw-r--r-- | drivers/gpio/gpio-bt8xx.c | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-bt8xx.c b/drivers/gpio/gpio-bt8xx.c new file mode 100644 index 000000000..f3a2321bc --- /dev/null +++ b/drivers/gpio/gpio-bt8xx.c @@ -0,0 +1,274 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + + bt8xx GPIO abuser + + Copyright (C) 2008 Michael Buesch <m@bues.ch> + + Please do _only_ contact the people listed _above_ with issues related to this driver. + All the other people listed below are not related to this driver. Their names + are only here, because this driver is derived from the bt848 driver. + + + Derived from the bt848 driver: + + Copyright (C) 1996,97,98 Ralph Metzler + & Marcus Metzler + (c) 1999-2002 Gerd Knorr + + some v4l2 code lines are taken from Justin's bttv2 driver which is + (c) 2000 Justin Schoeman + + V4L1 removal from: + (c) 2005-2006 Nickolay V. Shmyrev + + Fixes to be fully V4L2 compliant by + (c) 2006 Mauro Carvalho Chehab + + Cropping and overscan support + Copyright (C) 2005, 2006 Michael H. Schimek + Sponsored by OPQ Systems AB + +*/ + +#include <linux/cleanup.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/spinlock.h> +#include <linux/gpio/driver.h> +#include <linux/slab.h> + +/* Steal the hardware definitions from the bttv driver. */ +#include "../media/pci/bt8xx/bt848.h" + + +#define BT8XXGPIO_NR_GPIOS 24 /* We have 24 GPIO pins */ + + +struct bt8xxgpio { + spinlock_t lock; + + void __iomem *mmio; + struct pci_dev *pdev; + struct gpio_chip gpio; + + u32 saved_outen; + u32 saved_data; +}; + +#define bgwrite(dat, adr) writel((dat), bg->mmio+(adr)) +#define bgread(adr) readl(bg->mmio+(adr)) + + +static int modparam_gpiobase = -1/* dynamic */; +module_param_named(gpiobase, modparam_gpiobase, int, 0444); +MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the default."); + + +static int bt8xxgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) +{ + struct bt8xxgpio *bg = gpiochip_get_data(gpio); + u32 outen, data; + + guard(spinlock_irqsave)(&bg->lock); + + data = bgread(BT848_GPIO_DATA); + data &= ~(1 << nr); + bgwrite(data, BT848_GPIO_DATA); + + outen = bgread(BT848_GPIO_OUT_EN); + outen &= ~(1 << nr); + bgwrite(outen, BT848_GPIO_OUT_EN); + + return 0; +} + +static int bt8xxgpio_gpio_get(struct gpio_chip *gpio, unsigned nr) +{ + struct bt8xxgpio *bg = gpiochip_get_data(gpio); + u32 val; + + guard(spinlock_irqsave)(&bg->lock); + + val = bgread(BT848_GPIO_DATA); + + return !!(val & (1 << nr)); +} + +static int bt8xxgpio_gpio_direction_output(struct gpio_chip *gpio, + unsigned nr, int val) +{ + struct bt8xxgpio *bg = gpiochip_get_data(gpio); + u32 outen, data; + + guard(spinlock_irqsave)(&bg->lock); + + outen = bgread(BT848_GPIO_OUT_EN); + outen |= (1 << nr); + bgwrite(outen, BT848_GPIO_OUT_EN); + + data = bgread(BT848_GPIO_DATA); + if (val) + data |= (1 << nr); + else + data &= ~(1 << nr); + bgwrite(data, BT848_GPIO_DATA); + + return 0; +} + +static int bt8xxgpio_gpio_set(struct gpio_chip *gpio, unsigned int nr, int val) +{ + struct bt8xxgpio *bg = gpiochip_get_data(gpio); + u32 data; + + guard(spinlock_irqsave)(&bg->lock); + + data = bgread(BT848_GPIO_DATA); + if (val) + data |= (1 << nr); + else + data &= ~(1 << nr); + bgwrite(data, BT848_GPIO_DATA); + + return 0; +} + +static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg) +{ + struct gpio_chip *c = &bg->gpio; + + c->label = dev_name(&bg->pdev->dev); + c->owner = THIS_MODULE; + c->direction_input = bt8xxgpio_gpio_direction_input; + c->get = bt8xxgpio_gpio_get; + c->direction_output = bt8xxgpio_gpio_direction_output; + c->set = bt8xxgpio_gpio_set; + c->dbg_show = NULL; + c->base = modparam_gpiobase; + c->ngpio = BT8XXGPIO_NR_GPIOS; + c->can_sleep = false; +} + +static int bt8xxgpio_probe(struct pci_dev *dev, + const struct pci_device_id *pci_id) +{ + struct bt8xxgpio *bg; + void __iomem *mmio; + int err; + + mmio = devm_ioremap_resource(&dev->dev, pci_resource_n(dev, 0)); + if (IS_ERR(mmio)) + return PTR_ERR(mmio); + + bg = devm_kzalloc(&dev->dev, sizeof(struct bt8xxgpio), GFP_KERNEL); + if (!bg) + return -ENOMEM; + + bg->mmio = mmio; + bg->pdev = dev; + spin_lock_init(&bg->lock); + + err = pci_enable_device(dev); + if (err) { + dev_err(&dev->dev, "can't enable device.\n"); + return err; + } + pci_set_master(dev); + pci_set_drvdata(dev, bg); + + /* Disable interrupts */ + bgwrite(0, BT848_INT_MASK); + + /* gpio init */ + bgwrite(0, BT848_GPIO_DMA_CTL); + bgwrite(0, BT848_GPIO_REG_INP); + bgwrite(0, BT848_GPIO_OUT_EN); + + bt8xxgpio_gpio_setup(bg); + err = gpiochip_add_data(&bg->gpio, bg); + if (err) { + dev_err(&dev->dev, "failed to register GPIOs\n"); + goto err_disable; + } + + return 0; + +err_disable: + pci_disable_device(dev); + + return err; +} + +static void bt8xxgpio_remove(struct pci_dev *pdev) +{ + struct bt8xxgpio *bg = pci_get_drvdata(pdev); + + gpiochip_remove(&bg->gpio); + + bgwrite(0, BT848_INT_MASK); + bgwrite(~0x0, BT848_INT_STAT); + bgwrite(0x0, BT848_GPIO_OUT_EN); + + pci_disable_device(pdev); +} + + +static int bt8xxgpio_suspend(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct bt8xxgpio *bg = pci_get_drvdata(pdev); + + scoped_guard(spinlock_irqsave, &bg->lock) { + bg->saved_outen = bgread(BT848_GPIO_OUT_EN); + bg->saved_data = bgread(BT848_GPIO_DATA); + + bgwrite(0, BT848_INT_MASK); + bgwrite(~0x0, BT848_INT_STAT); + bgwrite(0x0, BT848_GPIO_OUT_EN); + } + + return 0; +} + +static int bt8xxgpio_resume(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct bt8xxgpio *bg = pci_get_drvdata(pdev); + + guard(spinlock_irqsave)(&bg->lock); + + bgwrite(0, BT848_INT_MASK); + bgwrite(0, BT848_GPIO_DMA_CTL); + bgwrite(0, BT848_GPIO_REG_INP); + bgwrite(bg->saved_outen, BT848_GPIO_OUT_EN); + bgwrite(bg->saved_data & bg->saved_outen, + BT848_GPIO_DATA); + + return 0; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(bt8xxgpio_pm_ops, bt8xxgpio_suspend, bt8xxgpio_resume); + +static const struct pci_device_id bt8xxgpio_pci_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879) }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, bt8xxgpio_pci_tbl); + +static struct pci_driver bt8xxgpio_pci_driver = { + .name = "bt8xxgpio", + .id_table = bt8xxgpio_pci_tbl, + .probe = bt8xxgpio_probe, + .remove = bt8xxgpio_remove, + .driver.pm = &bt8xxgpio_pm_ops, +}; + +module_pci_driver(bt8xxgpio_pci_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Michael Buesch"); +MODULE_DESCRIPTION("Abuse a BT8xx framegrabber card as generic GPIO card"); |
