linux/drivers/gpio/bt8xxgpio.c
<<
>>
Prefs
   1/*
   2
   3    bt8xx GPIO abuser
   4
   5    Copyright (C) 2008 Michael Buesch <mb@bu3sch.de>
   6
   7    Please do _only_ contact the people listed _above_ with issues related to this driver.
   8    All the other people listed below are not related to this driver. Their names
   9    are only here, because this driver is derived from the bt848 driver.
  10
  11
  12    Derived from the bt848 driver:
  13
  14    Copyright (C) 1996,97,98 Ralph  Metzler
  15                           & Marcus Metzler
  16    (c) 1999-2002 Gerd Knorr
  17
  18    some v4l2 code lines are taken from Justin's bttv2 driver which is
  19    (c) 2000 Justin Schoeman
  20
  21    V4L1 removal from:
  22    (c) 2005-2006 Nickolay V. Shmyrev
  23
  24    Fixes to be fully V4L2 compliant by
  25    (c) 2006 Mauro Carvalho Chehab
  26
  27    Cropping and overscan support
  28    Copyright (C) 2005, 2006 Michael H. Schimek
  29    Sponsored by OPQ Systems AB
  30
  31    This program is free software; you can redistribute it and/or modify
  32    it under the terms of the GNU General Public License as published by
  33    the Free Software Foundation; either version 2 of the License, or
  34    (at your option) any later version.
  35
  36    This program is distributed in the hope that it will be useful,
  37    but WITHOUT ANY WARRANTY; without even the implied warranty of
  38    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  39    GNU General Public License for more details.
  40
  41    You should have received a copy of the GNU General Public License
  42    along with this program; if not, write to the Free Software
  43    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  44*/
  45
  46#include <linux/module.h>
  47#include <linux/pci.h>
  48#include <linux/spinlock.h>
  49#include <linux/gpio.h>
  50
  51/* Steal the hardware definitions from the bttv driver. */
  52#include "../media/video/bt8xx/bt848.h"
  53
  54
  55#define BT8XXGPIO_NR_GPIOS              24 /* We have 24 GPIO pins */
  56
  57
  58struct bt8xxgpio {
  59        spinlock_t lock;
  60
  61        void __iomem *mmio;
  62        struct pci_dev *pdev;
  63        struct gpio_chip gpio;
  64
  65#ifdef CONFIG_PM
  66        u32 saved_outen;
  67        u32 saved_data;
  68#endif
  69};
  70
  71#define bgwrite(dat, adr)       writel((dat), bg->mmio+(adr))
  72#define bgread(adr)             readl(bg->mmio+(adr))
  73
  74
  75static int modparam_gpiobase = -1/* dynamic */;
  76module_param_named(gpiobase, modparam_gpiobase, int, 0444);
  77MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the default.");
  78
  79
  80static int bt8xxgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
  81{
  82        struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
  83        unsigned long flags;
  84        u32 outen, data;
  85
  86        spin_lock_irqsave(&bg->lock, flags);
  87
  88        data = bgread(BT848_GPIO_DATA);
  89        data &= ~(1 << nr);
  90        bgwrite(data, BT848_GPIO_DATA);
  91
  92        outen = bgread(BT848_GPIO_OUT_EN);
  93        outen &= ~(1 << nr);
  94        bgwrite(outen, BT848_GPIO_OUT_EN);
  95
  96        spin_unlock_irqrestore(&bg->lock, flags);
  97
  98        return 0;
  99}
 100
 101static int bt8xxgpio_gpio_get(struct gpio_chip *gpio, unsigned nr)
 102{
 103        struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
 104        unsigned long flags;
 105        u32 val;
 106
 107        spin_lock_irqsave(&bg->lock, flags);
 108        val = bgread(BT848_GPIO_DATA);
 109        spin_unlock_irqrestore(&bg->lock, flags);
 110
 111        return !!(val & (1 << nr));
 112}
 113
 114static int bt8xxgpio_gpio_direction_output(struct gpio_chip *gpio,
 115                                        unsigned nr, int val)
 116{
 117        struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
 118        unsigned long flags;
 119        u32 outen, data;
 120
 121        spin_lock_irqsave(&bg->lock, flags);
 122
 123        outen = bgread(BT848_GPIO_OUT_EN);
 124        outen |= (1 << nr);
 125        bgwrite(outen, BT848_GPIO_OUT_EN);
 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        spin_unlock_irqrestore(&bg->lock, flags);
 135
 136        return 0;
 137}
 138
 139static void bt8xxgpio_gpio_set(struct gpio_chip *gpio,
 140                            unsigned nr, int val)
 141{
 142        struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
 143        unsigned long flags;
 144        u32 data;
 145
 146        spin_lock_irqsave(&bg->lock, flags);
 147
 148        data = bgread(BT848_GPIO_DATA);
 149        if (val)
 150                data |= (1 << nr);
 151        else
 152                data &= ~(1 << nr);
 153        bgwrite(data, BT848_GPIO_DATA);
 154
 155        spin_unlock_irqrestore(&bg->lock, flags);
 156}
 157
 158static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg)
 159{
 160        struct gpio_chip *c = &bg->gpio;
 161
 162        c->label = dev_name(&bg->pdev->dev);
 163        c->owner = THIS_MODULE;
 164        c->direction_input = bt8xxgpio_gpio_direction_input;
 165        c->get = bt8xxgpio_gpio_get;
 166        c->direction_output = bt8xxgpio_gpio_direction_output;
 167        c->set = bt8xxgpio_gpio_set;
 168        c->dbg_show = NULL;
 169        c->base = modparam_gpiobase;
 170        c->ngpio = BT8XXGPIO_NR_GPIOS;
 171        c->can_sleep = 0;
 172}
 173
 174static int bt8xxgpio_probe(struct pci_dev *dev,
 175                        const struct pci_device_id *pci_id)
 176{
 177        struct bt8xxgpio *bg;
 178        int err;
 179
 180        bg = kzalloc(sizeof(*bg), GFP_KERNEL);
 181        if (!bg)
 182                return -ENOMEM;
 183
 184        bg->pdev = dev;
 185        spin_lock_init(&bg->lock);
 186
 187        err = pci_enable_device(dev);
 188        if (err) {
 189                printk(KERN_ERR "bt8xxgpio: Can't enable device.\n");
 190                goto err_freebg;
 191        }
 192        if (!request_mem_region(pci_resource_start(dev, 0),
 193                                pci_resource_len(dev, 0),
 194                                "bt8xxgpio")) {
 195                printk(KERN_WARNING "bt8xxgpio: Can't request iomem (0x%llx).\n",
 196                       (unsigned long long)pci_resource_start(dev, 0));
 197                err = -EBUSY;
 198                goto err_disable;
 199        }
 200        pci_set_master(dev);
 201        pci_set_drvdata(dev, bg);
 202
 203        bg->mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
 204        if (!bg->mmio) {
 205                printk(KERN_ERR "bt8xxgpio: ioremap() failed\n");
 206                err = -EIO;
 207                goto err_release_mem;
 208        }
 209
 210        /* Disable interrupts */
 211        bgwrite(0, BT848_INT_MASK);
 212
 213        /* gpio init */
 214        bgwrite(0, BT848_GPIO_DMA_CTL);
 215        bgwrite(0, BT848_GPIO_REG_INP);
 216        bgwrite(0, BT848_GPIO_OUT_EN);
 217
 218        bt8xxgpio_gpio_setup(bg);
 219        err = gpiochip_add(&bg->gpio);
 220        if (err) {
 221                printk(KERN_ERR "bt8xxgpio: Failed to register GPIOs\n");
 222                goto err_release_mem;
 223        }
 224
 225        printk(KERN_INFO "bt8xxgpio: Abusing BT8xx card for GPIOs %d to %d\n",
 226               bg->gpio.base, bg->gpio.base + BT8XXGPIO_NR_GPIOS - 1);
 227
 228        return 0;
 229
 230err_release_mem:
 231        release_mem_region(pci_resource_start(dev, 0),
 232                           pci_resource_len(dev, 0));
 233        pci_set_drvdata(dev, NULL);
 234err_disable:
 235        pci_disable_device(dev);
 236err_freebg:
 237        kfree(bg);
 238
 239        return err;
 240}
 241
 242static void bt8xxgpio_remove(struct pci_dev *pdev)
 243{
 244        struct bt8xxgpio *bg = pci_get_drvdata(pdev);
 245
 246        gpiochip_remove(&bg->gpio);
 247
 248        bgwrite(0, BT848_INT_MASK);
 249        bgwrite(~0x0, BT848_INT_STAT);
 250        bgwrite(0x0, BT848_GPIO_OUT_EN);
 251
 252        iounmap(bg->mmio);
 253        release_mem_region(pci_resource_start(pdev, 0),
 254                           pci_resource_len(pdev, 0));
 255        pci_disable_device(pdev);
 256
 257        pci_set_drvdata(pdev, NULL);
 258        kfree(bg);
 259}
 260
 261#ifdef CONFIG_PM
 262static int bt8xxgpio_suspend(struct pci_dev *pdev, pm_message_t state)
 263{
 264        struct bt8xxgpio *bg = pci_get_drvdata(pdev);
 265        unsigned long flags;
 266
 267        spin_lock_irqsave(&bg->lock, flags);
 268
 269        bg->saved_outen = bgread(BT848_GPIO_OUT_EN);
 270        bg->saved_data = bgread(BT848_GPIO_DATA);
 271
 272        bgwrite(0, BT848_INT_MASK);
 273        bgwrite(~0x0, BT848_INT_STAT);
 274        bgwrite(0x0, BT848_GPIO_OUT_EN);
 275
 276        spin_unlock_irqrestore(&bg->lock, flags);
 277
 278        pci_save_state(pdev);
 279        pci_disable_device(pdev);
 280        pci_set_power_state(pdev, pci_choose_state(pdev, state));
 281
 282        return 0;
 283}
 284
 285static int bt8xxgpio_resume(struct pci_dev *pdev)
 286{
 287        struct bt8xxgpio *bg = pci_get_drvdata(pdev);
 288        unsigned long flags;
 289        int err;
 290
 291        pci_set_power_state(pdev, 0);
 292        err = pci_enable_device(pdev);
 293        if (err)
 294                return err;
 295        pci_restore_state(pdev);
 296
 297        spin_lock_irqsave(&bg->lock, flags);
 298
 299        bgwrite(0, BT848_INT_MASK);
 300        bgwrite(0, BT848_GPIO_DMA_CTL);
 301        bgwrite(0, BT848_GPIO_REG_INP);
 302        bgwrite(bg->saved_outen, BT848_GPIO_OUT_EN);
 303        bgwrite(bg->saved_data & bg->saved_outen,
 304                BT848_GPIO_DATA);
 305
 306        spin_unlock_irqrestore(&bg->lock, flags);
 307
 308        return 0;
 309}
 310#else
 311#define bt8xxgpio_suspend NULL
 312#define bt8xxgpio_resume NULL
 313#endif /* CONFIG_PM */
 314
 315static struct pci_device_id bt8xxgpio_pci_tbl[] = {
 316        { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) },
 317        { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) },
 318        { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) },
 319        { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879) },
 320        { 0, },
 321};
 322MODULE_DEVICE_TABLE(pci, bt8xxgpio_pci_tbl);
 323
 324static struct pci_driver bt8xxgpio_pci_driver = {
 325        .name           = "bt8xxgpio",
 326        .id_table       = bt8xxgpio_pci_tbl,
 327        .probe          = bt8xxgpio_probe,
 328        .remove         = bt8xxgpio_remove,
 329        .suspend        = bt8xxgpio_suspend,
 330        .resume         = bt8xxgpio_resume,
 331};
 332
 333static int __init bt8xxgpio_init(void)
 334{
 335        return pci_register_driver(&bt8xxgpio_pci_driver);
 336}
 337module_init(bt8xxgpio_init)
 338
 339static void __exit bt8xxgpio_exit(void)
 340{
 341        pci_unregister_driver(&bt8xxgpio_pci_driver);
 342}
 343module_exit(bt8xxgpio_exit)
 344
 345MODULE_LICENSE("GPL");
 346MODULE_AUTHOR("Michael Buesch");
 347MODULE_DESCRIPTION("Abuse a BT8xx framegrabber card as generic GPIO card");
 348