linux/drivers/hwmon/pmbus/max20730.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Driver for MAX20730, MAX20734, and MAX20743 Integrated, Step-Down
   4 * Switching Regulators
   5 *
   6 * Copyright 2019 Google LLC.
   7 */
   8
   9#include <linux/bits.h>
  10#include <linux/err.h>
  11#include <linux/i2c.h>
  12#include <linux/init.h>
  13#include <linux/kernel.h>
  14#include <linux/module.h>
  15#include <linux/mutex.h>
  16#include <linux/of_device.h>
  17#include <linux/pmbus.h>
  18#include <linux/util_macros.h>
  19#include "pmbus.h"
  20
  21enum chips {
  22        max20730,
  23        max20734,
  24        max20743
  25};
  26
  27struct max20730_data {
  28        enum chips id;
  29        struct pmbus_driver_info info;
  30        struct mutex lock;      /* Used to protect against parallel writes */
  31        u16 mfr_devset1;
  32};
  33
  34#define to_max20730_data(x)  container_of(x, struct max20730_data, info)
  35
  36#define MAX20730_MFR_DEVSET1    0xd2
  37
  38/*
  39 * Convert discreet value to direct data format. Strictly speaking, all passed
  40 * values are constants, so we could do that calculation manually. On the
  41 * downside, that would make the driver more difficult to maintain, so lets
  42 * use this approach.
  43 */
  44static u16 val_to_direct(int v, enum pmbus_sensor_classes class,
  45                         const struct pmbus_driver_info *info)
  46{
  47        int R = info->R[class] - 3;     /* take milli-units into account */
  48        int b = info->b[class] * 1000;
  49        long d;
  50
  51        d = v * info->m[class] + b;
  52        /*
  53         * R < 0 is true for all callers, so we don't need to bother
  54         * about the R > 0 case.
  55         */
  56        while (R < 0) {
  57                d = DIV_ROUND_CLOSEST(d, 10);
  58                R++;
  59        }
  60        return (u16)d;
  61}
  62
  63static long direct_to_val(u16 w, enum pmbus_sensor_classes class,
  64                          const struct pmbus_driver_info *info)
  65{
  66        int R = info->R[class] - 3;
  67        int b = info->b[class] * 1000;
  68        int m = info->m[class];
  69        long d = (s16)w;
  70
  71        if (m == 0)
  72                return 0;
  73
  74        while (R < 0) {
  75                d *= 10;
  76                R++;
  77        }
  78        d = (d - b) / m;
  79        return d;
  80}
  81
  82static u32 max_current[][5] = {
  83        [max20730] = { 13000, 16600, 20100, 23600 },
  84        [max20734] = { 21000, 27000, 32000, 38000 },
  85        [max20743] = { 18900, 24100, 29200, 34100 },
  86};
  87
  88static int max20730_read_word_data(struct i2c_client *client, int page, int reg)
  89{
  90        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
  91        const struct max20730_data *data = to_max20730_data(info);
  92        int ret = 0;
  93        u32 max_c;
  94
  95        switch (reg) {
  96        case PMBUS_OT_FAULT_LIMIT:
  97                switch ((data->mfr_devset1 >> 11) & 0x3) {
  98                case 0x0:
  99                        ret = val_to_direct(150000, PSC_TEMPERATURE, info);
 100                        break;
 101                case 0x1:
 102                        ret = val_to_direct(130000, PSC_TEMPERATURE, info);
 103                        break;
 104                default:
 105                        ret = -ENODATA;
 106                        break;
 107                }
 108                break;
 109        case PMBUS_IOUT_OC_FAULT_LIMIT:
 110                max_c = max_current[data->id][(data->mfr_devset1 >> 5) & 0x3];
 111                ret = val_to_direct(max_c, PSC_CURRENT_OUT, info);
 112                break;
 113        default:
 114                ret = -ENODATA;
 115                break;
 116        }
 117        return ret;
 118}
 119
 120static int max20730_write_word_data(struct i2c_client *client, int page,
 121                                    int reg, u16 word)
 122{
 123        struct pmbus_driver_info *info;
 124        struct max20730_data *data;
 125        u16 devset1;
 126        int ret = 0;
 127        int idx;
 128
 129        info = (struct pmbus_driver_info *)pmbus_get_driver_info(client);
 130        data = to_max20730_data(info);
 131
 132        mutex_lock(&data->lock);
 133        devset1 = data->mfr_devset1;
 134
 135        switch (reg) {
 136        case PMBUS_OT_FAULT_LIMIT:
 137                devset1 &= ~(BIT(11) | BIT(12));
 138                if (direct_to_val(word, PSC_TEMPERATURE, info) < 140000)
 139                        devset1 |= BIT(11);
 140                break;
 141        case PMBUS_IOUT_OC_FAULT_LIMIT:
 142                devset1 &= ~(BIT(5) | BIT(6));
 143
 144                idx = find_closest(direct_to_val(word, PSC_CURRENT_OUT, info),
 145                                   max_current[data->id], 4);
 146                devset1 |= (idx << 5);
 147                break;
 148        default:
 149                ret = -ENODATA;
 150                break;
 151        }
 152
 153        if (!ret && devset1 != data->mfr_devset1) {
 154                ret = i2c_smbus_write_word_data(client, MAX20730_MFR_DEVSET1,
 155                                                devset1);
 156                if (!ret) {
 157                        data->mfr_devset1 = devset1;
 158                        pmbus_clear_cache(client);
 159                }
 160        }
 161        mutex_unlock(&data->lock);
 162        return ret;
 163}
 164
 165static const struct pmbus_driver_info max20730_info[] = {
 166        [max20730] = {
 167                .pages = 1,
 168                .read_word_data = max20730_read_word_data,
 169                .write_word_data = max20730_write_word_data,
 170
 171                /* Source : Maxim AN6042 */
 172                .format[PSC_TEMPERATURE] = direct,
 173                .m[PSC_TEMPERATURE] = 21,
 174                .b[PSC_TEMPERATURE] = 5887,
 175                .R[PSC_TEMPERATURE] = -1,
 176
 177                .format[PSC_VOLTAGE_IN] = direct,
 178                .m[PSC_VOLTAGE_IN] = 3609,
 179                .b[PSC_VOLTAGE_IN] = 0,
 180                .R[PSC_VOLTAGE_IN] = -2,
 181
 182                /*
 183                 * Values in the datasheet are adjusted for temperature and
 184                 * for the relationship between Vin and Vout.
 185                 * Unfortunately, the data sheet suggests that Vout measurement
 186                 * may be scaled with a resistor array. This is indeed the case
 187                 * at least on the evaulation boards. As a result, any in-driver
 188                 * adjustments would either be wrong or require elaborate means
 189                 * to configure the scaling. Instead of doing that, just report
 190                 * raw values and let userspace handle adjustments.
 191                 */
 192                .format[PSC_CURRENT_OUT] = direct,
 193                .m[PSC_CURRENT_OUT] = 153,
 194                .b[PSC_CURRENT_OUT] = 4976,
 195                .R[PSC_CURRENT_OUT] = -1,
 196
 197                .format[PSC_VOLTAGE_OUT] = linear,
 198
 199                .func[0] = PMBUS_HAVE_VIN |
 200                        PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
 201                        PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
 202                        PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
 203        },
 204        [max20734] = {
 205                .pages = 1,
 206                .read_word_data = max20730_read_word_data,
 207                .write_word_data = max20730_write_word_data,
 208
 209                /* Source : Maxim AN6209 */
 210                .format[PSC_TEMPERATURE] = direct,
 211                .m[PSC_TEMPERATURE] = 21,
 212                .b[PSC_TEMPERATURE] = 5887,
 213                .R[PSC_TEMPERATURE] = -1,
 214
 215                .format[PSC_VOLTAGE_IN] = direct,
 216                .m[PSC_VOLTAGE_IN] = 3592,
 217                .b[PSC_VOLTAGE_IN] = 0,
 218                .R[PSC_VOLTAGE_IN] = -2,
 219
 220                .format[PSC_CURRENT_OUT] = direct,
 221                .m[PSC_CURRENT_OUT] = 111,
 222                .b[PSC_CURRENT_OUT] = 3461,
 223                .R[PSC_CURRENT_OUT] = -1,
 224
 225                .format[PSC_VOLTAGE_OUT] = linear,
 226
 227                .func[0] = PMBUS_HAVE_VIN |
 228                        PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
 229                        PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
 230                        PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
 231        },
 232        [max20743] = {
 233                .pages = 1,
 234                .read_word_data = max20730_read_word_data,
 235                .write_word_data = max20730_write_word_data,
 236
 237                /* Source : Maxim AN6042 */
 238                .format[PSC_TEMPERATURE] = direct,
 239                .m[PSC_TEMPERATURE] = 21,
 240                .b[PSC_TEMPERATURE] = 5887,
 241                .R[PSC_TEMPERATURE] = -1,
 242
 243                .format[PSC_VOLTAGE_IN] = direct,
 244                .m[PSC_VOLTAGE_IN] = 3597,
 245                .b[PSC_VOLTAGE_IN] = 0,
 246                .R[PSC_VOLTAGE_IN] = -2,
 247
 248                .format[PSC_CURRENT_OUT] = direct,
 249                .m[PSC_CURRENT_OUT] = 95,
 250                .b[PSC_CURRENT_OUT] = 5014,
 251                .R[PSC_CURRENT_OUT] = -1,
 252
 253                .format[PSC_VOLTAGE_OUT] = linear,
 254
 255                .func[0] = PMBUS_HAVE_VIN |
 256                        PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
 257                        PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
 258                        PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
 259        },
 260};
 261
 262static int max20730_probe(struct i2c_client *client,
 263                          const struct i2c_device_id *id)
 264{
 265        struct device *dev = &client->dev;
 266        u8 buf[I2C_SMBUS_BLOCK_MAX + 1];
 267        struct max20730_data *data;
 268        enum chips chip_id;
 269        int ret;
 270
 271        if (!i2c_check_functionality(client->adapter,
 272                                     I2C_FUNC_SMBUS_READ_BYTE_DATA |
 273                                     I2C_FUNC_SMBUS_READ_WORD_DATA |
 274                                     I2C_FUNC_SMBUS_BLOCK_DATA))
 275                return -ENODEV;
 276
 277        ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, buf);
 278        if (ret < 0) {
 279                dev_err(&client->dev, "Failed to read Manufacturer ID\n");
 280                return ret;
 281        }
 282        if (ret != 5 || strncmp(buf, "MAXIM", 5)) {
 283                buf[ret] = '\0';
 284                dev_err(dev, "Unsupported Manufacturer ID '%s'\n", buf);
 285                return -ENODEV;
 286        }
 287
 288        /*
 289         * The chips support reading PMBUS_MFR_MODEL. On both MAX20730
 290         * and MAX20734, reading it returns M20743. Presumably that is
 291         * the reason why the command is not documented. Unfortunately,
 292         * that means that there is no reliable means to detect the chip.
 293         * However, we can at least detect the chip series. Compare
 294         * the returned value against 'M20743' and bail out if there is
 295         * a mismatch. If that doesn't work for all chips, we may have
 296         * to remove this check.
 297         */
 298        ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, buf);
 299        if (ret < 0) {
 300                dev_err(dev, "Failed to read Manufacturer Model\n");
 301                return ret;
 302        }
 303        if (ret != 6 || strncmp(buf, "M20743", 6)) {
 304                buf[ret] = '\0';
 305                dev_err(dev, "Unsupported Manufacturer Model '%s'\n", buf);
 306                return -ENODEV;
 307        }
 308
 309        ret = i2c_smbus_read_block_data(client, PMBUS_MFR_REVISION, buf);
 310        if (ret < 0) {
 311                dev_err(dev, "Failed to read Manufacturer Revision\n");
 312                return ret;
 313        }
 314        if (ret != 1 || buf[0] != 'F') {
 315                buf[ret] = '\0';
 316                dev_err(dev, "Unsupported Manufacturer Revision '%s'\n", buf);
 317                return -ENODEV;
 318        }
 319
 320        if (client->dev.of_node)
 321                chip_id = (enum chips)of_device_get_match_data(dev);
 322        else
 323                chip_id = id->driver_data;
 324
 325        data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 326        if (!data)
 327                return -ENOMEM;
 328        data->id = chip_id;
 329        mutex_init(&data->lock);
 330        memcpy(&data->info, &max20730_info[chip_id], sizeof(data->info));
 331
 332        ret = i2c_smbus_read_word_data(client, MAX20730_MFR_DEVSET1);
 333        if (ret < 0)
 334                return ret;
 335        data->mfr_devset1 = ret;
 336
 337        return pmbus_do_probe(client, id, &data->info);
 338}
 339
 340static const struct i2c_device_id max20730_id[] = {
 341        { "max20730", max20730 },
 342        { "max20734", max20734 },
 343        { "max20743", max20743 },
 344        { },
 345};
 346
 347MODULE_DEVICE_TABLE(i2c, max20730_id);
 348
 349static const struct of_device_id max20730_of_match[] = {
 350        { .compatible = "maxim,max20730", .data = (void *)max20730 },
 351        { .compatible = "maxim,max20734", .data = (void *)max20734 },
 352        { .compatible = "maxim,max20743", .data = (void *)max20743 },
 353        { },
 354};
 355
 356MODULE_DEVICE_TABLE(of, max20730_of_match);
 357
 358static struct i2c_driver max20730_driver = {
 359        .driver = {
 360                .name = "max20730",
 361                .of_match_table = max20730_of_match,
 362        },
 363        .probe = max20730_probe,
 364        .remove = pmbus_do_remove,
 365        .id_table = max20730_id,
 366};
 367
 368module_i2c_driver(max20730_driver);
 369
 370MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
 371MODULE_DESCRIPTION("PMBus driver for Maxim MAX20730 / MAX20734 / MAX20743");
 372MODULE_LICENSE("GPL");
 373