tps65086.c (4309B)
1/* 2 * Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com/ 3 * Andrew F. Davis <afd@ti.com> 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed "as is" WITHOUT ANY WARRANTY of any 10 * kind, whether expressed or implied; without even the implied warranty 11 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License version 2 for more details. 13 * 14 * Based on the TPS65912 driver 15 */ 16 17#include <linux/i2c.h> 18#include <linux/interrupt.h> 19#include <linux/mfd/core.h> 20#include <linux/module.h> 21 22#include <linux/mfd/tps65086.h> 23 24static const struct mfd_cell tps65086_cells[] = { 25 { .name = "tps65086-regulator", }, 26 { .name = "tps65086-gpio", }, 27 { .name = "tps65086-reset", }, 28}; 29 30static const struct regmap_range tps65086_yes_ranges[] = { 31 regmap_reg_range(TPS65086_IRQ, TPS65086_IRQ), 32 regmap_reg_range(TPS65086_PMICSTAT, TPS65086_SHUTDNSRC), 33 regmap_reg_range(TPS65086_GPOCTRL, TPS65086_GPOCTRL), 34 regmap_reg_range(TPS65086_PG_STATUS1, TPS65086_OC_STATUS), 35}; 36 37static const struct regmap_access_table tps65086_volatile_table = { 38 .yes_ranges = tps65086_yes_ranges, 39 .n_yes_ranges = ARRAY_SIZE(tps65086_yes_ranges), 40}; 41 42static const struct regmap_config tps65086_regmap_config = { 43 .reg_bits = 8, 44 .val_bits = 8, 45 .cache_type = REGCACHE_RBTREE, 46 .volatile_table = &tps65086_volatile_table, 47}; 48 49static const struct regmap_irq tps65086_irqs[] = { 50 REGMAP_IRQ_REG(TPS65086_IRQ_DIETEMP, 0, TPS65086_IRQ_DIETEMP_MASK), 51 REGMAP_IRQ_REG(TPS65086_IRQ_SHUTDN, 0, TPS65086_IRQ_SHUTDN_MASK), 52 REGMAP_IRQ_REG(TPS65086_IRQ_FAULT, 0, TPS65086_IRQ_FAULT_MASK), 53}; 54 55static struct regmap_irq_chip tps65086_irq_chip = { 56 .name = "tps65086", 57 .status_base = TPS65086_IRQ, 58 .mask_base = TPS65086_IRQ_MASK, 59 .ack_base = TPS65086_IRQ, 60 .init_ack_masked = true, 61 .num_regs = 1, 62 .irqs = tps65086_irqs, 63 .num_irqs = ARRAY_SIZE(tps65086_irqs), 64}; 65 66static const struct of_device_id tps65086_of_match_table[] = { 67 { .compatible = "ti,tps65086", }, 68 { /* sentinel */ } 69}; 70MODULE_DEVICE_TABLE(of, tps65086_of_match_table); 71 72static int tps65086_probe(struct i2c_client *client, 73 const struct i2c_device_id *ids) 74{ 75 struct tps65086 *tps; 76 unsigned int version; 77 int ret; 78 79 tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); 80 if (!tps) 81 return -ENOMEM; 82 83 i2c_set_clientdata(client, tps); 84 tps->dev = &client->dev; 85 tps->irq = client->irq; 86 87 tps->regmap = devm_regmap_init_i2c(client, &tps65086_regmap_config); 88 if (IS_ERR(tps->regmap)) { 89 dev_err(tps->dev, "Failed to initialize register map\n"); 90 return PTR_ERR(tps->regmap); 91 } 92 93 ret = regmap_read(tps->regmap, TPS65086_DEVICEID, &version); 94 if (ret) { 95 dev_err(tps->dev, "Failed to read revision register\n"); 96 return ret; 97 } 98 99 dev_info(tps->dev, "Device: TPS65086%01lX, OTP: %c, Rev: %ld\n", 100 (version & TPS65086_DEVICEID_PART_MASK), 101 (char)((version & TPS65086_DEVICEID_OTP_MASK) >> 4) + 'A', 102 (version & TPS65086_DEVICEID_REV_MASK) >> 6); 103 104 if (tps->irq > 0) { 105 ret = regmap_add_irq_chip(tps->regmap, tps->irq, IRQF_ONESHOT, 0, 106 &tps65086_irq_chip, &tps->irq_data); 107 if (ret) { 108 dev_err(tps->dev, "Failed to register IRQ chip\n"); 109 return ret; 110 } 111 } 112 113 ret = mfd_add_devices(tps->dev, PLATFORM_DEVID_AUTO, tps65086_cells, 114 ARRAY_SIZE(tps65086_cells), NULL, 0, 115 regmap_irq_get_domain(tps->irq_data)); 116 if (ret && tps->irq > 0) 117 regmap_del_irq_chip(tps->irq, tps->irq_data); 118 119 return ret; 120} 121 122static int tps65086_remove(struct i2c_client *client) 123{ 124 struct tps65086 *tps = i2c_get_clientdata(client); 125 126 if (tps->irq > 0) 127 regmap_del_irq_chip(tps->irq, tps->irq_data); 128 129 return 0; 130} 131 132static const struct i2c_device_id tps65086_id_table[] = { 133 { "tps65086", 0 }, 134 { /* sentinel */ } 135}; 136MODULE_DEVICE_TABLE(i2c, tps65086_id_table); 137 138static struct i2c_driver tps65086_driver = { 139 .driver = { 140 .name = "tps65086", 141 .of_match_table = tps65086_of_match_table, 142 }, 143 .probe = tps65086_probe, 144 .remove = tps65086_remove, 145 .id_table = tps65086_id_table, 146}; 147module_i2c_driver(tps65086_driver); 148 149MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); 150MODULE_DESCRIPTION("TPS65086 PMIC Driver"); 151MODULE_LICENSE("GPL v2");