linux/arch/arm/mach-davinci/sleep.S
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2009, Texas Instruments, Inc. http://www.ti.com/
   3 *
   4 * This program is free software; you can redistribute it and/or
   5 * modify it under the terms of the GNU General Public License
   6 * version 2 as published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope that it will be useful,
   9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE.  See the
  11 * GNU General Public License for more details.
  12 *
  13 * You should have received a copy of the GNU General Public License
  14 * along with this program; if not, write to the Free Software
  15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  16 * MA 02111-1307 USA
  17 */
  18
  19/* replicated define because linux/bitops.h cannot be included in assembly */
  20#define BIT(nr)                 (1 << (nr))
  21
  22#include <linux/linkage.h>
  23#include <asm/assembler.h>
  24#include "psc.h"
  25#include "ddr2.h"
  26
  27#include "clock.h"
  28
  29/* Arbitrary, hardware currently does not update PHYRDY correctly */
  30#define PHYRDY_CYCLES           0x1000
  31
  32/* Assume 25 MHz speed for the cycle conversions since PLLs are bypassed */
  33#define PLL_BYPASS_CYCLES       (PLL_BYPASS_TIME * 25)
  34#define PLL_RESET_CYCLES        (PLL_RESET_TIME * 25)
  35#define PLL_LOCK_CYCLES         (PLL_LOCK_TIME * 25)
  36
  37#define DEEPSLEEP_SLEEPENABLE_BIT       BIT(31)
  38
  39        .text
  40/*
  41 * Move DaVinci into deep sleep state
  42 *
  43 * Note: This code is copied to internal SRAM by PM code. When the DaVinci
  44 *       wakes up it continues execution at the point it went to sleep.
  45 * Register Usage:
  46 *      r0: contains virtual base for DDR2 controller
  47 *      r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
  48 *      r2: contains PSC number for DDR2
  49 *      r3: contains virtual base DDR2 PLL controller
  50 *      r4: contains virtual address of the DEEPSLEEP register
  51 */
  52ENTRY(davinci_cpu_suspend)
  53        stmfd   sp!, {r0-r12, lr}               @ save registers on stack
  54
  55        ldr     ip, CACHE_FLUSH
  56        blx     ip
  57
  58        ldmia   r0, {r0-r4}
  59
  60        /*
  61         * Switch DDR to self-refresh mode.
  62         */
  63
  64        /* calculate SDRCR address */
  65        ldr     ip, [r0, #DDR2_SDRCR_OFFSET]
  66        bic     ip, ip, #DDR2_SRPD_BIT
  67        orr     ip, ip, #DDR2_LPMODEN_BIT
  68        str     ip, [r0, #DDR2_SDRCR_OFFSET]
  69
  70        ldr     ip, [r0, #DDR2_SDRCR_OFFSET]
  71        orr     ip, ip, #DDR2_MCLKSTOPEN_BIT
  72        str     ip, [r0, #DDR2_SDRCR_OFFSET]
  73
  74       mov      ip, #PHYRDY_CYCLES
  751:     subs     ip, ip, #0x1
  76       bne      1b
  77
  78       /* Disable DDR2 LPSC */
  79        mov     r7, r0
  80        mov     r0, #0x2
  81        bl davinci_ddr_psc_config
  82        mov     r0, r7
  83
  84        /* Disable clock to DDR PHY */
  85        ldr     ip, [r3, #PLLDIV1]
  86        bic     ip, ip, #PLLDIV_EN
  87        str     ip, [r3, #PLLDIV1]
  88
  89        /* Put the DDR PLL in bypass and power down */
  90        ldr     ip, [r3, #PLLCTL]
  91        bic     ip, ip, #PLLCTL_PLLENSRC
  92        bic     ip, ip, #PLLCTL_PLLEN
  93        str     ip, [r3, #PLLCTL]
  94
  95        /* Wait for PLL to switch to bypass */
  96       mov      ip, #PLL_BYPASS_CYCLES
  972:     subs     ip, ip, #0x1
  98       bne      2b
  99
 100       /* Power down the PLL */
 101        ldr     ip, [r3, #PLLCTL]
 102        orr     ip, ip, #PLLCTL_PLLPWRDN
 103        str     ip, [r3, #PLLCTL]
 104
 105        /* Go to deep sleep */
 106        ldr     ip, [r4]
 107        orr     ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
 108        /* System goes to sleep beyond after this instruction */
 109        str     ip, [r4]
 110
 111        /* Wake up from sleep */
 112
 113        /* Clear sleep enable */
 114        ldr     ip, [r4]
 115        bic     ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
 116        str     ip, [r4]
 117
 118        /* initialize the DDR PLL controller */
 119
 120        /* Put PLL in reset */
 121        ldr     ip, [r3, #PLLCTL]
 122        bic     ip, ip, #PLLCTL_PLLRST
 123        str     ip, [r3, #PLLCTL]
 124
 125        /* Clear PLL power down */
 126        ldr     ip, [r3, #PLLCTL]
 127        bic     ip, ip, #PLLCTL_PLLPWRDN
 128        str     ip, [r3, #PLLCTL]
 129
 130       mov      ip, #PLL_RESET_CYCLES
 1313:     subs     ip, ip, #0x1
 132       bne      3b
 133
 134       /* Bring PLL out of reset */
 135        ldr     ip, [r3, #PLLCTL]
 136        orr     ip, ip, #PLLCTL_PLLRST
 137        str     ip, [r3, #PLLCTL]
 138
 139        /* Wait for PLL to lock (assume prediv = 1, 25MHz OSCIN) */
 140       mov      ip, #PLL_LOCK_CYCLES
 1414:     subs     ip, ip, #0x1
 142       bne      4b
 143
 144       /* Remove PLL from bypass mode */
 145        ldr     ip, [r3, #PLLCTL]
 146        bic     ip, ip, #PLLCTL_PLLENSRC
 147        orr     ip, ip, #PLLCTL_PLLEN
 148        str     ip, [r3, #PLLCTL]
 149
 150        /* Start 2x clock to DDR2 */
 151
 152        ldr     ip, [r3, #PLLDIV1]
 153        orr     ip, ip, #PLLDIV_EN
 154        str     ip, [r3, #PLLDIV1]
 155
 156        /* Enable VCLK */
 157
 158       /* Enable DDR2 LPSC */
 159        mov     r7, r0
 160        mov     r0, #0x3
 161        bl davinci_ddr_psc_config
 162        mov     r0, r7
 163
 164        /* clear  MCLKSTOPEN */
 165
 166        ldr     ip, [r0, #DDR2_SDRCR_OFFSET]
 167        bic     ip, ip, #DDR2_MCLKSTOPEN_BIT
 168        str     ip, [r0, #DDR2_SDRCR_OFFSET]
 169
 170        ldr     ip, [r0, #DDR2_SDRCR_OFFSET]
 171        bic     ip, ip, #DDR2_LPMODEN_BIT
 172        str     ip, [r0, #DDR2_SDRCR_OFFSET]
 173
 174        /* Restore registers and return */
 175        ldmfd   sp!, {r0-r12, pc}
 176
 177ENDPROC(davinci_cpu_suspend)
 178
 179/*
 180 * Disables or Enables DDR2 LPSC
 181 * Register Usage:
 182 *      r0: Enable or Disable LPSC r0 = 0x3 => Enable, r0 = 0x2 => Disable LPSC
 183 *      r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
 184 *      r2: contains PSC number for DDR2
 185 */
 186ENTRY(davinci_ddr_psc_config)
 187        /* Set next state in mdctl for DDR2 */
 188        mov     r6, #MDCTL
 189        add     r6, r6, r2, lsl #2
 190        ldr     ip, [r1, r6]
 191        bic     ip, ip, #MDSTAT_STATE_MASK
 192        orr     ip, ip, r0
 193        str     ip, [r1, r6]
 194
 195        /* Enable the Power Domain Transition Command */
 196        ldr     ip, [r1, #PTCMD]
 197        orr     ip, ip, #0x1
 198        str     ip, [r1, #PTCMD]
 199
 200        /* Check for Transition Complete (PTSTAT) */
 201ptstat_done:
 202        ldr     ip, [r1, #PTSTAT]
 203        and     ip, ip, #0x1
 204        cmp     ip, #0x0
 205        bne     ptstat_done
 206
 207        /* Check for DDR2 clock disable completion; */
 208        mov     r6, #MDSTAT
 209        add     r6, r6, r2, lsl #2
 210ddr2clk_stop_done:
 211        ldr     ip, [r1, r6]
 212        and     ip, ip, #MDSTAT_STATE_MASK
 213        cmp     ip, r0
 214        bne     ddr2clk_stop_done
 215
 216        ret     lr
 217ENDPROC(davinci_ddr_psc_config)
 218
 219CACHE_FLUSH:
 220#ifdef CONFIG_CPU_V6
 221        .word   v6_flush_kern_cache_all
 222#else
 223        .word   arm926_flush_kern_cache_all
 224#endif
 225
 226ENTRY(davinci_cpu_suspend_sz)
 227        .word   . - davinci_cpu_suspend
 228ENDPROC(davinci_cpu_suspend_sz)
 229