162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * hibernate_asm.S:  Hibernaton support specific for sparc64.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2013 Kirill V Tkhai (tkhai@yandex.ru)
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/linkage.h>
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <asm/asm-offsets.h>
1162306a36Sopenharmony_ci#include <asm/cpudata.h>
1262306a36Sopenharmony_ci#include <asm/page.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ciENTRY(swsusp_arch_suspend)
1562306a36Sopenharmony_ci	save	%sp, -128, %sp
1662306a36Sopenharmony_ci	save	%sp, -128, %sp
1762306a36Sopenharmony_ci	flushw
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci	setuw	saved_context, %g3
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci	/* Save window regs */
2262306a36Sopenharmony_ci	rdpr	%cwp, %g2
2362306a36Sopenharmony_ci	stx	%g2, [%g3 + SC_REG_CWP]
2462306a36Sopenharmony_ci	rdpr	%wstate, %g2
2562306a36Sopenharmony_ci	stx	%g2, [%g3 + SC_REG_WSTATE]
2662306a36Sopenharmony_ci	stx	%fp, [%g3 + SC_REG_FP]
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	/* Save state regs */
2962306a36Sopenharmony_ci	rdpr	%tick, %g2
3062306a36Sopenharmony_ci	stx	%g2, [%g3 + SC_REG_TICK]
3162306a36Sopenharmony_ci	rdpr	%pstate, %g2
3262306a36Sopenharmony_ci	stx	%g2, [%g3 + SC_REG_PSTATE]
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	/* Save global regs */
3562306a36Sopenharmony_ci	stx	%g4, [%g3 + SC_REG_G4]
3662306a36Sopenharmony_ci	stx	%g5, [%g3 + SC_REG_G5]
3762306a36Sopenharmony_ci	stx	%g6, [%g3 + SC_REG_G6]
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	call	swsusp_save
4062306a36Sopenharmony_ci	 nop
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	mov	%o0, %i0
4362306a36Sopenharmony_ci	restore
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	mov	%o0, %i0
4662306a36Sopenharmony_ci	ret
4762306a36Sopenharmony_ci	 restore
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ciENTRY(swsusp_arch_resume)
5062306a36Sopenharmony_ci	/* Write restore_pblist to %l0 */
5162306a36Sopenharmony_ci	sethi	%hi(restore_pblist), %l0
5262306a36Sopenharmony_ci	ldx	[%l0 + %lo(restore_pblist)], %l0
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	call	__flush_tlb_all
5562306a36Sopenharmony_ci	 nop
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	/* Write PAGE_OFFSET to %g7 */
5862306a36Sopenharmony_ci	sethi	%hi(PAGE_OFFSET), %g7
5962306a36Sopenharmony_ci	ldx	[%g7 + %lo(PAGE_OFFSET)], %g7
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	setuw	(PAGE_SIZE-8), %g3
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	/* Use MMU Bypass */
6462306a36Sopenharmony_ci	rd	%asi, %g1
6562306a36Sopenharmony_ci	wr	%g0, ASI_PHYS_USE_EC, %asi
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	ba	fill_itlb
6862306a36Sopenharmony_ci	 nop
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cipbe_loop:
7162306a36Sopenharmony_ci	cmp	%l0, %g0
7262306a36Sopenharmony_ci	be	restore_ctx
7362306a36Sopenharmony_ci	 sub	%l0, %g7, %l0
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	ldxa	[%l0    ] %asi, %l1 /* address */
7662306a36Sopenharmony_ci	ldxa	[%l0 + 8] %asi, %l2 /* orig_address */
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	/* phys addr */
7962306a36Sopenharmony_ci	sub	%l1, %g7, %l1
8062306a36Sopenharmony_ci	sub	%l2, %g7, %l2
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	mov	%g3, %l3 /* PAGE_SIZE-8 */
8362306a36Sopenharmony_cicopy_loop:
8462306a36Sopenharmony_ci	ldxa	[%l1 + %l3] ASI_PHYS_USE_EC, %g2
8562306a36Sopenharmony_ci	stxa	%g2, [%l2 + %l3] ASI_PHYS_USE_EC
8662306a36Sopenharmony_ci	cmp	%l3, %g0
8762306a36Sopenharmony_ci	bne	copy_loop
8862306a36Sopenharmony_ci	 sub	%l3, 8, %l3
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	/* next pbe */
9162306a36Sopenharmony_ci	ba	pbe_loop
9262306a36Sopenharmony_ci	 ldxa	[%l0 + 16] %asi, %l0
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cirestore_ctx:
9562306a36Sopenharmony_ci	setuw	saved_context, %g3
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	/* Restore window regs */
9862306a36Sopenharmony_ci	wrpr    %g0, 0, %canrestore
9962306a36Sopenharmony_ci	wrpr    %g0, 0, %otherwin
10062306a36Sopenharmony_ci	wrpr	%g0, 6, %cansave
10162306a36Sopenharmony_ci	wrpr    %g0, 0, %cleanwin
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	ldxa	[%g3 + SC_REG_CWP] %asi, %g2
10462306a36Sopenharmony_ci	wrpr	%g2, %cwp
10562306a36Sopenharmony_ci	ldxa	[%g3 + SC_REG_WSTATE] %asi, %g2
10662306a36Sopenharmony_ci	wrpr	%g2, %wstate
10762306a36Sopenharmony_ci	ldxa	[%g3 + SC_REG_FP] %asi, %fp
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	/* Restore state regs */
11062306a36Sopenharmony_ci	ldxa	[%g3 + SC_REG_PSTATE] %asi, %g2
11162306a36Sopenharmony_ci	wrpr	%g2, %pstate
11262306a36Sopenharmony_ci	ldxa	[%g3 + SC_REG_TICK] %asi, %g2
11362306a36Sopenharmony_ci	wrpr	%g2, %tick
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	/* Restore global regs */
11662306a36Sopenharmony_ci	ldxa	[%g3 + SC_REG_G4] %asi, %g4
11762306a36Sopenharmony_ci	ldxa	[%g3 + SC_REG_G5] %asi, %g5
11862306a36Sopenharmony_ci	ldxa	[%g3 + SC_REG_G6] %asi, %g6
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	wr	%g1, %g0, %asi
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	restore
12362306a36Sopenharmony_ci	restore
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	wrpr	%g0, 14, %pil
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	retl
12862306a36Sopenharmony_ci	 mov	%g0, %o0
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_cifill_itlb:
13162306a36Sopenharmony_ci	ba	pbe_loop
13262306a36Sopenharmony_ci	 wrpr	%g0, 15, %pil
133