Blame view
drivers/gpio/gpio-exar.c
5.34 KB
d2912cb15 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
6596e59e6 gpio: exar: add g... |
2 3 4 5 |
/* * GPIO driver for Exar XR17V35X chip * * Copyright (C) 2015 Sudip Mukherjee <sudip.mukherjee@codethink.co.uk> |
6596e59e6 gpio: exar: add g... |
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
*/ #include <linux/bitops.h> #include <linux/device.h> #include <linux/gpio/driver.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/platform_device.h> #define EXAR_OFFSET_MPIOLVL_LO 0x90 #define EXAR_OFFSET_MPIOSEL_LO 0x93 #define EXAR_OFFSET_MPIOLVL_HI 0x96 #define EXAR_OFFSET_MPIOSEL_HI 0x99 #define DRIVER_NAME "gpio_exar" static DEFINE_IDA(ida_index); struct exar_gpio_chip { struct gpio_chip gpio_chip; struct mutex lock; int index; void __iomem *regs; char name[20]; |
380b1e2f3 gpio-exar/8250-ex... |
31 |
unsigned int first_pin; |
6596e59e6 gpio: exar: add g... |
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
}; static void exar_update(struct gpio_chip *chip, unsigned int reg, int val, unsigned int offset) { struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip); int temp; mutex_lock(&exar_gpio->lock); temp = readb(exar_gpio->regs + reg); temp &= ~BIT(offset); if (val) temp |= BIT(offset); writeb(temp, exar_gpio->regs + reg); mutex_unlock(&exar_gpio->lock); } static int exar_set_direction(struct gpio_chip *chip, int direction, unsigned int offset) { |
380b1e2f3 gpio-exar/8250-ex... |
52 53 54 55 |
struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip); unsigned int addr = (offset + exar_gpio->first_pin) / 8 ? EXAR_OFFSET_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO; unsigned int bit = (offset + exar_gpio->first_pin) % 8; |
6596e59e6 gpio: exar: add g... |
56 |
|
380b1e2f3 gpio-exar/8250-ex... |
57 |
exar_update(chip, addr, direction, bit); |
6596e59e6 gpio: exar: add g... |
58 59 |
return 0; } |
6596e59e6 gpio: exar: add g... |
60 61 62 63 64 65 66 67 |
static int exar_get(struct gpio_chip *chip, unsigned int reg) { struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip); int value; mutex_lock(&exar_gpio->lock); value = readb(exar_gpio->regs + reg); mutex_unlock(&exar_gpio->lock); |
7f45a875d gpio: exar: Fix r... |
68 |
return value; |
6596e59e6 gpio: exar: add g... |
69 70 71 72 |
} static int exar_get_direction(struct gpio_chip *chip, unsigned int offset) { |
380b1e2f3 gpio-exar/8250-ex... |
73 74 75 76 |
struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip); unsigned int addr = (offset + exar_gpio->first_pin) / 8 ? EXAR_OFFSET_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO; unsigned int bit = (offset + exar_gpio->first_pin) % 8; |
6596e59e6 gpio: exar: add g... |
77 |
|
e42615ec2 gpio: Use new GPI... |
78 79 80 81 |
if (exar_get(chip, addr) & BIT(bit)) return GPIO_LINE_DIRECTION_IN; return GPIO_LINE_DIRECTION_OUT; |
6596e59e6 gpio: exar: add g... |
82 83 84 85 |
} static int exar_get_value(struct gpio_chip *chip, unsigned int offset) { |
380b1e2f3 gpio-exar/8250-ex... |
86 87 88 89 |
struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip); unsigned int addr = (offset + exar_gpio->first_pin) / 8 ? EXAR_OFFSET_MPIOLVL_HI : EXAR_OFFSET_MPIOLVL_LO; unsigned int bit = (offset + exar_gpio->first_pin) % 8; |
6596e59e6 gpio: exar: add g... |
90 |
|
380b1e2f3 gpio-exar/8250-ex... |
91 |
return !!(exar_get(chip, addr) & BIT(bit)); |
6596e59e6 gpio: exar: add g... |
92 93 94 95 96 |
} static void exar_set_value(struct gpio_chip *chip, unsigned int offset, int value) { |
380b1e2f3 gpio-exar/8250-ex... |
97 98 99 100 |
struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip); unsigned int addr = (offset + exar_gpio->first_pin) / 8 ? EXAR_OFFSET_MPIOLVL_HI : EXAR_OFFSET_MPIOLVL_LO; unsigned int bit = (offset + exar_gpio->first_pin) % 8; |
6596e59e6 gpio: exar: add g... |
101 |
|
380b1e2f3 gpio-exar/8250-ex... |
102 |
exar_update(chip, addr, value, bit); |
6596e59e6 gpio: exar: add g... |
103 |
} |
eddeae073 gpio: exar: Set p... |
104 105 106 107 108 109 110 111 112 113 114 |
static int exar_direction_output(struct gpio_chip *chip, unsigned int offset, int value) { exar_set_value(chip, offset, value); return exar_set_direction(chip, 0, offset); } static int exar_direction_input(struct gpio_chip *chip, unsigned int offset) { return exar_set_direction(chip, 1, offset); } |
6596e59e6 gpio: exar: add g... |
115 116 |
static int gpio_exar_probe(struct platform_device *pdev) { |
d3936d743 gpio-exar/8250-ex... |
117 |
struct pci_dev *pcidev = to_pci_dev(pdev->dev.parent); |
6596e59e6 gpio: exar: add g... |
118 |
struct exar_gpio_chip *exar_gpio; |
380b1e2f3 gpio-exar/8250-ex... |
119 |
u32 first_pin, ngpios; |
6596e59e6 gpio: exar: add g... |
120 121 |
void __iomem *p; int index, ret; |
6596e59e6 gpio: exar: add g... |
122 |
/* |
8847f5f9e gpio: exar: Fix i... |
123 124 |
* The UART driver must have mapped region 0 prior to registering this * device - use it. |
6596e59e6 gpio: exar: add g... |
125 |
*/ |
8847f5f9e gpio: exar: Fix i... |
126 |
p = pcim_iomap_table(pcidev)[0]; |
6596e59e6 gpio: exar: add g... |
127 128 |
if (!p) return -ENOMEM; |
a589e211b gpio: exar: Use c... |
129 |
ret = device_property_read_u32(&pdev->dev, "exar,first-pin", |
380b1e2f3 gpio-exar/8250-ex... |
130 131 132 133 134 135 136 |
&first_pin); if (ret) return ret; ret = device_property_read_u32(&pdev->dev, "ngpios", &ngpios); if (ret) return ret; |
5dab5872e gpio: exar: Alloc... |
137 |
exar_gpio = devm_kzalloc(&pdev->dev, sizeof(*exar_gpio), GFP_KERNEL); |
6596e59e6 gpio: exar: add g... |
138 139 140 141 142 143 |
if (!exar_gpio) return -ENOMEM; mutex_init(&exar_gpio->lock); index = ida_simple_get(&ida_index, 0, 0, GFP_KERNEL); |
333830aa1 gpio: exar: Fix b... |
144 145 146 147 |
if (index < 0) { ret = index; goto err_mutex_destroy; } |
6596e59e6 gpio: exar: add g... |
148 149 150 |
sprintf(exar_gpio->name, "exar_gpio%d", index); exar_gpio->gpio_chip.label = exar_gpio->name; |
4076cf08a gpio-exar/8250-ex... |
151 |
exar_gpio->gpio_chip.parent = &pdev->dev; |
6596e59e6 gpio: exar: add g... |
152 153 154 155 156 157 |
exar_gpio->gpio_chip.direction_output = exar_direction_output; exar_gpio->gpio_chip.direction_input = exar_direction_input; exar_gpio->gpio_chip.get_direction = exar_get_direction; exar_gpio->gpio_chip.get = exar_get_value; exar_gpio->gpio_chip.set = exar_set_value; exar_gpio->gpio_chip.base = -1; |
380b1e2f3 gpio-exar/8250-ex... |
158 |
exar_gpio->gpio_chip.ngpio = ngpios; |
6596e59e6 gpio: exar: add g... |
159 160 |
exar_gpio->regs = p; exar_gpio->index = index; |
380b1e2f3 gpio-exar/8250-ex... |
161 |
exar_gpio->first_pin = first_pin; |
6596e59e6 gpio: exar: add g... |
162 |
|
5dab5872e gpio: exar: Alloc... |
163 |
ret = devm_gpiochip_add_data(&pdev->dev, |
6596e59e6 gpio: exar: add g... |
164 165 166 167 168 169 170 171 172 173 |
&exar_gpio->gpio_chip, exar_gpio); if (ret) goto err_destroy; platform_set_drvdata(pdev, exar_gpio); return 0; err_destroy: ida_simple_remove(&ida_index, index); |
333830aa1 gpio: exar: Fix b... |
174 |
err_mutex_destroy: |
6596e59e6 gpio: exar: add g... |
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
mutex_destroy(&exar_gpio->lock); return ret; } static int gpio_exar_remove(struct platform_device *pdev) { struct exar_gpio_chip *exar_gpio = platform_get_drvdata(pdev); ida_simple_remove(&ida_index, exar_gpio->index); mutex_destroy(&exar_gpio->lock); return 0; } static struct platform_driver gpio_exar_driver = { .probe = gpio_exar_probe, .remove = gpio_exar_remove, .driver = { .name = DRIVER_NAME, }, }; module_platform_driver(gpio_exar_driver); MODULE_ALIAS("platform:" DRIVER_NAME); MODULE_DESCRIPTION("Exar GPIO driver"); MODULE_AUTHOR("Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>"); MODULE_LICENSE("GPL"); |