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(struct gpio_chip *chip, unsigned int offset) 30 { 31 struct lp87565_gpio *gpio = gpiochip_get_data(chip); 32 int ret, val; 33 34 ret = regmap_read(gpio->map, LP87565_REG_GPIO_IN, &val); 35 if (ret < 0) 36 return ret; 37 38 return !!(val & BIT(offset)); 39 } 40 41 static void lp87565_gpio_set(struct gpio_chip *chip, unsigned int offset, 42 int value) 43 { 44 struct lp87565_gpio *gpio = gpiochip_get_data(chip); 45 46 regmap_update_bits(gpio->map, LP87565_REG_GPIO_OUT, 47 BIT(offset), value ? BIT(offset) : 0); 48 } 49 50 static int lp87565_gpio_get_direction(struct gpio_chip *chip, 51 unsigned int offset) 52 { 53 struct lp87565_gpio *gpio = gpiochip_get_data(chip); 54 int ret, val; 55 56 ret = regmap_read(gpio->map, LP87565_REG_GPIO_CONFIG, &val); 57 if (ret < 0) 58 return ret; 59 60 return !(val & BIT(offset)); 61 } 62 63 static int lp87565_gpio_direction_input(struct gpio_chip *chip, 64 unsigned int offset) 65 { 66 struct lp87565_gpio *gpio = gpiochip_get_data(chip); 67 68 return regmap_update_bits(gpio->map, 69 LP87565_REG_GPIO_CONFIG, 70 BIT(offset), 0); 71 } 72 73 static int lp87565_gpio_direction_output(struct gpio_chip *chip, 74 unsigned int offset, int value) 75 { 76 struct lp87565_gpio *gpio = gpiochip_get_data(chip); 77 78 lp87565_gpio_set(chip, offset, value); 79 80 return regmap_update_bits(gpio->map, 81 LP87565_REG_GPIO_CONFIG, 82 BIT(offset), BIT(offset)); 83 } 84 85 static int lp87565_gpio_request(struct gpio_chip *gc, unsigned int offset) 86 { 87 struct lp87565_gpio *gpio = gpiochip_get_data(gc); 88 int ret; 89 90 switch (offset) { 91 case 0: 92 case 1: 93 case 2: 94 /* 95 * MUX can program the pin to be in EN1/2/3 pin mode 96 * Or GPIO1/2/3 mode. 97 * Setup the GPIO*_SEL MUX to GPIO mode 98 */ 99 ret = regmap_update_bits(gpio->map, 100 LP87565_REG_PIN_FUNCTION, 101 BIT(offset), BIT(offset)); 102 if (ret) 103 return ret; 104 105 break; 106 default: 107 return -EINVAL; 108 } 109 110 return 0; 111 } 112 113 static int lp87565_gpio_set_config(struct gpio_chip *gc, unsigned int offset, 114 unsigned long config) 115 { 116 struct lp87565_gpio *gpio = gpiochip_get_data(gc); 117 118 switch (pinconf_to_config_param(config)) { 119 case PIN_CONFIG_DRIVE_OPEN_DRAIN: 120 return regmap_update_bits(gpio->map, 121 LP87565_REG_GPIO_CONFIG, 122 BIT(offset + 123 __ffs(LP87565_GOIO1_OD)), 124 BIT(offset + 125 __ffs(LP87565_GOIO1_OD))); 126 case PIN_CONFIG_DRIVE_PUSH_PULL: 127 return regmap_update_bits(gpio->map, 128 LP87565_REG_GPIO_CONFIG, 129 BIT(offset + 130 __ffs(LP87565_GOIO1_OD)), 0); 131 default: 132 return -ENOTSUPP; 133 } 134 } 135 136 static const struct gpio_chip template_chip = { 137 .label = "lp87565-gpio", 138 .owner = THIS_MODULE, 139 .request = lp87565_gpio_request, 140 .get_direction = lp87565_gpio_get_direction, 141 .direction_input = lp87565_gpio_direction_input, 142 .direction_output = lp87565_gpio_direction_output, 143 .get = lp87565_gpio_get, 144 .set = lp87565_gpio_set, 145 .set_config = lp87565_gpio_set_config, 146 .base = -1, 147 .ngpio = 3, 148 .can_sleep = true, 149 }; 150 151 static int lp87565_gpio_probe(struct platform_device *pdev) 152 { 153 struct lp87565_gpio *gpio; 154 struct lp87565 *lp87565; 155 int ret; 156 157 gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); 158 if (!gpio) 159 return -ENOMEM; 160 161 lp87565 = dev_get_drvdata(pdev->dev.parent); 162 gpio->chip = template_chip; 163 gpio->chip.parent = lp87565->dev; 164 gpio->map = lp87565->regmap; 165 166 ret = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); 167 if (ret < 0) { 168 dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); 169 return ret; 170 } 171 172 return 0; 173 } 174 175 static const struct platform_device_id lp87565_gpio_id_table[] = { 176 { "lp87565-q1-gpio", }, 177 { /* sentinel */ } 178 }; 179 MODULE_DEVICE_TABLE(platform, lp87565_gpio_id_table); 180 181 static struct platform_driver lp87565_gpio_driver = { 182 .driver = { 183 .name = "lp87565-gpio", 184 }, 185 .probe = lp87565_gpio_probe, 186 .id_table = lp87565_gpio_id_table, 187 }; 188 module_platform_driver(lp87565_gpio_driver); 189 190 MODULE_AUTHOR("Keerthy <j-keerthy@ti.com>"); 191 MODULE_DESCRIPTION("LP87565 GPIO driver"); 192 MODULE_LICENSE("GPL v2"); 193