| .. | .. |
|---|
| 30 | 30 | * @mlxreg_io_dev_attr: sysfs sensor device attribute array; |
|---|
| 31 | 31 | * @group: sysfs attribute group; |
|---|
| 32 | 32 | * @groups: list of sysfs attribute group for hwmon registration; |
|---|
| 33 | + * @regsize: size of a register value; |
|---|
| 33 | 34 | */ |
|---|
| 34 | 35 | struct mlxreg_io_priv_data { |
|---|
| 35 | 36 | struct platform_device *pdev; |
|---|
| .. | .. |
|---|
| 39 | 40 | struct sensor_device_attribute mlxreg_io_dev_attr[MLXREG_IO_ATT_NUM]; |
|---|
| 40 | 41 | struct attribute_group group; |
|---|
| 41 | 42 | const struct attribute_group *groups[2]; |
|---|
| 43 | + int regsize; |
|---|
| 42 | 44 | }; |
|---|
| 43 | 45 | |
|---|
| 44 | 46 | static int |
|---|
| 45 | 47 | mlxreg_io_get_reg(void *regmap, struct mlxreg_core_data *data, u32 in_val, |
|---|
| 46 | | - bool rw_flag, u32 *regval) |
|---|
| 48 | + bool rw_flag, int regsize, u32 *regval) |
|---|
| 47 | 49 | { |
|---|
| 48 | | - int ret; |
|---|
| 50 | + int i, val, ret; |
|---|
| 49 | 51 | |
|---|
| 50 | 52 | ret = regmap_read(regmap, data->reg, regval); |
|---|
| 51 | 53 | if (ret) |
|---|
| 52 | 54 | goto access_error; |
|---|
| 53 | 55 | |
|---|
| 54 | 56 | /* |
|---|
| 55 | | - * There are three kinds of attributes: single bit, full register's |
|---|
| 56 | | - * bits and bit sequence. For the first kind field mask indicates which |
|---|
| 57 | | - * bits are not related and field bit is set zero. For the second kind |
|---|
| 58 | | - * field mask is set to zero and field bit is set with all bits one. |
|---|
| 59 | | - * No special handling for such kind of attributes - pass value as is. |
|---|
| 60 | | - * For the third kind, field mask indicates which bits are related and |
|---|
| 61 | | - * field bit is set to the first bit number (from 1 to 32) is the bit |
|---|
| 62 | | - * sequence. |
|---|
| 57 | + * There are four kinds of attributes: single bit, full register's |
|---|
| 58 | + * bits, bit sequence, bits in few registers For the first kind field |
|---|
| 59 | + * mask indicates which bits are not related and field bit is set zero. |
|---|
| 60 | + * For the second kind field mask is set to zero and field bit is set |
|---|
| 61 | + * with all bits one. No special handling for such kind of attributes - |
|---|
| 62 | + * pass value as is. For the third kind, the field mask indicates which |
|---|
| 63 | + * bits are related and the field bit is set to the first bit number |
|---|
| 64 | + * (from 1 to 32) is the bit sequence. For the fourth kind - the number |
|---|
| 65 | + * of registers which should be read for getting an attribute are |
|---|
| 66 | + * specified through 'data->regnum' field. |
|---|
| 63 | 67 | */ |
|---|
| 64 | 68 | if (!data->bit) { |
|---|
| 65 | 69 | /* Single bit. */ |
|---|
| .. | .. |
|---|
| 83 | 87 | /* Clear relevant bits and set them to new value. */ |
|---|
| 84 | 88 | *regval = (*regval & ~data->mask) | in_val; |
|---|
| 85 | 89 | } |
|---|
| 90 | + } else { |
|---|
| 91 | + /* |
|---|
| 92 | + * Some attributes could occupied few registers in case regmap |
|---|
| 93 | + * bit size is 8 or 16. Compose such attributes from 'regnum' |
|---|
| 94 | + * registers. Such attributes contain read-only data. |
|---|
| 95 | + */ |
|---|
| 96 | + for (i = 1; i < data->regnum; i++) { |
|---|
| 97 | + ret = regmap_read(regmap, data->reg + i, &val); |
|---|
| 98 | + if (ret) |
|---|
| 99 | + goto access_error; |
|---|
| 100 | + |
|---|
| 101 | + *regval |= rol32(val, regsize * i * 8); |
|---|
| 102 | + } |
|---|
| 86 | 103 | } |
|---|
| 87 | 104 | |
|---|
| 88 | 105 | access_error: |
|---|
| .. | .. |
|---|
| 99 | 116 | u32 regval = 0; |
|---|
| 100 | 117 | int ret; |
|---|
| 101 | 118 | |
|---|
| 102 | | - ret = mlxreg_io_get_reg(priv->pdata->regmap, data, 0, true, ®val); |
|---|
| 119 | + ret = mlxreg_io_get_reg(priv->pdata->regmap, data, 0, true, |
|---|
| 120 | + priv->regsize, ®val); |
|---|
| 103 | 121 | if (ret) |
|---|
| 104 | 122 | goto access_error; |
|---|
| 105 | 123 | |
|---|
| .. | .. |
|---|
| 128 | 146 | return ret; |
|---|
| 129 | 147 | |
|---|
| 130 | 148 | ret = mlxreg_io_get_reg(priv->pdata->regmap, data, input_val, false, |
|---|
| 131 | | - ®val); |
|---|
| 149 | + priv->regsize, ®val); |
|---|
| 132 | 150 | if (ret) |
|---|
| 133 | 151 | goto access_error; |
|---|
| 134 | 152 | |
|---|
| .. | .. |
|---|
| 207 | 225 | } |
|---|
| 208 | 226 | |
|---|
| 209 | 227 | priv->pdev = pdev; |
|---|
| 228 | + priv->regsize = regmap_get_val_bytes(priv->pdata->regmap); |
|---|
| 229 | + if (priv->regsize < 0) |
|---|
| 230 | + return priv->regsize; |
|---|
| 210 | 231 | |
|---|
| 211 | 232 | err = mlxreg_io_attr_init(priv); |
|---|
| 212 | 233 | if (err) { |
|---|