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 int lm25066_read_word_data(struct i2c_client *client, int page, int reg)
 215{
 216        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
 217        const struct lm25066_data *data = to_lm25066_data(info);
 218        int ret;
 219
 220        switch (reg) {
 221        case PMBUS_VIRT_READ_VMON:
 222                ret = pmbus_read_word_data(client, 0, LM25066_READ_VAUX);
 223                if (ret < 0)
 224                        break;
 225                /* Adjust returned value to match VIN coefficients */
 226                switch (data->id) {
 227                case lm25056:
 228                        /* VIN: 6.14 mV VAUX: 293 uV LSB */
 229                        ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
 230                        break;
 231                case lm25066:
 232                        /* VIN: 4.54 mV VAUX: 283.2 uV LSB */
 233                        ret = DIV_ROUND_CLOSEST(ret * 2832, 45400);
 234                        break;
 235                case lm5064:
 236                        /* VIN: 4.53 mV VAUX: 700 uV LSB */
 237                        ret = DIV_ROUND_CLOSEST(ret * 70, 453);
 238                        break;
 239                case lm5066:
 240                case lm5066i:
 241                        /* VIN: 2.18 mV VAUX: 725 uV LSB */
 242                        ret = DIV_ROUND_CLOSEST(ret * 725, 2180);
 243                        break;
 244                }
 245                break;
 246        case PMBUS_READ_IIN:
 247                ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_IIN);
 248                break;
 249        case PMBUS_READ_PIN:
 250                ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_PIN);
 251                break;
 252        case PMBUS_IIN_OC_WARN_LIMIT:
 253                ret = pmbus_read_word_data(client, 0,
 254                                           LM25066_MFR_IIN_OC_WARN_LIMIT);
 255                break;
 256        case PMBUS_PIN_OP_WARN_LIMIT:
 257                ret = pmbus_read_word_data(client, 0,
 258                                           LM25066_MFR_PIN_OP_WARN_LIMIT);
 259                break;
 260        case PMBUS_VIRT_READ_VIN_AVG:
 261                ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VIN);
 262                break;
 263        case PMBUS_VIRT_READ_VOUT_AVG:
 264                ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VOUT);
 265                break;
 266        case PMBUS_VIRT_READ_IIN_AVG:
 267                ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_IIN);
 268                break;
 269        case PMBUS_VIRT_READ_PIN_AVG:
 270                ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_PIN);
 271                break;
 272        case PMBUS_VIRT_READ_PIN_MAX:
 273                ret = pmbus_read_word_data(client, 0, LM25066_READ_PIN_PEAK);
 274                break;
 275        case PMBUS_VIRT_RESET_PIN_HISTORY:
 276                ret = 0;
 277                break;
 278        case PMBUS_VIRT_SAMPLES:
 279                ret = pmbus_read_byte_data(client, 0, LM25066_SAMPLES_FOR_AVG);
 280                if (ret < 0)
 281                        break;
 282                ret = 1 << ret;
 283                break;
 284        default:
 285                ret = -ENODATA;
 286                break;
 287        }
 288        return ret;
 289}
 290
 291static int lm25056_read_word_data(struct i2c_client *client, int page, int reg)
 292{
 293        int ret;
 294
 295        switch (reg) {
 296        case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
 297                ret = pmbus_read_word_data(client, 0,
 298                                           LM25056_VAUX_UV_WARN_LIMIT);
 299                if (ret < 0)
 300                        break;
 301                /* Adjust returned value to match VIN coefficients */
 302                ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
 303                break;
 304        case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
 305                ret = pmbus_read_word_data(client, 0,
 306                                           LM25056_VAUX_OV_WARN_LIMIT);
 307                if (ret < 0)
 308                        break;
 309                /* Adjust returned value to match VIN coefficients */
 310                ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
 311                break;
 312        default:
 313                ret = lm25066_read_word_data(client, page, reg);
 314                break;
 315        }
 316        return ret;
 317}
 318
 319static int lm25056_read_byte_data(struct i2c_client *client, int page, int reg)
 320{
 321        int ret, s;
 322
 323        switch (reg) {
 324        case PMBUS_VIRT_STATUS_VMON:
 325                ret = pmbus_read_byte_data(client, 0,
 326                                           PMBUS_STATUS_MFR_SPECIFIC);
 327                if (ret < 0)
 328                        break;
 329                s = 0;
 330                if (ret & LM25056_MFR_STS_VAUX_UV_WARN)
 331                        s |= PB_VOLTAGE_UV_WARNING;
 332                if (ret & LM25056_MFR_STS_VAUX_OV_WARN)
 333                        s |= PB_VOLTAGE_OV_WARNING;
 334                ret = s;
 335                break;
 336        default:
 337                ret = -ENODATA;
 338                break;
 339        }
 340        return ret;
 341}
 342
 343static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
 344                                   u16 word)
 345{
 346        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
 347        const struct lm25066_data *data = to_lm25066_data(info);
 348        int ret;
 349
 350        switch (reg) {
 351        case PMBUS_POUT_OP_FAULT_LIMIT:
 352        case PMBUS_POUT_OP_WARN_LIMIT:
 353        case PMBUS_VOUT_UV_WARN_LIMIT:
 354        case PMBUS_OT_FAULT_LIMIT:
 355        case PMBUS_OT_WARN_LIMIT:
 356        case PMBUS_IIN_OC_FAULT_LIMIT:
 357        case PMBUS_VIN_UV_WARN_LIMIT:
 358        case PMBUS_VIN_UV_FAULT_LIMIT:
 359        case PMBUS_VIN_OV_FAULT_LIMIT:
 360        case PMBUS_VIN_OV_WARN_LIMIT:
 361                word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
 362                ret = pmbus_write_word_data(client, 0, reg, word);
 363                pmbus_clear_cache(client);
 364                break;
 365        case PMBUS_IIN_OC_WARN_LIMIT:
 366                word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
 367                ret = pmbus_write_word_data(client, 0,
 368                                            LM25066_MFR_IIN_OC_WARN_LIMIT,
 369                                            word);
 370                pmbus_clear_cache(client);
 371                break;
 372        case PMBUS_PIN_OP_WARN_LIMIT:
 373                word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
 374                ret = pmbus_write_word_data(client, 0,
 375                                            LM25066_MFR_PIN_OP_WARN_LIMIT,
 376                                            word);
 377                pmbus_clear_cache(client);
 378                break;
 379        case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
 380                /* Adjust from VIN coefficients (for LM25056) */
 381                word = DIV_ROUND_CLOSEST((int)word * 6140, 293);
 382                word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
 383                ret = pmbus_write_word_data(client, 0,
 384                                            LM25056_VAUX_UV_WARN_LIMIT, word);
 385                pmbus_clear_cache(client);
 386                break;
 387        case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
 388                /* Adjust from VIN coefficients (for LM25056) */
 389                word = DIV_ROUND_CLOSEST((int)word * 6140, 293);
 390                word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
 391                ret = pmbus_write_word_data(client, 0,
 392                                            LM25056_VAUX_OV_WARN_LIMIT, word);
 393                pmbus_clear_cache(client);
 394                break;
 395        case PMBUS_VIRT_RESET_PIN_HISTORY:
 396                ret = pmbus_write_byte(client, 0, LM25066_CLEAR_PIN_PEAK);
 397                break;
 398        case PMBUS_VIRT_SAMPLES:
 399                word = clamp_val(word, 1, LM25066_SAMPLES_FOR_AVG_MAX);
 400                ret = pmbus_write_byte_data(client, 0, LM25066_SAMPLES_FOR_AVG,
 401                                            ilog2(word));
 402                break;
 403        default:
 404                ret = -ENODATA;
 405                break;
 406        }
 407        return ret;
 408}
 409
 410static int lm25066_probe(struct i2c_client *client,
 411                          const struct i2c_device_id *id)
 412{
 413        int config;
 414        struct lm25066_data *data;
 415        struct pmbus_driver_info *info;
 416        struct __coeff *coeff;
 417
 418        if (!i2c_check_functionality(client->adapter,
 419                                     I2C_FUNC_SMBUS_READ_BYTE_DATA))
 420                return -ENODEV;
 421
 422        data = devm_kzalloc(&client->dev, sizeof(struct lm25066_data),
 423                            GFP_KERNEL);
 424        if (!data)
 425                return -ENOMEM;
 426
 427        config = i2c_smbus_read_byte_data(client, LM25066_DEVICE_SETUP);
 428        if (config < 0)
 429                return config;
 430
 431        data->id = id->driver_data;
 432        info = &data->info;
 433
 434        info->pages = 1;
 435        info->format[PSC_VOLTAGE_IN] = direct;
 436        info->format[PSC_VOLTAGE_OUT] = direct;
 437        info->format[PSC_CURRENT_IN] = direct;
 438        info->format[PSC_TEMPERATURE] = direct;
 439        info->format[PSC_POWER] = direct;
 440
 441        info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VMON
 442          | PMBUS_HAVE_PIN | PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT
 443          | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_SAMPLES;
 444
 445        if (data->id == lm25056) {
 446                info->func[0] |= PMBUS_HAVE_STATUS_VMON;
 447                info->read_word_data = lm25056_read_word_data;
 448                info->read_byte_data = lm25056_read_byte_data;
 449                data->rlimit = 0x0fff;
 450        } else {
 451                info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
 452                info->read_word_data = lm25066_read_word_data;
 453                data->rlimit = 0x0fff;
 454        }
 455        info->write_word_data = lm25066_write_word_data;
 456
 457        coeff = &lm25066_coeff[data->id][0];
 458        info->m[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].m;
 459        info->b[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].b;
 460        info->R[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].R;
 461        info->m[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].m;
 462        info->b[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].b;
 463        info->R[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].R;
 464        info->m[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].m;
 465        info->b[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].b;
 466        info->R[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].R;
 467        info->R[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].R;
 468        info->R[PSC_POWER] = coeff[PSC_POWER].R;
 469        if (config & LM25066_DEV_SETUP_CL) {
 470                info->m[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN_L].m;
 471                info->b[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN_L].b;
 472                info->m[PSC_POWER] = coeff[PSC_POWER_L].m;
 473                info->b[PSC_POWER] = coeff[PSC_POWER_L].b;
 474        } else {
 475                info->m[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].m;
 476                info->b[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].b;
 477                info->m[PSC_POWER] = coeff[PSC_POWER].m;
 478                info->b[PSC_POWER] = coeff[PSC_POWER].b;
 479        }
 480
 481        return pmbus_do_probe(client, id, info);
 482}
 483
 484static const struct i2c_device_id lm25066_id[] = {
 485        {"lm25056", lm25056},
 486        {"lm25066", lm25066},
 487        {"lm5064", lm5064},
 488        {"lm5066", lm5066},
 489        {"lm5066i", lm5066i},
 490        { }
 491};
 492
 493MODULE_DEVICE_TABLE(i2c, lm25066_id);
 494
 495/* This is the driver that will be inserted */
 496static struct i2c_driver lm25066_driver = {
 497        .driver = {
 498                   .name = "lm25066",
 499                   },
 500        .probe = lm25066_probe,
 501        .remove = pmbus_do_remove,
 502        .id_table = lm25066_id,
 503};
 504
 505module_i2c_driver(lm25066_driver);
 506
 507MODULE_AUTHOR("Guenter Roeck");
 508MODULE_DESCRIPTION("PMBus driver for LM25066 and compatible chips");
 509MODULE_LICENSE("GPL");
 510