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