diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2012-05-11 12:18:27 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-05-20 11:27:04 -0400 |
commit | 10bbc48d7a045c022a54f637c0c6b72f0e38b519 (patch) | |
tree | e01f9375a4c6c8be210bf3ccc5568d010a434799 /drivers/gpio | |
parent | aa4603a0a7663b10e645b32cc808aac00bc390a3 (diff) |
gpio: Convert tps65910 to a platform driver
Make the gpio-tps65910 as platform driver and register
this from tps65910 core driver as mfd sub device.
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpio-tps65910.c | 140 |
1 files changed, 102 insertions, 38 deletions
diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c index bc155f2509ba..af6dc837ffca 100644 --- a/drivers/gpio/gpio-tps65910.c +++ b/drivers/gpio/gpio-tps65910.c | |||
@@ -18,11 +18,23 @@ | |||
18 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
19 | #include <linux/gpio.h> | 19 | #include <linux/gpio.h> |
20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
21 | #include <linux/platform_device.h> | ||
21 | #include <linux/mfd/tps65910.h> | 22 | #include <linux/mfd/tps65910.h> |
22 | 23 | ||
24 | struct tps65910_gpio { | ||
25 | struct gpio_chip gpio_chip; | ||
26 | struct tps65910 *tps65910; | ||
27 | }; | ||
28 | |||
29 | static inline struct tps65910_gpio *to_tps65910_gpio(struct gpio_chip *chip) | ||
30 | { | ||
31 | return container_of(chip, struct tps65910_gpio, gpio_chip); | ||
32 | } | ||
33 | |||
23 | static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset) | 34 | static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset) |
24 | { | 35 | { |
25 | struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio); | 36 | struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc); |
37 | struct tps65910 *tps65910 = tps65910_gpio->tps65910; | ||
26 | unsigned int val; | 38 | unsigned int val; |
27 | 39 | ||
28 | tps65910_reg_read(tps65910, TPS65910_GPIO0 + offset, &val); | 40 | tps65910_reg_read(tps65910, TPS65910_GPIO0 + offset, &val); |
@@ -36,7 +48,8 @@ static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset) | |||
36 | static void tps65910_gpio_set(struct gpio_chip *gc, unsigned offset, | 48 | static void tps65910_gpio_set(struct gpio_chip *gc, unsigned offset, |
37 | int value) | 49 | int value) |
38 | { | 50 | { |
39 | struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio); | 51 | struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc); |
52 | struct tps65910 *tps65910 = tps65910_gpio->tps65910; | ||
40 | 53 | ||
41 | if (value) | 54 | if (value) |
42 | tps65910_reg_set_bits(tps65910, TPS65910_GPIO0 + offset, | 55 | tps65910_reg_set_bits(tps65910, TPS65910_GPIO0 + offset, |
@@ -49,7 +62,8 @@ static void tps65910_gpio_set(struct gpio_chip *gc, unsigned offset, | |||
49 | static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset, | 62 | static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset, |
50 | int value) | 63 | int value) |
51 | { | 64 | { |
52 | struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio); | 65 | struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc); |
66 | struct tps65910 *tps65910 = tps65910_gpio->tps65910; | ||
53 | 67 | ||
54 | /* Set the initial value */ | 68 | /* Set the initial value */ |
55 | tps65910_gpio_set(gc, offset, value); | 69 | tps65910_gpio_set(gc, offset, value); |
@@ -60,59 +74,109 @@ static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset, | |||
60 | 74 | ||
61 | static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset) | 75 | static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset) |
62 | { | 76 | { |
63 | struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio); | 77 | struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc); |
78 | struct tps65910 *tps65910 = tps65910_gpio->tps65910; | ||
64 | 79 | ||
65 | return tps65910_reg_clear_bits(tps65910, TPS65910_GPIO0 + offset, | 80 | return tps65910_reg_clear_bits(tps65910, TPS65910_GPIO0 + offset, |
66 | GPIO_CFG_MASK); | 81 | GPIO_CFG_MASK); |
67 | } | 82 | } |
68 | 83 | ||
69 | void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base) | 84 | static int __devinit tps65910_gpio_probe(struct platform_device *pdev) |
70 | { | 85 | { |
86 | 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; | ||
71 | int ret; | 89 | int ret; |
72 | struct tps65910_board *board_data; | 90 | int i; |
91 | |||
92 | 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 | } | ||
73 | 98 | ||
74 | if (!gpio_base) | 99 | tps65910_gpio->tps65910 = tps65910; |
75 | return; | ||
76 | 100 | ||
77 | tps65910->gpio.owner = THIS_MODULE; | 101 | tps65910_gpio->gpio_chip.owner = THIS_MODULE; |
78 | tps65910->gpio.label = tps65910->i2c_client->name; | 102 | tps65910_gpio->gpio_chip.label = tps65910->i2c_client->name; |
79 | tps65910->gpio.dev = tps65910->dev; | ||
80 | tps65910->gpio.base = gpio_base; | ||
81 | 103 | ||
82 | switch(tps65910_chip_id(tps65910)) { | 104 | switch(tps65910_chip_id(tps65910)) { |
83 | case TPS65910: | 105 | case TPS65910: |
84 | tps65910->gpio.ngpio = TPS65910_NUM_GPIO; | 106 | tps65910_gpio->gpio_chip.ngpio = TPS65910_NUM_GPIO; |
85 | break; | 107 | break; |
86 | case TPS65911: | 108 | case TPS65911: |
87 | tps65910->gpio.ngpio = TPS65911_NUM_GPIO; | 109 | tps65910_gpio->gpio_chip.ngpio = TPS65911_NUM_GPIO; |
88 | break; | 110 | break; |
89 | default: | 111 | default: |
90 | return; | 112 | return -EINVAL; |
91 | } | 113 | } |
92 | tps65910->gpio.can_sleep = 1; | 114 | tps65910_gpio->gpio_chip.can_sleep = 1; |
93 | 115 | tps65910_gpio->gpio_chip.direction_input = tps65910_gpio_input; | |
94 | tps65910->gpio.direction_input = tps65910_gpio_input; | 116 | tps65910_gpio->gpio_chip.direction_output = tps65910_gpio_output; |
95 | tps65910->gpio.direction_output = tps65910_gpio_output; | 117 | tps65910_gpio->gpio_chip.set = tps65910_gpio_set; |
96 | tps65910->gpio.set = tps65910_gpio_set; | 118 | tps65910_gpio->gpio_chip.get = tps65910_gpio_get; |
97 | tps65910->gpio.get = tps65910_gpio_get; | 119 | tps65910_gpio->gpio_chip.dev = &pdev->dev; |
98 | 120 | if (pdata && pdata->gpio_base) | |
99 | /* Configure sleep control for gpios */ | 121 | tps65910_gpio->gpio_chip.base = pdata->gpio_base; |
100 | board_data = dev_get_platdata(tps65910->dev); | 122 | else |
101 | if (board_data) { | 123 | tps65910_gpio->gpio_chip.base = -1; |
102 | int i; | 124 | |
103 | for (i = 0; i < tps65910->gpio.ngpio; ++i) { | 125 | if (!pdata) |
104 | if (board_data->en_gpio_sleep[i]) { | 126 | goto skip_init; |
105 | ret = tps65910_reg_set_bits(tps65910, | 127 | |
106 | TPS65910_GPIO0 + i, GPIO_SLEEP_MASK); | 128 | /* Configure sleep control for gpios if provided */ |
107 | if (ret < 0) | 129 | for (i = 0; i < tps65910_gpio->gpio_chip.ngpio; ++i) { |
108 | dev_warn(tps65910->dev, | 130 | if (!pdata->en_gpio_sleep[i]) |
109 | "GPIO Sleep setting failed\n"); | 131 | continue; |
110 | } | 132 | |
111 | } | 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); | ||
138 | } | ||
139 | |||
140 | skip_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; | ||
112 | } | 145 | } |
113 | 146 | ||
114 | ret = gpiochip_add(&tps65910->gpio); | 147 | platform_set_drvdata(pdev, tps65910_gpio); |
115 | 148 | ||
116 | if (ret) | 149 | return ret; |
117 | dev_warn(tps65910->dev, "GPIO registration failed: %d\n", ret); | ||
118 | } | 150 | } |
151 | |||
152 | static 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 | |||
159 | static 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 | |||
166 | static int __init tps65910_gpio_init(void) | ||
167 | { | ||
168 | return platform_driver_register(&tps65910_gpio_driver); | ||
169 | } | ||
170 | subsys_initcall(tps65910_gpio_init); | ||
171 | |||
172 | static void __exit tps65910_gpio_exit(void) | ||
173 | { | ||
174 | platform_driver_unregister(&tps65910_gpio_driver); | ||
175 | } | ||
176 | module_exit(tps65910_gpio_exit); | ||
177 | |||
178 | MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>"); | ||
179 | MODULE_AUTHOR("Jorge Eduardo Candelaria jedu@slimlogic.co.uk>"); | ||
180 | MODULE_DESCRIPTION("GPIO interface for TPS65910/TPS6511 PMICs"); | ||
181 | MODULE_LICENSE("GPL v2"); | ||
182 | MODULE_ALIAS("platform:tps65910-gpio"); | ||