linux/drivers/hwmon/pmbus/lm25066.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Hardware monitoring driver for LM25056 / LM25066 / LM5064 / LM5066
   4 *
   5 * Copyright (c) 2011 Ericsson AB.
   6 * Copyright (c) 2013 Guenter Roeck
   7 */
   8
   9#include <linux/bitops.h>
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/init.h>
  13#include <linux/err.h>
  14#include <linux/slab.h>
  15#include <linux/i2c.h>
  16#include <linux/log2.h>
  17#include "pmbus.h"
  18
  19enum chips { lm25056, lm25066, lm5064, lm5066, lm5066i };
  20
  21#define LM25066_READ_VAUX               0xd0
  22#define LM25066_MFR_READ_IIN            0xd1
  23#define LM25066_MFR_READ_PIN            0xd2
  24#define LM25066_MFR_IIN_OC_WARN_LIMIT   0xd3
  25#define LM25066_MFR_PIN_OP_WARN_LIMIT   0xd4
  26#define LM25066_READ_PIN_PEAK           0xd5
  27#define LM25066_CLEAR_PIN_PEAK          0xd6
  28#define LM25066_DEVICE_SETUP            0xd9
  29#define LM25066_READ_AVG_VIN            0xdc
  30#define LM25066_SAMPLES_FOR_AVG         0xdb
  31#define LM25066_READ_AVG_VOUT           0xdd
  32#define LM25066_READ_AVG_IIN            0xde
  33#define LM25066_READ_AVG_PIN            0xdf
  34
  35#define LM25066_DEV_SETUP_CL            BIT(4)  /* Current limit */
  36
  37#define LM25066_SAMPLES_FOR_AVG_MAX     4096
  38
  39/* LM25056 only */
  40
  41#define LM25056_VAUX_OV_WARN_LIMIT      0xe3
  42#define LM25056_VAUX_UV_WARN_LIMIT      0xe4
  43
  44#define LM25056_MFR_STS_VAUX_OV_WARN    BIT(1)
  45#define LM25056_MFR_STS_VAUX_UV_WARN    BIT(0)
  46
  47struct __coeff {
  48        short m, b, R;
  49};
  50
  51#define PSC_CURRENT_IN_L        (PSC_NUM_CLASSES)
  52#define PSC_POWER_L             (PSC_NUM_CLASSES + 1)
  53
  54static struct __coeff lm25066_coeff[6][PSC_NUM_CLASSES + 2] = {
  55        [lm25056] = {
  56                [PSC_VOLTAGE_IN] = {
  57                        .m = 16296,
  58                        .R = -2,
  59                },
  60                [PSC_CURRENT_IN] = {
  61                        .m = 13797,
  62                        .R = -2,
  63                },
  64                [PSC_CURRENT_IN_L] = {
  65                        .m = 6726,
  66                        .R = -2,
  67                },
  68                [PSC_POWER] = {
  69                        .m = 5501,
  70                        .R = -3,
  71                },
  72                [PSC_POWER_L] = {
  73                        .m = 26882,
  74                        .R = -4,
  75                },
  76                [PSC_TEMPERATURE] = {
  77                        .m = 1580,
  78                        .b = -14500,
  79                        .R = -2,
  80                },
  81        },
  82        [lm25066] = {
  83                [PSC_VOLTAGE_IN] = {
  84                        .m = 22070,
  85                        .R = -2,
  86                },
  87                [PSC_VOLTAGE_OUT] = {
  88                        .m = 22070,
  89                        .R = -2,
  90                },
  91                [PSC_CURRENT_IN] = {
  92                        .m = 13661,
  93                        .R = -2,
  94                },
  95                [PSC_CURRENT_IN_L] = {
  96                        .m = 6852,
  97                        .R = -2,
  98                },
  99                [PSC_POWER] = {
 100                        .m = 736,
 101                        .R = -2,
 102                },
 103                [PSC_POWER_L] = {
 104                        .m = 369,
 105                        .R = -2,
 106                },
 107                [PSC_TEMPERATURE] = {
 108                        .m = 16,
 109                },
 110        },
 111        [lm5064] = {
 112                [PSC_VOLTAGE_IN] = {
 113                        .m = 4611,
 114                        .R = -2,
 115                },
 116                [PSC_VOLTAGE_OUT] = {
 117                        .m = 4621,
 118                        .R = -2,
 119                },
 120                [PSC_CURRENT_IN] = {
 121                        .m = 10742,
 122                        .R = -2,
 123                },
 124                [PSC_CURRENT_IN_L] = {
 125                        .m = 5456,
 126                        .R = -2,
 127                },
 128                [PSC_POWER] = {
 129                        .m = 1204,
 130                        .R = -3,
 131                },
 132                [PSC_POWER_L] = {
 133                        .m = 612,
 134                        .R = -3,
 135                },
 136                [PSC_TEMPERATURE] = {
 137                        .m = 16,
 138                },
 139        },
 140        [lm5066] = {
 141                [PSC_VOLTAGE_IN] = {
 142                        .m = 4587,
 143                        .R = -2,
 144                },
 145                [PSC_VOLTAGE_OUT] = {
 146                        .m = 4587,
 147                        .R = -2,
 148                },
 149                [PSC_CURRENT_IN] = {
 150                        .m = 10753,
 151                        .R = -2,
 152                },
 153                [PSC_CURRENT_IN_L] = {
 154                        .m = 5405,
 155                        .R = -2,
 156                },
 157                [PSC_POWER] = {
 158                        .m = 1204,
 159                        .R = -3,
 160                },
 161                [PSC_POWER_L] = {
 162                        .m = 605,
 163                        .R = -3,
 164                },
 165                [PSC_TEMPERATURE] = {
 166                        .m = 16,
 167                },
 168        },
 169        [lm5066i] = {
 170                [PSC_VOLTAGE_IN] = {
 171                        .m = 4617,
 172                        .b = -140,
 173                        .R = -2,
 174                },
 175                [PSC_VOLTAGE_OUT] = {
 176                        .m = 4602,
 177                        .b = 500,
 178                        .R = -2,
 179                },
 180                [PSC_CURRENT_IN] = {
 181                        .m = 15076,
 182                        .b = -504,
 183                        .R = -2,
 184                },
 185                [PSC_CURRENT_IN_L] = {
 186                        .m = 7645,
 187                        .b = 100,
 188                        .R = -2,
 189                },
 190                [PSC_POWER] = {
 191                        .m = 1701,
 192                        .b = -4000,
 193                        .R = -3,
 194                },
 195                [PSC_POWER_L] = {
 196                        .m = 861,
 197                        .b = -965,
 198                        .R = -3,
 199                },
 200                [PSC_TEMPERATURE] = {
 201                        .m = 16,
 202                },
 203        },
 204};
 205
 206struct lm25066_data {
 207        int id;
 208        u16 rlimit;                     /* Maximum register value */
 209        struct pmbus_driver_info info;
 210};
 211
 212#define to_lm25066_data(x)  container_of(x, struct lm25066_data, info)
 213
 214static const struct i2c_device_id lm25066_id[];
 215
 216static int lm25066_read_word_data(struct i2c_client *client, int page,
 217                                  int phase, int reg)
 218{
 219        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
 220        const struct lm25066_data *data = to_lm25066_data(info);
 221        int ret;
 222
 223        switch (reg) {
 224        case PMBUS_VIRT_READ_VMON:
 225                ret = pmbus_read_word_data(client, 0, 0xff, LM25066_READ_VAUX);
 226                if (ret < 0)
 227                        break;
 228                /* Adjust returned value to match VIN coefficients */
 229                switch (data->id) {
 230                case lm25056:
 231                        /* VIN: 6.14 mV VAUX: 293 uV LSB */
 232                        ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
 233                        break;
 234                case lm25066:
 235                        /* VIN: 4.54 mV VAUX: 283.2 uV LSB */
 236                        ret = DIV_ROUND_CLOSEST(ret * 2832, 45400);
 237                        break;
 238                case lm5064:
 239                        /* VIN: 4.53 mV VAUX: 700 uV LSB */
 240                        ret = DIV_ROUND_CLOSEST(ret * 70, 453);
 241                        break;
 242                case lm5066:
 243                case lm5066i:
 244                        /* VIN: 2.18 mV VAUX: 725 uV LSB */
 245                        ret = DIV_ROUND_CLOSEST(ret * 725, 2180);
 246                        break;
 247                }
 248                break;
 249        case PMBUS_READ_IIN:
 250                ret = pmbus_read_word_data(client, 0, 0xff,
 251                                           LM25066_MFR_READ_IIN);
 252                break;
 253        case PMBUS_READ_PIN:
 254                ret = pmbus_read_word_data(client, 0, 0xff,
 255                                           LM25066_MFR_READ_PIN);
 256                break;
 257        case PMBUS_IIN_OC_WARN_LIMIT:
 258                ret = pmbus_read_word_data(client, 0, 0xff,
 259                                           LM25066_MFR_IIN_OC_WARN_LIMIT);
 260                break;
 261        case PMBUS_PIN_OP_WARN_LIMIT:
 262                ret = pmbus_read_word_data(client, 0, 0xff,
 263                                           LM25066_MFR_PIN_OP_WARN_LIMIT);
 264                break;
 265        case PMBUS_VIRT_READ_VIN_AVG:
 266                ret = pmbus_read_word_data(client, 0, 0xff,
 267                                           LM25066_READ_AVG_VIN);
 268                break;
 269        case PMBUS_VIRT_READ_VOUT_AVG:
 270                ret = pmbus_read_word_data(client, 0, 0xff,
 271                                           LM25066_READ_AVG_VOUT);
 272                break;
 273        case PMBUS_VIRT_READ_IIN_AVG:
 274                ret = pmbus_read_word_data(client, 0, 0xff,
 275                                           LM25066_READ_AVG_IIN);
 276                break;
 277        case PMBUS_VIRT_READ_PIN_AVG:
 278                ret = pmbus_read_word_data(client, 0, 0xff,
 279                                           LM25066_READ_AVG_PIN);
 280                break;
 281        case PMBUS_VIRT_READ_PIN_MAX:
 282                ret = pmbus_read_word_data(client, 0, 0xff,
 283                                           LM25066_READ_PIN_PEAK);
 284                break;
 285        case PMBUS_VIRT_RESET_PIN_HISTORY:
 286                ret = 0;
 287                break;
 288        case PMBUS_VIRT_SAMPLES:
 289                ret = pmbus_read_byte_data(client, 0, LM25066_SAMPLES_FOR_AVG);
 290                if (ret < 0)
 291                        break;
 292                ret = 1 << ret;
 293                break;
 294        default:
 295                ret = -ENODATA;
 296                break;
 297        }
 298        return ret;
 299}
 300
 301static int lm25056_read_word_data(struct i2c_client *client, int page,
 302                                  int phase, int reg)
 303{
 304        int ret;
 305
 306        switch (reg) {
 307        case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
 308                ret = pmbus_read_word_data(client, 0, 0xff,
 309                                           LM25056_VAUX_UV_WARN_LIMIT);
 310                if (ret < 0)
 311                        break;
 312                /* Adjust returned value to match VIN coefficients */
 313                ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
 314                break;
 315        case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
 316                ret = pmbus_read_word_data(client, 0, 0xff,
 317                                           LM25056_VAUX_OV_WARN_LIMIT);
 318                if (ret < 0)
 319                        break;
 320                /* Adjust returned value to match VIN coefficients */
 321                ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
 322                break;
 323        default:
 324                ret = lm25066_read_word_data(client, page, phase, reg);
 325                break;
 326        }
 327        return ret;
 328}
 329
 330static int lm25056_read_byte_data(struct i2c_client *client, int page, int reg)
 331{
 332        int ret, s;
 333
 334        switch (reg) {
 335        case PMBUS_VIRT_STATUS_VMON:
 336                ret = pmbus_read_byte_data(client, 0,
 337                                           PMBUS_STATUS_MFR_SPECIFIC);
 338                if (ret < 0)
 339                        break;
 340                s = 0;
 341                if (ret & LM25056_MFR_STS_VAUX_UV_WARN)
 342                        s |= PB_VOLTAGE_UV_WARNING;
 343                if (ret & LM25056_MFR_STS_VAUX_OV_WARN)
 344                        s |= PB_VOLTAGE_OV_WARNING;
 345                ret = s;
 346                break;
 347        default:
 348                ret = -ENODATA;
 349                break;
 350        }
 351        return ret;
 352}
 353
 354static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
 355                                   u16 word)
 356{
 357        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
 358        const struct lm25066_data *data = to_lm25066_data(info);
 359        int ret;
 360
 361        switch (reg) {
 362        case PMBUS_POUT_OP_FAULT_LIMIT:
 363        case PMBUS_POUT_OP_WARN_LIMIT:
 364        case PMBUS_VOUT_UV_WARN_LIMIT:
 365        case PMBUS_OT_FAULT_LIMIT:
 366        case PMBUS_OT_WARN_LIMIT:
 367        case PMBUS_IIN_OC_FAULT_LIMIT:
 368        case PMBUS_VIN_UV_WARN_LIMIT:
 369        case PMBUS_VIN_UV_FAULT_LIMIT:
 370        case PMBUS_VIN_OV_FAULT_LIMIT:
 371        case PMBUS_VIN_OV_WARN_LIMIT:
 372                word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
 373                ret = pmbus_write_word_data(client, 0, reg, word);
 374                pmbus_clear_cache(client);
 375                break;
 376        case PMBUS_IIN_OC_WARN_LIMIT:
 377                word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
 378                ret = pmbus_write_word_data(client, 0,
 379                                            LM25066_MFR_IIN_OC_WARN_LIMIT,
 380                                            word);
 381                pmbus_clear_cache(client);
 382                break;
 383        case PMBUS_PIN_OP_WARN_LIMIT:
 384                word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
 385                ret = pmbus_write_word_data(client, 0,
 386                                            LM25066_MFR_PIN_OP_WARN_LIMIT,
 387                                            word);
 388                pmbus_clear_cache(client);
 389                break;
 390        case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
 391                /* Adjust from VIN coefficients (for LM25056) */
 392                word = DIV_ROUND_CLOSEST((int)word * 6140, 293);
 393                word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
 394                ret = pmbus_write_word_data(client, 0,
 395                                            LM25056_VAUX_UV_WARN_LIMIT, word);
 396                pmbus_clear_cache(client);
 397                break;
 398        case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
 399                /* Adjust from VIN coefficients (for LM25056) */
 400                word = DIV_ROUND_CLOSEST((int)word * 6140, 293);
 401                word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
 402                ret = pmbus_write_word_data(client, 0,
 403                                            LM25056_VAUX_OV_WARN_LIMIT, word);
 404                pmbus_clear_cache(client);
 405                break;
 406        case PMBUS_VIRT_RESET_PIN_HISTORY:
 407                ret = pmbus_write_byte(client, 0, LM25066_CLEAR_PIN_PEAK);
 408                break;
 409        case PMBUS_VIRT_SAMPLES:
 410                word = clamp_val(word, 1, LM25066_SAMPLES_FOR_AVG_MAX);
 411                ret = pmbus_write_byte_data(client, 0, LM25066_SAMPLES_FOR_AVG,
 412                                            ilog2(word));
 413                break;
 414        default:
 415                ret = -ENODATA;
 416                break;
 417        }
 418        return ret;
 419}
 420
 421static int lm25066_probe(struct i2c_client *client)
 422{
 423        int config;
 424        struct lm25066_data *data;
 425        struct pmbus_driver_info *info;
 426        struct __coeff *coeff;
 427
 428        if (!i2c_check_functionality(client->adapter,
 429                                     I2C_FUNC_SMBUS_READ_BYTE_DATA))
 430                return -ENODEV;
 431
 432        data = devm_kzalloc(&client->dev, sizeof(struct lm25066_data),
 433                            GFP_KERNEL);
 434        if (!data)
 435                return -ENOMEM;
 436
 437        config = i2c_smbus_read_byte_data(client, LM25066_DEVICE_SETUP);
 438        if (config < 0)
 439                return config;
 440
 441        data->id = i2c_match_id(lm25066_id, client)->driver_data;
 442        info = &data->info;
 443
 444        info->pages = 1;
 445        info->format[PSC_VOLTAGE_IN] = direct;
 446        info->format[PSC_VOLTAGE_OUT] = direct;
 447        info->format[PSC_CURRENT_IN] = direct;
 448        info->format[PSC_TEMPERATURE] = direct;
 449        info->format[PSC_POWER] = direct;
 450
 451        info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VMON
 452          | PMBUS_HAVE_PIN | PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT
 453          | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_SAMPLES;
 454
 455        if (data->id == lm25056) {
 456                info->func[0] |= PMBUS_HAVE_STATUS_VMON;
 457                info->read_word_data = lm25056_read_word_data;
 458                info->read_byte_data = lm25056_read_byte_data;
 459                data->rlimit = 0x0fff;
 460        } else {
 461                info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
 462                info->read_word_data = lm25066_read_word_data;
 463                data->rlimit = 0x0fff;
 464        }
 465        info->write_word_data = lm25066_write_word_data;
 466
 467        coeff = &lm25066_coeff[data->id][0];
 468        info->m[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].m;
 469        info->b[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].b;
 470        info->R[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].R;
 471        info->m[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].m;
 472        info->b[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].b;
 473        info->R[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].R;
 474        info->m[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].m;
 475        info->b[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].b;
 476        info->R[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].R;
 477        info->R[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].R;
 478        info->R[PSC_POWER] = coeff[PSC_POWER].R;
 479        if (config & LM25066_DEV_SETUP_CL) {
 480                info->m[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN_L].m;
 481                info->b[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN_L].b;
 482                info->m[PSC_POWER] = coeff[PSC_POWER_L].m;
 483                info->b[PSC_POWER] = coeff[PSC_POWER_L].b;
 484        } else {
 485                info->m[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].m;
 486                info->b[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].b;
 487                info->m[PSC_POWER] = coeff[PSC_POWER].m;
 488                info->b[PSC_POWER] = coeff[PSC_POWER].b;
 489        }
 490
 491        return pmbus_do_probe(client, info);
 492}
 493
 494static const struct i2c_device_id lm25066_id[] = {
 495        {"lm25056", lm25056},
 496        {"lm25066", lm25066},
 497        {"lm5064", lm5064},
 498        {"lm5066", lm5066},
 499        {"lm5066i", lm5066i},
 500        { }
 501};
 502
 503MODULE_DEVICE_TABLE(i2c, lm25066_id);
 504
 505/* This is the driver that will be inserted */
 506static struct i2c_driver lm25066_driver = {
 507        .driver = {
 508                   .name = "lm25066",
 509                   },
 510        .probe_new = lm25066_probe,
 511        .id_table = lm25066_id,
 512};
 513
 514module_i2c_driver(lm25066_driver);
 515
 516MODULE_AUTHOR("Guenter Roeck");
 517MODULE_DESCRIPTION("PMBus driver for LM25066 and compatible chips");
 518MODULE_LICENSE("GPL");
 519