1 /* 2 * tps65910.c -- TI TPS6591x 3 * 4 * Copyright 2010 Texas Instruments Inc. 5 * 6 * Author: Graeme Gregory <gg@slimlogic.co.uk> 7 * Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk> 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the 11 * Free Software Foundation; either version 2 of the License, or (at your 12 * option) any later version. 13 * 14 */ 15 16 #include <linux/module.h> 17 #include <linux/moduleparam.h> 18 #include <linux/init.h> 19 #include <linux/slab.h> 20 #include <linux/i2c.h> 21 #include <linux/gpio.h> 22 #include <linux/mfd/core.h> 23 #include <linux/mfd/tps65910.h> 24 25 static struct mfd_cell tps65910s[] = { 26 { 27 .name = "tps65910-pmic", 28 }, 29 { 30 .name = "tps65910-rtc", 31 }, 32 { 33 .name = "tps65910-power", 34 }, 35 }; 36 37 38 static int tps65910_i2c_read(struct tps65910 *tps65910, u8 reg, 39 int bytes, void *dest) 40 { 41 struct i2c_client *i2c = tps65910->i2c_client; 42 struct i2c_msg xfer[2]; 43 int ret; 44 45 /* Write register */ 46 xfer[0].addr = i2c->addr; 47 xfer[0].flags = 0; 48 xfer[0].len = 1; 49 xfer[0].buf = ® 50 51 /* Read data */ 52 xfer[1].addr = i2c->addr; 53 xfer[1].flags = I2C_M_RD; 54 xfer[1].len = bytes; 55 xfer[1].buf = dest; 56 57 ret = i2c_transfer(i2c->adapter, xfer, 2); 58 if (ret == 2) 59 ret = 0; 60 else if (ret >= 0) 61 ret = -EIO; 62 63 return ret; 64 } 65 66 static int tps65910_i2c_write(struct tps65910 *tps65910, u8 reg, 67 int bytes, void *src) 68 { 69 struct i2c_client *i2c = tps65910->i2c_client; 70 /* we add 1 byte for device register */ 71 u8 msg[TPS65910_MAX_REGISTER + 1]; 72 int ret; 73 74 if (bytes > TPS65910_MAX_REGISTER) 75 return -EINVAL; 76 77 msg[0] = reg; 78 memcpy(&msg[1], src, bytes); 79 80 ret = i2c_master_send(i2c, msg, bytes + 1); 81 if (ret < 0) 82 return ret; 83 if (ret != bytes + 1) 84 return -EIO; 85 return 0; 86 } 87 88 int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask) 89 { 90 u8 data; 91 int err; 92 93 mutex_lock(&tps65910->io_mutex); 94 err = tps65910_i2c_read(tps65910, reg, 1, &data); 95 if (err) { 96 dev_err(tps65910->dev, "read from reg %x failed\n", reg); 97 goto out; 98 } 99 100 data |= mask; 101 err = tps65910_i2c_write(tps65910, reg, 1, &data); 102 if (err) 103 dev_err(tps65910->dev, "write to reg %x failed\n", reg); 104 105 out: 106 mutex_unlock(&tps65910->io_mutex); 107 return err; 108 } 109 EXPORT_SYMBOL_GPL(tps65910_set_bits); 110 111 int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask) 112 { 113 u8 data; 114 int err; 115 116 mutex_lock(&tps65910->io_mutex); 117 err = tps65910_i2c_read(tps65910, reg, 1, &data); 118 if (err) { 119 dev_err(tps65910->dev, "read from reg %x failed\n", reg); 120 goto out; 121 } 122 123 data &= mask; 124 err = tps65910_i2c_write(tps65910, reg, 1, &data); 125 if (err) 126 dev_err(tps65910->dev, "write to reg %x failed\n", reg); 127 128 out: 129 mutex_unlock(&tps65910->io_mutex); 130 return err; 131 } 132 EXPORT_SYMBOL_GPL(tps65910_clear_bits); 133 134 static int tps65910_i2c_probe(struct i2c_client *i2c, 135 const struct i2c_device_id *id) 136 { 137 struct tps65910 *tps65910; 138 struct tps65910_board *pmic_plat_data; 139 struct tps65910_platform_data *init_data; 140 int ret = 0; 141 142 pmic_plat_data = dev_get_platdata(&i2c->dev); 143 if (!pmic_plat_data) 144 return -EINVAL; 145 146 init_data = kzalloc(sizeof(struct tps65910_platform_data), GFP_KERNEL); 147 if (init_data == NULL) 148 return -ENOMEM; 149 150 tps65910 = kzalloc(sizeof(struct tps65910), GFP_KERNEL); 151 if (tps65910 == NULL) { 152 kfree(init_data); 153 return -ENOMEM; 154 } 155 156 i2c_set_clientdata(i2c, tps65910); 157 tps65910->dev = &i2c->dev; 158 tps65910->i2c_client = i2c; 159 tps65910->id = id->driver_data; 160 tps65910->read = tps65910_i2c_read; 161 tps65910->write = tps65910_i2c_write; 162 mutex_init(&tps65910->io_mutex); 163 164 ret = mfd_add_devices(tps65910->dev, -1, 165 tps65910s, ARRAY_SIZE(tps65910s), 166 NULL, 0); 167 if (ret < 0) 168 goto err; 169 170 init_data->irq = pmic_plat_data->irq; 171 init_data->irq_base = pmic_plat_data->irq; 172 173 tps65910_gpio_init(tps65910, pmic_plat_data->gpio_base); 174 175 ret = tps65910_irq_init(tps65910, init_data->irq, init_data); 176 if (ret < 0) 177 goto err; 178 179 kfree(init_data); 180 return ret; 181 182 err: 183 mfd_remove_devices(tps65910->dev); 184 kfree(tps65910); 185 kfree(init_data); 186 return ret; 187 } 188 189 static int tps65910_i2c_remove(struct i2c_client *i2c) 190 { 191 struct tps65910 *tps65910 = i2c_get_clientdata(i2c); 192 193 mfd_remove_devices(tps65910->dev); 194 tps65910_irq_exit(tps65910); 195 kfree(tps65910); 196 197 return 0; 198 } 199 200 static const struct i2c_device_id tps65910_i2c_id[] = { 201 { "tps65910", TPS65910 }, 202 { "tps65911", TPS65911 }, 203 { } 204 }; 205 MODULE_DEVICE_TABLE(i2c, tps65910_i2c_id); 206 207 208 static struct i2c_driver tps65910_i2c_driver = { 209 .driver = { 210 .name = "tps65910", 211 .owner = THIS_MODULE, 212 }, 213 .probe = tps65910_i2c_probe, 214 .remove = tps65910_i2c_remove, 215 .id_table = tps65910_i2c_id, 216 }; 217 218 static int __init tps65910_i2c_init(void) 219 { 220 return i2c_add_driver(&tps65910_i2c_driver); 221 } 222 /* init early so consumer devices can complete system boot */ 223 subsys_initcall(tps65910_i2c_init); 224 225 static void __exit tps65910_i2c_exit(void) 226 { 227 i2c_del_driver(&tps65910_i2c_driver); 228 } 229 module_exit(tps65910_i2c_exit); 230 231 MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>"); 232 MODULE_AUTHOR("Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>"); 233 MODULE_DESCRIPTION("TPS6591x chip family multi-function driver"); 234 MODULE_LICENSE("GPL"); 235