linux/drivers/hwmon/pmbus/max16601.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Hardware monitoring driver for Maxim MAX16601
   4 *
   5 * Implementation notes:
   6 *
   7 * Ths chip supports two rails, VCORE and VSA. Telemetry information for the
   8 * two rails is reported in two subsequent I2C addresses. The driver
   9 * instantiates a dummy I2C client at the second I2C address to report
  10 * information for the VSA rail in a single instance of the driver.
  11 * Telemetry for the VSA rail is reported to the PMBus core in PMBus page 2.
  12 *
  13 * The chip reports input current using two separate methods. The input current
  14 * reported with the standard READ_IIN command is derived from the output
  15 * current. The first method is reported to the PMBus core with PMBus page 0,
  16 * the second method is reported with PMBus page 1.
  17 *
  18 * The chip supports reading per-phase temperatures and per-phase input/output
  19 * currents for VCORE. Telemetry is reported in vendor specific registers.
  20 * The driver translates the vendor specific register values to PMBus standard
  21 * register values and reports per-phase information in PMBus page 0.
  22 *
  23 * Copyright 2019, 2020 Google LLC.
  24 */
  25
  26#include <linux/bits.h>
  27#include <linux/i2c.h>
  28#include <linux/init.h>
  29#include <linux/kernel.h>
  30#include <linux/module.h>
  31
  32#include "pmbus.h"
  33
  34#define REG_SETPT_DVID          0xd1
  35#define  DAC_10MV_MODE          BIT(4)
  36#define REG_IOUT_AVG_PK         0xee
  37#define REG_IIN_SENSOR          0xf1
  38#define REG_TOTAL_INPUT_POWER   0xf2
  39#define REG_PHASE_ID            0xf3
  40#define  CORE_RAIL_INDICATOR    BIT(7)
  41#define REG_PHASE_REPORTING     0xf4
  42
  43struct max16601_data {
  44        struct pmbus_driver_info info;
  45        struct i2c_client *vsa;
  46        int iout_avg_pkg;
  47};
  48
  49#define to_max16601_data(x) container_of(x, struct max16601_data, info)
  50
  51static int max16601_read_byte(struct i2c_client *client, int page, int reg)
  52{
  53        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
  54        struct max16601_data *data = to_max16601_data(info);
  55
  56        if (page > 0) {
  57                if (page == 2)  /* VSA */
  58                        return i2c_smbus_read_byte_data(data->vsa, reg);
  59                return -EOPNOTSUPP;
  60        }
  61        return -ENODATA;
  62}
  63
  64static int max16601_read_word(struct i2c_client *client, int page, int phase,
  65                              int reg)
  66{
  67        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
  68        struct max16601_data *data = to_max16601_data(info);
  69        u8 buf[I2C_SMBUS_BLOCK_MAX + 1];
  70        int ret;
  71
  72        switch (page) {
  73        case 0:         /* VCORE */
  74                if (phase == 0xff)
  75                        return -ENODATA;
  76                switch (reg) {
  77                case PMBUS_READ_IIN:
  78                case PMBUS_READ_IOUT:
  79                case PMBUS_READ_TEMPERATURE_1:
  80                        ret = i2c_smbus_write_byte_data(client, REG_PHASE_ID,
  81                                                        phase);
  82                        if (ret)
  83                                return ret;
  84                        ret = i2c_smbus_read_block_data(client,
  85                                                        REG_PHASE_REPORTING,
  86                                                        buf);
  87                        if (ret < 0)
  88                                return ret;
  89                        if (ret < 6)
  90                                return -EIO;
  91                        switch (reg) {
  92                        case PMBUS_READ_TEMPERATURE_1:
  93                                return buf[1] << 8 | buf[0];
  94                        case PMBUS_READ_IOUT:
  95                                return buf[3] << 8 | buf[2];
  96                        case PMBUS_READ_IIN:
  97                                return buf[5] << 8 | buf[4];
  98                        default:
  99                                break;
 100                        }
 101                }
 102                return -EOPNOTSUPP;
 103        case 1:         /* VCORE, read IIN/PIN from sensor element */
 104                switch (reg) {
 105                case PMBUS_READ_IIN:
 106                        return i2c_smbus_read_word_data(client, REG_IIN_SENSOR);
 107                case PMBUS_READ_PIN:
 108                        return i2c_smbus_read_word_data(client,
 109                                                        REG_TOTAL_INPUT_POWER);
 110                default:
 111                        break;
 112                }
 113                return -EOPNOTSUPP;
 114        case 2:         /* VSA */
 115                switch (reg) {
 116                case PMBUS_VIRT_READ_IOUT_MAX:
 117                        ret = i2c_smbus_read_word_data(data->vsa,
 118                                                       REG_IOUT_AVG_PK);
 119                        if (ret < 0)
 120                                return ret;
 121                        if (sign_extend32(ret, 10) >
 122                            sign_extend32(data->iout_avg_pkg, 10))
 123                                data->iout_avg_pkg = ret;
 124                        return data->iout_avg_pkg;
 125                case PMBUS_VIRT_RESET_IOUT_HISTORY:
 126                        return 0;
 127                case PMBUS_IOUT_OC_FAULT_LIMIT:
 128                case PMBUS_IOUT_OC_WARN_LIMIT:
 129                case PMBUS_OT_FAULT_LIMIT:
 130                case PMBUS_OT_WARN_LIMIT:
 131                case PMBUS_READ_IIN:
 132                case PMBUS_READ_IOUT:
 133                case PMBUS_READ_TEMPERATURE_1:
 134                case PMBUS_STATUS_WORD:
 135                        return i2c_smbus_read_word_data(data->vsa, reg);
 136                default:
 137                        return -EOPNOTSUPP;
 138                }
 139        default:
 140                return -EOPNOTSUPP;
 141        }
 142}
 143
 144static int max16601_write_byte(struct i2c_client *client, int page, u8 reg)
 145{
 146        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
 147        struct max16601_data *data = to_max16601_data(info);
 148
 149        if (page == 2) {
 150                if (reg == PMBUS_CLEAR_FAULTS)
 151                        return i2c_smbus_write_byte(data->vsa, reg);
 152                return -EOPNOTSUPP;
 153        }
 154        return -ENODATA;
 155}
 156
 157static int max16601_write_word(struct i2c_client *client, int page, int reg,
 158                               u16 value)
 159{
 160        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
 161        struct max16601_data *data = to_max16601_data(info);
 162
 163        switch (page) {
 164        case 0:         /* VCORE */
 165                return -ENODATA;
 166        case 1:         /* VCORE IIN/PIN from sensor element */
 167        default:
 168                return -EOPNOTSUPP;
 169        case 2:         /* VSA */
 170                switch (reg) {
 171                case PMBUS_VIRT_RESET_IOUT_HISTORY:
 172                        data->iout_avg_pkg = 0xfc00;
 173                        return 0;
 174                case PMBUS_IOUT_OC_FAULT_LIMIT:
 175                case PMBUS_IOUT_OC_WARN_LIMIT:
 176                case PMBUS_OT_FAULT_LIMIT:
 177                case PMBUS_OT_WARN_LIMIT:
 178                        return i2c_smbus_write_word_data(data->vsa, reg, value);
 179                default:
 180                        return -EOPNOTSUPP;
 181                }
 182        }
 183}
 184
 185static int max16601_identify(struct i2c_client *client,
 186                             struct pmbus_driver_info *info)
 187{
 188        int reg;
 189
 190        reg = i2c_smbus_read_byte_data(client, REG_SETPT_DVID);
 191        if (reg < 0)
 192                return reg;
 193        if (reg & DAC_10MV_MODE)
 194                info->vrm_version[0] = vr13;
 195        else
 196                info->vrm_version[0] = vr12;
 197
 198        return 0;
 199}
 200
 201static struct pmbus_driver_info max16601_info = {
 202        .pages = 3,
 203        .format[PSC_VOLTAGE_IN] = linear,
 204        .format[PSC_VOLTAGE_OUT] = vid,
 205        .format[PSC_CURRENT_IN] = linear,
 206        .format[PSC_CURRENT_OUT] = linear,
 207        .format[PSC_TEMPERATURE] = linear,
 208        .format[PSC_POWER] = linear,
 209        .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN | PMBUS_HAVE_PIN |
 210                PMBUS_HAVE_STATUS_INPUT |
 211                PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
 212                PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
 213                PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP |
 214                PMBUS_HAVE_POUT | PMBUS_PAGE_VIRTUAL | PMBUS_PHASE_VIRTUAL,
 215        .func[1] = PMBUS_HAVE_IIN | PMBUS_HAVE_PIN | PMBUS_PAGE_VIRTUAL,
 216        .func[2] = PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT |
 217                PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
 218                PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_PAGE_VIRTUAL,
 219        .phases[0] = 8,
 220        .pfunc[0] = PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_TEMP,
 221        .pfunc[1] = PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT,
 222        .pfunc[2] = PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_TEMP,
 223        .pfunc[3] = PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT,
 224        .pfunc[4] = PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_TEMP,
 225        .pfunc[5] = PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT,
 226        .pfunc[6] = PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_TEMP,
 227        .pfunc[7] = PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT,
 228        .identify = max16601_identify,
 229        .read_byte_data = max16601_read_byte,
 230        .read_word_data = max16601_read_word,
 231        .write_byte = max16601_write_byte,
 232        .write_word_data = max16601_write_word,
 233};
 234
 235static void max16601_remove(void *_data)
 236{
 237        struct max16601_data *data = _data;
 238
 239        i2c_unregister_device(data->vsa);
 240}
 241
 242static int max16601_probe(struct i2c_client *client)
 243{
 244        struct device *dev = &client->dev;
 245        u8 buf[I2C_SMBUS_BLOCK_MAX + 1];
 246        struct max16601_data *data;
 247        int ret;
 248
 249        if (!i2c_check_functionality(client->adapter,
 250                                     I2C_FUNC_SMBUS_READ_BYTE_DATA |
 251                                     I2C_FUNC_SMBUS_READ_BLOCK_DATA))
 252                return -ENODEV;
 253
 254        ret = i2c_smbus_read_block_data(client, PMBUS_IC_DEVICE_ID, buf);
 255        if (ret < 0)
 256                return -ENODEV;
 257
 258        /* PMBUS_IC_DEVICE_ID is expected to return "MAX16601y.xx" */
 259        if (ret < 11 || strncmp(buf, "MAX16601", 8)) {
 260                buf[ret] = '\0';
 261                dev_err(dev, "Unsupported chip '%s'\n", buf);
 262                return -ENODEV;
 263        }
 264
 265        ret = i2c_smbus_read_byte_data(client, REG_PHASE_ID);
 266        if (ret < 0)
 267                return ret;
 268        if (!(ret & CORE_RAIL_INDICATOR)) {
 269                dev_err(dev,
 270                        "Driver must be instantiated on CORE rail I2C address\n");
 271                return -ENODEV;
 272        }
 273
 274        data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 275        if (!data)
 276                return -ENOMEM;
 277
 278        data->iout_avg_pkg = 0xfc00;
 279        data->vsa = i2c_new_dummy_device(client->adapter, client->addr + 1);
 280        if (IS_ERR(data->vsa)) {
 281                dev_err(dev, "Failed to register VSA client\n");
 282                return PTR_ERR(data->vsa);
 283        }
 284        ret = devm_add_action_or_reset(dev, max16601_remove, data);
 285        if (ret)
 286                return ret;
 287
 288        data->info = max16601_info;
 289
 290        return pmbus_do_probe(client, &data->info);
 291}
 292
 293static const struct i2c_device_id max16601_id[] = {
 294        {"max16601", 0},
 295        {}
 296};
 297
 298MODULE_DEVICE_TABLE(i2c, max16601_id);
 299
 300static struct i2c_driver max16601_driver = {
 301        .driver = {
 302                   .name = "max16601",
 303                   },
 304        .probe_new = max16601_probe,
 305        .remove = pmbus_do_remove,
 306        .id_table = max16601_id,
 307};
 308
 309module_i2c_driver(max16601_driver);
 310
 311MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
 312MODULE_DESCRIPTION("PMBus driver for Maxim MAX16601");
 313MODULE_LICENSE("GPL v2");
 314