| /* |
| * File: arch/blackfin/mach-common/dpmc.S |
| * Based on: |
| * Author: LG Soft India |
| * |
| * Created: ? |
| * Description: Watchdog Timer APIs |
| * |
| * Modified: |
| * Copyright 2004-2006 Analog Devices Inc. |
| * |
| * Bugs: Enter bugs at http://blackfin.uclinux.org/ |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, see the file COPYING, or write |
| * to the Free Software Foundation, Inc., |
| * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/linkage.h> |
| #include <asm/blackfin.h> |
| #include <asm/mach/irq.h> |
| |
| .text |
| |
| ENTRY(_unmask_wdog_wakeup_evt) |
| [--SP] = ( R7:0, P5:0 ); |
| #if defined(CONFIG_BF561) |
| P0.H = hi(SICA_IWR1); |
| P0.L = lo(SICA_IWR1); |
| #elif defined(CONFIG_BF54x) || defined(CONFIG_BF52x) |
| P0.h = HI(SIC_IWR0); |
| P0.l = LO(SIC_IWR0); |
| #else |
| P0.h = HI(SIC_IWR); |
| P0.l = LO(SIC_IWR); |
| #endif |
| R7 = [P0]; |
| #if defined(CONFIG_BF561) |
| BITSET(R7, 27); |
| #else |
| BITSET(R7,(IRQ_WATCH - IVG7)); |
| #endif |
| [P0] = R7; |
| SSYNC; |
| |
| ( R7:0, P5:0 ) = [SP++]; |
| RTS; |
| |
| .LWRITE_TO_STAT: |
| /* When watch dog timer is enabled, a write to STAT will load the |
| * contents of CNT to STAT |
| */ |
| R7 = 0x0000(z); |
| #if defined(CONFIG_BF561) |
| P0.h = HI(WDOGA_STAT); |
| P0.l = LO(WDOGA_STAT); |
| #else |
| P0.h = HI(WDOG_STAT); |
| P0.l = LO(WDOG_STAT); |
| #endif |
| [P0] = R7; |
| SSYNC; |
| JUMP .LSKIP_WRITE_TO_STAT; |
| |
| ENTRY(_program_wdog_timer) |
| [--SP] = ( R7:0, P5:0 ); |
| #if defined(CONFIG_BF561) |
| P0.h = HI(WDOGA_CNT); |
| P0.l = LO(WDOGA_CNT); |
| #else |
| P0.h = HI(WDOG_CNT); |
| P0.l = LO(WDOG_CNT); |
| #endif |
| [P0] = R0; |
| SSYNC; |
| |
| #if defined(CONFIG_BF561) |
| P0.h = HI(WDOGA_CTL); |
| P0.l = LO(WDOGA_CTL); |
| #else |
| P0.h = HI(WDOG_CTL); |
| P0.l = LO(WDOG_CTL); |
| #endif |
| R7 = W[P0](Z); |
| CC = BITTST(R7,1); |
| if !CC JUMP .LWRITE_TO_STAT; |
| CC = BITTST(R7,2); |
| if !CC JUMP .LWRITE_TO_STAT; |
| |
| .LSKIP_WRITE_TO_STAT: |
| #if defined(CONFIG_BF561) |
| P0.h = HI(WDOGA_CTL); |
| P0.l = LO(WDOGA_CTL); |
| #else |
| P0.h = HI(WDOG_CTL); |
| P0.l = LO(WDOG_CTL); |
| #endif |
| R7 = W[P0](Z); |
| BITCLR(R7,1); /* Enable GP event */ |
| BITSET(R7,2); |
| W[P0] = R7.L; |
| SSYNC; |
| NOP; |
| |
| R7 = W[P0](Z); |
| BITCLR(R7,4); /* Enable the wdog counter */ |
| W[P0] = R7.L; |
| SSYNC; |
| |
| ( R7:0, P5:0 ) = [SP++]; |
| RTS; |
| |
| ENTRY(_clear_wdog_wakeup_evt) |
| [--SP] = ( R7:0, P5:0 ); |
| |
| #if defined(CONFIG_BF561) |
| P0.h = HI(WDOGA_CTL); |
| P0.l = LO(WDOGA_CTL); |
| #else |
| P0.h = HI(WDOG_CTL); |
| P0.l = LO(WDOG_CTL); |
| #endif |
| R7 = 0x0AD6(Z); |
| W[P0] = R7.L; |
| SSYNC; |
| |
| R7 = W[P0](Z); |
| BITSET(R7,15); |
| W[P0] = R7.L; |
| SSYNC; |
| |
| R7 = W[P0](Z); |
| BITSET(R7,1); |
| BITSET(R7,2); |
| W[P0] = R7.L; |
| SSYNC; |
| |
| ( R7:0, P5:0 ) = [SP++]; |
| RTS; |
| |
| ENTRY(_disable_wdog_timer) |
| [--SP] = ( R7:0, P5:0 ); |
| #if defined(CONFIG_BF561) |
| P0.h = HI(WDOGA_CTL); |
| P0.l = LO(WDOGA_CTL); |
| #else |
| P0.h = HI(WDOG_CTL); |
| P0.l = LO(WDOG_CTL); |
| #endif |
| R7 = 0xAD6(Z); |
| W[P0] = R7.L; |
| SSYNC; |
| ( R7:0, P5:0 ) = [SP++]; |
| RTS; |
| |
| #if !defined(CONFIG_BF561) |
| |
| .section .l1.text |
| |
| ENTRY(_sleep_mode) |
| [--SP] = ( R7:0, P5:0 ); |
| [--SP] = RETS; |
| |
| call _set_sic_iwr; |
| |
| R0 = 0xFFFF (Z); |
| call _set_rtc_istat; |
| |
| 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:0, P5:0 ) = [SP++]; |
| RTS; |
| |
| ENTRY(_hibernate_mode) |
| [--SP] = ( R7:0, P5:0 ); |
| [--SP] = RETS; |
| |
| call _set_sic_iwr; |
| |
| R0 = 0xFFFF (Z); |
| call _set_rtc_istat; |
| |
| P0.H = hi(VR_CTL); |
| P0.L = lo(VR_CTL); |
| R1 = W[P0](z); |
| BITSET (R1, 8); |
| BITCLR (R1, 0); |
| BITCLR (R1, 1); |
| W[P0] = R1.L; |
| SSYNC; |
| |
| CLI R2; |
| IDLE; |
| |
| /* Actually, adding anything may not be necessary...SDRAM contents |
| * are lost |
| */ |
| |
| ENTRY(_deep_sleep) |
| [--SP] = ( R7:0, P5:0 ); |
| [--SP] = RETS; |
| |
| CLI R4; |
| |
| R0 = IWR_ENABLE(0); |
| R1 = IWR_DISABLE_ALL; |
| R2 = IWR_DISABLE_ALL; |
| |
| call _set_sic_iwr; |
| |
| call _set_dram_srfs; |
| |
| /* Clear all the interrupts,bits sticky */ |
| R0 = 0xFFFF (Z); |
| call _set_rtc_istat |
| |
| P0.H = hi(PLL_CTL); |
| P0.L = lo(PLL_CTL); |
| R0 = W[P0](z); |
| BITSET (R0, 5); |
| W[P0] = R0.L; |
| |
| call _test_pll_locked; |
| |
| SSYNC; |
| IDLE; |
| |
| call _unset_dram_srfs; |
| |
| 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); |
| R0 = w[p0](z); |
| BITCLR (R0, 3); |
| BITCLR (R0, 5); |
| BITCLR (R0, 8); |
| w[p0] = R0; |
| IDLE; |
| call _test_pll_locked; |
| |
| STI R4; |
| |
| RETS = [SP++]; |
| ( R7:0, P5:0 ) = [SP++]; |
| RTS; |
| |
| ENTRY(_sleep_deeper) |
| [--SP] = ( R7:0, P5:0 ); |
| [--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 */ |
| |
| /* Clear all the interrupts,bits sticky */ |
| R0 = 0xFFFF (Z); |
| call _set_rtc_istat; |
| 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:0, P5:0 ) = [SP++]; |
| RTS; |
| |
| ENTRY(_set_dram_srfs) |
| /* set the dram to self refresh mode */ |
| #if defined(CONFIG_BF54x) |
| P0.H = hi(EBIU_RSTCTL); |
| P0.L = lo(EBIU_RSTCTL); |
| R2 = [P0]; |
| R3.H = hi(SRREQ); |
| R3.L = lo(SRREQ); |
| #else |
| P0.H = hi(EBIU_SDGCTL); |
| P0.L = lo(EBIU_SDGCTL); |
| R2 = [P0]; |
| R3.H = hi(SRFS); |
| R3.L = lo(SRFS); |
| #endif |
| R2 = R2|R3; |
| [P0] = R2; |
| ssync; |
| #if defined(CONFIG_BF54x) |
| .LSRR_MODE: |
| R2 = [P0]; |
| CC = BITTST(R2, 4); |
| if !CC JUMP .LSRR_MODE; |
| #endif |
| RTS; |
| |
| ENTRY(_unset_dram_srfs) |
| /* set the dram out of self refresh mode */ |
| #if defined(CONFIG_BF54x) |
| P0.H = hi(EBIU_RSTCTL); |
| P0.L = lo(EBIU_RSTCTL); |
| R2 = [P0]; |
| R3.H = hi(SRREQ); |
| R3.L = lo(SRREQ); |
| #else |
| P0.H = hi(EBIU_SDGCTL); |
| P0.L = lo(EBIU_SDGCTL); |
| R2 = [P0]; |
| R3.H = hi(SRFS); |
| R3.L = lo(SRFS); |
| #endif |
| R3 = ~R3; |
| R2 = R2&R3; |
| [P0] = R2; |
| ssync; |
| RTS; |
| |
| ENTRY(_set_sic_iwr) |
| #if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) |
| P0.H = hi(SIC_IWR0); |
| P0.L = lo(SIC_IWR0); |
| P1.H = hi(SIC_IWR1); |
| P1.L = lo(SIC_IWR1); |
| [P1] = R1; |
| #if defined(CONFIG_BF54x) |
| P1.H = hi(SIC_IWR2); |
| P1.L = lo(SIC_IWR2); |
| [P1] = R2; |
| #endif |
| #else |
| P0.H = hi(SIC_IWR); |
| P0.L = lo(SIC_IWR); |
| #endif |
| [P0] = R0; |
| |
| SSYNC; |
| RTS; |
| |
| ENTRY(_set_rtc_istat) |
| P0.H = hi(RTC_ISTAT); |
| P0.L = lo(RTC_ISTAT); |
| w[P0] = R0.L; |
| SSYNC; |
| RTS; |
| |
| ENTRY(_test_pll_locked) |
| P0.H = hi(PLL_STAT); |
| P0.L = lo(PLL_STAT); |
| 1: |
| R0 = W[P0] (Z); |
| CC = BITTST(R0,5); |
| IF !CC JUMP 1b; |
| RTS; |
| #endif |