#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP) /* * tegra30_hotplug_shutdown(void) * * Powergates the current CPU. * Should never return.
*/
ENTRY(tegra30_hotplug_shutdown) /* Powergate this CPU */
mov r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
bl tegra30_cpu_shutdown
ret lr @ should never get here
ENDPROC(tegra30_hotplug_shutdown)
/* * tegra30_cpu_shutdown(unsigned long flags) * * Puts the current CPU in wait-for-event mode on the flow controller * and powergates it -- flags (in R0) indicate the request type. * * r10 = SoC ID * corrupts r0-r4, r10-r12
*/
ENTRY(tegra30_cpu_shutdown)
cpu_id r3
tegra_get_soc_id TEGRA_APB_MISC_VIRT, r10
cmp r10, #TEGRA30
bne _no_cpu0_chk @ It's not Tegra30
cmp r3, #0
reteq lr @ Must never be called for CPU 0
_no_cpu0_chk:
ldr r12, =TEGRA_FLOW_CTRL_VIRT
cpu_to_csr_reg r1, r3
add r1, r1, r12 @ virtual CSR address for this CPU
cpu_to_halt_reg r2, r3
add r2, r2, r12 @ virtual HALT_EVENTS address for this CPU
/* * Clear this CPU's "event" and "interrupt" flags and power gate * it when halting but not before it is in the "WFE" state.
*/
movw r12, \
FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG | \
FLOW_CTRL_CSR_ENABLE
cmp r10, #TEGRA30
moveq r4, #(1 << 4) @ wfe bitmap
movne r4, #(1 << 8) @ wfi bitmap
ARM( orr r12, r12, r4, lsl r3 )
THUMB( lsl r4, r4, r3 )
THUMB( orr r12, r12, r4 )
str r12, [r1]
/* Halt this CPU. */
mov r3, #0x400
delay_1:
subs r3, r3, #1 @ delay as a part of wfe war.
bge delay_1;
cpsid a @ disable imprecise aborts.
ldr r3, [r1] @ read CSR
str r3, [r1] @ clear CSR
/* flow controller set up for hotplug */
mov r3, #FLOW_CTRL_WAITEVENT @ For hotplug
b flow_ctrl_done
flow_ctrl_setting_for_lp2: /* flow controller set up for LP2 */
cmp r10, #TEGRA30
moveq r3, #FLOW_CTRL_WAIT_FOR_INTERRUPT @ For LP2
movne r3, #FLOW_CTRL_WAITEVENT
orrne r3, r3, #FLOW_CTRL_HALT_GIC_IRQ
orrne r3, r3, #FLOW_CTRL_HALT_GIC_FIQ
flow_ctrl_done:
cmp r10, #TEGRA30
str r3, [r2]
ldr r0, [r2]
b wfe_war
__cpu_reset_again:
dsb
.align 5
wfeeq @ CPU should be power gated here
wfine
wfe_war:
b __cpu_reset_again
/* * 38 nop's, which fills rest of wfe cache line and * 4 more cachelines with nop
*/
.rept 38
nop
.endr
b . @ should never get here
ENDPROC(tegra30_cpu_shutdown)
#endif
#ifdef CONFIG_PM_SLEEP /* * tegra30_sleep_core_finish(unsigned long v2p) * * Enters suspend in LP0 or LP1 by turning off the MMU and jumping to * tegra30_tear_down_core in IRAM
*/
ENTRY(tegra30_sleep_core_finish)
mov r4, r0 /* Flush, disable the L1 data cache and exit SMP */
mov r0, #TEGRA_FLUSH_CACHE_ALL
bl tegra_disable_clean_inv_dcache
mov r0, r4
/* * Preload all the address literals that are needed for the * CPU power-gating process, to avoid loading from SDRAM which * are not supported once SDRAM is put into self-refresh. * LP0 / LP1 use physical address, since the MMU needs to be * disabled before putting SDRAM into self-refresh to avoid * memory access due to page table walks.
*/
mov32 r4, TEGRA_PMC_BASE
mov32 r5, TEGRA_CLK_RESET_BASE
mov32 r6, TEGRA_FLOW_CTRL_BASE
mov32 r7, TEGRA_TMRUS_BASE
/* * tegra30_pm_secondary_cpu_suspend(unsigned long unused_arg) * * Enters LP2 on secondary CPU by exiting coherency and powergating the CPU.
*/
ENTRY(tegra30_pm_secondary_cpu_suspend)
mov r7, lr
/* Flush and disable the L1 data cache */
mov r0, #TEGRA_FLUSH_CACHE_LOUIS
bl tegra_disable_clean_inv_dcache
/* Powergate this CPU. */
mov r0, #0 @ power mode flags (!hotplug)
bl tegra30_cpu_shutdown
mov r0, #1 @ never return here
ret r7
ENDPROC(tegra30_pm_secondary_cpu_suspend)
/* * tegra30_tear_down_cpu * * Switches the CPU to enter sleep.
*/
ENTRY(tegra30_tear_down_cpu)
mov32 r6, TEGRA_FLOW_CTRL_BASE
b tegra30_enter_sleep
ENDPROC(tegra30_tear_down_cpu)
/* START OF ROUTINES COPIED TO IRAM */
.align L1_CACHE_SHIFT
.globl tegra30_iram_start
tegra30_iram_start:
/* * tegra30_lp1_reset * * reset vector for LP1 restore; copied into IRAM during suspend. * Brings the system back up to a safe staring point (SDRAM out of * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLX, * system clock running on the same PLL that it suspended at), and * jumps to tegra_resume to restore virtual addressing. * The physical address of tegra_resume expected to be stored in * PMC_SCRATCH41. * * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA.
*/
ENTRY(tegra30_lp1_reset) /* * The CPU and system bus are running at 32KHz and executing from * IRAM when this code is executed; immediately switch to CLKM and * enable PLLP, PLLM, PLLC, PLLA and PLLX.
*/
mov32 r0, TEGRA_CLK_RESET_BASE
/* * CPUFreq driver could select other PLL for CPU. PLLX will be * enabled by the Tegra30 CLK driver on an as-needed basis, see * tegra30_cpu_clock_resume().
*/
tegra_get_soc_id TEGRA_APB_MISC_BASE, r1
cmp r1, #TEGRA30
beq 1f
/* * tegra30_tear_down_core * * copied into and executed from IRAM * puts memory in self-refresh for LP0 and LP1
*/
tegra30_tear_down_core:
bl tegra30_sdram_self_refresh
bl tegra30_switch_cpu_to_clk32k
b tegra30_enter_sleep
/* * tegra30_switch_cpu_to_clk32k * * In LP0 and LP1 all PLLs will be turned off. Switching the CPU and System CLK * to the 32KHz clock. * r4 = TEGRA_PMC_BASE * r5 = TEGRA_CLK_RESET_BASE * r6 = TEGRA_FLOW_CTRL_BASE * r7 = TEGRA_TMRUS_BASE * r10= SoC ID
*/
tegra30_switch_cpu_to_clk32k: /* * start by jumping to CLKM to safely disable PLLs, then jump to * CLKS.
*/
mov r0, #(1 << 28)
str r0, [r5, #CLK_RESET_SCLK_BURST] /* 2uS delay delay between changing SCLK and CCLK */
ldr r1, [r7]
add r1, r1, #2
wait_until r1, r7, r9
str r0, [r5, #CLK_RESET_CCLK_BURST]
mov r0, #0
str r0, [r5, #CLK_RESET_CCLK_DIVIDER]
str r0, [r5, #CLK_RESET_SCLK_DIVIDER]
/* switch the clock source of mselect to be CLK_M */
ldr r0, [r5, #CLK_RESET_CLK_SOURCE_MSELECT]
orr r0, r0, #MSELECT_CLKM
str r0, [r5, #CLK_RESET_CLK_SOURCE_MSELECT]
/* * Switch to clk_s (32KHz); bits 28:31=0 * Enable burst on CPU IRQ; bit 24=1 * Set IRQ burst clock source to clk_m; bits 10:8=0
*/
mov r0, #(1 << 24)
str r0, [r5, #CLK_RESET_SCLK_BURST]
ret lr
/* * tegra30_enter_sleep * * uses flow controller to enter sleep state * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1 * executes from SDRAM with target state is LP2 * r6 = TEGRA_FLOW_CTRL_BASE
*/
tegra30_enter_sleep:
cpu_id r1
cmp r10, #TEGRA30
halted:
isb
dsb
wfine /* CPU should be power gated here */
wfeeq
/* !!!FIXME!!! Implement halt failure handler */
b halted
/* * tegra30_sdram_self_refresh * * called with MMU off and caches disabled * must be executed from IRAM * r4 = TEGRA_PMC_BASE * r5 = TEGRA_CLK_RESET_BASE * r6 = TEGRA_FLOW_CTRL_BASE * r7 = TEGRA_TMRUS_BASE * r10= SoC ID
*/
tegra30_sdram_self_refresh:
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.