diff options
-rw-r--r-- | drivers/power/reset/Kconfig | 3 | ||||
-rw-r--r-- | drivers/power/reset/ocelot-reset.c | 55 |
2 files changed, 44 insertions, 14 deletions
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index 0a1fb5c74f83..6361569aacb7 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -129,10 +129,9 @@ config POWER_RESET_QCOM_PON config POWER_RESET_OCELOT_RESET bool "Microsemi Ocelot reset driver" - depends on MSCC_OCELOT || COMPILE_TEST select MFD_SYSCON help - This driver supports restart for Microsemi Ocelot SoC. + This driver supports restart for Microsemi Ocelot SoC and similar. config POWER_RESET_OXNAS bool "OXNAS SoC restart driver" diff --git a/drivers/power/reset/ocelot-reset.c b/drivers/power/reset/ocelot-reset.c index 419952c61fd0..f74e1dbb4ba3 100644 --- a/drivers/power/reset/ocelot-reset.c +++ b/drivers/power/reset/ocelot-reset.c @@ -15,15 +15,20 @@ #include <linux/reboot.h> #include <linux/regmap.h> +struct reset_props { + const char *syscon; + u32 protect_reg; + u32 vcore_protect; + u32 if_si_owner_bit; +}; + struct ocelot_reset_context { void __iomem *base; struct regmap *cpu_ctrl; + const struct reset_props *props; struct notifier_block restart_handler; }; -#define ICPU_CFG_CPU_SYSTEM_CTRL_RESET 0x20 -#define CORE_RST_PROTECT BIT(2) - #define SOFT_CHIP_RST BIT(0) #define ICPU_CFG_CPU_SYSTEM_CTRL_GENERAL_CTRL 0x24 @@ -31,7 +36,6 @@ struct ocelot_reset_context { #define IF_SI_OWNER_SISL 0 #define IF_SI_OWNER_SIBM 1 #define IF_SI_OWNER_SIMC 2 -#define IF_SI_OWNER_OFFSET 4 static int ocelot_restart_handle(struct notifier_block *this, unsigned long mode, void *cmd) @@ -39,15 +43,18 @@ static int ocelot_restart_handle(struct notifier_block *this, struct ocelot_reset_context *ctx = container_of(this, struct ocelot_reset_context, restart_handler); + u32 if_si_owner_bit = ctx->props->if_si_owner_bit; /* Make sure the core is not protected from reset */ - regmap_update_bits(ctx->cpu_ctrl, ICPU_CFG_CPU_SYSTEM_CTRL_RESET, - CORE_RST_PROTECT, 0); + regmap_update_bits(ctx->cpu_ctrl, ctx->props->protect_reg, + ctx->props->vcore_protect, 0); /* Make the SI back to boot mode */ regmap_update_bits(ctx->cpu_ctrl, ICPU_CFG_CPU_SYSTEM_CTRL_GENERAL_CTRL, - IF_SI_OWNER_MASK << IF_SI_OWNER_OFFSET, - IF_SI_OWNER_SIBM << IF_SI_OWNER_OFFSET); + IF_SI_OWNER_MASK << if_si_owner_bit, + IF_SI_OWNER_SIBM << if_si_owner_bit); + + pr_emerg("Resetting SoC\n"); writel(SOFT_CHIP_RST, ctx->base); @@ -72,9 +79,13 @@ static int ocelot_reset_probe(struct platform_device *pdev) if (IS_ERR(ctx->base)) return PTR_ERR(ctx->base); - ctx->cpu_ctrl = syscon_regmap_lookup_by_compatible("mscc,ocelot-cpu-syscon"); - if (IS_ERR(ctx->cpu_ctrl)) + ctx->props = device_get_match_data(dev); + + ctx->cpu_ctrl = syscon_regmap_lookup_by_compatible(ctx->props->syscon); + if (IS_ERR(ctx->cpu_ctrl)) { + dev_err(dev, "No syscon map: %s\n", ctx->props->syscon); return PTR_ERR(ctx->cpu_ctrl); + } ctx->restart_handler.notifier_call = ocelot_restart_handle; ctx->restart_handler.priority = 192; @@ -85,9 +96,29 @@ static int ocelot_reset_probe(struct platform_device *pdev) return err; } +static const struct reset_props reset_props_ocelot = { + .syscon = "mscc,ocelot-cpu-syscon", + .protect_reg = 0x20, + .vcore_protect = BIT(2), + .if_si_owner_bit = 4, +}; + +static const struct reset_props reset_props_sparx5 = { + .syscon = "microchip,sparx5-cpu-syscon", + .protect_reg = 0x84, + .vcore_protect = BIT(10), + .if_si_owner_bit = 6, +}; + static const struct of_device_id ocelot_reset_of_match[] = { - { .compatible = "mscc,ocelot-chip-reset" }, - {} + { + .compatible = "mscc,ocelot-chip-reset", + .data = &reset_props_ocelot + }, { + .compatible = "microchip,sparx5-chip-reset", + .data = &reset_props_sparx5 + }, + { /*sentinel*/ } }; static struct platform_driver ocelot_reset_driver = { |