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