[PATCH 2.5]: IP32 enable power button

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,
the attached patch enables the power button on IP32 and adds definitions
for the extra registers of the ds1728[57]. Please apply.
Regards,
 -- Guido
Index: arch/mips/sgi-ip32/ip32-reset.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/sgi-ip32/ip32-reset.c,v
retrieving revision 1.1
diff -u -p -r1.1 ip32-reset.c
--- arch/mips/sgi-ip32/ip32-reset.c	25 Jul 2002 19:10:08 -0000	1.1
+++ arch/mips/sgi-ip32/ip32-reset.c	23 Mar 2003 18:27:34 -0000
@@ -5,30 +5,186 @@
  *
  * Copyright (C) 2001 Keith M Wesolowski
  * Copyright (C) 2001 Paul Mundt
+ * Copyright (C) 2003 Guido Guenther <agx@sigxcpu.org>
+ *
+ * based on sgi-ip22/ip22-reset.c
  */
+
 #include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/notifier.h>
+#include <linux/ds17287rtc.h>
 
+#include <asm/irq.h>
 #include <asm/reboot.h>
 #include <asm/sgialib.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include <asm/system.h>
+#include <asm/ip32/ip32_ints.h>
+
+#define POWERDOWN_TIMEOUT	120
+/*
+ * Blink frequency during reboot grace period and when paniced.
+ */
+#define POWERDOWN_FREQ		(HZ / 4)
+#define PANIC_FREQ		(HZ / 8)
+
+static struct timer_list power_timer, blink_timer, debounce_timer;
+static int shuting_down = 0, has_paniced = 0;
+
+static void ip32_machine_restart(char *command) __attribute__((noreturn));
+static void ip32_machine_halt(void) __attribute__((noreturn));
+static void ip32_machine_power_off(void) __attribute__((noreturn));
 
 static void ip32_machine_restart(char *cmd)
 {
+	if (shuting_down)
+		ip32_machine_power_off();
 	ArcReboot();
 }
 
 static inline void ip32_machine_halt(void)
 {
+	if (shuting_down)
+		ip32_machine_power_off();
 	ArcEnterInteractiveMode();
 }
 
 static void ip32_machine_power_off(void)
 {
-	ip32_machine_halt();
+	volatile unsigned char reg_a, xctrl_a, xctrl_b;
+
+	reg_a = CMOS_READ(RTC_REG_A);
+
+	/* setup for kickstart & wake-up (DS12287 Ref. Man. p. 19) */
+	reg_a &= ~DS_REGA_DV2;
+	reg_a |= DS_REGA_DV1 | DS_REGA_DV0;
+	CMOS_WRITE(reg_a, RTC_REG_A);
+
+	while(1) {
+		xctrl_a = CMOS_READ(DS_B1_XCTRL4A) 
+				& ~(DS_XCTRL4A_WF | DS_XCTRL4A_KF);
+		xctrl_a = DS_XCTRL4A_PAB; /* power off flag */
+		xctrl_b = CMOS_READ(DS_B1_XCTRL4B) 
+				| DS_XCTRL4B_WFE | DS_XCTRL4B_KFE;
+		CMOS_WRITE(xctrl_b, DS_B1_XCTRL4B);
+		CMOS_WRITE(xctrl_a, DS_B1_XCTRL4A);
+	}
+}
+
+static void power_timeout(unsigned long data)
+{
+	ip32_machine_power_off();
 }
 
