127c6750eSGraeme Gregory /* 227c6750eSGraeme Gregory * tps65910.c -- TI TPS6591x 327c6750eSGraeme Gregory * 427c6750eSGraeme Gregory * Copyright 2010 Texas Instruments Inc. 527c6750eSGraeme Gregory * 627c6750eSGraeme Gregory * Author: Graeme Gregory <gg@slimlogic.co.uk> 727c6750eSGraeme Gregory * Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk> 827c6750eSGraeme Gregory * 927c6750eSGraeme Gregory * This program is free software; you can redistribute it and/or modify it 1027c6750eSGraeme Gregory * under the terms of the GNU General Public License as published by the 1127c6750eSGraeme Gregory * Free Software Foundation; either version 2 of the License, or (at your 1227c6750eSGraeme Gregory * option) any later version. 1327c6750eSGraeme Gregory * 1427c6750eSGraeme Gregory */ 1527c6750eSGraeme Gregory 1627c6750eSGraeme Gregory #include <linux/module.h> 1727c6750eSGraeme Gregory #include <linux/moduleparam.h> 1827c6750eSGraeme Gregory #include <linux/init.h> 19*dc9913a0SLaxman Dewangan #include <linux/err.h> 2027c6750eSGraeme Gregory #include <linux/slab.h> 2127c6750eSGraeme Gregory #include <linux/i2c.h> 2227c6750eSGraeme Gregory #include <linux/gpio.h> 2327c6750eSGraeme Gregory #include <linux/mfd/core.h> 24*dc9913a0SLaxman Dewangan #include <linux/regmap.h> 2527c6750eSGraeme Gregory #include <linux/mfd/tps65910.h> 2627c6750eSGraeme Gregory 2727c6750eSGraeme Gregory static struct mfd_cell tps65910s[] = { 2827c6750eSGraeme Gregory { 2927c6750eSGraeme Gregory .name = "tps65910-pmic", 3027c6750eSGraeme Gregory }, 3127c6750eSGraeme Gregory { 3227c6750eSGraeme Gregory .name = "tps65910-rtc", 3327c6750eSGraeme Gregory }, 3427c6750eSGraeme Gregory { 3527c6750eSGraeme Gregory .name = "tps65910-power", 3627c6750eSGraeme Gregory }, 3727c6750eSGraeme Gregory }; 3827c6750eSGraeme Gregory 3927c6750eSGraeme Gregory 4027c6750eSGraeme Gregory static int tps65910_i2c_read(struct tps65910 *tps65910, u8 reg, 4127c6750eSGraeme Gregory int bytes, void *dest) 4227c6750eSGraeme Gregory { 43*dc9913a0SLaxman Dewangan return regmap_bulk_read(tps65910->regmap, reg, dest, bytes); 4427c6750eSGraeme Gregory } 4527c6750eSGraeme Gregory 4627c6750eSGraeme Gregory static int tps65910_i2c_write(struct tps65910 *tps65910, u8 reg, 4727c6750eSGraeme Gregory int bytes, void *src) 4827c6750eSGraeme Gregory { 49*dc9913a0SLaxman Dewangan return regmap_bulk_write(tps65910->regmap, reg, src, bytes); 5027c6750eSGraeme Gregory } 5127c6750eSGraeme Gregory 5227c6750eSGraeme Gregory int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask) 5327c6750eSGraeme Gregory { 54*dc9913a0SLaxman Dewangan return regmap_update_bits(tps65910->regmap, reg, mask, mask); 5527c6750eSGraeme Gregory } 5627c6750eSGraeme Gregory EXPORT_SYMBOL_GPL(tps65910_set_bits); 5727c6750eSGraeme Gregory 5827c6750eSGraeme Gregory int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask) 5927c6750eSGraeme Gregory { 60*dc9913a0SLaxman Dewangan return regmap_update_bits(tps65910->regmap, reg, mask, 0); 6127c6750eSGraeme Gregory } 6227c6750eSGraeme Gregory EXPORT_SYMBOL_GPL(tps65910_clear_bits); 6327c6750eSGraeme Gregory 64*dc9913a0SLaxman Dewangan static bool is_volatile_reg(struct device *dev, unsigned int reg) 65*dc9913a0SLaxman Dewangan { 66*dc9913a0SLaxman Dewangan struct tps65910 *tps65910 = dev_get_drvdata(dev); 67*dc9913a0SLaxman Dewangan 68*dc9913a0SLaxman Dewangan /* 69*dc9913a0SLaxman Dewangan * Caching all regulator registers. 70*dc9913a0SLaxman Dewangan * All regualator register address range is same for 71*dc9913a0SLaxman Dewangan * TPS65910 and TPS65911 72*dc9913a0SLaxman Dewangan */ 73*dc9913a0SLaxman Dewangan if ((reg >= TPS65910_VIO) && (reg <= TPS65910_VDAC)) { 74*dc9913a0SLaxman Dewangan /* Check for non-existing register */ 75*dc9913a0SLaxman Dewangan if (tps65910_chip_id(tps65910) == TPS65910) 76*dc9913a0SLaxman Dewangan if ((reg == TPS65911_VDDCTRL_OP) || 77*dc9913a0SLaxman Dewangan (reg == TPS65911_VDDCTRL_SR)) 78*dc9913a0SLaxman Dewangan return true; 79*dc9913a0SLaxman Dewangan return false; 80*dc9913a0SLaxman Dewangan } 81*dc9913a0SLaxman Dewangan return true; 82*dc9913a0SLaxman Dewangan } 83*dc9913a0SLaxman Dewangan 84*dc9913a0SLaxman Dewangan static const struct regmap_config rc5t583_regmap_config = { 85*dc9913a0SLaxman Dewangan .reg_bits = 8, 86*dc9913a0SLaxman Dewangan .val_bits = 8, 87*dc9913a0SLaxman Dewangan .volatile_reg = is_volatile_reg, 88*dc9913a0SLaxman Dewangan .max_register = TPS65910_MAX_REGISTER, 89*dc9913a0SLaxman Dewangan .num_reg_defaults_raw = TPS65910_MAX_REGISTER, 90*dc9913a0SLaxman Dewangan .cache_type = REGCACHE_RBTREE, 91*dc9913a0SLaxman Dewangan }; 92*dc9913a0SLaxman Dewangan 9327c6750eSGraeme Gregory static int tps65910_i2c_probe(struct i2c_client *i2c, 9427c6750eSGraeme Gregory const struct i2c_device_id *id) 9527c6750eSGraeme Gregory { 9627c6750eSGraeme Gregory struct tps65910 *tps65910; 972537df72SGraeme Gregory struct tps65910_board *pmic_plat_data; 98e3471bdcSGraeme Gregory struct tps65910_platform_data *init_data; 9927c6750eSGraeme Gregory int ret = 0; 10027c6750eSGraeme Gregory 1012537df72SGraeme Gregory pmic_plat_data = dev_get_platdata(&i2c->dev); 1022537df72SGraeme Gregory if (!pmic_plat_data) 1032537df72SGraeme Gregory return -EINVAL; 1042537df72SGraeme Gregory 105e3471bdcSGraeme Gregory init_data = kzalloc(sizeof(struct tps65910_platform_data), GFP_KERNEL); 106e3471bdcSGraeme Gregory if (init_data == NULL) 107e3471bdcSGraeme Gregory return -ENOMEM; 108e3471bdcSGraeme Gregory 10927c6750eSGraeme Gregory tps65910 = kzalloc(sizeof(struct tps65910), GFP_KERNEL); 110dc7e412dSJesper Juhl if (tps65910 == NULL) { 111dc7e412dSJesper Juhl kfree(init_data); 11227c6750eSGraeme Gregory return -ENOMEM; 113dc7e412dSJesper Juhl } 11427c6750eSGraeme Gregory 11527c6750eSGraeme Gregory i2c_set_clientdata(i2c, tps65910); 11627c6750eSGraeme Gregory tps65910->dev = &i2c->dev; 11727c6750eSGraeme Gregory tps65910->i2c_client = i2c; 11879557056SJorge Eduardo Candelaria tps65910->id = id->driver_data; 11927c6750eSGraeme Gregory tps65910->read = tps65910_i2c_read; 12027c6750eSGraeme Gregory tps65910->write = tps65910_i2c_write; 12127c6750eSGraeme Gregory mutex_init(&tps65910->io_mutex); 12227c6750eSGraeme Gregory 123*dc9913a0SLaxman Dewangan tps65910->regmap = regmap_init_i2c(i2c, &rc5t583_regmap_config); 124*dc9913a0SLaxman Dewangan if (IS_ERR(tps65910->regmap)) { 125*dc9913a0SLaxman Dewangan ret = PTR_ERR(tps65910->regmap); 126*dc9913a0SLaxman Dewangan dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret); 127*dc9913a0SLaxman Dewangan goto regmap_err; 128*dc9913a0SLaxman Dewangan } 129*dc9913a0SLaxman Dewangan 13027c6750eSGraeme Gregory ret = mfd_add_devices(tps65910->dev, -1, 13127c6750eSGraeme Gregory tps65910s, ARRAY_SIZE(tps65910s), 13227c6750eSGraeme Gregory NULL, 0); 13327c6750eSGraeme Gregory if (ret < 0) 13427c6750eSGraeme Gregory goto err; 13527c6750eSGraeme Gregory 136b1224cd1SJesper Juhl init_data->irq = pmic_plat_data->irq; 1371773140fSLaxman Dewangan init_data->irq_base = pmic_plat_data->irq_base; 138b1224cd1SJesper Juhl 1392537df72SGraeme Gregory tps65910_gpio_init(tps65910, pmic_plat_data->gpio_base); 1402537df72SGraeme Gregory 1411e351a95SAfzal Mohammed tps65910_irq_init(tps65910, init_data->irq, init_data); 142e3471bdcSGraeme Gregory 143dc7e412dSJesper Juhl kfree(init_data); 14427c6750eSGraeme Gregory return ret; 14527c6750eSGraeme Gregory 14627c6750eSGraeme Gregory err: 147*dc9913a0SLaxman Dewangan regmap_exit(tps65910->regmap); 148*dc9913a0SLaxman Dewangan regmap_err: 14927c6750eSGraeme Gregory kfree(tps65910); 150dc7e412dSJesper Juhl kfree(init_data); 15127c6750eSGraeme Gregory return ret; 15227c6750eSGraeme Gregory } 15327c6750eSGraeme Gregory 15427c6750eSGraeme Gregory static int tps65910_i2c_remove(struct i2c_client *i2c) 15527c6750eSGraeme Gregory { 15627c6750eSGraeme Gregory struct tps65910 *tps65910 = i2c_get_clientdata(i2c); 15727c6750eSGraeme Gregory 158ec2328c3SMark Brown tps65910_irq_exit(tps65910); 1591e351a95SAfzal Mohammed mfd_remove_devices(tps65910->dev); 160*dc9913a0SLaxman Dewangan regmap_exit(tps65910->regmap); 16127c6750eSGraeme Gregory kfree(tps65910); 16227c6750eSGraeme Gregory 16327c6750eSGraeme Gregory return 0; 16427c6750eSGraeme Gregory } 16527c6750eSGraeme Gregory 16627c6750eSGraeme Gregory static const struct i2c_device_id tps65910_i2c_id[] = { 16779557056SJorge Eduardo Candelaria { "tps65910", TPS65910 }, 16879557056SJorge Eduardo Candelaria { "tps65911", TPS65911 }, 16927c6750eSGraeme Gregory { } 17027c6750eSGraeme Gregory }; 17127c6750eSGraeme Gregory MODULE_DEVICE_TABLE(i2c, tps65910_i2c_id); 17227c6750eSGraeme Gregory 17327c6750eSGraeme Gregory 17427c6750eSGraeme Gregory static struct i2c_driver tps65910_i2c_driver = { 17527c6750eSGraeme Gregory .driver = { 17627c6750eSGraeme Gregory .name = "tps65910", 17727c6750eSGraeme Gregory .owner = THIS_MODULE, 17827c6750eSGraeme Gregory }, 17927c6750eSGraeme Gregory .probe = tps65910_i2c_probe, 18027c6750eSGraeme Gregory .remove = tps65910_i2c_remove, 18127c6750eSGraeme Gregory .id_table = tps65910_i2c_id, 18227c6750eSGraeme Gregory }; 18327c6750eSGraeme Gregory 18427c6750eSGraeme Gregory static int __init tps65910_i2c_init(void) 18527c6750eSGraeme Gregory { 18627c6750eSGraeme Gregory return i2c_add_driver(&tps65910_i2c_driver); 18727c6750eSGraeme Gregory } 18827c6750eSGraeme Gregory /* init early so consumer devices can complete system boot */ 18927c6750eSGraeme Gregory subsys_initcall(tps65910_i2c_init); 19027c6750eSGraeme Gregory 19127c6750eSGraeme Gregory static void __exit tps65910_i2c_exit(void) 19227c6750eSGraeme Gregory { 19327c6750eSGraeme Gregory i2c_del_driver(&tps65910_i2c_driver); 19427c6750eSGraeme Gregory } 19527c6750eSGraeme Gregory module_exit(tps65910_i2c_exit); 19627c6750eSGraeme Gregory 19727c6750eSGraeme Gregory MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>"); 19827c6750eSGraeme Gregory MODULE_AUTHOR("Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>"); 19927c6750eSGraeme Gregory MODULE_DESCRIPTION("TPS6591x chip family multi-function driver"); 20027c6750eSGraeme Gregory MODULE_LICENSE("GPL"); 201