aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWu Zhangjin <wuzhangjin@gmail.com>2009-11-21 06:05:24 -0500
committerRalf Baechle <ralf@linux-mips.org>2009-12-16 20:57:28 -0500
commitcb1ed9e117098269de3c0dfff816dff453dd4b59 (patch)
tree918d2eec2f59ca418e395d44b95881951a4dddab
parentec614d80b58677de30b876a16fdd3fde85bebdc1 (diff)
MIPS: Yeeloong 2F: Add LID open event as the wakeup event
Yeeloong 2F netbook has an KB3310B embedded controller to manage the LID action. When the LID is closed or opened a SCI interrupt is sent out and the corresponding event is saved to an EC register for later query. Allow the LID open interrupt to wake the processor from wait mode if it is in the suspend mode. Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com> Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/685/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/include/asm/mach-loongson/loongson.h1
-rw-r--r--arch/mips/loongson/lemote-2f/irq.c4
-rw-r--r--arch/mips/loongson/lemote-2f/pm.c71
3 files changed, 72 insertions, 4 deletions
diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
index a7fa66e8598..06c28f38711 100644
--- a/arch/mips/include/asm/mach-loongson/loongson.h
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
@@ -41,6 +41,7 @@ extern void __init bonito_irq_init(void);
41extern void __init set_irq_trigger_mode(void); 41extern void __init set_irq_trigger_mode(void);
42extern void __init mach_init_irq(void); 42extern void __init mach_init_irq(void);
43extern void mach_irq_dispatch(unsigned int pending); 43extern void mach_irq_dispatch(unsigned int pending);
44extern int mach_i8259_irq(void);
44 45
45/* We need this in some places... */ 46/* We need this in some places... */
46#define delay() ({ \ 47#define delay() ({ \
diff --git a/arch/mips/loongson/lemote-2f/irq.c b/arch/mips/loongson/lemote-2f/irq.c
index 50e7bb6012b..77d32f9cf31 100644
--- a/arch/mips/loongson/lemote-2f/irq.c
+++ b/arch/mips/loongson/lemote-2f/irq.c
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11#include <linux/interrupt.h> 11#include <linux/interrupt.h>
12#include <linux/module.h>
12 13
13#include <asm/irq_cpu.h> 14#include <asm/irq_cpu.h>
14#include <asm/i8259.h> 15#include <asm/i8259.h>
@@ -30,7 +31,7 @@
30 * The generic i8259_irq() make the kernel hang on booting. Since we cannot 31 * The generic i8259_irq() make the kernel hang on booting. Since we cannot
31 * get the irq via the IRR directly, we access the ISR instead. 32 * get the irq via the IRR directly, we access the ISR instead.
32 */ 33 */
33static inline int mach_i8259_irq(void) 34int mach_i8259_irq(void)
34{ 35{
35 int irq, isr; 36 int irq, isr;
36 37
@@ -60,6 +61,7 @@ static inline int mach_i8259_irq(void)
60 61
61 return irq; 62 return irq;
62} 63}
64EXPORT_SYMBOL(mach_i8259_irq);
63 65
64static void i8259_irqdispatch(void) 66static void i8259_irqdispatch(void)
65{ 67{
diff --git a/arch/mips/loongson/lemote-2f/pm.c b/arch/mips/loongson/lemote-2f/pm.c
index 8090d051422..81c06410aa7 100644
--- a/arch/mips/loongson/lemote-2f/pm.c
+++ b/arch/mips/loongson/lemote-2f/pm.c
@@ -14,6 +14,7 @@
14#include <linux/interrupt.h> 14#include <linux/interrupt.h>
15#include <linux/pm.h> 15#include <linux/pm.h>
16#include <linux/i8042.h> 16#include <linux/i8042.h>
17#include <linux/module.h>
17 18
18#include <asm/i8259.h> 19#include <asm/i8259.h>
19#include <asm/mipsregs.h> 20#include <asm/mipsregs.h>
@@ -21,6 +22,8 @@
21 22
22#include <loongson.h> 23#include <loongson.h>
23 24
25#include "ec_kb3310b.h"
26
24#define I8042_KBD_IRQ 1 27#define I8042_KBD_IRQ 1
25#define I8042_CTR_KBDINT 0x01 28#define I8042_CTR_KBDINT 0x01
26#define I8042_CTR_KBDDIS 0x10 29#define I8042_CTR_KBDDIS 0x10
@@ -49,9 +52,6 @@ static int i8042_enable_kbd_port(void)
49 return 0; 52 return 0;
50} 53}
51 54
52/*
53 * The i8042 is connnected to i8259A
54 */
55void setup_wakeup_events(void) 55void setup_wakeup_events(void)
56{ 56{
57 int irq_mask; 57 int irq_mask;
@@ -65,9 +65,74 @@ void setup_wakeup_events(void)
65 65
66 /* enable keyboard port */ 66 /* enable keyboard port */
67 i8042_enable_kbd_port(); 67 i8042_enable_kbd_port();
68
69 /* Wakeup CPU via SCI lid open event */
70 outb(irq_mask & ~(1 << PIC_CASCADE_IR), PIC_MASTER_IMR);
71 inb(PIC_MASTER_IMR);
72 outb(0xff & ~(1 << (SCI_IRQ_NUM - 8)), PIC_SLAVE_IMR);
73 inb(PIC_SLAVE_IMR);
74
68 break; 75 break;
69 76
70 default: 77 default:
71 break; 78 break;
72 } 79 }
73} 80}
81
82static struct delayed_work lid_task;
83static int initialized;
84/* yeeloong_report_lid_status will be implemented in yeeloong_laptop.c */
85sci_handler yeeloong_report_lid_status;
86EXPORT_SYMBOL(yeeloong_report_lid_status);
87static void yeeloong_lid_update_task(struct work_struct *work)
88{
89 if (yeeloong_report_lid_status)
90 yeeloong_report_lid_status(BIT_LID_DETECT_ON);
91}
92
93int wakeup_loongson(void)
94{
95 int irq;
96
97 /* query the interrupt number */
98 irq = mach_i8259_irq();
99 if (irq < 0)
100 return 0;
101
102 printk(KERN_INFO "%s: irq = %d\n", __func__, irq);
103
104 if (irq == I8042_KBD_IRQ)
105 return 1;
106 else if (irq == SCI_IRQ_NUM) {
107 int ret, sci_event;
108 /* query the event number */
109 ret = ec_query_seq(CMD_GET_EVENT_NUM);
110 if (ret < 0)
111 return 0;
112 sci_event = ec_get_event_num();
113 if (sci_event < 0)
114 return 0;
115 if (sci_event == EVENT_LID) {
116 int lid_status;
117 /* check the LID status */
118 lid_status = ec_read(REG_LID_DETECT);
119 /* wakeup cpu when people open the LID */
120 if (lid_status == BIT_LID_DETECT_ON) {
121 /* If we call it directly here, the WARNING
122 * will be sent out by getnstimeofday
123 * via "WARN_ON(timekeeping_suspended);"
124 * because we can not schedule in suspend mode.
125 */
126 if (initialized == 0) {
127 INIT_DELAYED_WORK(&lid_task,
128 yeeloong_lid_update_task);
129 initialized = 1;
130 }
131 schedule_delayed_work(&lid_task, 1);
132 return 1;
133 }
134 }
135 }
136
137 return 0;
138}