diff options
Diffstat (limited to 'drivers/hwmon/pmbus')
-rw-r--r-- | drivers/hwmon/pmbus/Kconfig | 4 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/adm1275.c | 13 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/max20730.c | 49 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/pmbus_core.c | 66 |
4 files changed, 82 insertions, 50 deletions
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig index ea516cec1d35..e35db489b76f 100644 --- a/drivers/hwmon/pmbus/Kconfig +++ b/drivers/hwmon/pmbus/Kconfig @@ -156,10 +156,10 @@ config SENSORS_MAX16601 be called max16601. config SENSORS_MAX20730 - tristate "Maxim MAX20730, MAX20734, MAX20743" + tristate "Maxim MAX20710, MAX20730, MAX20734, MAX20743" help If you say yes here you get hardware monitoring support for Maxim - MAX20730, MAX20734, and MAX20743. + MAX20710, MAX20730, MAX20734, and MAX20743. This driver can also be built as a module. If so, the module will be called max20730. diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c index 19317575d1c6..651846650a9c 100644 --- a/drivers/hwmon/pmbus/adm1275.c +++ b/drivers/hwmon/pmbus/adm1275.c @@ -683,11 +683,13 @@ static int adm1275_probe(struct i2c_client *client, tindex = 3; info->func[0] |= PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT | - PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; + PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | + PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; - /* Enable VOUT if not enabled (it is disabled by default) */ - if (!(config & ADM1278_VOUT_EN)) { - config |= ADM1278_VOUT_EN; + /* Enable VOUT & TEMP1 if not enabled (disabled by default) */ + if ((config & (ADM1278_VOUT_EN | ADM1278_TEMP1_EN)) != + (ADM1278_VOUT_EN | ADM1278_TEMP1_EN)) { + config |= ADM1278_VOUT_EN | ADM1278_TEMP1_EN; ret = i2c_smbus_write_byte_data(client, ADM1275_PMON_CONFIG, config); @@ -698,9 +700,6 @@ static int adm1275_probe(struct i2c_client *client, } } - if (config & ADM1278_TEMP1_EN) - info->func[0] |= - PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; if (config & ADM1278_VIN_EN) info->func[0] |= PMBUS_HAVE_VIN; break; diff --git a/drivers/hwmon/pmbus/max20730.c b/drivers/hwmon/pmbus/max20730.c index c0bb05487e0e..a151a2b588a5 100644 --- a/drivers/hwmon/pmbus/max20730.c +++ b/drivers/hwmon/pmbus/max20730.c @@ -1,9 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Driver for MAX20730, MAX20734, and MAX20743 Integrated, Step-Down - * Switching Regulators + * Driver for MAX20710, MAX20730, MAX20734, and MAX20743 Integrated, + * Step-Down Switching Regulators * * Copyright 2019 Google LLC. + * Copyright 2020 Maxim Integrated */ #include <linux/bits.h> @@ -19,6 +20,7 @@ #include "pmbus.h" enum chips { + max20710, max20730, max20734, max20743 @@ -80,6 +82,7 @@ static long direct_to_val(u16 w, enum pmbus_sensor_classes class, } static u32 max_current[][5] = { + [max20710] = { 6200, 8000, 9700, 11600 }, [max20730] = { 13000, 16600, 20100, 23600 }, [max20734] = { 21000, 27000, 32000, 38000 }, [max20743] = { 18900, 24100, 29200, 34100 }, @@ -164,6 +167,35 @@ static int max20730_write_word_data(struct i2c_client *client, int page, } static const struct pmbus_driver_info max20730_info[] = { + [max20710] = { + .pages = 1, + .read_word_data = max20730_read_word_data, + .write_word_data = max20730_write_word_data, + + /* Source : Maxim AN6140 and AN6042 */ + .format[PSC_TEMPERATURE] = direct, + .m[PSC_TEMPERATURE] = 21, + .b[PSC_TEMPERATURE] = 5887, + .R[PSC_TEMPERATURE] = -1, + + .format[PSC_VOLTAGE_IN] = direct, + .m[PSC_VOLTAGE_IN] = 3609, + .b[PSC_VOLTAGE_IN] = 0, + .R[PSC_VOLTAGE_IN] = -2, + + .format[PSC_CURRENT_OUT] = direct, + .m[PSC_CURRENT_OUT] = 153, + .b[PSC_CURRENT_OUT] = 4976, + .R[PSC_CURRENT_OUT] = -1, + + .format[PSC_VOLTAGE_OUT] = linear, + + .func[0] = PMBUS_HAVE_VIN | + PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | + PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | + PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | + PMBUS_HAVE_STATUS_INPUT, + }, [max20730] = { .pages = 1, .read_word_data = max20730_read_word_data, @@ -200,7 +232,8 @@ static const struct pmbus_driver_info max20730_info[] = { .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | - PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, + PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | + PMBUS_HAVE_STATUS_INPUT, }, [max20734] = { .pages = 1, @@ -228,7 +261,8 @@ static const struct pmbus_driver_info max20730_info[] = { .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | - PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, + PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | + PMBUS_HAVE_STATUS_INPUT, }, [max20743] = { .pages = 1, @@ -256,7 +290,8 @@ static const struct pmbus_driver_info max20730_info[] = { .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | - PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, + PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | + PMBUS_HAVE_STATUS_INPUT, }, }; @@ -339,6 +374,7 @@ static int max20730_probe(struct i2c_client *client, } static const struct i2c_device_id max20730_id[] = { + { "max20710", max20710 }, { "max20730", max20730 }, { "max20734", max20734 }, { "max20743", max20743 }, @@ -348,6 +384,7 @@ static const struct i2c_device_id max20730_id[] = { MODULE_DEVICE_TABLE(i2c, max20730_id); static const struct of_device_id max20730_of_match[] = { + { .compatible = "maxim,max20710", .data = (void *)max20710 }, { .compatible = "maxim,max20730", .data = (void *)max20730 }, { .compatible = "maxim,max20734", .data = (void *)max20734 }, { .compatible = "maxim,max20743", .data = (void *)max20743 }, @@ -369,5 +406,5 @@ static struct i2c_driver max20730_driver = { module_i2c_driver(max20730_driver); MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>"); -MODULE_DESCRIPTION("PMBus driver for Maxim MAX20730 / MAX20734 / MAX20743"); +MODULE_DESCRIPTION("PMBus driver for Maxim MAX20710 / MAX20730 / MAX20734 / MAX20743"); MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index 2191575a448b..44535add3a4a 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -628,12 +628,12 @@ static struct pmbus_data *pmbus_update_device(struct device *dev) * Convert linear sensor values to milli- or micro-units * depending on sensor type. */ -static long pmbus_reg2data_linear(struct pmbus_data *data, - struct pmbus_sensor *sensor) +static s64 pmbus_reg2data_linear(struct pmbus_data *data, + struct pmbus_sensor *sensor) { s16 exponent; s32 mantissa; - long val; + s64 val; if (sensor->class == PSC_VOLTAGE_OUT) { /* LINEAR16 */ exponent = data->exponent[sensor->page]; @@ -647,11 +647,11 @@ static long pmbus_reg2data_linear(struct pmbus_data *data, /* scale result to milli-units for all sensors except fans */ if (sensor->class != PSC_FAN) - val = val * 1000L; + val = val * 1000LL; /* scale result to micro-units for power sensors */ if (sensor->class == PSC_POWER) - val = val * 1000L; + val = val * 1000LL; if (exponent >= 0) val <<= exponent; @@ -665,8 +665,8 @@ static long pmbus_reg2data_linear(struct pmbus_data *data, * Convert direct sensor values to milli- or micro-units * depending on sensor type. */ -static long pmbus_reg2data_direct(struct pmbus_data *data, - struct pmbus_sensor *sensor) +static s64 pmbus_reg2data_direct(struct pmbus_data *data, + struct pmbus_sensor *sensor) { s64 b, val = (s16)sensor->data; s32 m, R; @@ -702,15 +702,15 @@ static long pmbus_reg2data_direct(struct pmbus_data *data, } val = div_s64(val - b, m); - return clamp_val(val, LONG_MIN, LONG_MAX); + return val; } /* * Convert VID sensor values to milli- or micro-units * depending on sensor type. */ -static long pmbus_reg2data_vid(struct pmbus_data *data, - struct pmbus_sensor *sensor) +static s64 pmbus_reg2data_vid(struct pmbus_data *data, + struct pmbus_sensor *sensor) { long val = sensor->data; long rv = 0; @@ -740,9 +740,9 @@ static long pmbus_reg2data_vid(struct pmbus_data *data, return rv; } -static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor) +static s64 pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor) { - long val; + s64 val; if (!sensor->convert) return sensor->data; @@ -766,7 +766,7 @@ static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor) #define MIN_MANTISSA (511 * 1000) static u16 pmbus_data2reg_linear(struct pmbus_data *data, - struct pmbus_sensor *sensor, long val) + struct pmbus_sensor *sensor, s64 val) { s16 exponent = 0, mantissa; bool negative = false; @@ -788,8 +788,8 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data, val <<= -data->exponent[sensor->page]; else val >>= data->exponent[sensor->page]; - val = DIV_ROUND_CLOSEST(val, 1000); - return val & 0xffff; + val = DIV_ROUND_CLOSEST_ULL(val, 1000); + return clamp_val(val, 0, 0xffff); } if (val < 0) { @@ -799,14 +799,14 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data, /* Power is in uW. Convert to mW before converting. */ if (sensor->class == PSC_POWER) - val = DIV_ROUND_CLOSEST(val, 1000L); + val = DIV_ROUND_CLOSEST_ULL(val, 1000); /* * For simplicity, convert fan data to milli-units * before calculating the exponent. */ if (sensor->class == PSC_FAN) - val = val * 1000; + val = val * 1000LL; /* Reduce large mantissa until it fits into 10 bit */ while (val >= MAX_MANTISSA && exponent < 15) { @@ -820,11 +820,7 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data, } /* Convert mantissa from milli-units to units */ - mantissa = DIV_ROUND_CLOSEST(val, 1000); - - /* Ensure that resulting number is within range */ - if (mantissa > 0x3ff) - mantissa = 0x3ff; + mantissa = clamp_val(DIV_ROUND_CLOSEST_ULL(val, 1000), 0, 0x3ff); /* restore sign */ if (negative) @@ -835,9 +831,9 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data, } static u16 pmbus_data2reg_direct(struct pmbus_data *data, - struct pmbus_sensor *sensor, long val) + struct pmbus_sensor *sensor, s64 val) { - s64 b, val64 = val; + s64 b; s32 m, R; m = data->info->m[sensor->class]; @@ -855,30 +851,30 @@ static u16 pmbus_data2reg_direct(struct pmbus_data *data, R -= 3; /* Adjust R and b for data in milli-units */ b *= 1000; } - val64 = val64 * m + b; + val = val * m + b; while (R > 0) { - val64 *= 10; + val *= 10; R--; } while (R < 0) { - val64 = div_s64(val64 + 5LL, 10L); /* round closest */ + val = div_s64(val + 5LL, 10L); /* round closest */ R++; } - return (u16)clamp_val(val64, S16_MIN, S16_MAX); + return (u16)clamp_val(val, S16_MIN, S16_MAX); } static u16 pmbus_data2reg_vid(struct pmbus_data *data, - struct pmbus_sensor *sensor, long val) + struct pmbus_sensor *sensor, s64 val) { val = clamp_val(val, 500, 1600); - return 2 + DIV_ROUND_CLOSEST((1600 - val) * 100, 625); + return 2 + DIV_ROUND_CLOSEST_ULL((1600LL - val) * 100LL, 625); } static u16 pmbus_data2reg(struct pmbus_data *data, - struct pmbus_sensor *sensor, long val) + struct pmbus_sensor *sensor, s64 val) { u16 regval; @@ -944,7 +940,7 @@ static int pmbus_get_boolean(struct pmbus_data *data, struct pmbus_boolean *b, WARN(1, "Bad boolean descriptor %p: s1=%p, s2=%p\n", b, s1, s2); return 0; } else { - long v1, v2; + s64 v1, v2; if (s1->data < 0) return s1->data; @@ -981,7 +977,7 @@ static ssize_t pmbus_show_sensor(struct device *dev, if (sensor->data < 0) return sensor->data; - return snprintf(buf, PAGE_SIZE, "%ld\n", pmbus_reg2data(data, sensor)); + return snprintf(buf, PAGE_SIZE, "%lld\n", pmbus_reg2data(data, sensor)); } static ssize_t pmbus_set_sensor(struct device *dev, @@ -992,11 +988,11 @@ static ssize_t pmbus_set_sensor(struct device *dev, struct pmbus_data *data = i2c_get_clientdata(client); struct pmbus_sensor *sensor = to_pmbus_sensor(devattr); ssize_t rv = count; - long val = 0; + s64 val; int ret; u16 regval; - if (kstrtol(buf, 10, &val) < 0) + if (kstrtos64(buf, 10, &val) < 0) return -EINVAL; mutex_lock(&data->update_lock); |