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 static unsigned int get_reboot_mode_magic(struct reboot_mode_driver
*reboot
,
29 const char *normal
= "normal";
31 struct mode_info
*info
;
36 list_for_each_entry(info
, &reboot
->head
, list
) {
37 if (!strcmp(info
->mode
, cmd
)) {
46 static int reboot_mode_notify(struct notifier_block
*this,
47 unsigned long mode
, void *cmd
)
49 struct reboot_mode_driver
*reboot
;
52 reboot
= container_of(this, struct reboot_mode_driver
, reboot_notifier
);
53 magic
= get_reboot_mode_magic(reboot
, cmd
);
55 reboot
->write(reboot
, magic
);
61 * reboot_mode_register - register a reboot mode driver
62 * @reboot: reboot mode driver
64 * Returns: 0 on success or a negative error code on failure.
66 int reboot_mode_register(struct reboot_mode_driver
*reboot
)
68 struct mode_info
*info
;
69 struct property
*prop
;
70 struct device_node
*np
= reboot
->dev
->of_node
;
71 size_t len
= strlen(PREFIX
);
74 INIT_LIST_HEAD(&reboot
->head
);
76 for_each_property_of_node(np
, prop
) {
77 if (strncmp(prop
->name
, PREFIX
, len
))
80 info
= devm_kzalloc(reboot
->dev
, sizeof(*info
), GFP_KERNEL
);
86 if (of_property_read_u32(np
, prop
->name
, &info
->magic
)) {
87 dev_err(reboot
->dev
, "reboot mode %s without magic number\n",
89 devm_kfree(reboot
->dev
, info
);
93 info
->mode
= kstrdup_const(prop
->name
+ len
, GFP_KERNEL
);
97 } else if (info
->mode
[0] == '\0') {
98 kfree_const(info
->mode
);
100 dev_err(reboot
->dev
, "invalid mode name(%s): too short!\n",
105 list_add_tail(&info
->list
, &reboot
->head
);
108 reboot
->reboot_notifier
.notifier_call
= reboot_mode_notify
;
109 register_reboot_notifier(&reboot
->reboot_notifier
);
114 list_for_each_entry(info
, &reboot
->head
, list
)
115 kfree_const(info
->mode
);
119 EXPORT_SYMBOL_GPL(reboot_mode_register
);
122 * reboot_mode_unregister - unregister a reboot mode driver
123 * @reboot: reboot mode driver
125 int reboot_mode_unregister(struct reboot_mode_driver
*reboot
)
127 struct mode_info
*info
;
129 unregister_reboot_notifier(&reboot
->reboot_notifier
);
131 list_for_each_entry(info
, &reboot
->head
, list
)
132 kfree_const(info
->mode
);
136 EXPORT_SYMBOL_GPL(reboot_mode_unregister
);
138 MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com");
139 MODULE_DESCRIPTION("System reboot mode core library");
140 MODULE_LICENSE("GPL v2");
This page took 0.035812 seconds and 6 git commands to generate.