0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/linkage.h>
0009 #include <linux/init.h>
0010 #include <linux/rtc/ds1286.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/kernel.h>
0013 #include <linux/sched/signal.h>
0014 #include <linux/panic_notifier.h>
0015 #include <linux/pm.h>
0016 #include <linux/timer.h>
0017
0018 #include <asm/io.h>
0019 #include <asm/irq.h>
0020 #include <asm/reboot.h>
0021 #include <asm/sgialib.h>
0022 #include <asm/sgi/ioc.h>
0023 #include <asm/sgi/hpc3.h>
0024 #include <asm/sgi/mc.h>
0025 #include <asm/sgi/ip22.h>
0026
0027
0028
0029
0030
0031
0032 #define POWERDOWN_TIMEOUT 120
0033
0034
0035
0036
0037 #define POWERDOWN_FREQ (HZ / 4)
0038 #define PANIC_FREQ (HZ / 8)
0039
0040 static struct timer_list power_timer, blink_timer, debounce_timer;
0041 static unsigned long blink_timer_timeout;
0042
0043 #define MACHINE_PANICKED 1
0044 #define MACHINE_SHUTTING_DOWN 2
0045
0046 static int machine_state;
0047
0048 static void __noreturn sgi_machine_power_off(void)
0049 {
0050 unsigned int tmp;
0051
0052 local_irq_disable();
0053
0054
0055 tmp = hpc3c0->rtcregs[RTC_CMD] & 0xff;
0056 hpc3c0->rtcregs[RTC_CMD] = tmp | RTC_WAM;
0057 hpc3c0->rtcregs[RTC_WSEC] = 0;
0058 hpc3c0->rtcregs[RTC_WHSEC] = 0;
0059
0060 while (1) {
0061 sgioc->panel = ~SGIOC_PANEL_POWERON;
0062
0063
0064
0065
0066 tmp = hpc3c0->rtcregs[RTC_HOURS_ALARM];
0067 }
0068 }
0069
0070 static void __noreturn sgi_machine_restart(char *command)
0071 {
0072 if (machine_state & MACHINE_SHUTTING_DOWN)
0073 sgi_machine_power_off();
0074 sgimc->cpuctrl0 |= SGIMC_CCTRL0_SYSINIT;
0075 while (1);
0076 }
0077
0078 static void __noreturn sgi_machine_halt(void)
0079 {
0080 if (machine_state & MACHINE_SHUTTING_DOWN)
0081 sgi_machine_power_off();
0082 ArcEnterInteractiveMode();
0083 }
0084
0085 static void power_timeout(struct timer_list *unused)
0086 {
0087 sgi_machine_power_off();
0088 }
0089
0090 static void blink_timeout(struct timer_list *unused)
0091 {
0092
0093 sgi_ioc_reset ^= (SGIOC_RESET_LC0OFF|SGIOC_RESET_LC1OFF);
0094 sgioc->reset = sgi_ioc_reset;
0095
0096 mod_timer(&blink_timer, jiffies + blink_timer_timeout);
0097 }
0098
0099 static void debounce(struct timer_list *unused)
0100 {
0101 del_timer(&debounce_timer);
0102 if (sgint->istat1 & SGINT_ISTAT1_PWR) {
0103
0104 debounce_timer.expires = jiffies + (HZ / 20);
0105 add_timer(&debounce_timer);
0106
0107 sgioc->panel = SGIOC_PANEL_POWERON | SGIOC_PANEL_POWERINTR |
0108 SGIOC_PANEL_VOLDNINTR | SGIOC_PANEL_VOLDNHOLD |
0109 SGIOC_PANEL_VOLUPINTR | SGIOC_PANEL_VOLUPHOLD;
0110
0111 return;
0112 }
0113
0114 if (machine_state & MACHINE_PANICKED)
0115 sgimc->cpuctrl0 |= SGIMC_CCTRL0_SYSINIT;
0116
0117 enable_irq(SGI_PANEL_IRQ);
0118 }
0119
0120 static inline void power_button(void)
0121 {
0122 if (machine_state & MACHINE_PANICKED)
0123 return;
0124
0125 if ((machine_state & MACHINE_SHUTTING_DOWN) ||
0126 kill_cad_pid(SIGINT, 1)) {
0127
0128 sgi_machine_power_off();
0129 }
0130
0131 machine_state |= MACHINE_SHUTTING_DOWN;
0132 blink_timer_timeout = POWERDOWN_FREQ;
0133 blink_timeout(&blink_timer);
0134
0135 timer_setup(&power_timer, power_timeout, 0);
0136 power_timer.expires = jiffies + POWERDOWN_TIMEOUT * HZ;
0137 add_timer(&power_timer);
0138 }
0139
0140 static irqreturn_t panel_int(int irq, void *dev_id)
0141 {
0142 unsigned int buttons;
0143
0144 buttons = sgioc->panel;
0145 sgioc->panel = SGIOC_PANEL_POWERON | SGIOC_PANEL_POWERINTR;
0146
0147 if (sgint->istat1 & SGINT_ISTAT1_PWR) {
0148
0149 disable_irq_nosync(SGI_PANEL_IRQ);
0150 timer_setup(&debounce_timer, debounce, 0);
0151 debounce_timer.expires = jiffies + 5;
0152 add_timer(&debounce_timer);
0153 }
0154
0155
0156
0157
0158
0159
0160 if (!(buttons & SGIOC_PANEL_POWERINTR))
0161 power_button();
0162
0163 return IRQ_HANDLED;
0164 }
0165
0166 static int panic_event(struct notifier_block *this, unsigned long event,
0167 void *ptr)
0168 {
0169 if (machine_state & MACHINE_PANICKED)
0170 return NOTIFY_DONE;
0171 machine_state |= MACHINE_PANICKED;
0172
0173 blink_timer_timeout = PANIC_FREQ;
0174 blink_timeout(&blink_timer);
0175
0176 return NOTIFY_DONE;
0177 }
0178
0179 static struct notifier_block panic_block = {
0180 .notifier_call = panic_event,
0181 };
0182
0183 static int __init reboot_setup(void)
0184 {
0185 int res;
0186
0187 _machine_restart = sgi_machine_restart;
0188 _machine_halt = sgi_machine_halt;
0189 pm_power_off = sgi_machine_power_off;
0190
0191 res = request_irq(SGI_PANEL_IRQ, panel_int, 0, "Front Panel", NULL);
0192 if (res) {
0193 printk(KERN_ERR "Allocation of front panel IRQ failed\n");
0194 return res;
0195 }
0196
0197 timer_setup(&blink_timer, blink_timeout, 0);
0198 atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
0199
0200 return 0;
0201 }
0202
0203 subsys_initcall(reboot_setup);