0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/suspend.h>
0010 #include <linux/interrupt.h>
0011 #include <linux/pm.h>
0012 #include <linux/i8042.h>
0013 #include <linux/export.h>
0014
0015 #include <asm/i8259.h>
0016 #include <asm/mipsregs.h>
0017 #include <asm/bootinfo.h>
0018
0019 #include <loongson.h>
0020
0021 #include <cs5536/cs5536_mfgpt.h>
0022 #include "ec_kb3310b.h"
0023
0024 #define I8042_KBD_IRQ 1
0025 #define I8042_CTR_KBDINT 0x01
0026 #define I8042_CTR_KBDDIS 0x10
0027
0028 static unsigned char i8042_ctr;
0029
0030 static int i8042_enable_kbd_port(void)
0031 {
0032 if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) {
0033 pr_err("i8042.c: Can't read CTR while enabling i8042 kbd port."
0034 "\n");
0035 return -EIO;
0036 }
0037
0038 i8042_ctr &= ~I8042_CTR_KBDDIS;
0039 i8042_ctr |= I8042_CTR_KBDINT;
0040
0041 if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
0042 i8042_ctr &= ~I8042_CTR_KBDINT;
0043 i8042_ctr |= I8042_CTR_KBDDIS;
0044 pr_err("i8042.c: Failed to enable KBD port.\n");
0045
0046 return -EIO;
0047 }
0048
0049 return 0;
0050 }
0051
0052 void setup_wakeup_events(void)
0053 {
0054 int irq_mask;
0055
0056 switch (mips_machtype) {
0057 case MACH_LEMOTE_ML2F7:
0058 case MACH_LEMOTE_YL2F89:
0059
0060 outb((0xff & ~(1 << I8042_KBD_IRQ)), PIC_MASTER_IMR);
0061 irq_mask = inb(PIC_MASTER_IMR);
0062
0063
0064 i8042_enable_kbd_port();
0065
0066
0067 outb(irq_mask & ~(1 << PIC_CASCADE_IR), PIC_MASTER_IMR);
0068 inb(PIC_MASTER_IMR);
0069 outb(0xff & ~(1 << (SCI_IRQ_NUM - 8)), PIC_SLAVE_IMR);
0070 inb(PIC_SLAVE_IMR);
0071
0072 break;
0073
0074 default:
0075 break;
0076 }
0077 }
0078
0079 static struct delayed_work lid_task;
0080 static int initialized;
0081
0082 sci_handler yeeloong_report_lid_status;
0083 EXPORT_SYMBOL(yeeloong_report_lid_status);
0084 static void yeeloong_lid_update_task(struct work_struct *work)
0085 {
0086 if (yeeloong_report_lid_status)
0087 yeeloong_report_lid_status(BIT_LID_DETECT_ON);
0088 }
0089
0090 int wakeup_loongson(void)
0091 {
0092 int irq;
0093
0094
0095 irq = mach_i8259_irq();
0096 if (irq < 0)
0097 return 0;
0098
0099 printk(KERN_INFO "%s: irq = %d\n", __func__, irq);
0100
0101 if (irq == I8042_KBD_IRQ)
0102 return 1;
0103 else if (irq == SCI_IRQ_NUM) {
0104 int ret, sci_event;
0105
0106 ret = ec_query_seq(CMD_GET_EVENT_NUM);
0107 if (ret < 0)
0108 return 0;
0109 sci_event = ec_get_event_num();
0110 if (sci_event < 0)
0111 return 0;
0112 if (sci_event == EVENT_LID) {
0113 int lid_status;
0114
0115 lid_status = ec_read(REG_LID_DETECT);
0116
0117 if (lid_status == BIT_LID_DETECT_ON) {
0118
0119
0120
0121
0122
0123 if (initialized == 0) {
0124 INIT_DELAYED_WORK(&lid_task,
0125 yeeloong_lid_update_task);
0126 initialized = 1;
0127 }
0128 schedule_delayed_work(&lid_task, 1);
0129 return 1;
0130 }
0131 }
0132 }
0133
0134 return 0;
0135 }
0136
0137 void __weak mach_suspend(void)
0138 {
0139 disable_mfgpt0_counter();
0140 }
0141
0142 void __weak mach_resume(void)
0143 {
0144 enable_mfgpt0_counter();
0145 }