249 lines · c
1/* SPDX-License-Identifier: GPL-2.0-or-later */2/*3 * HP PARISC soft power switch driver4 *5 * Copyright (c) 2001-2023 Helge Deller <deller@gmx.de>6 *7 * HINT:8 * Support of the soft power switch button may be enabled or disabled at9 * runtime through the "/proc/sys/kernel/power" procfs entry.10 */11 12#include <linux/module.h>13#include <linux/init.h>14#include <linux/kernel.h>15#include <linux/panic_notifier.h>16#include <linux/reboot.h>17#include <linux/sched/signal.h>18#include <linux/kthread.h>19#include <linux/pm.h>20 21#include <asm/pdc.h>22#include <asm/io.h>23#include <asm/led.h>24 25#define DRIVER_NAME "powersw"26#define KTHREAD_NAME "kpowerswd"27 28/* how often should the power button be polled ? */29#define POWERSWITCH_POLL_PER_SEC 230 31/* how long does the power button needs to be down until we react ? */32#define POWERSWITCH_DOWN_SEC 233 34/* assembly code to access special registers */35/* taken from PCXL ERS page 82 */36#define DIAG_CODE(code) (0x14000000 + ((code)<<5))37 38#define MFCPU_X(rDiagReg, t_ch, t_th, code) \39 (DIAG_CODE(code) + ((rDiagReg)<<21) + ((t_ch)<<16) + ((t_th)<<0) )40 41#define MTCPU(dr, gr) MFCPU_X(dr, gr, 0, 0x12) /* move value of gr to dr[dr] */42#define MFCPU_C(dr, gr) MFCPU_X(dr, gr, 0, 0x30) /* for dr0 and dr8 only ! */43#define MFCPU_T(dr, gr) MFCPU_X(dr, 0, gr, 0xa0) /* all dr except dr0 and dr8 */44 45#define __getDIAG(dr) ( { \46 register unsigned long __res asm("r28");\47 __asm__ __volatile__ ( \48 ".word %1" : "=&r" (__res) : "i" (MFCPU_T(dr,28) ) \49 ); \50 __res; \51} )52 53/* local shutdown counter */54static int shutdown_timer __read_mostly;55 56/* check, give feedback and start shutdown after one second */57static void process_shutdown(void)58{59 if (shutdown_timer == 0)60 printk(KERN_ALERT KTHREAD_NAME ": Shutdown requested...\n");61 62 shutdown_timer++;63 64 /* wait until the button was pressed for 1 second */65 if (shutdown_timer == (POWERSWITCH_DOWN_SEC*POWERSWITCH_POLL_PER_SEC)) {66 static const char msg[] = "Shutting down...";67 printk(KERN_INFO KTHREAD_NAME ": %s\n", msg);68 lcd_print(msg);69 70 /* send kill signal */71 if (kill_cad_pid(SIGINT, 1)) {72 /* just in case killing init process failed */73 machine_power_off();74 }75 }76}77 78 79/* main power switch task struct */80static struct task_struct *power_task;81 82/* filename in /proc which can be used to enable/disable the power switch */83#define SYSCTL_FILENAME "sys/kernel/power"84 85/* soft power switch enabled/disabled */86int pwrsw_enabled __read_mostly = 1;87 88/* main kernel thread worker. It polls the button state */89static int kpowerswd(void *param)90{91 __set_current_state(TASK_RUNNING);92 93 do {94 int button_not_pressed;95 unsigned long soft_power_reg = (unsigned long) param;96 97 schedule_timeout_interruptible(pwrsw_enabled ? HZ : HZ/POWERSWITCH_POLL_PER_SEC);98 99 if (unlikely(!pwrsw_enabled))100 continue;101 102 if (soft_power_reg) {103 /*104 * Non-Gecko-style machines:105 * Check the power switch status which is read from the106 * real I/O location at soft_power_reg.107 * Bit 31 ("the lowest bit) is the status of the power switch.108 * This bit is "1" if the button is NOT pressed.109 */110 button_not_pressed = (gsc_readl(soft_power_reg) & 0x1);111 } else {112 /*113 * On gecko style machines (e.g. 712/xx and 715/xx)114 * the power switch status is stored in Bit 0 ("the highest bit")115 * of CPU diagnose register 25.116 * Warning: Some machines never reset the DIAG flag, even if117 * the button has been released again.118 */119 button_not_pressed = (__getDIAG(25) & 0x80000000);120 }121 122 if (likely(button_not_pressed)) {123 if (unlikely(shutdown_timer && /* avoid writing if not necessary */124 shutdown_timer < (POWERSWITCH_DOWN_SEC*POWERSWITCH_POLL_PER_SEC))) {125 shutdown_timer = 0;126 printk(KERN_INFO KTHREAD_NAME ": Shutdown request aborted.\n");127 }128 } else129 process_shutdown();130 131 132 } while (!kthread_should_stop());133 134 return 0;135}136 137 138/*139 * powerfail interruption handler (irq IRQ_FROM_REGION(CPU_IRQ_REGION)+2)140 */141#if 0142static void powerfail_interrupt(int code, void *x)143{144 printk(KERN_CRIT "POWERFAIL INTERRUPTION !\n");145 poweroff();146}147#endif148 149 150 151 152/*153 * parisc_panic_event() is called by the panic handler.154 *155 * As soon as a panic occurs, our tasklets above will not156 * be executed any longer. This function then re-enables157 * the soft-power switch and allows the user to switch off158 * the system. We rely in pdc_soft_power_button_panic()159 * since this version spin_trylocks (instead of regular160 * spinlock), preventing deadlocks on panic path.161 */162static int parisc_panic_event(struct notifier_block *this,163 unsigned long event, void *ptr)164{165 /* re-enable the soft-power switch */166 pdc_soft_power_button_panic(0);167 return NOTIFY_DONE;168}169 170static struct notifier_block parisc_panic_block = {171 .notifier_call = parisc_panic_event,172 .priority = INT_MAX,173};174 175/* qemu soft power-off function */176static int qemu_power_off(struct sys_off_data *data)177{178 /* this turns the system off via SeaBIOS */179 gsc_writel(0, (unsigned long) data->cb_data);180 pdc_soft_power_button(1);181 return NOTIFY_DONE;182}183 184static int __init power_init(void)185{186 unsigned long ret;187 unsigned long soft_power_reg;188 189#if 0190 request_irq( IRQ_FROM_REGION(CPU_IRQ_REGION)+2, &powerfail_interrupt,191 0, "powerfail", NULL);192#endif193 194 /* enable the soft power switch if possible */195 ret = pdc_soft_power_info(&soft_power_reg);196 if (ret == PDC_OK)197 ret = pdc_soft_power_button(1);198 if (ret != PDC_OK)199 soft_power_reg = -1UL;200 201 switch (soft_power_reg) {202 case 0: printk(KERN_INFO DRIVER_NAME ": Gecko-style soft power switch enabled.\n");203 break;204 205 case -1UL: printk(KERN_INFO DRIVER_NAME ": Soft power switch support not available.\n");206 return -ENODEV;207 208 default: printk(KERN_INFO DRIVER_NAME ": Soft power switch at 0x%08lx enabled.\n",209 soft_power_reg);210 }211 212 power_task = NULL;213 if (running_on_qemu && soft_power_reg)214 register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, SYS_OFF_PRIO_DEFAULT,215 qemu_power_off, (void *)soft_power_reg);216 if (!running_on_qemu || soft_power_reg)217 power_task = kthread_run(kpowerswd, (void*)soft_power_reg,218 KTHREAD_NAME);219 if (IS_ERR(power_task)) {220 printk(KERN_ERR DRIVER_NAME ": thread creation failed. Driver not loaded.\n");221 pdc_soft_power_button(0);222 return -EIO;223 }224 225 /* Register a call for panic conditions. */226 atomic_notifier_chain_register(&panic_notifier_list,227 &parisc_panic_block);228 229 return 0;230}231 232static void __exit power_exit(void)233{234 kthread_stop(power_task);235 236 atomic_notifier_chain_unregister(&panic_notifier_list,237 &parisc_panic_block);238 239 pdc_soft_power_button(0);240}241 242arch_initcall(power_init);243module_exit(power_exit);244 245 246MODULE_AUTHOR("Helge Deller <deller@gmx.de>");247MODULE_DESCRIPTION("Soft power switch driver");248MODULE_LICENSE("Dual BSD/GPL");249