/*
* Copyright 2004-2008 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
#include <linux/linkage.h>
#include <asm/blackfin.h>
#include <mach/irq.h>
#include <asm/dpmc.h>
.section .l1.text
ENTRY(_sleep_mode)
[--SP] = (R7:4, P5:3);
[--SP] = RETS;
call _set_sic_iwr;
P0.H = hi(PLL_CTL);
P0.L = lo(PLL_CTL);
R1 = W[P0](z);
BITSET (R1, 3);
W[P0] = R1.L;
CLI R2;
SSYNC;
IDLE;
STI R2;
call _test_pll_locked;
R0 = IWR_ENABLE(0);
R1 = IWR_DISABLE_ALL;
R2 = IWR_DISABLE_ALL;
call _set_sic_iwr;
P0.H = hi(PLL_CTL);
P0.L = lo(PLL_CTL);
R7 = w[p0](z);
BITCLR (R7, 3);
BITCLR (R7, 5);
w[p0] = R7.L;
IDLE;
call _test_pll_locked;
RETS = [SP++];
(R7:4, P5:3) = [SP++];
RTS;
ENDPROC(_sleep_mode)
/*
* This func never returns as it puts the part into hibernate, and
* is only called from do_hibernate, so we don't bother saving or
* restoring any of the normal C runtime state. When we wake up,
* the entry point will be in do_hibernate and not here.
*
* We accept just one argument -- the value to write to VR_CTL.
*/
ENTRY(_hibernate_mode)
/* Save/setup the regs we need early for minor pipeline optimization */
R4 = R0;
P3.H = hi(VR_CTL);
P3.L = lo(VR_CTL);
/* Disable all wakeup sources */
R0 = IWR_DISABLE_ALL;
R1 = IWR_DISABLE_ALL;
R2 = IWR_DISABLE_ALL;
call _set_sic_iwr;
call _set_dram_srfs;
SSYNC;
/* Finally, we climb into our cave to hibernate */
W[P3] = R4.L;
CLI R2;
IDLE;
.Lforever:
jump .Lforever;
ENDPROC(_hibernate_mode)
ENTRY(_sleep_deeper)
[--SP] = (R7:4, P5:3);
[--SP] = RETS;
CLI R4;
P3 = R0;
P4 = R1;
P5 = R2;
R0 = IWR_ENABLE(0);
R1 = IWR_DISABLE_ALL;
R2 = IWR_DISABLE_ALL;
call _set_sic_iwr;
call _set_dram_srfs; /* Set SDRAM Self Refresh */
P0.H = hi(PLL_DIV);
P0.L = lo(PLL_DIV);
R6 = W[P0](z);
R0.L = 0xF;
W[P0] = R0.l; /* Set Max VCO to SCLK divider */
P0.H = hi(PLL_CTL);
P0.L = lo(PLL_CTL);
R5 = W[P0](z);
R0.L = (CONFIG_MIN_VCO_HZ/CONFIG_CLKIN_HZ) << 9;
W[P0] = R0.l; /* Set Min CLKIN to VCO multiplier */
SSYNC;
IDLE;
call _test_pll_locked;
P0.H = hi(VR_CTL);
P0.L = lo(VR_CTL);
R7 = W[P0](z);
R1 = 0x6;
R1 <<= 16;
R2 = 0x0404(Z);
R1 = R1|R2;
R2 = DEPOSIT(R7, R1);
W[P0] = R2; /* Set Min Core Voltage */
SSYNC;
IDLE;
call _test_pll_locked;
R0 = P3;
R1 = P4;
R3 = P5;
call _set_sic_iwr; /* Set Awake from IDLE */
P0.H = hi(PLL_CTL);
P0.L = lo(PLL_CTL);
R0 = W[P0](z);
BITSET (R0, 3);
W[P0] = R0.L; /* Turn CCLK OFF */
SSYNC;
IDLE;
call _test_pll_locked;
R0 = IWR_ENABLE(0);
R1 = IWR_DISABLE_ALL;
R2 = IWR_DISABLE_ALL;
call _set_sic_iwr; /* Set Awake from IDLE PLL */
P0.H = hi(VR_CTL);
P0.L = lo(VR_CTL);
W[P0]= R7;
SSYNC;
IDLE;
call _test_pll_locked;
P0.H = hi(PLL_DIV);
P0.L = lo(PLL_DIV);
W[P0]= R6; /* Restore CCLK and SCLK divider */
P0.H = hi(PLL_CTL);
P0.L = lo(PLL_CTL);
w[p0] = R5; /* Restore VCO multiplier */
IDLE;
call _test_pll_locked;
call _unset_dram_srfs; /* SDRAM Self Refresh Off */
STI R4;
RETS = [SP++];
(R7:4, P5:3) = [SP++];
RTS;
ENDPROC(_sleep_deeper)
ENTRY(_set_dram_srfs)
/* set the dram to self refresh mode */
SSYNC;
#if defined(EBIU_RSTCTL) /* DDR */
P0.H = hi(EBIU_RSTCTL);
P0.L = lo(EBIU_RSTCTL);
R2 = [P0];
BITSET(R2, 3); /* SRREQ enter self-refresh mode */
[