1 /* 2 * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ 3 * Andrew F. Davis <afd@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 TPS65912 driver 15 */ 16 17 #include <linux/gpio.h> 18 #include <linux/module.h> 19 #include <linux/platform_device.h> 20 21 #include <linux/mfd/tps65086.h> 22 23 struct tps65086_gpio { 24 struct gpio_chip chip; 25 struct tps65086 *tps; 26 }; 27 28 static int tps65086_gpio_get_direction(struct gpio_chip *chip, 29 unsigned offset) 30 { 31 /* This device is output only */ 32 return 0; 33 } 34 35 static int tps65086_gpio_direction_input(struct gpio_chip *chip, 36 unsigned offset) 37 { 38 /* This device is output only */ 39 return -EINVAL; 40 } 41 42 static int tps65086_gpio_direction_output(struct gpio_chip *chip, 43 unsigned offset, int value) 44 { 45 struct tps65086_gpio *gpio = gpiochip_get_data(chip); 46 47 /* Set the initial value */ 48 regmap_update_bits(gpio->tps->regmap, TPS65086_GPOCTRL, 49 BIT(4 + offset), value ? BIT(4 + offset) : 0); 50 51 return 0; 52 } 53 54 static int tps65086_gpio_get(struct gpio_chip *chip, unsigned offset) 55 { 56 struct tps65086_gpio *gpio = gpiochip_get_data(chip); 57 int ret, val; 58 59 ret = regmap_read(gpio->tps->regmap, TPS65086_GPOCTRL, &val); 60 if (ret < 0) 61 return ret; 62 63 return val & BIT(4 + offset); 64 } 65 66 static void tps65086_gpio_set(struct gpio_chip *chip, unsigned offset, 67 int value) 68 { 69 struct tps65086_gpio *gpio = gpiochip_get_data(chip); 70 71 regmap_update_bits(gpio->tps->regmap, TPS65086_GPOCTRL, 72 BIT(4 + offset), value ? BIT(4 + offset) : 0); 73 } 74 75 static struct gpio_chip template_chip = { 76 .label = "tps65086-gpio", 77 .owner = THIS_MODULE, 78 .get_direction = tps65086_gpio_get_direction, 79 .direction_input = tps65086_gpio_direction_input, 80 .direction_output = tps65086_gpio_direction_output, 81 .get = tps65086_gpio_get, 82 .set = tps65086_gpio_set, 83 .base = -1, 84 .ngpio = 4, 85 .can_sleep = true, 86 }; 87 88 static int tps65086_gpio_probe(struct platform_device *pdev) 89 { 90 struct tps65086_gpio *gpio; 91 int ret; 92 93 gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); 94 if (!gpio) 95 return -ENOMEM; 96 97 platform_set_drvdata(pdev, gpio); 98 99 gpio->tps = dev_get_drvdata(pdev->dev.parent); 100 gpio->chip = template_chip; 101 gpio->chip.parent = gpio->tps->dev; 102 103 ret = gpiochip_add_data(&gpio->chip, gpio); 104 if (ret < 0) { 105 dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); 106 return ret; 107 } 108 109 return 0; 110 } 111 112 static int tps65086_gpio_remove(struct platform_device *pdev) 113 { 114 struct tps65086_gpio *gpio = platform_get_drvdata(pdev); 115 116 gpiochip_remove(&gpio->chip); 117 118 return 0; 119 } 120 121 static const struct platform_device_id tps65086_gpio_id_table[] = { 122 { "tps65086-gpio", }, 123 { /* sentinel */ } 124 }; 125 MODULE_DEVICE_TABLE(platform, tps65086_gpio_id_table); 126 127 static struct platform_driver tps65086_gpio_driver = { 128 .driver = { 129 .name = "tps65086-gpio", 130 }, 131 .probe = tps65086_gpio_probe, 132 .remove = tps65086_gpio_remove, 133 .id_table = tps65086_gpio_id_table, 134 }; 135 module_platform_driver(tps65086_gpio_driver); 136 137 MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); 138 MODULE_DESCRIPTION("TPS65086 GPIO driver"); 139 MODULE_LICENSE("GPL v2"); 140