hwmon: (pmbus/tps53679) Add support for TPS53681
[linux-block.git] / drivers / hwmon / pmbus / tps53679.c
CommitLineData
c942fddf 1// SPDX-License-Identifier: GPL-2.0-or-later
61052652
VP
2/*
3 * Hardware monitoring driver for Texas Instruments TPS53679
4 *
5 * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
6 * Copyright (c) 2017 Vadim Pasternak <vadimp@mellanox.com>
61052652
VP
7 */
8
53030bcc 9#include <linux/bits.h>
61052652
VP
10#include <linux/err.h>
11#include <linux/i2c.h>
12#include <linux/init.h>
13#include <linux/kernel.h>
14#include <linux/module.h>
63eb4587 15#include <linux/of_device.h>
61052652
VP
16#include "pmbus.h"
17
63eb4587 18enum chips {
53030bcc 19 tps53679, tps53681, tps53688
63eb4587
GR
20};
21
61052652
VP
22#define TPS53679_PROT_VR12_5MV 0x01 /* VR12.0 mode, 5-mV DAC */
23#define TPS53679_PROT_VR12_5_10MV 0x02 /* VR12.5 mode, 10-mV DAC */
24#define TPS53679_PROT_VR13_10MV 0x04 /* VR13.0 mode, 10-mV DAC */
25#define TPS53679_PROT_IMVP8_5MV 0x05 /* IMVP8 mode, 5-mV DAC */
26#define TPS53679_PROT_VR13_5MV 0x07 /* VR13.0 mode, 5-mV DAC */
27#define TPS53679_PAGE_NUM 2
28
53030bcc
GR
29#define TPS53681_DEVICE_ID 0x81
30
31#define TPS53681_PMBUS_REVISION 0x33
32
33#define TPS53681_MFR_SPECIFIC_20 0xe4 /* Number of phases, per page */
34
35static int tps53679_identify_mode(struct i2c_client *client,
36 struct pmbus_driver_info *info)
61052652
VP
37{
38 u8 vout_params;
b9fa0a3a 39 int i, ret;
61052652 40
b9fa0a3a
VP
41 for (i = 0; i < TPS53679_PAGE_NUM; i++) {
42 /* Read the register with VOUT scaling value.*/
43 ret = pmbus_read_byte_data(client, i, PMBUS_VOUT_MODE);
44 if (ret < 0)
45 return ret;
61052652 46
b9fa0a3a 47 vout_params = ret & GENMASK(4, 0);
61052652 48
b9fa0a3a
VP
49 switch (vout_params) {
50 case TPS53679_PROT_VR13_10MV:
51 case TPS53679_PROT_VR12_5_10MV:
52 info->vrm_version[i] = vr13;
53 break;
54 case TPS53679_PROT_VR13_5MV:
55 case TPS53679_PROT_VR12_5MV:
56 case TPS53679_PROT_IMVP8_5MV:
57 info->vrm_version[i] = vr12;
58 break;
59 default:
60 return -EINVAL;
61 }
61052652
VP
62 }
63
64 return 0;
65}
66
53030bcc
GR
67static int tps53679_identify_phases(struct i2c_client *client,
68 struct pmbus_driver_info *info)
69{
70 int ret;
71
72 /* On TPS53681, only channel A provides per-phase output current */
73 ret = pmbus_read_byte_data(client, 0, TPS53681_MFR_SPECIFIC_20);
74 if (ret < 0)
75 return ret;
76 info->phases[0] = (ret & 0x07) + 1;
77
78 return 0;
79}
80
81static int tps53679_identify_chip(struct i2c_client *client,
82 u8 revision, u16 id)
83{
84 u8 buf[I2C_SMBUS_BLOCK_MAX];
85 int ret;
86
87 ret = pmbus_read_byte_data(client, 0, PMBUS_REVISION);
88 if (ret < 0)
89 return ret;
90 if (ret != revision) {
91 dev_err(&client->dev, "Unexpected PMBus revision 0x%x\n", ret);
92 return -ENODEV;
93 }
94
95 ret = i2c_smbus_read_block_data(client, PMBUS_IC_DEVICE_ID, buf);
96 if (ret < 0)
97 return ret;
98 if (ret != 1 || buf[0] != id) {
99 dev_err(&client->dev, "Unexpected device ID 0x%x\n", buf[0]);
100 return -ENODEV;
101 }
102 return 0;
103}
104
105/*
106 * Common identification function for chips with multi-phase support.
107 * Since those chips have special configuration registers, we want to have
108 * some level of reassurance that we are really talking with the chip
109 * being probed. Check PMBus revision and chip ID.
110 */
111static int tps53679_identify_multiphase(struct i2c_client *client,
112 struct pmbus_driver_info *info,
113 int pmbus_rev, int device_id)
114{
115 int ret;
116
117 ret = tps53679_identify_chip(client, pmbus_rev, device_id);
118 if (ret < 0)
119 return ret;
120
121 ret = tps53679_identify_mode(client, info);
122 if (ret < 0)
123 return ret;
124
125 return tps53679_identify_phases(client, info);
126}
127
128static int tps53679_identify(struct i2c_client *client,
129 struct pmbus_driver_info *info)
130{
131 return tps53679_identify_mode(client, info);
132}
133
134static int tps53681_identify(struct i2c_client *client,
135 struct pmbus_driver_info *info)
136{
137 return tps53679_identify_multiphase(client, info,
138 TPS53681_PMBUS_REVISION,
139 TPS53681_DEVICE_ID);
140}
141
142static int tps53681_read_word_data(struct i2c_client *client, int page,
143 int phase, int reg)
144{
145 /*
146 * For reading the total output current (READ_IOUT) for all phases,
147 * the chip datasheet is a bit vague. It says "PHASE must be set to
148 * FFh to access all phases simultaneously. PHASE may also be set to
149 * 80h readack (!) the total phase current".
150 * Experiments show that the command does _not_ report the total
151 * current for all phases if the phase is set to 0xff. Instead, it
152 * appears to report the current of one of the phases. Override phase
153 * parameter with 0x80 when reading the total output current on page 0.
154 */
155 if (reg == PMBUS_READ_IOUT && page == 0 && phase == 0xff)
156 return pmbus_read_word_data(client, page, 0x80, reg);
157 return -ENODATA;
158}
159
61052652 160static struct pmbus_driver_info tps53679_info = {
61052652
VP
161 .format[PSC_VOLTAGE_IN] = linear,
162 .format[PSC_VOLTAGE_OUT] = vid,
163 .format[PSC_TEMPERATURE] = linear,
164 .format[PSC_CURRENT_OUT] = linear,
165 .format[PSC_POWER] = linear,
39c749ac
GR
166 .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN | PMBUS_HAVE_PIN |
167 PMBUS_HAVE_STATUS_INPUT |
63eb4587 168 PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
61052652
VP
169 PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
170 PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP |
171 PMBUS_HAVE_POUT,
39c749ac 172 .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
61052652
VP
173 PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
174 PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP |
175 PMBUS_HAVE_POUT,
53030bcc
GR
176 .pfunc[0] = PMBUS_HAVE_IOUT,
177 .pfunc[1] = PMBUS_HAVE_IOUT,
178 .pfunc[2] = PMBUS_HAVE_IOUT,
179 .pfunc[3] = PMBUS_HAVE_IOUT,
180 .pfunc[4] = PMBUS_HAVE_IOUT,
181 .pfunc[5] = PMBUS_HAVE_IOUT,
61052652
VP
182};
183
184static int tps53679_probe(struct i2c_client *client,
185 const struct i2c_device_id *id)
186{
63eb4587 187 struct device *dev = &client->dev;
ff066653 188 struct pmbus_driver_info *info;
63eb4587
GR
189 enum chips chip_id;
190
191 if (dev->of_node)
192 chip_id = (enum chips)of_device_get_match_data(dev);
193 else
194 chip_id = id->driver_data;
ff066653 195
63eb4587 196 info = devm_kmemdup(dev, &tps53679_info, sizeof(*info), GFP_KERNEL);
ff066653
VP
197 if (!info)
198 return -ENOMEM;
199
63eb4587
GR
200 switch (chip_id) {
201 case tps53679:
202 case tps53688:
203 info->pages = TPS53679_PAGE_NUM;
204 info->identify = tps53679_identify;
205 break;
53030bcc
GR
206 case tps53681:
207 info->pages = TPS53679_PAGE_NUM;
208 info->phases[0] = 6;
209 info->identify = tps53681_identify;
210 info->read_word_data = tps53681_read_word_data;
211 break;
63eb4587
GR
212 default:
213 return -ENODEV;
214 }
215
ff066653 216 return pmbus_do_probe(client, id, info);
61052652
VP
217}
218
219static const struct i2c_device_id tps53679_id[] = {
63eb4587 220 {"tps53679", tps53679},
53030bcc 221 {"tps53681", tps53681},
63eb4587 222 {"tps53688", tps53688},
61052652
VP
223 {}
224};
225
226MODULE_DEVICE_TABLE(i2c, tps53679_id);
227
e91cb17b 228static const struct of_device_id __maybe_unused tps53679_of_match[] = {
63eb4587 229 {.compatible = "ti,tps53679", .data = (void *)tps53679},
53030bcc 230 {.compatible = "ti,tps53681", .data = (void *)tps53681},
63eb4587 231 {.compatible = "ti,tps53688", .data = (void *)tps53688},
61052652
VP
232 {}
233};
234MODULE_DEVICE_TABLE(of, tps53679_of_match);
235
236static struct i2c_driver tps53679_driver = {
237 .driver = {
238 .name = "tps53679",
239 .of_match_table = of_match_ptr(tps53679_of_match),
240 },
241 .probe = tps53679_probe,
242 .remove = pmbus_do_remove,
243 .id_table = tps53679_id,
244};
245
246module_i2c_driver(tps53679_driver);
247
248MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
249MODULE_DESCRIPTION("PMBus driver for Texas Instruments TPS53679");
250MODULE_LICENSE("GPL");