.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Hardware monitoring driver for LM25056 / LM25066 / LM5064 / LM5066 |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (c) 2011 Ericsson AB. |
---|
5 | 6 | * 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 | 7 | */ |
---|
21 | 8 | |
---|
22 | 9 | #include <linux/bitops.h> |
---|
.. | .. |
---|
26 | 13 | #include <linux/err.h> |
---|
27 | 14 | #include <linux/slab.h> |
---|
28 | 15 | #include <linux/i2c.h> |
---|
| 16 | +#include <linux/log2.h> |
---|
29 | 17 | #include "pmbus.h" |
---|
30 | 18 | |
---|
31 | 19 | enum chips { lm25056, lm25066, lm5064, lm5066, lm5066i }; |
---|
.. | .. |
---|
39 | 27 | #define LM25066_CLEAR_PIN_PEAK 0xd6 |
---|
40 | 28 | #define LM25066_DEVICE_SETUP 0xd9 |
---|
41 | 29 | #define LM25066_READ_AVG_VIN 0xdc |
---|
| 30 | +#define LM25066_SAMPLES_FOR_AVG 0xdb |
---|
42 | 31 | #define LM25066_READ_AVG_VOUT 0xdd |
---|
43 | 32 | #define LM25066_READ_AVG_IIN 0xde |
---|
44 | 33 | #define LM25066_READ_AVG_PIN 0xdf |
---|
45 | 34 | |
---|
46 | 35 | #define LM25066_DEV_SETUP_CL BIT(4) /* Current limit */ |
---|
| 36 | + |
---|
| 37 | +#define LM25066_SAMPLES_FOR_AVG_MAX 4096 |
---|
47 | 38 | |
---|
48 | 39 | /* LM25056 only */ |
---|
49 | 40 | |
---|
.. | .. |
---|
243 | 234 | |
---|
244 | 235 | #define to_lm25066_data(x) container_of(x, struct lm25066_data, info) |
---|
245 | 236 | |
---|
246 | | -static int lm25066_read_word_data(struct i2c_client *client, int page, int reg) |
---|
| 237 | +static const struct i2c_device_id lm25066_id[]; |
---|
| 238 | + |
---|
| 239 | +static int lm25066_read_word_data(struct i2c_client *client, int page, |
---|
| 240 | + int phase, int reg) |
---|
247 | 241 | { |
---|
248 | 242 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); |
---|
249 | 243 | const struct lm25066_data *data = to_lm25066_data(info); |
---|
.. | .. |
---|
251 | 245 | |
---|
252 | 246 | switch (reg) { |
---|
253 | 247 | case PMBUS_VIRT_READ_VMON: |
---|
254 | | - ret = pmbus_read_word_data(client, 0, LM25066_READ_VAUX); |
---|
| 248 | + ret = pmbus_read_word_data(client, 0, 0xff, LM25066_READ_VAUX); |
---|
255 | 249 | if (ret < 0) |
---|
256 | 250 | break; |
---|
257 | 251 | /* Adjust returned value to match VIN coefficients */ |
---|
.. | .. |
---|
276 | 270 | } |
---|
277 | 271 | break; |
---|
278 | 272 | case PMBUS_READ_IIN: |
---|
279 | | - ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_IIN); |
---|
| 273 | + ret = pmbus_read_word_data(client, 0, 0xff, |
---|
| 274 | + LM25066_MFR_READ_IIN); |
---|
280 | 275 | break; |
---|
281 | 276 | case PMBUS_READ_PIN: |
---|
282 | | - ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_PIN); |
---|
| 277 | + ret = pmbus_read_word_data(client, 0, 0xff, |
---|
| 278 | + LM25066_MFR_READ_PIN); |
---|
283 | 279 | break; |
---|
284 | 280 | case PMBUS_IIN_OC_WARN_LIMIT: |
---|
285 | | - ret = pmbus_read_word_data(client, 0, |
---|
| 281 | + ret = pmbus_read_word_data(client, 0, 0xff, |
---|
286 | 282 | LM25066_MFR_IIN_OC_WARN_LIMIT); |
---|
287 | 283 | break; |
---|
288 | 284 | case PMBUS_PIN_OP_WARN_LIMIT: |
---|
289 | | - ret = pmbus_read_word_data(client, 0, |
---|
| 285 | + ret = pmbus_read_word_data(client, 0, 0xff, |
---|
290 | 286 | LM25066_MFR_PIN_OP_WARN_LIMIT); |
---|
291 | 287 | break; |
---|
292 | 288 | case PMBUS_VIRT_READ_VIN_AVG: |
---|
293 | | - ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VIN); |
---|
| 289 | + ret = pmbus_read_word_data(client, 0, 0xff, |
---|
| 290 | + LM25066_READ_AVG_VIN); |
---|
294 | 291 | break; |
---|
295 | 292 | case PMBUS_VIRT_READ_VOUT_AVG: |
---|
296 | | - ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VOUT); |
---|
| 293 | + ret = pmbus_read_word_data(client, 0, 0xff, |
---|
| 294 | + LM25066_READ_AVG_VOUT); |
---|
297 | 295 | break; |
---|
298 | 296 | case PMBUS_VIRT_READ_IIN_AVG: |
---|
299 | | - ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_IIN); |
---|
| 297 | + ret = pmbus_read_word_data(client, 0, 0xff, |
---|
| 298 | + LM25066_READ_AVG_IIN); |
---|
300 | 299 | break; |
---|
301 | 300 | case PMBUS_VIRT_READ_PIN_AVG: |
---|
302 | | - ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_PIN); |
---|
| 301 | + ret = pmbus_read_word_data(client, 0, 0xff, |
---|
| 302 | + LM25066_READ_AVG_PIN); |
---|
303 | 303 | break; |
---|
304 | 304 | case PMBUS_VIRT_READ_PIN_MAX: |
---|
305 | | - ret = pmbus_read_word_data(client, 0, LM25066_READ_PIN_PEAK); |
---|
| 305 | + ret = pmbus_read_word_data(client, 0, 0xff, |
---|
| 306 | + LM25066_READ_PIN_PEAK); |
---|
306 | 307 | break; |
---|
307 | 308 | case PMBUS_VIRT_RESET_PIN_HISTORY: |
---|
308 | 309 | ret = 0; |
---|
| 310 | + break; |
---|
| 311 | + case PMBUS_VIRT_SAMPLES: |
---|
| 312 | + ret = pmbus_read_byte_data(client, 0, LM25066_SAMPLES_FOR_AVG); |
---|
| 313 | + if (ret < 0) |
---|
| 314 | + break; |
---|
| 315 | + ret = 1 << ret; |
---|
309 | 316 | break; |
---|
310 | 317 | default: |
---|
311 | 318 | ret = -ENODATA; |
---|
.. | .. |
---|
314 | 321 | return ret; |
---|
315 | 322 | } |
---|
316 | 323 | |
---|
317 | | -static int lm25056_read_word_data(struct i2c_client *client, int page, int reg) |
---|
| 324 | +static int lm25056_read_word_data(struct i2c_client *client, int page, |
---|
| 325 | + int phase, int reg) |
---|
318 | 326 | { |
---|
319 | 327 | int ret; |
---|
320 | 328 | |
---|
321 | 329 | switch (reg) { |
---|
322 | 330 | case PMBUS_VIRT_VMON_UV_WARN_LIMIT: |
---|
323 | | - ret = pmbus_read_word_data(client, 0, |
---|
| 331 | + ret = pmbus_read_word_data(client, 0, 0xff, |
---|
324 | 332 | LM25056_VAUX_UV_WARN_LIMIT); |
---|
325 | 333 | if (ret < 0) |
---|
326 | 334 | break; |
---|
.. | .. |
---|
328 | 336 | ret = DIV_ROUND_CLOSEST(ret * 293, 6140); |
---|
329 | 337 | break; |
---|
330 | 338 | case PMBUS_VIRT_VMON_OV_WARN_LIMIT: |
---|
331 | | - ret = pmbus_read_word_data(client, 0, |
---|
| 339 | + ret = pmbus_read_word_data(client, 0, 0xff, |
---|
332 | 340 | LM25056_VAUX_OV_WARN_LIMIT); |
---|
333 | 341 | if (ret < 0) |
---|
334 | 342 | break; |
---|
.. | .. |
---|
336 | 344 | ret = DIV_ROUND_CLOSEST(ret * 293, 6140); |
---|
337 | 345 | break; |
---|
338 | 346 | default: |
---|
339 | | - ret = lm25066_read_word_data(client, page, reg); |
---|
| 347 | + ret = lm25066_read_word_data(client, page, phase, reg); |
---|
340 | 348 | break; |
---|
341 | 349 | } |
---|
342 | 350 | return ret; |
---|
.. | .. |
---|
421 | 429 | case PMBUS_VIRT_RESET_PIN_HISTORY: |
---|
422 | 430 | ret = pmbus_write_byte(client, 0, LM25066_CLEAR_PIN_PEAK); |
---|
423 | 431 | break; |
---|
| 432 | + case PMBUS_VIRT_SAMPLES: |
---|
| 433 | + word = clamp_val(word, 1, LM25066_SAMPLES_FOR_AVG_MAX); |
---|
| 434 | + ret = pmbus_write_byte_data(client, 0, LM25066_SAMPLES_FOR_AVG, |
---|
| 435 | + ilog2(word)); |
---|
| 436 | + break; |
---|
424 | 437 | default: |
---|
425 | 438 | ret = -ENODATA; |
---|
426 | 439 | break; |
---|
.. | .. |
---|
428 | 441 | return ret; |
---|
429 | 442 | } |
---|
430 | 443 | |
---|
431 | | -static int lm25066_probe(struct i2c_client *client, |
---|
432 | | - const struct i2c_device_id *id) |
---|
| 444 | +static int lm25066_probe(struct i2c_client *client) |
---|
433 | 445 | { |
---|
434 | 446 | int config; |
---|
435 | 447 | struct lm25066_data *data; |
---|
.. | .. |
---|
449 | 461 | if (config < 0) |
---|
450 | 462 | return config; |
---|
451 | 463 | |
---|
452 | | - data->id = id->driver_data; |
---|
| 464 | + data->id = i2c_match_id(lm25066_id, client)->driver_data; |
---|
453 | 465 | info = &data->info; |
---|
454 | 466 | |
---|
455 | 467 | info->pages = 1; |
---|
.. | .. |
---|
461 | 473 | |
---|
462 | 474 | info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VMON |
---|
463 | 475 | | PMBUS_HAVE_PIN | PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT |
---|
464 | | - | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; |
---|
| 476 | + | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_SAMPLES; |
---|
465 | 477 | |
---|
466 | 478 | if (data->id == lm25056) { |
---|
467 | 479 | info->func[0] |= PMBUS_HAVE_STATUS_VMON; |
---|
.. | .. |
---|
499 | 511 | info->b[PSC_POWER] = coeff[PSC_POWER].b; |
---|
500 | 512 | } |
---|
501 | 513 | |
---|
502 | | - return pmbus_do_probe(client, id, info); |
---|
| 514 | + return pmbus_do_probe(client, info); |
---|
503 | 515 | } |
---|
504 | 516 | |
---|
505 | 517 | static const struct i2c_device_id lm25066_id[] = { |
---|
.. | .. |
---|
518 | 530 | .driver = { |
---|
519 | 531 | .name = "lm25066", |
---|
520 | 532 | }, |
---|
521 | | - .probe = lm25066_probe, |
---|
| 533 | + .probe_new = lm25066_probe, |
---|
522 | 534 | .remove = pmbus_do_remove, |
---|
523 | 535 | .id_table = lm25066_id, |
---|
524 | 536 | }; |
---|