cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pm.c (3168B)


      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
     28static unsigned char i8042_ctr;
     29
     30static 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
     52void 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
     79static struct delayed_work lid_task;
     80static int initialized;
     81/* yeeloong_report_lid_status will be implemented in yeeloong_laptop.c */
     82sci_handler yeeloong_report_lid_status;
     83EXPORT_SYMBOL(yeeloong_report_lid_status);
     84static 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
     90int 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
    137void __weak mach_suspend(void)
    138{
    139	disable_mfgpt0_counter();
    140}
    141
    142void __weak mach_resume(void)
    143{
    144	enable_mfgpt0_counter();
    145}