root/drivers/power/reset/ocelot-reset.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ocelot_restart_handle
  2. ocelot_reset_probe

   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 
  18 struct ocelot_reset_context {
  19         void __iomem *base;
  20         struct regmap *cpu_ctrl;
  21         struct notifier_block restart_handler;
  22 };
  23 
  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
  34 #define IF_SI_OWNER_OFFSET                      4
  35 
  36 static 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);
  42 
  43         /* 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);
  46 
  47         /* Make the SI back to boot mode */
  48         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);
  51 
  52         writel(SOFT_CHIP_RST, ctx->base);
  53 
  54         pr_emerg("Unable to restart system\n");
  55         return NOTIFY_DONE;
  56 }
  57 
  58 static int ocelot_reset_probe(struct platform_device *pdev)
  59 {
  60         struct ocelot_reset_context *ctx;
  61         struct resource *res;
  62 
  63         struct device *dev = &pdev->dev;
  64         int err;
  65 
  66         ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
  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 
  75         ctx->cpu_ctrl = syscon_regmap_lookup_by_compatible("mscc,ocelot-cpu-syscon");
  76         if (IS_ERR(ctx->cpu_ctrl))
  77                 return PTR_ERR(ctx->cpu_ctrl);
  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 
  88 static const struct of_device_id ocelot_reset_of_match[] = {
  89         { .compatible = "mscc,ocelot-chip-reset" },
  90         {}
  91 };
  92 
  93 static 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 };
 100 builtin_platform_driver(ocelot_reset_driver);

/* [<][>][^][v][top][bottom][index][help] */