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, int reg)
 129{
 130        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
 131        struct zl6100_data *data = to_zl6100_data(info);
 132        int ret, vreg;
 133
 134        if (page > 0)
 135                return -ENXIO;
 136
 137        if (data->id == zl2005) {
 138                /*
 139                 * Limit register detection is not reliable on ZL2005.
 140                 * Make sure registers are not erroneously detected.
 141                 */
 142                switch (reg) {
 143                case PMBUS_VOUT_OV_WARN_LIMIT:
 144                case PMBUS_VOUT_UV_WARN_LIMIT:
 145                case PMBUS_IOUT_OC_WARN_LIMIT:
 146                        return -ENXIO;
 147                }
 148        }
 149
 150        switch (reg) {
 151        case PMBUS_VIRT_READ_VMON:
 152                vreg = MFR_READ_VMON;
 153                break;
 154        case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
 155        case PMBUS_VIRT_VMON_OV_FAULT_LIMIT:
 156                vreg = MFR_VMON_OV_FAULT_LIMIT;
 157                break;
 158        case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
 159        case PMBUS_VIRT_VMON_UV_FAULT_LIMIT:
 160                vreg = MFR_VMON_UV_FAULT_LIMIT;
 161                break;
 162        default:
 163                if (reg >= PMBUS_VIRT_BASE)
 164                        return -ENXIO;
 165                vreg = reg;
 166                break;
 167        }
 168
 169        zl6100_wait(data);
 170        ret = pmbus_read_word_data(client, page, vreg);
 171        data->access = ktime_get();
 172        if (ret < 0)
 173                return ret;
 174
 175        switch (reg) {
 176        case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
 177                ret = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(ret) * 9, 10));
 178                break;
 179        case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
 180                ret = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(ret) * 11, 10));
 181                break;
 182        }
 183
 184        return ret;
 185}
 186
 187static int zl6100_read_byte_data(struct i2c_client *client, int page, int reg)
 188{
 189        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
 190        struct zl6100_data *data = to_zl6100_data(info);
 191        int ret, status;
 192
 193        if (page > 0)
 194                return -ENXIO;
 195
 196        zl6100_wait(data);
 197
 198        switch (reg) {
 199        case PMBUS_VIRT_STATUS_VMON:
 200                ret = pmbus_read_byte_data(client, 0,
 201                                           PMBUS_STATUS_MFR_SPECIFIC);
 202                if (ret < 0)
 203                        break;
 204
 205                status = 0;
 206                if (ret & VMON_UV_WARNING)
 207                        status |= PB_VOLTAGE_UV_WARNING;
 208                if (ret & VMON_OV_WARNING)
 209                        status |= PB_VOLTAGE_OV_WARNING;
 210                if (ret & VMON_UV_FAULT)
 211                        status |= PB_VOLTAGE_UV_FAULT;
 212                if (ret & VMON_OV_FAULT)
 213                        status |= PB_VOLTAGE_OV_FAULT;
 214                ret = status;
 215                break;
 216        default:
 217                ret = pmbus_read_byte_data(client, page, reg);
 218                break;
 219        }
 220        data->access = ktime_get();
 221
 222        return ret;
 223}
 224
 225static int zl6100_write_word_data(struct i2c_client *client, int page, int reg,
 226                                  u16 word)
 227{
 228        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
 229        struct zl6100_data *data = to_zl6100_data(info);
 230        int ret, vreg;
 231
 232        if (page > 0)
 233                return -ENXIO;
 234
 235        switch (reg) {
 236        case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
 237                word = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(word) * 10, 9));
 238                vreg = MFR_VMON_OV_FAULT_LIMIT;
 239                pmbus_clear_cache(client);
 240                break;
 241        case PMBUS_VIRT_VMON_OV_FAULT_LIMIT:
 242                vreg = MFR_VMON_OV_FAULT_LIMIT;
 243                pmbus_clear_cache(client);
 244                break;
 245        case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
 246                word = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(word) * 10, 11));
 247                vreg = MFR_VMON_UV_FAULT_LIMIT;
 248                pmbus_clear_cache(client);
 249                break;
 250        case PMBUS_VIRT_VMON_UV_FAULT_LIMIT:
 251                vreg = MFR_VMON_UV_FAULT_LIMIT;
 252                pmbus_clear_cache(client);
 253                break;
 254        default:
 255                if (reg >= PMBUS_VIRT_BASE)
 256                        return -ENXIO;
 257                vreg = reg;
 258        }
 259
 260        zl6100_wait(data);
 261        ret = pmbus_write_word_data(client, page, vreg, word);
 262        data->access = ktime_get();
 263
 264        return ret;
 265}
 266
 267static int zl6100_write_byte(struct i2c_client *client, int page, u8 value)
 268{
 269        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
 270        struct zl6100_data *data = to_zl6100_data(info);
 271        int ret;
 272
 273        if (page > 0)
 274                return -ENXIO;
 275
 276        zl6100_wait(data);
 277        ret = pmbus_write_byte(client, page, value);
 278        data->access = ktime_get();
 279
 280        return ret;
 281}
 282
 283static const struct i2c_device_id zl6100_id[] = {
 284        {"bmr450", zl2005},
 285        {"bmr451", zl2005},
 286        {"bmr462", zl2008},
 287        {"bmr463", zl2008},
 288        {"bmr464", zl2008},
 289        {"zl2004", zl2004},
 290        {"zl2005", zl2005},
 291        {"zl2006", zl2006},
 292        {"zl2008", zl2008},
 293        {"zl2105", zl2105},
 294        {"zl2106", zl2106},
 295        {"zl6100", zl6100},
 296        {"zl6105", zl6105},
 297        {"zl9101", zl9101},
 298        {"zl9117", zl9117},
 299        { }
 300};
 301MODULE_DEVICE_TABLE(i2c, zl6100_id);
 302
 303static int zl6100_probe(struct i2c_client *client,
 304                        const struct i2c_device_id *id)
 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 (id->driver_data != mid->driver_data)
 336                dev_notice(&client->dev,
 337                           "Device mismatch: Configured %s, detected %s\n",
 338                           id->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, mid, info);
 392}
 393
 394static struct i2c_driver zl6100_driver = {
 395        .driver = {
 396                   .name = "zl6100",
 397                   },
 398        .probe = zl6100_probe,
 399        .remove = pmbus_do_remove,
 400        .id_table = zl6100_id,
 401};
 402
 403module_i2c_driver(zl6100_driver);
 404
 405MODULE_AUTHOR("Guenter Roeck");
 406MODULE_DESCRIPTION("PMBus driver for ZL6100 and compatibles");
 407MODULE_LICENSE("GPL");
 408