1/* 2 * linux/drivers/mfd/aat2870-core.c 3 * 4 * Copyright (c) 2011, NVIDIA Corporation. 5 * Author: Jin Park <jinyoungp@nvidia.com> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * version 2 as published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 19 * 02110-1301 USA 20 */ 21 22#include <linux/kernel.h> 23#include <linux/module.h> 24#include <linux/init.h> 25#include <linux/debugfs.h> 26#include <linux/slab.h> 27#include <linux/uaccess.h> 28#include <linux/i2c.h> 29#include <linux/delay.h> 30#include <linux/gpio.h> 31#include <linux/mfd/core.h> 32#include <linux/mfd/aat2870.h> 33#include <linux/regulator/machine.h> 34 35static struct aat2870_register aat2870_regs[AAT2870_REG_NUM] = { 36 /* readable, writeable, value */ 37 { 0, 1, 0x00 }, /* 0x00 AAT2870_BL_CH_EN */ 38 { 0, 1, 0x16 }, /* 0x01 AAT2870_BLM */ 39 { 0, 1, 0x16 }, /* 0x02 AAT2870_BLS */ 40 { 0, 1, 0x56 }, /* 0x03 AAT2870_BL1 */ 41 { 0, 1, 0x56 }, /* 0x04 AAT2870_BL2 */ 42 { 0, 1, 0x56 }, /* 0x05 AAT2870_BL3 */ 43 { 0, 1, 0x56 }, /* 0x06 AAT2870_BL4 */ 44 { 0, 1, 0x56 }, /* 0x07 AAT2870_BL5 */ 45 { 0, 1, 0x56 }, /* 0x08 AAT2870_BL6 */ 46 { 0, 1, 0x56 }, /* 0x09 AAT2870_BL7 */ 47 { 0, 1, 0x56 }, /* 0x0A AAT2870_BL8 */ 48 { 0, 1, 0x00 }, /* 0x0B AAT2870_FLR */ 49 { 0, 1, 0x03 }, /* 0x0C AAT2870_FM */ 50 { 0, 1, 0x03 }, /* 0x0D AAT2870_FS */ 51 { 0, 1, 0x10 }, /* 0x0E AAT2870_ALS_CFG0 */ 52 { 0, 1, 0x06 }, /* 0x0F AAT2870_ALS_CFG1 */ 53 { 0, 1, 0x00 }, /* 0x10 AAT2870_ALS_CFG2 */ 54 { 1, 0, 0x00 }, /* 0x11 AAT2870_AMB */ 55 { 0, 1, 0x00 }, /* 0x12 AAT2870_ALS0 */ 56 { 0, 1, 0x00 }, /* 0x13 AAT2870_ALS1 */ 57 { 0, 1, 0x00 }, /* 0x14 AAT2870_ALS2 */ 58 { 0, 1, 0x00 }, /* 0x15 AAT2870_ALS3 */ 59 { 0, 1, 0x00 }, /* 0x16 AAT2870_ALS4 */ 60 { 0, 1, 0x00 }, /* 0x17 AAT2870_ALS5 */ 61 { 0, 1, 0x00 }, /* 0x18 AAT2870_ALS6 */ 62 { 0, 1, 0x00 }, /* 0x19 AAT2870_ALS7 */ 63 { 0, 1, 0x00 }, /* 0x1A AAT2870_ALS8 */ 64 { 0, 1, 0x00 }, /* 0x1B AAT2870_ALS9 */ 65 { 0, 1, 0x00 }, /* 0x1C AAT2870_ALSA */ 66 { 0, 1, 0x00 }, /* 0x1D AAT2870_ALSB */ 67 { 0, 1, 0x00 }, /* 0x1E AAT2870_ALSC */ 68 { 0, 1, 0x00 }, /* 0x1F AAT2870_ALSD */ 69 { 0, 1, 0x00 }, /* 0x20 AAT2870_ALSE */ 70 { 0, 1, 0x00 }, /* 0x21 AAT2870_ALSF */ 71 { 0, 1, 0x00 }, /* 0x22 AAT2870_SUB_SET */ 72 { 0, 1, 0x00 }, /* 0x23 AAT2870_SUB_CTRL */ 73 { 0, 1, 0x00 }, /* 0x24 AAT2870_LDO_AB */ 74 { 0, 1, 0x00 }, /* 0x25 AAT2870_LDO_CD */ 75 { 0, 1, 0x00 }, /* 0x26 AAT2870_LDO_EN */ 76}; 77 78static struct mfd_cell aat2870_devs[] = { 79 { 80 .name = "aat2870-backlight", 81 .id = AAT2870_ID_BL, 82 .pdata_size = sizeof(struct aat2870_bl_platform_data), 83 }, 84 { 85 .name = "aat2870-regulator", 86 .id = AAT2870_ID_LDOA, 87 .pdata_size = sizeof(struct regulator_init_data), 88 }, 89 { 90 .name = "aat2870-regulator", 91 .id = AAT2870_ID_LDOB, 92 .pdata_size = sizeof(struct regulator_init_data), 93 }, 94 { 95 .name = "aat2870-regulator", 96 .id = AAT2870_ID_LDOC, 97 .pdata_size = sizeof(struct regulator_init_data), 98 }, 99 { 100 .name = "aat2870-regulator", 101 .id = AAT2870_ID_LDOD, 102 .pdata_size = sizeof(struct regulator_init_data), 103 }, 104}; 105 106static int __aat2870_read(struct aat2870_data *aat2870, u8 addr, u8 *val) 107{ 108 int ret; 109 110 if (addr >= AAT2870_REG_NUM) { 111 dev_err(aat2870->dev, "Invalid address, 0x%02x\n", addr); 112 return -EINVAL; 113 } 114 115 if (!aat2870->reg_cache[addr].readable) { 116 *val = aat2870->reg_cache[addr].value; 117 goto out; 118 } 119 120 ret = i2c_master_send(aat2870->client, &addr, 1); 121 if (ret < 0) 122 return ret; 123 if (ret != 1) 124 return -EIO; 125 126 ret = i2c_master_recv(aat2870->client, val, 1); 127 if (ret < 0) 128 return ret; 129 if (ret != 1) 130 return -EIO; 131 132out: 133 dev_dbg(aat2870->dev, "read: addr=0x%02x, val=0x%02x\n", addr, *val); 134 return 0; 135} 136 137static int __aat2870_write(struct aat2870_data *aat2870, u8 addr, u8 val) 138{ 139 u8 msg[2]; 140 int ret; 141 142 if (addr >= AAT2870_REG_NUM) { 143 dev_err(aat2870->dev, "Invalid address, 0x%02x\n", addr); 144 return -EINVAL; 145 } 146 147 if (!aat2870->reg_cache[addr].writeable) { 148 dev_err(aat2870->dev, "Address 0x%02x is not writeable\n", 149 addr); 150 return -EINVAL; 151 } 152 153 msg[0] = addr; 154 msg[1] = val; 155 ret = i2c_master_send(aat2870->client, msg, 2); 156 if (ret < 0) 157 return ret; 158 if (ret != 2) 159 return -EIO; 160 161 aat2870->reg_cache[addr].value = val; 162 163 dev_dbg(aat2870->dev, "write: addr=0x%02x, val=0x%02x\n", addr, val); 164 return 0; 165} 166 167static int aat2870_read(struct aat2870_data *aat2870, u8 addr, u8 *val) 168{ 169 int ret; 170 171 mutex_lock(&aat2870->io_lock); 172 ret = __aat2870_read(aat2870, addr, val); 173 mutex_unlock(&aat2870->io_lock); 174 175 return ret; 176} 177 178static int aat2870_write(struct aat2870_data *aat2870, u8 addr, u8 val) 179{ 180 int ret; 181 182 mutex_lock(&aat2870->io_lock); 183 ret = __aat2870_write(aat2870, addr, val); 184 mutex_unlock(&aat2870->io_lock); 185 186 return ret; 187} 188 189static int aat2870_update(struct aat2870_data *aat2870, u8 addr, u8 mask, 190 u8 val) 191{ 192 int change; 193 u8 old_val, new_val; 194 int ret; 195 196 mutex_lock(&aat2870->io_lock); 197 198 ret = __aat2870_read(aat2870, addr, &old_val); 199 if (ret) 200 goto out_unlock; 201 202 new_val = (old_val & ~mask) | (val & mask); 203 change = old_val != new_val; 204 if (change) 205 ret = __aat2870_write(aat2870, addr, new_val); 206 207out_unlock: 208 mutex_unlock(&aat2870->io_lock); 209 210 return ret; 211} 212 213static inline void aat2870_enable(struct aat2870_data *aat2870) 214{ 215 if (aat2870->en_pin >= 0) 216 gpio_set_value(aat2870->en_pin, 1); 217 218 aat2870->is_enable = 1; 219} 220 221static inline void aat2870_disable(struct aat2870_data *aat2870) 222{ 223 if (aat2870->en_pin >= 0) 224 gpio_set_value(aat2870->en_pin, 0); 225 226 aat2870->is_enable = 0; 227} 228 229#ifdef CONFIG_DEBUG_FS 230static ssize_t aat2870_dump_reg(struct aat2870_data *aat2870, char *buf) 231{ 232 u8 addr, val; 233 ssize_t count = 0; 234 int ret; 235 236 count += sprintf(buf, "aat2870 registers\n"); 237 for (addr = 0; addr < AAT2870_REG_NUM; addr++) { 238 count += sprintf(buf + count, "0x%02x: ", addr); 239 if (count >= PAGE_SIZE - 1) 240 break; 241 242 ret = aat2870->read(aat2870, addr, &val); 243 if (ret == 0) 244 count += snprintf(buf + count, PAGE_SIZE - count, 245 "0x%02x", val); 246 else 247 count += snprintf(buf + count, PAGE_SIZE - count, 248 "<read fail: %d>", ret); 249 250 if (count >= PAGE_SIZE - 1) 251 break; 252 253 count += snprintf(buf + count, PAGE_SIZE - count, "\n"); 254 if (count >= PAGE_SIZE - 1) 255 break; 256 } 257 258 /* Truncate count; min() would cause a warning */ 259 if (count >= PAGE_SIZE) 260 count = PAGE_SIZE - 1; 261 262 return count; 263} 264 265static ssize_t aat2870_reg_read_file(struct file *file, char __user *user_buf, 266 size_t count, loff_t *ppos) 267{ 268 struct aat2870_data *aat2870 = file->private_data; 269 char *buf; 270 ssize_t ret; 271 272 buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 273 if (!buf) 274 return -ENOMEM; 275 276 ret = aat2870_dump_reg(aat2870, buf); 277 if (ret >= 0) 278 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 279 280 kfree(buf); 281 282 return ret; 283} 284 285static ssize_t aat2870_reg_write_file(struct file *file, 286 const char __user *user_buf, size_t count, 287 loff_t *ppos) 288{ 289 struct aat2870_data *aat2870 = file->private_data; 290 char buf[32]; 291 ssize_t buf_size; 292 char *start = buf; 293 unsigned long addr, val; 294 int ret; 295 296 buf_size = min(count, (size_t)(sizeof(buf)-1)); 297 if (copy_from_user(buf, user_buf, buf_size)) { 298 dev_err(aat2870->dev, "Failed to copy from user\n"); 299 return -EFAULT; 300 } 301 buf[buf_size] = 0; 302 303 while (*start == ' ') 304 start++; 305 306 ret = kstrtoul(start, 16, &addr); 307 if (ret) 308 return ret; 309 310 if (addr >= AAT2870_REG_NUM) { 311 dev_err(aat2870->dev, "Invalid address, 0x%lx\n", addr); 312 return -EINVAL; 313 } 314 315 while (*start == ' ') 316 start++; 317 318 ret = kstrtoul(start, 16, &val); 319 if (ret) 320 return ret; 321 322 ret = aat2870->write(aat2870, (u8)addr, (u8)val); 323 if (ret) 324 return ret; 325 326 return buf_size; 327} 328 329static const struct file_operations aat2870_reg_fops = { 330 .open = simple_open, 331 .read = aat2870_reg_read_file, 332 .write = aat2870_reg_write_file, 333}; 334 335static void aat2870_init_debugfs(struct aat2870_data *aat2870) 336{ 337 aat2870->dentry_root = debugfs_create_dir("aat2870", NULL); 338 if (!aat2870->dentry_root) { 339 dev_warn(aat2870->dev, 340 "Failed to create debugfs root directory\n"); 341 return; 342 } 343 344 aat2870->dentry_reg = debugfs_create_file("regs", 0644, 345 aat2870->dentry_root, 346 aat2870, &aat2870_reg_fops); 347 if (!aat2870->dentry_reg) 348 dev_warn(aat2870->dev, 349 "Failed to create debugfs register file\n"); 350} 351 352static void aat2870_uninit_debugfs(struct aat2870_data *aat2870) 353{ 354 debugfs_remove_recursive(aat2870->dentry_root); 355} 356#else 357static inline void aat2870_init_debugfs(struct aat2870_data *aat2870) 358{ 359} 360 361static inline void aat2870_uninit_debugfs(struct aat2870_data *aat2870) 362{ 363} 364#endif /* CONFIG_DEBUG_FS */ 365 366static int aat2870_i2c_probe(struct i2c_client *client, 367 const struct i2c_device_id *id) 368{ 369 struct aat2870_platform_data *pdata = dev_get_platdata(&client->dev); 370 struct aat2870_data *aat2870; 371 int i, j; 372 int ret = 0; 373 374 aat2870 = devm_kzalloc(&client->dev, sizeof(struct aat2870_data), 375 GFP_KERNEL); 376 if (!aat2870) { 377 dev_err(&client->dev, 378 "Failed to allocate memory for aat2870\n"); 379 return -ENOMEM; 380 } 381 382 aat2870->dev = &client->dev; 383 dev_set_drvdata(aat2870->dev, aat2870); 384 385 aat2870->client = client; 386 i2c_set_clientdata(client, aat2870); 387 388 aat2870->reg_cache = aat2870_regs; 389 390 if (pdata->en_pin < 0) 391 aat2870->en_pin = -1; 392 else 393 aat2870->en_pin = pdata->en_pin; 394 395 aat2870->init = pdata->init; 396 aat2870->uninit = pdata->uninit; 397 aat2870->read = aat2870_read; 398 aat2870->write = aat2870_write; 399 aat2870->update = aat2870_update; 400 401 mutex_init(&aat2870->io_lock); 402 403 if (aat2870->init) 404 aat2870->init(aat2870); 405 406 if (aat2870->en_pin >= 0) { 407 ret = devm_gpio_request_one(&client->dev, aat2870->en_pin, 408 GPIOF_OUT_INIT_HIGH, "aat2870-en"); 409 if (ret < 0) { 410 dev_err(&client->dev, 411 "Failed to request GPIO %d\n", aat2870->en_pin); 412 return ret; 413 } 414 } 415 416 aat2870_enable(aat2870); 417 418 for (i = 0; i < pdata->num_subdevs; i++) { 419 for (j = 0; j < ARRAY_SIZE(aat2870_devs); j++) { 420 if ((pdata->subdevs[i].id == aat2870_devs[j].id) && 421 !strcmp(pdata->subdevs[i].name, 422 aat2870_devs[j].name)) { 423 aat2870_devs[j].platform_data = 424 pdata->subdevs[i].platform_data; 425 break; 426 } 427 } 428 } 429 430 ret = mfd_add_devices(aat2870->dev, 0, aat2870_devs, 431 ARRAY_SIZE(aat2870_devs), NULL, 0, NULL); 432 if (ret != 0) { 433 dev_err(aat2870->dev, "Failed to add subdev: %d\n", ret); 434 goto out_disable; 435 } 436 437 aat2870_init_debugfs(aat2870); 438 439 return 0; 440 441out_disable: 442 aat2870_disable(aat2870); 443 return ret; 444} 445 446static int aat2870_i2c_remove(struct i2c_client *client) 447{ 448 struct aat2870_data *aat2870 = i2c_get_clientdata(client); 449 450 aat2870_uninit_debugfs(aat2870); 451 452 mfd_remove_devices(aat2870->dev); 453 aat2870_disable(aat2870); 454 if (aat2870->uninit) 455 aat2870->uninit(aat2870); 456 457 return 0; 458} 459 460#ifdef CONFIG_PM_SLEEP 461static int aat2870_i2c_suspend(struct device *dev) 462{ 463 struct i2c_client *client = to_i2c_client(dev); 464 struct aat2870_data *aat2870 = i2c_get_clientdata(client); 465 466 aat2870_disable(aat2870); 467 468 return 0; 469} 470 471static int aat2870_i2c_resume(struct device *dev) 472{ 473 struct i2c_client *client = to_i2c_client(dev); 474 struct aat2870_data *aat2870 = i2c_get_clientdata(client); 475 struct aat2870_register *reg = NULL; 476 int i; 477 478 aat2870_enable(aat2870); 479 480 /* restore registers */ 481 for (i = 0; i < AAT2870_REG_NUM; i++) { 482 reg = &aat2870->reg_cache[i]; 483 if (reg->writeable) 484 aat2870->write(aat2870, i, reg->value); 485 } 486 487 return 0; 488} 489#endif /* CONFIG_PM_SLEEP */ 490 491static SIMPLE_DEV_PM_OPS(aat2870_pm_ops, aat2870_i2c_suspend, 492 aat2870_i2c_resume); 493 494static const struct i2c_device_id aat2870_i2c_id_table[] = { 495 { "aat2870", 0 }, 496 { } 497}; 498MODULE_DEVICE_TABLE(i2c, aat2870_i2c_id_table); 499 500static struct i2c_driver aat2870_i2c_driver = { 501 .driver = { 502 .name = "aat2870", 503 .pm = &aat2870_pm_ops, 504 }, 505 .probe = aat2870_i2c_probe, 506 .remove = aat2870_i2c_remove, 507 .id_table = aat2870_i2c_id_table, 508}; 509 510static int __init aat2870_init(void) 511{ 512 return i2c_add_driver(&aat2870_i2c_driver); 513} 514subsys_initcall(aat2870_init); 515 516static void __exit aat2870_exit(void) 517{ 518 i2c_del_driver(&aat2870_i2c_driver); 519} 520module_exit(aat2870_exit); 521 522MODULE_DESCRIPTION("Core support for the AnalogicTech AAT2870"); 523MODULE_LICENSE("GPL"); 524MODULE_AUTHOR("Jin Park <jinyoungp@nvidia.com>"); 525