-void __init ip32_reboot_setup(void)
+static void blink_timeout(unsigned long data)
+{
+	u64 mc_led =  mace_read_64(MACEISA_FLASH_NIC_REG);
+
+	mc_led ^= MACEISA_LED_RED;
+	if(has_paniced) 
+		mc_led &= ~MACEISA_LED_GREEN;
+	mace_write_64(MACEISA_FLASH_NIC_REG, mc_led);
+	mod_timer(&blink_timer, jiffies+data);
+}
+
+static void debounce(unsigned long data)
+{
+	volatile unsigned char reg_a,reg_c,xctrl_a;
+
+	reg_c = CMOS_READ(RTC_INTR_FLAGS);
+	reg_a = CMOS_READ(RTC_REG_A);
+	CMOS_WRITE(reg_a | DS_REGA_DV0, RTC_REG_A);
+	xctrl_a = CMOS_READ(DS_B1_XCTRL4A);
+	if( xctrl_a & DS_XCTRL4A_KF || reg_c & RTC_IRQF ) {
+		/* Interrupt still being sent. */
+		debounce_timer.expires = jiffies + 5; /* 0.05s  */
+		add_timer(&debounce_timer);
+
+		/* clear interrupt source */
+		CMOS_WRITE( xctrl_a & ~(DS_XCTRL4A_KF|DS_XCTRL4A_WF|DS_XCTRL4A_RF),
+			    DS_B1_XCTRL4A);
+		CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A);
+		return;
+	}
+	CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A);
+
+	if (has_paniced)
+		ArcReboot();
+
+	enable_irq(MACEISA_RTC_IRQ);
+}
+
+static inline void ip32_power_button(void)
+{
+	if (has_paniced)
+		return;
+
+	if (shuting_down || kill_proc(1, SIGINT, 1)) {
+		/* No init process or button pressed twice.  */
+		ip32_machine_power_off();
+	}
+
+	shuting_down = 1;
+	blink_timer.data = POWERDOWN_FREQ;
+	blink_timeout(POWERDOWN_FREQ);
+
+	init_timer(&power_timer);
+	power_timer.function = power_timeout;
+	power_timer.expires = jiffies + POWERDOWN_TIMEOUT * HZ;
+	add_timer(&power_timer);
+}
+
+static void ip32_rtc_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+	volatile unsigned char reg_c;
+
+	reg_c = CMOS_READ(RTC_INTR_FLAGS);
+	if( reg_c & RTC_IRQF ) {
+		/* Wait until interrupt goes away */
+		disable_irq(MACEISA_RTC_IRQ);
+		init_timer(&debounce_timer);
+		debounce_timer.function = debounce;
+		debounce_timer.expires = jiffies + 5;
+		add_timer(&debounce_timer);
+	} else
+		printk(KERN_WARNING 
+			"%s: RTC IRQ without RTC_IRQF\n", __FUNCTION__);
+
+	printk(KERN_DEBUG "Power button pressed\n");
+	ip32_power_button();
+}
+
+static int panic_event(struct notifier_block *this, unsigned long event,
+                      void *ptr)
+{
+	if (has_paniced)
+		return NOTIFY_DONE;
+	has_paniced = 1;
+
+	blink_timer.data = PANIC_FREQ;
+	blink_timeout(PANIC_FREQ);
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block panic_block = {
+	.notifier_call	= panic_event,
+};
+
+static __init int ip32_reboot_setup(void)
 {
 	_machine_restart = ip32_machine_restart;
 	_machine_halt = ip32_machine_halt;
 	_machine_power_off = ip32_machine_power_off;
+	request_irq(MACEISA_RTC_IRQ, ip32_rtc_int, 0, "rtc", NULL);
+	init_timer(&blink_timer);
+	blink_timer.function = blink_timeout;
+	notifier_chain_register(&panic_notifier_list, &panic_block);
+
+	return 0;
 }
+
+subsys_initcall(ip32_reboot_setup);
Index: arch/mips/sgi-ip32/ip32-setup.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/sgi-ip32/ip32-setup.c,v
retrieving revision 1.2
diff -u -p -r1.2 ip32-setup.c
--- arch/mips/sgi-ip32/ip32-setup.c	21 Sep 2002 21:21:18 -0000	1.2
+++ arch/mips/sgi-ip32/ip32-setup.c	23 Mar 2003 18:27:34 -0000
@@ -89,8 +105,6 @@ void __init ip32_setup(void)
 #ifdef CONFIG_VT
 	conswitchp = &dummy_con;
 #endif
-
-	ip32_reboot_setup();
 
 	rtc_ops = &ip32_rtc_ops;
 	board_time_init = ip32_time_init;
--- /dev/null	Sat Mar 16 18:32:44 2002
+++ include/linux/ds17287rtc.h	Sun Mar 23 17:58:47 2003
@@ -0,0 +1,64 @@
+/* 
+ * ds17287rtc.h - register definitions for the ds1728[57] RTC / CMOS RAM
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ * 
+ * (C) 2003 Guido Guenther <agx@sigxcpu.org>
+ *
+ */
+
+#ifndef _DS17287RTC_H
+#define _DS17287RTC_H
+
+#include <asm/io.h>
+#include <linux/rtc.h>			/* get the user-level API */
+#include <linux/spinlock.h>		/* spinlock_t */
+#include <linux/mc146818rtc.h>
+
+/* register A */
+#define DS_REGA_DV2 0x40		/* countdown chain */
+#define DS_REGA_DV1 0x20		/* oscillator enable */
+#define DS_REGA_DV0 0x10		/* bank select */
+
+/* bank 1 registers */
+#define DS_B1_MODEL	 0x40		/* model number byte */
+#define DS_B1_SN1 	 0x41		/* serial number byte 1 */
+#define DS_B1_SN2 	 0x42		/* serial number byte 2 */
+#define DS_B1_SN3 	 0x43		/* serial number byte 3 */
+#define DS_B1_SN4 	 0x44		/* serial number byte 4 */
+#define DS_B1_SN5 	 0x45		/* serial number byte 5 */
+#define DS_B1_SN6 	 0x46		/* serial number byte 6 */
+#define DS_B1_CRC 	 0x47		/* CRC byte */
+#define DS_B1_CENTURY 	 0x48		/* Century byte */
+#define DS_B1_DALARM 	 0x49		/* date alarm */
+#define DS_B1_XCTRL4A	 0x4a		/* extendec control register 4a */
+#define DS_B1_XCTRL4B	 0x4b		/* extendec control register 4b */
+#define DS_B1_RTCADDR2 	 0x4e		/* rtc address 2 */
+#define DS_B1_RTCADDR3 	 0x4f		/* rtc address 2 */
+#define DS_B1_RAMLSB	 0x50		/* extended ram LSB */
+#define DS_B1_RAMMSB	 0x51		/* extended ram MSB */
+#define DS_B1_RAMDPORT	 0x53		/* extended ram data port */
+
+/* register details */
+/* extended control register 4a */
+#define DS_XCTRL4A_VRT2  0x80 		/* valid ram and time */
+#define DS_XCTRL4A_INCR  0x40		/* increment progress status */
+#define DS_XCTRL4A_BME   0x20		/* burst mode enable */
+#define DS_XCTRL4A_PAB   0x08		/* power active bar ctrl */
+#define DS_XCTRL4A_RF    0x04		/* ram clear flag */
+#define DS_XCTRL4A_WF    0x02		/* wake up alarm flag */
+#define DS_XCTRL4A_KF    0x01		/* kickstart flag */
+
+/* extended control register 4b */
+#define DS_XCTRL4B_ABE   0x80 		/* auxiliary battery enable */
+#define DS_XCTRL4B_E32K	 0x40		/* enable 32.768 kHz Output */
+#define DS_XCTRL4B_CS    0x20		/* crystal select */
+#define DS_XCTRL4B_RCE   0x10		/* ram clear enable */
+#define DS_XCTRL4B_PRS   0x08		/* PAB resec select */
+#define DS_XCTRL4B_RIE   0x04		/* ram clear interrupt enable */
+#define DS_XCTRL4B_WFE   0x02		/* wake up alarm interrupt enable */
+#define DS_XCTRL4B_KFE   0x01		/* kickstart interrupt enable */
+
+#endif /* _DS17287RTC_H */

[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux