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 tps6586x_gpio_to_irq(struct gpio_chip *gc, unsigned offset) 84 { 85 struct tps6586x_gpio *tps6586x_gpio = to_tps6586x_gpio(gc); 86 87 return tps6586x_irq_get_virq(tps6586x_gpio->parent, 88 TPS6586X_INT_PLDO_0 + offset); 89 } 90 91 static int tps6586x_gpio_probe(struct platform_device *pdev) 92 { 93 struct tps6586x_platform_data *pdata; 94 struct tps6586x_gpio *tps6586x_gpio; 95 int ret; 96 97 pdata = dev_get_platdata(pdev->dev.parent); 98 tps6586x_gpio = devm_kzalloc(&pdev->dev, 99 sizeof(*tps6586x_gpio), GFP_KERNEL); 100 if (!tps6586x_gpio) { 101 dev_err(&pdev->dev, "Could not allocate tps6586x_gpio\n"); 102 return -ENOMEM; 103 } 104 105 tps6586x_gpio->parent = pdev->dev.parent; 106 107 tps6586x_gpio->gpio_chip.owner = THIS_MODULE; 108 tps6586x_gpio->gpio_chip.label = pdev->name; 109 tps6586x_gpio->gpio_chip.dev = &pdev->dev; 110 tps6586x_gpio->gpio_chip.ngpio = 4; 111 tps6586x_gpio->gpio_chip.can_sleep = 1; 112 113 /* FIXME: add handling of GPIOs as dedicated inputs */ 114 tps6586x_gpio->gpio_chip.direction_output = tps6586x_gpio_output; 115 tps6586x_gpio->gpio_chip.set = tps6586x_gpio_set; 116 tps6586x_gpio->gpio_chip.get = tps6586x_gpio_get; 117 tps6586x_gpio->gpio_chip.to_irq = tps6586x_gpio_to_irq; 118 119 #ifdef CONFIG_OF_GPIO 120 tps6586x_gpio->gpio_chip.of_node = pdev->dev.parent->of_node; 121 #endif 122 if (pdata && pdata->gpio_base) 123 tps6586x_gpio->gpio_chip.base = pdata->gpio_base; 124 else 125 tps6586x_gpio->gpio_chip.base = -1; 126 127 ret = gpiochip_add(&tps6586x_gpio->gpio_chip); 128 if (ret < 0) { 129 dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); 130 return ret; 131 } 132 133 platform_set_drvdata(pdev, tps6586x_gpio); 134 135 return ret; 136 } 137 138 static int tps6586x_gpio_remove(struct platform_device *pdev) 139 { 140 struct tps6586x_gpio *tps6586x_gpio = platform_get_drvdata(pdev); 141 142 return gpiochip_remove(&tps6586x_gpio->gpio_chip); 143 } 144 145 static struct platform_driver tps6586x_gpio_driver = { 146 .driver.name = "tps6586x-gpio", 147 .driver.owner = THIS_MODULE, 148 .probe = tps6586x_gpio_probe, 149 .remove = tps6586x_gpio_remove, 150 }; 151 152 static int __init tps6586x_gpio_init(void) 153 { 154 return platform_driver_register(&tps6586x_gpio_driver); 155 } 156 subsys_initcall(tps6586x_gpio_init); 157 158 static void __exit tps6586x_gpio_exit(void) 159 { 160 platform_driver_unregister(&tps6586x_gpio_driver); 161 } 162 module_exit(tps6586x_gpio_exit); 163 164 MODULE_ALIAS("platform:tps6586x-gpio"); 165 MODULE_DESCRIPTION("GPIO interface for TPS6586X PMIC"); 166 MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); 167 MODULE_LICENSE("GPL"); 168