1/* 2 * Core driver for TI TPS6586x PMIC family 3 * 4 * Copyright (c) 2010 CompuLab Ltd. 5 * Mike Rapoport <mike@compulab.co.il> 6 * 7 * Based on da903x.c. 8 * Copyright (C) 2008 Compulab, Ltd. 9 * Mike Rapoport <mike@compulab.co.il> 10 * Copyright (C) 2006-2008 Marvell International Ltd. 11 * Eric Miao <eric.miao@marvell.com> 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License version 2 as 15 * published by the Free Software Foundation. 16 */ 17 18#include <linux/kernel.h> 19#include <linux/module.h> 20#include <linux/mutex.h> 21#include <linux/slab.h> 22#include <linux/gpio.h> 23#include <linux/i2c.h> 24 25#include <linux/mfd/core.h> 26#include <linux/mfd/tps6586x.h> 27 28/* GPIO control registers */ 29#define TPS6586X_GPIOSET1 0x5d 30#define TPS6586X_GPIOSET2 0x5e 31 32/* device id */ 33#define TPS6586X_VERSIONCRC 0xcd 34#define TPS658621A_VERSIONCRC 0x15 35 36struct tps6586x { 37 struct mutex lock; 38 struct device *dev; 39 struct i2c_client *client; 40 41 struct gpio_chip gpio; 42}; 43 44static inline int __tps6586x_read(struct i2c_client *client, 45 int reg, uint8_t *val) 46{ 47 int ret; 48 49 ret = i2c_smbus_read_byte_data(client, reg); 50 if (ret < 0) { 51 dev_err(&client->dev, "failed reading at 0x%02x\n", reg); 52 return ret; 53 } 54 55 *val = (uint8_t)ret; 56 57 return 0; 58} 59 60static inline int __tps6586x_reads(struct i2c_client *client, int reg, 61 int len, uint8_t *val) 62{ 63 int ret; 64 65 ret = i2c_smbus_read_i2c_block_data(client, reg, len, val); 66 if (ret < 0) { 67 dev_err(&client->dev, "failed reading from 0x%02x\n", reg); 68 return ret; 69 } 70 71 return 0; 72} 73 74static inline int __tps6586x_write(struct i2c_client *client, 75 int reg, uint8_t val) 76{ 77 int ret; 78 79 ret = i2c_smbus_write_byte_data(client, reg, val); 80 if (ret < 0) { 81 dev_err(&client->dev, "failed writing 0x%02x to 0x%02x\n", 82 val, reg); 83 return ret; 84 } 85 86 return 0; 87} 88 89static inline int __tps6586x_writes(struct i2c_client *client, int reg, 90 int len, uint8_t *val) 91{ 92 int ret; 93 94 ret = i2c_smbus_write_i2c_block_data(client, reg, len, val); 95 if (ret < 0) { 96 dev_err(&client->dev, "failed writings to 0x%02x\n", reg); 97 return ret; 98 } 99 100 return 0; 101} 102 103int tps6586x_write(struct device *dev, int reg, uint8_t val) 104{ 105 return __tps6586x_write(to_i2c_client(dev), reg, val); 106} 107EXPORT_SYMBOL_GPL(tps6586x_write); 108 109int tps6586x_writes(struct device *dev, int reg, int len, uint8_t *val) 110{ 111 return __tps6586x_writes(to_i2c_client(dev), reg, len, val); 112} 113EXPORT_SYMBOL_GPL(tps6586x_writes); 114 115int tps6586x_read(struct device *dev, int reg, uint8_t *val) 116{ 117 return __tps6586x_read(to_i2c_client(dev), reg, val); 118} 119EXPORT_SYMBOL_GPL(tps6586x_read); 120 121int tps6586x_reads(struct device *dev, int reg, int len, uint8_t *val) 122{ 123 return __tps6586x_reads(to_i2c_client(dev), reg, len, val); 124} 125EXPORT_SYMBOL_GPL(tps6586x_reads); 126 127int tps6586x_set_bits(struct device *dev, int reg, uint8_t bit_mask) 128{ 129 struct tps6586x *tps6586x = dev_get_drvdata(dev); 130 uint8_t reg_val; 131 int ret = 0; 132 133 mutex_lock(&tps6586x->lock); 134 135 ret = __tps6586x_read(to_i2c_client(dev), reg, ®_val); 136 if (ret) 137 goto out; 138 139 if ((reg_val & bit_mask) == 0) { 140 reg_val |= bit_mask; 141 ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val); 142 } 143out: 144 mutex_unlock(&tps6586x->lock); 145 return ret; 146} 147EXPORT_SYMBOL_GPL(tps6586x_set_bits); 148 149int tps6586x_clr_bits(struct device *dev, int reg, uint8_t bit_mask) 150{ 151 struct tps6586x *tps6586x = dev_get_drvdata(dev); 152 uint8_t reg_val; 153 int ret = 0; 154 155 mutex_lock(&tps6586x->lock); 156 157 ret = __tps6586x_read(to_i2c_client(dev), reg, ®_val); 158 if (ret) 159 goto out; 160 161 if (reg_val & bit_mask) { 162 reg_val &= ~bit_mask; 163 ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val); 164 } 165out: 166 mutex_unlock(&tps6586x->lock); 167 return ret; 168} 169EXPORT_SYMBOL_GPL(tps6586x_clr_bits); 170 171int tps6586x_update(struct device *dev, int reg, uint8_t val, uint8_t mask) 172{ 173 struct tps6586x *tps6586x = dev_get_drvdata(dev); 174 uint8_t reg_val; 175 int ret = 0; 176 177 mutex_lock(&tps6586x->lock); 178 179 ret = __tps6586x_read(tps6586x->client, reg, ®_val); 180 if (ret) 181 goto out; 182 183 if ((reg_val & mask) != val) { 184 reg_val = (reg_val & ~mask) | val; 185 ret = __tps6586x_write(tps6586x->client, reg, reg_val); 186 } 187out: 188 mutex_unlock(&tps6586x->lock); 189 return ret; 190} 191EXPORT_SYMBOL_GPL(tps6586x_update); 192 193static int tps6586x_gpio_get(struct gpio_chip *gc, unsigned offset) 194{ 195 struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio); 196 uint8_t val; 197 int ret; 198 199 ret = __tps6586x_read(tps6586x->client, TPS6586X_GPIOSET2, &val); 200 if (ret) 201 return ret; 202 203 return !!(val & (1 << offset)); 204} 205 206 207static void tps6586x_gpio_set(struct gpio_chip *chip, unsigned offset, 208 int value) 209{ 210 struct tps6586x *tps6586x = container_of(chip, struct tps6586x, gpio); 211 212 __tps6586x_write(tps6586x->client, TPS6586X_GPIOSET2, 213 value << offset); 214} 215 216static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset, 217 int value) 218{ 219 struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio); 220 uint8_t val, mask; 221 222 tps6586x_gpio_set(gc, offset, value); 223 224 val = 0x1 << (offset * 2); 225 mask = 0x3 << (offset * 2); 226 227 return tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET1, val, mask); 228} 229 230static void tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base) 231{ 232 int ret; 233 234 if (!gpio_base) 235 return; 236 237 tps6586x->gpio.owner = THIS_MODULE; 238 tps6586x->gpio.label = tps6586x->client->name; 239 tps6586x->gpio.dev = tps6586x->dev; 240 tps6586x->gpio.base = gpio_base; 241 tps6586x->gpio.ngpio = 4; 242 tps6586x->gpio.can_sleep = 1; 243 244 tps6586x->gpio.direction_output = tps6586x_gpio_output; 245 tps6586x->gpio.set = tps6586x_gpio_set; 246 tps6586x->gpio.get = tps6586x_gpio_get; 247 248 ret = gpiochip_add(&tps6586x->gpio); 249 if (ret) 250 dev_warn(tps6586x->dev, "GPIO registration failed: %d\n", ret); 251} 252 253static int __remove_subdev(struct device *dev, void *unused) 254{ 255 platform_device_unregister(to_platform_device(dev)); 256 return 0; 257} 258 259static int tps6586x_remove_subdevs(struct tps6586x *tps6586x) 260{ 261 return device_for_each_child(tps6586x->dev, NULL, __remove_subdev); 262} 263 264static int __devinit tps6586x_add_subdevs(struct tps6586x *tps6586x, 265 struct tps6586x_platform_data *pdata) 266{ 267 struct tps6586x_subdev_info *subdev; 268 struct platform_device *pdev; 269 int i, ret = 0; 270 271 for (i = 0; i < pdata->num_subdevs; i++) { 272 subdev = &pdata->subdevs[i]; 273 274 pdev = platform_device_alloc(subdev->name, subdev->id); 275 276 pdev->dev.parent = tps6586x->dev; 277 pdev->dev.platform_data = subdev->platform_data; 278 279 ret = platform_device_add(pdev); 280 if (ret) 281 goto failed; 282 } 283 return 0; 284 285failed: 286 tps6586x_remove_subdevs(tps6586x); 287 return ret; 288} 289 290static int __devinit tps6586x_i2c_probe(struct i2c_client *client, 291 const struct i2c_device_id *id) 292{ 293 struct tps6586x_platform_data *pdata = client->dev.platform_data; 294 struct tps6586x *tps6586x; 295 int ret; 296 297 if (!pdata) { 298 dev_err(&client->dev, "tps6586x requires platform data\n"); 299 return -ENOTSUPP; 300 } 301 302 ret = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC); 303 if (ret < 0) { 304 dev_err(&client->dev, "Chip ID read failed: %d\n", ret); 305 return -EIO; 306 } 307 308 if (ret != TPS658621A_VERSIONCRC) { 309 dev_err(&client->dev, "Unsupported chip ID: %x\n", ret); 310 return -ENODEV; 311 } 312 313 tps6586x = kzalloc(sizeof(struct tps6586x), GFP_KERNEL); 314 if (tps6586x == NULL) 315 return -ENOMEM; 316 317 tps6586x->client = client; 318 tps6586x->dev = &client->dev; 319 i2c_set_clientdata(client, tps6586x); 320 321 mutex_init(&tps6586x->lock); 322 323 ret = tps6586x_add_subdevs(tps6586x, pdata); 324 if (ret) { 325 dev_err(&client->dev, "add devices failed: %d\n", ret); 326 goto err_add_devs; 327 } 328 329 tps6586x_gpio_init(tps6586x, pdata->gpio_base); 330 331 return 0; 332 333err_add_devs: 334 kfree(tps6586x); 335 return ret; 336} 337 338static int __devexit tps6586x_i2c_remove(struct i2c_client *client) 339{ 340 return 0; 341} 342 343static const struct i2c_device_id tps6586x_id_table[] = { 344 { "tps6586x", 0 }, 345 { }, 346}; 347MODULE_DEVICE_TABLE(i2c, tps6586x_id_table); 348 349static struct i2c_driver tps6586x_driver = { 350 .driver = { 351 .name = "tps6586x", 352 .owner = THIS_MODULE, 353 }, 354 .probe = tps6586x_i2c_probe, 355 .remove = __devexit_p(tps6586x_i2c_remove), 356 .id_table = tps6586x_id_table, 357}; 358 359static int __init tps6586x_init(void) 360{ 361 return i2c_add_driver(&tps6586x_driver); 362} 363subsys_initcall(tps6586x_init); 364 365static void __exit tps6586x_exit(void) 366{ 367 i2c_del_driver(&tps6586x_driver); 368} 369module_exit(tps6586x_exit); 370 371MODULE_DESCRIPTION("TPS6586X core driver"); 372MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); 373MODULE_LICENSE("GPL"); 374