2020-06-01 09:21:09

by Vadim Pasternak

[permalink] [raw]
Subject: [PATCH platform-next v1 0/8] platform/x86: Add new features for Mellanox systems

The patchset adds new features for the existing Mellanox systems.

Patch #1 allows to configure number of hotplug 'sysfs' attributes for
the particular system class according to the hardware data for
the specific system from this class, instead of configuring it
up-to maximum number in the class.
Patch #2 adds environmental data to hotplug uevent.
Patches #3-#4 adds more definitions for system attributes.
Patch #5 extends 'mlxreg-io' driver with complex attributes support.
Patches #6 extends documentation with new attributes.
Patches #7-#8 extends FAN platform data with register presence field.

Vadim Pasternak (8):
platform/mellanox: mlxreg-hotplug: Use capability register for
attribute creation
platform/mellanox: mlxreg-hotplug: Add environmental data to uevent
platform_data/mlxreg: Add support for complex attributes
platform/x86: mlx-platform: Add more definitions for system attributes
platform/mellanox: mlxreg-io: Add support for complex attributes
Documentation/ABI: Add new attribute for mlxreg-io sysfs interfaces
platform_data/mlxreg: Add presence register field for FAN devices
platform/x86: mlx-platform: Extend FAN platform data description

Documentation/ABI/stable/sysfs-driver-mlxreg-io | 17 +++
drivers/platform/mellanox/mlxreg-hotplug.c | 81 ++++++++++----
drivers/platform/mellanox/mlxreg-io.c | 47 ++++++--
drivers/platform/x86/mlx-platform.c | 141 ++++++++++++++++++++++++
include/linux/platform_data/mlxreg.h | 4 +
5 files changed, 258 insertions(+), 32 deletions(-)

--
2.11.0


2020-06-01 09:21:18

by Vadim Pasternak

[permalink] [raw]
Subject: [PATCH platform-next v1 4/8] platform/x86: mlx-platform: Add more definitions for system attributes

Add new attributes for the all type systems specifying for each
equipped CPLD device, the CPLD part number and the CPLD minor version
of the device: 'cpld{n}_pn' and 'cpld{n}_version_min'.
This information is to be used for mathcing the current CPLD image and
for making decision if image upgrade is required for CPLD device.

Signed-off-by: Vadim Pasternak <[email protected]>
---
drivers/platform/x86/mlx-platform.c | 128 ++++++++++++++++++++++++++++++++++++
1 file changed, 128 insertions(+)

diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
index c27548fd386a..034736cec9a6 100644
--- a/drivers/platform/x86/mlx-platform.c
+++ b/drivers/platform/x86/mlx-platform.c
@@ -26,6 +26,10 @@
#define MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET 0x01
#define MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET 0x02
#define MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET 0x03
+#define MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET 0x04
+#define MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET 0x06
+#define MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET 0x08
+#define MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET 0x0a
#define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET 0x1d
#define MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET 0x1e
#define MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET 0x1f
@@ -72,6 +76,10 @@
#define MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET 0xd1
#define MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET 0xd2
#define MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET 0xd3
+#define MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET 0xde
+#define MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET 0xdf
+#define MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET 0xe0
+#define MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET 0xe1
#define MLXPLAT_CPLD_LPC_REG_UFM_VERSION_OFFSET 0xe2
#define MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET 0xe3
#define MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET 0xe4
@@ -1304,6 +1312,32 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_regs_io_data[] = {
.mode = 0444,
},
{
+ .label = "cpld1_pn",
+ .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET,
+ .bit = GENMASK(15, 0),
+ .mode = 0444,
+ .regnum = 2,
+ },
+ {
+ .label = "cpld2_pn",
+ .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET,
+ .bit = GENMASK(15, 0),
+ .mode = 0444,
+ .regnum = 2,
+ },
+ {
+ .label = "cpld1_version_min",
+ .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET,
+ .bit = GENMASK(7, 0),
+ .mode = 0444,
+ },
+ {
+ .label = "cpld2_version_min",
+ .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET,
+ .bit = GENMASK(7, 0),
+ .mode = 0444,
+ },
+ {
.label = "reset_long_pb",
.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(0),
@@ -1410,6 +1444,32 @@ static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_regs_io_data[] = {
.mode = 0444,
},
{
+ .label = "cpld1_pn",
+ .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET,
+ .bit = GENMASK(15, 0),
+ .mode = 0444,
+ .regnum = 2,
+ },
+ {
+ .label = "cpld2_pn",
+ .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET,
+ .bit = GENMASK(15, 0),
+ .mode = 0444,
+ .regnum = 2,
+ },
+ {
+ .label = "cpld1_version_min",
+ .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET,
+ .bit = GENMASK(7, 0),
+ .mode = 0444,
+ },
+ {
+ .label = "cpld2_version_min",
+ .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET,
+ .bit = GENMASK(7, 0),
+ .mode = 0444,
+ },
+ {
.label = "reset_long_pb",
.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(0),
@@ -1528,6 +1588,58 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = {
.mode = 0444,
},
{
+ .label = "cpld1_pn",
+ .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET,
+ .bit = GENMASK(15, 0),
+ .mode = 0444,
+ .regnum = 2,
+ },
+ {
+ .label = "cpld2_pn",
+ .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET,
+ .bit = GENMASK(15, 0),
+ .mode = 0444,
+ .regnum = 2,
+ },
+ {
+ .label = "cpld3_pn",
+ .reg = MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET,
+ .bit = GENMASK(15, 0),
+ .mode = 0444,
+ .regnum = 2,
+ },
+ {
+ .label = "cpld4_pn",
+ .reg = MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET,
+ .bit = GENMASK(15, 0),
+ .mode = 0444,
+ .regnum = 2,
+ },
+ {
+ .label = "cpld1_version_min",
+ .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET,
+ .bit = GENMASK(7, 0),
+ .mode = 0444,
+ },
+ {
+ .label = "cpld2_version_min",
+ .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET,
+ .bit = GENMASK(7, 0),
+ .mode = 0444,
+ },
+ {
+ .label = "cpld3_version_min",
+ .reg = MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET,
+ .bit = GENMASK(7, 0),
+ .mode = 0444,
+ },
+ {
+ .label = "cpld4_version_min",
+ .reg = MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET,
+ .bit = GENMASK(7, 0),
+ .mode = 0444,
+ },
+ {
.label = "reset_long_pb",
.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(0),
@@ -2006,6 +2118,10 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET:
@@ -2051,6 +2167,10 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET:
case MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET:
@@ -2085,6 +2205,10 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET:
@@ -2122,6 +2246,10 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_WD2_TLEFT_OFFSET:
case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET:
--
2.11.0

2020-06-01 09:21:26

by Vadim Pasternak

[permalink] [raw]
Subject: [PATCH platform-next v1 6/8] Documentation/ABI: Add new attribute for mlxreg-io sysfs interfaces

Add documentation for the new attributes for exposing CPLDs part
numbers and CPLD minor versions.

Signed-off-by: Vadim Pasternak <[email protected]>
---
Documentation/ABI/stable/sysfs-driver-mlxreg-io | 17 +++++++++++++++++
1 file changed, 17 insertions(+)

diff --git a/Documentation/ABI/stable/sysfs-driver-mlxreg-io b/Documentation/ABI/stable/sysfs-driver-mlxreg-io
index b0d90cc696a8..1397f207523c 100644
--- a/Documentation/ABI/stable/sysfs-driver-mlxreg-io
+++ b/Documentation/ABI/stable/sysfs-driver-mlxreg-io
@@ -206,3 +206,20 @@ Description: This file exposes the firmware version of burnable voltage
regulator devices.

The file is read only.
+
+What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld1_pn
+What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld2_pn
+What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld3_pn
+What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld4_pn
+What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld1_version_min
+What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld2_version_min
+What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld3_version_min
+What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld4_version_min
+Date: June 2020
+KernelVersion: 5.8
+Contact: Vadim Pasternak <vadimpmellanox.com>
+Description: These files show with which CPLD part numbers and minor
+ versions have been burned CPLD devices equipped on a
+ system.
+
+ The files are read only.
--
2.11.0

2020-06-01 09:21:31

by Vadim Pasternak

[permalink] [raw]
Subject: [PATCH platform-next v1 8/8] platform/x86: mlx-platform: Extend FAN platform data description

Extend FAN platform data with register presence field.
Add register present entry per rotor (tachometer) description tuple.
The purpose is to allow indication of FAN presence.

Signed-off-by: Vadim Pasternak <[email protected]>
---
drivers/platform/x86/mlx-platform.c | 13 +++++++++++++
1 file changed, 13 insertions(+)

diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
index 034736cec9a6..90bc7969b199 100644
--- a/drivers/platform/x86/mlx-platform.c
+++ b/drivers/platform/x86/mlx-platform.c
@@ -1840,6 +1840,8 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
.bit = BIT(0),
+ .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
+
},
{
.label = "tacho2",
@@ -1847,6 +1849,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
.bit = BIT(1),
+ .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
},
{
.label = "tacho3",
@@ -1854,6 +1857,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
.bit = BIT(2),
+ .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
},
{
.label = "tacho4",
@@ -1861,6 +1865,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
.bit = BIT(3),
+ .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
},
{
.label = "tacho5",
@@ -1868,6 +1873,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
.bit = BIT(4),
+ .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
},
{
.label = "tacho6",
@@ -1875,6 +1881,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
.bit = BIT(5),
+ .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
},
{
.label = "tacho7",
@@ -1882,6 +1889,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
.bit = BIT(6),
+ .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
},
{
.label = "tacho8",
@@ -1889,6 +1897,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
.bit = BIT(7),
+ .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
},
{
.label = "tacho9",
@@ -1896,6 +1905,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
.bit = BIT(0),
+ .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
},
{
.label = "tacho10",
@@ -1903,6 +1913,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
.bit = BIT(1),
+ .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
},
{
.label = "tacho11",
@@ -1910,6 +1921,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
.bit = BIT(2),
+ .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
},
{
.label = "tacho12",
@@ -1917,6 +1929,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
.bit = BIT(3),
+ .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
},
{
.label = "conf",
--
2.11.0

2020-06-01 09:22:05

by Vadim Pasternak

[permalink] [raw]
Subject: [PATCH platform-next v1 5/8] 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 attribute can occupy up to two
register, 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 <[email protected]>
---
drivers/platform/mellanox/mlxreg-io.c | 47 ++++++++++++++++++++++++++---------
1 file changed, 35 insertions(+), 12 deletions(-)

diff --git a/drivers/platform/mellanox/mlxreg-io.c b/drivers/platform/mellanox/mlxreg-io.c
index acfaf64ffde6..93dbbe381bc4 100644
--- a/drivers/platform/mellanox/mlxreg-io.c
+++ b/drivers/platform/mellanox/mlxreg-io.c
@@ -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, 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. 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,21 @@ 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 attribute from 'regnum'
+ * registers. Such attributes contain read only data.
+ */
+ if (data->regnum > 1 && !rw_flag)
+ return -EINVAL;
+ 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 +118,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, &regval);
+ ret = mlxreg_io_get_reg(priv->pdata->regmap, data, 0, true,
+ priv->regsize, &regval);
if (ret)
goto access_error;

@@ -128,7 +148,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,
- &regval);
+ priv->regsize, &regval);
if (ret)
goto access_error;

