cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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");