diff options
Diffstat (limited to 'drivers/hwmon/pmbus')
-rw-r--r-- | drivers/hwmon/pmbus/Kconfig | 36 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/Makefile | 2 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/ltc2978.c | 16 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/max16601.c | 14 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/mpq7932.c | 156 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/pmbus.h | 5 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/tda38640.c | 74 |
7 files changed, 286 insertions, 17 deletions
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig index 89668af67206..59d9a7430499 100644 --- a/drivers/hwmon/pmbus/Kconfig +++ b/drivers/hwmon/pmbus/Kconfig @@ -237,10 +237,10 @@ config SENSORS_MAX16064 be called max16064. config SENSORS_MAX16601 - tristate "Maxim MAX16508, MAX16601, MAX16602" + tristate "Maxim MAX16508, MAX16600, MAX16601, and MAX16602" help If you say yes here you get hardware monitoring support for Maxim - MAX16508, MAX16601 and MAX16602. + MAX16508, MAX16600, MAX16601, and MAX16602. This driver can also be built as a module. If so, the module will be called max16601. @@ -317,6 +317,22 @@ config SENSORS_MP5023 This driver can also be built as a module. If so, the module will be called mp5023. +config SENSORS_MPQ7932_REGULATOR + bool "Regulator support for MPQ7932" + depends on SENSORS_MPQ7932 && REGULATOR + help + If you say yes here you get six integrated buck converter regulator + support for power management IC MPS MPQ7932. + +config SENSORS_MPQ7932 + tristate "MPS MPQ7932" + help + If you say yes here you get hardware monitoring functionality support + for power management IC MPS MPQ7932. + + This driver can also be built as a module. If so, the module will + be called mpq7932. + config SENSORS_PIM4328 tristate "Flex PIM4328 and compatibles" help @@ -379,6 +395,22 @@ config SENSORS_STPDDC60 This driver can also be built as a module. If so, the module will be called stpddc60. +config SENSORS_TDA38640 + tristate "Infineon TDA38640" + help + If you say yes here you get hardware monitoring support for Infineon + TDA38640. + + This driver can also be built as a module. If so, the module will + be called tda38640. + +config SENSORS_TDA38640_REGULATOR + bool "Regulator support for TDA38640 and compatibles" + depends on SENSORS_TDA38640 && REGULATOR + help + If you say yes here you get regulator support for Infineon + TDA38640 as regulator. + config SENSORS_TPS40422 tristate "TI TPS40422" help diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile index 0002dbe22d52..3ae019916267 100644 --- a/drivers/hwmon/pmbus/Makefile +++ b/drivers/hwmon/pmbus/Makefile @@ -34,11 +34,13 @@ obj-$(CONFIG_SENSORS_MAX8688) += max8688.o obj-$(CONFIG_SENSORS_MP2888) += mp2888.o obj-$(CONFIG_SENSORS_MP2975) += mp2975.o obj-$(CONFIG_SENSORS_MP5023) += mp5023.o +obj-$(CONFIG_SENSORS_MPQ7932) += mpq7932.o obj-$(CONFIG_SENSORS_PLI1209BC) += pli1209bc.o obj-$(CONFIG_SENSORS_PM6764TR) += pm6764tr.o obj-$(CONFIG_SENSORS_PXE1610) += pxe1610.o obj-$(CONFIG_SENSORS_Q54SJ108A2) += q54sj108a2.o obj-$(CONFIG_SENSORS_STPDDC60) += stpddc60.o +obj-$(CONFIG_SENSORS_TDA38640) += tda38640.o obj-$(CONFIG_SENSORS_TPS40422) += tps40422.o obj-$(CONFIG_SENSORS_TPS53679) += tps53679.o obj-$(CONFIG_SENSORS_TPS546D24) += tps546d24.o diff --git a/drivers/hwmon/pmbus/ltc2978.c b/drivers/hwmon/pmbus/ltc2978.c index 79f480b4425d..91df8e895147 100644 --- a/drivers/hwmon/pmbus/ltc2978.c +++ b/drivers/hwmon/pmbus/ltc2978.c @@ -570,14 +570,14 @@ MODULE_DEVICE_TABLE(i2c, ltc2978_id); #define LTC2978_N_VOLTAGES ((LTC2978_MAX_UV / LTC2978_UV_STEP) + 1) static const struct regulator_desc ltc2978_reg_desc[] = { - PMBUS_REGULATOR_STEP("vout", 0, LTC2978_N_VOLTAGES, LTC2978_UV_STEP), - PMBUS_REGULATOR_STEP("vout", 1, LTC2978_N_VOLTAGES, LTC2978_UV_STEP), - PMBUS_REGULATOR_STEP("vout", 2, LTC2978_N_VOLTAGES, LTC2978_UV_STEP), - PMBUS_REGULATOR_STEP("vout", 3, LTC2978_N_VOLTAGES, LTC2978_UV_STEP), - PMBUS_REGULATOR_STEP("vout", 4, LTC2978_N_VOLTAGES, LTC2978_UV_STEP), - PMBUS_REGULATOR_STEP("vout", 5, LTC2978_N_VOLTAGES, LTC2978_UV_STEP), - PMBUS_REGULATOR_STEP("vout", 6, LTC2978_N_VOLTAGES, LTC2978_UV_STEP), - PMBUS_REGULATOR_STEP("vout", 7, LTC2978_N_VOLTAGES, LTC2978_UV_STEP), + PMBUS_REGULATOR_STEP("vout", 0, LTC2978_N_VOLTAGES, LTC2978_UV_STEP, 0), + PMBUS_REGULATOR_STEP("vout", 1, LTC2978_N_VOLTAGES, LTC2978_UV_STEP, 0), + PMBUS_REGULATOR_STEP("vout", 2, LTC2978_N_VOLTAGES, LTC2978_UV_STEP, 0), + PMBUS_REGULATOR_STEP("vout", 3, LTC2978_N_VOLTAGES, LTC2978_UV_STEP, 0), + PMBUS_REGULATOR_STEP("vout", 4, LTC2978_N_VOLTAGES, LTC2978_UV_STEP, 0), + PMBUS_REGULATOR_STEP("vout", 5, LTC2978_N_VOLTAGES, LTC2978_UV_STEP, 0), + PMBUS_REGULATOR_STEP("vout", 6, LTC2978_N_VOLTAGES, LTC2978_UV_STEP, 0), + PMBUS_REGULATOR_STEP("vout", 7, LTC2978_N_VOLTAGES, LTC2978_UV_STEP, 0), }; static const struct regulator_desc ltc2978_reg_desc_default[] = { diff --git a/drivers/hwmon/pmbus/max16601.c b/drivers/hwmon/pmbus/max16601.c index b628405e6586..6724f723f74c 100644 --- a/drivers/hwmon/pmbus/max16601.c +++ b/drivers/hwmon/pmbus/max16601.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Hardware monitoring driver for Maxim MAX16508, MAX16601 and MAX16602. + * Hardware monitoring driver for Maxim MAX16508, MAX16600, MAX16601, + * and MAX16602. * * Implementation notes: * @@ -31,7 +32,7 @@ #include "pmbus.h" -enum chips { max16508, max16601, max16602 }; +enum chips { max16508, max16600, max16601, max16602 }; #define REG_DEFAULT_NUM_POP 0xc4 #define REG_SETPT_DVID 0xd1 @@ -202,7 +203,7 @@ static int max16601_identify(struct i2c_client *client, else info->vrm_version[0] = vr12; - if (data->id != max16601 && data->id != max16602) + if (data->id != max16600 && data->id != max16601 && data->id != max16602) return 0; reg = i2c_smbus_read_byte_data(client, REG_DEFAULT_NUM_POP); @@ -263,6 +264,7 @@ static void max16601_remove(void *_data) static const struct i2c_device_id max16601_id[] = { {"max16508", max16508}, + {"max16600", max16600}, {"max16601", max16601}, {"max16602", max16602}, {} @@ -281,11 +283,13 @@ static int max16601_get_id(struct i2c_client *client) return -ENODEV; /* - * PMBUS_IC_DEVICE_ID is expected to return "MAX16601y.xx" or - * MAX16602y.xx or "MAX16500y.xx".cdxxcccccccccc + * PMBUS_IC_DEVICE_ID is expected to return MAX1660[012]y.xx" or + * "MAX16500y.xx".cdxxcccccccccc */ if (!strncmp(buf, "MAX16500", 8)) { id = max16508; + } else if (!strncmp(buf, "MAX16600", 8)) { + id = max16600; } else if (!strncmp(buf, "MAX16601", 8)) { id = max16601; } else if (!strncmp(buf, "MAX16602", 8)) { diff --git a/drivers/hwmon/pmbus/mpq7932.c b/drivers/hwmon/pmbus/mpq7932.c new file mode 100644 index 000000000000..ff939881dc3b --- /dev/null +++ b/drivers/hwmon/pmbus/mpq7932.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * mpq7932.c - hwmon with optional regulator driver for mps mpq7932 + * Copyright 2022 Monolithic Power Systems, Inc + * + * Author: Saravanan Sekar <saravanan@linumiz.com> + */ + +#include <linux/bits.h> +#include <linux/err.h> +#include <linux/i2c.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/pmbus.h> +#include "pmbus.h" + +#define MPQ7932_BUCK_UV_MIN 206250 +#define MPQ7932_UV_STEP 6250 +#define MPQ7932_N_VOLTAGES 256 +#define MPQ7932_VOUT_MAX 0xFF +#define MPQ7932_NUM_PAGES 6 + +#define MPQ7932_TON_DELAY 0x60 +#define MPQ7932_VOUT_STARTUP_SLEW 0xA3 +#define MPQ7932_VOUT_SHUTDOWN_SLEW 0xA5 +#define MPQ7932_VOUT_SLEW_MASK GENMASK(1, 0) +#define MPQ7932_TON_DELAY_MASK GENMASK(4, 0) + +struct mpq7932_data { + struct pmbus_driver_info info; + struct pmbus_platform_data pdata; +}; + +#if IS_ENABLED(CONFIG_SENSORS_MPQ7932_REGULATOR) +static struct regulator_desc mpq7932_regulators_desc[] = { + PMBUS_REGULATOR_STEP("buck", 0, MPQ7932_N_VOLTAGES, + MPQ7932_UV_STEP, MPQ7932_BUCK_UV_MIN), + PMBUS_REGULATOR_STEP("buck", 1, MPQ7932_N_VOLTAGES, + MPQ7932_UV_STEP, MPQ7932_BUCK_UV_MIN), + PMBUS_REGULATOR_STEP("buck", 2, MPQ7932_N_VOLTAGES, + MPQ7932_UV_STEP, MPQ7932_BUCK_UV_MIN), + PMBUS_REGULATOR_STEP("buck", 3, MPQ7932_N_VOLTAGES, + MPQ7932_UV_STEP, MPQ7932_BUCK_UV_MIN), + PMBUS_REGULATOR_STEP("buck", 4, MPQ7932_N_VOLTAGES, + MPQ7932_UV_STEP, MPQ7932_BUCK_UV_MIN), + PMBUS_REGULATOR_STEP("buck", 5, MPQ7932_N_VOLTAGES, + MPQ7932_UV_STEP, MPQ7932_BUCK_UV_MIN), +}; +#endif + +static int mpq7932_write_word_data(struct i2c_client *client, int page, int reg, + u16 word) +{ + switch (reg) { + /* + * chip supports only byte access for VOUT_COMMAND otherwise + * access results -EREMOTEIO + */ + case PMBUS_VOUT_COMMAND: + return pmbus_write_byte_data(client, page, reg, word & 0xFF); + + default: + return -ENODATA; + } +} + +static int mpq7932_read_word_data(struct i2c_client *client, int page, + int phase, int reg) +{ + switch (reg) { + /* + * chip supports neither (PMBUS_VOUT_MARGIN_HIGH, PMBUS_VOUT_MARGIN_LOW) + * nor (PMBUS_MFR_VOUT_MIN, PMBUS_MFR_VOUT_MAX). As a result set voltage + * fails due to error in pmbus_regulator_get_low_margin, so faked. + */ + case PMBUS_MFR_VOUT_MIN: + return 0; + + case PMBUS_MFR_VOUT_MAX: + return MPQ7932_VOUT_MAX; + + /* + * chip supports only byte access for VOUT_COMMAND otherwise + * access results in -EREMOTEIO + */ + case PMBUS_READ_VOUT: + return pmbus_read_byte_data(client, page, PMBUS_VOUT_COMMAND); + + default: + return -ENODATA; + } +} + +static int mpq7932_probe(struct i2c_client *client) +{ + struct mpq7932_data *data; + struct pmbus_driver_info *info; + struct device *dev = &client->dev; + int i; + + data = devm_kzalloc(dev, sizeof(struct mpq7932_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + info = &data->info; + info->pages = MPQ7932_NUM_PAGES; + info->format[PSC_VOLTAGE_OUT] = direct; + info->m[PSC_VOLTAGE_OUT] = 160; + info->b[PSC_VOLTAGE_OUT] = -33; + for (i = 0; i < info->pages; i++) { + info->func[i] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT + | PMBUS_HAVE_STATUS_TEMP; + } + +#if IS_ENABLED(CONFIG_SENSORS_MPQ7932_REGULATOR) + info->num_regulators = ARRAY_SIZE(mpq7932_regulators_desc); + info->reg_desc = mpq7932_regulators_desc; +#endif + + info->read_word_data = mpq7932_read_word_data; + info->write_word_data = mpq7932_write_word_data; + + data->pdata.flags = PMBUS_NO_CAPABILITY; + dev->platform_data = &data->pdata; + + return pmbus_do_probe(client, info); +} + +static const struct of_device_id mpq7932_of_match[] = { + { .compatible = "mps,mpq7932"}, + {}, +}; +MODULE_DEVICE_TABLE(of, mpq7932_of_match); + +static const struct i2c_device_id mpq7932_id[] = { + { "mpq7932", }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, mpq7932_id); + +static struct i2c_driver mpq7932_regulator_driver = { + .driver = { + .name = "mpq7932", + .of_match_table = mpq7932_of_match, + }, + .probe_new = mpq7932_probe, + .id_table = mpq7932_id, +}; +module_i2c_driver(mpq7932_regulator_driver); + +MODULE_AUTHOR("Saravanan Sekar <saravanan@linumiz.com>"); +MODULE_DESCRIPTION("MPQ7932 PMIC regulator driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(PMBUS); diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h index 10fb17879f8e..713ea7915425 100644 --- a/drivers/hwmon/pmbus/pmbus.h +++ b/drivers/hwmon/pmbus/pmbus.h @@ -464,7 +464,7 @@ struct pmbus_driver_info { extern const struct regulator_ops pmbus_regulator_ops; /* Macros for filling in array of struct regulator_desc */ -#define PMBUS_REGULATOR_STEP(_name, _id, _voltages, _step) \ +#define PMBUS_REGULATOR_STEP(_name, _id, _voltages, _step, _min_uV) \ [_id] = { \ .name = (_name # _id), \ .id = (_id), \ @@ -475,9 +475,10 @@ extern const struct regulator_ops pmbus_regulator_ops; .owner = THIS_MODULE, \ .n_voltages = _voltages, \ .uV_step = _step, \ + .min_uV = _min_uV, \ } -#define PMBUS_REGULATOR(_name, _id) PMBUS_REGULATOR_STEP(_name, _id, 0, 0) +#define PMBUS_REGULATOR(_name, _id) PMBUS_REGULATOR_STEP(_name, _id, 0, 0, 0) /* Function declarations */ diff --git a/drivers/hwmon/pmbus/tda38640.c b/drivers/hwmon/pmbus/tda38640.c new file mode 100644 index 000000000000..c3e781319cd1 --- /dev/null +++ b/drivers/hwmon/pmbus/tda38640.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Hardware monitoring driver for Infineon TDA38640 + * + * Copyright (c) 2023 9elements GmbH + * + */ + +#include <linux/err.h> +#include <linux/i2c.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/regulator/driver.h> +#include "pmbus.h" + +static const struct regulator_desc __maybe_unused tda38640_reg_desc[] = { + PMBUS_REGULATOR("vout", 0), +}; + +static struct pmbus_driver_info tda38640_info = { + .pages = 1, + .format[PSC_VOLTAGE_IN] = linear, + .format[PSC_VOLTAGE_OUT] = linear, + .format[PSC_CURRENT_OUT] = linear, + .format[PSC_CURRENT_IN] = linear, + .format[PSC_POWER] = linear, + .format[PSC_TEMPERATURE] = linear, + + .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT + | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP + | PMBUS_HAVE_IIN + | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT + | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT + | PMBUS_HAVE_POUT | PMBUS_HAVE_PIN, +#if IS_ENABLED(CONFIG_SENSORS_TDA38640_REGULATOR) + .num_regulators = 1, + .reg_desc = tda38640_reg_desc, +#endif +}; + +static int tda38640_probe(struct i2c_client *client) +{ + return pmbus_do_probe(client, &tda38640_info); +} + +static const struct i2c_device_id tda38640_id[] = { + {"tda38640", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, tda38640_id); + +static const struct of_device_id __maybe_unused tda38640_of_match[] = { + { .compatible = "infineon,tda38640"}, + { }, +}; +MODULE_DEVICE_TABLE(of, tda38640_of_match); + +/* This is the driver that will be inserted */ +static struct i2c_driver tda38640_driver = { + .driver = { + .name = "tda38640", + .of_match_table = of_match_ptr(tda38640_of_match), + }, + .probe_new = tda38640_probe, + .id_table = tda38640_id, +}; + +module_i2c_driver(tda38640_driver); + +MODULE_AUTHOR("Patrick Rudolph <patrick.rudolph@9elements.com>"); +MODULE_DESCRIPTION("PMBus driver for Infineon TDA38640"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(PMBUS); |