blob: 8ab1308bec20608cb488d905f6dcdbafae3f0640 [file] [log] [blame]
eric miao9e60fdc2008-02-04 22:28:26 -08001/*
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -08002 * pca953x.c - 4/8/16 bit I/O ports
eric miao9e60fdc2008-02-04 22:28:26 -08003 *
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>
16#include <linux/i2c.h>
Guennadi Liakhovetskid1c057e32008-02-06 01:39:02 -080017#include <linux/i2c/pca953x.h>
Nate Case1965d302009-06-17 16:26:17 -070018#ifdef CONFIG_OF_GPIO
19#include <linux/of_platform.h>
20#include <linux/of_gpio.h>
21#endif
eric miao9e60fdc2008-02-04 22:28:26 -080022
23#include <asm/gpio.h>
24
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -080025#define PCA953X_INPUT 0
26#define PCA953X_OUTPUT 1
27#define PCA953X_INVERT 2
28#define PCA953X_DIRECTION 3
eric miao9e60fdc2008-02-04 22:28:26 -080029
Jean Delvare3760f732008-04-29 23:11:40 +020030static const struct i2c_device_id pca953x_id[] = {
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -080031 { "pca9534", 8, },
32 { "pca9535", 16, },
33 { "pca9536", 4, },
34 { "pca9537", 4, },
35 { "pca9538", 8, },
36 { "pca9539", 16, },
David Brownell69292b32008-05-23 13:04:42 -070037 { "pca9554", 8, },
Will Newtonf39e5782008-05-01 04:35:10 -070038 { "pca9555", 16, },
Nate Case10dfb542009-06-17 16:26:18 -070039 { "pca9556", 8, },
Will Newtonf39e5782008-05-01 04:35:10 -070040 { "pca9557", 8, },
David Brownellab5dc372009-01-06 14:42:27 -080041
David Brownell7059d4b2008-07-04 09:59:37 -070042 { "max7310", 8, },
Alek Du61e06712009-09-22 16:46:36 -070043 { "max7315", 8, },
David Brownellab5dc372009-01-06 14:42:27 -080044 { "pca6107", 8, },
45 { "tca6408", 8, },
46 { "tca6416", 16, },
47 /* NYET: { "tca6424", 24, }, */
Jean Delvare3760f732008-04-29 23:11:40 +020048 { }
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -080049};
Jean Delvare3760f732008-04-29 23:11:40 +020050MODULE_DEVICE_TABLE(i2c, pca953x_id);
eric miao9e60fdc2008-02-04 22:28:26 -080051
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -080052struct pca953x_chip {
eric miao9e60fdc2008-02-04 22:28:26 -080053 unsigned gpio_start;
54 uint16_t reg_output;
55 uint16_t reg_direction;
56
57 struct i2c_client *client;
Nate Case1965d302009-06-17 16:26:17 -070058 struct pca953x_platform_data *dyn_pdata;
eric miao9e60fdc2008-02-04 22:28:26 -080059 struct gpio_chip gpio_chip;
Daniel Silverstone77906a542009-06-17 16:26:15 -070060 char **names;
eric miao9e60fdc2008-02-04 22:28:26 -080061};
62
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -080063static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
eric miao9e60fdc2008-02-04 22:28:26 -080064{
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -080065 int ret;
66
67 if (chip->gpio_chip.ngpio <= 8)
68 ret = i2c_smbus_write_byte_data(chip->client, reg, val);
eric miao9e60fdc2008-02-04 22:28:26 -080069 else
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -080070 ret = i2c_smbus_write_word_data(chip->client, reg << 1, val);
71
72 if (ret < 0) {
73 dev_err(&chip->client->dev, "failed writing register\n");
David Brownellab5dc372009-01-06 14:42:27 -080074 return ret;
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -080075 }
76
77 return 0;
eric miao9e60fdc2008-02-04 22:28:26 -080078}
79
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -080080static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val)
eric miao9e60fdc2008-02-04 22:28:26 -080081{
82 int ret;
83
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -080084 if (chip->gpio_chip.ngpio <= 8)
85 ret = i2c_smbus_read_byte_data(chip->client, reg);
86 else
87 ret = i2c_smbus_read_word_data(chip->client, reg << 1);
88
eric miao9e60fdc2008-02-04 22:28:26 -080089 if (ret < 0) {
90 dev_err(&chip->client->dev, "failed reading register\n");
David Brownellab5dc372009-01-06 14:42:27 -080091 return ret;
eric miao9e60fdc2008-02-04 22:28:26 -080092 }
93
94 *val = (uint16_t)ret;
95 return 0;
96}
97
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -080098static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
eric miao9e60fdc2008-02-04 22:28:26 -080099{
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800100 struct pca953x_chip *chip;
eric miao9e60fdc2008-02-04 22:28:26 -0800101 uint16_t reg_val;
102 int ret;
103
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800104 chip = container_of(gc, struct pca953x_chip, gpio_chip);
eric miao9e60fdc2008-02-04 22:28:26 -0800105
106 reg_val = chip->reg_direction | (1u << off);
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800107 ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
eric miao9e60fdc2008-02-04 22:28:26 -0800108 if (ret)
109 return ret;
110
111 chip->reg_direction = reg_val;
112 return 0;
113}
114
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800115static int pca953x_gpio_direction_output(struct gpio_chip *gc,
eric miao9e60fdc2008-02-04 22:28:26 -0800116 unsigned off, int val)
117{
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800118 struct pca953x_chip *chip;
eric miao9e60fdc2008-02-04 22:28:26 -0800119 uint16_t reg_val;
120 int ret;
121
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800122 chip = container_of(gc, struct pca953x_chip, gpio_chip);
eric miao9e60fdc2008-02-04 22:28:26 -0800123
124 /* set output level */
125 if (val)
126 reg_val = chip->reg_output | (1u << off);
127 else
128 reg_val = chip->reg_output & ~(1u << off);
129
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800130 ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val);
eric miao9e60fdc2008-02-04 22:28:26 -0800131 if (ret)
132 return ret;
133
134 chip->reg_output = reg_val;
135
136 /* then direction */
137 reg_val = chip->reg_direction & ~(1u << off);
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800138 ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
eric miao9e60fdc2008-02-04 22:28:26 -0800139 if (ret)
140 return ret;
141
142 chip->reg_direction = reg_val;
143 return 0;
144}
145
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800146static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
eric miao9e60fdc2008-02-04 22:28:26 -0800147{
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800148 struct pca953x_chip *chip;
eric miao9e60fdc2008-02-04 22:28:26 -0800149 uint16_t reg_val;
150 int ret;
151
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800152 chip = container_of(gc, struct pca953x_chip, gpio_chip);
eric miao9e60fdc2008-02-04 22:28:26 -0800153
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800154 ret = pca953x_read_reg(chip, PCA953X_INPUT, &reg_val);
eric miao9e60fdc2008-02-04 22:28:26 -0800155 if (ret < 0) {
156 /* NOTE: diagnostic already emitted; that's all we should
157 * do unless gpio_*_value_cansleep() calls become different
158 * from their nonsleeping siblings (and report faults).
159 */
160 return 0;
161 }
162
163 return (reg_val & (1u << off)) ? 1 : 0;
164}
165
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800166static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
eric miao9e60fdc2008-02-04 22:28:26 -0800167{
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800168 struct pca953x_chip *chip;
eric miao9e60fdc2008-02-04 22:28:26 -0800169 uint16_t reg_val;
170 int ret;
171
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800172 chip = container_of(gc, struct pca953x_chip, gpio_chip);
eric miao9e60fdc2008-02-04 22:28:26 -0800173
174 if (val)
175 reg_val = chip->reg_output | (1u << off);
176 else
177 reg_val = chip->reg_output & ~(1u << off);
178
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800179 ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val);
eric miao9e60fdc2008-02-04 22:28:26 -0800180 if (ret)
181 return;
182
183 chip->reg_output = reg_val;
184}
185
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -0800186static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
eric miao9e60fdc2008-02-04 22:28:26 -0800187{
188 struct gpio_chip *gc;
189
190 gc = &chip->gpio_chip;
191
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800192 gc->direction_input = pca953x_gpio_direction_input;
193 gc->direction_output = pca953x_gpio_direction_output;
194 gc->get = pca953x_gpio_get_value;
195 gc->set = pca953x_gpio_set_value;
Arnaud Patard84207802008-03-10 11:43:48 -0700196 gc->can_sleep = 1;
eric miao9e60fdc2008-02-04 22:28:26 -0800197
198 gc->base = chip->gpio_start;
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -0800199 gc->ngpio = gpios;
200 gc->label = chip->client->name;
David Brownelld8f388d2008-07-25 01:46:07 -0700201 gc->dev = &chip->client->dev;
Guennadi Liakhovetskid72cbed2008-04-28 02:14:45 -0700202 gc->owner = THIS_MODULE;
Daniel Silverstone77906a542009-06-17 16:26:15 -0700203 gc->names = chip->names;
eric miao9e60fdc2008-02-04 22:28:26 -0800204}
205
Nate Case1965d302009-06-17 16:26:17 -0700206/*
207 * Handlers for alternative sources of platform_data
208 */
209#ifdef CONFIG_OF_GPIO
210/*
211 * Translate OpenFirmware node properties into platform_data
212 */
213static struct pca953x_platform_data *
214pca953x_get_alt_pdata(struct i2c_client *client)
215{
216 struct pca953x_platform_data *pdata;
217 struct device_node *node;
218 const uint16_t *val;
219
220 node = dev_archdata_get_node(&client->dev.archdata);
221 if (node == NULL)
222 return NULL;
223
224 pdata = kzalloc(sizeof(struct pca953x_platform_data), GFP_KERNEL);
225 if (pdata == NULL) {
226 dev_err(&client->dev, "Unable to allocate platform_data\n");
227 return NULL;
228 }
229
230 pdata->gpio_base = -1;
231 val = of_get_property(node, "linux,gpio-base", NULL);
232 if (val) {
233 if (*val < 0)
234 dev_warn(&client->dev,
235 "invalid gpio-base in device tree\n");
236 else
237 pdata->gpio_base = *val;
238 }
239
240 val = of_get_property(node, "polarity", NULL);
241 if (val)
242 pdata->invert = *val;
243
244 return pdata;
245}
246#else
247static struct pca953x_platform_data *
248pca953x_get_alt_pdata(struct i2c_client *client)
249{
250 return NULL;
251}
252#endif
253
Jean Delvared2653e92008-04-29 23:11:39 +0200254static int __devinit pca953x_probe(struct i2c_client *client,
Jean Delvare3760f732008-04-29 23:11:40 +0200255 const struct i2c_device_id *id)
eric miao9e60fdc2008-02-04 22:28:26 -0800256{
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800257 struct pca953x_platform_data *pdata;
258 struct pca953x_chip *chip;
Will Newtonf39e5782008-05-01 04:35:10 -0700259 int ret;
eric miao9e60fdc2008-02-04 22:28:26 -0800260
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800261 chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
eric miao9e60fdc2008-02-04 22:28:26 -0800262 if (chip == NULL)
263 return -ENOMEM;
264
Nate Case1965d302009-06-17 16:26:17 -0700265 pdata = client->dev.platform_data;
266 if (pdata == NULL) {
267 pdata = pca953x_get_alt_pdata(client);
268 /*
269 * Unlike normal platform_data, this is allocated
270 * dynamically and must be freed in the driver
271 */
272 chip->dyn_pdata = pdata;
273 }
274
275 if (pdata == NULL) {
276 dev_dbg(&client->dev, "no platform data\n");
277 ret = -EINVAL;
278 goto out_failed;
279 }
280
eric miao9e60fdc2008-02-04 22:28:26 -0800281 chip->client = client;
282
283 chip->gpio_start = pdata->gpio_base;
284
Daniel Silverstone77906a542009-06-17 16:26:15 -0700285 chip->names = pdata->names;
286
eric miao9e60fdc2008-02-04 22:28:26 -0800287 /* initialize cached registers from their original values.
288 * we can't share this chip with another i2c master.
289 */
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -0800290 pca953x_setup_gpio(chip, id->driver_data);
291
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800292 ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output);
eric miao9e60fdc2008-02-04 22:28:26 -0800293 if (ret)
294 goto out_failed;
295
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800296 ret = pca953x_read_reg(chip, PCA953X_DIRECTION, &chip->reg_direction);
eric miao9e60fdc2008-02-04 22:28:26 -0800297 if (ret)
298 goto out_failed;
299
300 /* set platform specific polarity inversion */
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800301 ret = pca953x_write_reg(chip, PCA953X_INVERT, pdata->invert);
eric miao9e60fdc2008-02-04 22:28:26 -0800302 if (ret)
303 goto out_failed;
304
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -0800305
306 ret = gpiochip_add(&chip->gpio_chip);
eric miao9e60fdc2008-02-04 22:28:26 -0800307 if (ret)
308 goto out_failed;
309
310 if (pdata->setup) {
311 ret = pdata->setup(client, chip->gpio_chip.base,
312 chip->gpio_chip.ngpio, pdata->context);
313 if (ret < 0)
314 dev_warn(&client->dev, "setup failed, %d\n", ret);
315 }
316
317 i2c_set_clientdata(client, chip);
318 return 0;
319
320out_failed:
Nate Case1965d302009-06-17 16:26:17 -0700321 kfree(chip->dyn_pdata);
eric miao9e60fdc2008-02-04 22:28:26 -0800322 kfree(chip);
323 return ret;
324}
325
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800326static int pca953x_remove(struct i2c_client *client)
eric miao9e60fdc2008-02-04 22:28:26 -0800327{
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800328 struct pca953x_platform_data *pdata = client->dev.platform_data;
329 struct pca953x_chip *chip = i2c_get_clientdata(client);
eric miao9e60fdc2008-02-04 22:28:26 -0800330 int ret = 0;
331
332 if (pdata->teardown) {
333 ret = pdata->teardown(client, chip->gpio_chip.base,
334 chip->gpio_chip.ngpio, pdata->context);
335 if (ret < 0) {
336 dev_err(&client->dev, "%s failed, %d\n",
337 "teardown", ret);
338 return ret;
339 }
340 }
341
342 ret = gpiochip_remove(&chip->gpio_chip);
343 if (ret) {
344 dev_err(&client->dev, "%s failed, %d\n",
345 "gpiochip_remove()", ret);
346 return ret;
347 }
348
Nate Case1965d302009-06-17 16:26:17 -0700349 kfree(chip->dyn_pdata);
eric miao9e60fdc2008-02-04 22:28:26 -0800350 kfree(chip);
351 return 0;
352}
353
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800354static struct i2c_driver pca953x_driver = {
eric miao9e60fdc2008-02-04 22:28:26 -0800355 .driver = {
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800356 .name = "pca953x",
eric miao9e60fdc2008-02-04 22:28:26 -0800357 },
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800358 .probe = pca953x_probe,
359 .remove = pca953x_remove,
Jean Delvare3760f732008-04-29 23:11:40 +0200360 .id_table = pca953x_id,
eric miao9e60fdc2008-02-04 22:28:26 -0800361};
362
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800363static int __init pca953x_init(void)
eric miao9e60fdc2008-02-04 22:28:26 -0800364{
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800365 return i2c_add_driver(&pca953x_driver);
eric miao9e60fdc2008-02-04 22:28:26 -0800366}
David Brownell2f8d1192008-10-15 22:03:13 -0700367/* register after i2c postcore initcall and before
368 * subsys initcalls that may rely on these GPIOs
369 */
370subsys_initcall(pca953x_init);
eric miao9e60fdc2008-02-04 22:28:26 -0800371
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800372static void __exit pca953x_exit(void)
eric miao9e60fdc2008-02-04 22:28:26 -0800373{
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800374 i2c_del_driver(&pca953x_driver);
eric miao9e60fdc2008-02-04 22:28:26 -0800375}
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800376module_exit(pca953x_exit);
eric miao9e60fdc2008-02-04 22:28:26 -0800377
378MODULE_AUTHOR("eric miao <eric.miao@marvell.com>");
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800379MODULE_DESCRIPTION("GPIO expander driver for PCA953x");
eric miao9e60fdc2008-02-04 22:28:26 -0800380MODULE_LICENSE("GPL");