blob: af6dc837ffcafa54d4e1eb50d86b31ac4b136433 [file] [log] [blame]
Graeme Gregory2537df72011-05-02 16:19:52 -05001/*
Grant Likelyc103de22011-06-04 18:38:28 -06002 * TI TPS6591x GPIO driver
Graeme Gregory2537df72011-05-02 16:19:52 -05003 *
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>
Laxman Dewangan10bbc482012-05-11 21:48:27 +053021#include <linux/platform_device.h>
Graeme Gregory2537df72011-05-02 16:19:52 -050022#include <linux/mfd/tps65910.h>
23
Laxman Dewangan10bbc482012-05-11 21:48:27 +053024struct tps65910_gpio {
25 struct gpio_chip gpio_chip;
26 struct tps65910 *tps65910;
27};
28
29static inline struct tps65910_gpio *to_tps65910_gpio(struct gpio_chip *chip)
30{
31 return container_of(chip, struct tps65910_gpio, gpio_chip);
32}
33
Graeme Gregory2537df72011-05-02 16:19:52 -050034static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset)
35{
Laxman Dewangan10bbc482012-05-11 21:48:27 +053036 struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc);
37 struct tps65910 *tps65910 = tps65910_gpio->tps65910;
Rhyland Klein3f7e8272012-05-08 11:42:38 -070038 unsigned int val;
Graeme Gregory2537df72011-05-02 16:19:52 -050039
Rhyland Klein3f7e8272012-05-08 11:42:38 -070040 tps65910_reg_read(tps65910, TPS65910_GPIO0 + offset, &val);
Graeme Gregory2537df72011-05-02 16:19:52 -050041
Jorge Eduardo Candelaria11ad14f82011-05-16 18:35:42 -050042 if (val & GPIO_STS_MASK)
Graeme Gregory2537df72011-05-02 16:19:52 -050043 return 1;
44
45 return 0;
46}
47
48static void tps65910_gpio_set(struct gpio_chip *gc, unsigned offset,
49 int value)
50{
Laxman Dewangan10bbc482012-05-11 21:48:27 +053051 struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc);
52 struct tps65910 *tps65910 = tps65910_gpio->tps65910;
Graeme Gregory2537df72011-05-02 16:19:52 -050053
54 if (value)
Rhyland Klein3f7e8272012-05-08 11:42:38 -070055 tps65910_reg_set_bits(tps65910, TPS65910_GPIO0 + offset,
Jorge Eduardo Candelaria11ad14f82011-05-16 18:35:42 -050056 GPIO_SET_MASK);
Graeme Gregory2537df72011-05-02 16:19:52 -050057 else
Rhyland Klein3f7e8272012-05-08 11:42:38 -070058 tps65910_reg_clear_bits(tps65910, TPS65910_GPIO0 + offset,
Jorge Eduardo Candelaria11ad14f82011-05-16 18:35:42 -050059 GPIO_SET_MASK);
Graeme Gregory2537df72011-05-02 16:19:52 -050060}
61
62static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset,
63 int value)
64{
Laxman Dewangan10bbc482012-05-11 21:48:27 +053065 struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc);
66 struct tps65910 *tps65910 = tps65910_gpio->tps65910;
Graeme Gregory2537df72011-05-02 16:19:52 -050067
68 /* Set the initial value */
Laxman Dewangan94bd2442012-01-18 20:07:35 +053069 tps65910_gpio_set(gc, offset, value);
Graeme Gregory2537df72011-05-02 16:19:52 -050070
Rhyland Klein3f7e8272012-05-08 11:42:38 -070071 return tps65910_reg_set_bits(tps65910, TPS65910_GPIO0 + offset,
Jorge Eduardo Candelaria11ad14f82011-05-16 18:35:42 -050072 GPIO_CFG_MASK);
Graeme Gregory2537df72011-05-02 16:19:52 -050073}
74
75static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset)
76{
Laxman Dewangan10bbc482012-05-11 21:48:27 +053077 struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc);
78 struct tps65910 *tps65910 = tps65910_gpio->tps65910;
Graeme Gregory2537df72011-05-02 16:19:52 -050079
Rhyland Klein3f7e8272012-05-08 11:42:38 -070080 return tps65910_reg_clear_bits(tps65910, TPS65910_GPIO0 + offset,
Jorge Eduardo Candelaria11ad14f82011-05-16 18:35:42 -050081 GPIO_CFG_MASK);
Graeme Gregory2537df72011-05-02 16:19:52 -050082}
83
Laxman Dewangan10bbc482012-05-11 21:48:27 +053084static int __devinit tps65910_gpio_probe(struct platform_device *pdev)
Graeme Gregory2537df72011-05-02 16:19:52 -050085{
Laxman Dewangan10bbc482012-05-11 21:48:27 +053086 struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
87 struct tps65910_board *pdata = dev_get_platdata(tps65910->dev);
88 struct tps65910_gpio *tps65910_gpio;
Graeme Gregory2537df72011-05-02 16:19:52 -050089 int ret;
Laxman Dewangan10bbc482012-05-11 21:48:27 +053090 int i;
Graeme Gregory2537df72011-05-02 16:19:52 -050091
Laxman Dewangan10bbc482012-05-11 21:48:27 +053092 tps65910_gpio = devm_kzalloc(&pdev->dev,
93 sizeof(*tps65910_gpio), GFP_KERNEL);
94 if (!tps65910_gpio) {
95 dev_err(&pdev->dev, "Could not allocate tps65910_gpio\n");
96 return -ENOMEM;
97 }
Graeme Gregory2537df72011-05-02 16:19:52 -050098
Laxman Dewangan10bbc482012-05-11 21:48:27 +053099 tps65910_gpio->tps65910 = tps65910;
100
101 tps65910_gpio->gpio_chip.owner = THIS_MODULE;
102 tps65910_gpio->gpio_chip.label = tps65910->i2c_client->name;
Jorge Eduardo Candelaria11ad14f82011-05-16 18:35:42 -0500103
104 switch(tps65910_chip_id(tps65910)) {
105 case TPS65910:
Laxman Dewangan10bbc482012-05-11 21:48:27 +0530106 tps65910_gpio->gpio_chip.ngpio = TPS65910_NUM_GPIO;
Axel Lin58956ba2011-07-06 10:08:27 +0800107 break;
Jorge Eduardo Candelaria11ad14f82011-05-16 18:35:42 -0500108 case TPS65911:
Laxman Dewangan10bbc482012-05-11 21:48:27 +0530109 tps65910_gpio->gpio_chip.ngpio = TPS65911_NUM_GPIO;
Axel Lin58956ba2011-07-06 10:08:27 +0800110 break;
Jorge Eduardo Candelaria11ad14f82011-05-16 18:35:42 -0500111 default:
Laxman Dewangan10bbc482012-05-11 21:48:27 +0530112 return -EINVAL;
Jorge Eduardo Candelaria11ad14f82011-05-16 18:35:42 -0500113 }
Laxman Dewangan10bbc482012-05-11 21:48:27 +0530114 tps65910_gpio->gpio_chip.can_sleep = 1;
115 tps65910_gpio->gpio_chip.direction_input = tps65910_gpio_input;
116 tps65910_gpio->gpio_chip.direction_output = tps65910_gpio_output;
117 tps65910_gpio->gpio_chip.set = tps65910_gpio_set;
118 tps65910_gpio->gpio_chip.get = tps65910_gpio_get;
119 tps65910_gpio->gpio_chip.dev = &pdev->dev;
120 if (pdata && pdata->gpio_base)
121 tps65910_gpio->gpio_chip.base = pdata->gpio_base;
122 else
123 tps65910_gpio->gpio_chip.base = -1;
Graeme Gregory2537df72011-05-02 16:19:52 -0500124
Laxman Dewangan10bbc482012-05-11 21:48:27 +0530125 if (!pdata)
126 goto skip_init;
Graeme Gregory2537df72011-05-02 16:19:52 -0500127
Laxman Dewangan10bbc482012-05-11 21:48:27 +0530128 /* Configure sleep control for gpios if provided */
129 for (i = 0; i < tps65910_gpio->gpio_chip.ngpio; ++i) {
130 if (!pdata->en_gpio_sleep[i])
131 continue;
132
133 ret = tps65910_reg_set_bits(tps65910,
134 TPS65910_GPIO0 + i, GPIO_SLEEP_MASK);
135 if (ret < 0)
136 dev_warn(tps65910->dev,
137 "GPIO Sleep setting failed with err %d\n", ret);
Laxman Dewangan9467d292012-02-01 12:09:04 +0530138 }
139
Laxman Dewangan10bbc482012-05-11 21:48:27 +0530140skip_init:
141 ret = gpiochip_add(&tps65910_gpio->gpio_chip);
142 if (ret < 0) {
143 dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
144 return ret;
145 }
Graeme Gregory2537df72011-05-02 16:19:52 -0500146
Laxman Dewangan10bbc482012-05-11 21:48:27 +0530147 platform_set_drvdata(pdev, tps65910_gpio);
148
149 return ret;
Graeme Gregory2537df72011-05-02 16:19:52 -0500150}
Laxman Dewangan10bbc482012-05-11 21:48:27 +0530151
152static int __devexit tps65910_gpio_remove(struct platform_device *pdev)
153{
154 struct tps65910_gpio *tps65910_gpio = platform_get_drvdata(pdev);
155
156 return gpiochip_remove(&tps65910_gpio->gpio_chip);
157}
158
159static struct platform_driver tps65910_gpio_driver = {
160 .driver.name = "tps65910-gpio",
161 .driver.owner = THIS_MODULE,
162 .probe = tps65910_gpio_probe,
163 .remove = __devexit_p(tps65910_gpio_remove),
164};
165
166static int __init tps65910_gpio_init(void)
167{
168 return platform_driver_register(&tps65910_gpio_driver);
169}
170subsys_initcall(tps65910_gpio_init);
171
172static void __exit tps65910_gpio_exit(void)
173{
174 platform_driver_unregister(&tps65910_gpio_driver);
175}
176module_exit(tps65910_gpio_exit);
177
178MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
179MODULE_AUTHOR("Jorge Eduardo Candelaria jedu@slimlogic.co.uk>");
180MODULE_DESCRIPTION("GPIO interface for TPS65910/TPS6511 PMICs");
181MODULE_LICENSE("GPL v2");
182MODULE_ALIAS("platform:tps65910-gpio");