mirror of
https://github.com/Telecominfraproject/OpenNetworkLinux.git
synced 2025-12-24 16:57:02 +00:00
Removed: mallanox wdt driver patch
Signed-off-by: Oleksandr Shamray <oleksandrs@mellanox.com>
This commit is contained in:
@@ -2549,9 +2549,9 @@ CONFIG_X86_PKG_TEMP_THERMAL=m
|
||||
# CONFIG_INTEL_PCH_THERMAL is not set
|
||||
# CONFIG_GENERIC_ADC_THERMAL is not set
|
||||
CONFIG_WATCHDOG=y
|
||||
CONFIG_WATCHDOG_CORE=y
|
||||
# CONFIG_WATCHDOG_CORE is not set
|
||||
# CONFIG_WATCHDOG_NOWAYOUT is not set
|
||||
CONFIG_WATCHDOG_SYSFS=y
|
||||
# CONFIG_WATCHDOG_SYSFS is not set
|
||||
|
||||
#
|
||||
# Watchdog Device Drivers
|
||||
@@ -2595,7 +2595,6 @@ CONFIG_WATCHDOG_SYSFS=y
|
||||
# CONFIG_SBC_EPX_C3_WATCHDOG is not set
|
||||
# CONFIG_NI903X_WDT is not set
|
||||
# CONFIG_MEN_A21_WDT is not set
|
||||
CONFIG_MLX_WDT=m
|
||||
|
||||
#
|
||||
# PCI-based Watchdog Cards
|
||||
|
||||
@@ -1,839 +0,0 @@
|
||||
From a648f2856518f8884a7798469faf755d0f5dcd50 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Shych <michaelsh@mellanox.com>
|
||||
Date: Mon, 17 Dec 2018 12:32:45 +0000
|
||||
Subject: [PATCH v1 mlx-wdt 1/1] watchdog: mlx-wdt: introduce watchdog driver
|
||||
for Mellanox systems
|
||||
|
||||
Watchdog driver for Mellanox watchdog devices, implemented in
|
||||
programmable logic device.
|
||||
|
||||
Main and auxiliary watchdog devices can exist on the same system.
|
||||
There are several actions that can be defined in the watchdog:
|
||||
system reset, start fans on full speed and increase counter.
|
||||
The last 2 actions are performed without system reset.
|
||||
Actions without reset are provided for auxiliary watchdog devices,
|
||||
which is optional.
|
||||
Access to CPLD registers is performed through generic
|
||||
regmap interface.
|
||||
|
||||
There are 2 types of HW CPLD watchdog implementations.
|
||||
Type 1: actual HW timeout can be defined as power of 2 msec.
|
||||
e.g. timeout 20 sec will be rounded up to 32768 msec.;
|
||||
maximum timeout period is 32 sec (32768 msec.);
|
||||
get time-left isn't supported
|
||||
Type 2: actual HW timeout is defined in sec. and it's a same as
|
||||
user defined timeout;
|
||||
maximum timeout is 255 sec;
|
||||
get time-left is supported;
|
||||
|
||||
Watchdog driver is probed from common mlx_platform driver.
|
||||
|
||||
Signed-off-by: Michael Shych <michaelsh@mellanox.com>
|
||||
---
|
||||
drivers/platform/x86/mlx-platform.c | 202 +++++++++++++++++-
|
||||
drivers/watchdog/Kconfig | 15 ++
|
||||
drivers/watchdog/Makefile | 1 +
|
||||
drivers/watchdog/mlx_wdt.c | 391 +++++++++++++++++++++++++++++++++++
|
||||
include/linux/platform_data/mlxreg.h | 6 +
|
||||
5 files changed, 612 insertions(+), 3 deletions(-)
|
||||
create mode 100644 drivers/watchdog/mlx_wdt.c
|
||||
|
||||
diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
|
||||
index 6e150b4..fc8d655 100644
|
||||
--- a/drivers/platform/x86/mlx-platform.c
|
||||
+++ b/drivers/platform/x86/mlx-platform.c
|
||||
@@ -55,6 +55,14 @@
|
||||
#define MLXPLAT_CPLD_LPC_REG_FAN_OFFSET 0x88
|
||||
#define MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET 0x89
|
||||
#define MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET 0x8a
|
||||
+#define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET 0xc7
|
||||
+#define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET 0xc8
|
||||
+#define MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET 0xc9
|
||||
+#define MLXPLAT_CPLD_LPC_REG_WD1_ACT_OFFSET 0xcb
|
||||
+#define MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET 0xcd
|
||||
+#define MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET 0xcf
|
||||
+#define MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET 0xd1
|
||||
+#define MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET 0xd2
|
||||
#define MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET 0xe3
|
||||
#define MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET 0xe4
|
||||
#define MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET 0xe5
|
||||
@@ -128,6 +136,18 @@
|
||||
#define MLXPLAT_CPLD_FAN3_DEFAULT_NR 13
|
||||
#define MLXPLAT_CPLD_FAN4_DEFAULT_NR 14
|
||||
|
||||
+/* Masks and default values for watchdogs */
|
||||
+#define MLXPLAT_CPLD_WD1_CLEAR_MASK GENMASK(7, 1)
|
||||
+#define MLXPLAT_CPLD_WD2_CLEAR_MASK (GENMASK(7, 0) & ~BIT(1))
|
||||
+
|
||||
+#define MLXPLAT_CPLD_WD_TYPE1_TO_MASK GENMASK(7, 4)
|
||||
+#define MLXPLAT_CPLD_WD_TYPE2_TO_MASK 0
|
||||
+#define MLXPLAT_CPLD_WD_RESET_ACT_MASK GENMASK(7, 1)
|
||||
+#define MLXPLAT_CPLD_WD_FAN_ACT_MASK (GENMASK(7, 0) & ~BIT(4))
|
||||
+#define MLXPLAT_CPLD_WD_COUNT_ACT_MASK (GENMASK(7, 0) & ~BIT(7))
|
||||
+#define MLXPLAT_CPLD_WD_DFLT_TIMEOUT 30
|
||||
+#define MLXPLAT_CPLD_WD_MAX_DEVS 2
|
||||
+
|
||||
/* mlxplat_priv - platform private data
|
||||
* @pdev_i2c - i2c controller platform device
|
||||
* @pdev_mux - array of mux platform devices
|
||||
@@ -135,6 +155,7 @@
|
||||
* @pdev_led - led platform devices
|
||||
* @pdev_io_regs - register access platform devices
|
||||
* @pdev_fan - FAN platform devices
|
||||
+ * @pdev_wd - array of watchdog platform devices
|
||||
*/
|
||||
struct mlxplat_priv {
|
||||
struct platform_device *pdev_i2c;
|
||||
@@ -143,6 +164,7 @@ struct mlxplat_priv {
|
||||
struct platform_device *pdev_led;
|
||||
struct platform_device *pdev_io_regs;
|
||||
struct platform_device *pdev_fan;
|
||||
+ struct platform_device *pdev_wd[MLXPLAT_CPLD_WD_MAX_DEVS];
|
||||
};
|
||||
|
||||
/* Regions for LPC I2C controller and LPC base register space */
|
||||
@@ -1340,6 +1362,132 @@ static struct mlxreg_core_platform_data mlxplat_default_fan_data = {
|
||||
.counter = ARRAY_SIZE(mlxplat_mlxcpld_default_fan_data),
|
||||
};
|
||||
|
||||
+/* Type1 watchdog implementation on MSN2700, MSN2100 and MSN2140 systems */
|
||||
+static struct mlxreg_core_data mlxplat_mlxcpld_wd_main_regs_type1[] = {
|
||||
+ {
|
||||
+ .label = "action",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD1_ACT_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_RESET_ACT_MASK,
|
||||
+ .bit = 0,
|
||||
+ },
|
||||
+ {
|
||||
+ .label = "timeout",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_TYPE1_TO_MASK,
|
||||
+ .health_cntr = MLXPLAT_CPLD_WD_DFLT_TIMEOUT,
|
||||
+ },
|
||||
+ {
|
||||
+ .label = "ping",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD1_CLEAR_MASK,
|
||||
+ .bit = 0,
|
||||
+ },
|
||||
+ {
|
||||
+ .label = "reset",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
|
||||
+ .mask = GENMASK(7, 0) & ~BIT(6),
|
||||
+ .bit = 6,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct mlxreg_core_data mlxplat_mlxcpld_wd_aux_regs_type1[] = {
|
||||
+ {
|
||||
+ .label = "action",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_FAN_ACT_MASK,
|
||||
+ .bit = 4,
|
||||
+ },
|
||||
+ {
|
||||
+ .label = "timeout",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_TYPE1_TO_MASK,
|
||||
+ .health_cntr = MLXPLAT_CPLD_WD_DFLT_TIMEOUT,
|
||||
+ },
|
||||
+ {
|
||||
+ .label = "ping",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD1_CLEAR_MASK,
|
||||
+ .bit = 1,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct mlxreg_core_platform_data mlxplat_mlxcpld_wd_set_type1[] = {
|
||||
+ {
|
||||
+ .data = mlxplat_mlxcpld_wd_main_regs_type1,
|
||||
+ .counter = ARRAY_SIZE(mlxplat_mlxcpld_wd_main_regs_type1),
|
||||
+ .identity = "mlx-wdt-main",
|
||||
+ },
|
||||
+ {
|
||||
+ .data = mlxplat_mlxcpld_wd_aux_regs_type1,
|
||||
+ .counter = ARRAY_SIZE(mlxplat_mlxcpld_wd_aux_regs_type1),
|
||||
+ .identity = "mlx-wdt-aux",
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+/* Type2 watchdog implementation on MSB8700 and up systems
|
||||
+ * To differentiate: ping reg == action reg
|
||||
+ */
|
||||
+static struct mlxreg_core_data mlxplat_mlxcpld_wd_main_regs_type2[] = {
|
||||
+ {
|
||||
+ .label = "action",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_RESET_ACT_MASK,
|
||||
+ .bit = 0,
|
||||
+ },
|
||||
+ {
|
||||
+ .label = "timeout",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_TYPE2_TO_MASK,
|
||||
+ .health_cntr = MLXPLAT_CPLD_WD_DFLT_TIMEOUT,
|
||||
+ },
|
||||
+ {
|
||||
+ .label = "ping",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_RESET_ACT_MASK,
|
||||
+ .bit = 0,
|
||||
+ },
|
||||
+ {
|
||||
+ .label = "reset",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
|
||||
+ .mask = GENMASK(7, 0) & ~BIT(6),
|
||||
+ .bit = 6,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct mlxreg_core_data mlxplat_mlxcpld_wd_aux_regs_type2[] = {
|
||||
+ {
|
||||
+ .label = "action",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_FAN_ACT_MASK,
|
||||
+ .bit = 4,
|
||||
+ },
|
||||
+ {
|
||||
+ .label = "timeout",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_TYPE2_TO_MASK,
|
||||
+ .health_cntr = MLXPLAT_CPLD_WD_DFLT_TIMEOUT,
|
||||
+ },
|
||||
+ {
|
||||
+ .label = "ping",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_FAN_ACT_MASK,
|
||||
+ .bit = 4,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct mlxreg_core_platform_data mlxplat_mlxcpld_wd_set_type2[] = {
|
||||
+ {
|
||||
+ .data = mlxplat_mlxcpld_wd_main_regs_type2,
|
||||
+ .counter = ARRAY_SIZE(mlxplat_mlxcpld_wd_main_regs_type2),
|
||||
+ .identity = "mlx-wdt-main",
|
||||
+ },
|
||||
+ {
|
||||
+ .data = mlxplat_mlxcpld_wd_aux_regs_type2,
|
||||
+ .counter = ARRAY_SIZE(mlxplat_mlxcpld_wd_aux_regs_type2),
|
||||
+ .identity = "mlx-wdt-aux",
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
@@ -1362,6 +1510,14 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
|
||||
case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD1_ACT_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET:
|
||||
return true;
|
||||
@@ -1404,6 +1560,14 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
|
||||
case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD1_ACT_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET:
|
||||
@@ -1460,6 +1624,8 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
|
||||
case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET:
|
||||
@@ -1487,6 +1653,7 @@ static const struct reg_default mlxplat_mlxcpld_regmap_default[] = {
|
||||
{ MLXPLAT_CPLD_LPC_REG_WP1_OFFSET, 0x00 },
|
||||
{ MLXPLAT_CPLD_LPC_REG_WP2_OFFSET, 0x00 },
|
||||
{ MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, 0x00 },
|
||||
+ { MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET, 0x00 },
|
||||
};
|
||||
|
||||
struct mlxplat_mlxcpld_regmap_context {
|
||||
@@ -1536,6 +1703,8 @@ static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug;
|
||||
static struct mlxreg_core_platform_data *mlxplat_led;
|
||||
static struct mlxreg_core_platform_data *mlxplat_regs_io;
|
||||
static struct mlxreg_core_platform_data *mlxplat_fan;
|
||||
+static struct mlxreg_core_platform_data
|
||||
+ *mlxplat_wd_data[MLXPLAT_CPLD_WD_MAX_DEVS];
|
||||
|
||||
static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
|
||||
{
|
||||
@@ -1551,6 +1720,7 @@ static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
|
||||
mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
|
||||
mlxplat_led = &mlxplat_default_led_data;
|
||||
mlxplat_regs_io = &mlxplat_default_regs_io_data;
|
||||
+ mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0];
|
||||
|
||||
return 1;
|
||||
};
|
||||
@@ -1569,6 +1739,7 @@ static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi)
|
||||
mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
|
||||
mlxplat_led = &mlxplat_msn21xx_led_data;
|
||||
mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data;
|
||||
+ mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0];
|
||||
|
||||
return 1;
|
||||
};
|
||||
@@ -1587,6 +1758,7 @@ static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi)
|
||||
mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
|
||||
mlxplat_led = &mlxplat_default_led_data;
|
||||
mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data;
|
||||
+ mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0];
|
||||
|
||||
return 1;
|
||||
};
|
||||
@@ -1605,6 +1777,7 @@ static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi)
|
||||
mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
|
||||
mlxplat_led = &mlxplat_msn21xx_led_data;
|
||||
mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data;
|
||||
+ mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0];
|
||||
|
||||
return 1;
|
||||
};
|
||||
@@ -1624,6 +1797,8 @@ static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi)
|
||||
mlxplat_led = &mlxplat_default_ng_led_data;
|
||||
mlxplat_regs_io = &mlxplat_default_ng_regs_io_data;
|
||||
mlxplat_fan = &mlxplat_default_fan_data;
|
||||
+ for (i = 0; i < ARRAY_SIZE(mlxplat_mlxcpld_wd_set_type2); i++)
|
||||
+ mlxplat_wd_data[i] = &mlxplat_mlxcpld_wd_set_type2[i];
|
||||
|
||||
return 1;
|
||||
};
|
||||
@@ -1906,15 +2081,33 @@ static int __init mlxplat_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
+ /* Add WD drivers. */
|
||||
+ for (j = 0; j < MLXPLAT_CPLD_WD_MAX_DEVS; j++) {
|
||||
+ if (mlxplat_wd_data[j]) {
|
||||
+ mlxplat_wd_data[j]->regmap = mlxplat_hotplug->regmap;
|
||||
+ priv->pdev_wd[j] = platform_device_register_resndata(
|
||||
+ &mlxplat_dev->dev,
|
||||
+ "mlx-wdt", j, NULL, 0,
|
||||
+ mlxplat_wd_data[j],
|
||||
+ sizeof(*mlxplat_wd_data[j]));
|
||||
+ if (IS_ERR(priv->pdev_wd[j])) {
|
||||
+ err = PTR_ERR(priv->pdev_wd[j]);
|
||||
+ goto fail_platform_wd_register;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* Sync registers with hardware. */
|
||||
regcache_mark_dirty(mlxplat_hotplug->regmap);
|
||||
err = regcache_sync(mlxplat_hotplug->regmap);
|
||||
if (err)
|
||||
- goto fail_platform_fan_register;
|
||||
+ goto fail_platform_wd_register;
|
||||
|
||||
return 0;
|
||||
|
||||
-fail_platform_fan_register:
|
||||
+fail_platform_wd_register:
|
||||
+ while (--j >= 0)
|
||||
+ platform_device_unregister(priv->pdev_wd[j]);
|
||||
if (mlxplat_fan)
|
||||
platform_device_unregister(priv->pdev_fan);
|
||||
fail_platform_io_regs_register:
|
||||
@@ -1946,7 +2139,10 @@ static void __exit mlxplat_exit(void)
|
||||
platform_device_unregister(priv->pdev_io_regs);
|
||||
platform_device_unregister(priv->pdev_led);
|
||||
platform_device_unregister(priv->pdev_hotplug);
|
||||
-
|
||||
+ for (i = MLXPLAT_CPLD_WD_MAX_DEVS - 1; i >= 0 ; i--) {
|
||||
+ if (mlxplat_wd_data[i])
|
||||
+ platform_device_unregister(priv->pdev_wd[i]);
|
||||
+ }
|
||||
for (i = ARRAY_SIZE(mlxplat_mux_data) - 1; i >= 0 ; i--)
|
||||
platform_device_unregister(priv->pdev_mux[i]);
|
||||
|
||||
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
|
||||
index 3eb58cb..ada5a33 100644
|
||||
--- a/drivers/watchdog/Kconfig
|
||||
+++ b/drivers/watchdog/Kconfig
|
||||
@@ -141,6 +141,21 @@ config MENF21BMC_WATCHDOG
|
||||
This driver can also be built as a module. If so the module
|
||||
will be called menf21bmc_wdt.
|
||||
|
||||
+config MLX_WDT
|
||||
+ tristate "Mellanox Watchdog"
|
||||
+ select WATCHDOG_CORE
|
||||
+ select REGMAP
|
||||
+ ---help---
|
||||
+ This is the driver for the hardware watchdog on Mellanox systems.
|
||||
+ If you are going to use it, say Y here, otherwise N.
|
||||
+ This driver can be used together with the watchdog daemon.
|
||||
+ It can also watch your kernel to make sure it doesn't freeze,
|
||||
+ and if it does, it reboots your system after a certain amount of
|
||||
+ time.
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the
|
||||
+ module will be called mlx-wdt.
|
||||
+
|
||||
config TANGOX_WATCHDOG
|
||||
tristate "Sigma Designs SMP86xx/SMP87xx watchdog"
|
||||
select WATCHDOG_CORE
|
||||
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
|
||||
index caa9f4a..50494df 100644
|
||||
--- a/drivers/watchdog/Makefile
|
||||
+++ b/drivers/watchdog/Makefile
|
||||
@@ -139,6 +139,7 @@ obj-$(CONFIG_INTEL_SCU_WATCHDOG) += intel_scu_watchdog.o
|
||||
obj-$(CONFIG_INTEL_MID_WATCHDOG) += intel-mid_wdt.o
|
||||
obj-$(CONFIG_INTEL_MEI_WDT) += mei_wdt.o
|
||||
obj-$(CONFIG_NI903X_WDT) += ni903x_wdt.o
|
||||
+obj-$(CONFIG_MLX_WDT) += mlx_wdt.o
|
||||
|
||||
# M32R Architecture
|
||||
|
||||
diff --git a/drivers/watchdog/mlx_wdt.c b/drivers/watchdog/mlx_wdt.c
|
||||
new file mode 100644
|
||||
index 0000000..7effe8c
|
||||
--- /dev/null
|
||||
+++ b/drivers/watchdog/mlx_wdt.c
|
||||
@@ -0,0 +1,391 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0+
|
||||
+/*
|
||||
+ * Mellanox watchdog driver
|
||||
+ *
|
||||
+ * Copyright (C) 2018 Mellanox Technologies
|
||||
+ * Copyright (C) 2018 Michael Shych <mshych@mellanox.com>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/bitops.h>
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/log2.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/platform_data/mlxreg.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <linux/spinlock.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/watchdog.h>
|
||||
+
|
||||
+#define MLXREG_WDT_CLOCK_SCALE 1000
|
||||
+#define MLXREG_WDT_MAX_TIMEOUT_TYPE1 32
|
||||
+#define MLXREG_WDT_MAX_TIMEOUT_TYPE2 255
|
||||
+#define MLXREG_WDT_MIN_TIMEOUT 1
|
||||
+#define MLXREG_WDT_HW_TIMEOUT_CONVERT(hw_timeout) ((1 << (hw_timeout)) \
|
||||
+ / MLXREG_WDT_CLOCK_SCALE)
|
||||
+
|
||||
+/**
|
||||
+ * enum mlxreg_wdt_type - type of HW watchdog
|
||||
+ *
|
||||
+ * TYPE1 can be differentiated by different register/mask
|
||||
+ * for WD action set and ping.
|
||||
+ */
|
||||
+enum mlxreg_wdt_type {
|
||||
+ MLX_WDT_TYPE1,
|
||||
+ MLX_WDT_TYPE2,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct mlxreg_wdt - wd private data:
|
||||
+ *
|
||||
+ * @wdd: watchdog device;
|
||||
+ * @device: basic device;
|
||||
+ * @pdata: data received from platform driver;
|
||||
+ * @regmap: register map of parent device;
|
||||
+ * @timeout: defined timeout in sec.;
|
||||
+ * @hw_timeout: real timeout set in hw;
|
||||
+ * It will be roundup base of 2 in WD type 1,
|
||||
+ * in WD type 2 it will be same number of sec as timeout;
|
||||
+ * @action_idx: index for direct access to action register;
|
||||
+ * @timeout_idx:index for direct access to TO register;
|
||||
+ * @ping_idx: index for direct access to ping register;
|
||||
+ * @reset_idx: index for direct access to reset cause register;
|
||||
+ * @wd_type: watchdog HW type;
|
||||
+ * @hw_timeout: actual HW timeout;
|
||||
+ * @io_lock: spinlock for io access;
|
||||
+ */
|
||||
+struct mlxreg_wdt {
|
||||
+ struct watchdog_device wdd;
|
||||
+ struct mlxreg_core_platform_data *pdata;
|
||||
+ void *regmap;
|
||||
+ int action_idx;
|
||||
+ int timeout_idx;
|
||||
+ int ping_idx;
|
||||
+ int reset_idx;
|
||||
+ enum mlxreg_wdt_type wdt_type;
|
||||
+ u8 hw_timeout;
|
||||
+ spinlock_t io_lock; /* the lock for io operations */
|
||||
+};
|
||||
+
|
||||
+static int mlxreg_wdt_roundup_to_base_2(struct mlxreg_wdt *wdt, int timeout)
|
||||
+{
|
||||
+ timeout *= MLXREG_WDT_CLOCK_SCALE;
|
||||
+
|
||||
+ wdt->hw_timeout = order_base_2(timeout);
|
||||
+ dev_info(wdt->wdd.parent,
|
||||
+ "watchdog %s timeout %d was rounded up to %lu (msec)\n",
|
||||
+ wdt->wdd.info->identity, timeout, roundup_pow_of_two(timeout));
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static enum mlxreg_wdt_type
|
||||
+mlxreg_wdt_check_watchdog_type(struct mlxreg_wdt *wdt,
|
||||
+ struct mlxreg_core_platform_data *pdata)
|
||||
+{
|
||||
+ if ((pdata->data[wdt->action_idx].reg ==
|
||||
+ pdata->data[wdt->ping_idx].reg) &&
|
||||
+ (pdata->data[wdt->action_idx].mask ==
|
||||
+ pdata->data[wdt->ping_idx].mask))
|
||||
+ return MLX_WDT_TYPE2;
|
||||
+ else
|
||||
+ return MLX_WDT_TYPE1;
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_wdt_check_card_reset(struct mlxreg_wdt *wdt)
|
||||
+{
|
||||
+ struct mlxreg_core_data *reg_data;
|
||||
+ u32 regval;
|
||||
+ int rc;
|
||||
+
|
||||
+ if (wdt->reset_idx == -EINVAL)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!(wdt->wdd.info->options & WDIOF_CARDRESET))
|
||||
+ return 0;
|
||||
+
|
||||
+ spin_lock(&wdt->io_lock);
|
||||
+ reg_data = &wdt->pdata->data[wdt->reset_idx];
|
||||
+ rc = regmap_read(wdt->regmap, reg_data->reg, ®val);
|
||||
+ spin_unlock(&wdt->io_lock);
|
||||
+ if (rc)
|
||||
+ goto read_error;
|
||||
+
|
||||
+ if (regval & ~reg_data->mask) {
|
||||
+ wdt->wdd.bootstatus = WDIOF_CARDRESET;
|
||||
+ dev_info(wdt->wdd.parent,
|
||||
+ "watchdog previously reset the CPU\n");
|
||||
+ }
|
||||
+
|
||||
+read_error:
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_wdt_start(struct watchdog_device *wdd)
|
||||
+{
|
||||
+ struct mlxreg_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
+ struct mlxreg_core_data *reg_data = &wdt->pdata->data[wdt->action_idx];
|
||||
+ u32 regval;
|
||||
+ int rc;
|
||||
+
|
||||
+ spin_lock(&wdt->io_lock);
|
||||
+ rc = regmap_read(wdt->regmap, reg_data->reg, ®val);
|
||||
+ if (rc) {
|
||||
+ spin_unlock(&wdt->io_lock);
|
||||
+ goto read_error;
|
||||
+ }
|
||||
+
|
||||
+ regval = (regval & reg_data->mask) | BIT(reg_data->bit);
|
||||
+ rc = regmap_write(wdt->regmap, reg_data->reg, regval);
|
||||
+ spin_unlock(&wdt->io_lock);
|
||||
+ if (!rc) {
|
||||
+ set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
|
||||
+ dev_info(wdt->wdd.parent, "watchdog %s started\n",
|
||||
+ wdd->info->identity);
|
||||
+ }
|
||||
+
|
||||
+read_error:
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_wdt_stop(struct watchdog_device *wdd)
|
||||
+{
|
||||
+ struct mlxreg_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
+ struct mlxreg_core_data *reg_data = &wdt->pdata->data[wdt->action_idx];
|
||||
+ u32 regval;
|
||||
+ int rc;
|
||||
+
|
||||
+ spin_lock(&wdt->io_lock);
|
||||
+ rc = regmap_read(wdt->regmap, reg_data->reg, ®val);
|
||||
+ if (rc) {
|
||||
+ spin_unlock(&wdt->io_lock);
|
||||
+ goto read_error;
|
||||
+ }
|
||||
+
|
||||
+ regval = (regval & reg_data->mask) & ~BIT(reg_data->bit);
|
||||
+ rc = regmap_write(wdt->regmap, reg_data->reg, regval);
|
||||
+ spin_unlock(&wdt->io_lock);
|
||||
+ if (!rc)
|
||||
+ dev_info(wdt->wdd.parent, "watchdog %s stopped\n",
|
||||
+ wdd->info->identity);
|
||||
+
|
||||
+read_error:
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_wdt_ping(struct watchdog_device *wdd)
|
||||
+{
|
||||
+ struct mlxreg_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
+ struct mlxreg_core_data *reg_data = &wdt->pdata->data[wdt->ping_idx];
|
||||
+ u32 regval;
|
||||
+ int rc;
|
||||
+
|
||||
+ spin_lock(&wdt->io_lock);
|
||||
+ rc = regmap_read(wdt->regmap, reg_data->reg, ®val);
|
||||
+ if (rc)
|
||||
+ goto read_error;
|
||||
+
|
||||
+ regval = (regval & reg_data->mask) | BIT(reg_data->bit);
|
||||
+ rc = regmap_write(wdt->regmap, reg_data->reg, regval);
|
||||
+
|
||||
+read_error:
|
||||
+ spin_unlock(&wdt->io_lock);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_wdt_set_timeout(struct watchdog_device *wdd,
|
||||
+ unsigned int timeout)
|
||||
+{
|
||||
+ struct mlxreg_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
+ struct mlxreg_core_data *reg_data = &wdt->pdata->data[wdt->timeout_idx];
|
||||
+ u32 regval;
|
||||
+ int rc;
|
||||
+
|
||||
+ spin_lock(&wdt->io_lock);
|
||||
+
|
||||
+ if (wdt->wdt_type == MLX_WDT_TYPE1) {
|
||||
+ rc = regmap_read(wdt->regmap, reg_data->reg, ®val);
|
||||
+ if (rc)
|
||||
+ goto read_error;
|
||||
+ regval = (regval & reg_data->mask) | wdt->hw_timeout;
|
||||
+ } else {
|
||||
+ wdt->hw_timeout = timeout;
|
||||
+ regval = timeout;
|
||||
+ }
|
||||
+
|
||||
+ rc = regmap_write(wdt->regmap, reg_data->reg, regval);
|
||||
+
|
||||
+read_error:
|
||||
+ spin_unlock(&wdt->io_lock);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static unsigned int mlxreg_wdt_get_timeleft(struct watchdog_device *wdd)
|
||||
+{
|
||||
+ struct mlxreg_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
+ struct mlxreg_core_data *reg_data = &wdt->pdata->data[wdt->timeout_idx];
|
||||
+ u32 regval;
|
||||
+ int rc;
|
||||
+
|
||||
+ if (wdt->wdt_type == MLX_WDT_TYPE1)
|
||||
+ return 0;
|
||||
+
|
||||
+ spin_lock(&wdt->io_lock);
|
||||
+ rc = regmap_read(wdt->regmap, reg_data->reg, ®val);
|
||||
+ if (rc)
|
||||
+ rc = 0;
|
||||
+ else
|
||||
+ rc = regval;
|
||||
+
|
||||
+ spin_unlock(&wdt->io_lock);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static const struct watchdog_ops mlxreg_wdt_ops_type1 = {
|
||||
+ .start = mlxreg_wdt_start,
|
||||
+ .stop = mlxreg_wdt_stop,
|
||||
+ .ping = mlxreg_wdt_ping,
|
||||
+ .set_timeout = mlxreg_wdt_set_timeout,
|
||||
+ .owner = THIS_MODULE,
|
||||
+};
|
||||
+
|
||||
+static const struct watchdog_ops mlxreg_wdt_ops_type2 = {
|
||||
+ .start = mlxreg_wdt_start,
|
||||
+ .stop = mlxreg_wdt_stop,
|
||||
+ .ping = mlxreg_wdt_ping,
|
||||
+ .set_timeout = mlxreg_wdt_set_timeout,
|
||||
+ .get_timeleft = mlxreg_wdt_get_timeleft,
|
||||
+ .owner = THIS_MODULE,
|
||||
+};
|
||||
+
|
||||
+static const struct watchdog_info mlxreg_wdt_main_info = {
|
||||
+ .options = WDIOF_KEEPALIVEPING
|
||||
+ | WDIOF_MAGICCLOSE
|
||||
+ | WDIOF_SETTIMEOUT
|
||||
+ | WDIOF_CARDRESET,
|
||||
+ .identity = "mlx-wdt-main",
|
||||
+};
|
||||
+
|
||||
+static const struct watchdog_info mlxreg_wdt_aux_info = {
|
||||
+ .options = WDIOF_KEEPALIVEPING
|
||||
+ | WDIOF_MAGICCLOSE
|
||||
+ | WDIOF_SETTIMEOUT
|
||||
+ | WDIOF_ALARMONLY,
|
||||
+ .identity = "mlx-wdt-aux",
|
||||
+};
|
||||
+
|
||||
+static int mlxreg_wdt_config(struct mlxreg_wdt *wdt,
|
||||
+ struct mlxreg_core_platform_data *pdata)
|
||||
+{
|
||||
+ struct mlxreg_core_data *data = pdata->data;
|
||||
+ int i, timeout;
|
||||
+
|
||||
+ wdt->reset_idx = -EINVAL;
|
||||
+ for (i = 0; i < pdata->counter; i++, data++) {
|
||||
+ if (strnstr(data->label, "action", sizeof(data->label)))
|
||||
+ wdt->action_idx = i;
|
||||
+ else if (strnstr(data->label, "timeout", sizeof(data->label)))
|
||||
+ wdt->timeout_idx = i;
|
||||
+ else if (strnstr(data->label, "ping", sizeof(data->label)))
|
||||
+ wdt->ping_idx = i;
|
||||
+ else if (strnstr(data->label, "reset", sizeof(data->label)))
|
||||
+ wdt->reset_idx = i;
|
||||
+ }
|
||||
+
|
||||
+ wdt->pdata = pdata;
|
||||
+ if (strnstr(pdata->identity, mlxreg_wdt_main_info.identity,
|
||||
+ sizeof(mlxreg_wdt_main_info.identity)))
|
||||
+ wdt->wdd.info = &mlxreg_wdt_main_info;
|
||||
+ else
|
||||
+ wdt->wdd.info = &mlxreg_wdt_aux_info;
|
||||
+
|
||||
+ timeout = pdata->data[wdt->timeout_idx].health_cntr;
|
||||
+ wdt->wdt_type = mlxreg_wdt_check_watchdog_type(wdt, pdata);
|
||||
+ if (wdt->wdt_type == MLX_WDT_TYPE2) {
|
||||
+ wdt->hw_timeout = timeout;
|
||||
+ wdt->wdd.ops = &mlxreg_wdt_ops_type2;
|
||||
+ wdt->wdd.timeout = wdt->hw_timeout;
|
||||
+ wdt->wdd.max_timeout = MLXREG_WDT_MAX_TIMEOUT_TYPE2;
|
||||
+ } else {
|
||||
+ mlxreg_wdt_roundup_to_base_2(wdt, timeout);
|
||||
+ wdt->wdd.ops = &mlxreg_wdt_ops_type1;
|
||||
+ /* Rowndown to actual closest number of sec. */
|
||||
+ wdt->wdd.timeout =
|
||||
+ MLXREG_WDT_HW_TIMEOUT_CONVERT(wdt->hw_timeout);
|
||||
+ wdt->wdd.max_timeout = MLXREG_WDT_MAX_TIMEOUT_TYPE1;
|
||||
+ }
|
||||
+ wdt->wdd.min_timeout = MLXREG_WDT_MIN_TIMEOUT;
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_wdt_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mlxreg_core_platform_data *pdata;
|
||||
+ struct mlxreg_wdt *wdt;
|
||||
+ int rc;
|
||||
+
|
||||
+ pdata = dev_get_platdata(&pdev->dev);
|
||||
+ if (!pdata) {
|
||||
+ dev_err(&pdev->dev, "Failed to get platform data.\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
|
||||
+ if (!wdt)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ spin_lock_init(&wdt->io_lock);
|
||||
+
|
||||
+ wdt->wdd.parent = &pdev->dev;
|
||||
+ wdt->regmap = pdata->regmap;
|
||||
+ mlxreg_wdt_config(wdt, pdata);
|
||||
+
|
||||
+ if ((pdata->features & MLXREG_CORE_WD_FEATURE_NOSTOP_AFTER_START))
|
||||
+ watchdog_set_nowayout(&wdt->wdd, WATCHDOG_NOWAYOUT);
|
||||
+ watchdog_stop_on_reboot(&wdt->wdd);
|
||||
+ watchdog_init_timeout(&wdt->wdd, 0, &pdev->dev);
|
||||
+ watchdog_set_drvdata(&wdt->wdd, wdt);
|
||||
+
|
||||
+ mlxreg_wdt_check_card_reset(wdt);
|
||||
+ rc = devm_watchdog_register_device(&pdev->dev, &wdt->wdd);
|
||||
+ if (rc) {
|
||||
+ dev_err(&pdev->dev,
|
||||
+ "Cannot register watchdog device (err=%d)\n", rc);
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ mlxreg_wdt_set_timeout(&wdt->wdd, wdt->wdd.timeout);
|
||||
+ if ((pdata->features & MLXREG_CORE_WD_FEATURE_START_AT_BOOT))
|
||||
+ mlxreg_wdt_start(&wdt->wdd);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_wdt_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mlxreg_wdt *wdt = dev_get_platdata(&pdev->dev);
|
||||
+
|
||||
+ mlxreg_wdt_stop(&wdt->wdd);
|
||||
+ watchdog_unregister_device(&wdt->wdd);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver mlxreg_wdt_driver = {
|
||||
+ .probe = mlxreg_wdt_probe,
|
||||
+ .remove = mlxreg_wdt_remove,
|
||||
+ .driver = {
|
||||
+ .name = "mlx-wdt",
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(mlxreg_wdt_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Michael Shych <michaelsh@mellanox.com>");
|
||||
+MODULE_DESCRIPTION("Mellanox watchdog driver");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_ALIAS("platform:mlx-wdt");
|
||||
diff --git a/include/linux/platform_data/mlxreg.h b/include/linux/platform_data/mlxreg.h
|
||||
index 1b2f86f..4d70c00 100644
|
||||
--- a/include/linux/platform_data/mlxreg.h
|
||||
+++ b/include/linux/platform_data/mlxreg.h
|
||||
@@ -35,6 +35,8 @@
|
||||
#define __LINUX_PLATFORM_DATA_MLXREG_H
|
||||
|
||||
#define MLXREG_CORE_LABEL_MAX_SIZE 32
|
||||
+#define MLXREG_CORE_WD_FEATURE_NOSTOP_AFTER_START BIT(0)
|
||||
+#define MLXREG_CORE_WD_FEATURE_START_AT_BOOT BIT(1)
|
||||
|
||||
/**
|
||||
* struct mlxreg_hotplug_device - I2C device data:
|
||||
@@ -112,11 +114,15 @@ struct mlxreg_core_item {
|
||||
* @data: instance private data;
|
||||
* @regmap: register map of parent device;
|
||||
* @counter: number of instances;
|
||||
+ * @features: supported features of device;
|
||||
+ * @identity: device identity name;
|
||||
*/
|
||||
struct mlxreg_core_platform_data {
|
||||
struct mlxreg_core_data *data;
|
||||
void *regmap;
|
||||
int counter;
|
||||
+ u32 features;
|
||||
+ char identity[MLXREG_CORE_LABEL_MAX_SIZE];
|
||||
};
|
||||
|
||||
/**
|
||||
--
|
||||
2.1.4
|
||||
|
||||
@@ -19,6 +19,5 @@ driver-add-the-support-max6620.patch
|
||||
0016-qsfp_sysfs-Fix-dmidecode-call.patch
|
||||
0017-mlxsw-qsfp_sysfs-Support-extended-port-numbers-for-S.patch
|
||||
0018-mlxsw-thermal-monitoring-amendments.patch
|
||||
0019-watchdog-mlx-wdt-introduce-watchdog-driver-for-Mella.patch
|
||||
0020-mlxsw-qsfp_sysfs-Support-port-numbers-initialization.patch
|
||||
0021-mlxsw-Align-code-with-kernel-v-5.0.patch
|
||||
|
||||
Reference in New Issue
Block a user