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
6 * Copyright (C) 2001 Keith M Wesolowski
7 * Copyright (C) 2001 Paul Mundt
8 * Copyright (C) 2003 Guido Guenther <agx@sigxcpu.org>
11 #include <linux/compiler.h>
12 #include <linux/init.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/panic_notifier.h>
16 #include <linux/sched.h>
17 #include <linux/sched/signal.h>
18 #include <linux/notifier.h>
19 #include <linux/delay.h>
20 #include <linux/rtc/ds1685.h>
21 #include <linux/interrupt.h>
24 #include <asm/addrspace.h>
26 #include <asm/reboot.h>
27 #include <asm/wbflush.h>
28 #include <asm/ip32/mace.h>
29 #include <asm/ip32/crime.h>
30 #include <asm/ip32/ip32_ints.h>
32 #include "ip32-common.h"
34 #define POWERDOWN_TIMEOUT 120
36 * Blink frequency during reboot grace period and when panicked.
38 #define POWERDOWN_FREQ (HZ / 4)
39 #define PANIC_FREQ (HZ / 8)
41 extern struct platform_device ip32_rtc_device
;
43 static struct timer_list power_timer
, blink_timer
;
44 static unsigned long blink_timer_timeout
;
45 static int has_panicked
, shutting_down
;
47 static __noreturn
void ip32_poweroff(void *data
)
49 void (*poweroff_func
)(struct platform_device
*) =
50 symbol_get(ds1685_rtc_poweroff
);
53 /* If the first __symbol_get failed, our module wasn't loaded. */
55 request_module("rtc-ds1685");
56 poweroff_func
= symbol_get(ds1685_rtc_poweroff
);
61 pr_emerg("RTC not available for power-off. Spinning forever ...\n");
63 (*poweroff_func
)((struct platform_device
*)data
);
64 symbol_put(ds1685_rtc_poweroff
);
70 static void ip32_machine_restart(char *cmd
) __noreturn
;
71 static void ip32_machine_restart(char *cmd
)
74 crime
->control
= CRIME_CONTROL_HARD_RESET
;
78 static void blink_timeout(struct timer_list
*unused
)
80 unsigned long led
= mace
->perif
.ctrl
.misc
^ MACEISA_LED_RED
;
81 mace
->perif
.ctrl
.misc
= led
;
82 mod_timer(&blink_timer
, jiffies
+ blink_timer_timeout
);
85 static void ip32_machine_halt(void)
87 ip32_poweroff(&ip32_rtc_device
);
90 static void power_timeout(struct timer_list
*unused
)
92 ip32_poweroff(&ip32_rtc_device
);
95 void ip32_prepare_poweroff(void)
100 if (shutting_down
|| kill_cad_pid(SIGINT
, 1)) {
101 /* No init process or button pressed twice. */
102 ip32_poweroff(&ip32_rtc_device
);
106 blink_timer_timeout
= POWERDOWN_FREQ
;
107 blink_timeout(&blink_timer
);
109 timer_setup(&power_timer
, power_timeout
, 0);
110 power_timer
.expires
= jiffies
+ POWERDOWN_TIMEOUT
* HZ
;
111 add_timer(&power_timer
);
114 static int panic_event(struct notifier_block
*this, unsigned long event
,
123 /* turn off the green LED */
124 led
= mace
->perif
.ctrl
.misc
| MACEISA_LED_GREEN
;
125 mace
->perif
.ctrl
.misc
= led
;
127 blink_timer_timeout
= PANIC_FREQ
;
128 blink_timeout(&blink_timer
);
133 static struct notifier_block panic_block
= {
134 .notifier_call
= panic_event
,
137 static __init
int ip32_reboot_setup(void)
139 /* turn on the green led only */
140 unsigned long led
= mace
->perif
.ctrl
.misc
;
141 led
|= MACEISA_LED_RED
;
142 led
&= ~MACEISA_LED_GREEN
;
143 mace
->perif
.ctrl
.misc
= led
;
145 _machine_restart
= ip32_machine_restart
;
146 _machine_halt
= ip32_machine_halt
;
147 pm_power_off
= ip32_machine_halt
;
149 timer_setup(&blink_timer
, blink_timeout
, 0);
150 atomic_notifier_chain_register(&panic_notifier_list
, &panic_block
);
155 subsys_initcall(ip32_reboot_setup
);