linux/drivers/gpio/gpio-bt8xx.c
<<
>>
Prefs
   1/*
   2
   3    bt8xx GPIO abuser
   4
   5    Copyright (C) 2008 Michael Buesch <m@bues.ch>
   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#include <linux/slab.h>
  51
  52/* Steal the hardware definitions from the bttv driver. */
  53#include "../media/pci/bt8xx/bt848.h"
  54
  55
  56#define BT8XXGPIO_NR_GPIOS              24 /* We have 24 GPIO pins */
  57
  58
  59struct bt8xxgpio {
  60        spinlock_t lock;
  61
  62        void __iomem *mmio;
  63        struct pci_dev *pdev;
  64        struct gpio_chip gpio;
  65
  66#ifdef CONFIG_PM
  67        u32 saved_outen;
  68        u32 saved_data;
  69#endif
  70};
  71
  72#define bgwrite(dat, adr)       writel((dat), bg->mmio+(adr))
  73#define bgread(adr)             readl(bg->mmio+(adr))
  74
  75
  76static int modparam_gpiobase = -1/* dynamic */;
  77module_param_named(gpiobase, modparam_gpiobase, int, 0444);
  78MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the default.");
  79
  80
  81static int bt8xxgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
  82{
  83        struct bt8xxgpio *bg = gpiochip_get_data(gpio);
  84        unsigned long flags;
  85        u32 outen, data;
  86
  87        spin_lock_irqsave(&bg->lock, flags);
  88
  89        data = bgread(BT848_GPIO_DATA);
  90        data &= ~(1 << nr);
  91        bgwrite(data, BT848_GPIO_DATA);
  92
  93        outen = bgread(BT848_GPIO_OUT_EN);
  94        outen &= ~(1 << nr);
  95        bgwrite(outen, BT848_GPIO_OUT_EN);
  96
  97        spin_unlock_irqrestore(&bg->lock, flags);
  98
  99        return 0;
 100}
 101
 102static int bt8xxgpio_gpio_get(struct gpio_chip *gpio, unsigned nr)
 103{
 104        struct bt8xxgpio *bg = gpiochip_get_data(gpio);
 105        unsigned long flags;
 106        u32 val;
 107
 108        spin_lock_irqsave(&bg->lock, flags);
 109        val = bgread(BT848_GPIO_DATA);
 110        spin_unlock_irqrestore(&bg->lock, flags);
 111
 112        return !!(val & (1 << nr));
 113}
 114
 115static int bt8xxgpio_gpio_direction_output(struct gpio_chip *gpio,
 116                                        unsigned nr, int val)
 117{
 118        struct bt8xxgpio *bg = gpiochip_get_data(gpio);
 119        unsigned long flags;
 120        u32 outen, data;
 121
 122        spin_lock_irqsave(&bg->lock, flags);
 123
 124        outen = bgread(BT848_GPIO_OUT_EN);
 125        outen |= (1 << nr);
 126        bgwrite(outen, BT848_GPIO_OUT_EN);
 127
 128        data = bgread(BT848_GPIO_DATA);
 129        if (val)
 130                data |= (1 << nr);
 131        else
 132                data &= ~(1 << nr);
 133        bgwrite(data, BT848_GPIO_DATA);
 134
 135        spin_unlock_irqrestore(&bg->lock, flags);
 136
 137        return 0;
 138}
 139
 140static void bt8xxgpio_gpio_set(struct gpio_chip *gpio,
 141                            unsigned nr, int val)
 142{
 143        struct bt8xxgpio *bg = gpiochip_get_data(gpio);
 144        unsigned long flags;
 145        u32 data;
 146
 147        spin_lock_irqsave(&bg->lock, flags);
 148
 149        data = bgread(BT848_GPIO_DATA);
 150        if (val)
 151                data |= (1 << nr);
 152        else
 153                data &= ~(1 << nr);
 154        bgwrite(data, BT848_GPIO_DATA);
 155
 156        spin_unlock_irqrestore(&bg->lock, flags);
 157}
 158
 159static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg)
 160{
 161        struct gpio_chip *c = &bg->gpio;
 162
 163        c->label = dev_name(&bg->pdev->dev);
 164        c->owner = THIS_MODULE;
 165        c->direction_input = bt8xxgpio_gpio_direction_input;
 166        c->get = bt8xxgpio_gpio_get;
 167        c->direction_output = bt8xxgpio_gpio_direction_output;
 168        c->set = bt8xxgpio_gpio_set;
 169        c->dbg_show = NULL;
 170        c->base = modparam_gpiobase;
 171        c->ngpio = BT8XXGPIO_NR_GPIOS;
 172        c->can_sleep = false;
 173}
 174
 175static int bt8xxgpio_probe(struct pci_dev *dev,
 176                        const struct pci_device_id *pci_id)
 177{
 178        struct bt8xxgpio *bg;
 179        int err;
 180
 181        bg = devm_kzalloc(&dev->dev, sizeof(struct bt8xxgpio), GFP_KERNEL);
 182        if (!bg)
 183                return -ENOMEM;
 184
 185        bg->pdev = dev;
 186        spin_lock_init(&bg->lock);
 187
 188        err = pci_enable_device(dev);
 189        if (err) {
 190                printk(KERN_ERR "bt8xxgpio: Can't enable device.\n");
 191                return err;
 192        }
 193        if (!devm_request_mem_region(&dev->dev, pci_resource_start(dev, 0),
 194                                pci_resource_len(dev, 0),
 195                                "bt8xxgpio")) {
 196                printk(KERN_WARNING "bt8xxgpio: Can't request iomem (0x%llx).\n",
 197                       (unsigned long long)pci_resource_start(dev, 0));
 198                err = -EBUSY;
 199                goto err_disable;
 200        }
 201        pci_set_master(dev);
 202        pci_set_drvdata(dev, bg);
 203
 204        bg->mmio = devm_ioremap(&dev->dev, pci_resource_start(dev, 0), 0x1000);
 205        if (!bg->mmio) {
 206                printk(KERN_ERR "bt8xxgpio: ioremap() failed\n");
 207                err = -EIO;
 208                goto err_disable;
 209        }
 210
 211        /* Disable interrupts */
 212        bgwrite(0, BT848_INT_MASK);
 213
 214        /* gpio init */
 215        bgwrite(0, BT848_GPIO_DMA_CTL);
 216        bgwrite(0, BT848_GPIO_REG_INP);
 217        bgwrite(0, BT848_GPIO_OUT_EN);
 218
 219        bt8xxgpio_gpio_setup(bg);
 220        err = gpiochip_add_data(&bg->gpio, bg);
 221        if (err) {
 222                printk(KERN_ERR "bt8xxgpio: Failed to register GPIOs\n");
 223                goto err_disable;
 224        }
 225
 226        return 0;
 227
 228err_disable:
 229        pci_disable_device(dev);
 230
 231        return err;
 232}
 233
 234static void bt8xxgpio_remove(struct pci_dev *pdev)
 235{
 236        struct bt8xxgpio *bg = pci_get_drvdata(pdev);
 237
 238        gpiochip_remove(&bg->gpio);
 239
 240        bgwrite(0, BT848_INT_MASK);
 241        bgwrite(~0x0, BT848_INT_STAT);
 242        bgwrite(0x0, BT848_GPIO_OUT_EN);
 243
 244        pci_disable_device(pdev);
 245}
 246
 247#ifdef CONFIG_PM
 248static int bt8xxgpio_suspend(struct pci_dev *pdev, pm_message_t state)
 249{
 250        struct bt8xxgpio *bg = pci_get_drvdata(pdev);
 251        unsigned long flags;
 252
 253        spin_lock_irqsave(&bg->lock, flags);
 254
 255        bg->saved_outen = bgread(BT848_GPIO_OUT_EN);
 256        bg->saved_data = bgread(BT848_GPIO_DATA);
 257
 258        bgwrite(0, BT848_INT_MASK);
 259        bgwrite(~0x0, BT848_INT_STAT);
 260        bgwrite(0x0, BT848_GPIO_OUT_EN);
 261
 262        spin_unlock_irqrestore(&bg->lock, flags);
 263
 264        pci_save_state(pdev);
 265        pci_disable_device(pdev);
 266        pci_set_power_state(pdev, pci_choose_state(pdev, state));
 267
 268        return 0;
 269}
 270
 271static int bt8xxgpio_resume(struct pci_dev *pdev)
 272{
 273        struct bt8xxgpio *bg = pci_get_drvdata(pdev);
 274        unsigned long flags;
 275        int err;
 276
 277        pci_set_power_state(pdev, PCI_D0);
 278        err = pci_enable_device(pdev);
 279        if (err)
 280                return err;
 281        pci_restore_state(pdev);
 282
 283        spin_lock_irqsave(&bg->lock, flags);
 284
 285        bgwrite(0, BT848_INT_MASK);
 286        bgwrite(0, BT848_GPIO_DMA_CTL);
 287        bgwrite(0, BT848_GPIO_REG_INP);
 288        bgwrite(bg->saved_outen, BT848_GPIO_OUT_EN);
 289        bgwrite(bg->saved_data & bg->saved_outen,
 290                BT848_GPIO_DATA);
 291
 292        spin_unlock_irqrestore(&bg->lock, flags);
 293
 294        return 0;
 295}
 296#else
 297#define bt8xxgpio_suspend NULL
 298#define bt8xxgpio_resume NULL
 299#endif /* CONFIG_PM */
 300
 301static const struct pci_device_id bt8xxgpio_pci_tbl[] = {
 302        { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) },
 303        { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) },
 304        { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) },
 305        { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879) },
 306        { 0, },
 307};
 308MODULE_DEVICE_TABLE(pci, bt8xxgpio_pci_tbl);
 309
 310static struct pci_driver bt8xxgpio_pci_driver = {
 311        .name           = "bt8xxgpio",
 312        .id_table       = bt8xxgpio_pci_tbl,
 313        .probe          = bt8xxgpio_probe,
 314        .remove         = bt8xxgpio_remove,
 315        .suspend        = bt8xxgpio_suspend,
 316        .resume         = bt8xxgpio_resume,
 317};
 318
 319module_pci_driver(bt8xxgpio_pci_driver);
 320
 321MODULE_LICENSE("GPL");
 322MODULE_AUTHOR("Michael Buesch");
 323MODULE_DESCRIPTION("Abuse a BT8xx framegrabber card as generic GPIO card");
 324