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