linux/drivers/hwmon/pmbus/zl6100.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Hardware monitoring driver for ZL6100 and compatibles
   4 *
   5 * Copyright (c) 2011 Ericsson AB.
   6 * Copyright (c) 2012 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/ktime.h>
  17#include <linux/delay.h>
  18#include "pmbus.h"
  19
  20enum chips { zl2004, zl2005, zl2006, zl2008, zl2105, zl2106, zl6100, zl6105,
  21             zl9101, zl9117 };
  22
  23struct zl6100_data {
  24        int id;
  25        ktime_t access;         /* chip access time */
  26        int delay;              /* Delay between chip accesses in uS */
  27        struct pmbus_driver_info info;
  28};
  29
  30#define to_zl6100_data(x)  container_of(x, struct zl6100_data, info)
  31
  32#define ZL6100_MFR_CONFIG               0xd0
  33#define ZL6100_DEVICE_ID                0xe4
  34
  35#define ZL6100_MFR_XTEMP_ENABLE         BIT(7)
  36
  37#define MFR_VMON_OV_FAULT_LIMIT         0xf5
  38#define MFR_VMON_UV_FAULT_LIMIT         0xf6
  39#define MFR_READ_VMON                   0xf7
  40
  41#define VMON_UV_WARNING                 BIT(5)
  42#define VMON_OV_WARNING                 BIT(4)
  43#define VMON_UV_FAULT                   BIT(1)
  44#define VMON_OV_FAULT                   BIT(0)
  45
  46#define ZL6100_WAIT_TIME                1000    /* uS   */
  47
  48static ushort delay = ZL6100_WAIT_TIME;
  49module_param(delay, ushort, 0644);
  50MODULE_PARM_DESC(delay, "Delay between chip accesses in uS");
  51
  52/* Convert linear sensor value to milli-units */
  53static long zl6100_l2d(s16 l)
  54{
  55        s16 exponent;
  56        s32 mantissa;
  57        long val;
  58
  59        exponent = l >> 11;
  60        mantissa = ((s16)((l & 0x7ff) << 5)) >> 5;
  61
  62        val = mantissa;
  63
  64        /* scale result to milli-units */
  65        val = val * 1000L;
  66
  67        if (exponent >= 0)
  68                val <<= exponent;
  69        else
  70                val >>= -exponent;
  71
  72        return val;
  73}
  74
  75#define MAX_MANTISSA    (1023 * 1000)
  76#define MIN_MANTISSA    (511 * 1000)
  77
  78static u16 zl6100_d2l(long val)
  79{
  80        s16 exponent = 0, mantissa;
  81        bool negative = false;
  82
  83        /* simple case */
  84        if (val == 0)
  85                return 0;
  86
  87        if (val < 0) {
  88                negative = true;
  89                val = -val;
  90        }
  91
  92        /* Reduce large mantissa until it fits into 10 bit */
  93        while (val >= MAX_MANTISSA && exponent < 15) {
  94                exponent++;
  95                val >>= 1;
  96        }
  97        /* Increase small mantissa to improve precision */
  98        while (val < MIN_MANTISSA && exponent > -15) {
  99                exponent--;
 100                val <<= 1;
 101        }
 102
 103        /* Convert mantissa from milli-units to units */
 104        mantissa = DIV_ROUND_CLOSEST(val, 1000);
 105
 106        /* Ensure that resulting number is within range */
 107        if (mantissa > 0x3ff)
 108                mantissa = 0x3ff;
 109
 110        /* restore sign */
 111        if (negative)
 112                mantissa = -mantissa;
 113
 114        /* Convert to 5 bit exponent, 11 bit mantissa */
 115        return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800);
 116}
 117
 118/* Some chips need a delay between accesses */
 119static inline void zl6100_wait(const struct zl6100_data *data)
 120{
 121        if (data->delay) {
 122                s64 delta = ktime_us_delta(ktime_get(), data->access);
 123                if (delta < data->delay)
 124                        udelay(data->delay - delta);
 125        }
 126}
 127
 128static int zl6100_read_word_data(struct i2c_client *client, int page,
 129                                 int phase, int reg)
 130{
 131        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
 132        struct zl6100_data *data = to_zl6100_data(info);
 133        int ret, vreg;
 134
 135        if (page > 0)
 136                return -ENXIO;
 137
 138        if (data->id == zl2005) {
 139                /*
 140                 * Limit register detection is not reliable on ZL2005.
 141                 * Make sure registers are not erroneously detected.
 142                 */
 143                switch (reg) {
 144                case PMBUS_VOUT_OV_WARN_LIMIT:
 145                case PMBUS_VOUT_UV_WARN_LIMIT:
 146                case PMBUS_IOUT_OC_WARN_LIMIT:
 147                        return -ENXIO;
 148                }
 149        }
 150
 151        switch (reg) {
 152        case PMBUS_VIRT_READ_VMON:
 153                vreg = MFR_READ_VMON;
 154                break;
 155        case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
 156        case PMBUS_VIRT_VMON_OV_FAULT_LIMIT:
 157                vreg = MFR_VMON_OV_FAULT_LIMIT;
 158                break;
 159        case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
 160        case PMBUS_VIRT_VMON_UV_FAULT_LIMIT:
 161                vreg = MFR_VMON_UV_FAULT_LIMIT;
 162                break;
 163        default:
 164                if (reg >= PMBUS_VIRT_BASE)
 165                        return -ENXIO;
 166                vreg = reg;
 167                break;
 168        }
 169
 170        zl6100_wait(data);
 171        ret = pmbus_read_word_data(client, page, phase, vreg);
 172        data->access = ktime_get();
 173        if (ret < 0)
 174                return ret;
 175
 176        switch (reg) {
 177        case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
 178                ret = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(ret) * 9, 10));
 179                break;
 180        case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
 181                ret = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(ret) * 11, 10));
 182                break;
 183        }
 184
 185        return ret;
 186}
 187
 188static int zl6100_read_byte_data(struct i2c_client *client, int page, int reg)
 189{
 190        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
 191        struct zl6100_data *data = to_zl6100_data(info);
 192        int ret, status;
 193
 194        if (page > 0)
 195                return -ENXIO;
 196
 197        zl6100_wait(data);
 198
 199        switch (reg) {
 200        case PMBUS_VIRT_STATUS_VMON:
 201                ret = pmbus_read_byte_data(client, 0,
 202                                           PMBUS_STATUS_MFR_SPECIFIC);
 203                if (ret < 0)
 204                        break;
 205
 206                status = 0;
 207                if (ret & VMON_UV_WARNING)
 208                        status |= PB_VOLTAGE_UV_WARNING;
 209                if (ret & VMON_OV_WARNING)
 210                        status |= PB_VOLTAGE_OV_WARNING;
 211                if (ret & VMON_UV_FAULT)
 212                        status |= PB_VOLTAGE_UV_FAULT;
 213                if (ret & VMON_OV_FAULT)
 214                        status |= PB_VOLTAGE_OV_FAULT;
 215                ret = status;
 216                break;
 217        default:
 218                ret = pmbus_read_byte_data(client, page, reg);
 219                break;
 220        }
 221        data->access = ktime_get();
 222
 223        return ret;
 224}
 225
 226static int zl6100_write_word_data(struct i2c_client *client, int page, int reg,
 227                                  u16 word)
 228{
 229        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
 230        struct zl6100_data *data = to_zl6100_data(info);
 231        int ret, vreg;
 232
 233        if (page > 0)
 234                return -ENXIO;
 235
 236        switch (reg) {
 237        case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
 238                word = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(word) * 10, 9));
 239                vreg = MFR_VMON_OV_FAULT_LIMIT;
 240                pmbus_clear_cache(client);
 241                break;
 242        case PMBUS_VIRT_VMON_OV_FAULT_LIMIT:
 243                vreg = MFR_VMON_OV_FAULT_LIMIT;
 244                pmbus_clear_cache(client);
 245                break;
 246        case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
 247                word = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(word) * 10, 11));
 248                vreg = MFR_VMON_UV_FAULT_LIMIT;
 249                pmbus_clear_cache(client);
 250                break;
 251        case PMBUS_VIRT_VMON_UV_FAULT_LIMIT:
 252                vreg = MFR_VMON_UV_FAULT_LIMIT;
 253                pmbus_clear_cache(client);
 254                break;
 255        default:
 256                if (reg >= PMBUS_VIRT_BASE)
 257                        return -ENXIO;
 258                vreg = reg;
 259        }
 260
 261        zl6100_wait(data);
 262        ret = pmbus_write_word_data(client, page, vreg, word);
 263        data->access = ktime_get();
 264
 265        return ret;
 266}
 267
 268static int zl6100_write_byte(struct i2c_client *client, int page, u8 value)
 269{
 270        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
 271        struct zl6100_data *data = to_zl6100_data(info);
 272        int ret;
 273
 274        if (page > 0)
 275                return -ENXIO;
 276
 277        zl6100_wait(data);
 278        ret = pmbus_write_byte(client, page, value);
 279        data->access = ktime_get();
 280
 281        return ret;
 282}
 283
 284static const struct i2c_device_id zl6100_id[] = {
 285        {"bmr450", zl2005},
 286        {"bmr451", zl2005},
 287        {"bmr462", zl2008},
 288        {"bmr463", zl2008},
 289        {"bmr464", zl2008},
 290        {"zl2004", zl2004},
 291        {"zl2005", zl2005},
 292        {"zl2006", zl2006},
 293        {"zl2008", zl2008},
 294        {"zl2105", zl2105},
 295        {"zl2106", zl2106},
 296        {"zl6100", zl6100},
 297        {"zl6105", zl6105},
 298        {"zl9101", zl9101},
 299        {"zl9117", zl9117},
 300        { }
 301};
 302MODULE_DEVICE_TABLE(i2c, zl6100_id);
 303
 304static int zl6100_probe(struct i2c_client *client)
 305{
 306        int ret;
 307        struct zl6100_data *data;
 308        struct pmbus_driver_info *info;
 309        u8 device_id[I2C_SMBUS_BLOCK_MAX + 1];
 310        const struct i2c_device_id *mid;
 311
 312        if (!i2c_check_functionality(client->adapter,
 313                                     I2C_FUNC_SMBUS_READ_WORD_DATA
 314                                     | I2C_FUNC_SMBUS_READ_BLOCK_DATA))
 315                return -ENODEV;
 316
 317        ret = i2c_smbus_read_block_data(client, ZL6100_DEVICE_ID,
 318                                        device_id);
 319        if (ret < 0) {
 320                dev_err(&client->dev, "Failed to read device ID\n");
 321                return ret;
 322        }
 323        device_id[ret] = '\0';
 324        dev_info(&client->dev, "Device ID %s\n", device_id);
 325
 326        mid = NULL;
 327        for (mid = zl6100_id; mid->name[0]; mid++) {
 328                if (!strncasecmp(mid->name, device_id, strlen(mid->name)))
 329                        break;
 330        }
 331        if (!mid->name[0]) {
 332                dev_err(&client->dev, "Unsupported device\n");
 333                return -ENODEV;
 334        }
 335        if (strcmp(client->name, mid->name) != 0)
 336                dev_notice(&client->dev,
 337                           "Device mismatch: Configured %s, detected %s\n",
 338                           client->name, mid->name);
 339
 340        data = devm_kzalloc(&client->dev, sizeof(struct zl6100_data),
 341                            GFP_KERNEL);
 342        if (!data)
 343                return -ENOMEM;
 344
 345        data->id = mid->driver_data;
 346
 347        /*
 348         * According to information from the chip vendor, all currently
 349         * supported chips are known to require a wait time between I2C
 350         * accesses.
 351         */
 352        data->delay = delay;
 353
 354        /*
 355         * Since there was a direct I2C device access above, wait before
 356         * accessing the chip again.
 357         */
 358        data->access = ktime_get();
 359        zl6100_wait(data);
 360
 361        info = &data->info;
 362
 363        info->pages = 1;
 364        info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
 365          | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
 366          | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
 367          | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
 368
 369        /*
 370         * ZL2004, ZL9101M, and ZL9117M support monitoring an extra voltage
 371         * (VMON for ZL2004, VDRV for ZL9101M and ZL9117M). Report it as vmon.
 372         */
 373        if (data->id == zl2004 || data->id == zl9101 || data->id == zl9117)
 374                info->func[0] |= PMBUS_HAVE_VMON | PMBUS_HAVE_STATUS_VMON;
 375
 376        ret = i2c_smbus_read_word_data(client, ZL6100_MFR_CONFIG);
 377        if (ret < 0)
 378                return ret;
 379
 380        if (ret & ZL6100_MFR_XTEMP_ENABLE)
 381                info->func[0] |= PMBUS_HAVE_TEMP2;
 382
 383        data->access = ktime_get();
 384        zl6100_wait(data);
 385
 386        info->read_word_data = zl6100_read_word_data;
 387        info->read_byte_data = zl6100_read_byte_data;
 388        info->write_word_data = zl6100_write_word_data;
 389        info->write_byte = zl6100_write_byte;
 390
 391        return pmbus_do_probe(client, info);
 392}
 393
 394static struct i2c_driver zl6100_driver = {
 395        .driver = {
 396                   .name = "zl6100",
 397                   },
 398        .probe_new = zl6100_probe,
 399        .id_table = zl6100_id,
 400};
 401
 402module_i2c_driver(zl6100_driver);
 403
 404MODULE_AUTHOR("Guenter Roeck");
 405MODULE_DESCRIPTION("PMBus driver for ZL6100 and compatibles");
 406MODULE_LICENSE("GPL");
 407