blob: 0b0d2fd2bd0cb145dc35ee2092ad7ace0a6ac28d [file] [log] [blame]
Thomas Gleixner1a59d1b82019-05-27 08:55:05 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Loc Ho67778e0e2013-07-02 14:38:58 -06002/*
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 *
Loc Ho67778e0e2013-07-02 14:38:58 -06009 * 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 */
Guenter Roeck745e19762014-09-30 10:48:31 -070013#include <linux/delay.h>
Loc Ho67778e0e2013-07-02 14:38:58 -060014#include <linux/io.h>
Guenter Roeck8f57f232014-09-30 10:48:32 -070015#include <linux/notifier.h>
Loc Ho67778e0e2013-07-02 14:38:58 -060016#include <linux/of_device.h>
17#include <linux/of_address.h>
18#include <linux/platform_device.h>
Guenter Roeck8f57f232014-09-30 10:48:32 -070019#include <linux/reboot.h>
Loc Ho67778e0e2013-07-02 14:38:58 -060020#include <linux/stat.h>
21#include <linux/slab.h>
Loc Ho67778e0e2013-07-02 14:38:58 -060022
23struct xgene_reboot_context {
Guenter Roeck43160712014-09-30 10:48:30 -070024 struct device *dev;
Loc Ho67778e0e2013-07-02 14:38:58 -060025 void *csr;
26 u32 mask;
Guenter Roeck8f57f232014-09-30 10:48:32 -070027 struct notifier_block restart_handler;
Loc Ho67778e0e2013-07-02 14:38:58 -060028};
29
Guenter Roeck8f57f232014-09-30 10:48:32 -070030static int xgene_restart_handler(struct notifier_block *this,
31 unsigned long mode, void *cmd)
Loc Ho67778e0e2013-07-02 14:38:58 -060032{
Guenter Roeck8f57f232014-09-30 10:48:32 -070033 struct xgene_reboot_context *ctx =
34 container_of(this, struct xgene_reboot_context,
35 restart_handler);
Loc Ho67778e0e2013-07-02 14:38:58 -060036
37 /* Issue the reboot */
Guenter Roeck8f57f232014-09-30 10:48:32 -070038 writel(ctx->mask, ctx->csr);
Loc Ho67778e0e2013-07-02 14:38:58 -060039
Guenter Roeck745e19762014-09-30 10:48:31 -070040 mdelay(1000);
Loc Ho67778e0e2013-07-02 14:38:58 -060041
Guenter Roeck43160712014-09-30 10:48:30 -070042 dev_emerg(ctx->dev, "Unable to restart system\n");
Guenter Roeck8f57f232014-09-30 10:48:32 -070043
44 return NOTIFY_DONE;
Loc Ho67778e0e2013-07-02 14:38:58 -060045}
46
47static int xgene_reboot_probe(struct platform_device *pdev)
48{
49 struct xgene_reboot_context *ctx;
Guenter Roeck43160712014-09-30 10:48:30 -070050 struct device *dev = &pdev->dev;
Guenter Roeck8f57f232014-09-30 10:48:32 -070051 int err;
Loc Ho67778e0e2013-07-02 14:38:58 -060052
Guenter Roeck43160712014-09-30 10:48:30 -070053 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
Guenter Roeckef288f92014-09-30 10:48:28 -070054 if (!ctx)
55 return -ENOMEM;
Loc Ho67778e0e2013-07-02 14:38:58 -060056
Guenter Roeck43160712014-09-30 10:48:30 -070057 ctx->csr = of_iomap(dev->of_node, 0);
Loc Ho67778e0e2013-07-02 14:38:58 -060058 if (!ctx->csr) {
Guenter Roeck43160712014-09-30 10:48:30 -070059 dev_err(dev, "can not map resource\n");
Loc Ho67778e0e2013-07-02 14:38:58 -060060 return -ENODEV;
61 }
62
Guenter Roeck43160712014-09-30 10:48:30 -070063 if (of_property_read_u32(dev->of_node, "mask", &ctx->mask))
Loc Ho67778e0e2013-07-02 14:38:58 -060064 ctx->mask = 0xFFFFFFFF;
65
Guenter Roeck43160712014-09-30 10:48:30 -070066 ctx->dev = dev;
Guenter Roeck8f57f232014-09-30 10:48:32 -070067 ctx->restart_handler.notifier_call = xgene_restart_handler;
68 ctx->restart_handler.priority = 128;
69 err = register_restart_handler(&ctx->restart_handler);
Arvind Yadav896af832016-09-14 16:25:39 +053070 if (err) {
71 iounmap(ctx->csr);
Guenter Roeck8f57f232014-09-30 10:48:32 -070072 dev_err(dev, "cannot register restart handler (err=%d)\n", err);
Arvind Yadav896af832016-09-14 16:25:39 +053073 }
Loc Ho67778e0e2013-07-02 14:38:58 -060074
Guenter Roeck8f57f232014-09-30 10:48:32 -070075 return err;
Loc Ho67778e0e2013-07-02 14:38:58 -060076}
77
Fabian Frederick8fb08852015-03-16 20:17:12 +010078static const struct of_device_id xgene_reboot_of_match[] = {
Loc Ho67778e0e2013-07-02 14:38:58 -060079 { .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);