]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - arch/mips/sgi-ip32/ip32-reset.c
Merge tag 'powerpc-4.15-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[mirror_ubuntu-bionic-kernel.git] / arch / mips / sgi-ip32 / ip32-reset.c
CommitLineData
1da177e4
LT
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2001 Keith M Wesolowski
7 * Copyright (C) 2001 Paul Mundt
8 * Copyright (C) 2003 Guido Guenther <agx@sigxcpu.org>
9 */
10
efc46d13 11#include <linux/compiler.h>
1da177e4
LT
12#include <linux/init.h>
13#include <linux/kernel.h>
15beb694 14#include <linux/module.h>
1da177e4 15#include <linux/sched.h>
fc69910f 16#include <linux/sched/signal.h>
1da177e4
LT
17#include <linux/notifier.h>
18#include <linux/delay.h>
15beb694 19#include <linux/rtc/ds1685.h>
1da177e4 20#include <linux/interrupt.h>
fcdb27ad 21#include <linux/pm.h>
1da177e4
LT
22
23#include <asm/addrspace.h>
24#include <asm/irq.h>
25#include <asm/reboot.h>
1da177e4
LT
26#include <asm/wbflush.h>
27#include <asm/ip32/mace.h>
28#include <asm/ip32/crime.h>
29#include <asm/ip32/ip32_ints.h>
30
31#define POWERDOWN_TIMEOUT 120
32/*
f18190bd 33 * Blink frequency during reboot grace period and when panicked.
1da177e4
LT
34 */
35#define POWERDOWN_FREQ (HZ / 4)
36#define PANIC_FREQ (HZ / 8)
37
15beb694 38extern struct platform_device ip32_rtc_device;
1da177e4 39
15beb694 40static struct timer_list power_timer, blink_timer;
a66b899d 41static unsigned long blink_timer_timeout;
15beb694 42static int has_panicked, shutting_down;
1da177e4 43
15beb694 44static __noreturn void ip32_poweroff(void *data)
1da177e4 45{
15beb694
JK
46 void (*poweroff_func)(struct platform_device *) =
47 symbol_get(ds1685_rtc_poweroff);
48
49#ifdef CONFIG_MODULES
50 /* If the first __symbol_get failed, our module wasn't loaded. */
51 if (!poweroff_func) {
52 request_module("rtc-ds1685");
53 poweroff_func = symbol_get(ds1685_rtc_poweroff);
54 }
55#endif
1da177e4 56
15beb694
JK
57 if (!poweroff_func)
58 pr_emerg("RTC not available for power-off. Spinning forever ...\n");
59 else {
60 (*poweroff_func)((struct platform_device *)data);
61 symbol_put(ds1685_rtc_poweroff);
62 }
1da177e4 63
15beb694 64 unreachable();
1da177e4
LT
65}
66
15beb694
JK
67static void ip32_machine_restart(char *cmd) __noreturn;
68static void ip32_machine_restart(char *cmd)
1da177e4 69{
15beb694
JK
70 msleep(20);
71 crime->control = CRIME_CONTROL_HARD_RESET;
72 unreachable();
1da177e4
LT
73}
74
a66b899d 75static void blink_timeout(struct timer_list *unused)
1da177e4
LT
76{
77 unsigned long led = mace->perif.ctrl.misc ^ MACEISA_LED_RED;
78 mace->perif.ctrl.misc = led;
a66b899d 79 mod_timer(&blink_timer, jiffies + blink_timer_timeout);
1da177e4
LT
80}
81
15beb694 82static void ip32_machine_halt(void)
1da177e4 83{
15beb694
JK
84 ip32_poweroff(&ip32_rtc_device);
85}
1da177e4 86
a66b899d 87static void power_timeout(struct timer_list *unused)
15beb694
JK
88{
89 ip32_poweroff(&ip32_rtc_device);
1da177e4
LT
90}
91
15beb694 92void ip32_prepare_poweroff(void)
1da177e4 93{
f18190bd 94 if (has_panicked)
1da177e4
LT
95 return;
96
15beb694 97 if (shutting_down || kill_cad_pid(SIGINT, 1)) {
1da177e4 98 /* No init process or button pressed twice. */
15beb694 99 ip32_poweroff(&ip32_rtc_device);
1da177e4
LT
100 }
101
15beb694 102 shutting_down = 1;
a66b899d
KC
103 blink_timer_timeout = POWERDOWN_FREQ;
104 blink_timeout(&blink_timer);
1da177e4 105
a66b899d 106 timer_setup(&power_timer, power_timeout, 0);
1da177e4
LT
107 power_timer.expires = jiffies + POWERDOWN_TIMEOUT * HZ;
108 add_timer(&power_timer);
109}
110
1da177e4
LT
111static int panic_event(struct notifier_block *this, unsigned long event,
112 void *ptr)
113{
114 unsigned long led;
115
f18190bd 116 if (has_panicked)
1da177e4 117 return NOTIFY_DONE;
f18190bd 118 has_panicked = 1;
1da177e4
LT
119
120 /* turn off the green LED */
121 led = mace->perif.ctrl.misc | MACEISA_LED_GREEN;
122 mace->perif.ctrl.misc = led;
123
a66b899d
KC
124 blink_timer_timeout = PANIC_FREQ;
125 blink_timeout(&blink_timer);
1da177e4
LT
126
127 return NOTIFY_DONE;
128}
129
130static struct notifier_block panic_block = {
131 .notifier_call = panic_event,
132};
133
134static __init int ip32_reboot_setup(void)
135{
136 /* turn on the green led only */
137 unsigned long led = mace->perif.ctrl.misc;
138 led |= MACEISA_LED_RED;
139 led &= ~MACEISA_LED_GREEN;
140 mace->perif.ctrl.misc = led;
141
142 _machine_restart = ip32_machine_restart;
143 _machine_halt = ip32_machine_halt;
15beb694 144 pm_power_off = ip32_machine_halt;
1da177e4 145
a66b899d 146 timer_setup(&blink_timer, blink_timeout, 0);
e041c683 147 atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
1da177e4 148
1da177e4
LT
149 return 0;
150}
151
152subsys_initcall(ip32_reboot_setup);