@@ -207,6 +227,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) {
--
2.11.0

2020-06-01 09:22:15

by Vadim Pasternak

[permalink] [raw]
Subject: [PATCH platform-next v1 1/8] platform/mellanox: mlxreg-hotplug: Use capability register for attribute creation

Create the 'sysfs' attributes according to configuration provided
through the capability register, which purpose is to indicate the
actual number of the components within the particular group.
Such components could be, for example the FAN or power supply units.
The motivation is to avoid adding a new code in the future in order to
distinct between the systems types supported different number of the
components like power supplies, FANs, ASICs, line cards.

Signed-off-by: Vadim Pasternak <[email protected]>
---
drivers/platform/mellanox/mlxreg-hotplug.c | 54 ++++++++++++++++++++----------
1 file changed, 36 insertions(+), 18 deletions(-)

diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c
index 77be37a1fbcf..832fcf282d45 100644
--- a/drivers/platform/mellanox/mlxreg-hotplug.c
+++ b/drivers/platform/mellanox/mlxreg-hotplug.c
@@ -196,17 +196,46 @@ static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv)
struct mlxreg_core_hotplug_platform_data *pdata;
struct mlxreg_core_item *item;
struct mlxreg_core_data *data;
- int num_attrs = 0, id = 0, i, j;
+ u32 regval;
+ int num_attrs = 0, id = 0, i, j, k, ret;

