Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * AppliedMicro X-Gene SoC Reboot Driver
0004  *
0005  * Copyright (c) 2013, Applied Micro Circuits Corporation
0006  * Author: Feng Kan <fkan@apm.com>
0007  * Author: Loc Ho <lho@apm.com>
0008  *
0009  * This driver provides system reboot functionality for APM X-Gene SoC.
0010  * For system shutdown, this is board specify. If a board designer
0011  * implements GPIO shutdown, use the gpio-poweroff.c driver.
0012  */
0013 #include <linux/delay.h>
0014 #include <linux/io.h>
0015 #include <linux/notifier.h>
0016 #include <linux/of_device.h>
0017 #include <linux/of_address.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/reboot.h>
0020 #include <linux/stat.h>
0021 #include <linux/slab.h>
0022 
0023 struct xgene_reboot_context {
0024     struct device *dev;
0025     void *csr;
0026     u32 mask;
0027     struct notifier_block restart_handler;
0028 };
0029 
0030 static int xgene_restart_handler(struct notifier_block *this,
0031                  unsigned long mode, void *cmd)
0032 {
0033     struct xgene_reboot_context *ctx =
0034         container_of(this, struct xgene_reboot_context,
0035                  restart_handler);
0036 
0037     /* Issue the reboot */
0038     writel(ctx->mask, ctx->csr);
0039 
0040     mdelay(1000);
0041 
0042     dev_emerg(ctx->dev, "Unable to restart system\n");
0043 
0044     return NOTIFY_DONE;
0045 }
0046 
0047 static int xgene_reboot_probe(struct platform_device *pdev)
0048 {
0049     struct xgene_reboot_context *ctx;
0050     struct device *dev = &pdev->dev;
0051     int err;
0052 
0053     ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
0054     if (!ctx)
0055         return -ENOMEM;
0056 
0057     ctx->csr = of_iomap(dev->of_node, 0);
0058     if (!ctx->csr) {
0059         dev_err(dev, "can not map resource\n");
0060         return -ENODEV;
0061     }
0062 
0063     if (of_property_read_u32(dev->of_node, "mask", &ctx->mask))
0064         ctx->mask = 0xFFFFFFFF;
0065 
0066     ctx->dev = dev;
0067     ctx->restart_handler.notifier_call = xgene_restart_handler;
0068     ctx->restart_handler.priority = 128;
0069     err = register_restart_handler(&ctx->restart_handler);
0070     if (err) {
0071         iounmap(ctx->csr);
0072         dev_err(dev, "cannot register restart handler (err=%d)\n", err);
0073     }
0074 
0075     return err;
0076 }
0077 
0078 static const struct of_device_id xgene_reboot_of_match[] = {
0079     { .compatible = "apm,xgene-reboot" },
0080     {}
0081 };
0082 
0083 static struct platform_driver xgene_reboot_driver = {
0084     .probe = xgene_reboot_probe,
0085     .driver = {
0086         .name = "xgene-reboot",
0087         .of_match_table = xgene_reboot_of_match,
0088     },
0089 };
0090 
0091 static int __init xgene_reboot_init(void)
0092 {
0093     return platform_driver_register(&xgene_reboot_driver);
0094 }
0095 device_initcall(xgene_reboot_init);