Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.30 309 lines 6.9 kB view raw
1/* 2 * pca953x.c - 4/8/16 bit I/O ports 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> 16#include <linux/i2c.h> 17#include <linux/i2c/pca953x.h> 18 19#include <asm/gpio.h> 20 21#define PCA953X_INPUT 0 22#define PCA953X_OUTPUT 1 23#define PCA953X_INVERT 2 24#define PCA953X_DIRECTION 3 25 26static const struct i2c_device_id pca953x_id[] = { 27 { "pca9534", 8, }, 28 { "pca9535", 16, }, 29 { "pca9536", 4, }, 30 { "pca9537", 4, }, 31 { "pca9538", 8, }, 32 { "pca9539", 16, }, 33 { "pca9554", 8, }, 34 { "pca9555", 16, }, 35 { "pca9557", 8, }, 36 37 { "max7310", 8, }, 38 { "pca6107", 8, }, 39 { "tca6408", 8, }, 40 { "tca6416", 16, }, 41 /* NYET: { "tca6424", 24, }, */ 42 { } 43}; 44MODULE_DEVICE_TABLE(i2c, pca953x_id); 45 46struct pca953x_chip { 47 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; 53}; 54 55static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) 56{ 57 int ret; 58 59 if (chip->gpio_chip.ngpio <= 8) 60 ret = i2c_smbus_write_byte_data(chip->client, reg, val); 61 else 62 ret = i2c_smbus_write_word_data(chip->client, reg << 1, val); 63 64 if (ret < 0) { 65 dev_err(&chip->client->dev, "failed writing register\n"); 66 return ret; 67 } 68 69 return 0; 70} 71 72static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val) 73{ 74 int ret; 75 76 if (chip->gpio_chip.ngpio <= 8) 77 ret = i2c_smbus_read_byte_data(chip->client, reg); 78 else 79 ret = i2c_smbus_read_word_data(chip->client, reg << 1); 80 81 if (ret < 0) { 82 dev_err(&chip->client->dev, "failed reading register\n"); 83 return ret; 84 } 85 86 *val = (uint16_t)ret; 87 return 0; 88} 89 90static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) 91{ 92 struct pca953x_chip *chip; 93 uint16_t reg_val; 94 int ret; 95 96 chip = container_of(gc, struct pca953x_chip, gpio_chip); 97 98 reg_val = chip->reg_direction | (1u << off); 99 ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val); 100 if (ret) 101 return ret; 102 103 chip->reg_direction = reg_val; 104 return 0; 105} 106 107static int pca953x_gpio_direction_output(struct gpio_chip *gc, 108 unsigned off, int val) 109{ 110 struct pca953x_chip *chip; 111 uint16_t reg_val; 112 int ret; 113 114 chip = container_of(gc, struct pca953x_chip, gpio_chip); 115 116 /* set output level */ 117 if (val) 118 reg_val = chip->reg_output | (1u << off); 119 else 120 reg_val = chip->reg_output & ~(1u << off); 121 122 ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val); 123 if (ret) 124 return ret; 125 126 chip->reg_output = reg_val; 127 128 /* then direction */ 129 reg_val = chip->reg_direction & ~(1u << off); 130 ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val); 131 if (ret) 132 return ret; 133 134 chip->reg_direction = reg_val; 135 return 0; 136} 137 138static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) 139{ 140 struct pca953x_chip *chip; 141 uint16_t reg_val; 142 int ret; 143 144 chip = container_of(gc, struct pca953x_chip, gpio_chip); 145 146 ret = pca953x_read_reg(chip, PCA953X_INPUT, &reg_val); 147 if (ret < 0) { 148 /* NOTE: diagnostic already emitted; that's all we should 149 * do unless gpio_*_value_cansleep() calls become different 150 * from their nonsleeping siblings (and report faults). 151 */ 152 return 0; 153 } 154 155 return (reg_val & (1u << off)) ? 1 : 0; 156} 157 158static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) 159{ 160 struct pca953x_chip *chip; 161 uint16_t reg_val; 162 int ret; 163 164 chip = container_of(gc, struct pca953x_chip, gpio_chip); 165 166 if (val) 167 reg_val = chip->reg_output | (1u << off); 168 else 169 reg_val = chip->reg_output & ~(1u << off); 170 171 ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val); 172 if (ret) 173 return; 174 175 chip->reg_output = reg_val; 176} 177 178static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) 179{ 180 struct gpio_chip *gc; 181 182 gc = &chip->gpio_chip; 183 184 gc->direction_input = pca953x_gpio_direction_input; 185 gc->direction_output = pca953x_gpio_direction_output; 186 gc->get = pca953x_gpio_get_value; 187 gc->set = pca953x_gpio_set_value; 188 gc->can_sleep = 1; 189 190 gc->base = chip->gpio_start; 191 gc->ngpio = gpios; 192 gc->label = chip->client->name; 193 gc->dev = &chip->client->dev; 194 gc->owner = THIS_MODULE; 195} 196 197static int __devinit pca953x_probe(struct i2c_client *client, 198 const struct i2c_device_id *id) 199{ 200 struct pca953x_platform_data *pdata; 201 struct pca953x_chip *chip; 202 int ret; 203 204 pdata = client->dev.platform_data; 205 if (pdata == NULL) { 206 dev_dbg(&client->dev, "no platform data\n"); 207 return -EINVAL; 208 } 209 210 chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); 211 if (chip == NULL) 212 return -ENOMEM; 213 214 chip->client = client; 215 216 chip->gpio_start = pdata->gpio_base; 217 218 /* initialize cached registers from their original values. 219 * we can't share this chip with another i2c master. 220 */ 221 pca953x_setup_gpio(chip, id->driver_data); 222 223 ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output); 224 if (ret) 225 goto out_failed; 226 227 ret = pca953x_read_reg(chip, PCA953X_DIRECTION, &chip->reg_direction); 228 if (ret) 229 goto out_failed; 230 231 /* set platform specific polarity inversion */ 232 ret = pca953x_write_reg(chip, PCA953X_INVERT, pdata->invert); 233 if (ret) 234 goto out_failed; 235 236 237 ret = gpiochip_add(&chip->gpio_chip); 238 if (ret) 239 goto out_failed; 240 241 if (pdata->setup) { 242 ret = pdata->setup(client, chip->gpio_chip.base, 243 chip->gpio_chip.ngpio, pdata->context); 244 if (ret < 0) 245 dev_warn(&client->dev, "setup failed, %d\n", ret); 246 } 247 248 i2c_set_clientdata(client, chip); 249 return 0; 250 251out_failed: 252 kfree(chip); 253 return ret; 254} 255 256static int pca953x_remove(struct i2c_client *client) 257{ 258 struct pca953x_platform_data *pdata = client->dev.platform_data; 259 struct pca953x_chip *chip = i2c_get_clientdata(client); 260 int ret = 0; 261 262 if (pdata->teardown) { 263 ret = pdata->teardown(client, chip->gpio_chip.base, 264 chip->gpio_chip.ngpio, pdata->context); 265 if (ret < 0) { 266 dev_err(&client->dev, "%s failed, %d\n", 267 "teardown", ret); 268 return ret; 269 } 270 } 271 272 ret = gpiochip_remove(&chip->gpio_chip); 273 if (ret) { 274 dev_err(&client->dev, "%s failed, %d\n", 275 "gpiochip_remove()", ret); 276 return ret; 277 } 278 279 kfree(chip); 280 return 0; 281} 282 283static struct i2c_driver pca953x_driver = { 284 .driver = { 285 .name = "pca953x", 286 }, 287 .probe = pca953x_probe, 288 .remove = pca953x_remove, 289 .id_table = pca953x_id, 290}; 291 292static int __init pca953x_init(void) 293{ 294 return i2c_add_driver(&pca953x_driver); 295} 296/* register after i2c postcore initcall and before 297 * subsys initcalls that may rely on these GPIOs 298 */ 299subsys_initcall(pca953x_init); 300 301static void __exit pca953x_exit(void) 302{ 303 i2c_del_driver(&pca953x_driver); 304} 305module_exit(pca953x_exit); 306 307MODULE_AUTHOR("eric miao <eric.miao@marvell.com>"); 308MODULE_DESCRIPTION("GPIO expander driver for PCA953x"); 309MODULE_LICENSE("GPL");