diff options
Diffstat (limited to 'arch/mips/loongson/lemote-2f/pm.c')
-rw-r--r-- | arch/mips/loongson/lemote-2f/pm.c | 71 |
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 | */ | ||
55 | void setup_wakeup_events(void) | 55 | void 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 | |||
82 | static struct delayed_work lid_task; | ||
83 | static int initialized; | ||
84 | /* yeeloong_report_lid_status will be implemented in yeeloong_laptop.c */ | ||
85 | sci_handler yeeloong_report_lid_status; | ||
86 | EXPORT_SYMBOL(yeeloong_report_lid_status); | ||
87 | static 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 | |||
93 | int 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 | } | ||