blob: 945f7eced409f644cccf58f6a4af95f2fa9171bb [file] [log] [blame]
Guenter Roeckc3ff9a62011-09-02 09:58:37 -07001/*
Guenter Roeckddfb41c2011-09-11 20:31:09 -07002 * Hardware monitoring driver for LTC2978 and LTC3880
Guenter Roeckc3ff9a62011-09-02 09:58:37 -07003 *
4 * Copyright (c) 2011 Ericsson AB.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/init.h>
24#include <linux/err.h>
25#include <linux/slab.h>
26#include <linux/i2c.h>
27#include "pmbus.h"
28
Guenter Roeckddfb41c2011-09-11 20:31:09 -070029enum chips { ltc2978, ltc3880 };
Guenter Roeckc3ff9a62011-09-02 09:58:37 -070030
Guenter Roeckddfb41c2011-09-11 20:31:09 -070031/* LTC2978 and LTC3880 */
Guenter Roeckc3ff9a62011-09-02 09:58:37 -070032#define LTC2978_MFR_VOUT_PEAK 0xdd
33#define LTC2978_MFR_VIN_PEAK 0xde
34#define LTC2978_MFR_TEMPERATURE_PEAK 0xdf
35#define LTC2978_MFR_SPECIAL_ID 0xe7
36
Guenter Roeckddfb41c2011-09-11 20:31:09 -070037/* LTC2978 only */
Guenter Roeckc3ff9a62011-09-02 09:58:37 -070038#define LTC2978_MFR_VOUT_MIN 0xfb
39#define LTC2978_MFR_VIN_MIN 0xfc
40#define LTC2978_MFR_TEMPERATURE_MIN 0xfd
41
Guenter Roeckddfb41c2011-09-11 20:31:09 -070042/* LTC3880 only */
43#define LTC3880_MFR_IOUT_PEAK 0xd7
44#define LTC3880_MFR_CLEAR_PEAKS 0xe3
45#define LTC3880_MFR_TEMPERATURE2_PEAK 0xf4
46
Guenter Roeckc3ff9a62011-09-02 09:58:37 -070047#define LTC2978_ID_REV1 0x0121
48#define LTC2978_ID_REV2 0x0122
Guenter Roeckddfb41c2011-09-11 20:31:09 -070049#define LTC3880_ID 0x4000
50#define LTC3880_ID_MASK 0xff00
Guenter Roeckc3ff9a62011-09-02 09:58:37 -070051
Guenter Roeck3d0d2832013-02-28 08:14:45 -080052#define LTC2978_NUM_PAGES 8
53#define LTC3880_NUM_PAGES 2
54
Guenter Roeckc3ff9a62011-09-02 09:58:37 -070055/*
56 * LTC2978 clears peak data whenever the CLEAR_FAULTS command is executed, which
57 * happens pretty much each time chip data is updated. Raw peak data therefore
58 * does not provide much value. To be able to provide useful peak data, keep an
59 * internal cache of measured peak data, which is only cleared if an explicit
60 * "clear peak" command is executed for the sensor in question.
61 */
Guenter Roeck3d0d2832013-02-28 08:14:45 -080062
Guenter Roeckc3ff9a62011-09-02 09:58:37 -070063struct ltc2978_data {
64 enum chips id;
Guenter Roeck3d0d2832013-02-28 08:14:45 -080065 u16 vin_min, vin_max;
66 u16 temp_min, temp_max[LTC3880_NUM_PAGES];
67 u16 vout_min[LTC2978_NUM_PAGES], vout_max[LTC2978_NUM_PAGES];
68 u16 iout_max[LTC3880_NUM_PAGES];
69 u16 temp2_max;
Guenter Roeckc3ff9a62011-09-02 09:58:37 -070070 struct pmbus_driver_info info;
71};
72
73#define to_ltc2978_data(x) container_of(x, struct ltc2978_data, info)
74
75static inline int lin11_to_val(int data)
76{
77 s16 e = ((s16)data) >> 11;
78 s32 m = (((s16)(data << 5)) >> 5);
79
80 /*
81 * mantissa is 10 bit + sign, exponent adds up to 15 bit.
82 * Add 6 bit to exponent for maximum accuracy (10 + 15 + 6 = 31).
83 */
84 e += 6;
85 return (e < 0 ? m >> -e : m << e);
86}
87
Guenter Roeckddfb41c2011-09-11 20:31:09 -070088static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
89 int reg)
Guenter Roeckc3ff9a62011-09-02 09:58:37 -070090{
91 const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
92 struct ltc2978_data *data = to_ltc2978_data(info);
93 int ret;
94
95 switch (reg) {
96 case PMBUS_VIRT_READ_VIN_MAX:
97 ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_PEAK);
98 if (ret >= 0) {
99 if (lin11_to_val(ret) > lin11_to_val(data->vin_max))
100 data->vin_max = ret;
101 ret = data->vin_max;
102 }
103 break;
104 case PMBUS_VIRT_READ_VOUT_MAX:
105 ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_PEAK);
106 if (ret >= 0) {
107 /*
108 * VOUT is 16 bit unsigned with fixed exponent,
109 * so we can compare it directly
110 */
111 if (ret > data->vout_max[page])
112 data->vout_max[page] = ret;
113 ret = data->vout_max[page];
114 }
115 break;
116 case PMBUS_VIRT_READ_TEMP_MAX:
117 ret = pmbus_read_word_data(client, page,
118 LTC2978_MFR_TEMPERATURE_PEAK);
119 if (ret >= 0) {
Guenter Roeck8c958c72013-02-21 10:27:54 -0800120 if (lin11_to_val(ret)
121 > lin11_to_val(data->temp_max[page]))
122 data->temp_max[page] = ret;
123 ret = data->temp_max[page];
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700124 }
125 break;
Guenter Roeckddfb41c2011-09-11 20:31:09 -0700126 case PMBUS_VIRT_RESET_VOUT_HISTORY:
127 case PMBUS_VIRT_RESET_VIN_HISTORY:
128 case PMBUS_VIRT_RESET_TEMP_HISTORY:
129 ret = 0;
130 break;
131 default:
132 ret = -ENODATA;
133 break;
134 }
135 return ret;
136}
137
138static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg)
139{
140 const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
141 struct ltc2978_data *data = to_ltc2978_data(info);
142 int ret;
143
144 switch (reg) {
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700145 case PMBUS_VIRT_READ_VIN_MIN:
146 ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_MIN);
147 if (ret >= 0) {
148 if (lin11_to_val(ret) < lin11_to_val(data->vin_min))
149 data->vin_min = ret;
150 ret = data->vin_min;
151 }
152 break;
153 case PMBUS_VIRT_READ_VOUT_MIN:
154 ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_MIN);
155 if (ret >= 0) {
156 /*
157 * VOUT_MIN is known to not be supported on some lots
158 * of LTC2978 revision 1, and will return the maximum
159 * possible voltage if read. If VOUT_MAX is valid and
160 * lower than the reading of VOUT_MIN, use it instead.
161 */
162 if (data->vout_max[page] && ret > data->vout_max[page])
163 ret = data->vout_max[page];
164 if (ret < data->vout_min[page])
165 data->vout_min[page] = ret;
166 ret = data->vout_min[page];
167 }
168 break;
169 case PMBUS_VIRT_READ_TEMP_MIN:
170 ret = pmbus_read_word_data(client, page,
171 LTC2978_MFR_TEMPERATURE_MIN);
172 if (ret >= 0) {
173 if (lin11_to_val(ret)
174 < lin11_to_val(data->temp_min))
175 data->temp_min = ret;
176 ret = data->temp_min;
177 }
178 break;
Guenter Roeckddfb41c2011-09-11 20:31:09 -0700179 case PMBUS_VIRT_READ_IOUT_MAX:
180 case PMBUS_VIRT_RESET_IOUT_HISTORY:
181 case PMBUS_VIRT_READ_TEMP2_MAX:
182 case PMBUS_VIRT_RESET_TEMP2_HISTORY:
183 ret = -ENXIO;
184 break;
185 default:
186 ret = ltc2978_read_word_data_common(client, page, reg);
187 break;
188 }
189 return ret;
190}
191
192static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg)
193{
194 const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
195 struct ltc2978_data *data = to_ltc2978_data(info);
196 int ret;
197
198 switch (reg) {
199 case PMBUS_VIRT_READ_IOUT_MAX:
200 ret = pmbus_read_word_data(client, page, LTC3880_MFR_IOUT_PEAK);
201 if (ret >= 0) {
202 if (lin11_to_val(ret)
203 > lin11_to_val(data->iout_max[page]))
204 data->iout_max[page] = ret;
205 ret = data->iout_max[page];
206 }
207 break;
208 case PMBUS_VIRT_READ_TEMP2_MAX:
209 ret = pmbus_read_word_data(client, page,
210 LTC3880_MFR_TEMPERATURE2_PEAK);
211 if (ret >= 0) {
Guenter Roeckdbd712c2013-02-21 09:33:25 -0800212 if (lin11_to_val(ret) > lin11_to_val(data->temp2_max))
213 data->temp2_max = ret;
214 ret = data->temp2_max;
Guenter Roeckddfb41c2011-09-11 20:31:09 -0700215 }
216 break;
217 case PMBUS_VIRT_READ_VIN_MIN:
218 case PMBUS_VIRT_READ_VOUT_MIN:
219 case PMBUS_VIRT_READ_TEMP_MIN:
220 ret = -ENXIO;
221 break;
222 case PMBUS_VIRT_RESET_IOUT_HISTORY:
223 case PMBUS_VIRT_RESET_TEMP2_HISTORY:
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700224 ret = 0;
225 break;
226 default:
Guenter Roeckddfb41c2011-09-11 20:31:09 -0700227 ret = ltc2978_read_word_data_common(client, page, reg);
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700228 break;
229 }
230 return ret;
231}
232
Guenter Roeckddfb41c2011-09-11 20:31:09 -0700233static int ltc2978_clear_peaks(struct i2c_client *client, int page,
234 enum chips id)
235{
236 int ret;
237
238 if (id == ltc2978)
239 ret = pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS);
240 else
241 ret = pmbus_write_byte(client, 0, LTC3880_MFR_CLEAR_PEAKS);
242
243 return ret;
244}
245
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700246static int ltc2978_write_word_data(struct i2c_client *client, int page,
247 int reg, u16 word)
248{
249 const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
250 struct ltc2978_data *data = to_ltc2978_data(info);
251 int ret;
252
253 switch (reg) {
Guenter Roeckddfb41c2011-09-11 20:31:09 -0700254 case PMBUS_VIRT_RESET_IOUT_HISTORY:
Guenter Roeckdbd712c2013-02-21 09:33:25 -0800255 data->iout_max[page] = 0x7c00;
Guenter Roeckddfb41c2011-09-11 20:31:09 -0700256 ret = ltc2978_clear_peaks(client, page, data->id);
257 break;
258 case PMBUS_VIRT_RESET_TEMP2_HISTORY:
Guenter Roeckdbd712c2013-02-21 09:33:25 -0800259 data->temp2_max = 0x7c00;
Guenter Roeckddfb41c2011-09-11 20:31:09 -0700260 ret = ltc2978_clear_peaks(client, page, data->id);
261 break;
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700262 case PMBUS_VIRT_RESET_VOUT_HISTORY:
263 data->vout_min[page] = 0xffff;
264 data->vout_max[page] = 0;
Guenter Roeckddfb41c2011-09-11 20:31:09 -0700265 ret = ltc2978_clear_peaks(client, page, data->id);
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700266 break;
267 case PMBUS_VIRT_RESET_VIN_HISTORY:
268 data->vin_min = 0x7bff;
Guenter Roeckdbd712c2013-02-21 09:33:25 -0800269 data->vin_max = 0x7c00;
Guenter Roeckddfb41c2011-09-11 20:31:09 -0700270 ret = ltc2978_clear_peaks(client, page, data->id);
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700271 break;
272 case PMBUS_VIRT_RESET_TEMP_HISTORY:
273 data->temp_min = 0x7bff;
Guenter Roeck8c958c72013-02-21 10:27:54 -0800274 data->temp_max[page] = 0x7c00;
Guenter Roeckddfb41c2011-09-11 20:31:09 -0700275 ret = ltc2978_clear_peaks(client, page, data->id);
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700276 break;
277 default:
278 ret = -ENODATA;
279 break;
280 }
281 return ret;
282}
283
284static const struct i2c_device_id ltc2978_id[] = {
285 {"ltc2978", ltc2978},
Guenter Roeckddfb41c2011-09-11 20:31:09 -0700286 {"ltc3880", ltc3880},
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700287 {}
288};
289MODULE_DEVICE_TABLE(i2c, ltc2978_id);
290
291static int ltc2978_probe(struct i2c_client *client,
292 const struct i2c_device_id *id)
293{
Guenter Roeck8b313ca2012-02-22 08:56:43 -0800294 int chip_id, i;
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700295 struct ltc2978_data *data;
296 struct pmbus_driver_info *info;
297
298 if (!i2c_check_functionality(client->adapter,
299 I2C_FUNC_SMBUS_READ_WORD_DATA))
300 return -ENODEV;
301
Guenter Roeck8b313ca2012-02-22 08:56:43 -0800302 data = devm_kzalloc(&client->dev, sizeof(struct ltc2978_data),
303 GFP_KERNEL);
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700304 if (!data)
305 return -ENOMEM;
306
307 chip_id = i2c_smbus_read_word_data(client, LTC2978_MFR_SPECIAL_ID);
Guenter Roeck8b313ca2012-02-22 08:56:43 -0800308 if (chip_id < 0)
309 return chip_id;
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700310
311 if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2) {
312 data->id = ltc2978;
Guenter Roeckddfb41c2011-09-11 20:31:09 -0700313 } else if ((chip_id & LTC3880_ID_MASK) == LTC3880_ID) {
314 data->id = ltc3880;
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700315 } else {
316 dev_err(&client->dev, "Unsupported chip ID 0x%x\n", chip_id);
Guenter Roeck8b313ca2012-02-22 08:56:43 -0800317 return -ENODEV;
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700318 }
319 if (data->id != id->driver_data)
320 dev_warn(&client->dev,
321 "Device mismatch: Configured %s, detected %s\n",
322 id->name,
323 ltc2978_id[data->id].name);
324
325 info = &data->info;
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700326 info->write_word_data = ltc2978_write_word_data;
327
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700328 data->vin_min = 0x7bff;
Guenter Roeckdbd712c2013-02-21 09:33:25 -0800329 data->vin_max = 0x7c00;
Guenter Roeck3d0d2832013-02-28 08:14:45 -0800330 for (i = 0; i < ARRAY_SIZE(data->vout_min); i++)
331 data->vout_min[i] = 0xffff;
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700332 data->temp_min = 0x7bff;
Guenter Roeck8c958c72013-02-21 10:27:54 -0800333 for (i = 0; i < ARRAY_SIZE(data->temp_max); i++)
334 data->temp_max[i] = 0x7c00;
Guenter Roeckdbd712c2013-02-21 09:33:25 -0800335 data->temp2_max = 0x7c00;
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700336
Guenter Roeckf366fcc2013-02-21 10:49:40 -0800337 switch (data->id) {
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700338 case ltc2978:
Guenter Roeckddfb41c2011-09-11 20:31:09 -0700339 info->read_word_data = ltc2978_read_word_data;
Guenter Roeck3d0d2832013-02-28 08:14:45 -0800340 info->pages = LTC2978_NUM_PAGES;
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700341 info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
342 | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
343 | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
Guenter Roeck3d0d2832013-02-28 08:14:45 -0800344 for (i = 1; i < LTC2978_NUM_PAGES; i++) {
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700345 info->func[i] = PMBUS_HAVE_VOUT
346 | PMBUS_HAVE_STATUS_VOUT;
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700347 }
348 break;
Guenter Roeckddfb41c2011-09-11 20:31:09 -0700349 case ltc3880:
350 info->read_word_data = ltc3880_read_word_data;
Guenter Roeck3d0d2832013-02-28 08:14:45 -0800351 info->pages = LTC3880_NUM_PAGES;
Guenter Roeckddfb41c2011-09-11 20:31:09 -0700352 info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
353 | PMBUS_HAVE_STATUS_INPUT
354 | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
355 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
356 | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
357 | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
358 info->func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
359 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
360 | PMBUS_HAVE_POUT
361 | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
Guenter Roeckdbd712c2013-02-21 09:33:25 -0800362 data->iout_max[0] = 0x7c00;
363 data->iout_max[1] = 0x7c00;
Guenter Roeckddfb41c2011-09-11 20:31:09 -0700364 break;
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700365 default:
Guenter Roeck8b313ca2012-02-22 08:56:43 -0800366 return -ENODEV;
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700367 }
Guenter Roeck8b313ca2012-02-22 08:56:43 -0800368 return pmbus_do_probe(client, id, info);
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700369}
370
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700371/* This is the driver that will be inserted */
372static struct i2c_driver ltc2978_driver = {
373 .driver = {
374 .name = "ltc2978",
375 },
376 .probe = ltc2978_probe,
Guenter Roeckdd285ad2012-02-22 08:56:44 -0800377 .remove = pmbus_do_remove,
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700378 .id_table = ltc2978_id,
379};
380
Axel Linf0967ee2012-01-20 15:38:18 +0800381module_i2c_driver(ltc2978_driver);
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700382
383MODULE_AUTHOR("Guenter Roeck");
Guenter Roeckddfb41c2011-09-11 20:31:09 -0700384MODULE_DESCRIPTION("PMBus driver for LTC2978 and LTC3880");
Guenter Roeckc3ff9a62011-09-02 09:58:37 -0700385MODULE_LICENSE("GPL");