aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/loongson/lemote-2f/pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/loongson/lemote-2f/pm.c')
-rw-r--r--arch/mips/loongson/lemote-2f/pm.c71
1 files changed, 68 insertions, 3 deletions
diff --git a/arch/mips/loongson/lemote-2f/pm.c b/arch/mips/loongson/lemote-2f/pm.c
index 8090d0514221..81c06410aa76 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}