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