linux/arch/arm/mach-tegra/sleep-tegra20.S
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
   4 * Copyright (c) 2011, Google, Inc.
   5 *
   6 * Author: Colin Cross <ccross@android.com>
   7 *         Gary King <gking@nvidia.com>
   8 */
   9
  10#include <linux/linkage.h>
  11
  12#include <soc/tegra/flowctrl.h>
  13
  14#include <asm/assembler.h>
  15#include <asm/proc-fns.h>
  16#include <asm/cp15.h>
  17#include <asm/cache.h>
  18
  19#include "irammap.h"
  20#include "reset.h"
  21#include "sleep.h"
  22
  23#define EMC_CFG                         0xc
  24#define EMC_ADR_CFG                     0x10
  25#define EMC_NOP                         0xdc
  26#define EMC_SELF_REF                    0xe0
  27#define EMC_REQ_CTRL                    0x2b0
  28#define EMC_EMC_STATUS                  0x2b4
  29
  30#define CLK_RESET_CCLK_BURST            0x20
  31#define CLK_RESET_CCLK_DIVIDER          0x24
  32#define CLK_RESET_SCLK_BURST            0x28
  33#define CLK_RESET_SCLK_DIVIDER          0x2c
  34#define CLK_RESET_PLLC_BASE             0x80
  35#define CLK_RESET_PLLM_BASE             0x90
  36#define CLK_RESET_PLLP_BASE             0xa0
  37
  38#define APB_MISC_XM2CFGCPADCTRL         0x8c8
  39#define APB_MISC_XM2CFGDPADCTRL         0x8cc
  40#define APB_MISC_XM2CLKCFGPADCTRL       0x8d0
  41#define APB_MISC_XM2COMPPADCTRL         0x8d4
  42#define APB_MISC_XM2VTTGENPADCTRL       0x8d8
  43#define APB_MISC_XM2CFGCPADCTRL2        0x8e4
  44#define APB_MISC_XM2CFGDPADCTRL2        0x8e8
  45
  46#define PLLC_STORE_MASK                 (1 << 0)
  47#define PLLM_STORE_MASK                 (1 << 1)
  48#define PLLP_STORE_MASK                 (1 << 2)
  49
  50.macro test_pll_state, rd, test_mask
  51        ldr     \rd, tegra_pll_state
  52        tst     \rd, #\test_mask
  53.endm
  54
  55.macro store_pll_state, rd, tmp, r_car_base, pll_base, pll_mask
  56        ldr     \rd, [\r_car_base, #\pll_base]
  57        tst     \rd, #(1 << 30)
  58        ldr     \rd, tegra_pll_state
  59        biceq   \rd, \rd, #\pll_mask
  60        orrne   \rd, \rd, #\pll_mask
  61        adr     \tmp, tegra_pll_state
  62        str     \rd, [\tmp]
  63.endm
  64
  65.macro pll_enable, rd, r_car_base, pll_base, test_mask
  66        test_pll_state \rd, \test_mask
  67        beq     1f
  68
  69        ldr     \rd, [\r_car_base, #\pll_base]
  70        tst     \rd, #(1 << 30)
  71        orreq   \rd, \rd, #(1 << 30)
  72        streq   \rd, [\r_car_base, #\pll_base]
  731:
  74.endm
  75
  76.macro emc_device_mask, rd, base
  77        ldr     \rd, [\base, #EMC_ADR_CFG]
  78        tst     \rd, #(0x3 << 24)
  79        moveq   \rd, #(0x1 << 8)                @ just 1 device
  80        movne   \rd, #(0x3 << 8)                @ 2 devices
  81.endm
  82
  83#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
  84/*
  85 * tegra20_hotplug_shutdown(void)
  86 *
  87 * puts the current cpu in reset
  88 * should never return
  89 */
  90ENTRY(tegra20_hotplug_shutdown)
  91        /* Put this CPU down */
  92        cpu_id  r0
  93        bl      tegra20_cpu_shutdown
  94        ret     lr                      @ should never get here
  95ENDPROC(tegra20_hotplug_shutdown)
  96
  97/*
  98 * tegra20_cpu_shutdown(int cpu)
  99 *
 100 * r0 is cpu to reset
 101 *
 102 * puts the specified CPU in wait-for-event mode on the flow controller
 103 * and puts the CPU in reset
 104 * can be called on the current cpu or another cpu
 105 * if called on the current cpu, does not return
 106 * MUST NOT BE CALLED FOR CPU 0.
 107 *
 108 * corrupts r0-r3, r12
 109 */
 110ENTRY(tegra20_cpu_shutdown)
 111        cmp     r0, #0
 112        reteq   lr                      @ must not be called for CPU 0
 113
 114        cpu_to_halt_reg r1, r0
 115        ldr     r3, =TEGRA_FLOW_CTRL_VIRT
 116        mov     r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME
 117        str     r2, [r3, r1]            @ put flow controller in wait event mode
 118        ldr     r2, [r3, r1]
 119        isb
 120        dsb
 121        movw    r1, 0x1011
 122        mov     r1, r1, lsl r0
 123        ldr     r3, =TEGRA_CLK_RESET_VIRT
 124        str     r1, [r3, #0x340]        @ put slave CPU in reset
 125        isb
 126        dsb
 127        cpu_id  r3
 128        cmp     r3, r0
 129        beq     .
 130        ret     lr
 131ENDPROC(tegra20_cpu_shutdown)
 132#endif
 133
 134#ifdef CONFIG_PM_SLEEP
 135/*
 136 * tegra20_sleep_core_finish(unsigned long v2p)
 137 *
 138 * Enters suspend in LP0 or LP1 by turning off the mmu and jumping to
 139 * tegra20_tear_down_core in IRAM
 140 */
 141ENTRY(tegra20_sleep_core_finish)
 142        mov     r4, r0
 143        /* Flush, disable the L1 data cache and exit SMP */
 144        mov     r0, #TEGRA_FLUSH_CACHE_ALL
 145        bl      tegra_disable_clean_inv_dcache
 146        mov     r0, r4
 147
 148        mov32   r3, tegra_shut_off_mmu
 149        add     r3, r3, r0
 150
 151        mov32   r0, tegra20_tear_down_core
 152        mov32   r1, tegra20_iram_start
 153        sub     r0, r0, r1
 154        mov32   r1, TEGRA_IRAM_LPx_RESUME_AREA
 155        add     r0, r0, r1
 156
 157        ret     r3
 158ENDPROC(tegra20_sleep_core_finish)
 159
 160/*
 161 * tegra20_tear_down_cpu
 162 *
 163 * Switches the CPU cluster to PLL-P and enters sleep.
 164 */
 165ENTRY(tegra20_tear_down_cpu)
 166        bl      tegra_switch_cpu_to_pllp
 167        b       tegra20_enter_sleep
 168ENDPROC(tegra20_tear_down_cpu)
 169
 170/* START OF ROUTINES COPIED TO IRAM */
 171        .align L1_CACHE_SHIFT
 172        .globl tegra20_iram_start
 173tegra20_iram_start:
 174
 175/*
 176 * tegra20_lp1_reset
 177 *
 178 * reset vector for LP1 restore; copied into IRAM during suspend.
 179 * Brings the system back up to a safe staring point (SDRAM out of
 180 * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLP,
 181 * system clock running on the same PLL that it suspended at), and
 182 * jumps to tegra_resume to restore virtual addressing and PLLX.
 183 * The physical address of tegra_resume expected to be stored in
 184 * PMC_SCRATCH41.
 185 *
 186 * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA.
 187 */
 188ENTRY(tegra20_lp1_reset)
 189        /*
 190         * The CPU and system bus are running at 32KHz and executing from
 191         * IRAM when this code is executed; immediately switch to CLKM and
 192         * enable PLLM, PLLP, PLLC.
 193         */
 194        mov32   r0, TEGRA_CLK_RESET_BASE
 195
 196        mov     r1, #(1 << 28)
 197        str     r1, [r0, #CLK_RESET_SCLK_BURST]
 198        str     r1, [r0, #CLK_RESET_CCLK_BURST]
 199        mov     r1, #0
 200        str     r1, [r0, #CLK_RESET_CCLK_DIVIDER]
 201        str     r1, [r0, #CLK_RESET_SCLK_DIVIDER]
 202
 203        pll_enable r1, r0, CLK_RESET_PLLM_BASE, PLLM_STORE_MASK
 204        pll_enable r1, r0, CLK_RESET_PLLP_BASE, PLLP_STORE_MASK
 205        pll_enable r1, r0, CLK_RESET_PLLC_BASE, PLLC_STORE_MASK
 206
 207        adr     r2, tegra20_sdram_pad_address
 208        adr     r4, tegra20_sdram_pad_save
 209        mov     r5, #0
 210
 211        ldr     r6, tegra20_sdram_pad_size
 212padload:
 213        ldr     r7, [r2, r5]            @ r7 is the addr in the pad_address
 214
 215        ldr     r1, [r4, r5]
 216        str     r1, [r7]                @ restore the value in pad_save
 217
 218        add     r5, r5, #4
 219        cmp     r6, r5
 220        bne     padload
 221
 222padload_done:
 223        /* 255uS delay for PLL stabilization */
 224        mov32   r7, TEGRA_TMRUS_BASE
 225        ldr     r1, [r7]
 226        add     r1, r1, #0xff
 227        wait_until r1, r7, r9
 228
 229        adr     r4, tegra20_sclk_save
 230        ldr     r4, [r4]
 231        str     r4, [r0, #CLK_RESET_SCLK_BURST]
 232        mov32   r4, ((1 << 28) | (4))   @ burst policy is PLLP
 233        str     r4, [r0, #CLK_RESET_CCLK_BURST]
 234
 235        mov32   r0, TEGRA_EMC_BASE
 236        ldr     r1, [r0, #EMC_CFG]
 237        bic     r1, r1, #(1 << 31)      @ disable DRAM_CLK_STOP
 238        str     r1, [r0, #EMC_CFG]
 239
 240        mov     r1, #0
 241        str     r1, [r0, #EMC_SELF_REF] @ take DRAM out of self refresh
 242        mov     r1, #1
 243        str     r1, [r0, #EMC_NOP]
 244        str     r1, [r0, #EMC_NOP]
 245
 246        emc_device_mask r1, r0
 247
 248exit_selfrefresh_loop:
 249        ldr     r2, [r0, #EMC_EMC_STATUS]
 250        ands    r2, r2, r1
 251        bne     exit_selfrefresh_loop
 252
 253        mov     r1, #0                  @ unstall all transactions
 254        str     r1, [r0, #EMC_REQ_CTRL]
 255
 256        mov32   r0, TEGRA_PMC_BASE
 257        ldr     r0, [r0, #PMC_SCRATCH41]
 258        ret     r0                      @ jump to tegra_resume
 259ENDPROC(tegra20_lp1_reset)
 260
 261/*
 262 * tegra20_tear_down_core
 263 *
 264 * copied into and executed from IRAM
 265 * puts memory in self-refresh for LP0 and LP1
 266 */
 267tegra20_tear_down_core:
 268        bl      tegra20_sdram_self_refresh
 269        bl      tegra20_switch_cpu_to_clk32k
 270        b       tegra20_enter_sleep
 271
 272/*
 273 * tegra20_switch_cpu_to_clk32k
 274 *
 275 * In LP0 and LP1 all PLLs will be turned off. Switch the CPU and system clock
 276 * to the 32KHz clock.
 277 */
 278tegra20_switch_cpu_to_clk32k:
 279        /*
 280         * start by switching to CLKM to safely disable PLLs, then switch to
 281         * CLKS.
 282         */
 283        mov     r0, #(1 << 28)
 284        str     r0, [r5, #CLK_RESET_SCLK_BURST]
 285        str     r0, [r5, #CLK_RESET_CCLK_BURST]
 286        mov     r0, #0
 287        str     r0, [r5, #CLK_RESET_CCLK_DIVIDER]
 288        str     r0, [r5, #CLK_RESET_SCLK_DIVIDER]
 289
 290        /* 2uS delay delay between changing SCLK and disabling PLLs */
 291        mov32   r7, TEGRA_TMRUS_BASE
 292        ldr     r1, [r7]
 293        add     r1, r1, #2
 294        wait_until r1, r7, r9
 295
 296        store_pll_state r0, r1, r5, CLK_RESET_PLLC_BASE, PLLC_STORE_MASK
 297        store_pll_state r0, r1, r5, CLK_RESET_PLLM_BASE, PLLM_STORE_MASK
 298        store_pll_state r0, r1, r5, CLK_RESET_PLLP_BASE, PLLP_STORE_MASK
 299
 300        /* disable PLLM, PLLP and PLLC */
 301        ldr     r0, [r5, #CLK_RESET_PLLM_BASE]
 302        bic     r0, r0, #(1 << 30)
 303        str     r0, [r5, #CLK_RESET_PLLM_BASE]
 304        ldr     r0, [r5, #CLK_RESET_PLLP_BASE]
 305        bic     r0, r0, #(1 << 30)
 306        str     r0, [r5, #CLK_RESET_PLLP_BASE]
 307        ldr     r0, [r5, #CLK_RESET_PLLC_BASE]
 308        bic     r0, r0, #(1 << 30)
 309        str     r0, [r5, #CLK_RESET_PLLC_BASE]
 310
 311        /* switch to CLKS */
 312        mov     r0, #0  /* brust policy = 32KHz */
 313        str     r0, [r5, #CLK_RESET_SCLK_BURST]
 314
 315        ret     lr
 316
 317/*
 318 * tegra20_enter_sleep
 319 *
 320 * uses flow controller to enter sleep state
 321 * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1
 322 * executes from SDRAM with target state is LP2
 323 */
 324tegra20_enter_sleep:
 325        mov32   r6, TEGRA_FLOW_CTRL_BASE
 326
 327        mov     r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT
 328        orr     r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ
 329        cpu_id  r1
 330        cpu_to_halt_reg r1, r1
 331        str     r0, [r6, r1]
 332        dsb
 333        ldr     r0, [r6, r1] /* memory barrier */
 334
 335halted:
 336        dsb
 337        wfe     /* CPU should be power gated here */
 338        isb
 339        b       halted
 340
 341/*
 342 * tegra20_sdram_self_refresh
 343 *
 344 * called with MMU off and caches disabled
 345 * puts sdram in self refresh
 346 * must be executed from IRAM
 347 */
 348tegra20_sdram_self_refresh:
 349        mov32   r1, TEGRA_EMC_BASE      @ r1 reserved for emc base addr
 350
 351        mov     r2, #3
 352        str     r2, [r1, #EMC_REQ_CTRL] @ stall incoming DRAM requests
 353
 354emcidle:
 355        ldr     r2, [r1, #EMC_EMC_STATUS]
 356        tst     r2, #4
 357        beq     emcidle
 358
 359        mov     r2, #1
 360        str     r2, [r1, #EMC_SELF_REF]
 361
 362        emc_device_mask r2, r1
 363
 364emcself:
 365        ldr     r3, [r1, #EMC_EMC_STATUS]
 366        and     r3, r3, r2
 367        cmp     r3, r2
 368        bne     emcself                 @ loop until DDR in self-refresh
 369
 370        adr     r2, tegra20_sdram_pad_address
 371        adr     r3, tegra20_sdram_pad_safe
 372        adr     r4, tegra20_sdram_pad_save
 373        mov     r5, #0
 374
 375        ldr     r6, tegra20_sdram_pad_size
 376padsave:
 377        ldr     r0, [r2, r5]            @ r0 is the addr in the pad_address
 378
 379        ldr     r1, [r0]
 380        str     r1, [r4, r5]            @ save the content of the addr
 381
 382        ldr     r1, [r3, r5]
 383        str     r1, [r0]                @ set the save val to the addr
 384
 385        add     r5, r5, #4
 386        cmp     r6, r5
 387        bne     padsave
 388padsave_done:
 389
 390        mov32   r5, TEGRA_CLK_RESET_BASE
 391        ldr     r0, [r5, #CLK_RESET_SCLK_BURST]
 392        adr     r2, tegra20_sclk_save
 393        str     r0, [r2]
 394        dsb
 395        ret     lr
 396
 397tegra20_sdram_pad_address:
 398        .word   TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL
 399        .word   TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL
 400        .word   TEGRA_APB_MISC_BASE + APB_MISC_XM2CLKCFGPADCTRL
 401        .word   TEGRA_APB_MISC_BASE + APB_MISC_XM2COMPPADCTRL
 402        .word   TEGRA_APB_MISC_BASE + APB_MISC_XM2VTTGENPADCTRL
 403        .word   TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL2
 404        .word   TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL2
 405
 406tegra20_sdram_pad_size:
 407        .word   tegra20_sdram_pad_size - tegra20_sdram_pad_address
 408
 409tegra20_sdram_pad_safe:
 410        .word   0x8
 411        .word   0x8
 412        .word   0x0
 413        .word   0x8
 414        .word   0x5500
 415        .word   0x08080040
 416        .word   0x0
 417
 418tegra20_sclk_save:
 419        .word   0x0
 420
 421tegra20_sdram_pad_save:
 422        .rept (tegra20_sdram_pad_size - tegra20_sdram_pad_address) / 4
 423        .long   0
 424        .endr
 425
 426tegra_pll_state:
 427        .word   0x0
 428
 429        .ltorg
 430/* dummy symbol for end of IRAM */
 431        .align L1_CACHE_SHIFT
 432        .globl tegra20_iram_end
 433tegra20_iram_end:
 434        b       .
 435#endif
 436