Commit 368a5b56 authored by Mao Minkai's avatar Mao Minkai Committed by guzitao
Browse files

sw64: add suspend support

Sunway inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8Y8CY



--------------------------------

Add suspend support for SW64.

Signed-off-by: default avatarMao Minkai <maominkai@wxiat.com>
Reviewed-by: default avatarHe Sheng <hesheng@wxiat.com>
Signed-off-by: default avatarGu Zitao <guzitao@wxiat.com>
parent 56aba530
Loading
Loading
Loading
Loading
+50 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_SW64_SUSPEND_H
#define _ASM_SW64_SUSPEND_H

#include <asm/hmcall.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
#define SOFTINF_SLEEP_MAGIC 0x0123456789ABCDEFUL

#ifdef CONFIG_HIBERNATION
#include <asm/vcpu.h>
#include <asm/thread_info.h>
#endif

struct callee_saved_regs {
	unsigned long r9;
	unsigned long r10;
	unsigned long r11;
	unsigned long r12;
	unsigned long r13;
	unsigned long r14;
	unsigned long r15;
	unsigned long ra;
};

struct callee_saved_fpregs {
	unsigned long f2[4];
	unsigned long f3[4];
	unsigned long f4[4];
	unsigned long f5[4];
	unsigned long f6[4];
	unsigned long f7[4];
	unsigned long f8[4];
	unsigned long f9[4];
} __aligned(32);	/* 256 bits aligned for simd */

struct processor_state {
	struct callee_saved_regs regs;
	struct callee_saved_fpregs fpregs;
	unsigned long fpcr;
	unsigned long ktp;
#ifdef CONFIG_HIBERNATION
	unsigned long sp;
	struct vcpucb vcb;
#endif
};

extern void sw64_suspend_deep_sleep(struct processor_state *state);
extern const struct platform_suspend_ops native_suspend_ops;
#endif /* _ASM_SW64_SUSPEND_H */
+57 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
#include <linux/suspend.h>

#include <asm/suspend.h>
#include <asm/sw64_init.h>

struct processor_state suspend_state;

static int native_suspend_state_valid(suspend_state_t pm_state)
{
	switch (pm_state) {
	case PM_SUSPEND_ON:
	case PM_SUSPEND_STANDBY:
	case PM_SUSPEND_MEM:
		return 1;
	default:
		return 0;
	}
}

void disable_local_timer(void)
{
	wrtimer(0);
}

extern struct pci_controller *hose_head;

/*
 * Boot Core will enter suspend stat here.
 */
void sw64_suspend_enter(void)
{
	/* boot processor will go to deep sleep mode from here
	 * After wake up  boot processor, pc will go here
	 */
	disable_local_timer();
	current_thread_info()->pcb.tp = rtid();

	sw64_suspend_deep_sleep(&suspend_state);
	wrtp(current_thread_info()->pcb.tp);

	disable_local_timer();
}

static int native_suspend_enter(suspend_state_t state)
{
	if (is_in_guest())
		return 0;
	/* processor specific suspend */
	sw64_suspend_enter();
	return 0;
}

const struct platform_suspend_ops native_suspend_ops = {
	.valid = native_suspend_state_valid,
	.enter = native_suspend_enter,
};
+99 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/page.h>
#include <asm/regdef.h>

	.text
	.set	noat
ENTRY(sw64_suspend_deep_sleep)
	/* a0 $16 will be the address of suspend_state */
	ldi	$1, PSTATE_REGS($16)
	stl	$9, CALLEE_R9($1)
	stl	$10, CALLEE_R10($1)
	stl	$11, CALLEE_R11($1)
	stl	$12, CALLEE_R12($1)
	stl	$13, CALLEE_R13($1)
	stl	$14, CALLEE_R14($1)
	stl	$15, CALLEE_R15($1)
	stl	$26, CALLEE_RA($1)
	/* SIMD-FP */
	ldi	$1, PSTATE_FPREGS($16)
	vstd	$f2, CALLEE_F2($1)
	vstd	$f3, CALLEE_F3($1)
	vstd	$f4, CALLEE_F4($1)
	vstd	$f5, CALLEE_F5($1)
	vstd	$f6, CALLEE_F6($1)
	vstd	$f7, CALLEE_F7($1)
	vstd	$f8, CALLEE_F8($1)
	vstd	$f9, CALLEE_F9($1)
	rfpcr	$f0
	fstd	$f0, PSTATE_FPCR($16)
	stl	$8, PSTATE_KTP($16)

	/* save the address of suspend_state to $18 */
	mov	$16, $18

	/*
	 * Now will Go to Deep Sleep
	 * HMcode should save  pc, gp, ps, r16, r17, r18
	 */

	sys_call HMC_sleepen
	sys_call HMC_whami
	bis	$0, $0, $16
	ldi	$17, 0x2($31)
	sys_call HMC_sendii

	/* wait for a while to receive interrupt */
	ldi	$16, 0x1($31)
	sll	$16, 24, $16
$subloop:
	subl	$16, 1, $16
	bis	$16, $16, $16
	bis	$16, $16, $16
	bne	$16, $subloop


	ldl	$8, PSTATE_KTP($18)
	ldi	$1, PSTATE_REGS($18)
	ldl	$9, CALLEE_R9($1)
	ldl	$10, CALLEE_R10($1)
	ldl	$11, CALLEE_R11($1)
	ldl	$12, CALLEE_R12($1)
	ldl	$13, CALLEE_R13($1)
	ldl	$14, CALLEE_R14($1)
	ldl	$15, CALLEE_R15($1)
	ldl	$26, CALLEE_RA($1)
	/* SIMD-FP */
	fldd	$f0, PSTATE_FPCR($18)
	wfpcr	$f0
	fimovd	$f0, $2
	and	$2, 0x3, $2
	beq	$2, $suspend_setfpec_0
	subl	$2, 0x1, $2
	beq	$2, $suspend_setfpec_1
	subl	$2, 0x1, $2
	beq	$2, $suspend_setfpec_2
	setfpec3
	br	$suspend_setfpec_over
$suspend_setfpec_0:
	setfpec0
	br	$suspend_setfpec_over
$suspend_setfpec_1:
	setfpec1
	br	$suspend_setfpec_over
$suspend_setfpec_2:
	setfpec2
$suspend_setfpec_over:
	ldi	$1, PSTATE_FPREGS($18)
	vldd	$f2, CALLEE_F2($1)
	vldd	$f3, CALLEE_F3($1)
	vldd	$f4, CALLEE_F4($1)
	vldd	$f5, CALLEE_F5($1)
	vldd	$f6, CALLEE_F6($1)
	vldd	$f7, CALLEE_F7($1)
	vldd	$f8, CALLEE_F8($1)
	vldd	$f9, CALLEE_F9($1)
	ret
END(sw64_suspend_deep_sleep)