ocelot-reset.c (597473720f4dc69749542bfcfed4a927a43d935e) | ocelot-reset.c (ec871696b77767672cae1fe3158dbe1a86abcfdd) |
---|---|
1// SPDX-License-Identifier: (GPL-2.0 OR MIT) 2/* 3 * Microsemi MIPS SoC reset driver 4 * 5 * License: Dual MIT/GPL 6 * Copyright (c) 2017 Microsemi Corporation 7 */ 8#include <linux/delay.h> 9#include <linux/io.h> 10#include <linux/notifier.h> 11#include <linux/mfd/syscon.h> 12#include <linux/of_address.h> 13#include <linux/of_device.h> 14#include <linux/platform_device.h> 15#include <linux/reboot.h> 16#include <linux/regmap.h> 17 | 1// SPDX-License-Identifier: (GPL-2.0 OR MIT) 2/* 3 * Microsemi MIPS SoC reset driver 4 * 5 * License: Dual MIT/GPL 6 * Copyright (c) 2017 Microsemi Corporation 7 */ 8#include <linux/delay.h> 9#include <linux/io.h> 10#include <linux/notifier.h> 11#include <linux/mfd/syscon.h> 12#include <linux/of_address.h> 13#include <linux/of_device.h> 14#include <linux/platform_device.h> 15#include <linux/reboot.h> 16#include <linux/regmap.h> 17 |
18struct reset_props { 19 const char *syscon; 20 u32 protect_reg; 21 u32 vcore_protect; 22 u32 if_si_owner_bit; 23}; 24 |
|
18struct ocelot_reset_context { 19 void __iomem *base; 20 struct regmap *cpu_ctrl; | 25struct ocelot_reset_context { 26 void __iomem *base; 27 struct regmap *cpu_ctrl; |
28 const struct reset_props *props; |
|
21 struct notifier_block restart_handler; 22}; 23 | 29 struct notifier_block restart_handler; 30}; 31 |
24#define ICPU_CFG_CPU_SYSTEM_CTRL_RESET 0x20 25#define CORE_RST_PROTECT BIT(2) 26 | |
27#define SOFT_CHIP_RST BIT(0) 28 29#define ICPU_CFG_CPU_SYSTEM_CTRL_GENERAL_CTRL 0x24 30#define IF_SI_OWNER_MASK GENMASK(1, 0) 31#define IF_SI_OWNER_SISL 0 32#define IF_SI_OWNER_SIBM 1 33#define IF_SI_OWNER_SIMC 2 | 32#define SOFT_CHIP_RST BIT(0) 33 34#define ICPU_CFG_CPU_SYSTEM_CTRL_GENERAL_CTRL 0x24 35#define IF_SI_OWNER_MASK GENMASK(1, 0) 36#define IF_SI_OWNER_SISL 0 37#define IF_SI_OWNER_SIBM 1 38#define IF_SI_OWNER_SIMC 2 |
34#define IF_SI_OWNER_OFFSET 4 | |
35 36static int ocelot_restart_handle(struct notifier_block *this, 37 unsigned long mode, void *cmd) 38{ 39 struct ocelot_reset_context *ctx = container_of(this, struct 40 ocelot_reset_context, 41 restart_handler); | 39 40static int ocelot_restart_handle(struct notifier_block *this, 41 unsigned long mode, void *cmd) 42{ 43 struct ocelot_reset_context *ctx = container_of(this, struct 44 ocelot_reset_context, 45 restart_handler); |
46 u32 if_si_owner_bit = ctx->props->if_si_owner_bit; |
|
42 43 /* Make sure the core is not protected from reset */ | 47 48 /* Make sure the core is not protected from reset */ |
44 regmap_update_bits(ctx->cpu_ctrl, ICPU_CFG_CPU_SYSTEM_CTRL_RESET, 45 CORE_RST_PROTECT, 0); | 49 regmap_update_bits(ctx->cpu_ctrl, ctx->props->protect_reg, 50 ctx->props->vcore_protect, 0); |
46 47 /* Make the SI back to boot mode */ 48 regmap_update_bits(ctx->cpu_ctrl, ICPU_CFG_CPU_SYSTEM_CTRL_GENERAL_CTRL, | 51 52 /* Make the SI back to boot mode */ 53 regmap_update_bits(ctx->cpu_ctrl, ICPU_CFG_CPU_SYSTEM_CTRL_GENERAL_CTRL, |
49 IF_SI_OWNER_MASK << IF_SI_OWNER_OFFSET, 50 IF_SI_OWNER_SIBM << IF_SI_OWNER_OFFSET); | 54 IF_SI_OWNER_MASK << if_si_owner_bit, 55 IF_SI_OWNER_SIBM << if_si_owner_bit); |
51 | 56 |
57 pr_emerg("Resetting SoC\n"); 58 |
|
52 writel(SOFT_CHIP_RST, ctx->base); 53 54 pr_emerg("Unable to restart system\n"); 55 return NOTIFY_DONE; 56} 57 58static int ocelot_reset_probe(struct platform_device *pdev) 59{ --- 7 unchanged lines hidden (view full) --- 67 if (!ctx) 68 return -ENOMEM; 69 70 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 71 ctx->base = devm_ioremap_resource(dev, res); 72 if (IS_ERR(ctx->base)) 73 return PTR_ERR(ctx->base); 74 | 59 writel(SOFT_CHIP_RST, ctx->base); 60 61 pr_emerg("Unable to restart system\n"); 62 return NOTIFY_DONE; 63} 64 65static int ocelot_reset_probe(struct platform_device *pdev) 66{ --- 7 unchanged lines hidden (view full) --- 74 if (!ctx) 75 return -ENOMEM; 76 77 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 78 ctx->base = devm_ioremap_resource(dev, res); 79 if (IS_ERR(ctx->base)) 80 return PTR_ERR(ctx->base); 81 |
75 ctx->cpu_ctrl = syscon_regmap_lookup_by_compatible("mscc,ocelot-cpu-syscon"); 76 if (IS_ERR(ctx->cpu_ctrl)) | 82 ctx->props = device_get_match_data(dev); 83 84 ctx->cpu_ctrl = syscon_regmap_lookup_by_compatible(ctx->props->syscon); 85 if (IS_ERR(ctx->cpu_ctrl)) { 86 dev_err(dev, "No syscon map: %s\n", ctx->props->syscon); |
77 return PTR_ERR(ctx->cpu_ctrl); | 87 return PTR_ERR(ctx->cpu_ctrl); |
88 } |
|
78 79 ctx->restart_handler.notifier_call = ocelot_restart_handle; 80 ctx->restart_handler.priority = 192; 81 err = register_restart_handler(&ctx->restart_handler); 82 if (err) 83 dev_err(dev, "can't register restart notifier (err=%d)\n", err); 84 85 return err; 86} 87 | 89 90 ctx->restart_handler.notifier_call = ocelot_restart_handle; 91 ctx->restart_handler.priority = 192; 92 err = register_restart_handler(&ctx->restart_handler); 93 if (err) 94 dev_err(dev, "can't register restart notifier (err=%d)\n", err); 95 96 return err; 97} 98 |
99static const struct reset_props reset_props_ocelot = { 100 .syscon = "mscc,ocelot-cpu-syscon", 101 .protect_reg = 0x20, 102 .vcore_protect = BIT(2), 103 .if_si_owner_bit = 4, 104}; 105 106static const struct reset_props reset_props_sparx5 = { 107 .syscon = "microchip,sparx5-cpu-syscon", 108 .protect_reg = 0x84, 109 .vcore_protect = BIT(10), 110 .if_si_owner_bit = 6, 111}; 112 |
|
88static const struct of_device_id ocelot_reset_of_match[] = { | 113static const struct of_device_id ocelot_reset_of_match[] = { |
89 { .compatible = "mscc,ocelot-chip-reset" }, 90 {} | 114 { 115 .compatible = "mscc,ocelot-chip-reset", 116 .data = &reset_props_ocelot 117 }, { 118 .compatible = "microchip,sparx5-chip-reset", 119 .data = &reset_props_sparx5 120 }, 121 { /*sentinel*/ } |
91}; 92 93static struct platform_driver ocelot_reset_driver = { 94 .probe = ocelot_reset_probe, 95 .driver = { 96 .name = "ocelot-chip-reset", 97 .of_match_table = ocelot_reset_of_match, 98 }, 99}; 100builtin_platform_driver(ocelot_reset_driver); | 122}; 123 124static struct platform_driver ocelot_reset_driver = { 125 .probe = ocelot_reset_probe, 126 .driver = { 127 .name = "ocelot-chip-reset", 128 .of_match_table = ocelot_reset_of_match, 129 }, 130}; 131builtin_platform_driver(ocelot_reset_driver); |