1 /* 2 * GPIO driver for TI TPS65912x PMICs 3 * 4 * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ 5 * Andrew F. Davis <afd@ti.com> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 * This program is distributed "as is" WITHOUT ANY WARRANTY of any 12 * kind, whether expressed or implied; without even the implied warranty 13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License version 2 for more details. 15 * 16 * Based on the Arizona GPIO driver and the previous TPS65912 driver by 17 * Margarita Olaya Cabrera <magi@slimlogic.co.uk> 18 */ 19 20 #include <linux/gpio.h> 21 #include <linux/module.h> 22 #include <linux/platform_device.h> 23 24 #include <linux/mfd/tps65912.h> 25 26 struct tps65912_gpio { 27 struct gpio_chip gpio_chip; 28 struct tps65912 *tps; 29 }; 30 31 static int tps65912_gpio_get_direction(struct gpio_chip *gc, 32 unsigned offset) 33 { 34 struct tps65912_gpio *gpio = gpiochip_get_data(gc); 35 36 int ret, val; 37 38 ret = regmap_read(gpio->tps->regmap, TPS65912_GPIO1 + offset, &val); 39 if (ret) 40 return ret; 41 42 if (val & GPIO_CFG_MASK) 43 return GPIOF_DIR_OUT; 44 else 45 return GPIOF_DIR_IN; 46 } 47 48 static int tps65912_gpio_direction_input(struct gpio_chip *gc, unsigned offset) 49 { 50 struct tps65912_gpio *gpio = gpiochip_get_data(gc); 51 52 return regmap_update_bits(gpio->tps->regmap, TPS65912_GPIO1 + offset, 53 GPIO_CFG_MASK, 0); 54 } 55 56 static int tps65912_gpio_direction_output(struct gpio_chip *gc, 57 unsigned offset, int value) 58 { 59 struct tps65912_gpio *gpio = gpiochip_get_data(gc); 60 61 /* Set the initial value */ 62 regmap_update_bits(gpio->tps->regmap, TPS65912_GPIO1 + offset, 63 GPIO_SET_MASK, value ? GPIO_SET_MASK : 0); 64 65 return regmap_update_bits(gpio->tps->regmap, TPS65912_GPIO1 + offset, 66 GPIO_CFG_MASK, GPIO_CFG_MASK); 67 } 68 69 static int tps65912_gpio_get(struct gpio_chip *gc, unsigned offset) 70 { 71 struct tps65912_gpio *gpio = gpiochip_get_data(gc); 72 int ret, val; 73 74 ret = regmap_read(gpio->tps->regmap, TPS65912_GPIO1 + offset, &val); 75 if (ret) 76 return ret; 77 78 if (val & GPIO_STS_MASK) 79 return 1; 80 81 return 0; 82 } 83 84 static void tps65912_gpio_set(struct gpio_chip *gc, unsigned offset, 85 int value) 86 { 87 struct tps65912_gpio *gpio = gpiochip_get_data(gc); 88 89 regmap_update_bits(gpio->tps->regmap, TPS65912_GPIO1 + offset, 90 GPIO_SET_MASK, value ? GPIO_SET_MASK : 0); 91 } 92 93 static const struct gpio_chip template_chip = { 94 .label = "tps65912-gpio", 95 .owner = THIS_MODULE, 96 .get_direction = tps65912_gpio_get_direction, 97 .direction_input = tps65912_gpio_direction_input, 98 .direction_output = tps65912_gpio_direction_output, 99 .get = tps65912_gpio_get, 100 .set = tps65912_gpio_set, 101 .base = -1, 102 .ngpio = 5, 103 .can_sleep = true, 104 }; 105 106 static int tps65912_gpio_probe(struct platform_device *pdev) 107 { 108 struct tps65912 *tps = dev_get_drvdata(pdev->dev.parent); 109 struct tps65912_gpio *gpio; 110 int ret; 111 112 gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); 113 if (!gpio) 114 return -ENOMEM; 115 116 gpio->tps = dev_get_drvdata(pdev->dev.parent); 117 gpio->gpio_chip = template_chip; 118 gpio->gpio_chip.parent = tps->dev; 119 120 ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gpio_chip, 121 gpio); 122 if (ret < 0) { 123 dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); 124 return ret; 125 } 126 127 platform_set_drvdata(pdev, gpio); 128 129 return 0; 130 } 131 132 static const struct platform_device_id tps65912_gpio_id_table[] = { 133 { "tps65912-gpio", }, 134 { /* sentinel */ } 135 }; 136 MODULE_DEVICE_TABLE(platform, tps65912_gpio_id_table); 137 138 static struct platform_driver tps65912_gpio_driver = { 139 .driver = { 140 .name = "tps65912-gpio", 141 }, 142 .probe = tps65912_gpio_probe, 143 .id_table = tps65912_gpio_id_table, 144 }; 145 module_platform_driver(tps65912_gpio_driver); 146 147 MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); 148 MODULE_DESCRIPTION("TPS65912 GPIO driver"); 149 MODULE_LICENSE("GPL v2"); 150