Re: [PATCH 2.5]: IP32 enable power button

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

 



On Mon, Mar 24, 2003 at 10:40:41PM +0100, Ralf Baechle wrote:
> On Mon, Mar 24, 2003 at 01:46:14AM +0100, Guido Guenther wrote:
> 
> > On Sun, Mar 23, 2003 at 07:43:17PM +0100, Guido Guenther wrote:
> > > the attached patch enables the power button on IP32 and adds definitions
> > > for the extra registers of the ds1728[57]. Please apply.
> > Hmm...the patch that worked without problems all over the day now
> > refuses to shut of the machine. I'll have to look into that and post a
> > fixed version when I know whats wrong.
> 
> Ok, will ignore the patch for now,
I'm running the attached version now for quiet some time without
problems. Should be o.k. to apply now.
Regards,
 -- Guido
--- ../o2-2.5.47.glaurung/arch/mips/sgi-ip32/ip32-setup.c	Thu Mar 20 02:15:31 2003
+++ arch/mips/sgi-ip32/ip32-setup.c	Sun Mar 23 19:36:27 2003
@@ -106,8 +106,6 @@
 	conswitchp = &dummy_con;
 #endif
 
-	ip32_reboot_setup();
-
 	rtc_ops = &ip32_rtc_ops;
 	board_time_init = ip32_time_init;
         board_timer_setup = NULL;
Index: include/asm-mips64/ip32/mace.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips64/ip32/mace.h,v
retrieving revision 1.5
diff -u -p -r1.5 mace.h
--- include/asm-mips64/ip32/mace.h	6 Aug 2002 00:09:00 -0000	1.5
+++ include/asm-mips64/ip32/mace.h	25 Mar 2003 23:24:48 -0000
@@ -151,8 +152,8 @@
 #define MACEISA_PWD_CLEAR      BIT(1) /* 1=> PWD CLEAR jumper detected */
 #define MACEISA_NIC_DEASSERT   BIT(2)
 #define MACEISA_NIC_DATA       BIT(3)
-#define MACEISA_LED_RED        BIT(4) /* 1=> Illuminate RED LED */
-#define MACEISA_LED_GREEN      BIT(5) /* 1=> Illuminate GREEN LED */
+#define MACEISA_LED_RED        BIT(4) /* 0=> Illuminate RED LED */
+#define MACEISA_LED_GREEN      BIT(5) /* 0=> Illuminate GREEN LED */
 #define MACEISA_DP_RAM_ENABLE  BIT(6)
 
 /*
--- /dev/null	Sat Mar 16 18:32:44 2002
+++ include/linux/ds17287rtc.h	Wed Mar 26 22:15:05 2003
@@ -0,0 +1,68 @@
+/* 
+ * 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 3 */
+#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 */
+/* interrupt causes */
+#define DS_XCTRL4A_IFS	(DS_XCTRL4A_RF|DS_XCTRL4A_WF|DS_XCTRL4A_KF)
+
+/* 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 */
+/* interrupt enable bits */
+#define DS_XCTRL4B_IFES	(DS_XCTRL4B_RIE|DS_XCTRL4B_WFE|DS_XCTRL4B_KFE)
+
+#endif /* _DS17287RTC_H */
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	28 Mar 2003 11:28:47 -0000
@@ -5,30 +5,204 @@
  *
  * Copyright (C) 2001 Keith M Wesolowski
  * Copyright (C) 2001 Paul Mundt
+ * Copyright (C) 2003 Guido Guenther <agx@sigxcpu.org>
  */
+
 #include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/notifier.h>
+#include <linux/delay.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/wbflush.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;
+
+	disable_irq(MACEISA_RTC_IRQ);
+	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;
+
+	CMOS_WRITE(reg_a | DS_REGA_DV0, RTC_REG_A);
+	wbflush();
+	xctrl_b = CMOS_READ(DS_B1_XCTRL4B)
+		   | DS_XCTRL4B_ABE | DS_XCTRL4B_KFE;
+	CMOS_WRITE(xctrl_b, DS_B1_XCTRL4B);
+	xctrl_a = CMOS_READ(DS_B1_XCTRL4A) & ~DS_XCTRL4A_IFS;
+	CMOS_WRITE(xctrl_a, DS_B1_XCTRL4A);
+	wbflush();
+	/* adios amigos... */
+	CMOS_WRITE(xctrl_a | DS_XCTRL4A_PAB, DS_B1_XCTRL4A);
+	CMOS_WRITE(reg_a, RTC_REG_A);
+	wbflush();
+
+	while(1) {
+	  	printk(KERN_DEBUG "Power off!\n");
+	}
+}
+
+static void power_timeout(unsigned long data)
+{
+	ip32_machine_power_off();
+}
+
+static void blink_timeout(unsigned long data)
+{
+	u64 mc_led =  mace_read_64(MACEISA_FLASH_NIC_REG);
+
+	mc_led ^= MACEISA_LED_RED;
+	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);
+	CMOS_WRITE(reg_a | DS_REGA_DV0, RTC_REG_A);
+	wbflush();
+	xctrl_a = CMOS_READ(DS_B1_XCTRL4A);
+	if( (xctrl_a & DS_XCTRL4A_IFS ) || ( reg_c & RTC_IRQF ) ) {
+		/* Interrupt still being sent. */
+		debounce_timer.expires = jiffies + 50;
+		add_timer(&debounce_timer);
+
+		/* clear interrupt source */
+		CMOS_WRITE( xctrl_a & ~DS_XCTRL4A_IFS, 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);
 }
 
-void __init ip32_reboot_setup(void)
+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) ) {
+		printk(KERN_WARNING 
+			"%s: RTC IRQ without RTC_IRQF\n", __FUNCTION__);
+	}
+	/* Wait until interrupt goes away */
+	disable_irq(MACEISA_RTC_IRQ);
+	init_timer(&debounce_timer);
+	debounce_timer.function = debounce;
+	debounce_timer.expires = jiffies + 50;
+	add_timer(&debounce_timer);
+
+	printk(KERN_DEBUG "Power button pressed\n");
+	ip32_power_button();
+}
+
+static int panic_event(struct notifier_block *this, unsigned long event,
+                      void *ptr)
+{
+	u64 mc_led;
+
+	if (has_paniced)
+		return NOTIFY_DONE;
+	has_paniced = 1;
+
+	/* turn off the green LED */
+	mc_led = mace_read_64(MACEISA_FLASH_NIC_REG);
+	mc_led |= MACEISA_LED_GREEN;
+	mace_write_64(MACEISA_FLASH_NIC_REG, mc_led);
+
+	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)
+{
+	u64 mc_led =  mace_read_64(MACEISA_FLASH_NIC_REG);
+
 	_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);
+
+	/* turn on the green led only */
+	mc_led |= MACEISA_LED_RED;
+	mc_led &= ~MACEISA_LED_GREEN;
+	mace_write_64(MACEISA_FLASH_NIC_REG, mc_led);
+
+	return 0;
 }
+
+subsys_initcall(ip32_reboot_setup);

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

  Powered by Linux