hwmon: (pmbus) Move pec attribute to I2C device
Enabling and disabling PEC for PMBus devices is currently only supported with a debugfs attribute, which requires debugfs to be enabled and is thus less than perfect. Take the lm90 driver as example and add a 'pec' attribute to the I2C device if both the I2C adapter and the PMBus device support it. Remove the now obsolete 'pec' attribute from debugfs. Cc: Andrew Jeffery <andrew@aj.id.au> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
parent
88084a3df1
commit
f30ce040a7
@ -938,3 +938,12 @@ Description:
|
|||||||
- 1: enable
|
- 1: enable
|
||||||
|
|
||||||
RW
|
RW
|
||||||
|
|
||||||
|
What: /sys/class/hwmon/hwmonX/device/pec
|
||||||
|
Description:
|
||||||
|
PEC support on I2C devices
|
||||||
|
|
||||||
|
- 0, off, n: disable
|
||||||
|
- 1, on, y: enable
|
||||||
|
|
||||||
|
RW
|
||||||
|
@ -121,6 +121,15 @@ Specifically, it provides the following information.
|
|||||||
non-standard PMBus commands to standard commands, or to augment standard
|
non-standard PMBus commands to standard commands, or to augment standard
|
||||||
command return values with device specific information.
|
command return values with device specific information.
|
||||||
|
|
||||||
|
PEC Support
|
||||||
|
===========
|
||||||
|
|
||||||
|
Many PMBus devices support SMBus PEC (Packet Error Checking). If supported
|
||||||
|
by both the I2C adapter and by the PMBus chip, it is by default enabled.
|
||||||
|
If PEC is supported, the PMBus core driver adds an attribute named 'pec' to
|
||||||
|
the I2C device. This attribute can be used to control PEC support in the
|
||||||
|
communication with the PMBus chip.
|
||||||
|
|
||||||
API functions
|
API functions
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
@ -2388,6 +2388,42 @@ static int pmbus_read_status_word(struct i2c_client *client, int page)
|
|||||||
return _pmbus_read_word_data(client, page, 0xff, PMBUS_STATUS_WORD);
|
return _pmbus_read_word_data(client, page, 0xff, PMBUS_STATUS_WORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* PEC attribute support */
|
||||||
|
|
||||||
|
static ssize_t pec_show(struct device *dev, struct device_attribute *dummy,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
|
||||||
|
return sysfs_emit(buf, "%d\n", !!(client->flags & I2C_CLIENT_PEC));
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t pec_store(struct device *dev, struct device_attribute *dummy,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
bool enable;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = kstrtobool(buf, &enable);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
client->flags |= I2C_CLIENT_PEC;
|
||||||
|
else
|
||||||
|
client->flags &= ~I2C_CLIENT_PEC;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR_RW(pec);
|
||||||
|
|
||||||
|
static void pmbus_remove_pec(void *dev)
|
||||||
|
{
|
||||||
|
device_remove_file(dev, &dev_attr_pec);
|
||||||
|
}
|
||||||
|
|
||||||
static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
|
static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
|
||||||
struct pmbus_driver_info *info)
|
struct pmbus_driver_info *info)
|
||||||
{
|
{
|
||||||
@ -2474,6 +2510,20 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (client->flags & I2C_CLIENT_PEC) {
|
||||||
|
/*
|
||||||
|
* If I2C_CLIENT_PEC is set here, both the I2C adapter and the
|
||||||
|
* chip support PEC. Add 'pec' attribute to client device to let
|
||||||
|
* the user control it.
|
||||||
|
*/
|
||||||
|
ret = device_create_file(dev, &dev_attr_pec);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
ret = devm_add_action_or_reset(dev, pmbus_remove_pec, dev);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2782,42 +2832,6 @@ static int pmbus_debugfs_get_status(void *data, u64 *val)
|
|||||||
DEFINE_DEBUGFS_ATTRIBUTE(pmbus_debugfs_ops_status, pmbus_debugfs_get_status,
|
DEFINE_DEBUGFS_ATTRIBUTE(pmbus_debugfs_ops_status, pmbus_debugfs_get_status,
|
||||||
NULL, "0x%04llx\n");
|
NULL, "0x%04llx\n");
|
||||||
|
|
||||||
static int pmbus_debugfs_get_pec(void *data, u64 *val)
|
|
||||||
{
|
|
||||||
struct i2c_client *client = data;
|
|
||||||
|
|
||||||
*val = !!(client->flags & I2C_CLIENT_PEC);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pmbus_debugfs_set_pec(void *data, u64 val)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
struct i2c_client *client = data;
|
|
||||||
|
|
||||||
if (!val) {
|
|
||||||
client->flags &= ~I2C_CLIENT_PEC;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (val != 1)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
rc = i2c_smbus_read_byte_data(client, PMBUS_CAPABILITY);
|
|
||||||
if (rc < 0)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
if (!(rc & PB_CAPABILITY_ERROR_CHECK))
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
|
|
||||||
client->flags |= I2C_CLIENT_PEC;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
DEFINE_DEBUGFS_ATTRIBUTE(pmbus_debugfs_ops_pec, pmbus_debugfs_get_pec,
|
|
||||||
pmbus_debugfs_set_pec, "%llu\n");
|
|
||||||
|
|
||||||
static void pmbus_remove_debugfs(void *data)
|
static void pmbus_remove_debugfs(void *data)
|
||||||
{
|
{
|
||||||
struct dentry *entry = data;
|
struct dentry *entry = data;
|
||||||
@ -2853,9 +2867,6 @@ static int pmbus_init_debugfs(struct i2c_client *client,
|
|||||||
if (!entries)
|
if (!entries)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
debugfs_create_file("pec", 0664, data->debugfs, client,
|
|
||||||
&pmbus_debugfs_ops_pec);
|
|
||||||
|
|
||||||
for (i = 0; i < data->info->pages; ++i) {
|
for (i = 0; i < data->info->pages; ++i) {
|
||||||
/* Check accessibility of status register if it's not page 0 */
|
/* Check accessibility of status register if it's not page 0 */
|
||||||
if (!i || pmbus_check_status_register(client, i)) {
|
if (!i || pmbus_check_status_register(client, i)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user