2 * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
10 #include <linux/device.h>
11 #include <linux/init.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
15 #include <linux/reboot.h>
16 #include "reboot-mode.h"
18 #define PREFIX "mode-"
23 struct list_head list;
26 struct reboot_mode_driver {
27 struct list_head head;
28 int (*write)(int magic);
29 struct notifier_block reboot_notifier;
32 static int get_reboot_mode_magic(struct reboot_mode_driver *reboot,
35 const char *normal = "normal";
37 struct mode_info *info;
42 list_for_each_entry(info, &reboot->head, list) {
43 if (!strcmp(info->mode, cmd)) {
52 static int reboot_mode_notify(struct notifier_block *this,
53 unsigned long mode, void *cmd)
55 struct reboot_mode_driver *reboot;
58 reboot = container_of(this, struct reboot_mode_driver, reboot_notifier);
59 magic = get_reboot_mode_magic(reboot, cmd);
61 magic = get_reboot_mode_magic(reboot, NULL);
68 int reboot_mode_register(struct device *dev, int (*write)(int))
70 struct reboot_mode_driver *reboot;
71 struct mode_info *info;
72 struct property *prop;
73 size_t len = strlen(PREFIX);
76 reboot = devm_kzalloc(dev, sizeof(*reboot), GFP_KERNEL);
80 reboot->write = write;
81 INIT_LIST_HEAD(&reboot->head);
82 for_each_property_of_node(dev->of_node, prop) {
83 if (len > strlen(prop->name) || strncmp(prop->name, PREFIX, len))
85 info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
88 strcpy(info->mode, prop->name + len);
89 if (of_property_read_u32(dev->of_node, prop->name, &info->magic)) {
90 dev_err(dev, "reboot mode %s without magic number\n",
92 devm_kfree(dev, info);
95 list_add_tail(&info->list, &reboot->head);
97 reboot->reboot_notifier.notifier_call = reboot_mode_notify;
98 ret = register_reboot_notifier(&reboot->reboot_notifier);
100 dev_err(dev, "can't register reboot notifier\n");
104 EXPORT_SYMBOL_GPL(reboot_mode_register);
106 MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com");
107 MODULE_DESCRIPTION("System reboot mode driver");
108 MODULE_LICENSE("GPL v2");