1/* 2 * tps65217.c 3 * 4 * TPS65217 chip family multi-function driver 5 * 6 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation version 2. 11 * 12 * This program is distributed "as is" WITHOUT ANY WARRANTY of any 13 * kind, whether express or implied; without even the implied warranty 14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 */ 17 18#include <linux/kernel.h> 19#include <linux/device.h> 20#include <linux/module.h> 21#include <linux/platform_device.h> 22#include <linux/init.h> 23#include <linux/i2c.h> 24#include <linux/slab.h> 25#include <linux/regmap.h> 26#include <linux/err.h> 27#include <linux/of.h> 28#include <linux/of_device.h> 29 30#include <linux/mfd/core.h> 31#include <linux/mfd/tps65217.h> 32 33static const struct mfd_cell tps65217s[] = { 34 { 35 .name = "tps65217-pmic", 36 .of_compatible = "ti,tps65217-pmic", 37 }, 38 { 39 .name = "tps65217-bl", 40 .of_compatible = "ti,tps65217-bl", 41 }, 42 { 43 .name = "tps65217-charger", 44 .of_compatible = "ti,tps65217-charger", 45 }, 46}; 47 48/** 49 * tps65217_reg_read: Read a single tps65217 register. 50 * 51 * @tps: Device to read from. 52 * @reg: Register to read. 53 * @val: Contians the value 54 */ 55int tps65217_reg_read(struct tps65217 *tps, unsigned int reg, 56 unsigned int *val) 57{ 58 return regmap_read(tps->regmap, reg, val); 59} 60EXPORT_SYMBOL_GPL(tps65217_reg_read); 61 62/** 63 * tps65217_reg_write: Write a single tps65217 register. 64 * 65 * @tps65217: Device to write to. 66 * @reg: Register to write to. 67 * @val: Value to write. 68 * @level: Password protected level 69 */ 70int tps65217_reg_write(struct tps65217 *tps, unsigned int reg, 71 unsigned int val, unsigned int level) 72{ 73 int ret; 74 unsigned int xor_reg_val; 75 76 switch (level) { 77 case TPS65217_PROTECT_NONE: 78 return regmap_write(tps->regmap, reg, val); 79 case TPS65217_PROTECT_L1: 80 xor_reg_val = reg ^ TPS65217_PASSWORD_REGS_UNLOCK; 81 ret = regmap_write(tps->regmap, TPS65217_REG_PASSWORD, 82 xor_reg_val); 83 if (ret < 0) 84 return ret; 85 86 return regmap_write(tps->regmap, reg, val); 87 case TPS65217_PROTECT_L2: 88 xor_reg_val = reg ^ TPS65217_PASSWORD_REGS_UNLOCK; 89 ret = regmap_write(tps->regmap, TPS65217_REG_PASSWORD, 90 xor_reg_val); 91 if (ret < 0) 92 return ret; 93 ret = regmap_write(tps->regmap, reg, val); 94 if (ret < 0) 95 return ret; 96 ret = regmap_write(tps->regmap, TPS65217_REG_PASSWORD, 97 xor_reg_val); 98 if (ret < 0) 99 return ret; 100 return regmap_write(tps->regmap, reg, val); 101 default: 102 return -EINVAL; 103 } 104} 105EXPORT_SYMBOL_GPL(tps65217_reg_write); 106 107/** 108 * tps65217_update_bits: Modify bits w.r.t mask, val and level. 109 * 110 * @tps65217: Device to write to. 111 * @reg: Register to read-write to. 112 * @mask: Mask. 113 * @val: Value to write. 114 * @level: Password protected level 115 */ 116static int tps65217_update_bits(struct tps65217 *tps, unsigned int reg, 117 unsigned int mask, unsigned int val, unsigned int level) 118{ 119 int ret; 120 unsigned int data; 121 122 ret = tps65217_reg_read(tps, reg, &data); 123 if (ret) { 124 dev_err(tps->dev, "Read from reg 0x%x failed\n", reg); 125 return ret; 126 } 127 128 data &= ~mask; 129 data |= val & mask; 130 131 ret = tps65217_reg_write(tps, reg, data, level); 132 if (ret) 133 dev_err(tps->dev, "Write for reg 0x%x failed\n", reg); 134 135 return ret; 136} 137 138int tps65217_set_bits(struct tps65217 *tps, unsigned int reg, 139 unsigned int mask, unsigned int val, unsigned int level) 140{ 141 return tps65217_update_bits(tps, reg, mask, val, level); 142} 143EXPORT_SYMBOL_GPL(tps65217_set_bits); 144 145int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg, 146 unsigned int mask, unsigned int level) 147{ 148 return tps65217_update_bits(tps, reg, mask, 0, level); 149} 150EXPORT_SYMBOL_GPL(tps65217_clear_bits); 151 152static const struct regmap_config tps65217_regmap_config = { 153 .reg_bits = 8, 154 .val_bits = 8, 155 156 .max_register = TPS65217_REG_MAX, 157}; 158 159static const struct of_device_id tps65217_of_match[] = { 160 { .compatible = "ti,tps65217", .data = (void *)TPS65217 }, 161 { /* sentinel */ }, 162}; 163MODULE_DEVICE_TABLE(of, tps65217_of_match); 164 165static int tps65217_probe(struct i2c_client *client, 166 const struct i2c_device_id *ids) 167{ 168 struct tps65217 *tps; 169 unsigned int version; 170 unsigned long chip_id = ids->driver_data; 171 const struct of_device_id *match; 172 bool status_off = false; 173 int ret; 174 175 if (client->dev.of_node) { 176 match = of_match_device(tps65217_of_match, &client->dev); 177 if (!match) { 178 dev_err(&client->dev, 179 "Failed to find matching dt id\n"); 180 return -EINVAL; 181 } 182 chip_id = (unsigned long)match->data; 183 status_off = of_property_read_bool(client->dev.of_node, 184 "ti,pmic-shutdown-controller"); 185 } 186 187 if (!chip_id) { 188 dev_err(&client->dev, "id is null.\n"); 189 return -ENODEV; 190 } 191 192 tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); 193 if (!tps) 194 return -ENOMEM; 195 196 i2c_set_clientdata(client, tps); 197 tps->dev = &client->dev; 198 tps->id = chip_id; 199 200 tps->regmap = devm_regmap_init_i2c(client, &tps65217_regmap_config); 201 if (IS_ERR(tps->regmap)) { 202 ret = PTR_ERR(tps->regmap); 203 dev_err(tps->dev, "Failed to allocate register map: %d\n", 204 ret); 205 return ret; 206 } 207 208 ret = mfd_add_devices(tps->dev, -1, tps65217s, 209 ARRAY_SIZE(tps65217s), NULL, 0, NULL); 210 if (ret < 0) { 211 dev_err(tps->dev, "mfd_add_devices failed: %d\n", ret); 212 return ret; 213 } 214 215 ret = tps65217_reg_read(tps, TPS65217_REG_CHIPID, &version); 216 if (ret < 0) { 217 dev_err(tps->dev, "Failed to read revision register: %d\n", 218 ret); 219 return ret; 220 } 221 222 /* Set the PMIC to shutdown on PWR_EN toggle */ 223 if (status_off) { 224 ret = tps65217_set_bits(tps, TPS65217_REG_STATUS, 225 TPS65217_STATUS_OFF, TPS65217_STATUS_OFF, 226 TPS65217_PROTECT_NONE); 227 if (ret) 228 dev_warn(tps->dev, "unable to set the status OFF\n"); 229 } 230 231 dev_info(tps->dev, "TPS65217 ID %#x version 1.%d\n", 232 (version & TPS65217_CHIPID_CHIP_MASK) >> 4, 233 version & TPS65217_CHIPID_REV_MASK); 234 235 return 0; 236} 237 238static int tps65217_remove(struct i2c_client *client) 239{ 240 struct tps65217 *tps = i2c_get_clientdata(client); 241 242 mfd_remove_devices(tps->dev); 243 244 return 0; 245} 246 247static const struct i2c_device_id tps65217_id_table[] = { 248 {"tps65217", TPS65217}, 249 { /* sentinel */ } 250}; 251MODULE_DEVICE_TABLE(i2c, tps65217_id_table); 252 253static struct i2c_driver tps65217_driver = { 254 .driver = { 255 .name = "tps65217", 256 .of_match_table = tps65217_of_match, 257 }, 258 .id_table = tps65217_id_table, 259 .probe = tps65217_probe, 260 .remove = tps65217_remove, 261}; 262 263static int __init tps65217_init(void) 264{ 265 return i2c_add_driver(&tps65217_driver); 266} 267subsys_initcall(tps65217_init); 268 269static void __exit tps65217_exit(void) 270{ 271 i2c_del_driver(&tps65217_driver); 272} 273module_exit(tps65217_exit); 274 275MODULE_AUTHOR("AnilKumar Ch <anilkumar@ti.com>"); 276MODULE_DESCRIPTION("TPS65217 chip family multi-function driver"); 277MODULE_LICENSE("GPL v2"); 278