Commit | Line | Data |
---|---|---|
9e60fdcf | 1 | /* |
f5e8ff48 | 2 | * pca953x.c - 4/8/16 bit I/O ports |
9e60fdcf | 3 | * |
4 | * Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com> | |
5 | * Copyright (C) 2007 Marvell International Ltd. | |
6 | * | |
7 | * Derived from drivers/i2c/chips/pca9539.c | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License as published by | |
11 | * the Free Software Foundation; version 2 of the License. | |
12 | */ | |
13 | ||
14 | #include <linux/module.h> | |
15 | #include <linux/init.h> | |
d120c17f | 16 | #include <linux/gpio.h> |
9e60fdcf | 17 | #include <linux/i2c.h> |
d1c057e3 | 18 | #include <linux/i2c/pca953x.h> |
1965d303 NC |
19 | #ifdef CONFIG_OF_GPIO |
20 | #include <linux/of_platform.h> | |
21 | #include <linux/of_gpio.h> | |
22 | #endif | |
9e60fdcf | 23 | |
f5e8ff48 GL |
24 | #define PCA953X_INPUT 0 |
25 | #define PCA953X_OUTPUT 1 | |
26 | #define PCA953X_INVERT 2 | |
27 | #define PCA953X_DIRECTION 3 | |
9e60fdcf | 28 | |
3760f736 | 29 | static const struct i2c_device_id pca953x_id[] = { |
f5e8ff48 GL |
30 | { "pca9534", 8, }, |
31 | { "pca9535", 16, }, | |
32 | { "pca9536", 4, }, | |
33 | { "pca9537", 4, }, | |
34 | { "pca9538", 8, }, | |
35 | { "pca9539", 16, }, | |
69292b34 | 36 | { "pca9554", 8, }, |
f39e5781 | 37 | { "pca9555", 16, }, |
10dfb54c | 38 | { "pca9556", 8, }, |
f39e5781 | 39 | { "pca9557", 8, }, |
ab5dc372 | 40 | |
7059d4b0 | 41 | { "max7310", 8, }, |
61e0671c | 42 | { "max7315", 8, }, |
ab5dc372 DB |
43 | { "pca6107", 8, }, |
44 | { "tca6408", 8, }, | |
45 | { "tca6416", 16, }, | |
46 | /* NYET: { "tca6424", 24, }, */ | |
3760f736 | 47 | { } |
f5e8ff48 | 48 | }; |
3760f736 | 49 | MODULE_DEVICE_TABLE(i2c, pca953x_id); |
9e60fdcf | 50 | |
f3dc3630 | 51 | struct pca953x_chip { |
9e60fdcf | 52 | unsigned gpio_start; |
53 | uint16_t reg_output; | |
54 | uint16_t reg_direction; | |
55 | ||
56 | struct i2c_client *client; | |
1965d303 | 57 | struct pca953x_platform_data *dyn_pdata; |
9e60fdcf | 58 | struct gpio_chip gpio_chip; |
77906a54 | 59 | char **names; |
9e60fdcf | 60 | }; |
61 | ||
f3dc3630 | 62 | static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) |
9e60fdcf | 63 | { |
f5e8ff48 GL |
64 | int ret; |
65 | ||
66 | if (chip->gpio_chip.ngpio <= 8) | |
67 | ret = i2c_smbus_write_byte_data(chip->client, reg, val); | |
9e60fdcf | 68 | else |
f5e8ff48 GL |
69 | ret = i2c_smbus_write_word_data(chip->client, reg << 1, val); |
70 | ||
71 | if (ret < 0) { | |
72 | dev_err(&chip->client->dev, "failed writing register\n"); | |
ab5dc372 | 73 | return ret; |
f5e8ff48 GL |
74 | } |
75 | ||
76 | return 0; | |
9e60fdcf | 77 | } |
78 | ||
f3dc3630 | 79 | static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val) |
9e60fdcf | 80 | { |
81 | int ret; | |
82 | ||
f5e8ff48 GL |
83 | if (chip->gpio_chip.ngpio <= 8) |
84 | ret = i2c_smbus_read_byte_data(chip->client, reg); | |
85 | else | |
86 | ret = i2c_smbus_read_word_data(chip->client, reg << 1); | |
87 | ||
9e60fdcf | 88 | if (ret < 0) { |
89 | dev_err(&chip->client->dev, "failed reading register\n"); | |
ab5dc372 | 90 | return ret; |
9e60fdcf | 91 | } |
92 | ||
93 | *val = (uint16_t)ret; | |
94 | return 0; | |
95 | } | |
96 | ||
f3dc3630 | 97 | static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) |
9e60fdcf | 98 | { |
f3dc3630 | 99 | struct pca953x_chip *chip; |
9e60fdcf | 100 | uint16_t reg_val; |
101 | int ret; | |
102 | ||
f3dc3630 | 103 | chip = container_of(gc, struct pca953x_chip, gpio_chip); |
9e60fdcf | 104 | |
105 | reg_val = chip->reg_direction | (1u << off); | |
f3dc3630 | 106 | ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val); |
9e60fdcf | 107 | if (ret) |
108 | return ret; | |
109 | ||
110 | chip->reg_direction = reg_val; | |
111 | return 0; | |
112 | } | |
113 | ||
f3dc3630 | 114 | static int pca953x_gpio_direction_output(struct gpio_chip *gc, |
9e60fdcf | 115 | unsigned off, int val) |
116 | { | |
f3dc3630 | 117 | struct pca953x_chip *chip; |
9e60fdcf | 118 | uint16_t reg_val; |
119 | int ret; | |
120 | ||
f3dc3630 | 121 | chip = container_of(gc, struct pca953x_chip, gpio_chip); |
9e60fdcf | 122 | |
123 | /* set output level */ | |
124 | if (val) | |
125 | reg_val = chip->reg_output | (1u << off); | |
126 | else | |
127 | reg_val = chip->reg_output & ~(1u << off); | |
128 | ||
f3dc3630 | 129 | ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val); |
9e60fdcf | 130 | if (ret) |
131 | return ret; | |
132 | ||
133 | chip->reg_output = reg_val; | |
134 | ||
135 | /* then direction */ | |
136 | reg_val = chip->reg_direction & ~(1u << off); | |
f3dc3630 | 137 | ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val); |
9e60fdcf | 138 | if (ret) |
139 | return ret; | |
140 | ||
141 | chip->reg_direction = reg_val; | |
142 | return 0; | |
143 | } | |
144 | ||
f3dc3630 | 145 | static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) |
9e60fdcf | 146 | { |
f3dc3630 | 147 | struct pca953x_chip *chip; |
9e60fdcf | 148 | uint16_t reg_val; |
149 | int ret; | |
150 | ||
f3dc3630 | 151 | chip = container_of(gc, struct pca953x_chip, gpio_chip); |
9e60fdcf | 152 | |
f3dc3630 | 153 | ret = pca953x_read_reg(chip, PCA953X_INPUT, ®_val); |
9e60fdcf | 154 | if (ret < 0) { |
155 | /* NOTE: diagnostic already emitted; that's all we should | |
156 | * do unless gpio_*_value_cansleep() calls become different | |
157 | * from their nonsleeping siblings (and report faults). | |
158 | */ | |
159 | return 0; | |
160 | } | |
161 | ||
162 | return (reg_val & (1u << off)) ? 1 : 0; | |
163 | } | |
164 | ||
f3dc3630 | 165 | static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) |
9e60fdcf | 166 | { |
f3dc3630 | 167 | struct pca953x_chip *chip; |
9e60fdcf | 168 | uint16_t reg_val; |
169 | int ret; | |
170 | ||
f3dc3630 | 171 | chip = container_of(gc, struct pca953x_chip, gpio_chip); |
9e60fdcf | 172 | |
173 | if (val) | |
174 | reg_val = chip->reg_output | (1u << off); | |
175 | else | |
176 | reg_val = chip->reg_output & ~(1u << off); | |
177 | ||
f3dc3630 | 178 | ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val); |
9e60fdcf | 179 | if (ret) |
180 | return; | |
181 | ||
182 | chip->reg_output = reg_val; | |
183 | } | |
184 | ||
f5e8ff48 | 185 | static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) |
9e60fdcf | 186 | { |
187 | struct gpio_chip *gc; | |
188 | ||
189 | gc = &chip->gpio_chip; | |
190 | ||
f3dc3630 GL |
191 | gc->direction_input = pca953x_gpio_direction_input; |
192 | gc->direction_output = pca953x_gpio_direction_output; | |
193 | gc->get = pca953x_gpio_get_value; | |
194 | gc->set = pca953x_gpio_set_value; | |
84207805 | 195 | gc->can_sleep = 1; |
9e60fdcf | 196 | |
197 | gc->base = chip->gpio_start; | |
f5e8ff48 GL |
198 | gc->ngpio = gpios; |
199 | gc->label = chip->client->name; | |
d8f388d8 | 200 | gc->dev = &chip->client->dev; |
d72cbed0 | 201 | gc->owner = THIS_MODULE; |
77906a54 | 202 | gc->names = chip->names; |
9e60fdcf | 203 | } |
204 | ||
1965d303 NC |
205 | /* |
206 | * Handlers for alternative sources of platform_data | |
207 | */ | |
208 | #ifdef CONFIG_OF_GPIO | |
209 | /* | |
210 | * Translate OpenFirmware node properties into platform_data | |
211 | */ | |
212 | static struct pca953x_platform_data * | |
213 | pca953x_get_alt_pdata(struct i2c_client *client) | |
214 | { | |
215 | struct pca953x_platform_data *pdata; | |
216 | struct device_node *node; | |
217 | const uint16_t *val; | |
218 | ||
219 | node = dev_archdata_get_node(&client->dev.archdata); | |
220 | if (node == NULL) | |
221 | return NULL; | |
222 | ||
223 | pdata = kzalloc(sizeof(struct pca953x_platform_data), GFP_KERNEL); | |
224 | if (pdata == NULL) { | |
225 | dev_err(&client->dev, "Unable to allocate platform_data\n"); | |
226 | return NULL; | |
227 | } | |
228 | ||
229 | pdata->gpio_base = -1; | |
230 | val = of_get_property(node, "linux,gpio-base", NULL); | |
231 | if (val) { | |
232 | if (*val < 0) | |
233 | dev_warn(&client->dev, | |
234 | "invalid gpio-base in device tree\n"); | |
235 | else | |
236 | pdata->gpio_base = *val; | |
237 | } | |
238 | ||
239 | val = of_get_property(node, "polarity", NULL); | |
240 | if (val) | |
241 | pdata->invert = *val; | |
242 | ||
243 | return pdata; | |
244 | } | |
245 | #else | |
246 | static struct pca953x_platform_data * | |
247 | pca953x_get_alt_pdata(struct i2c_client *client) | |
248 | { | |
249 | return NULL; | |
250 | } | |
251 | #endif | |
252 | ||
d2653e92 | 253 | static int __devinit pca953x_probe(struct i2c_client *client, |
3760f736 | 254 | const struct i2c_device_id *id) |
9e60fdcf | 255 | { |
f3dc3630 GL |
256 | struct pca953x_platform_data *pdata; |
257 | struct pca953x_chip *chip; | |
f39e5781 | 258 | int ret; |
9e60fdcf | 259 | |
1965d303 NC |
260 | chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); |
261 | if (chip == NULL) | |
262 | return -ENOMEM; | |
263 | ||
9e60fdcf | 264 | pdata = client->dev.platform_data; |
a342d215 | 265 | if (pdata == NULL) { |
1965d303 NC |
266 | pdata = pca953x_get_alt_pdata(client); |
267 | /* | |
268 | * Unlike normal platform_data, this is allocated | |
269 | * dynamically and must be freed in the driver | |
270 | */ | |
271 | chip->dyn_pdata = pdata; | |
a342d215 | 272 | } |
9e60fdcf | 273 | |
1965d303 NC |
274 | if (pdata == NULL) { |
275 | dev_dbg(&client->dev, "no platform data\n"); | |
276 | ret = -EINVAL; | |
277 | goto out_failed; | |
278 | } | |
9e60fdcf | 279 | |
280 | chip->client = client; | |
281 | ||
282 | chip->gpio_start = pdata->gpio_base; | |
283 | ||
77906a54 DS |
284 | chip->names = pdata->names; |
285 | ||
9e60fdcf | 286 | /* initialize cached registers from their original values. |
287 | * we can't share this chip with another i2c master. | |
288 | */ | |
f5e8ff48 GL |
289 | pca953x_setup_gpio(chip, id->driver_data); |
290 | ||
f3dc3630 | 291 | ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output); |
9e60fdcf | 292 | if (ret) |
293 | goto out_failed; | |
294 | ||
f3dc3630 | 295 | ret = pca953x_read_reg(chip, PCA953X_DIRECTION, &chip->reg_direction); |
9e60fdcf | 296 | if (ret) |
297 | goto out_failed; | |
298 | ||
299 | /* set platform specific polarity inversion */ | |
f3dc3630 | 300 | ret = pca953x_write_reg(chip, PCA953X_INVERT, pdata->invert); |
9e60fdcf | 301 | if (ret) |
302 | goto out_failed; | |
303 | ||
f5e8ff48 GL |
304 | |
305 | ret = gpiochip_add(&chip->gpio_chip); | |
9e60fdcf | 306 | if (ret) |
307 | goto out_failed; | |
308 | ||
309 | if (pdata->setup) { | |
310 | ret = pdata->setup(client, chip->gpio_chip.base, | |
311 | chip->gpio_chip.ngpio, pdata->context); | |
312 | if (ret < 0) | |
313 | dev_warn(&client->dev, "setup failed, %d\n", ret); | |
314 | } | |
315 | ||
316 | i2c_set_clientdata(client, chip); | |
317 | return 0; | |
318 | ||
319 | out_failed: | |
1965d303 | 320 | kfree(chip->dyn_pdata); |
9e60fdcf | 321 | kfree(chip); |
322 | return ret; | |
323 | } | |
324 | ||
f3dc3630 | 325 | static int pca953x_remove(struct i2c_client *client) |
9e60fdcf | 326 | { |
f3dc3630 GL |
327 | struct pca953x_platform_data *pdata = client->dev.platform_data; |
328 | struct pca953x_chip *chip = i2c_get_clientdata(client); | |
9e60fdcf | 329 | int ret = 0; |
330 | ||
331 | if (pdata->teardown) { | |
332 | ret = pdata->teardown(client, chip->gpio_chip.base, | |
333 | chip->gpio_chip.ngpio, pdata->context); | |
334 | if (ret < 0) { | |
335 | dev_err(&client->dev, "%s failed, %d\n", | |
336 | "teardown", ret); | |
337 | return ret; | |
338 | } | |
339 | } | |
340 | ||
341 | ret = gpiochip_remove(&chip->gpio_chip); | |
342 | if (ret) { | |
343 | dev_err(&client->dev, "%s failed, %d\n", | |
344 | "gpiochip_remove()", ret); | |
345 | return ret; | |
346 | } | |
347 | ||
1965d303 | 348 | kfree(chip->dyn_pdata); |
9e60fdcf | 349 | kfree(chip); |
350 | return 0; | |
351 | } | |
352 | ||
f3dc3630 | 353 | static struct i2c_driver pca953x_driver = { |
9e60fdcf | 354 | .driver = { |
f3dc3630 | 355 | .name = "pca953x", |
9e60fdcf | 356 | }, |
f3dc3630 GL |
357 | .probe = pca953x_probe, |
358 | .remove = pca953x_remove, | |
3760f736 | 359 | .id_table = pca953x_id, |
9e60fdcf | 360 | }; |
361 | ||
f3dc3630 | 362 | static int __init pca953x_init(void) |
9e60fdcf | 363 | { |
f3dc3630 | 364 | return i2c_add_driver(&pca953x_driver); |
9e60fdcf | 365 | } |
2f8d1197 DB |
366 | /* register after i2c postcore initcall and before |
367 | * subsys initcalls that may rely on these GPIOs | |
368 | */ | |
369 | subsys_initcall(pca953x_init); | |
9e60fdcf | 370 | |
f3dc3630 | 371 | static void __exit pca953x_exit(void) |
9e60fdcf | 372 | { |
f3dc3630 | 373 | i2c_del_driver(&pca953x_driver); |
9e60fdcf | 374 | } |
f3dc3630 | 375 | module_exit(pca953x_exit); |
9e60fdcf | 376 | |
377 | MODULE_AUTHOR("eric miao <eric.miao@marvell.com>"); | |
f3dc3630 | 378 | MODULE_DESCRIPTION("GPIO expander driver for PCA953x"); |
9e60fdcf | 379 | MODULE_LICENSE("GPL"); |