On Mon, 14 Aug 2023, Vadim Pasternak wrote: > On L1 switches reset should include special actions against CPLD device > for performing graceful operations. > For that purpose, special PLATFORM_RESET# signal should be indicated. > > Signed-off-by: Vadim Pasternak <vadimp@xxxxxxxxxx> > Reviewed-by: Michael Shych <michaelsh@xxxxxxxxxx> > --- > drivers/platform/x86/mlx-platform.c | 45 +++++++++++++++++++++++++++-- > 1 file changed, 43 insertions(+), 2 deletions(-) > > diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c > index 1010064d54e9..b577ce572ab1 100644 > --- a/drivers/platform/x86/mlx-platform.c > +++ b/drivers/platform/x86/mlx-platform.c > @@ -35,6 +35,7 @@ > #define MLXPLAT_CPLD_LPC_REG_CPLD3_PN1_OFFSET 0x09 > #define MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET 0x0a > #define MLXPLAT_CPLD_LPC_REG_CPLD4_PN1_OFFSET 0x0b > +#define MLXPLAT_CPLD_LPC_REG_RESET_GP1_OFFSET 0x17 > #define MLXPLAT_CPLD_LPC_REG_RESET_GP2_OFFSET 0x19 > #define MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET 0x1c > #define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET 0x1d > @@ -265,6 +266,7 @@ > #define MLXPLAT_CPLD_LPC_LC_MASK GENMASK(7, 0) > > #define MLXPLAT_CPLD_HALT_MASK BIT(3) > +#define MLXPLAT_CPLD_RESET_MASK 0xfe GENMASK() > /* Default I2C parent bus number */ > #define MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR 1 > @@ -441,6 +443,7 @@ static struct i2c_mux_reg_platform_data mlxplat_default_mux_data[] = { > static int mlxplat_max_adap_num; > static int mlxplat_mux_num; > static struct i2c_mux_reg_platform_data *mlxplat_mux_data; > +static struct notifier_block *mlxplat_reboot_nb; > > /* Platform extended mux data */ > static struct i2c_mux_reg_platform_data mlxplat_extended_mux_data[] = { > @@ -2361,8 +2364,11 @@ static int > mlxplat_mlxcpld_l1_switch_pwr_events_handler(void *handle, enum mlxreg_hotplug_kind kind, > u8 action) > { > - dev_info(&mlxplat_dev->dev, "System shutdown due to short press of power button"); > - kernel_power_off(); > + if (action) { > + dev_info(&mlxplat_dev->dev, "System shutdown due to short press of power button"); > + kernel_power_off(); > + } > + > return 0; > } > > @@ -4957,6 +4963,7 @@ static struct mlxreg_core_platform_data mlxplat_mlxcpld_wd_set_type3[] = { > static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) > { > switch (reg) { > + case MLXPLAT_CPLD_LPC_REG_RESET_GP1_OFFSET: > case MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET: > case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: > case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: > @@ -5065,6 +5072,7 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) > case MLXPLAT_CPLD_LPC_REG_CPLD4_PN1_OFFSET: > case MLXPLAT_CPLD_LPC_REG_CPLD5_PN_OFFSET: > case MLXPLAT_CPLD_LPC_REG_CPLD5_PN1_OFFSET: > + case MLXPLAT_CPLD_LPC_REG_RESET_GP1_OFFSET: > case MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET: > case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: > case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET: > @@ -5229,6 +5237,7 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) > case MLXPLAT_CPLD_LPC_REG_CPLD4_PN1_OFFSET: > case MLXPLAT_CPLD_LPC_REG_CPLD5_PN_OFFSET: > case MLXPLAT_CPLD_LPC_REG_CPLD5_PN1_OFFSET: > + case MLXPLAT_CPLD_LPC_REG_RESET_GP1_OFFSET: > case MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET: > case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: > case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET: > @@ -5533,11 +5542,33 @@ static struct mlxreg_core_platform_data > *mlxplat_wd_data[MLXPLAT_CPLD_WD_MAX_DEVS]; > static const struct regmap_config *mlxplat_regmap_config; > > +/* Platform default reset function */ > +static int mlxplat_reboot_notifier(struct notifier_block *nb, unsigned long action, void *unused) > +{ > + struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev); > + u32 regval; > + int ret; > + > + ret = regmap_read(priv->regmap, MLXPLAT_CPLD_LPC_REG_RESET_GP1_OFFSET, ®val); > + > + if (action == SYS_RESTART && !ret && regval & BIT(0)) Use a named define instead of BIT(0) here. -- i. > + regmap_write(priv->regmap, MLXPLAT_CPLD_LPC_REG_RESET_GP1_OFFSET, > + MLXPLAT_CPLD_RESET_MASK); > + > + return NOTIFY_DONE; > +} > + > +static struct notifier_block mlxplat_reboot_default_nb = { > + .notifier_call = mlxplat_reboot_notifier, > +}; > + > /* Platform default poweroff function */ > static void mlxplat_poweroff(void) > { > struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev); > > + if (mlxplat_reboot_nb) > + unregister_reboot_notifier(mlxplat_reboot_nb); > regmap_write(priv->regmap, MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, MLXPLAT_CPLD_HALT_MASK); > kernel_halt(); > } > @@ -5861,6 +5892,7 @@ static int __init mlxplat_dmi_l1_switch_matched(const struct dmi_system_id *dmi) > mlxplat_i2c = &mlxplat_mlxcpld_i2c_ng_data; > mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config_rack_switch; > pm_power_off = mlxplat_poweroff; > + mlxplat_reboot_nb = &mlxplat_reboot_default_nb; > > return 1; > } > @@ -6410,8 +6442,15 @@ static int __init mlxplat_init(void) > if (err) > goto fail_regcache_sync; > > + if (mlxplat_reboot_nb) { > + err = register_reboot_notifier(mlxplat_reboot_nb); > + if (err) > + goto fail_register_reboot_notifier; > + } > + > return 0; > > +fail_register_reboot_notifier: > fail_regcache_sync: > mlxplat_pre_exit(priv); > fail_mlxplat_i2c_main_init: > @@ -6429,6 +6468,8 @@ static void __exit mlxplat_exit(void) > > if (pm_power_off) > pm_power_off = NULL; > + if (mlxplat_reboot_nb) > + unregister_reboot_notifier(mlxplat_reboot_nb); > mlxplat_pre_exit(priv); > mlxplat_i2c_main_exit(priv); > mlxplat_post_exit(); >