ocelot-reset.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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. struct ocelot_reset_context {
  18. void __iomem *base;
  19. struct regmap *cpu_ctrl;
  20. struct notifier_block restart_handler;
  21. };
  22. #define ICPU_CFG_CPU_SYSTEM_CTRL_RESET 0x20
  23. #define CORE_RST_PROTECT BIT(2)
  24. #define SOFT_CHIP_RST BIT(0)
  25. static int ocelot_restart_handle(struct notifier_block *this,
  26. unsigned long mode, void *cmd)
  27. {
  28. struct ocelot_reset_context *ctx = container_of(this, struct
  29. ocelot_reset_context,
  30. restart_handler);
  31. /* Make sure the core is not protected from reset */
  32. regmap_update_bits(ctx->cpu_ctrl, ICPU_CFG_CPU_SYSTEM_CTRL_RESET,
  33. CORE_RST_PROTECT, 0);
  34. writel(SOFT_CHIP_RST, ctx->base);
  35. pr_emerg("Unable to restart system\n");
  36. return NOTIFY_DONE;
  37. }
  38. static int ocelot_reset_probe(struct platform_device *pdev)
  39. {
  40. struct ocelot_reset_context *ctx;
  41. struct resource *res;
  42. struct device *dev = &pdev->dev;
  43. int err;
  44. ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
  45. if (!ctx)
  46. return -ENOMEM;
  47. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  48. ctx->base = devm_ioremap_resource(dev, res);
  49. if (IS_ERR(ctx->base))
  50. return PTR_ERR(ctx->base);
  51. ctx->cpu_ctrl = syscon_regmap_lookup_by_compatible("mscc,ocelot-cpu-syscon");
  52. if (IS_ERR(ctx->cpu_ctrl))
  53. return PTR_ERR(ctx->cpu_ctrl);
  54. ctx->restart_handler.notifier_call = ocelot_restart_handle;
  55. ctx->restart_handler.priority = 192;
  56. err = register_restart_handler(&ctx->restart_handler);
  57. if (err)
  58. dev_err(dev, "can't register restart notifier (err=%d)\n", err);
  59. return err;
  60. }
  61. static const struct of_device_id ocelot_reset_of_match[] = {
  62. { .compatible = "mscc,ocelot-chip-reset" },
  63. {}
  64. };
  65. static struct platform_driver ocelot_reset_driver = {
  66. .probe = ocelot_reset_probe,
  67. .driver = {
  68. .name = "ocelot-chip-reset",
  69. .of_match_table = ocelot_reset_of_match,
  70. },
  71. };
  72. builtin_platform_driver(ocelot_reset_driver);