linux/arch/arm/mach-tegra/reset-handler.S
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2012, NVIDIA Corporation. All rights reserved.
   3 *
   4 * This program is free software; you can redistribute it and/or modify it
   5 * under the terms and conditions 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 it will be useful, but WITHOUT
   9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  11 * more details.
  12 *
  13 * You should have received a copy of the GNU General Public License
  14 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  15 */
  16
  17#include <linux/init.h>
  18#include <linux/linkage.h>
  19
  20#include <soc/tegra/flowctrl.h>
  21#include <soc/tegra/fuse.h>
  22
  23#include <asm/asm-offsets.h>
  24#include <asm/cache.h>
  25
  26#include "iomap.h"
  27#include "reset.h"
  28#include "sleep.h"
  29
  30#define PMC_SCRATCH41   0x140
  31
  32#define RESET_DATA(x)   ((TEGRA_RESET_##x)*4)
  33
  34#ifdef CONFIG_PM_SLEEP
  35/*
  36 *      tegra_resume
  37 *
  38 *        CPU boot vector when restarting the a CPU following
  39 *        an LP2 transition. Also branched to by LP0 and LP1 resume after
  40 *        re-enabling sdram.
  41 *
  42 *      r6: SoC ID
  43 *      r8: CPU part number
  44 */
  45ENTRY(tegra_resume)
  46        check_cpu_part_num 0xc09, r8, r9
  47        bleq    v7_invalidate_l1
  48
  49        cpu_id  r0
  50        cmp     r0, #0                          @ CPU0?
  51 THUMB( it      ne )
  52        bne     cpu_resume                      @ no
  53
  54        tegra_get_soc_id TEGRA_APB_MISC_BASE, r6
  55        /* Are we on Tegra20? */
  56        cmp     r6, #TEGRA20
  57        beq     1f                              @ Yes
  58        /* Clear the flow controller flags for this CPU. */
  59        cpu_to_csr_reg r1, r0
  60        mov32   r2, TEGRA_FLOW_CTRL_BASE
  61        ldr     r1, [r2, r1]
  62        /* Clear event & intr flag */
  63        orr     r1, r1, \
  64                #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
  65        movw    r0, #0x3FFD     @ enable, cluster_switch, immed, bitmaps
  66                                @ & ext flags for CPU power mgnt
  67        bic     r1, r1, r0
  68        str     r1, [r2]
  691:
  70
  71        mov32   r9, 0xc09
  72        cmp     r8, r9
  73        bne     end_ca9_scu_l2_resume
  74#ifdef CONFIG_HAVE_ARM_SCU
  75        /* enable SCU */
  76        mov32   r0, TEGRA_ARM_PERIF_BASE
  77        ldr     r1, [r0]
  78        orr     r1, r1, #1
  79        str     r1, [r0]
  80#endif
  81
  82#ifdef CONFIG_CACHE_L2X0
  83        /* L2 cache resume & re-enable */
  84        bl      l2c310_early_resume
  85#endif
  86end_ca9_scu_l2_resume:
  87        mov32   r9, 0xc0f
  88        cmp     r8, r9
  89        bleq    tegra_init_l2_for_a15
  90
  91        b       cpu_resume
  92ENDPROC(tegra_resume)
  93#endif
  94
  95        .align L1_CACHE_SHIFT
  96ENTRY(__tegra_cpu_reset_handler_start)
  97
  98/*
  99 * __tegra_cpu_reset_handler:
 100 *
 101 * Common handler for all CPU reset events.
 102 *
 103 * Register usage within the reset handler:
 104 *
 105 *      Others: scratch
 106 *      R6  = SoC ID
 107 *      R7  = CPU present (to the OS) mask
 108 *      R8  = CPU in LP1 state mask
 109 *      R9  = CPU in LP2 state mask
 110 *      R10 = CPU number
 111 *      R11 = CPU mask
 112 *      R12 = pointer to reset handler data
 113 *
 114 * NOTE: This code is copied to IRAM. All code and data accesses
 115 *       must be position-independent.
 116 */
 117
 118        .align L1_CACHE_SHIFT
 119ENTRY(__tegra_cpu_reset_handler)
 120
 121        cpsid   aif, 0x13                       @ SVC mode, interrupts disabled
 122
 123        tegra_get_soc_id TEGRA_APB_MISC_BASE, r6
 124#ifdef CONFIG_ARCH_TEGRA_2x_SOC
 125t20_check:
 126        cmp     r6, #TEGRA20
 127        bne     after_t20_check
 128t20_errata:
 129        # Tegra20 is a Cortex-A9 r1p1
 130        mrc     p15, 0, r0, c1, c0, 0   @ read system control register
 131        orr     r0, r0, #1 << 14        @ erratum 716044
 132        mcr     p15, 0, r0, c1, c0, 0   @ write system control register
 133        mrc     p15, 0, r0, c15, c0, 1  @ read diagnostic register
 134        orr     r0, r0, #1 << 4         @ erratum 742230
 135        orr     r0, r0, #1 << 11        @ erratum 751472
 136        mcr     p15, 0, r0, c15, c0, 1  @ write diagnostic register
 137        b       after_errata
 138after_t20_check:
 139#endif
 140#ifdef CONFIG_ARCH_TEGRA_3x_SOC
 141t30_check:
 142        cmp     r6, #TEGRA30
 143        bne     after_t30_check
 144t30_errata:
 145        # Tegra30 is a Cortex-A9 r2p9
 146        mrc     p15, 0, r0, c15, c0, 1  @ read diagnostic register
 147        orr     r0, r0, #1 << 6         @ erratum 743622
 148        orr     r0, r0, #1 << 11        @ erratum 751472
 149        mcr     p15, 0, r0, c15, c0, 1  @ write diagnostic register
 150        b       after_errata
 151after_t30_check:
 152#endif
 153after_errata:
 154        mrc     p15, 0, r10, c0, c0, 5          @ MPIDR
 155        and     r10, r10, #0x3                  @ R10 = CPU number
 156        mov     r11, #1
 157        mov     r11, r11, lsl r10               @ R11 = CPU mask
 158        adr     r12, __tegra_cpu_reset_handler_data
 159
 160#ifdef CONFIG_SMP
 161        /* Does the OS know about this CPU? */
 162        ldr     r7, [r12, #RESET_DATA(MASK_PRESENT)]
 163        tst     r7, r11                         @ if !present
 164        bleq    __die                           @ CPU not present (to OS)
 165#endif
 166
 167#ifdef CONFIG_ARCH_TEGRA_2x_SOC
 168        /* Are we on Tegra20? */
 169        cmp     r6, #TEGRA20
 170        bne     1f
 171        /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
 172        mov32   r5, TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET
 173        mov     r0, #CPU_NOT_RESETTABLE
 174        cmp     r10, #0
 175        strneb  r0, [r5, #__tegra20_cpu1_resettable_status_offset]
 1761:
 177#endif
 178
 179        /* Waking up from LP1? */
 180        ldr     r8, [r12, #RESET_DATA(MASK_LP1)]
 181        tst     r8, r11                         @ if in_lp1
 182        beq     __is_not_lp1
 183        cmp     r10, #0
 184        bne     __die                           @ only CPU0 can be here
 185        ldr     lr, [r12, #RESET_DATA(STARTUP_LP1)]
 186        cmp     lr, #0
 187        bleq    __die                           @ no LP1 startup handler
 188 THUMB( add     lr, lr, #1 )                    @ switch to Thumb mode
 189        bx      lr
 190__is_not_lp1:
 191
 192        /* Waking up from LP2? */
 193        ldr     r9, [r12, #RESET_DATA(MASK_LP2)]
 194        tst     r9, r11                         @ if in_lp2
 195        beq     __is_not_lp2
 196        ldr     lr, [r12, #RESET_DATA(STARTUP_LP2)]
 197        cmp     lr, #0
 198        bleq    __die                           @ no LP2 startup handler
 199        bx      lr
 200
 201__is_not_lp2:
 202
 203#ifdef CONFIG_SMP
 204        /*
 205         * Can only be secondary boot (initial or hotplug)
 206         * CPU0 can't be here for Tegra20/30
 207         */
 208        cmp     r6, #TEGRA114
 209        beq     __no_cpu0_chk
 210        cmp     r10, #0
 211        bleq    __die                           @ CPU0 cannot be here
 212__no_cpu0_chk:
 213        ldr     lr, [r12, #RESET_DATA(STARTUP_SECONDARY)]
 214        cmp     lr, #0
 215        bleq    __die                           @ no secondary startup handler
 216        bx      lr
 217#endif
 218
 219/*
 220 * We don't know why the CPU reset. Just kill it.
 221 * The LR register will contain the address we died at + 4.
 222 */
 223
 224__die:
 225        sub     lr, lr, #4
 226        mov32   r7, TEGRA_PMC_BASE
 227        str     lr, [r7, #PMC_SCRATCH41]
 228
 229        mov32   r7, TEGRA_CLK_RESET_BASE
 230
 231        /* Are we on Tegra20? */
 232        cmp     r6, #TEGRA20
 233        bne     1f
 234
 235#ifdef CONFIG_ARCH_TEGRA_2x_SOC
 236        mov32   r0, 0x1111
 237        mov     r1, r0, lsl r10
 238        str     r1, [r7, #0x340]                @ CLK_RST_CPU_CMPLX_SET
 239#endif
 2401:
 241#ifdef CONFIG_ARCH_TEGRA_3x_SOC
 242        mov32   r6, TEGRA_FLOW_CTRL_BASE
 243
 244        cmp     r10, #0
 245        moveq   r1, #FLOW_CTRL_HALT_CPU0_EVENTS
 246        moveq   r2, #FLOW_CTRL_CPU0_CSR
 247        movne   r1, r10, lsl #3
 248        addne   r2, r1, #(FLOW_CTRL_CPU1_CSR-8)
 249        addne   r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8)
 250
 251        /* Clear CPU "event" and "interrupt" flags and power gate
 252           it when halting but not before it is in the "WFI" state. */
 253        ldr     r0, [r6, +r2]
 254        orr     r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
 255        orr     r0, r0, #FLOW_CTRL_CSR_ENABLE
 256        str     r0, [r6, +r2]
 257
 258        /* Unconditionally halt this CPU */
 259        mov     r0, #FLOW_CTRL_WAITEVENT
 260        str     r0, [r6, +r1]
 261        ldr     r0, [r6, +r1]                   @ memory barrier
 262
 263        dsb
 264        isb
 265        wfi                                     @ CPU should be power gated here
 266
 267        /* If the CPU didn't power gate above just kill it's clock. */
 268
 269        mov     r0, r11, lsl #8
 270        str     r0, [r7, #348]                  @ CLK_CPU_CMPLX_SET
 271#endif
 272
 273        /* If the CPU still isn't dead, just spin here. */
 274        b       .
 275ENDPROC(__tegra_cpu_reset_handler)
 276
 277        .align L1_CACHE_SHIFT
 278        .type   __tegra_cpu_reset_handler_data, %object
 279        .globl  __tegra_cpu_reset_handler_data
 280__tegra_cpu_reset_handler_data:
 281        .rept   TEGRA_RESET_DATA_SIZE
 282        .long   0
 283        .endr
 284        .globl  __tegra20_cpu1_resettable_status_offset
 285        .equ    __tegra20_cpu1_resettable_status_offset, \
 286                                        . - __tegra_cpu_reset_handler_start
 287        .byte   0
 288        .align L1_CACHE_SHIFT
 289
 290ENTRY(__tegra_cpu_reset_handler_end)
 291