root/arch/mips/loongson64/lemote-2f/pm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. i8042_enable_kbd_port
  2. setup_wakeup_events
  3. yeeloong_lid_update_task
  4. wakeup_loongson
  5. mach_suspend
  6. mach_resume

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *  Lemote loongson2f family machines' specific suspend support
   4  *
   5  *  Copyright (C) 2009 Lemote Inc.
   6  *  Author: Wu Zhangjin <wuzhangjin@gmail.com>
   7  */
   8 
   9 #include <linux/suspend.h>
  10 #include <linux/interrupt.h>
  11 #include <linux/pm.h>
  12 #include <linux/i8042.h>
  13 #include <linux/export.h>
  14 
  15 #include <asm/i8259.h>
  16 #include <asm/mipsregs.h>
  17 #include <asm/bootinfo.h>
  18 
  19 #include <loongson.h>
  20 
  21 #include <cs5536/cs5536_mfgpt.h>
  22 #include "ec_kb3310b.h"
  23 
  24 #define I8042_KBD_IRQ           1
  25 #define I8042_CTR_KBDINT        0x01
  26 #define I8042_CTR_KBDDIS        0x10
  27 
  28 static unsigned char i8042_ctr;
  29 
  30 static int i8042_enable_kbd_port(void)
  31 {
  32         if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) {
  33                 pr_err("i8042.c: Can't read CTR while enabling i8042 kbd port."
  34                        "\n");
  35                 return -EIO;
  36         }
  37 
  38         i8042_ctr &= ~I8042_CTR_KBDDIS;
  39         i8042_ctr |= I8042_CTR_KBDINT;
  40 
  41         if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
  42                 i8042_ctr &= ~I8042_CTR_KBDINT;
  43                 i8042_ctr |= I8042_CTR_KBDDIS;
  44                 pr_err("i8042.c: Failed to enable KBD port.\n");
  45 
  46                 return -EIO;
  47         }
  48 
  49         return 0;
  50 }
  51 
  52 void setup_wakeup_events(void)
  53 {
  54         int irq_mask;
  55 
  56         switch (mips_machtype) {
  57         case MACH_LEMOTE_ML2F7:
  58         case MACH_LEMOTE_YL2F89:
  59                 /* open the keyboard irq in i8259A */
  60                 outb((0xff & ~(1 << I8042_KBD_IRQ)), PIC_MASTER_IMR);
  61                 irq_mask = inb(PIC_MASTER_IMR);
  62 
  63                 /* enable keyboard port */
  64                 i8042_enable_kbd_port();
  65 
  66                 /* Wakeup CPU via SCI lid open event */
  67                 outb(irq_mask & ~(1 << PIC_CASCADE_IR), PIC_MASTER_IMR);
  68                 inb(PIC_MASTER_IMR);
  69                 outb(0xff & ~(1 << (SCI_IRQ_NUM - 8)), PIC_SLAVE_IMR);
  70                 inb(PIC_SLAVE_IMR);
  71 
  72                 break;
  73 
  74         default:
  75                 break;
  76         }
  77 }
  78 
  79 static struct delayed_work lid_task;
  80 static int initialized;
  81 /* yeeloong_report_lid_status will be implemented in yeeloong_laptop.c */
  82 sci_handler yeeloong_report_lid_status;
  83 EXPORT_SYMBOL(yeeloong_report_lid_status);
  84 static void yeeloong_lid_update_task(struct work_struct *work)
  85 {
  86         if (yeeloong_report_lid_status)
  87                 yeeloong_report_lid_status(BIT_LID_DETECT_ON);
  88 }
  89 
  90 int wakeup_loongson(void)
  91 {
  92         int irq;
  93 
  94         /* query the interrupt number */
  95         irq = mach_i8259_irq();
  96         if (irq < 0)
  97                 return 0;
  98 
  99         printk(KERN_INFO "%s: irq = %d\n", __func__, irq);
 100 
 101         if (irq == I8042_KBD_IRQ)
 102                 return 1;
 103         else if (irq == SCI_IRQ_NUM) {
 104                 int ret, sci_event;
 105                 /* query the event number */
 106                 ret = ec_query_seq(CMD_GET_EVENT_NUM);
 107                 if (ret < 0)
 108                         return 0;
 109                 sci_event = ec_get_event_num();
 110                 if (sci_event < 0)
 111                         return 0;
 112                 if (sci_event == EVENT_LID) {
 113                         int lid_status;
 114                         /* check the LID status */
 115                         lid_status = ec_read(REG_LID_DETECT);
 116                         /* wakeup cpu when people open the LID */
 117                         if (lid_status == BIT_LID_DETECT_ON) {
 118                                 /* If we call it directly here, the WARNING
 119                                  * will be sent out by getnstimeofday
 120                                  * via "WARN_ON(timekeeping_suspended);"
 121                                  * because we can not schedule in suspend mode.
 122                                  */
 123                                 if (initialized == 0) {
 124                                         INIT_DELAYED_WORK(&lid_task,
 125                                                 yeeloong_lid_update_task);
 126                                         initialized = 1;
 127                                 }
 128                                 schedule_delayed_work(&lid_task, 1);
 129                                 return 1;
 130                         }
 131                 }
 132         }
 133 
 134         return 0;
 135 }
 136 
 137 void __weak mach_suspend(void)
 138 {
 139         disable_mfgpt0_counter();
 140 }
 141 
 142 void __weak mach_resume(void)
 143 {
 144         enable_mfgpt0_counter();
 145 }

/* [<][>][^][v][top][bottom][index][help] */