Add a module parameter to force the write protection mode of pmbus chips. 2 protections modes are provided to start with: * 0: Remove the write protection if possible * 1: Enable full write protection if possible Of course, if the parameter is not provided, the default write protection status of the pmbus chips is left untouched. Suggested-by: Guenter Roeck <linux@xxxxxxxxxxxx> Signed-off-by: Jerome Brunet <jbrunet@xxxxxxxxxxxx> --- Documentation/admin-guide/kernel-parameters.txt | 4 ++ drivers/hwmon/pmbus/pmbus_core.c | 74 ++++++++++++++++++------- 2 files changed, 59 insertions(+), 19 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 1518343bbe2237f1d577df5656339d6224b769be..aa79242fe0a9238f618182289f18563ed63cba1c 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -4733,6 +4733,10 @@ Format: { parport<nr> | timid | 0 } See also Documentation/admin-guide/parport.rst. + pmbus.wp= [HW] PMBus Chips write protection forced mode + Format: { 0 | 1 } + See drivers/hwmon/pmbus/pmbus_core.c + pmtmr= [X86] Manual setup of pmtmr I/O Port. Override pmtimer IOPort with a hex value. e.g. pmtmr=0x508 diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index 7bdd8f2ffcabc51500437182f411e9826cd7a55d..ce697ca03de01c0e5a352f8f6b72671137721868 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -31,6 +31,20 @@ #define PMBUS_ATTR_ALLOC_SIZE 32 #define PMBUS_NAME_SIZE 24 +/* + * PMBus write protect forced mode: + * PMBus may come up with a variety of write protection configuration. + * 'pmbus_wp' may be used if a particular write protection is necessary. + * The ability to actually alter the protection may also depend on the chip + * so the actual runtime write protection configuration may differ from + * the requested one. pmbus_core currently support the following value: + * - 0: write protection removed + * - 1: write protection fully enabled, including OPERATION and VOUT_COMMAND + * registers. Chips essentially become read-only with this. + */ +static int wp = -1; +module_param(wp, int, 0444); + struct pmbus_sensor { struct pmbus_sensor *next; char name[PMBUS_NAME_SIZE]; /* sysfs sensor name */ @@ -2665,6 +2679,45 @@ static void pmbus_remove_pec(void *dev) device_remove_file(dev, &dev_attr_pec); } +static void pmbus_init_wp(struct i2c_client *client, struct pmbus_data *data) +{ + int ret; + + switch (wp) { + case 0: + _pmbus_write_byte_data(client, 0xff, + PMBUS_WRITE_PROTECT, 0); + break; + + case 1: + _pmbus_write_byte_data(client, 0xff, + PMBUS_WRITE_PROTECT, PB_WP_ALL); + break; + + default: + /* Ignore the other values */ + break; + } + + ret = _pmbus_read_byte_data(client, 0xff, PMBUS_WRITE_PROTECT); + + switch (ret) { + case PB_WP_ALL: + data->flags |= PMBUS_OP_PROTECTED; + fallthrough; + case PB_WP_OP: + data->flags |= PMBUS_VOUT_PROTECTED; + fallthrough; + case PB_WP_VOUT: + data->flags |= PMBUS_WRITE_PROTECTED | PMBUS_SKIP_STATUS_CHECK; + break; + + default: + /* Ignore manufacturer specific and invalid as well as errors */ + break; + } +} + static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data, struct pmbus_driver_info *info) { @@ -2718,25 +2771,8 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data, * faults, and we should not try it. Also, in that case, writes into * limit registers need to be disabled. */ - if (!(data->flags & PMBUS_NO_WRITE_PROTECT)) { - ret = _pmbus_read_byte_data(client, 0xff, PMBUS_WRITE_PROTECT); - - switch (ret) { - case PB_WP_ALL: - data->flags |= PMBUS_OP_PROTECTED; - fallthrough; - case PB_WP_OP: - data->flags |= PMBUS_VOUT_PROTECTED; - fallthrough; - case PB_WP_VOUT: - data->flags |= PMBUS_WRITE_PROTECTED | PMBUS_SKIP_STATUS_CHECK; - break; - - default: - /* Ignore manufacturer specific and invalid as well as errors */ - break; - } - } + if (!(data->flags & PMBUS_NO_WRITE_PROTECT)) + pmbus_init_wp(client, data); ret = i2c_smbus_read_byte_data(client, PMBUS_REVISION); if (ret >= 0) -- 2.45.2