linux/drivers/power/reset/xgene-reboot.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * AppliedMicro X-Gene SoC Reboot Driver
   4 *
   5 * Copyright (c) 2013, Applied Micro Circuits Corporation
   6 * Author: Feng Kan <fkan@apm.com>
   7 * Author: Loc Ho <lho@apm.com>
   8 *
   9 * This driver provides system reboot functionality for APM X-Gene SoC.
  10 * For system shutdown, this is board specify. If a board designer
  11 * implements GPIO shutdown, use the gpio-poweroff.c driver.
  12 */
  13#include <linux/delay.h>
  14#include <linux/io.h>
  15#include <linux/notifier.h>
  16#include <linux/of_device.h>
  17#include <linux/of_address.h>
  18#include <linux/platform_device.h>
  19#include <linux/reboot.h>
  20#include <linux/stat.h>
  21#include <linux/slab.h>
  22
  23struct xgene_reboot_context {
  24        struct device *dev;
  25        void *csr;
  26        u32 mask;
  27        struct notifier_block restart_handler;
  28};
  29
  30static int xgene_restart_handler(struct notifier_block *this,
  31                                 unsigned long mode, void *cmd)
  32{
  33        struct xgene_reboot_context *ctx =
  34                container_of(this, struct xgene_reboot_context,
  35                             restart_handler);
  36
  37        /* Issue the reboot */
  38        writel(ctx->mask, ctx->csr);
  39
  40        mdelay(1000);
  41
  42        dev_emerg(ctx->dev, "Unable to restart system\n");
  43
  44        return NOTIFY_DONE;
  45}
  46
  47static int xgene_reboot_probe(struct platform_device *pdev)
  48{
  49        struct xgene_reboot_context *ctx;
  50        struct device *dev = &pdev->dev;
  51        int err;
  52
  53        ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
  54        if (!ctx)
  55                return -ENOMEM;
  56
  57        ctx->csr = of_iomap(dev->of_node, 0);
  58        if (!ctx->csr) {
  59                dev_err(dev, "can not map resource\n");
  60                return -ENODEV;
  61        }
  62
  63        if (of_property_read_u32(dev->of_node, "mask", &ctx->mask))
  64                ctx->mask = 0xFFFFFFFF;
  65
  66        ctx->dev = dev;
  67        ctx->restart_handler.notifier_call = xgene_restart_handler;
  68        ctx->restart_handler.priority = 128;
  69        err = register_restart_handler(&ctx->restart_handler);
  70        if (err) {
  71                iounmap(ctx->csr);
  72                dev_err(dev, "cannot register restart handler (err=%d)\n", err);
  73        }
  74
  75        return err;
  76}
  77
  78static const struct of_device_id xgene_reboot_of_match[] = {
  79        { .compatible = "apm,xgene-reboot" },
  80        {}
  81};
  82
  83static struct platform_driver xgene_reboot_driver = {
  84        .probe = xgene_reboot_probe,
  85        .driver = {
  86                .name = "xgene-reboot",
  87                .of_match_table = xgene_reboot_of_match,
  88        },
  89};
  90
  91static int __init xgene_reboot_init(void)
  92{
  93        return platform_driver_register(&xgene_reboot_driver);
  94}
  95device_initcall(xgene_reboot_init);
  96