linux/drivers/hwmon/pmbus/lm25066.c
<<
>>
Prefs
   1/*
   2 * Hardware monitoring driver for LM25056 / 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, lm25066, lm5064, lm5066, lm5066i };
  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
  56struct __coeff {
  57        short m, b, R;
  58};
  59
  60#define PSC_CURRENT_IN_L        (PSC_NUM_CLASSES)
  61#define PSC_POWER_L             (PSC_NUM_CLASSES + 1)
  62
  63static struct __coeff lm25066_coeff[6][PSC_NUM_CLASSES + 2] = {
  64        [lm25056] = {
  65                [PSC_VOLTAGE_IN] = {
  66                        .m = 16296,
  67                        .R = -2,
  68                },
  69                [PSC_CURRENT_IN] = {
  70                        .m = 13797,
  71                        .R = -2,
  72                },
  73                [PSC_CURRENT_IN_L] = {
  74                        .m = 6726,
  75                        .R = -2,
  76                },
  77                [PSC_POWER] = {
  78                        .m = 5501,
  79                        .R = -3,
  80                },
  81                [PSC_POWER_L] = {
  82                        .m = 26882,
  83                        .R = -4,
  84                },
  85                [PSC_TEMPERATURE] = {
  86                        .m = 1580,
  87                        .b = -14500,
  88                        .R = -2,
  89                },
  90        },
  91        [lm25066] = {
  92                [PSC_VOLTAGE_IN] = {
  93                        .m = 22070,
  94                        .R = -2,
  95                },
  96                [PSC_VOLTAGE_OUT] = {
  97                        .m = 22070,
  98                        .R = -2,
  99                },
 100                [PSC_CURRENT_IN] = {
 101                        .m = 13661,
 102                        .R = -2,
 103                },
 104                [PSC_CURRENT_IN_L] = {
 105                        .m = 6852,
 106                        .R = -2,
 107                },
 108                [PSC_POWER] = {
 109                        .m = 736,
 110                        .R = -2,
 111                },
 112                [PSC_POWER_L] = {
 113                        .m = 369,
 114                        .R = -2,
 115                },
 116                [PSC_TEMPERATURE] = {
 117                        .m = 16,
 118                },
 119        },
 120        [lm5064] = {
 121                [PSC_VOLTAGE_IN] = {
 122                        .m = 4611,
 123                        .R = -2,
 124                },
 125                [PSC_VOLTAGE_OUT] = {
 126                        .m = 4621,
 127                        .R = -2,
 128                },
 129                [PSC_CURRENT_IN] = {
 130                        .m = 10742,
 131                        .R = -2,
 132                },
 133                [PSC_CURRENT_IN_L] = {
 134                        .m = 5456,
 135                        .R = -2,
 136                },
 137                [PSC_POWER] = {
 138                        .m = 1204,
 139                        .R = -3,
 140                },
 141                [PSC_POWER_L] = {
 142                        .m = 612,
 143                        .R = -3,
 144                },
 145                [PSC_TEMPERATURE] = {
 146                        .m = 16,
 147                },
 148        },
 149        [lm5066] = {
 150                [PSC_VOLTAGE_IN] = {
 151                        .m = 4587,
 152                        .R = -2,
 153                },
 154                [PSC_VOLTAGE_OUT] = {
 155                        .m = 4587,
 156                        .R = -2,
 157                },
 158                [PSC_CURRENT_IN] = {
 159                        .m = 10753,
 160                        .R = -2,
 161                },
 162                [PSC_CURRENT_IN_L] = {
 163                        .m = 5405,
 164                        .R = -2,
 165                },
 166                [PSC_POWER] = {
 167                        .m = 1204,
 168                        .R = -3,
 169                },
 170                [PSC_POWER_L] = {
 171                        .m = 605,
 172                        .R = -3,
 173                },
 174                [PSC_TEMPERATURE] = {
 175                        .m = 16,
 176                },
 177        },
 178        [lm5066i] = {
 179                [PSC_VOLTAGE_IN] = {
 180                        .m = 4617,
 181                        .b = -140,
 182                        .R = -2,
 183                },
 184                [PSC_VOLTAGE_OUT] = {
 185                        .m = 4602,
 186                        .b = 500,
 187                        .R = -2,
 188                },
 189                [PSC_CURRENT_IN] = {
 190                        .m = 15076,
 191                        .b = -504,
 192                        .R = -2,
 193                },
 194                [PSC_CURRENT_IN_L] = {
 195                        .m = 7645,
 196                        .b = 100,
 197                        .R = -2,
 198                },
 199                [PSC_POWER] = {
 200                        .m = 1701,
 201                        .b = -4000,
 202                        .R = -3,
 203                },
 204                [PSC_POWER_L] = {
 205                        .m = 861,
 206                        .b = -965,
 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 lm25066:
 241                        /* VIN: 4.54 mV VAUX: 283.2 uV LSB */
 242                        ret = DIV_ROUND_CLOSEST(ret * 2832, 45400);
 243                        break;
 244                case lm5064:
 245                        /* VIN: 4.53 mV VAUX: 700 uV LSB */
 246                        ret = DIV_ROUND_CLOSEST(ret * 70, 453);
 247                        break;
 248                case lm5066:
 249                case lm5066i:
 250                        /* VIN: 2.18 mV VAUX: 725 uV LSB */
 251                        ret = DIV_ROUND_CLOSEST(ret * 725, 2180);
 252                        break;
 253                }
 254                break;
 255        case PMBUS_READ_IIN:
 256                ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_IIN);
 257                break;
 258        case PMBUS_READ_PIN:
 259                ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_PIN);
 260                break;
 261        case PMBUS_IIN_OC_WARN_LIMIT:
 262                ret = pmbus_read_word_data(client, 0,
 263                                           LM25066_MFR_IIN_OC_WARN_LIMIT);
 264                break;
 265        case PMBUS_PIN_OP_WARN_LIMIT:
 266                ret = pmbus_read_word_data(client, 0,
 267                                           LM25066_MFR_PIN_OP_WARN_LIMIT);
 268                break;
 269        case PMBUS_VIRT_READ_VIN_AVG:
 270                ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VIN);
 271                break;
 272        case PMBUS_VIRT_READ_VOUT_AVG:
 273                ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VOUT);
 274                break;
 275        case PMBUS_VIRT_READ_IIN_AVG:
 276                ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_IIN);
 277                break;
 278        case PMBUS_VIRT_READ_PIN_AVG:
 279                ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_PIN);
 280                break;
 281        case PMBUS_VIRT_READ_PIN_MAX:
 282                ret = pmbus_read_word_data(client, 0, LM25066_READ_PIN_PEAK);
 283                break;
 284        case PMBUS_VIRT_RESET_PIN_HISTORY:
 285                ret = 0;
 286                break;
 287        default:
 288                ret = -ENODATA;
 289                break;
 290        }
 291        return ret;
 292}
 293
 294static int lm25056_read_word_data(struct i2c_client *client, int page, int reg)
 295{
 296        int ret;
 297
 298        switch (reg) {
 299        case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
 300                ret = pmbus_read_word_data(client, 0,
 301                                           LM25056_VAUX_UV_WARN_LIMIT);
 302                if (ret < 0)
 303                        break;
 304                /* Adjust returned value to match VIN coefficients */
 305                ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
 306                break;
 307        case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
 308                ret = pmbus_read_word_data(client, 0,
 309                                           LM25056_VAUX_OV_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        default:
 316                ret = lm25066_read_word_data(client, page, reg);
 317                break;
 318        }
 319        return ret;
 320}
 321
 322static int lm25056_read_byte_data(struct i2c_client *client, int page, int reg)
 323{
 324        int ret, s;
 325
 326        switch (reg) {
 327        case PMBUS_VIRT_STATUS_VMON:
 328                ret = pmbus_read_byte_data(client, 0,
 329                                           PMBUS_STATUS_MFR_SPECIFIC);
 330                if (ret < 0)
 331                        break;
 332                s = 0;
 333                if (ret & LM25056_MFR_STS_VAUX_UV_WARN)
 334                        s |= PB_VOLTAGE_UV_WARNING;
 335                if (ret & LM25056_MFR_STS_VAUX_OV_WARN)
 336                        s |= PB_VOLTAGE_OV_WARNING;
 337                ret = s;
 338                break;
 339        default:
 340                ret = -ENODATA;
 341                break;
 342        }
 343        return ret;
 344}
 345
 346static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
 347                                   u16 word)
 348{
 349        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
 350        const struct lm25066_data *data = to_lm25066_data(info);
 351        int ret;
 352
 353        switch (reg) {
 354        case PMBUS_POUT_OP_FAULT_LIMIT:
 355        case PMBUS_POUT_OP_WARN_LIMIT:
 356        case PMBUS_VOUT_UV_WARN_LIMIT:
 357        case PMBUS_OT_FAULT_LIMIT:
 358        case PMBUS_OT_WARN_LIMIT:
 359        case PMBUS_IIN_OC_FAULT_LIMIT:
 360        case PMBUS_VIN_UV_WARN_LIMIT:
 361        case PMBUS_VIN_UV_FAULT_LIMIT:
 362        case PMBUS_VIN_OV_FAULT_LIMIT:
 363        case PMBUS_VIN_OV_WARN_LIMIT:
 364                word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
 365                ret = pmbus_write_word_data(client, 0, reg, word);
 366                pmbus_clear_cache(client);
 367                break;
 368        case PMBUS_IIN_OC_WARN_LIMIT:
 369                word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
 370                ret = pmbus_write_word_data(client, 0,
 371                                            LM25066_MFR_IIN_OC_WARN_LIMIT,
 372                                            word);
 373                pmbus_clear_cache(client);
 374                break;
 375        case PMBUS_PIN_OP_WARN_LIMIT:
 376                word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
 377                ret = pmbus_write_word_data(client, 0,
 378                                            LM25066_MFR_PIN_OP_WARN_LIMIT,
 379                                            word);
 380                pmbus_clear_cache(client);
 381                break;
 382        case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
 383                /* Adjust from VIN coefficients (for LM25056) */
 384                word = DIV_ROUND_CLOSEST((int)word * 6140, 293);
 385                word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
 386                ret = pmbus_write_word_data(client, 0,
 387                                            LM25056_VAUX_UV_WARN_LIMIT, word);
 388                pmbus_clear_cache(client);
 389                break;
 390        case PMBUS_VIRT_VMON_OV_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_OV_WARN_LIMIT, word);
 396                pmbus_clear_cache(client);
 397                break;
 398        case PMBUS_VIRT_RESET_PIN_HISTORY:
 399                ret = pmbus_write_byte(client, 0, LM25066_CLEAR_PIN_PEAK);
 400                break;
 401        default:
 402                ret = -ENODATA;
 403                break;
 404        }
 405        return ret;
 406}
 407
 408static int lm25066_probe(struct i2c_client *client,
 409                          const struct i2c_device_id *id)
 410{
 411        int config;
 412        struct lm25066_data *data;
 413        struct pmbus_driver_info *info;
 414        struct __coeff *coeff;
 415
 416        if (!i2c_check_functionality(client->adapter,
 417                                     I2C_FUNC_SMBUS_READ_BYTE_DATA))
 418                return -ENODEV;
 419
 420        data = devm_kzalloc(&client->dev, sizeof(struct lm25066_data),
 421                            GFP_KERNEL);
 422        if (!data)
 423                return -ENOMEM;
 424
 425        config = i2c_smbus_read_byte_data(client, LM25066_DEVICE_SETUP);
 426        if (config < 0)
 427                return config;
 428
 429        data->id = id->driver_data;
 430        info = &data->info;
 431
 432        info->pages = 1;
 433        info->format[PSC_VOLTAGE_IN] = direct;
 434        info->format[PSC_VOLTAGE_OUT] = direct;
 435        info->format[PSC_CURRENT_IN] = direct;
 436        info->format[PSC_TEMPERATURE] = direct;
 437        info->format[PSC_POWER] = direct;
 438
 439        info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VMON
 440          | PMBUS_HAVE_PIN | PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT
 441          | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
 442
 443        if (data->id == lm25056) {
 444                info->func[0] |= PMBUS_HAVE_STATUS_VMON;
 445                info->read_word_data = lm25056_read_word_data;
 446                info->read_byte_data = lm25056_read_byte_data;
 447                data->rlimit = 0x0fff;
 448        } else {
 449                info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
 450                info->read_word_data = lm25066_read_word_data;
 451                data->rlimit = 0x0fff;
 452        }
 453        info->write_word_data = lm25066_write_word_data;
 454
 455        coeff = &lm25066_coeff[data->id][0];
 456        info->m[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].m;
 457        info->b[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].b;
 458        info->R[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].R;
 459        info->m[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].m;
 460        info->b[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].b;
 461        info->R[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].R;
 462        info->m[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].m;
 463        info->b[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].b;
 464        info->R[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].R;
 465        info->R[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].R;
 466        info->R[PSC_POWER] = coeff[PSC_POWER].R;
 467        if (config & LM25066_DEV_SETUP_CL) {
 468                info->m[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN_L].m;
 469                info->b[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN_L].b;
 470                info->m[PSC_POWER] = coeff[PSC_POWER_L].m;
 471                info->b[PSC_POWER] = coeff[PSC_POWER_L].b;
 472        } else {
 473                info->m[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].m;
 474                info->b[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].b;
 475                info->m[PSC_POWER] = coeff[PSC_POWER].m;
 476                info->b[PSC_POWER] = coeff[PSC_POWER].b;
 477        }
 478
 479        return pmbus_do_probe(client, id, info);
 480}
 481
 482static const struct i2c_device_id lm25066_id[] = {
 483        {"lm25056", lm25056},
 484        {"lm25066", lm25066},
 485        {"lm5064", lm5064},
 486        {"lm5066", lm5066},
 487        {"lm5066i", lm5066i},
 488        { }
 489};
 490
 491MODULE_DEVICE_TABLE(i2c, lm25066_id);
 492
 493/* This is the driver that will be inserted */
 494static struct i2c_driver lm25066_driver = {
 495        .driver = {
 496                   .name = "lm25066",
 497                   },
 498        .probe = lm25066_probe,
 499        .remove = pmbus_do_remove,
 500        .id_table = lm25066_id,
 501};
 502
 503module_i2c_driver(lm25066_driver);
 504
 505MODULE_AUTHOR("Guenter Roeck");
 506MODULE_DESCRIPTION("PMBus driver for LM25066 and compatible chips");
 507MODULE_LICENSE("GPL");
 508