pdata = dev_get_platdata(&priv->pdev->dev);
item = pdata->items;

/* Go over all kinds of items - psu, pwr, fan. */
for (i = 0; i < pdata->counter; i++, item++) {
- num_attrs += item->count;
+ if (item->capability) {
+ /*
+ * Read group capability register to get actual number
+ * of interrupt capable components and set group mask
+ * accordingly.
+ */
+ ret = regmap_read(priv->regmap, item->capability,
+ &regval);
+ if (ret)
+ return ret;
+
+ item->mask = GENMASK((regval & item->mask) - 1, 0);
+ }
+
data = item->data;
/* Go over all units within the item. */
- for (j = 0; j < item->count; j++, data++, id++) {
+ for (j = 0, k = 0; j < item->count; j++, data++) {
+ /* Skip if bit in mask is not set. */
+ if (!(item->mask & BIT(j)))
+ continue;
+ if (data->capability) {
+ /*
+ * Read capability register and skip non
+ * relevant attributes.
+ */
+ ret = regmap_read(priv->regmap,
+ data->capability, &regval);
+ if (ret)
+ return ret;
+ if (!(regval & data->bit))
+ continue;
+ }
PRIV_ATTR(id) = &PRIV_DEV_ATTR(id).dev_attr.attr;
PRIV_ATTR(id)->name = devm_kasprintf(&priv->pdev->dev,
GFP_KERNEL,
@@ -224,9 +253,12 @@ static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv)
PRIV_DEV_ATTR(id).dev_attr.show =
mlxreg_hotplug_attr_show;
PRIV_DEV_ATTR(id).nr = i;
- PRIV_DEV_ATTR(id).index = j;
+ PRIV_DEV_ATTR(id).index = k;
sysfs_attr_init(&PRIV_DEV_ATTR(id).dev_attr.attr);
+ id++;
+ k++;
}
+ num_attrs += k;
}

priv->group.attrs = devm_kcalloc(&priv->pdev->dev,
@@ -504,20 +536,6 @@ static int mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv)
item = pdata->items;

for (i = 0; i < pdata->counter; i++, item++) {
- if (item->capability) {
- /*
- * Read group capability register to get actual number
- * of interrupt capable components and set group mask
- * accordingly.
- */
- ret = regmap_read(priv->regmap, item->capability,
- &regval);
- if (ret)
- goto out;
-
- item->mask = GENMASK((regval & item->mask) - 1, 0);
- }
-
/* Clear group presense event. */
ret = regmap_write(priv->regmap, item->reg +
MLXREG_HOTPLUG_EVENT_OFF, 0);
--
2.11.0

2020-06-01 09:22:24

by Vadim Pasternak

[permalink] [raw]
Subject: [PATCH platform-next v1 3/8] platform_data/mlxreg: Add support for complex attributes

Add new field 'regnum' to the structure 'mlxreg_core_data' to specify
the number of registers occupied by multi-register attribute.

Signed-off-by: Vadim Pasternak <[email protected]>
---
include/linux/platform_data/mlxreg.h | 2 ++
1 file changed, 2 insertions(+)

diff --git a/include/linux/platform_data/mlxreg.h b/include/linux/platform_data/mlxreg.h
index b8da8aef2446..a2adc3ad45f2 100644
--- a/include/linux/platform_data/mlxreg.h
+++ b/include/linux/platform_data/mlxreg.h
@@ -80,6 +80,7 @@ struct mlxreg_hotplug_device {
* @hpdev - hotplug device data;
* @health_cntr: dynamic device health indication counter;
* @attached: true if device has been attached after good health indication;
+ * @regnum: number of registers occupied by multi-register attribute;
*/
struct mlxreg_core_data {
char label[MLXREG_CORE_LABEL_MAX_SIZE];
@@ -92,6 +93,7 @@ struct mlxreg_core_data {
struct mlxreg_hotplug_device hpdev;
u8 health_cntr;
bool attached;
+ u8 regnum;
};

/**
--
2.11.0

2020-06-01 09:23:20

by Vadim Pasternak

[permalink] [raw]
Subject: [PATCH platform-next v1 7/8] platform_data/mlxreg: Add presence register field for FAN devices

Add new field 'reg_prsnt' to the structure 'mlxreg_core_data' to
provide the number FAN drawers equpped within the system. The purpose
is to allow mapping between FAN drawers and FAN rotors (tachometer),
since FAN drawer can be eqipped with a few rotors.

Signed-off-by: Vadim Pasternak <[email protected]>
---
include/linux/platform_data/mlxreg.h | 2 ++
1 file changed, 2 insertions(+)

diff --git a/include/linux/platform_data/mlxreg.h b/include/linux/platform_data/mlxreg.h
index a2adc3ad45f2..9cffa9a64ab3 100644
--- a/include/linux/platform_data/mlxreg.h
+++ b/include/linux/platform_data/mlxreg.h
@@ -75,6 +75,7 @@ struct mlxreg_hotplug_device {
* @mask: attribute access mask;
* @bit: attribute effective bit;
* @capability: attribute capability register;
+ * @reg_prsnt: attribute presence register;
* @mode: access mode;
* @np - pointer to node platform associated with attribute;
* @hpdev - hotplug device data;
@@ -88,6 +89,7 @@ struct mlxreg_core_data {
u32 mask;
u32 bit;
u32 capability;
+ u32 reg_prsnt;
umode_t mode;
struct device_node *np;
struct mlxreg_hotplug_device hpdev;
--
2.11.0

2020-07-09 16:09:45

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH platform-next v1 1/8] platform/mellanox: mlxreg-hotplug: Use capability register for attribute creation

On Mon, Jun 1, 2020 at 12:19 PM Vadim Pasternak <[email protected]> wrote:
>
> Create the 'sysfs' attributes according to configuration provided
> through the capability register, which purpose is to indicate the
> actual number of the components within the particular group.
> Such components could be, for example the FAN or power supply units.
> The motivation is to avoid adding a new code in the future in order to
> distinct between the systems types supported different number of the

supported -> supporting a

> components like power supplies, FANs, ASICs, line cards.

...

> /* Go over all units within the item. */
> - for (j = 0; j < item->count; j++, data++, id++) {
> + for (j = 0, k = 0; j < item->count; j++, data++) {
> + /* Skip if bit in mask is not set. */
> + if (!(item->mask & BIT(j)))
> + continue;

Instead of splitted comments and this code, perhaps

/* Go over all unmasked units within item */
for_each_set_bit(j, &item->mask, item->count) {
...
}

It might require a mask defined as unsigned long, though. Or temporary
variables.

> }
> + num_attrs += k;
> }

--
With Best Regards,
Andy Shevchenko

2020-07-09 16:39:27

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH platform-next v1 5/8] platform/mellanox: mlxreg-io: Add support for complex attributes

On Mon, Jun 1, 2020 at 12:19 PM Vadim Pasternak <[email protected]> wrote:
>
> Add support for attributes composed from few registers.
> Such attributes could occupy from 2 to 4 sequential registers.
> For word size register space complex attribute can occupy up to two

attributes

> register, for byte size - up to four. These attributes can carry, for

registers

> example, CPLD or FPGA versioning, power consuming info, etcetera.
> Such registers contain read only data.

read-only.

...

> + * 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, field mask indicates which

the field

> + * bits are related and field bit is set to the first bit number (from

the field

> + * 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.
> */

...

> + /*
> + * Some attributes could occupied few registers in case regmap
> + * bit size is 8 or 16. Compose such attribute from 'regnum'

attributes

> + * registers. Such attributes contain read only data.

read-only

> + */
> + if (data->regnum > 1 && !rw_flag)

This I didn't get. They contain read-only data and here you explicitly
turn down rw_flag == false.
Can you clarify this?

> + return -EINVAL;
> + 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);
> + }

--
With Best Regards,
Andy Shevchenko