1 /* 2 * TI TPS6591x GPIO driver 3 * 4 * Copyright 2010 Texas Instruments Inc. 5 * 6 * Author: Graeme Gregory <gg@slimlogic.co.uk> 7 * Author: Jorge Eduardo Candelaria jedu@slimlogic.co.uk> 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the 11 * Free Software Foundation; either version 2 of the License, or (at your 12 * option) any later version. 13 * 14 */ 15 16 #include <linux/kernel.h> 17 #include <linux/module.h> 18 #include <linux/errno.h> 19 #include <linux/gpio.h> 20 #include <linux/i2c.h> 21 #include <linux/platform_device.h> 22 #include <linux/mfd/tps65910.h> 23 #include <linux/of_device.h> 24 25 struct tps65910_gpio { 26 struct gpio_chip gpio_chip; 27 struct tps65910 *tps65910; 28 }; 29 30 static inline struct tps65910_gpio *to_tps65910_gpio(struct gpio_chip *chip) 31 { 32 return container_of(chip, struct tps65910_gpio, gpio_chip); 33 } 34 35 static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset) 36 { 37 struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc); 38 struct tps65910 *tps65910 = tps65910_gpio->tps65910; 39 unsigned int val; 40 41 tps65910_reg_read(tps65910, TPS65910_GPIO0 + offset, &val); 42 43 if (val & GPIO_STS_MASK) 44 return 1; 45 46 return 0; 47 } 48 49 static void tps65910_gpio_set(struct gpio_chip *gc, unsigned offset, 50 int value) 51 { 52 struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc); 53 struct tps65910 *tps65910 = tps65910_gpio->tps65910; 54 55 if (value) 56 tps65910_reg_set_bits(tps65910, TPS65910_GPIO0 + offset, 57 GPIO_SET_MASK); 58 else 59 tps65910_reg_clear_bits(tps65910, TPS65910_GPIO0 + offset, 60 GPIO_SET_MASK); 61 } 62 63 static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset, 64 int value) 65 { 66 struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc); 67 struct tps65910 *tps65910 = tps65910_gpio->tps65910; 68 69 /* Set the initial value */ 70 tps65910_gpio_set(gc, offset, value); 71 72 return tps65910_reg_set_bits(tps65910, TPS65910_GPIO0 + offset, 73 GPIO_CFG_MASK); 74 } 75 76 static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset) 77 { 78 struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc); 79 struct tps65910 *tps65910 = tps65910_gpio->tps65910; 80 81 return tps65910_reg_clear_bits(tps65910, TPS65910_GPIO0 + offset, 82 GPIO_CFG_MASK); 83 } 84 85 #ifdef CONFIG_OF 86 static struct tps65910_board *tps65910_parse_dt_for_gpio(struct device *dev, 87 struct tps65910 *tps65910, int chip_ngpio) 88 { 89 struct tps65910_board *tps65910_board = tps65910->of_plat_data; 90 unsigned int prop_array[TPS6591X_MAX_NUM_GPIO]; 91 int ngpio = min(chip_ngpio, TPS6591X_MAX_NUM_GPIO); 92 int ret; 93 int idx; 94 95 tps65910_board->gpio_base = -1; 96 ret = of_property_read_u32_array(tps65910->dev->of_node, 97 "ti,en-gpio-sleep", prop_array, ngpio); 98 if (ret < 0) { 99 dev_dbg(dev, "ti,en-gpio-sleep not specified\n"); 100 return tps65910_board; 101 } 102 103 for (idx = 0; idx < ngpio; idx++) 104 tps65910_board->en_gpio_sleep[idx] = (prop_array[idx] != 0); 105 106 return tps65910_board; 107 } 108 #else 109 static struct tps65910_board *tps65910_parse_dt_for_gpio(struct device *dev, 110 struct tps65910 *tps65910, int chip_ngpio) 111 { 112 return NULL; 113 } 114 #endif 115 116 static int __devinit tps65910_gpio_probe(struct platform_device *pdev) 117 { 118 struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); 119 struct tps65910_board *pdata = dev_get_platdata(tps65910->dev); 120 struct tps65910_gpio *tps65910_gpio; 121 int ret; 122 int i; 123 124 tps65910_gpio = devm_kzalloc(&pdev->dev, 125 sizeof(*tps65910_gpio), GFP_KERNEL); 126 if (!tps65910_gpio) { 127 dev_err(&pdev->dev, "Could not allocate tps65910_gpio\n"); 128 return -ENOMEM; 129 } 130 131 tps65910_gpio->tps65910 = tps65910; 132 133 tps65910_gpio->gpio_chip.owner = THIS_MODULE; 134 tps65910_gpio->gpio_chip.label = tps65910->i2c_client->name; 135 136 switch(tps65910_chip_id(tps65910)) { 137 case TPS65910: 138 tps65910_gpio->gpio_chip.ngpio = TPS65910_NUM_GPIO; 139 break; 140 case TPS65911: 141 tps65910_gpio->gpio_chip.ngpio = TPS65911_NUM_GPIO; 142 break; 143 default: 144 return -EINVAL; 145 } 146 tps65910_gpio->gpio_chip.can_sleep = 1; 147 tps65910_gpio->gpio_chip.direction_input = tps65910_gpio_input; 148 tps65910_gpio->gpio_chip.direction_output = tps65910_gpio_output; 149 tps65910_gpio->gpio_chip.set = tps65910_gpio_set; 150 tps65910_gpio->gpio_chip.get = tps65910_gpio_get; 151 tps65910_gpio->gpio_chip.dev = &pdev->dev; 152 #ifdef CONFIG_OF_GPIO 153 tps65910_gpio->gpio_chip.of_node = tps65910->dev->of_node; 154 #endif 155 if (pdata && pdata->gpio_base) 156 tps65910_gpio->gpio_chip.base = pdata->gpio_base; 157 else 158 tps65910_gpio->gpio_chip.base = -1; 159 160 if (!pdata && tps65910->dev->of_node) 161 pdata = tps65910_parse_dt_for_gpio(&pdev->dev, tps65910, 162 tps65910_gpio->gpio_chip.ngpio); 163 164 if (!pdata) 165 goto skip_init; 166 167 /* Configure sleep control for gpios if provided */ 168 for (i = 0; i < tps65910_gpio->gpio_chip.ngpio; ++i) { 169 if (!pdata->en_gpio_sleep[i]) 170 continue; 171 172 ret = tps65910_reg_set_bits(tps65910, 173 TPS65910_GPIO0 + i, GPIO_SLEEP_MASK); 174 if (ret < 0) 175 dev_warn(tps65910->dev, 176 "GPIO Sleep setting failed with err %d\n", ret); 177 } 178 179 skip_init: 180 ret = gpiochip_add(&tps65910_gpio->gpio_chip); 181 if (ret < 0) { 182 dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); 183 return ret; 184 } 185 186 platform_set_drvdata(pdev, tps65910_gpio); 187 188 return ret; 189 } 190 191 static int __devexit tps65910_gpio_remove(struct platform_device *pdev) 192 { 193 struct tps65910_gpio *tps65910_gpio = platform_get_drvdata(pdev); 194 195 return gpiochip_remove(&tps65910_gpio->gpio_chip); 196 } 197 198 static struct platform_driver tps65910_gpio_driver = { 199 .driver.name = "tps65910-gpio", 200 .driver.owner = THIS_MODULE, 201 .probe = tps65910_gpio_probe, 202 .remove = __devexit_p(tps65910_gpio_remove), 203 }; 204 205 static int __init tps65910_gpio_init(void) 206 { 207 return platform_driver_register(&tps65910_gpio_driver); 208 } 209 subsys_initcall(tps65910_gpio_init); 210 211 static void __exit tps65910_gpio_exit(void) 212 { 213 platform_driver_unregister(&tps65910_gpio_driver); 214 } 215 module_exit(tps65910_gpio_exit); 216 217 MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>"); 218 MODULE_AUTHOR("Jorge Eduardo Candelaria jedu@slimlogic.co.uk>"); 219 MODULE_DESCRIPTION("GPIO interface for TPS65910/TPS6511 PMICs"); 220 MODULE_LICENSE("GPL v2"); 221 MODULE_ALIAS("platform:tps65910-gpio"); 222