linux/drivers/hwmon/pmbus/max15301.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Hardware monitoring driver for Maxim MAX15301
   4 *
   5 * Copyright (c) 2021 Flextronics International Sweden AB
   6 *
   7 * Even though the specification does not specifically mention it,
   8 * extensive empirical testing has revealed that auto-detection of
   9 * limit-registers will fail in a random fashion unless the delay
  10 * parameter is set to above about 80us. The default delay is set
  11 * to 100us to include some safety margin.
  12 */
  13
  14#include <linux/kernel.h>
  15#include <linux/module.h>
  16#include <linux/init.h>
  17#include <linux/err.h>
  18#include <linux/slab.h>
  19#include <linux/i2c.h>
  20#include <linux/ktime.h>
  21#include <linux/delay.h>
  22#include <linux/pmbus.h>
  23#include "pmbus.h"
  24
  25static const struct i2c_device_id max15301_id[] = {
  26        {"bmr461", 0},
  27        {"max15301", 0},
  28        {}
  29};
  30MODULE_DEVICE_TABLE(i2c, max15301_id);
  31
  32struct max15301_data {
  33        int id;
  34        ktime_t access;         /* Chip access time */
  35        int delay;              /* Delay between chip accesses in us */
  36        struct pmbus_driver_info info;
  37};
  38
  39#define to_max15301_data(x)  container_of(x, struct max15301_data, info)
  40
  41#define MAX15301_WAIT_TIME              100     /* us   */
  42
  43static ushort delay = MAX15301_WAIT_TIME;
  44module_param(delay, ushort, 0644);
  45MODULE_PARM_DESC(delay, "Delay between chip accesses in us");
  46
  47static struct max15301_data max15301_data = {
  48        .info = {
  49                .pages = 1,
  50                .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
  51                        | PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
  52                        | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2
  53                        | PMBUS_HAVE_STATUS_TEMP
  54                        | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
  55        }
  56};
  57
  58/* This chip needs a delay between accesses */
  59static inline void max15301_wait(const struct max15301_data *data)
  60{
  61        if (data->delay) {
  62                s64 delta = ktime_us_delta(ktime_get(), data->access);
  63
  64                if (delta < data->delay)
  65                        udelay(data->delay - delta);
  66        }
  67}
  68
  69static int max15301_read_word_data(struct i2c_client *client, int page,
  70                                   int phase, int reg)
  71{
  72        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
  73        struct max15301_data *data = to_max15301_data(info);
  74        int ret;
  75
  76        if (page > 0)
  77                return -ENXIO;
  78
  79        if (reg >= PMBUS_VIRT_BASE)
  80                return -ENXIO;
  81
  82        max15301_wait(data);
  83        ret = pmbus_read_word_data(client, page, phase, reg);
  84        data->access = ktime_get();
  85
  86        return ret;
  87}
  88
  89static int max15301_read_byte_data(struct i2c_client *client, int page, int reg)
  90{
  91        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
  92        struct max15301_data *data = to_max15301_data(info);
  93        int ret;
  94
  95        if (page > 0)
  96                return -ENXIO;
  97
  98        max15301_wait(data);
  99        ret = pmbus_read_byte_data(client, page, reg);
 100        data->access = ktime_get();
 101
 102        return ret;
 103}
 104
 105static int max15301_write_word_data(struct i2c_client *client, int page, int reg,
 106                                    u16 word)
 107{
 108        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
 109        struct max15301_data *data = to_max15301_data(info);
 110        int ret;
 111
 112        if (page > 0)
 113                return -ENXIO;
 114
 115        if (reg >= PMBUS_VIRT_BASE)
 116                return -ENXIO;
 117
 118        max15301_wait(data);
 119        ret = pmbus_write_word_data(client, page, reg, word);
 120        data->access = ktime_get();
 121
 122        return ret;
 123}
 124
 125static int max15301_write_byte(struct i2c_client *client, int page, u8 value)
 126{
 127        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
 128        struct max15301_data *data = to_max15301_data(info);
 129        int ret;
 130
 131        if (page > 0)
 132                return -ENXIO;
 133
 134        max15301_wait(data);
 135        ret = pmbus_write_byte(client, page, value);
 136        data->access = ktime_get();
 137
 138        return ret;
 139}
 140
 141static int max15301_probe(struct i2c_client *client)
 142{
 143        int status;
 144        u8 device_id[I2C_SMBUS_BLOCK_MAX + 1];
 145        const struct i2c_device_id *mid;
 146        struct pmbus_driver_info *info = &max15301_data.info;
 147
 148        if (!i2c_check_functionality(client->adapter,
 149                                     I2C_FUNC_SMBUS_READ_BYTE_DATA
 150                                     | I2C_FUNC_SMBUS_BLOCK_DATA))
 151                return -ENODEV;
 152
 153        status = i2c_smbus_read_block_data(client, PMBUS_IC_DEVICE_ID, device_id);
 154        if (status < 0) {
 155                dev_err(&client->dev, "Failed to read Device Id\n");
 156                return status;
 157        }
 158        for (mid = max15301_id; mid->name[0]; mid++) {
 159                if (!strncasecmp(mid->name, device_id, strlen(mid->name)))
 160                        break;
 161        }
 162        if (!mid->name[0]) {
 163                dev_err(&client->dev, "Unsupported device\n");
 164                return -ENODEV;
 165        }
 166
 167        max15301_data.delay = delay;
 168
 169        info->read_byte_data = max15301_read_byte_data;
 170        info->read_word_data = max15301_read_word_data;
 171        info->write_byte = max15301_write_byte;
 172        info->write_word_data = max15301_write_word_data;
 173
 174        return pmbus_do_probe(client, info);
 175}
 176
 177static struct i2c_driver max15301_driver = {
 178        .driver = {
 179                   .name = "max15301",
 180                   },
 181        .probe_new = max15301_probe,
 182        .id_table = max15301_id,
 183};
 184
 185module_i2c_driver(max15301_driver);
 186
 187MODULE_AUTHOR("Erik Rosen <erik.rosen@metormote.com>");
 188MODULE_DESCRIPTION("PMBus driver for Maxim MAX15301");
 189MODULE_LICENSE("GPL");
 190MODULE_IMPORT_NS(PMBUS);
 191