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