mirror of
https://github.com/torvalds/linux.git
synced 2024-11-29 23:51:37 +00:00
ARM: tegra114: add CPU hotplug support
The Tegra114 is a quad cores SoC. Each core can be hotplugged including CPU0. The hotplug sequence can be controlled by setting event trigger in flow controller. Then the flow controller will take care all the power sequence that include CPU up and down. Signed-off-by: Joseph Lo <josephl@nvidia.com> Signed-off-by: Stephen Warren <swarren@nvidia.com>
This commit is contained in:
parent
31972fd955
commit
33d5c01915
@ -30,6 +30,7 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
|||||||
obj-$(CONFIG_TEGRA_PCI) += pcie.o
|
obj-$(CONFIG_TEGRA_PCI) += pcie.o
|
||||||
|
|
||||||
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += tegra114_speedo.o
|
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += tegra114_speedo.o
|
||||||
|
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += sleep-tegra30.o
|
||||||
ifeq ($(CONFIG_CPU_IDLE),y)
|
ifeq ($(CONFIG_CPU_IDLE),y)
|
||||||
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += cpuidle-tegra114.o
|
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += cpuidle-tegra114.o
|
||||||
endif
|
endif
|
||||||
|
@ -55,4 +55,6 @@ void __init tegra_hotplug_init(void)
|
|||||||
tegra_hotplug_shutdown = tegra20_hotplug_shutdown;
|
tegra_hotplug_shutdown = tegra20_hotplug_shutdown;
|
||||||
if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)
|
if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)
|
||||||
tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
|
tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
|
||||||
|
if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_chip_id == TEGRA114)
|
||||||
|
tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
|
||||||
}
|
}
|
||||||
|
@ -38,18 +38,24 @@
|
|||||||
* CPU boot vector when restarting the a CPU following
|
* CPU boot vector when restarting the a CPU following
|
||||||
* an LP2 transition. Also branched to by LP0 and LP1 resume after
|
* an LP2 transition. Also branched to by LP0 and LP1 resume after
|
||||||
* re-enabling sdram.
|
* re-enabling sdram.
|
||||||
|
*
|
||||||
|
* r6: SoC ID
|
||||||
*/
|
*/
|
||||||
ENTRY(tegra_resume)
|
ENTRY(tegra_resume)
|
||||||
bl v7_invalidate_l1
|
bl v7_invalidate_l1
|
||||||
|
|
||||||
cpu_id r0
|
cpu_id r0
|
||||||
|
tegra_get_soc_id TEGRA_APB_MISC_BASE, r6
|
||||||
|
cmp r6, #TEGRA114
|
||||||
|
beq no_cpu0_chk
|
||||||
|
|
||||||
cmp r0, #0 @ CPU0?
|
cmp r0, #0 @ CPU0?
|
||||||
THUMB( it ne )
|
THUMB( it ne )
|
||||||
bne cpu_resume @ no
|
bne cpu_resume @ no
|
||||||
|
no_cpu0_chk:
|
||||||
|
|
||||||
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
|
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
|
||||||
/* Are we on Tegra20? */
|
/* Are we on Tegra20? */
|
||||||
tegra_get_soc_id TEGRA_APB_MISC_BASE, r6
|
|
||||||
cmp r6, #TEGRA20
|
cmp r6, #TEGRA20
|
||||||
beq 1f @ Yes
|
beq 1f @ Yes
|
||||||
/* Clear the flow controller flags for this CPU. */
|
/* Clear the flow controller flags for this CPU. */
|
||||||
@ -187,11 +193,14 @@ __is_not_lp2:
|
|||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
/*
|
/*
|
||||||
* Can only be secondary boot (initial or hotplug) but CPU 0
|
* Can only be secondary boot (initial or hotplug)
|
||||||
* cannot be here.
|
* CPU0 can't be here for Tegra20/30
|
||||||
*/
|
*/
|
||||||
|
cmp r6, #TEGRA114
|
||||||
|
beq __no_cpu0_chk
|
||||||
cmp r10, #0
|
cmp r10, #0
|
||||||
bleq __die @ CPU0 cannot be here
|
bleq __die @ CPU0 cannot be here
|
||||||
|
__no_cpu0_chk:
|
||||||
ldr lr, [r12, #RESET_DATA(STARTUP_SECONDARY)]
|
ldr lr, [r12, #RESET_DATA(STARTUP_SECONDARY)]
|
||||||
cmp lr, #0
|
cmp lr, #0
|
||||||
bleq __die @ no secondary startup handler
|
bleq __die @ no secondary startup handler
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <asm/assembler.h>
|
#include <asm/assembler.h>
|
||||||
#include <asm/asm-offsets.h>
|
#include <asm/asm-offsets.h>
|
||||||
|
|
||||||
|
#include "fuse.h"
|
||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
#include "flowctrl.h"
|
#include "flowctrl.h"
|
||||||
|
|
||||||
@ -43,14 +44,19 @@ ENDPROC(tegra30_hotplug_shutdown)
|
|||||||
*
|
*
|
||||||
* Puts the current CPU in wait-for-event mode on the flow controller
|
* Puts the current CPU in wait-for-event mode on the flow controller
|
||||||
* and powergates it -- flags (in R0) indicate the request type.
|
* and powergates it -- flags (in R0) indicate the request type.
|
||||||
* Must never be called for CPU 0.
|
|
||||||
*
|
*
|
||||||
* corrupts r0-r4, r12
|
* r10 = SoC ID
|
||||||
|
* corrupts r0-r4, r10-r12
|
||||||
*/
|
*/
|
||||||
ENTRY(tegra30_cpu_shutdown)
|
ENTRY(tegra30_cpu_shutdown)
|
||||||
cpu_id r3
|
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
|
cmp r3, #0
|
||||||
moveq pc, lr @ Must never be called for CPU 0
|
moveq pc, lr @ Must never be called for CPU 0
|
||||||
|
_no_cpu0_chk:
|
||||||
|
|
||||||
ldr r12, =TEGRA_FLOW_CTRL_VIRT
|
ldr r12, =TEGRA_FLOW_CTRL_VIRT
|
||||||
cpu_to_csr_reg r1, r3
|
cpu_to_csr_reg r1, r3
|
||||||
@ -65,7 +71,9 @@ ENTRY(tegra30_cpu_shutdown)
|
|||||||
movw r12, \
|
movw r12, \
|
||||||
FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG | \
|
FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG | \
|
||||||
FLOW_CTRL_CSR_ENABLE
|
FLOW_CTRL_CSR_ENABLE
|
||||||
mov r4, #(1 << 4)
|
cmp r10, #TEGRA30
|
||||||
|
moveq r4, #(1 << 4) @ wfe bitmap
|
||||||
|
movne r4, #(1 << 8) @ wfi bitmap
|
||||||
ARM( orr r12, r12, r4, lsl r3 )
|
ARM( orr r12, r12, r4, lsl r3 )
|
||||||
THUMB( lsl r4, r4, r3 )
|
THUMB( lsl r4, r4, r3 )
|
||||||
THUMB( orr r12, r12, r4 )
|
THUMB( orr r12, r12, r4 )
|
||||||
@ -79,9 +87,20 @@ delay_1:
|
|||||||
cpsid a @ disable imprecise aborts.
|
cpsid a @ disable imprecise aborts.
|
||||||
ldr r3, [r1] @ read CSR
|
ldr r3, [r1] @ read CSR
|
||||||
str r3, [r1] @ clear CSR
|
str r3, [r1] @ clear CSR
|
||||||
|
|
||||||
tst r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
|
tst r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
|
||||||
|
beq flow_ctrl_setting_for_lp2
|
||||||
|
|
||||||
|
/* 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
|
moveq r3, #FLOW_CTRL_WAIT_FOR_INTERRUPT @ For LP2
|
||||||
movne r3, #FLOW_CTRL_WAITEVENT @ For hotplug
|
movne r3, #FLOW_CTRL_WAITEVENT
|
||||||
|
flow_ctrl_done:
|
||||||
|
cmp r10, #TEGRA30
|
||||||
str r3, [r2]
|
str r3, [r2]
|
||||||
ldr r0, [r2]
|
ldr r0, [r2]
|
||||||
b wfe_war
|
b wfe_war
|
||||||
@ -89,7 +108,8 @@ delay_1:
|
|||||||
__cpu_reset_again:
|
__cpu_reset_again:
|
||||||
dsb
|
dsb
|
||||||
.align 5
|
.align 5
|
||||||
wfe @ CPU should be power gated here
|
wfeeq @ CPU should be power gated here
|
||||||
|
wfine
|
||||||
wfe_war:
|
wfe_war:
|
||||||
b __cpu_reset_again
|
b __cpu_reset_again
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
+ IO_PPSB_VIRT)
|
+ IO_PPSB_VIRT)
|
||||||
#define TEGRA_CLK_RESET_VIRT (TEGRA_CLK_RESET_BASE - IO_PPSB_PHYS \
|
#define TEGRA_CLK_RESET_VIRT (TEGRA_CLK_RESET_BASE - IO_PPSB_PHYS \
|
||||||
+ IO_PPSB_VIRT)
|
+ IO_PPSB_VIRT)
|
||||||
|
#define TEGRA_APB_MISC_VIRT (TEGRA_APB_MISC_BASE - IO_APB_PHYS \
|
||||||
|
+ IO_APB_VIRT)
|
||||||
#define TEGRA_PMC_VIRT (TEGRA_PMC_BASE - IO_APB_PHYS + IO_APB_VIRT)
|
#define TEGRA_PMC_VIRT (TEGRA_PMC_BASE - IO_APB_PHYS + IO_APB_VIRT)
|
||||||
|
|
||||||
/* PMC_SCRATCH37-39 and 41 are used for tegra_pen_lock and idle */
|
/* PMC_SCRATCH37-39 and 41 are used for tegra_pen_lock and idle */
|
||||||
|
Loading…
Reference in New Issue
Block a user