diff options
Diffstat (limited to 'drivers/hwmon/pmbus')
34 files changed, 526 insertions, 42 deletions
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig index a25faf69fce3..03606d4298a4 100644 --- a/drivers/hwmon/pmbus/Kconfig +++ b/drivers/hwmon/pmbus/Kconfig @@ -220,6 +220,15 @@ config SENSORS_MP2975 This driver can also be built as a module. If so, the module will be called mp2975. +config SENSORS_PM6764TR + tristate "ST PM6764TR" + help + If you say yes here you get hardware monitoring support for ST + PM6764TR. + + This driver can also be built as a module. If so, the module will + be called pm6764tr. + config SENSORS_PXE1610 tristate "Infineon PXE1610" help @@ -229,6 +238,15 @@ config SENSORS_PXE1610 This driver can also be built as a module. If so, the module will be called pxe1610. +config SENSORS_Q54SJ108A2 + tristate "Delta Power Supplies Q54SJ108A2" + help + If you say yes here you get hardware monitoring support for Delta + Q54SJ108A2 series Power Supplies. + + This driver can also be built as a module. If so, the module will + be called q54sj108a2. + config SENSORS_TPS40422 tristate "TI TPS40422" help diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile index 4c97ad0bd791..6a4ba0fdc1db 100644 --- a/drivers/hwmon/pmbus/Makefile +++ b/drivers/hwmon/pmbus/Makefile @@ -25,7 +25,9 @@ obj-$(CONFIG_SENSORS_MAX31785) += max31785.o obj-$(CONFIG_SENSORS_MAX34440) += max34440.o obj-$(CONFIG_SENSORS_MAX8688) += max8688.o obj-$(CONFIG_SENSORS_MP2975) += mp2975.o +obj-$(CONFIG_SENSORS_PM6764TR) += pm6764tr.o obj-$(CONFIG_SENSORS_PXE1610) += pxe1610.o +obj-$(CONFIG_SENSORS_Q54SJ108A2) += q54sj108a2.o obj-$(CONFIG_SENSORS_TPS40422) += tps40422.o obj-$(CONFIG_SENSORS_TPS53679) += tps53679.o obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o diff --git a/drivers/hwmon/pmbus/adm1266.c b/drivers/hwmon/pmbus/adm1266.c index c7b373ba92f2..4d2e4ddcfbfd 100644 --- a/drivers/hwmon/pmbus/adm1266.c +++ b/drivers/hwmon/pmbus/adm1266.c @@ -502,7 +502,6 @@ static struct i2c_driver adm1266_driver = { .of_match_table = adm1266_of_match, }, .probe_new = adm1266_probe, - .remove = pmbus_do_remove, .id_table = adm1266_id, }; diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c index e7997f37b266..38a6515b0763 100644 --- a/drivers/hwmon/pmbus/adm1275.c +++ b/drivers/hwmon/pmbus/adm1275.c @@ -797,7 +797,6 @@ static struct i2c_driver adm1275_driver = { .name = "adm1275", }, .probe_new = adm1275_probe, - .remove = pmbus_do_remove, .id_table = adm1275_id, }; diff --git a/drivers/hwmon/pmbus/bel-pfe.c b/drivers/hwmon/pmbus/bel-pfe.c index 2c5b853d6c7f..aed7542d7ce5 100644 --- a/drivers/hwmon/pmbus/bel-pfe.c +++ b/drivers/hwmon/pmbus/bel-pfe.c @@ -121,7 +121,6 @@ static struct i2c_driver pfe_pmbus_driver = { .name = "bel-pfe", }, .probe_new = pfe_pmbus_probe, - .remove = pmbus_do_remove, .id_table = pfe_device_id, }; diff --git a/drivers/hwmon/pmbus/ibm-cffps.c b/drivers/hwmon/pmbus/ibm-cffps.c index 2fb7540ee952..d6bbbb223871 100644 --- a/drivers/hwmon/pmbus/ibm-cffps.c +++ b/drivers/hwmon/pmbus/ibm-cffps.c @@ -617,7 +617,6 @@ static struct i2c_driver ibm_cffps_driver = { .of_match_table = ibm_cffps_of_match, }, .probe_new = ibm_cffps_probe, - .remove = pmbus_do_remove, .id_table = ibm_cffps_id, }; diff --git a/drivers/hwmon/pmbus/inspur-ipsps.c b/drivers/hwmon/pmbus/inspur-ipsps.c index be493182174d..88c5865c4d6f 100644 --- a/drivers/hwmon/pmbus/inspur-ipsps.c +++ b/drivers/hwmon/pmbus/inspur-ipsps.c @@ -216,7 +216,6 @@ static struct i2c_driver ipsps_driver = { .of_match_table = of_match_ptr(ipsps_of_match), }, .probe_new = ipsps_probe, - .remove = pmbus_do_remove, .id_table = ipsps_id, }; diff --git a/drivers/hwmon/pmbus/ir35221.c b/drivers/hwmon/pmbus/ir35221.c index 5fadb1def49f..3aebeb1443fd 100644 --- a/drivers/hwmon/pmbus/ir35221.c +++ b/drivers/hwmon/pmbus/ir35221.c @@ -137,7 +137,6 @@ static struct i2c_driver ir35221_driver = { .name = "ir35221", }, .probe_new = ir35221_probe, - .remove = pmbus_do_remove, .id_table = ir35221_id, }; diff --git a/drivers/hwmon/pmbus/ir38064.c b/drivers/hwmon/pmbus/ir38064.c index 9ac563ce7dd8..46f17c4b4873 100644 --- a/drivers/hwmon/pmbus/ir38064.c +++ b/drivers/hwmon/pmbus/ir38064.c @@ -53,7 +53,6 @@ static struct i2c_driver ir38064_driver = { .name = "ir38064", }, .probe_new = ir38064_probe, - .remove = pmbus_do_remove, .id_table = ir38064_id, }; diff --git a/drivers/hwmon/pmbus/irps5401.c b/drivers/hwmon/pmbus/irps5401.c index 44aeafcbd56c..93ef6d64a33a 100644 --- a/drivers/hwmon/pmbus/irps5401.c +++ b/drivers/hwmon/pmbus/irps5401.c @@ -55,7 +55,6 @@ static struct i2c_driver irps5401_driver = { .name = "irps5401", }, .probe_new = irps5401_probe, - .remove = pmbus_do_remove, .id_table = irps5401_id, }; diff --git a/drivers/hwmon/pmbus/isl68137.c b/drivers/hwmon/pmbus/isl68137.c index 7cad76e07f70..2bee930d3900 100644 --- a/drivers/hwmon/pmbus/isl68137.c +++ b/drivers/hwmon/pmbus/isl68137.c @@ -324,7 +324,6 @@ static struct i2c_driver isl68137_driver = { .name = "isl68137", }, .probe_new = isl68137_probe, - .remove = pmbus_do_remove, .id_table = raa_dmpvr_id, }; diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c index 429172a42902..c75a6bf39641 100644 --- a/drivers/hwmon/pmbus/lm25066.c +++ b/drivers/hwmon/pmbus/lm25066.c @@ -508,7 +508,6 @@ static struct i2c_driver lm25066_driver = { .name = "lm25066", }, .probe_new = lm25066_probe, - .remove = pmbus_do_remove, .id_table = lm25066_id, }; diff --git a/drivers/hwmon/pmbus/ltc2978.c b/drivers/hwmon/pmbus/ltc2978.c index 9a024cf70145..7e53fa95b92d 100644 --- a/drivers/hwmon/pmbus/ltc2978.c +++ b/drivers/hwmon/pmbus/ltc2978.c @@ -875,7 +875,6 @@ static struct i2c_driver ltc2978_driver = { .of_match_table = of_match_ptr(ltc2978_of_match), }, .probe_new = ltc2978_probe, - .remove = pmbus_do_remove, .id_table = ltc2978_id, }; diff --git a/drivers/hwmon/pmbus/ltc3815.c b/drivers/hwmon/pmbus/ltc3815.c index 8328fb367ad6..e45e14d26c9a 100644 --- a/drivers/hwmon/pmbus/ltc3815.c +++ b/drivers/hwmon/pmbus/ltc3815.c @@ -200,7 +200,6 @@ static struct i2c_driver ltc3815_driver = { .name = "ltc3815", }, .probe_new = ltc3815_probe, - .remove = pmbus_do_remove, .id_table = ltc3815_id, }; diff --git a/drivers/hwmon/pmbus/max16064.c b/drivers/hwmon/pmbus/max16064.c index 26e7f5ef9d7f..d79add99083e 100644 --- a/drivers/hwmon/pmbus/max16064.c +++ b/drivers/hwmon/pmbus/max16064.c @@ -103,7 +103,6 @@ static struct i2c_driver max16064_driver = { .name = "max16064", }, .probe_new = max16064_probe, - .remove = pmbus_do_remove, .id_table = max16064_id, }; diff --git a/drivers/hwmon/pmbus/max16601.c b/drivers/hwmon/pmbus/max16601.c index 71bb74e27a5c..a960b86e72d2 100644 --- a/drivers/hwmon/pmbus/max16601.c +++ b/drivers/hwmon/pmbus/max16601.c @@ -302,7 +302,6 @@ static struct i2c_driver max16601_driver = { .name = "max16601", }, .probe_new = max16601_probe, - .remove = pmbus_do_remove, .id_table = max16601_id, }; diff --git a/drivers/hwmon/pmbus/max20730.c b/drivers/hwmon/pmbus/max20730.c index be83b98411c7..9dd3dd79bc18 100644 --- a/drivers/hwmon/pmbus/max20730.c +++ b/drivers/hwmon/pmbus/max20730.c @@ -328,8 +328,6 @@ static int max20730_init_debugfs(struct i2c_client *client, return -ENOENT; max20730_dir = debugfs_create_dir(client->name, debugfs); - if (!max20730_dir) - return -ENOENT; for (i = 0; i < MAX20730_DEBUGFS_NUM_ENTRIES; ++i) psu->debugfs_entries[i] = i; @@ -779,7 +777,6 @@ static struct i2c_driver max20730_driver = { .of_match_table = max20730_of_match, }, .probe_new = max20730_probe, - .remove = pmbus_do_remove, .id_table = max20730_id, }; diff --git a/drivers/hwmon/pmbus/max20751.c b/drivers/hwmon/pmbus/max20751.c index 921e92d82aec..9d42f82fdd99 100644 --- a/drivers/hwmon/pmbus/max20751.c +++ b/drivers/hwmon/pmbus/max20751.c @@ -43,7 +43,6 @@ static struct i2c_driver max20751_driver = { .name = "max20751", }, .probe_new = max20751_probe, - .remove = pmbus_do_remove, .id_table = max20751_id, }; diff --git a/drivers/hwmon/pmbus/max31785.c b/drivers/hwmon/pmbus/max31785.c index 839b957bc03e..e5a9f4019cd5 100644 --- a/drivers/hwmon/pmbus/max31785.c +++ b/drivers/hwmon/pmbus/max31785.c @@ -390,7 +390,6 @@ static struct i2c_driver max31785_driver = { .of_match_table = max31785_of_match, }, .probe_new = max31785_probe, - .remove = pmbus_do_remove, .id_table = max31785_id, }; diff --git a/drivers/hwmon/pmbus/max34440.c b/drivers/hwmon/pmbus/max34440.c index f4cb196aaaf3..dad66b3c0116 100644 --- a/drivers/hwmon/pmbus/max34440.c +++ b/drivers/hwmon/pmbus/max34440.c @@ -521,7 +521,6 @@ static struct i2c_driver max34440_driver = { .name = "max34440", }, .probe_new = max34440_probe, - .remove = pmbus_do_remove, .id_table = max34440_id, }; diff --git a/drivers/hwmon/pmbus/max8688.c b/drivers/hwmon/pmbus/max8688.c index 4b2239a6afd3..329dc851fc59 100644 --- a/drivers/hwmon/pmbus/max8688.c +++ b/drivers/hwmon/pmbus/max8688.c @@ -183,7 +183,6 @@ static struct i2c_driver max8688_driver = { .name = "max8688", }, .probe_new = max8688_probe, - .remove = pmbus_do_remove, .id_table = max8688_id, }; diff --git a/drivers/hwmon/pmbus/mp2975.c b/drivers/hwmon/pmbus/mp2975.c index 1c3e2a9453b1..60fbdb371332 100644 --- a/drivers/hwmon/pmbus/mp2975.c +++ b/drivers/hwmon/pmbus/mp2975.c @@ -758,7 +758,6 @@ static struct i2c_driver mp2975_driver = { .of_match_table = of_match_ptr(mp2975_of_match), }, .probe_new = mp2975_probe, - .remove = pmbus_do_remove, .id_table = mp2975_id, }; diff --git a/drivers/hwmon/pmbus/pm6764tr.c b/drivers/hwmon/pmbus/pm6764tr.c new file mode 100644 index 000000000000..d97cb6d6c87f --- /dev/null +++ b/drivers/hwmon/pmbus/pm6764tr.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Hardware monitoring driver for STMicroelectronics digital controller PM6764TR + */ + +#include <linux/err.h> +#include <linux/i2c.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pmbus.h> +#include "pmbus.h" + +#define PM6764TR_PMBUS_READ_VOUT 0xD4 + +static int pm6764tr_read_word_data(struct i2c_client *client, int page, int phase, int reg) +{ + int ret; + + switch (reg) { + case PMBUS_VIRT_READ_VMON: + ret = pmbus_read_word_data(client, page, phase, PM6764TR_PMBUS_READ_VOUT); + break; + default: + ret = -ENODATA; + break; + } + return ret; +} + +static struct pmbus_driver_info pm6764tr_info = { + .pages = 1, + .format[PSC_VOLTAGE_IN] = linear, + .format[PSC_VOLTAGE_OUT] = vid, + .format[PSC_TEMPERATURE] = linear, + .format[PSC_CURRENT_OUT] = linear, + .format[PSC_POWER] = linear, + .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN | PMBUS_HAVE_PIN | + PMBUS_HAVE_IOUT | PMBUS_HAVE_POUT | PMBUS_HAVE_VMON | + PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_STATUS_VOUT | + PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, + .read_word_data = pm6764tr_read_word_data, +}; + +static int pm6764tr_probe(struct i2c_client *client) +{ + return pmbus_do_probe(client, &pm6764tr_info); +} + +static const struct i2c_device_id pm6764tr_id[] = { + {"pm6764tr", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, pm6764tr_id); + +static const struct of_device_id __maybe_unused pm6764tr_of_match[] = { + {.compatible = "st,pm6764tr"}, + {} +}; + +/* This is the driver that will be inserted */ +static struct i2c_driver pm6764tr_driver = { + .driver = { + .name = "pm6764tr", + .of_match_table = of_match_ptr(pm6764tr_of_match), + }, + .probe_new = pm6764tr_probe, + .id_table = pm6764tr_id, +}; + +module_i2c_driver(pm6764tr_driver); + +MODULE_AUTHOR("Charles Hsu"); +MODULE_DESCRIPTION("PMBus driver for ST PM6764TR"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/pmbus/pmbus.c b/drivers/hwmon/pmbus/pmbus.c index 20f1af9165c2..a1b4260e75b2 100644 --- a/drivers/hwmon/pmbus/pmbus.c +++ b/drivers/hwmon/pmbus/pmbus.c @@ -238,7 +238,6 @@ static struct i2c_driver pmbus_driver = { .name = "pmbus", }, .probe_new = pmbus_probe, - .remove = pmbus_do_remove, .id_table = pmbus_id, }; diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h index 88a5df2633fb..4c30ec89f5bf 100644 --- a/drivers/hwmon/pmbus/pmbus.h +++ b/drivers/hwmon/pmbus/pmbus.h @@ -490,7 +490,6 @@ void pmbus_clear_faults(struct i2c_client *client); bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg); bool pmbus_check_word_register(struct i2c_client *client, int page, int reg); int pmbus_do_probe(struct i2c_client *client, struct pmbus_driver_info *info); -int pmbus_do_remove(struct i2c_client *client); const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client *client); int pmbus_get_fan_rate_device(struct i2c_client *client, int page, int id, diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index b0e2820a2d57..192442b3b7a2 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -2395,6 +2395,13 @@ static int pmbus_debugfs_set_pec(void *data, u64 val) DEFINE_DEBUGFS_ATTRIBUTE(pmbus_debugfs_ops_pec, pmbus_debugfs_get_pec, pmbus_debugfs_set_pec, "%llu\n"); +static void pmbus_remove_debugfs(void *data) +{ + struct dentry *entry = data; + + debugfs_remove_recursive(entry); +} + static int pmbus_init_debugfs(struct i2c_client *client, struct pmbus_data *data) { @@ -2530,7 +2537,8 @@ static int pmbus_init_debugfs(struct i2c_client *client, } } - return 0; + return devm_add_action_or_reset(data->dev, + pmbus_remove_debugfs, data->debugfs); } #else static int pmbus_init_debugfs(struct i2c_client *client, @@ -2617,16 +2625,6 @@ int pmbus_do_probe(struct i2c_client *client, struct pmbus_driver_info *info) } EXPORT_SYMBOL_GPL(pmbus_do_probe); -int pmbus_do_remove(struct i2c_client *client) -{ - struct pmbus_data *data = i2c_get_clientdata(client); - - debugfs_remove_recursive(data->debugfs); - - return 0; -} -EXPORT_SYMBOL_GPL(pmbus_do_remove); - struct dentry *pmbus_get_debugfs_dir(struct i2c_client *client) { struct pmbus_data *data = i2c_get_clientdata(client); diff --git a/drivers/hwmon/pmbus/pxe1610.c b/drivers/hwmon/pmbus/pxe1610.c index fa5c5dd29b7a..da27ce34ee3f 100644 --- a/drivers/hwmon/pmbus/pxe1610.c +++ b/drivers/hwmon/pmbus/pxe1610.c @@ -131,7 +131,6 @@ static struct i2c_driver pxe1610_driver = { .name = "pxe1610", }, .probe_new = pxe1610_probe, - .remove = pmbus_do_remove, .id_table = pxe1610_id, }; diff --git a/drivers/hwmon/pmbus/q54sj108a2.c b/drivers/hwmon/pmbus/q54sj108a2.c new file mode 100644 index 000000000000..aec512766c31 --- /dev/null +++ b/drivers/hwmon/pmbus/q54sj108a2.c @@ -0,0 +1,422 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Driver for Delta modules, Q54SJ108A2 series 1/4 Brick DC/DC + * Regulated Power Module + * + * Copyright 2020 Delta LLC. + */ + +#include <linux/debugfs.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include "pmbus.h" + +#define STORE_DEFAULT_ALL 0x11 +#define ERASE_BLACKBOX_DATA 0xD1 +#define READ_HISTORY_EVENT_NUMBER 0xD2 +#define READ_HISTORY_EVENTS 0xE0 +#define SET_HISTORY_EVENT_OFFSET 0xE1 +#define PMBUS_FLASH_KEY_WRITE 0xEC + +enum chips { + q54sj108a2 +}; + +enum { + Q54SJ108A2_DEBUGFS_OPERATION = 0, + Q54SJ108A2_DEBUGFS_CLEARFAULT, + Q54SJ108A2_DEBUGFS_WRITEPROTECT, + Q54SJ108A2_DEBUGFS_STOREDEFAULT, + Q54SJ108A2_DEBUGFS_VOOV_RESPONSE, + Q54SJ108A2_DEBUGFS_IOOC_RESPONSE, + Q54SJ108A2_DEBUGFS_PMBUS_VERSION, + Q54SJ108A2_DEBUGFS_MFR_ID, + Q54SJ108A2_DEBUGFS_MFR_MODEL, + Q54SJ108A2_DEBUGFS_MFR_REVISION, + Q54SJ108A2_DEBUGFS_MFR_LOCATION, + Q54SJ108A2_DEBUGFS_BLACKBOX_ERASE, + Q54SJ108A2_DEBUGFS_BLACKBOX_READ_OFFSET, + Q54SJ108A2_DEBUGFS_BLACKBOX_SET_OFFSET, + Q54SJ108A2_DEBUGFS_BLACKBOX_READ, + Q54SJ108A2_DEBUGFS_FLASH_KEY, + Q54SJ108A2_DEBUGFS_NUM_ENTRIES +}; + +struct q54sj108a2_data { + enum chips chip; + struct i2c_client *client; + + int debugfs_entries[Q54SJ108A2_DEBUGFS_NUM_ENTRIES]; +}; + +#define to_psu(x, y) container_of((x), struct q54sj108a2_data, debugfs_entries[(y)]) + +static struct pmbus_driver_info q54sj108a2_info[] = { + [q54sj108a2] = { + .pages = 1, + + /* Source : Delta Q54SJ108A2 */ + .format[PSC_TEMPERATURE] = linear, + .format[PSC_VOLTAGE_IN] = linear, + .format[PSC_CURRENT_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, + }, +}; + +static ssize_t q54sj108a2_debugfs_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + int rc; + int *idxp = file->private_data; + int idx = *idxp; + struct q54sj108a2_data *psu = to_psu(idxp, idx); + char data[I2C_SMBUS_BLOCK_MAX + 2] = { 0 }; + char data_char[I2C_SMBUS_BLOCK_MAX + 2] = { 0 }; + char *res; + + switch (idx) { + case Q54SJ108A2_DEBUGFS_OPERATION: + rc = i2c_smbus_read_byte_data(psu->client, PMBUS_OPERATION); + if (rc < 0) + return rc; + + rc = snprintf(data, 3, "%02x", rc); + break; + case Q54SJ108A2_DEBUGFS_WRITEPROTECT: + rc = i2c_smbus_read_byte_data(psu->client, PMBUS_WRITE_PROTECT); + if (rc < 0) + return rc; + + rc = snprintf(data, 3, "%02x", rc); + break; + case Q54SJ108A2_DEBUGFS_VOOV_RESPONSE: + rc = i2c_smbus_read_byte_data(psu->client, PMBUS_VOUT_OV_FAULT_RESPONSE); + if (rc < 0) + return rc; + + rc = snprintf(data, 3, "%02x", rc); + break; + case Q54SJ108A2_DEBUGFS_IOOC_RESPONSE: + rc = i2c_smbus_read_byte_data(psu->client, PMBUS_IOUT_OC_FAULT_RESPONSE); + if (rc < 0) + return rc; + + rc = snprintf(data, 3, "%02x", rc); + break; + case Q54SJ108A2_DEBUGFS_PMBUS_VERSION: + rc = i2c_smbus_read_byte_data(psu->client, PMBUS_REVISION); + if (rc < 0) + return rc; + + rc = snprintf(data, 3, "%02x", rc); + break; + case Q54SJ108A2_DEBUGFS_MFR_ID: + rc = i2c_smbus_read_block_data(psu->client, PMBUS_MFR_ID, data); + if (rc < 0) + return rc; + break; + case Q54SJ108A2_DEBUGFS_MFR_MODEL: + rc = i2c_smbus_read_block_data(psu->client, PMBUS_MFR_MODEL, data); + if (rc < 0) + return rc; + break; + case Q54SJ108A2_DEBUGFS_MFR_REVISION: + rc = i2c_smbus_read_block_data(psu->client, PMBUS_MFR_REVISION, data); + if (rc < 0) + return rc; + break; + case Q54SJ108A2_DEBUGFS_MFR_LOCATION: + rc = i2c_smbus_read_block_data(psu->client, PMBUS_MFR_LOCATION, data); + if (rc < 0) + return rc; + break; + case Q54SJ108A2_DEBUGFS_BLACKBOX_READ_OFFSET: + rc = i2c_smbus_read_byte_data(psu->client, READ_HISTORY_EVENT_NUMBER); + if (rc < 0) + return rc; + + rc = snprintf(data, 3, "%02x", rc); + break; + case Q54SJ108A2_DEBUGFS_BLACKBOX_READ: + rc = i2c_smbus_read_block_data(psu->client, READ_HISTORY_EVENTS, data); + if (rc < 0) + return rc; + + res = bin2hex(data, data_char, 32); + rc = res - data; + + break; + case Q54SJ108A2_DEBUGFS_FLASH_KEY: + rc = i2c_smbus_read_block_data(psu->client, PMBUS_FLASH_KEY_WRITE, data); + if (rc < 0) + return rc; + + res = bin2hex(data, data_char, 4); + rc = res - data; + + break; + default: + return -EINVAL; + } + + data[rc] = '\n'; + rc += 2; + + return simple_read_from_buffer(buf, count, ppos, data, rc); +} + +static ssize_t q54sj108a2_debugfs_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + u8 flash_key[4]; + u8 dst_data; + ssize_t rc; + int *idxp = file->private_data; + int idx = *idxp; + struct q54sj108a2_data *psu = to_psu(idxp, idx); + + rc = i2c_smbus_write_byte_data(psu->client, PMBUS_WRITE_PROTECT, 0); + if (rc) + return rc; + + switch (idx) { + case Q54SJ108A2_DEBUGFS_OPERATION: + rc = kstrtou8_from_user(buf, count, 0, &dst_data); + if (rc < 0) + return rc; + + rc = i2c_smbus_write_byte_data(psu->client, PMBUS_OPERATION, dst_data); + if (rc < 0) + return rc; + + break; + case Q54SJ108A2_DEBUGFS_CLEARFAULT: + rc = i2c_smbus_write_byte(psu->client, PMBUS_CLEAR_FAULTS); + if (rc < 0) + return rc; + + break; + case Q54SJ108A2_DEBUGFS_STOREDEFAULT: + flash_key[0] = 0x7E; + flash_key[1] = 0x15; + flash_key[2] = 0xDC; + flash_key[3] = 0x42; + rc = i2c_smbus_write_block_data(psu->client, PMBUS_FLASH_KEY_WRITE, 4, flash_key); + if (rc < 0) + return rc; + + rc = i2c_smbus_write_byte(psu->client, STORE_DEFAULT_ALL); + if (rc < 0) + return rc; + + break; + case Q54SJ108A2_DEBUGFS_VOOV_RESPONSE: + rc = kstrtou8_from_user(buf, count, 0, &dst_data); + if (rc < 0) + return rc; + + rc = i2c_smbus_write_byte_data(psu->client, PMBUS_VOUT_OV_FAULT_RESPONSE, dst_data); + if (rc < 0) + return rc; + + break; + case Q54SJ108A2_DEBUGFS_IOOC_RESPONSE: + rc = kstrtou8_from_user(buf, count, 0, &dst_data); + if (rc < 0) + return rc; + + rc = i2c_smbus_write_byte_data(psu->client, PMBUS_IOUT_OC_FAULT_RESPONSE, dst_data); + if (rc < 0) + return rc; + + break; + case Q54SJ108A2_DEBUGFS_BLACKBOX_ERASE: + rc = i2c_smbus_write_byte(psu->client, ERASE_BLACKBOX_DATA); + if (rc < 0) + return rc; + + break; + case Q54SJ108A2_DEBUGFS_BLACKBOX_SET_OFFSET: + rc = kstrtou8_from_user(buf, count, 0, &dst_data); + if (rc < 0) + return rc; + + rc = i2c_smbus_write_byte_data(psu->client, SET_HISTORY_EVENT_OFFSET, dst_data); + if (rc < 0) + return rc; + + break; + default: + return -EINVAL; + } + + return count; +} + +static const struct file_operations q54sj108a2_fops = { + .llseek = noop_llseek, + .read = q54sj108a2_debugfs_read, + .write = q54sj108a2_debugfs_write, + .open = simple_open, +}; + +static const struct i2c_device_id q54sj108a2_id[] = { + { "q54sj108a2", q54sj108a2 }, + { }, +}; + +MODULE_DEVICE_TABLE(i2c, q54sj108a2_id); + +static int q54sj108a2_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + u8 buf[I2C_SMBUS_BLOCK_MAX + 1]; + enum chips chip_id; + int ret, i; + struct dentry *debugfs; + struct dentry *q54sj108a2_dir; + struct q54sj108a2_data *psu; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA)) + return -ENODEV; + + if (client->dev.of_node) + chip_id = (enum chips)(unsigned long)of_device_get_match_data(dev); + else + chip_id = i2c_match_id(q54sj108a2_id, client)->driver_data; + + ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, buf); + if (ret < 0) { + dev_err(&client->dev, "Failed to read Manufacturer ID\n"); + return ret; + } + if (ret != 5 || strncmp(buf, "DELTA", 5)) { + buf[ret] = '\0'; + dev_err(dev, "Unsupported Manufacturer ID '%s'\n", buf); + return -ENODEV; + } + + /* + * The chips support reading PMBUS_MFR_MODEL. + */ + ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, buf); + if (ret < 0) { + dev_err(dev, "Failed to read Manufacturer Model\n"); + return ret; + } + if (ret != 14 || strncmp(buf, "Q54SJ108A2", 10)) { + buf[ret] = '\0'; + dev_err(dev, "Unsupported Manufacturer Model '%s'\n", buf); + return -ENODEV; + } + + ret = i2c_smbus_read_block_data(client, PMBUS_MFR_REVISION, buf); + if (ret < 0) { + dev_err(dev, "Failed to read Manufacturer Revision\n"); + return ret; + } + if (ret != 4 || buf[0] != 'S') { + buf[ret] = '\0'; + dev_err(dev, "Unsupported Manufacturer Revision '%s'\n", buf); + return -ENODEV; + } + + ret = pmbus_do_probe(client, &q54sj108a2_info[chip_id]); + if (ret) + return ret; + + psu = devm_kzalloc(&client->dev, sizeof(*psu), GFP_KERNEL); + if (!psu) + return 0; + + psu->client = client; + + debugfs = pmbus_get_debugfs_dir(client); + + q54sj108a2_dir = debugfs_create_dir(client->name, debugfs); + + for (i = 0; i < Q54SJ108A2_DEBUGFS_NUM_ENTRIES; ++i) + psu->debugfs_entries[i] = i; + + debugfs_create_file("operation", 0644, q54sj108a2_dir, + &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_OPERATION], + &q54sj108a2_fops); + debugfs_create_file("clear_fault", 0200, q54sj108a2_dir, + &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_CLEARFAULT], + &q54sj108a2_fops); + debugfs_create_file("write_protect", 0444, q54sj108a2_dir, + &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_WRITEPROTECT], + &q54sj108a2_fops); + debugfs_create_file("store_default", 0200, q54sj108a2_dir, + &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_STOREDEFAULT], + &q54sj108a2_fops); + debugfs_create_file("vo_ov_response", 0644, q54sj108a2_dir, + &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_VOOV_RESPONSE], + &q54sj108a2_fops); + debugfs_create_file("io_oc_response", 0644, q54sj108a2_dir, + &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_IOOC_RESPONSE], + &q54sj108a2_fops); + debugfs_create_file("pmbus_revision", 0444, q54sj108a2_dir, + &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_PMBUS_VERSION], + &q54sj108a2_fops); + debugfs_create_file("mfr_id", 0444, q54sj108a2_dir, + &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_MFR_ID], + &q54sj108a2_fops); + debugfs_create_file("mfr_model", 0444, q54sj108a2_dir, + &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_MFR_MODEL], + &q54sj108a2_fops); + debugfs_create_file("mfr_revision", 0444, q54sj108a2_dir, + &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_MFR_REVISION], + &q54sj108a2_fops); + debugfs_create_file("mfr_location", 0444, q54sj108a2_dir, + &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_MFR_LOCATION], + &q54sj108a2_fops); + debugfs_create_file("blackbox_erase", 0200, q54sj108a2_dir, + &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_BLACKBOX_ERASE], + &q54sj108a2_fops); + debugfs_create_file("blackbox_read_offset", 0444, q54sj108a2_dir, + &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_BLACKBOX_READ_OFFSET], + &q54sj108a2_fops); + debugfs_create_file("blackbox_set_offset", 0200, q54sj108a2_dir, + &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_BLACKBOX_SET_OFFSET], + &q54sj108a2_fops); + debugfs_create_file("blackbox_read", 0444, q54sj108a2_dir, + &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_BLACKBOX_READ], + &q54sj108a2_fops); + debugfs_create_file("flash_key", 0444, q54sj108a2_dir, + &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_FLASH_KEY], + &q54sj108a2_fops); + + return 0; +} + +static const struct of_device_id q54sj108a2_of_match[] = { + { .compatible = "delta,q54sj108a2", .data = (void *)q54sj108a2 }, + { }, +}; + +MODULE_DEVICE_TABLE(of, q54sj108a2_of_match); + +static struct i2c_driver q54sj108a2_driver = { + .driver = { + .name = "q54sj108a2", + .of_match_table = q54sj108a2_of_match, + }, + .probe_new = q54sj108a2_probe, + .id_table = q54sj108a2_id, +}; + +module_i2c_driver(q54sj108a2_driver); + +MODULE_AUTHOR("Xiao.Ma <xiao.mx.ma@deltaww.com>"); +MODULE_DESCRIPTION("PMBus driver for Delta Q54SJ108A2 series modules"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/pmbus/tps40422.c b/drivers/hwmon/pmbus/tps40422.c index edbdfa809d51..f7f00ab6f46c 100644 --- a/drivers/hwmon/pmbus/tps40422.c +++ b/drivers/hwmon/pmbus/tps40422.c @@ -43,7 +43,6 @@ static struct i2c_driver tps40422_driver = { .name = "tps40422", }, .probe_new = tps40422_probe, - .remove = pmbus_do_remove, .id_table = tps40422_id, }; diff --git a/drivers/hwmon/pmbus/tps53679.c b/drivers/hwmon/pmbus/tps53679.c index db2bdf2a1f02..ba838fa311c3 100644 --- a/drivers/hwmon/pmbus/tps53679.c +++ b/drivers/hwmon/pmbus/tps53679.c @@ -251,7 +251,6 @@ static struct i2c_driver tps53679_driver = { .of_match_table = of_match_ptr(tps53679_of_match), }, .probe_new = tps53679_probe, - .remove = pmbus_do_remove, .id_table = tps53679_id, }; diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c index f8017993e2b4..a15e6fe3e425 100644 --- a/drivers/hwmon/pmbus/ucd9000.c +++ b/drivers/hwmon/pmbus/ucd9000.c @@ -621,7 +621,6 @@ static struct i2c_driver ucd9000_driver = { .of_match_table = of_match_ptr(ucd9000_of_match), }, .probe_new = ucd9000_probe, - .remove = pmbus_do_remove, .id_table = ucd9000_id, }; diff --git a/drivers/hwmon/pmbus/ucd9200.c b/drivers/hwmon/pmbus/ucd9200.c index e111e25e1619..47cc7ca9d329 100644 --- a/drivers/hwmon/pmbus/ucd9200.c +++ b/drivers/hwmon/pmbus/ucd9200.c @@ -201,7 +201,6 @@ static struct i2c_driver ucd9200_driver = { .of_match_table = of_match_ptr(ucd9200_of_match), }, .probe_new = ucd9200_probe, - .remove = pmbus_do_remove, .id_table = ucd9200_id, }; diff --git a/drivers/hwmon/pmbus/xdpe12284.c b/drivers/hwmon/pmbus/xdpe12284.c index c95ac934fde4..f8bc0f41cd5f 100644 --- a/drivers/hwmon/pmbus/xdpe12284.c +++ b/drivers/hwmon/pmbus/xdpe12284.c @@ -160,7 +160,6 @@ static struct i2c_driver xdpe122_driver = { .of_match_table = of_match_ptr(xdpe122_of_match), }, .probe_new = xdpe122_probe, - .remove = pmbus_do_remove, .id_table = xdpe122_id, }; diff --git a/drivers/hwmon/pmbus/zl6100.c b/drivers/hwmon/pmbus/zl6100.c index e8bda340482b..69120ca7aaa8 100644 --- a/drivers/hwmon/pmbus/zl6100.c +++ b/drivers/hwmon/pmbus/zl6100.c @@ -396,7 +396,6 @@ static struct i2c_driver zl6100_driver = { .name = "zl6100", }, .probe_new = zl6100_probe, - .remove = pmbus_do_remove, .id_table = zl6100_id, }; |