Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio: lp87565: Add support for GPIO

Add driver for lp87565 PMIC family GPIOs. Three GPIOs are supported
and can be configured in Open-drain output or Push-pull output.

Signed-off-by: Keerthy <j-keerthy@ti.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Keerthy and committed by
Linus Walleij
5c7f2c76 edadced2

+201
+10
drivers/gpio/Kconfig
··· 954 954 This driver can also be built as a module. If so, the module will be 955 955 called gpio-lp873x. 956 956 957 + config GPIO_LP87565 958 + tristate "TI LP87565 GPIO" 959 + depends on MFD_TI_LP87565 960 + help 961 + This driver supports the GPIO on TI Lp873565 PMICs. 3 GPIOs are present 962 + on LP87565 PMICs. 963 + 964 + This driver can also be built as a module. If so, the module will be 965 + called gpio-lp87565. 966 + 957 967 config GPIO_MAX77620 958 968 tristate "GPIO support for PMIC MAX77620 and MAX20024" 959 969 depends on MFD_MAX77620
+1
drivers/gpio/Makefile
··· 66 66 obj-$(CONFIG_GPIO_LPC18XX) += gpio-lpc18xx.o 67 67 obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o 68 68 obj-$(CONFIG_GPIO_LP873X) += gpio-lp873x.o 69 + obj-$(CONFIG_GPIO_LP87565) += gpio-lp87565.o 69 70 obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o 70 71 obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o 71 72 obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o
+190
drivers/gpio/gpio-lp87565.c
··· 1 + /* 2 + * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ 3 + * Keerthy <j-keerthy@ti.com> 4 + * 5 + * This program is free software; you can redistribute it and/or 6 + * modify it under the terms of the GNU General Public License version 2 as 7 + * published by the Free Software Foundation. 8 + * 9 + * This program is distributed "as is" WITHOUT ANY WARRANTY of any 10 + * kind, whether expressed or implied; without even the implied warranty 11 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License version 2 for more details. 13 + * 14 + * Based on the LP873X driver 15 + */ 16 + 17 + #include <linux/gpio/driver.h> 18 + #include <linux/module.h> 19 + #include <linux/platform_device.h> 20 + #include <linux/regmap.h> 21 + 22 + #include <linux/mfd/lp87565.h> 23 + 24 + struct lp87565_gpio { 25 + struct gpio_chip chip; 26 + struct regmap *map; 27 + }; 28 + 29 + static int lp87565_gpio_get_direction(struct gpio_chip *chip, 30 + unsigned int offset) 31 + { 32 + struct lp87565_gpio *gpio = gpiochip_get_data(chip); 33 + int ret, val; 34 + 35 + ret = regmap_read(gpio->map, LP87565_REG_GPIO_CONFIG, &val); 36 + if (ret < 0) 37 + return ret; 38 + 39 + return !(val & BIT(offset)); 40 + } 41 + 42 + static int lp87565_gpio_direction_input(struct gpio_chip *chip, 43 + unsigned int offset) 44 + { 45 + struct lp87565_gpio *gpio = gpiochip_get_data(chip); 46 + 47 + return regmap_update_bits(gpio->map, 48 + LP87565_REG_GPIO_CONFIG, 49 + BIT(offset), 0); 50 + } 51 + 52 + static int lp87565_gpio_direction_output(struct gpio_chip *chip, 53 + unsigned int offset, int value) 54 + { 55 + struct lp87565_gpio *gpio = gpiochip_get_data(chip); 56 + 57 + return regmap_update_bits(gpio->map, 58 + LP87565_REG_GPIO_CONFIG, 59 + BIT(offset), !value ? BIT(offset) : 0); 60 + } 61 + 62 + static int lp87565_gpio_get(struct gpio_chip *chip, unsigned int offset) 63 + { 64 + struct lp87565_gpio *gpio = gpiochip_get_data(chip); 65 + int ret, val; 66 + 67 + ret = regmap_read(gpio->map, LP87565_REG_GPIO_IN, &val); 68 + if (ret < 0) 69 + return ret; 70 + 71 + return !!(val & BIT(offset)); 72 + } 73 + 74 + static void lp87565_gpio_set(struct gpio_chip *chip, unsigned int offset, 75 + int value) 76 + { 77 + struct lp87565_gpio *gpio = gpiochip_get_data(chip); 78 + 79 + regmap_update_bits(gpio->map, LP87565_REG_GPIO_OUT, 80 + BIT(offset), value ? BIT(offset) : 0); 81 + } 82 + 83 + static int lp87565_gpio_request(struct gpio_chip *gc, unsigned int offset) 84 + { 85 + struct lp87565_gpio *gpio = gpiochip_get_data(gc); 86 + int ret; 87 + 88 + switch (offset) { 89 + case 0: 90 + case 1: 91 + case 2: 92 + /* 93 + * MUX can program the pin to be in EN1/2/3 pin mode 94 + * Or GPIO1/2/3 mode. 95 + * Setup the GPIO*_SEL MUX to GPIO mode 96 + */ 97 + ret = regmap_update_bits(gpio->map, 98 + LP87565_REG_PIN_FUNCTION, 99 + BIT(offset), BIT(offset)); 100 + if (ret) 101 + return ret; 102 + 103 + break; 104 + default: 105 + return -EINVAL; 106 + } 107 + 108 + return 0; 109 + } 110 + 111 + static int lp87565_gpio_set_config(struct gpio_chip *gc, unsigned int offset, 112 + unsigned long config) 113 + { 114 + struct lp87565_gpio *gpio = gpiochip_get_data(gc); 115 + 116 + switch (pinconf_to_config_param(config)) { 117 + case PIN_CONFIG_DRIVE_OPEN_DRAIN: 118 + return regmap_update_bits(gpio->map, 119 + LP87565_REG_GPIO_CONFIG, 120 + BIT(offset + 121 + __ffs(LP87565_GOIO1_OD)), 122 + BIT(offset + 123 + __ffs(LP87565_GOIO1_OD))); 124 + case PIN_CONFIG_DRIVE_PUSH_PULL: 125 + return regmap_update_bits(gpio->map, 126 + LP87565_REG_GPIO_CONFIG, 127 + BIT(offset + 128 + __ffs(LP87565_GOIO1_OD)), 0); 129 + default: 130 + return -ENOTSUPP; 131 + } 132 + } 133 + 134 + static const struct gpio_chip template_chip = { 135 + .label = "lp87565-gpio", 136 + .owner = THIS_MODULE, 137 + .request = lp87565_gpio_request, 138 + .get_direction = lp87565_gpio_get_direction, 139 + .direction_input = lp87565_gpio_direction_input, 140 + .direction_output = lp87565_gpio_direction_output, 141 + .get = lp87565_gpio_get, 142 + .set = lp87565_gpio_set, 143 + .set_config = lp87565_gpio_set_config, 144 + .base = -1, 145 + .ngpio = 3, 146 + .can_sleep = true, 147 + }; 148 + 149 + static int lp87565_gpio_probe(struct platform_device *pdev) 150 + { 151 + struct lp87565_gpio *gpio; 152 + struct lp87565 *lp87565; 153 + int ret; 154 + 155 + gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); 156 + if (!gpio) 157 + return -ENOMEM; 158 + 159 + lp87565 = dev_get_drvdata(pdev->dev.parent); 160 + gpio->chip = template_chip; 161 + gpio->chip.parent = lp87565->dev; 162 + gpio->map = lp87565->regmap; 163 + 164 + ret = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); 165 + if (ret < 0) { 166 + dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); 167 + return ret; 168 + } 169 + 170 + return 0; 171 + } 172 + 173 + static const struct platform_device_id lp87565_gpio_id_table[] = { 174 + { "lp87565-q1-gpio", }, 175 + { /* sentinel */ } 176 + }; 177 + MODULE_DEVICE_TABLE(platform, lp87565_gpio_id_table); 178 + 179 + static struct platform_driver lp87565_gpio_driver = { 180 + .driver = { 181 + .name = "lp87565-gpio", 182 + }, 183 + .probe = lp87565_gpio_probe, 184 + .id_table = lp87565_gpio_id_table, 185 + }; 186 + module_platform_driver(lp87565_gpio_driver); 187 + 188 + MODULE_AUTHOR("Keerthy <j-keerthy@ti.com>"); 189 + MODULE_DESCRIPTION("LP87565 GPIO driver"); 190 + MODULE_LICENSE("GPL v2");