]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/hwmon/pmbus/lm25066.c
Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge
[karo-tx-linux.git] / drivers / hwmon / pmbus / lm25066.c
1 /*
2  * Hardware monitoring driver for LM25056 / LM25066 / LM5064 / LM5066
3  *
4  * Copyright (c) 2011 Ericsson AB.
5  * Copyright (c) 2013 Guenter Roeck
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #include <linux/kernel.h>
23 #include <linux/module.h>
24 #include <linux/init.h>
25 #include <linux/err.h>
26 #include <linux/slab.h>
27 #include <linux/i2c.h>
28 #include "pmbus.h"
29
30 enum chips { lm25056, lm25066, lm5064, lm5066 };
31
32 #define LM25066_READ_VAUX               0xd0
33 #define LM25066_MFR_READ_IIN            0xd1
34 #define LM25066_MFR_READ_PIN            0xd2
35 #define LM25066_MFR_IIN_OC_WARN_LIMIT   0xd3
36 #define LM25066_MFR_PIN_OP_WARN_LIMIT   0xd4
37 #define LM25066_READ_PIN_PEAK           0xd5
38 #define LM25066_CLEAR_PIN_PEAK          0xd6
39 #define LM25066_DEVICE_SETUP            0xd9
40 #define LM25066_READ_AVG_VIN            0xdc
41 #define LM25066_READ_AVG_VOUT           0xdd
42 #define LM25066_READ_AVG_IIN            0xde
43 #define LM25066_READ_AVG_PIN            0xdf
44
45 #define LM25066_DEV_SETUP_CL            (1 << 4)        /* Current limit */
46
47 /* LM25056 only */
48
49 #define LM25056_VAUX_OV_WARN_LIMIT      0xe3
50 #define LM25056_VAUX_UV_WARN_LIMIT      0xe4
51
52 #define LM25056_MFR_STS_VAUX_OV_WARN    (1 << 1)
53 #define LM25056_MFR_STS_VAUX_UV_WARN    (1 << 0)
54
55 struct __coeff {
56         short m, b, R;
57 };
58
59 #define PSC_CURRENT_IN_L        (PSC_NUM_CLASSES)
60 #define PSC_POWER_L             (PSC_NUM_CLASSES + 1)
61
62 static struct __coeff lm25066_coeff[4][PSC_NUM_CLASSES + 2] = {
63         [lm25056] = {
64                 [PSC_VOLTAGE_IN] = {
65                         .m = 16296,
66                         .R = -2,
67                 },
68                 [PSC_CURRENT_IN] = {
69                         .m = 13797,
70                         .R = -2,
71                 },
72                 [PSC_CURRENT_IN_L] = {
73                         .m = 6726,
74                         .R = -2,
75                 },
76                 [PSC_POWER] = {
77                         .m = 5501,
78                         .R = -3,
79                 },
80                 [PSC_POWER_L] = {
81                         .m = 26882,
82                         .R = -4,
83                 },
84                 [PSC_TEMPERATURE] = {
85                         .m = 1580,
86                         .b = -14500,
87                         .R = -2,
88                 },
89         },
90         [lm25066] = {
91                 [PSC_VOLTAGE_IN] = {
92                         .m = 22070,
93                         .R = -2,
94                 },
95                 [PSC_VOLTAGE_OUT] = {
96                         .m = 22070,
97                         .R = -2,
98                 },
99                 [PSC_CURRENT_IN] = {
100                         .m = 13661,
101                         .R = -2,
102                 },
103                 [PSC_CURRENT_IN_L] = {
104                         .m = 6852,
105                         .R = -2,
106                 },
107                 [PSC_POWER] = {
108                         .m = 736,
109                         .R = -2,
110                 },
111                 [PSC_POWER_L] = {
112                         .m = 369,
113                         .R = -2,
114                 },
115                 [PSC_TEMPERATURE] = {
116                         .m = 16,
117                 },
118         },
119         [lm5064] = {
120                 [PSC_VOLTAGE_IN] = {
121                         .m = 4611,
122                         .R = -2,
123                 },
124                 [PSC_VOLTAGE_OUT] = {
125                         .m = 4621,
126                         .R = -2,
127                 },
128                 [PSC_CURRENT_IN] = {
129                         .m = 10742,
130                         .R = -2,
131                 },
132                 [PSC_CURRENT_IN_L] = {
133                         .m = 5456,
134                         .R = -2,
135                 },
136                 [PSC_POWER] = {
137                         .m = 1204,
138                         .R = -3,
139                 },
140                 [PSC_POWER_L] = {
141                         .m = 612,
142                         .R = -3,
143                 },
144                 [PSC_TEMPERATURE] = {
145                         .m = 16,
146                 },
147         },
148         [lm5066] = {
149                 [PSC_VOLTAGE_IN] = {
150                         .m = 4587,
151                         .R = -2,
152                 },
153                 [PSC_VOLTAGE_OUT] = {
154                         .m = 4587,
155                         .R = -2,
156                 },
157                 [PSC_CURRENT_IN] = {
158                         .m = 10753,
159                         .R = -2,
160                 },
161                 [PSC_CURRENT_IN_L] = {
162                         .m = 5405,
163                         .R = -2,
164                 },
165                 [PSC_POWER] = {
166                         .m = 1204,
167                         .R = -3,
168                 },
169                 [PSC_POWER_L] = {
170                         .m = 605,
171                         .R = -3,
172                 },
173                 [PSC_TEMPERATURE] = {
174                         .m = 16,
175                 },
176         },
177 };
178
179 struct lm25066_data {
180         int id;
181         struct pmbus_driver_info info;
182 };
183
184 #define to_lm25066_data(x)  container_of(x, struct lm25066_data, info)
185
186 static int lm25066_read_word_data(struct i2c_client *client, int page, int reg)
187 {
188         const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
189         const struct lm25066_data *data = to_lm25066_data(info);
190         int ret;
191
192         switch (reg) {
193         case PMBUS_VIRT_READ_VMON:
194                 ret = pmbus_read_word_data(client, 0, LM25066_READ_VAUX);
195                 if (ret < 0)
196                         break;
197                 /* Adjust returned value to match VIN coefficients */
198                 switch (data->id) {
199                 case lm25056:
200                         /* VIN: 6.14 mV VAUX: 293 uV LSB */
201                         ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
202                         break;
203                 case lm25066:
204                         /* VIN: 4.54 mV VAUX: 283.2 uV LSB */
205                         ret = DIV_ROUND_CLOSEST(ret * 2832, 45400);
206                         break;
207                 case lm5064:
208                         /* VIN: 4.53 mV VAUX: 700 uV LSB */
209                         ret = DIV_ROUND_CLOSEST(ret * 70, 453);
210                         break;
211                 case lm5066:
212                         /* VIN: 2.18 mV VAUX: 725 uV LSB */
213                         ret = DIV_ROUND_CLOSEST(ret * 725, 2180);
214                         break;
215                 }
216                 break;
217         case PMBUS_READ_IIN:
218                 ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_IIN);
219                 break;
220         case PMBUS_READ_PIN:
221                 ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_PIN);
222                 break;
223         case PMBUS_IIN_OC_WARN_LIMIT:
224                 ret = pmbus_read_word_data(client, 0,
225                                            LM25066_MFR_IIN_OC_WARN_LIMIT);
226                 break;
227         case PMBUS_PIN_OP_WARN_LIMIT:
228                 ret = pmbus_read_word_data(client, 0,
229                                            LM25066_MFR_PIN_OP_WARN_LIMIT);
230                 break;
231         case PMBUS_VIRT_READ_VIN_AVG:
232                 ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VIN);
233                 break;
234         case PMBUS_VIRT_READ_VOUT_AVG:
235                 ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VOUT);
236                 break;
237         case PMBUS_VIRT_READ_IIN_AVG:
238                 ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_IIN);
239                 break;
240         case PMBUS_VIRT_READ_PIN_AVG:
241                 ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_PIN);
242                 break;
243         case PMBUS_VIRT_READ_PIN_MAX:
244                 ret = pmbus_read_word_data(client, 0, LM25066_READ_PIN_PEAK);
245                 break;
246         case PMBUS_VIRT_RESET_PIN_HISTORY:
247                 ret = 0;
248                 break;
249         default:
250                 ret = -ENODATA;
251                 break;
252         }
253         return ret;
254 }
255
256 static int lm25056_read_word_data(struct i2c_client *client, int page, int reg)
257 {
258         int ret;
259
260         switch (reg) {
261         case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
262                 ret = pmbus_read_word_data(client, 0,
263                                            LM25056_VAUX_UV_WARN_LIMIT);
264                 if (ret < 0)
265                         break;
266                 /* Adjust returned value to match VIN coefficients */
267                 ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
268                 break;
269         case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
270                 ret = pmbus_read_word_data(client, 0,
271                                            LM25056_VAUX_OV_WARN_LIMIT);
272                 if (ret < 0)
273                         break;
274                 /* Adjust returned value to match VIN coefficients */
275                 ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
276                 break;
277         default:
278                 ret = lm25066_read_word_data(client, page, reg);
279                 break;
280         }
281         return ret;
282 }
283
284 static int lm25056_read_byte_data(struct i2c_client *client, int page, int reg)
285 {
286         int ret, s;
287
288         switch (reg) {
289         case PMBUS_VIRT_STATUS_VMON:
290                 ret = pmbus_read_byte_data(client, 0,
291                                            PMBUS_STATUS_MFR_SPECIFIC);
292                 if (ret < 0)
293                         break;
294                 s = 0;
295                 if (ret & LM25056_MFR_STS_VAUX_UV_WARN)
296                         s |= PB_VOLTAGE_UV_WARNING;
297                 if (ret & LM25056_MFR_STS_VAUX_OV_WARN)
298                         s |= PB_VOLTAGE_OV_WARNING;
299                 ret = s;
300                 break;
301         default:
302                 ret = -ENODATA;
303                 break;
304         }
305         return ret;
306 }
307
308 static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
309                                    u16 word)
310 {
311         int ret;
312
313         switch (reg) {
314         case PMBUS_VOUT_UV_WARN_LIMIT:
315         case PMBUS_OT_FAULT_LIMIT:
316         case PMBUS_OT_WARN_LIMIT:
317         case PMBUS_VIN_UV_WARN_LIMIT:
318         case PMBUS_VIN_OV_WARN_LIMIT:
319                 word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
320                 ret = pmbus_write_word_data(client, 0, reg, word);
321                 pmbus_clear_cache(client);
322                 break;
323         case PMBUS_IIN_OC_WARN_LIMIT:
324                 word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
325                 ret = pmbus_write_word_data(client, 0,
326                                             LM25066_MFR_IIN_OC_WARN_LIMIT,
327                                             word);
328                 pmbus_clear_cache(client);
329                 break;
330         case PMBUS_PIN_OP_WARN_LIMIT:
331                 word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
332                 ret = pmbus_write_word_data(client, 0,
333                                             LM25066_MFR_PIN_OP_WARN_LIMIT,
334                                             word);
335                 pmbus_clear_cache(client);
336                 break;
337         case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
338                 /* Adjust from VIN coefficients (for LM25056) */
339                 word = DIV_ROUND_CLOSEST((int)word * 6140, 293);
340                 word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
341                 ret = pmbus_write_word_data(client, 0,
342                                             LM25056_VAUX_UV_WARN_LIMIT, word);
343                 pmbus_clear_cache(client);
344                 break;
345         case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
346                 /* Adjust from VIN coefficients (for LM25056) */
347                 word = DIV_ROUND_CLOSEST((int)word * 6140, 293);
348                 word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
349                 ret = pmbus_write_word_data(client, 0,
350                                             LM25056_VAUX_OV_WARN_LIMIT, word);
351                 pmbus_clear_cache(client);
352                 break;
353         case PMBUS_VIRT_RESET_PIN_HISTORY:
354                 ret = pmbus_write_byte(client, 0, LM25066_CLEAR_PIN_PEAK);
355                 break;
356         default:
357                 ret = -ENODATA;
358                 break;
359         }
360         return ret;
361 }
362
363 static int lm25066_probe(struct i2c_client *client,
364                           const struct i2c_device_id *id)
365 {
366         int config;
367         struct lm25066_data *data;
368         struct pmbus_driver_info *info;
369         struct __coeff *coeff;
370
371         if (!i2c_check_functionality(client->adapter,
372                                      I2C_FUNC_SMBUS_READ_BYTE_DATA))
373                 return -ENODEV;
374
375         data = devm_kzalloc(&client->dev, sizeof(struct lm25066_data),
376                             GFP_KERNEL);
377         if (!data)
378                 return -ENOMEM;
379
380         config = i2c_smbus_read_byte_data(client, LM25066_DEVICE_SETUP);
381         if (config < 0)
382                 return config;
383
384         data->id = id->driver_data;
385         info = &data->info;
386
387         info->pages = 1;
388         info->format[PSC_VOLTAGE_IN] = direct;
389         info->format[PSC_VOLTAGE_OUT] = direct;
390         info->format[PSC_CURRENT_IN] = direct;
391         info->format[PSC_TEMPERATURE] = direct;
392         info->format[PSC_POWER] = direct;
393
394         info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VMON
395           | PMBUS_HAVE_PIN | PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT
396           | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
397
398         if (data->id == lm25056) {
399                 info->func[0] |= PMBUS_HAVE_STATUS_VMON;
400                 info->read_word_data = lm25056_read_word_data;
401                 info->read_byte_data = lm25056_read_byte_data;
402         } else {
403                 info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
404                 info->read_word_data = lm25066_read_word_data;
405         }
406         info->write_word_data = lm25066_write_word_data;
407
408         coeff = &lm25066_coeff[data->id][0];
409         info->m[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].m;
410         info->b[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].b;
411         info->R[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].R;
412         info->m[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].m;
413         info->b[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].b;
414         info->R[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].R;
415         info->m[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].m;
416         info->b[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].b;
417         info->R[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].R;
418         info->b[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].b;
419         info->R[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].R;
420         info->b[PSC_POWER] = coeff[PSC_POWER].b;
421         info->R[PSC_POWER] = coeff[PSC_POWER].R;
422         if (config & LM25066_DEV_SETUP_CL) {
423                 info->m[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN_L].m;
424                 info->m[PSC_POWER] = coeff[PSC_POWER_L].m;
425         } else {
426                 info->m[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].m;
427                 info->m[PSC_POWER] = coeff[PSC_POWER].m;
428         }
429
430         return pmbus_do_probe(client, id, info);
431 }
432
433 static const struct i2c_device_id lm25066_id[] = {
434         {"lm25056", lm25056},
435         {"lm25066", lm25066},
436         {"lm5064", lm5064},
437         {"lm5066", lm5066},
438         { }
439 };
440
441 MODULE_DEVICE_TABLE(i2c, lm25066_id);
442
443 /* This is the driver that will be inserted */
444 static struct i2c_driver lm25066_driver = {
445         .driver = {
446                    .name = "lm25066",
447                    },
448         .probe = lm25066_probe,
449         .remove = pmbus_do_remove,
450         .id_table = lm25066_id,
451 };
452
453 module_i2c_driver(lm25066_driver);
454
455 MODULE_AUTHOR("Guenter Roeck");
456 MODULE_DESCRIPTION("PMBus driver for LM25056/LM25066/LM5064/LM5066");
457 MODULE_LICENSE("GPL");