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