0001
0002
0003
0004
0005
0006 #include <linux/init.h>
0007 #include <linux/linkage.h>
0008
0009 #include <soc/tegra/flowctrl.h>
0010 #include <soc/tegra/fuse.h>
0011
0012 #include <asm/assembler.h>
0013 #include <asm/asm-offsets.h>
0014 #include <asm/cache.h>
0015
0016 #include "iomap.h"
0017 #include "reset.h"
0018 #include "sleep.h"
0019
0020 #define PMC_SCRATCH41 0x140
0021
0022 #ifdef CONFIG_PM_SLEEP
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 ENTRY(tegra_resume)
0034 check_cpu_part_num 0xc09, r8, r9
0035 bleq v7_invalidate_l1
0036
0037 cpu_id r0
0038 cmp r0, #0 @ CPU0?
0039 THUMB( it ne )
0040 bne cpu_resume @ no
0041
0042 tegra_get_soc_id TEGRA_APB_MISC_BASE, r6
0043
0044 cmp r6, #TEGRA20
0045 beq 1f @ Yes
0046
0047 cpu_to_csr_reg r3, r0
0048 mov32 r2, TEGRA_FLOW_CTRL_BASE
0049 ldr r1, [r2, r3]
0050
0051 orr r1, r1, \
0052 #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
0053 movw r0, #0x3FFD @ enable, cluster_switch, immed, bitmaps
0054 @ & ext flags for CPU power mgnt
0055 bic r1, r1, r0
0056 str r1, [r2, r3]
0057 1:
0058
0059 mov32 r9, 0xc09
0060 cmp r8, r9
0061 bne end_ca9_scu_l2_resume
0062 #ifdef CONFIG_HAVE_ARM_SCU
0063
0064 mov32 r0, TEGRA_ARM_PERIF_BASE
0065 ldr r1, [r0]
0066 orr r1, r1, #1
0067 str r1, [r0]
0068 #endif
0069 bl tegra_resume_trusted_foundations
0070
0071 #ifdef CONFIG_CACHE_L2X0
0072
0073 bl l2c310_early_resume
0074 #endif
0075 end_ca9_scu_l2_resume:
0076 mov32 r9, 0xc0f
0077 cmp r8, r9
0078 bleq tegra_init_l2_for_a15
0079
0080 b cpu_resume
0081 ENDPROC(tegra_resume)
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091 ENTRY(tegra_resume_trusted_foundations)
0092
0093 mov32 r2, TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET
0094 ldr r1, =__tegra_cpu_reset_handler_data_offset + \
0095 RESET_DATA(TF_PRESENT)
0096 ldr r1, [r2, r1]
0097 cmp r1, #0
0098 reteq lr
0099
0100 .arch_extension sec
0101
0102
0103
0104
0105
0106 mov r0, #3
0107 smc #0
0108
0109 b cpu_resume
0110 ENDPROC(tegra_resume_trusted_foundations)
0111 #endif
0112
0113 .align L1_CACHE_SHIFT
0114 ENTRY(__tegra_cpu_reset_handler_start)
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136 .arm
0137 .align L1_CACHE_SHIFT
0138 ENTRY(__tegra_cpu_reset_handler)
0139
0140 cpsid aif, 0x13 @ SVC mode, interrupts disabled
0141
0142 tegra_get_soc_id TEGRA_APB_MISC_BASE, r6
0143
0144 adr r12, __tegra_cpu_reset_handler_data
0145 ldr r5, [r12, #RESET_DATA(TF_PRESENT)]
0146 cmp r5, #0
0147 bne after_errata
0148
0149 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
0150 t20_check:
0151 cmp r6, #TEGRA20
0152 bne after_t20_check
0153 t20_errata:
0154 # Tegra20 is a Cortex-A9 r1p1
0155 mrc p15, 0, r0, c1, c0, 0 @ read system control register
0156 orr r0, r0, #1 << 14 @ erratum 716044
0157 mcr p15, 0, r0, c1, c0, 0 @ write system control register
0158 mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register
0159 orr r0, r0, #1 << 4 @ erratum 742230
0160 orr r0, r0, #1 << 11 @ erratum 751472
0161 mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register
0162 b after_errata
0163 after_t20_check:
0164 #endif
0165 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
0166 t30_check:
0167 cmp r6, #TEGRA30
0168 bne after_t30_check
0169 t30_errata:
0170 # Tegra30 is a Cortex-A9 r2p9
0171 mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register
0172 orr r0, r0, #1 << 6 @ erratum 743622
0173 orr r0, r0, #1 << 11 @ erratum 751472
0174 mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register
0175 b after_errata
0176 after_t30_check:
0177 #endif
0178 after_errata:
0179 mrc p15, 0, r10, c0, c0, 5 @ MPIDR
0180 and r10, r10, #0x3 @ R10 = CPU number
0181 mov r11, #1
0182 mov r11, r11, lsl r10 @ R11 = CPU mask
0183
0184 #ifdef CONFIG_SMP
0185
0186 ldr r7, [r12, #RESET_DATA(MASK_PRESENT)]
0187 tst r7, r11 @ if !present
0188 bleq __die @ CPU not present (to OS)
0189 #endif
0190
0191
0192 ldr r8, [r12, #RESET_DATA(MASK_LP1)]
0193 tst r8, r11 @ if in_lp1
0194 beq __is_not_lp1
0195 cmp r10, #0
0196 bne __die @ only CPU0 can be here
0197 ldr lr, [r12, #RESET_DATA(STARTUP_LP1)]
0198 cmp lr, #0
0199 bleq __die @ no LP1 startup handler
0200 THUMB( add lr, lr, #1 ) @ switch to Thumb mode
0201 bx lr
0202 __is_not_lp1:
0203
0204
0205 ldr r9, [r12, #RESET_DATA(MASK_LP2)]
0206 tst r9, r11 @ if in_lp2
0207 beq __is_not_lp2
0208 ldr lr, [r12, #RESET_DATA(STARTUP_LP2)]
0209 cmp lr, #0
0210 bleq __die @ no LP2 startup handler
0211 bx lr
0212
0213 __is_not_lp2:
0214
0215 #ifdef CONFIG_SMP
0216
0217
0218
0219
0220 cmp r6, #TEGRA114
0221 beq __no_cpu0_chk
0222 cmp r10, #0
0223 bleq __die @ CPU0 cannot be here
0224 __no_cpu0_chk:
0225 ldr lr, [r12, #RESET_DATA(STARTUP_SECONDARY)]
0226 cmp lr, #0
0227 bleq __die @ no secondary startup handler
0228 bx lr
0229 #endif
0230
0231
0232
0233
0234
0235
0236 __die:
0237 sub lr, lr, #4
0238 mov32 r7, TEGRA_PMC_BASE
0239 str lr, [r7, #PMC_SCRATCH41]
0240
0241 mov32 r7, TEGRA_CLK_RESET_BASE
0242
0243
0244 cmp r6, #TEGRA20
0245 bne 1f
0246
0247 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
0248 mov32 r0, 0x1111
0249 mov r1, r0, lsl r10
0250 str r1, [r7, #0x340] @ CLK_RST_CPU_CMPLX_SET
0251 #endif
0252 1:
0253 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
0254 mov32 r6, TEGRA_FLOW_CTRL_BASE
0255
0256 cmp r10, #0
0257 moveq r1, #FLOW_CTRL_HALT_CPU0_EVENTS
0258 moveq r2, #FLOW_CTRL_CPU0_CSR
0259 movne r1, r10, lsl #3
0260 addne r2, r1, #(FLOW_CTRL_CPU1_CSR-8)
0261 addne r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8)
0262
0263
0264
0265 ldr r0, [r6, +r2]
0266 orr r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
0267 orr r0, r0, #FLOW_CTRL_CSR_ENABLE
0268 str r0, [r6, +r2]
0269
0270
0271 mov r0, #FLOW_CTRL_WAITEVENT
0272 str r0, [r6, +r1]
0273 ldr r0, [r6, +r1] @ memory barrier
0274
0275 dsb
0276 isb
0277 wfi @ CPU should be power gated here
0278
0279
0280
0281 mov r0, r11, lsl #8
0282 str r0, [r7, #348] @ CLK_CPU_CMPLX_SET
0283 #endif
0284
0285
0286 b .
0287 ENDPROC(__tegra_cpu_reset_handler)
0288
0289 .align L1_CACHE_SHIFT
0290 .type __tegra_cpu_reset_handler_data, %object
0291 .globl __tegra_cpu_reset_handler_data
0292 .globl __tegra_cpu_reset_handler_data_offset
0293 .equ __tegra_cpu_reset_handler_data_offset, \
0294 . - __tegra_cpu_reset_handler_start
0295 __tegra_cpu_reset_handler_data:
0296 .rept TEGRA_RESET_DATA_SIZE
0297 .long 0
0298 .endr
0299 .align L1_CACHE_SHIFT
0300
0301 ENTRY(__tegra_cpu_reset_handler_end)