mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-14 23:46:53 +07:00
platform/x86: mlx-platform: Add mlx-wdt platform driver activation
Add mlx-wdt platform driver activation. Watchdog driver uses the same regmap infrastructure as others Mellanox platform drivers. Specific registers description for watchdog platform data configuration are added to mlx-platform. There are the registers for watchdog timer manipulation, and action setting on watchdog timer expiration. The watchdog action function could be configured to perform one of the following: system reset, setting PWM to full speed or counter increment. Two types of watchdog devices are supported main and auxiliary. These devices are co-exist and each of them could be configured to handle the specific action. Signed-off-by: Michael Shych <michealsh@mellanox.com> Signed-off-by: Vadim Pasternak <vadimp@mellanox.com> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
This commit is contained in:
parent
584814af9f
commit
9b9f2f5416
@ -56,6 +56,16 @@
|
||||
#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_TLEFT_OFFSET 0xce
|
||||
#define MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET 0xcf
|
||||
#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_PWM1_OFFSET 0xe3
|
||||
#define MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET 0xe4
|
||||
#define MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET 0xe5
|
||||
@ -129,6 +139,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
|
||||
@ -136,6 +158,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;
|
||||
@ -144,6 +167,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 */
|
||||
@ -1351,6 +1375,148 @@ static struct mlxreg_core_platform_data mlxplat_default_fan_data = {
|
||||
.counter = ARRAY_SIZE(mlxplat_mlxcpld_default_fan_data),
|
||||
};
|
||||
|
||||
/* Watchdog type1: hardware implementation version1
|
||||
* (MSN2700, MSN2410, MSN2740, 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),
|
||||
.version = MLX_WDT_TYPE1,
|
||||
.identity = "mlx-wdt-main",
|
||||
},
|
||||
{
|
||||
.data = mlxplat_mlxcpld_wd_aux_regs_type1,
|
||||
.counter = ARRAY_SIZE(mlxplat_mlxcpld_wd_aux_regs_type1),
|
||||
.version = MLX_WDT_TYPE1,
|
||||
.identity = "mlx-wdt-aux",
|
||||
},
|
||||
};
|
||||
|
||||
/* Watchdog type2: hardware implementation version 2
|
||||
* (all systems except (MSN2700, MSN2410, MSN2740, MSN2100 and MSN2140).
|
||||
*/
|
||||
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 = "timeleft",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_WD2_TLEFT_OFFSET,
|
||||
.mask = MLXPLAT_CPLD_WD_TYPE2_TO_MASK,
|
||||
},
|
||||
{
|
||||
.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 = "timeleft",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET,
|
||||
.mask = MLXPLAT_CPLD_WD_TYPE2_TO_MASK,
|
||||
},
|
||||
{
|
||||
.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),
|
||||
.version = MLX_WDT_TYPE2,
|
||||
.identity = "mlx-wdt-main",
|
||||
},
|
||||
{
|
||||
.data = mlxplat_mlxcpld_wd_aux_regs_type2,
|
||||
.counter = ARRAY_SIZE(mlxplat_mlxcpld_wd_aux_regs_type2),
|
||||
.version = MLX_WDT_TYPE2,
|
||||
.identity = "mlx-wdt-aux",
|
||||
},
|
||||
};
|
||||
|
||||
static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
@ -1373,6 +1539,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;
|
||||
@ -1416,6 +1590,16 @@ 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_TLEFT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET:
|
||||
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_PWM1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET:
|
||||
@ -1473,6 +1657,10 @@ 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_WD2_TLEFT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET:
|
||||
@ -1500,6 +1688,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 {
|
||||
@ -1549,6 +1738,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)
|
||||
{
|
||||
@ -1564,6 +1755,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;
|
||||
};
|
||||
@ -1582,6 +1774,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;
|
||||
};
|
||||
@ -1600,6 +1793,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;
|
||||
};
|
||||
@ -1618,6 +1812,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;
|
||||
};
|
||||
@ -1637,6 +1832,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;
|
||||
};
|
||||
@ -1919,15 +2116,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:
|
||||
@ -1953,6 +2168,8 @@ static void __exit mlxplat_exit(void)
|
||||
struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev);
|
||||
int i;
|
||||
|
||||
for (i = MLXPLAT_CPLD_WD_MAX_DEVS - 1; i >= 0 ; i--)
|
||||
platform_device_unregister(priv->pdev_wd[i]);
|
||||
if (priv->pdev_fan)
|
||||
platform_device_unregister(priv->pdev_fan);
|
||||
if (priv->pdev_io_regs)
|
||||
|
Loading…
Reference in New Issue
Block a user