blob: 2dae94fbabf4f94c21ec8aab08cedca312daa732 [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>
eric miao9e60fdc2008-02-04 22:28:26 -080018
19#include <asm/gpio.h>
20
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -080021#define PCA953X_INPUT 0
22#define PCA953X_OUTPUT 1
23#define PCA953X_INVERT 2
24#define PCA953X_DIRECTION 3
eric miao9e60fdc2008-02-04 22:28:26 -080025
Jean Delvare3760f732008-04-29 23:11:40 +020026static const struct i2c_device_id pca953x_id[] = {
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -080027 { "pca9534", 8, },
28 { "pca9535", 16, },
29 { "pca9536", 4, },
30 { "pca9537", 4, },
31 { "pca9538", 8, },
32 { "pca9539", 16, },
David Brownell69292b32008-05-23 13:04:42 -070033 { "pca9554", 8, },
Will Newtonf39e5782008-05-01 04:35:10 -070034 { "pca9555", 16, },
35 { "pca9557", 8, },
David Brownellab5dc372009-01-06 14:42:27 -080036
David Brownell7059d4b2008-07-04 09:59:37 -070037 { "max7310", 8, },
David Brownellab5dc372009-01-06 14:42:27 -080038 { "pca6107", 8, },
39 { "tca6408", 8, },
40 { "tca6416", 16, },
41 /* NYET: { "tca6424", 24, }, */
Jean Delvare3760f732008-04-29 23:11:40 +020042 { }
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -080043};
Jean Delvare3760f732008-04-29 23:11:40 +020044MODULE_DEVICE_TABLE(i2c, pca953x_id);
eric miao9e60fdc2008-02-04 22:28:26 -080045
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -080046struct pca953x_chip {
eric miao9e60fdc2008-02-04 22:28:26 -080047 unsigned gpio_start;
48 uint16_t reg_output;
49 uint16_t reg_direction;
50
51 struct i2c_client *client;
52 struct gpio_chip gpio_chip;
Daniel Silverstone77906a542009-06-17 16:26:15 -070053 char **names;
eric miao9e60fdc2008-02-04 22:28:26 -080054};
55
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -080056static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
eric miao9e60fdc2008-02-04 22:28:26 -080057{
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -080058 int ret;
59
60 if (chip->gpio_chip.ngpio <= 8)
61 ret = i2c_smbus_write_byte_data(chip->client, reg, val);
eric miao9e60fdc2008-02-04 22:28:26 -080062 else
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -080063 ret = i2c_smbus_write_word_data(chip->client, reg << 1, val);
64
65 if (ret < 0) {
66 dev_err(&chip->client->dev, "failed writing register\n");
David Brownellab5dc372009-01-06 14:42:27 -080067 return ret;
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -080068 }
69
70 return 0;
eric miao9e60fdc2008-02-04 22:28:26 -080071}
72
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -080073static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val)
eric miao9e60fdc2008-02-04 22:28:26 -080074{
75 int ret;
76
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -080077 if (chip->gpio_chip.ngpio <= 8)
78 ret = i2c_smbus_read_byte_data(chip->client, reg);
79 else
80 ret = i2c_smbus_read_word_data(chip->client, reg << 1);
81
eric miao9e60fdc2008-02-04 22:28:26 -080082 if (ret < 0) {
83 dev_err(&chip->client->dev, "failed reading register\n");
David Brownellab5dc372009-01-06 14:42:27 -080084 return ret;
eric miao9e60fdc2008-02-04 22:28:26 -080085 }
86
87 *val = (uint16_t)ret;
88 return 0;
89}
90
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -080091static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
eric miao9e60fdc2008-02-04 22:28:26 -080092{
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -080093 struct pca953x_chip *chip;
eric miao9e60fdc2008-02-04 22:28:26 -080094 uint16_t reg_val;
95 int ret;
96
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -080097 chip = container_of(gc, struct pca953x_chip, gpio_chip);
eric miao9e60fdc2008-02-04 22:28:26 -080098
99 reg_val = chip->reg_direction | (1u << off);
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800100 ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
eric miao9e60fdc2008-02-04 22:28:26 -0800101 if (ret)
102 return ret;
103
104 chip->reg_direction = reg_val;
105 return 0;
106}
107
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800108static int pca953x_gpio_direction_output(struct gpio_chip *gc,
eric miao9e60fdc2008-02-04 22:28:26 -0800109 unsigned off, int val)
110{
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800111 struct pca953x_chip *chip;
eric miao9e60fdc2008-02-04 22:28:26 -0800112 uint16_t reg_val;
113 int ret;
114
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800115 chip = container_of(gc, struct pca953x_chip, gpio_chip);
eric miao9e60fdc2008-02-04 22:28:26 -0800116
117 /* set output level */
118 if (val)
119 reg_val = chip->reg_output | (1u << off);
120 else
121 reg_val = chip->reg_output & ~(1u << off);
122
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800123 ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val);
eric miao9e60fdc2008-02-04 22:28:26 -0800124 if (ret)
125 return ret;
126
127 chip->reg_output = reg_val;
128
129 /* then direction */
130 reg_val = chip->reg_direction & ~(1u << off);
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800131 ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
eric miao9e60fdc2008-02-04 22:28:26 -0800132 if (ret)
133 return ret;
134
135 chip->reg_direction = reg_val;
136 return 0;
137}
138
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800139static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
eric miao9e60fdc2008-02-04 22:28:26 -0800140{
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800141 struct pca953x_chip *chip;
eric miao9e60fdc2008-02-04 22:28:26 -0800142 uint16_t reg_val;
143 int ret;
144
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800145 chip = container_of(gc, struct pca953x_chip, gpio_chip);
eric miao9e60fdc2008-02-04 22:28:26 -0800146
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800147 ret = pca953x_read_reg(chip, PCA953X_INPUT, &reg_val);
eric miao9e60fdc2008-02-04 22:28:26 -0800148 if (ret < 0) {
149 /* NOTE: diagnostic already emitted; that's all we should
150 * do unless gpio_*_value_cansleep() calls become different
151 * from their nonsleeping siblings (and report faults).
152 */
153 return 0;
154 }
155
156 return (reg_val & (1u << off)) ? 1 : 0;
157}
158
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800159static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
eric miao9e60fdc2008-02-04 22:28:26 -0800160{
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800161 struct pca953x_chip *chip;
eric miao9e60fdc2008-02-04 22:28:26 -0800162 uint16_t reg_val;
163 int ret;
164
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800165 chip = container_of(gc, struct pca953x_chip, gpio_chip);
eric miao9e60fdc2008-02-04 22:28:26 -0800166
167 if (val)
168 reg_val = chip->reg_output | (1u << off);
169 else
170 reg_val = chip->reg_output & ~(1u << off);
171
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800172 ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val);
eric miao9e60fdc2008-02-04 22:28:26 -0800173 if (ret)
174 return;
175
176 chip->reg_output = reg_val;
177}
178
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -0800179static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
eric miao9e60fdc2008-02-04 22:28:26 -0800180{
181 struct gpio_chip *gc;
182
183 gc = &chip->gpio_chip;
184
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800185 gc->direction_input = pca953x_gpio_direction_input;
186 gc->direction_output = pca953x_gpio_direction_output;
187 gc->get = pca953x_gpio_get_value;
188 gc->set = pca953x_gpio_set_value;
Arnaud Patard84207802008-03-10 11:43:48 -0700189 gc->can_sleep = 1;
eric miao9e60fdc2008-02-04 22:28:26 -0800190
191 gc->base = chip->gpio_start;
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -0800192 gc->ngpio = gpios;
193 gc->label = chip->client->name;
David Brownelld8f388d2008-07-25 01:46:07 -0700194 gc->dev = &chip->client->dev;
Guennadi Liakhovetskid72cbed2008-04-28 02:14:45 -0700195 gc->owner = THIS_MODULE;
Daniel Silverstone77906a542009-06-17 16:26:15 -0700196 gc->names = chip->names;
eric miao9e60fdc2008-02-04 22:28:26 -0800197}
198
Jean Delvared2653e92008-04-29 23:11:39 +0200199static int __devinit pca953x_probe(struct i2c_client *client,
Jean Delvare3760f732008-04-29 23:11:40 +0200200 const struct i2c_device_id *id)
eric miao9e60fdc2008-02-04 22:28:26 -0800201{
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800202 struct pca953x_platform_data *pdata;
203 struct pca953x_chip *chip;
Will Newtonf39e5782008-05-01 04:35:10 -0700204 int ret;
eric miao9e60fdc2008-02-04 22:28:26 -0800205
206 pdata = client->dev.platform_data;
Ben Dooksa342d212009-01-15 13:50:45 -0800207 if (pdata == NULL) {
208 dev_dbg(&client->dev, "no platform data\n");
209 return -EINVAL;
210 }
eric miao9e60fdc2008-02-04 22:28:26 -0800211
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800212 chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
eric miao9e60fdc2008-02-04 22:28:26 -0800213 if (chip == NULL)
214 return -ENOMEM;
215
216 chip->client = client;
217
218 chip->gpio_start = pdata->gpio_base;
219
Daniel Silverstone77906a542009-06-17 16:26:15 -0700220 chip->names = pdata->names;
221
eric miao9e60fdc2008-02-04 22:28:26 -0800222 /* initialize cached registers from their original values.
223 * we can't share this chip with another i2c master.
224 */
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -0800225 pca953x_setup_gpio(chip, id->driver_data);
226
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800227 ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output);
eric miao9e60fdc2008-02-04 22:28:26 -0800228 if (ret)
229 goto out_failed;
230
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800231 ret = pca953x_read_reg(chip, PCA953X_DIRECTION, &chip->reg_direction);
eric miao9e60fdc2008-02-04 22:28:26 -0800232 if (ret)
233 goto out_failed;
234
235 /* set platform specific polarity inversion */
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800236 ret = pca953x_write_reg(chip, PCA953X_INVERT, pdata->invert);
eric miao9e60fdc2008-02-04 22:28:26 -0800237 if (ret)
238 goto out_failed;
239
Guennadi Liakhovetskif5e8ff42008-02-06 01:39:04 -0800240
241 ret = gpiochip_add(&chip->gpio_chip);
eric miao9e60fdc2008-02-04 22:28:26 -0800242 if (ret)
243 goto out_failed;
244
245 if (pdata->setup) {
246 ret = pdata->setup(client, chip->gpio_chip.base,
247 chip->gpio_chip.ngpio, pdata->context);
248 if (ret < 0)
249 dev_warn(&client->dev, "setup failed, %d\n", ret);
250 }
251
252 i2c_set_clientdata(client, chip);
253 return 0;
254
255out_failed:
256 kfree(chip);
257 return ret;
258}
259
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800260static int pca953x_remove(struct i2c_client *client)
eric miao9e60fdc2008-02-04 22:28:26 -0800261{
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800262 struct pca953x_platform_data *pdata = client->dev.platform_data;
263 struct pca953x_chip *chip = i2c_get_clientdata(client);
eric miao9e60fdc2008-02-04 22:28:26 -0800264 int ret = 0;
265
266 if (pdata->teardown) {
267 ret = pdata->teardown(client, chip->gpio_chip.base,
268 chip->gpio_chip.ngpio, pdata->context);
269 if (ret < 0) {
270 dev_err(&client->dev, "%s failed, %d\n",
271 "teardown", ret);
272 return ret;
273 }
274 }
275
276 ret = gpiochip_remove(&chip->gpio_chip);
277 if (ret) {
278 dev_err(&client->dev, "%s failed, %d\n",
279 "gpiochip_remove()", ret);
280 return ret;
281 }
282
283 kfree(chip);
284 return 0;
285}
286
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800287static struct i2c_driver pca953x_driver = {
eric miao9e60fdc2008-02-04 22:28:26 -0800288 .driver = {
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800289 .name = "pca953x",
eric miao9e60fdc2008-02-04 22:28:26 -0800290 },
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800291 .probe = pca953x_probe,
292 .remove = pca953x_remove,
Jean Delvare3760f732008-04-29 23:11:40 +0200293 .id_table = pca953x_id,
eric miao9e60fdc2008-02-04 22:28:26 -0800294};
295
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800296static int __init pca953x_init(void)
eric miao9e60fdc2008-02-04 22:28:26 -0800297{
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800298 return i2c_add_driver(&pca953x_driver);
eric miao9e60fdc2008-02-04 22:28:26 -0800299}
David Brownell2f8d1192008-10-15 22:03:13 -0700300/* register after i2c postcore initcall and before
301 * subsys initcalls that may rely on these GPIOs
302 */
303subsys_initcall(pca953x_init);
eric miao9e60fdc2008-02-04 22:28:26 -0800304
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800305static void __exit pca953x_exit(void)
eric miao9e60fdc2008-02-04 22:28:26 -0800306{
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800307 i2c_del_driver(&pca953x_driver);
eric miao9e60fdc2008-02-04 22:28:26 -0800308}
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800309module_exit(pca953x_exit);
eric miao9e60fdc2008-02-04 22:28:26 -0800310
311MODULE_AUTHOR("eric miao <eric.miao@marvell.com>");
Guennadi Liakhovetskif3dc3632008-02-06 01:39:03 -0800312MODULE_DESCRIPTION("GPIO expander driver for PCA953x");
eric miao9e60fdc2008-02-04 22:28:26 -0800313MODULE_LICENSE("GPL");