platform/mellanox: mlxreg-io: Add support for complex attributes
Add support for attributes composed from few registers. Such attributes could occupy from 2 to 4 sequential registers. For word size register space complex attributes can occupy up to two registers, for byte size - up to four. These attributes can carry, for example, CPLD or FPGA versioning, power consuming info, etcetera. Such registers contain read-only data. Signed-off-by: Vadim Pasternak <vadimp@mellanox.com> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
This commit is contained in:
Родитель
ae1aabf44b
Коммит
86148190a7
|
@ -30,6 +30,7 @@
|
|||
* @mlxreg_io_dev_attr: sysfs sensor device attribute array;
|
||||
* @group: sysfs attribute group;
|
||||
* @groups: list of sysfs attribute group for hwmon registration;
|
||||
* @regsize: size of a register value;
|
||||
*/
|
||||
struct mlxreg_io_priv_data {
|
||||
struct platform_device *pdev;
|
||||
|
@ -39,27 +40,30 @@ struct mlxreg_io_priv_data {
|
|||
struct sensor_device_attribute mlxreg_io_dev_attr[MLXREG_IO_ATT_NUM];
|
||||
struct attribute_group group;
|
||||
const struct attribute_group *groups[2];
|
||||
int regsize;
|
||||
};
|
||||
|
||||
static int
|
||||
mlxreg_io_get_reg(void *regmap, struct mlxreg_core_data *data, u32 in_val,
|
||||
bool rw_flag, u32 *regval)
|
||||
bool rw_flag, int regsize, u32 *regval)
|
||||
{
|
||||
int ret;
|
||||
int i, val, ret;
|
||||
|
||||
ret = regmap_read(regmap, data->reg, regval);
|
||||
if (ret)
|
||||
goto access_error;
|
||||
|
||||
/*
|
||||
* There are three kinds of attributes: single bit, full register's
|
||||
* bits and bit sequence. For the first kind field mask indicates which
|
||||
* bits are not related and field bit is set zero. For the second kind
|
||||
* field mask is set to zero and field bit is set with all bits one.
|
||||
* No special handling for such kind of attributes - pass value as is.
|
||||
* For the third kind, field mask indicates which bits are related and
|
||||
* field bit is set to the first bit number (from 1 to 32) is the bit
|
||||
* sequence.
|
||||
* There are four kinds of attributes: single bit, full register's
|
||||
* bits, bit sequence, bits in few registers For the first kind field
|
||||
* mask indicates which bits are not related and field bit is set zero.
|
||||
* For the second kind field mask is set to zero and field bit is set
|
||||
* with all bits one. No special handling for such kind of attributes -
|
||||
* pass value as is. For the third kind, the field mask indicates which
|
||||
* bits are related and the field bit is set to the first bit number
|
||||
* (from 1 to 32) is the bit sequence. For the fourth kind - the number
|
||||
* of registers which should be read for getting an attribute are
|
||||
* specified through 'data->regnum' field.
|
||||
*/
|
||||
if (!data->bit) {
|
||||
/* Single bit. */
|
||||
|
@ -83,6 +87,19 @@ mlxreg_io_get_reg(void *regmap, struct mlxreg_core_data *data, u32 in_val,
|
|||
/* Clear relevant bits and set them to new value. */
|
||||
*regval = (*regval & ~data->mask) | in_val;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Some attributes could occupied few registers in case regmap
|
||||
* bit size is 8 or 16. Compose such attributes from 'regnum'
|
||||
* registers. Such attributes contain read-only data.
|
||||
*/
|
||||
for (i = 1; i < data->regnum; i++) {
|
||||
ret = regmap_read(regmap, data->reg + i, &val);
|
||||
if (ret)
|
||||
goto access_error;
|
||||
|
||||
*regval |= rol32(val, regsize * i);
|
||||
}
|
||||
}
|
||||
|
||||
access_error:
|
||||
|
@ -99,7 +116,8 @@ mlxreg_io_attr_show(struct device *dev, struct device_attribute *attr,
|
|||
u32 regval = 0;
|
||||
int ret;
|
||||
|
||||
ret = mlxreg_io_get_reg(priv->pdata->regmap, data, 0, true, ®val);
|
||||
ret = mlxreg_io_get_reg(priv->pdata->regmap, data, 0, true,
|
||||
priv->regsize, ®val);
|
||||
if (ret)
|
||||
goto access_error;
|
||||
|
||||
|
@ -128,7 +146,7 @@ mlxreg_io_attr_store(struct device *dev, struct device_attribute *attr,
|
|||
return ret;
|
||||
|
||||
ret = mlxreg_io_get_reg(priv->pdata->regmap, data, input_val, false,
|
||||
®val);
|
||||
priv->regsize, ®val);
|
||||
if (ret)
|
||||
goto access_error;
|
||||
|
||||
|
@ -207,6 +225,9 @@ static int mlxreg_io_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
priv->pdev = pdev;
|
||||
priv->regsize = regmap_get_val_bytes(priv->pdata->regmap);
|
||||
if (priv->regsize < 0)
|
||||
return priv->regsize;
|
||||
|
||||
err = mlxreg_io_attr_init(priv);
|
||||
if (err) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче