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