1 /* 2 * TI TPS6586x GPIO driver 3 * 4 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. 5 * Author: Laxman dewangan <ldewangan@nvidia.com> 6 * 7 * Based on tps6586x.c 8 * Copyright (c) 2010 CompuLab Ltd. 9 * Mike Rapoport <mike@compulab.co.il> 10 * 11 * This program is free software; you can redistribute it and/or modify it 12 * under the terms and conditions of the GNU General Public License, 13 * version 2, as published by the Free Software Foundation. 14 * 15 * This program is distributed in the hope it will be useful, but WITHOUT 16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 18 * more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program. If not, see <http://www.gnu.org/licenses/>. 22 */ 23 24 #include <linux/errno.h> 25 #include <linux/gpio.h> 26 #include <linux/kernel.h> 27 #include <linux/module.h> 28 #include <linux/mfd/tps6586x.h> 29 #include <linux/of_device.h> 30 #include <linux/platform_device.h> 31 32 /* GPIO control registers */ 33 #define TPS6586X_GPIOSET1 0x5d 34 #define TPS6586X_GPIOSET2 0x5e 35 36 struct tps6586x_gpio { 37 struct gpio_chip gpio_chip; 38 struct device *parent; 39 }; 40 41 static inline struct tps6586x_gpio *to_tps6586x_gpio(struct gpio_chip *chip) 42 { 43 return container_of(chip, struct tps6586x_gpio, gpio_chip); 44 } 45 46 static int tps6586x_gpio_get(struct gpio_chip *gc, unsigned offset) 47 { 48 struct tps6586x_gpio *tps6586x_gpio = to_tps6586x_gpio(gc); 49 uint8_t val; 50 int ret; 51 52 ret = tps6586x_read(tps6586x_gpio->parent, TPS6586X_GPIOSET2, &val); 53 if (ret) 54 return ret; 55 56 return !!(val & (1 << offset)); 57 } 58 59 static void tps6586x_gpio_set(struct gpio_chip *gc, unsigned offset, 60 int value) 61 { 62 struct tps6586x_gpio *tps6586x_gpio = to_tps6586x_gpio(gc); 63 64 tps6586x_update(tps6586x_gpio->parent, TPS6586X_GPIOSET2, 65 value << offset, 1 << offset); 66 } 67 68 static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset, 69 int value) 70 { 71 struct tps6586x_gpio *tps6586x_gpio = to_tps6586x_gpio(gc); 72 uint8_t val, mask; 73 74 tps6586x_gpio_set(gc, offset, value); 75 76 val = 0x1 << (offset * 2); 77 mask = 0x3 << (offset * 2); 78 79 return tps6586x_update(tps6586x_gpio->parent, TPS6586X_GPIOSET1, 80 val, mask); 81 } 82 83 static int __devinit tps6586x_gpio_probe(struct platform_device *pdev) 84 { 85 struct tps6586x_platform_data *pdata; 86 struct tps6586x_gpio *tps6586x_gpio; 87 int ret; 88 89 pdata = dev_get_platdata(pdev->dev.parent); 90 tps6586x_gpio = devm_kzalloc(&pdev->dev, 91 sizeof(*tps6586x_gpio), GFP_KERNEL); 92 if (!tps6586x_gpio) { 93 dev_err(&pdev->dev, "Could not allocate tps6586x_gpio\n"); 94 return -ENOMEM; 95 } 96 97 tps6586x_gpio->parent = pdev->dev.parent; 98 99 tps6586x_gpio->gpio_chip.owner = THIS_MODULE; 100 tps6586x_gpio->gpio_chip.label = pdev->name; 101 tps6586x_gpio->gpio_chip.dev = &pdev->dev; 102 tps6586x_gpio->gpio_chip.ngpio = 4; 103 tps6586x_gpio->gpio_chip.can_sleep = 1; 104 105 /* FIXME: add handling of GPIOs as dedicated inputs */ 106 tps6586x_gpio->gpio_chip.direction_output = tps6586x_gpio_output; 107 tps6586x_gpio->gpio_chip.set = tps6586x_gpio_set; 108 tps6586x_gpio->gpio_chip.get = tps6586x_gpio_get; 109 110 #ifdef CONFIG_OF_GPIO 111 tps6586x_gpio->gpio_chip.of_node = pdev->dev.parent->of_node; 112 #endif 113 if (pdata && pdata->gpio_base) 114 tps6586x_gpio->gpio_chip.base = pdata->gpio_base; 115 else 116 tps6586x_gpio->gpio_chip.base = -1; 117 118 ret = gpiochip_add(&tps6586x_gpio->gpio_chip); 119 if (ret < 0) { 120 dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); 121 return ret; 122 } 123 124 platform_set_drvdata(pdev, tps6586x_gpio); 125 126 return ret; 127 } 128 129 static int __devexit tps6586x_gpio_remove(struct platform_device *pdev) 130 { 131 struct tps6586x_gpio *tps6586x_gpio = platform_get_drvdata(pdev); 132 133 return gpiochip_remove(&tps6586x_gpio->gpio_chip); 134 } 135 136 static struct platform_driver tps6586x_gpio_driver = { 137 .driver.name = "tps6586x-gpio", 138 .driver.owner = THIS_MODULE, 139 .probe = tps6586x_gpio_probe, 140 .remove = __devexit_p(tps6586x_gpio_remove), 141 }; 142 143 static int __init tps6586x_gpio_init(void) 144 { 145 return platform_driver_register(&tps6586x_gpio_driver); 146 } 147 subsys_initcall(tps6586x_gpio_init); 148 149 static void __exit tps6586x_gpio_exit(void) 150 { 151 platform_driver_unregister(&tps6586x_gpio_driver); 152 } 153 module_exit(tps6586x_gpio_exit); 154 155 MODULE_ALIAS("platform:tps6586x-gpio"); 156 MODULE_DESCRIPTION("GPIO interface for TPS6586X PMIC"); 157 MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); 158 MODULE_LICENSE("GPL"); 159