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> 1927c6750eSGraeme Gregory #include <linux/slab.h> 2027c6750eSGraeme Gregory #include <linux/i2c.h> 2127c6750eSGraeme Gregory #include <linux/gpio.h> 2227c6750eSGraeme Gregory #include <linux/mfd/core.h> 2327c6750eSGraeme Gregory #include <linux/mfd/tps65910.h> 2427c6750eSGraeme Gregory 2527c6750eSGraeme Gregory static struct mfd_cell tps65910s[] = { 2627c6750eSGraeme Gregory { 2727c6750eSGraeme Gregory .name = "tps65910-pmic", 2827c6750eSGraeme Gregory }, 2927c6750eSGraeme Gregory { 3027c6750eSGraeme Gregory .name = "tps65910-rtc", 3127c6750eSGraeme Gregory }, 3227c6750eSGraeme Gregory { 3327c6750eSGraeme Gregory .name = "tps65910-power", 3427c6750eSGraeme Gregory }, 3527c6750eSGraeme Gregory }; 3627c6750eSGraeme Gregory 3727c6750eSGraeme Gregory 3827c6750eSGraeme Gregory static int tps65910_i2c_read(struct tps65910 *tps65910, u8 reg, 3927c6750eSGraeme Gregory int bytes, void *dest) 4027c6750eSGraeme Gregory { 4127c6750eSGraeme Gregory struct i2c_client *i2c = tps65910->i2c_client; 4227c6750eSGraeme Gregory struct i2c_msg xfer[2]; 4327c6750eSGraeme Gregory int ret; 4427c6750eSGraeme Gregory 4527c6750eSGraeme Gregory /* Write register */ 4627c6750eSGraeme Gregory xfer[0].addr = i2c->addr; 4727c6750eSGraeme Gregory xfer[0].flags = 0; 4827c6750eSGraeme Gregory xfer[0].len = 1; 4927c6750eSGraeme Gregory xfer[0].buf = ® 5027c6750eSGraeme Gregory 5127c6750eSGraeme Gregory /* Read data */ 5227c6750eSGraeme Gregory xfer[1].addr = i2c->addr; 5327c6750eSGraeme Gregory xfer[1].flags = I2C_M_RD; 5427c6750eSGraeme Gregory xfer[1].len = bytes; 5527c6750eSGraeme Gregory xfer[1].buf = dest; 5627c6750eSGraeme Gregory 5727c6750eSGraeme Gregory ret = i2c_transfer(i2c->adapter, xfer, 2); 5827c6750eSGraeme Gregory if (ret == 2) 5927c6750eSGraeme Gregory ret = 0; 6027c6750eSGraeme Gregory else if (ret >= 0) 6127c6750eSGraeme Gregory ret = -EIO; 6227c6750eSGraeme Gregory 6327c6750eSGraeme Gregory return ret; 6427c6750eSGraeme Gregory } 6527c6750eSGraeme Gregory 6627c6750eSGraeme Gregory static int tps65910_i2c_write(struct tps65910 *tps65910, u8 reg, 6727c6750eSGraeme Gregory int bytes, void *src) 6827c6750eSGraeme Gregory { 6927c6750eSGraeme Gregory struct i2c_client *i2c = tps65910->i2c_client; 7027c6750eSGraeme Gregory /* we add 1 byte for device register */ 7127c6750eSGraeme Gregory u8 msg[TPS65910_MAX_REGISTER + 1]; 7227c6750eSGraeme Gregory int ret; 7327c6750eSGraeme Gregory 7427c6750eSGraeme Gregory if (bytes > (TPS65910_MAX_REGISTER + 1)) 7527c6750eSGraeme Gregory return -EINVAL; 7627c6750eSGraeme Gregory 7727c6750eSGraeme Gregory msg[0] = reg; 7827c6750eSGraeme Gregory memcpy(&msg[1], src, bytes); 7927c6750eSGraeme Gregory 8027c6750eSGraeme Gregory ret = i2c_master_send(i2c, msg, bytes + 1); 8127c6750eSGraeme Gregory if (ret < 0) 8227c6750eSGraeme Gregory return ret; 8327c6750eSGraeme Gregory if (ret != bytes + 1) 8427c6750eSGraeme Gregory return -EIO; 8527c6750eSGraeme Gregory return 0; 8627c6750eSGraeme Gregory } 8727c6750eSGraeme Gregory 8827c6750eSGraeme Gregory int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask) 8927c6750eSGraeme Gregory { 9027c6750eSGraeme Gregory u8 data; 9127c6750eSGraeme Gregory int err; 9227c6750eSGraeme Gregory 9327c6750eSGraeme Gregory mutex_lock(&tps65910->io_mutex); 9427c6750eSGraeme Gregory err = tps65910_i2c_read(tps65910, reg, 1, &data); 9527c6750eSGraeme Gregory if (err) { 9627c6750eSGraeme Gregory dev_err(tps65910->dev, "read from reg %x failed\n", reg); 9727c6750eSGraeme Gregory goto out; 9827c6750eSGraeme Gregory } 9927c6750eSGraeme Gregory 10027c6750eSGraeme Gregory data |= mask; 10127c6750eSGraeme Gregory err = tps65910_i2c_write(tps65910, reg, 1, &data); 10227c6750eSGraeme Gregory if (err) 10327c6750eSGraeme Gregory dev_err(tps65910->dev, "write to reg %x failed\n", reg); 10427c6750eSGraeme Gregory 10527c6750eSGraeme Gregory out: 10627c6750eSGraeme Gregory mutex_unlock(&tps65910->io_mutex); 10727c6750eSGraeme Gregory return err; 10827c6750eSGraeme Gregory } 10927c6750eSGraeme Gregory EXPORT_SYMBOL_GPL(tps65910_set_bits); 11027c6750eSGraeme Gregory 11127c6750eSGraeme Gregory int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask) 11227c6750eSGraeme Gregory { 11327c6750eSGraeme Gregory u8 data; 11427c6750eSGraeme Gregory int err; 11527c6750eSGraeme Gregory 11627c6750eSGraeme Gregory mutex_lock(&tps65910->io_mutex); 11727c6750eSGraeme Gregory err = tps65910_i2c_read(tps65910, reg, 1, &data); 11827c6750eSGraeme Gregory if (err) { 11927c6750eSGraeme Gregory dev_err(tps65910->dev, "read from reg %x failed\n", reg); 12027c6750eSGraeme Gregory goto out; 12127c6750eSGraeme Gregory } 12227c6750eSGraeme Gregory 12327c6750eSGraeme Gregory data &= mask; 12427c6750eSGraeme Gregory err = tps65910_i2c_write(tps65910, reg, 1, &data); 12527c6750eSGraeme Gregory if (err) 12627c6750eSGraeme Gregory dev_err(tps65910->dev, "write to reg %x failed\n", reg); 12727c6750eSGraeme Gregory 12827c6750eSGraeme Gregory out: 12927c6750eSGraeme Gregory mutex_unlock(&tps65910->io_mutex); 13027c6750eSGraeme Gregory return err; 13127c6750eSGraeme Gregory } 13227c6750eSGraeme Gregory EXPORT_SYMBOL_GPL(tps65910_clear_bits); 13327c6750eSGraeme Gregory 13427c6750eSGraeme Gregory static int tps65910_i2c_probe(struct i2c_client *i2c, 13527c6750eSGraeme Gregory const struct i2c_device_id *id) 13627c6750eSGraeme Gregory { 13727c6750eSGraeme Gregory struct tps65910 *tps65910; 138*2537df72SGraeme Gregory struct tps65910_board *pmic_plat_data; 13927c6750eSGraeme Gregory int ret = 0; 14027c6750eSGraeme Gregory 141*2537df72SGraeme Gregory pmic_plat_data = dev_get_platdata(&i2c->dev); 142*2537df72SGraeme Gregory if (!pmic_plat_data) 143*2537df72SGraeme Gregory return -EINVAL; 144*2537df72SGraeme Gregory 14527c6750eSGraeme Gregory tps65910 = kzalloc(sizeof(struct tps65910), GFP_KERNEL); 14627c6750eSGraeme Gregory if (tps65910 == NULL) 14727c6750eSGraeme Gregory return -ENOMEM; 14827c6750eSGraeme Gregory 14927c6750eSGraeme Gregory i2c_set_clientdata(i2c, tps65910); 15027c6750eSGraeme Gregory tps65910->dev = &i2c->dev; 15127c6750eSGraeme Gregory tps65910->i2c_client = i2c; 15227c6750eSGraeme Gregory tps65910->read = tps65910_i2c_read; 15327c6750eSGraeme Gregory tps65910->write = tps65910_i2c_write; 15427c6750eSGraeme Gregory mutex_init(&tps65910->io_mutex); 15527c6750eSGraeme Gregory 15627c6750eSGraeme Gregory ret = mfd_add_devices(tps65910->dev, -1, 15727c6750eSGraeme Gregory tps65910s, ARRAY_SIZE(tps65910s), 15827c6750eSGraeme Gregory NULL, 0); 15927c6750eSGraeme Gregory if (ret < 0) 16027c6750eSGraeme Gregory goto err; 16127c6750eSGraeme Gregory 162*2537df72SGraeme Gregory tps65910_gpio_init(tps65910, pmic_plat_data->gpio_base); 163*2537df72SGraeme Gregory 16427c6750eSGraeme Gregory return ret; 16527c6750eSGraeme Gregory 16627c6750eSGraeme Gregory err: 16727c6750eSGraeme Gregory mfd_remove_devices(tps65910->dev); 16827c6750eSGraeme Gregory kfree(tps65910); 16927c6750eSGraeme Gregory return ret; 17027c6750eSGraeme Gregory } 17127c6750eSGraeme Gregory 17227c6750eSGraeme Gregory static int tps65910_i2c_remove(struct i2c_client *i2c) 17327c6750eSGraeme Gregory { 17427c6750eSGraeme Gregory struct tps65910 *tps65910 = i2c_get_clientdata(i2c); 17527c6750eSGraeme Gregory 17627c6750eSGraeme Gregory mfd_remove_devices(tps65910->dev); 17727c6750eSGraeme Gregory kfree(tps65910); 17827c6750eSGraeme Gregory 17927c6750eSGraeme Gregory return 0; 18027c6750eSGraeme Gregory } 18127c6750eSGraeme Gregory 18227c6750eSGraeme Gregory static const struct i2c_device_id tps65910_i2c_id[] = { 18327c6750eSGraeme Gregory { "tps65910", 0 }, 18427c6750eSGraeme Gregory { } 18527c6750eSGraeme Gregory }; 18627c6750eSGraeme Gregory MODULE_DEVICE_TABLE(i2c, tps65910_i2c_id); 18727c6750eSGraeme Gregory 18827c6750eSGraeme Gregory 18927c6750eSGraeme Gregory static struct i2c_driver tps65910_i2c_driver = { 19027c6750eSGraeme Gregory .driver = { 19127c6750eSGraeme Gregory .name = "tps65910", 19227c6750eSGraeme Gregory .owner = THIS_MODULE, 19327c6750eSGraeme Gregory }, 19427c6750eSGraeme Gregory .probe = tps65910_i2c_probe, 19527c6750eSGraeme Gregory .remove = tps65910_i2c_remove, 19627c6750eSGraeme Gregory .id_table = tps65910_i2c_id, 19727c6750eSGraeme Gregory }; 19827c6750eSGraeme Gregory 19927c6750eSGraeme Gregory static int __init tps65910_i2c_init(void) 20027c6750eSGraeme Gregory { 20127c6750eSGraeme Gregory return i2c_add_driver(&tps65910_i2c_driver); 20227c6750eSGraeme Gregory } 20327c6750eSGraeme Gregory /* init early so consumer devices can complete system boot */ 20427c6750eSGraeme Gregory subsys_initcall(tps65910_i2c_init); 20527c6750eSGraeme Gregory 20627c6750eSGraeme Gregory static void __exit tps65910_i2c_exit(void) 20727c6750eSGraeme Gregory { 20827c6750eSGraeme Gregory i2c_del_driver(&tps65910_i2c_driver); 20927c6750eSGraeme Gregory } 21027c6750eSGraeme Gregory module_exit(tps65910_i2c_exit); 21127c6750eSGraeme Gregory 21227c6750eSGraeme Gregory MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>"); 21327c6750eSGraeme Gregory MODULE_AUTHOR("Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>"); 21427c6750eSGraeme Gregory MODULE_DESCRIPTION("TPS6591x chip family multi-function driver"); 21527c6750eSGraeme Gregory MODULE_LICENSE("GPL"); 216