2 * Lemote loongson2f family machines' specific suspend support
4 * Copyright (C) 2009 Lemote Inc.
5 * Author: Wu Zhangjin <wuzhangjin@gmail.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
13 #include <linux/suspend.h>
14 #include <linux/interrupt.h>
16 #include <linux/i8042.h>
17 #include <linux/module.h>
19 #include <asm/i8259.h>
20 #include <asm/mipsregs.h>
21 #include <asm/bootinfo.h>
25 #include <cs5536/cs5536_mfgpt.h>
26 #include "ec_kb3310b.h"
28 #define I8042_KBD_IRQ 1
29 #define I8042_CTR_KBDINT 0x01
30 #define I8042_CTR_KBDDIS 0x10
32 static unsigned char i8042_ctr
;
34 static int i8042_enable_kbd_port(void)
36 if (i8042_command(&i8042_ctr
, I8042_CMD_CTL_RCTR
)) {
37 pr_err("i8042.c: Can't read CTR while enabling i8042 kbd port."
42 i8042_ctr
&= ~I8042_CTR_KBDDIS
;
43 i8042_ctr
|= I8042_CTR_KBDINT
;
45 if (i8042_command(&i8042_ctr
, I8042_CMD_CTL_WCTR
)) {
46 i8042_ctr
&= ~I8042_CTR_KBDINT
;
47 i8042_ctr
|= I8042_CTR_KBDDIS
;
48 pr_err("i8042.c: Failed to enable KBD port.\n");
56 void setup_wakeup_events(void)
60 switch (mips_machtype
) {
61 case MACH_LEMOTE_ML2F7
:
62 case MACH_LEMOTE_YL2F89
:
63 /* open the keyboard irq in i8259A */
64 outb((0xff & ~(1 << I8042_KBD_IRQ
)), PIC_MASTER_IMR
);
65 irq_mask
= inb(PIC_MASTER_IMR
);
67 /* enable keyboard port */
68 i8042_enable_kbd_port();
70 /* Wakeup CPU via SCI lid open event */
71 outb(irq_mask
& ~(1 << PIC_CASCADE_IR
), PIC_MASTER_IMR
);
73 outb(0xff & ~(1 << (SCI_IRQ_NUM
- 8)), PIC_SLAVE_IMR
);
83 static struct delayed_work lid_task
;
84 static int initialized
;
85 /* yeeloong_report_lid_status will be implemented in yeeloong_laptop.c */
86 sci_handler yeeloong_report_lid_status
;
87 EXPORT_SYMBOL(yeeloong_report_lid_status
);
88 static void yeeloong_lid_update_task(struct work_struct
*work
)
90 if (yeeloong_report_lid_status
)
91 yeeloong_report_lid_status(BIT_LID_DETECT_ON
);
94 int wakeup_loongson(void)
98 /* query the interrupt number */
99 irq
= mach_i8259_irq();
103 printk(KERN_INFO
"%s: irq = %d\n", __func__
, irq
);
105 if (irq
== I8042_KBD_IRQ
)
107 else if (irq
== SCI_IRQ_NUM
) {
109 /* query the event number */
110 ret
= ec_query_seq(CMD_GET_EVENT_NUM
);
113 sci_event
= ec_get_event_num();
116 if (sci_event
== EVENT_LID
) {
118 /* check the LID status */
119 lid_status
= ec_read(REG_LID_DETECT
);
120 /* wakeup cpu when people open the LID */
121 if (lid_status
== BIT_LID_DETECT_ON
) {
122 /* If we call it directly here, the WARNING
123 * will be sent out by getnstimeofday
124 * via "WARN_ON(timekeeping_suspended);"
125 * because we can not schedule in suspend mode.
127 if (initialized
== 0) {
128 INIT_DELAYED_WORK(&lid_task
,
129 yeeloong_lid_update_task
);
132 schedule_delayed_work(&lid_task
, 1);
141 void __weak
mach_suspend(void)
143 disable_mfgpt0_counter();
146 void __weak
mach_resume(void)
148 enable_mfgpt0_counter();