File Index
Files and directories
Sign in
FILE

pm.c

File preview with syntax highlighting.

linux-6.19.14/arch/mips/loongson2ef/lemote-2f/pm.c C
  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}
~/ Read-only file preview.