Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Hardware monitoring driver for Maxim MAX15301
0004  *
0005  * Copyright (c) 2021 Flextronics International Sweden AB
0006  *
0007  * Even though the specification does not specifically mention it,
0008  * extensive empirical testing has revealed that auto-detection of
0009  * limit-registers will fail in a random fashion unless the delay
0010  * parameter is set to above about 80us. The default delay is set
0011  * to 100us to include some safety margin.
0012  */
0013 
0014 #include <linux/kernel.h>
0015 #include <linux/module.h>
0016 #include <linux/init.h>
0017 #include <linux/err.h>
0018 #include <linux/slab.h>
0019 #include <linux/i2c.h>
0020 #include <linux/ktime.h>
0021 #include <linux/delay.h>
0022 #include <linux/pmbus.h>
0023 #include "pmbus.h"
0024 
0025 static const struct i2c_device_id max15301_id[] = {
0026     {"bmr461", 0},
0027     {"max15301", 0},
0028     {}
0029 };
0030 MODULE_DEVICE_TABLE(i2c, max15301_id);
0031 
0032 struct max15301_data {
0033     int id;
0034     ktime_t access;     /* Chip access time */
0035     int delay;      /* Delay between chip accesses in us */
0036     struct pmbus_driver_info info;
0037 };
0038 
0039 #define to_max15301_data(x)  container_of(x, struct max15301_data, info)
0040 
0041 #define MAX15301_WAIT_TIME      100 /* us   */
0042 
0043 static ushort delay = MAX15301_WAIT_TIME;
0044 module_param(delay, ushort, 0644);
0045 MODULE_PARM_DESC(delay, "Delay between chip accesses in us");
0046 
0047 static struct max15301_data max15301_data = {
0048     .info = {
0049         .pages = 1,
0050         .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
0051             | PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
0052             | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2
0053             | PMBUS_HAVE_STATUS_TEMP
0054             | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
0055     }
0056 };
0057 
0058 /* This chip needs a delay between accesses */
0059 static inline void max15301_wait(const struct max15301_data *data)
0060 {
0061     if (data->delay) {
0062         s64 delta = ktime_us_delta(ktime_get(), data->access);
0063 
0064         if (delta < data->delay)
0065             udelay(data->delay - delta);
0066     }
0067 }
0068 
0069 static int max15301_read_word_data(struct i2c_client *client, int page,
0070                    int phase, int reg)
0071 {
0072     const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
0073     struct max15301_data *data = to_max15301_data(info);
0074     int ret;
0075 
0076     if (page > 0)
0077         return -ENXIO;
0078 
0079     if (reg >= PMBUS_VIRT_BASE)
0080         return -ENXIO;
0081 
0082     max15301_wait(data);
0083     ret = pmbus_read_word_data(client, page, phase, reg);
0084     data->access = ktime_get();
0085 
0086     return ret;
0087 }
0088 
0089 static int max15301_read_byte_data(struct i2c_client *client, int page, int reg)
0090 {
0091     const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
0092     struct max15301_data *data = to_max15301_data(info);
0093     int ret;
0094 
0095     if (page > 0)
0096         return -ENXIO;
0097 
0098     max15301_wait(data);
0099     ret = pmbus_read_byte_data(client, page, reg);
0100     data->access = ktime_get();
0101 
0102     return ret;
0103 }
0104 
0105 static int max15301_write_word_data(struct i2c_client *client, int page, int reg,
0106                     u16 word)
0107 {
0108     const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
0109     struct max15301_data *data = to_max15301_data(info);
0110     int ret;
0111 
0112     if (page > 0)
0113         return -ENXIO;
0114 
0115     if (reg >= PMBUS_VIRT_BASE)
0116         return -ENXIO;
0117 
0118     max15301_wait(data);
0119     ret = pmbus_write_word_data(client, page, reg, word);
0120     data->access = ktime_get();
0121 
0122     return ret;
0123 }
0124 
0125 static int max15301_write_byte(struct i2c_client *client, int page, u8 value)
0126 {
0127     const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
0128     struct max15301_data *data = to_max15301_data(info);
0129     int ret;
0130 
0131     if (page > 0)
0132         return -ENXIO;
0133 
0134     max15301_wait(data);
0135     ret = pmbus_write_byte(client, page, value);
0136     data->access = ktime_get();
0137 
0138     return ret;
0139 }
0140 
0141 static int max15301_probe(struct i2c_client *client)
0142 {
0143     int status;
0144     u8 device_id[I2C_SMBUS_BLOCK_MAX + 1];
0145     const struct i2c_device_id *mid;
0146     struct pmbus_driver_info *info = &max15301_data.info;
0147 
0148     if (!i2c_check_functionality(client->adapter,
0149                      I2C_FUNC_SMBUS_READ_BYTE_DATA
0150                      | I2C_FUNC_SMBUS_BLOCK_DATA))
0151         return -ENODEV;
0152 
0153     status = i2c_smbus_read_block_data(client, PMBUS_IC_DEVICE_ID, device_id);
0154     if (status < 0) {
0155         dev_err(&client->dev, "Failed to read Device Id\n");
0156         return status;
0157     }
0158     for (mid = max15301_id; mid->name[0]; mid++) {
0159         if (!strncasecmp(mid->name, device_id, strlen(mid->name)))
0160             break;
0161     }
0162     if (!mid->name[0]) {
0163         dev_err(&client->dev, "Unsupported device\n");
0164         return -ENODEV;
0165     }
0166 
0167     max15301_data.delay = delay;
0168 
0169     info->read_byte_data = max15301_read_byte_data;
0170     info->read_word_data = max15301_read_word_data;
0171     info->write_byte = max15301_write_byte;
0172     info->write_word_data = max15301_write_word_data;
0173 
0174     return pmbus_do_probe(client, info);
0175 }
0176 
0177 static struct i2c_driver max15301_driver = {
0178     .driver = {
0179            .name = "max15301",
0180            },
0181     .probe_new = max15301_probe,
0182     .id_table = max15301_id,
0183 };
0184 
0185 module_i2c_driver(max15301_driver);
0186 
0187 MODULE_AUTHOR("Erik Rosen <erik.rosen@metormote.com>");
0188 MODULE_DESCRIPTION("PMBus driver for Maxim MAX15301");
0189 MODULE_LICENSE("GPL");
0190 MODULE_IMPORT_NS(PMBUS);