81 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * HiSilicon SoC reset code4 *5 * Copyright (c) 2014 HiSilicon Ltd.6 * Copyright (c) 2014 Linaro Ltd.7 *8 * Author: Haojian Zhuang <haojian.zhuang@linaro.org>9 */10 11#include <linux/delay.h>12#include <linux/io.h>13#include <linux/module.h>14#include <linux/notifier.h>15#include <linux/of_address.h>16#include <linux/platform_device.h>17#include <linux/reboot.h>18 19#include <asm/proc-fns.h>20 21static void __iomem *base;22static u32 reboot_offset;23 24static int hisi_restart_handler(struct notifier_block *this,25 unsigned long mode, void *cmd)26{27 writel_relaxed(0xdeadbeef, base + reboot_offset);28 29 while (1)30 cpu_do_idle();31 32 return NOTIFY_DONE;33}34 35static struct notifier_block hisi_restart_nb = {36 .notifier_call = hisi_restart_handler,37 .priority = 128,38};39 40static int hisi_reboot_probe(struct platform_device *pdev)41{42 struct device_node *np = pdev->dev.of_node;43 int err;44 45 base = of_iomap(np, 0);46 if (!base) {47 WARN(1, "failed to map base address");48 return -ENODEV;49 }50 51 if (of_property_read_u32(np, "reboot-offset", &reboot_offset) < 0) {52 pr_err("failed to find reboot-offset property\n");53 iounmap(base);54 return -EINVAL;55 }56 57 err = register_restart_handler(&hisi_restart_nb);58 if (err) {59 dev_err(&pdev->dev, "cannot register restart handler (err=%d)\n",60 err);61 iounmap(base);62 }63 64 return err;65}66 67static const struct of_device_id hisi_reboot_of_match[] = {68 { .compatible = "hisilicon,sysctrl" },69 {}70};71MODULE_DEVICE_TABLE(of, hisi_reboot_of_match);72 73static struct platform_driver hisi_reboot_driver = {74 .probe = hisi_reboot_probe,75 .driver = {76 .name = "hisi-reboot",77 .of_match_table = hisi_reboot_of_match,78 },79};80module_platform_driver(hisi_reboot_driver);81