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-exar.c (5598B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * GPIO driver for Exar XR17V35X chip
      4 *
      5 * Copyright (C) 2015 Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>
      6 */
      7
      8#include <linux/bitops.h>
      9#include <linux/device.h>
     10#include <linux/gpio/driver.h>
     11#include <linux/idr.h>
     12#include <linux/init.h>
     13#include <linux/kernel.h>
     14#include <linux/module.h>
     15#include <linux/pci.h>
     16#include <linux/platform_device.h>
     17#include <linux/regmap.h>
     18
     19#define EXAR_OFFSET_MPIOLVL_LO 0x90
     20#define EXAR_OFFSET_MPIOSEL_LO 0x93
     21#define EXAR_OFFSET_MPIOLVL_HI 0x96
     22#define EXAR_OFFSET_MPIOSEL_HI 0x99
     23
     24#define DRIVER_NAME "gpio_exar"
     25
     26static DEFINE_IDA(ida_index);
     27
     28struct exar_gpio_chip {
     29	struct gpio_chip gpio_chip;
     30	struct regmap *regmap;
     31	int index;
     32	char name[20];
     33	unsigned int first_pin;
     34};
     35
     36static unsigned int
     37exar_offset_to_sel_addr(struct exar_gpio_chip *exar_gpio, unsigned int offset)
     38{
     39	return (offset + exar_gpio->first_pin) / 8 ? EXAR_OFFSET_MPIOSEL_HI
     40						   : EXAR_OFFSET_MPIOSEL_LO;
     41}
     42
     43static unsigned int
     44exar_offset_to_lvl_addr(struct exar_gpio_chip *exar_gpio, unsigned int offset)
     45{
     46	return (offset + exar_gpio->first_pin) / 8 ? EXAR_OFFSET_MPIOLVL_HI
     47						   : EXAR_OFFSET_MPIOLVL_LO;
     48}
     49
     50static unsigned int
     51exar_offset_to_bit(struct exar_gpio_chip *exar_gpio, unsigned int offset)
     52{
     53	return (offset + exar_gpio->first_pin) % 8;
     54}
     55
     56static int exar_get_direction(struct gpio_chip *chip, unsigned int offset)
     57{
     58	struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
     59	unsigned int addr = exar_offset_to_sel_addr(exar_gpio, offset);
     60	unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
     61
     62	if (regmap_test_bits(exar_gpio->regmap, addr, BIT(bit)))
     63		return GPIO_LINE_DIRECTION_IN;
     64
     65	return GPIO_LINE_DIRECTION_OUT;
     66}
     67
     68static int exar_get_value(struct gpio_chip *chip, unsigned int offset)
     69{
     70	struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
     71	unsigned int addr = exar_offset_to_lvl_addr(exar_gpio, offset);
     72	unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
     73
     74	return !!(regmap_test_bits(exar_gpio->regmap, addr, BIT(bit)));
     75}
     76
     77static void exar_set_value(struct gpio_chip *chip, unsigned int offset,
     78			   int value)
     79{
     80	struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
     81	unsigned int addr = exar_offset_to_lvl_addr(exar_gpio, offset);
     82	unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
     83
     84	if (value)
     85		regmap_set_bits(exar_gpio->regmap, addr, BIT(bit));
     86	else
     87		regmap_clear_bits(exar_gpio->regmap, addr, BIT(bit));
     88}
     89
     90static int exar_direction_output(struct gpio_chip *chip, unsigned int offset,
     91				 int value)
     92{
     93	struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
     94	unsigned int addr = exar_offset_to_sel_addr(exar_gpio, offset);
     95	unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
     96
     97	exar_set_value(chip, offset, value);
     98	regmap_clear_bits(exar_gpio->regmap, addr, BIT(bit));
     99
    100	return 0;
    101}
    102
    103static int exar_direction_input(struct gpio_chip *chip, unsigned int offset)
    104{
    105	struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
    106	unsigned int addr = exar_offset_to_sel_addr(exar_gpio, offset);
    107	unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
    108
    109	regmap_set_bits(exar_gpio->regmap, addr, BIT(bit));
    110
    111	return 0;
    112}
    113
    114static void exar_devm_ida_free(void *data)
    115{
    116	struct exar_gpio_chip *exar_gpio = data;
    117
    118	ida_free(&ida_index, exar_gpio->index);
    119}
    120
    121static const struct regmap_config exar_regmap_config = {
    122	.name		= "exar-gpio",
    123	.reg_bits	= 16,
    124	.val_bits	= 8,
    125};
    126
    127static int gpio_exar_probe(struct platform_device *pdev)
    128{
    129	struct device *dev = &pdev->dev;
    130	struct pci_dev *pcidev = to_pci_dev(dev->parent);
    131	struct exar_gpio_chip *exar_gpio;
    132	u32 first_pin, ngpios;
    133	void __iomem *p;
    134	int index, ret;
    135
    136	/*
    137	 * The UART driver must have mapped region 0 prior to registering this
    138	 * device - use it.
    139	 */
    140	p = pcim_iomap_table(pcidev)[0];
    141	if (!p)
    142		return -ENOMEM;
    143
    144	ret = device_property_read_u32(dev, "exar,first-pin", &first_pin);
    145	if (ret)
    146		return ret;
    147
    148	ret = device_property_read_u32(dev, "ngpios", &ngpios);
    149	if (ret)
    150		return ret;
    151
    152	exar_gpio = devm_kzalloc(dev, sizeof(*exar_gpio), GFP_KERNEL);
    153	if (!exar_gpio)
    154		return -ENOMEM;
    155
    156	/*
    157	 * We don't need to check the return values of mmio regmap operations (unless
    158	 * the regmap has a clock attached which is not the case here).
    159	 */
    160	exar_gpio->regmap = devm_regmap_init_mmio(dev, p, &exar_regmap_config);
    161	if (IS_ERR(exar_gpio->regmap))
    162		return PTR_ERR(exar_gpio->regmap);
    163
    164	index = ida_alloc(&ida_index, GFP_KERNEL);
    165	if (index < 0)
    166		return index;
    167
    168	ret = devm_add_action_or_reset(dev, exar_devm_ida_free, exar_gpio);
    169	if (ret)
    170		return ret;
    171
    172	sprintf(exar_gpio->name, "exar_gpio%d", index);
    173	exar_gpio->gpio_chip.label = exar_gpio->name;
    174	exar_gpio->gpio_chip.parent = dev;
    175	exar_gpio->gpio_chip.direction_output = exar_direction_output;
    176	exar_gpio->gpio_chip.direction_input = exar_direction_input;
    177	exar_gpio->gpio_chip.get_direction = exar_get_direction;
    178	exar_gpio->gpio_chip.get = exar_get_value;
    179	exar_gpio->gpio_chip.set = exar_set_value;
    180	exar_gpio->gpio_chip.base = -1;
    181	exar_gpio->gpio_chip.ngpio = ngpios;
    182	exar_gpio->index = index;
    183	exar_gpio->first_pin = first_pin;
    184
    185	ret = devm_gpiochip_add_data(dev, &exar_gpio->gpio_chip, exar_gpio);
    186	if (ret)
    187		return ret;
    188
    189	platform_set_drvdata(pdev, exar_gpio);
    190
    191	return 0;
    192}
    193
    194static struct platform_driver gpio_exar_driver = {
    195	.probe	= gpio_exar_probe,
    196	.driver	= {
    197		.name = DRIVER_NAME,
    198	},
    199};
    200
    201module_platform_driver(gpio_exar_driver);
    202
    203MODULE_ALIAS("platform:" DRIVER_NAME);
    204MODULE_DESCRIPTION("Exar GPIO driver");
    205MODULE_AUTHOR("Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>");
    206MODULE_LICENSE("GPL");