Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
e8c04e50
Commit
e8c04e50
authored
Mar 13, 2020
by
Thierry Reding
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-5.7/arm/core' into for-5.7/cpuidle
parents
bb6d3fb3
650a941c
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
150 additions
and
315 deletions
+150
-315
arch/arm/mach-tegra/Makefile
arch/arm/mach-tegra/Makefile
+2
-4
arch/arm/mach-tegra/cpuidle-tegra114.c
arch/arm/mach-tegra/cpuidle-tegra114.c
+5
-4
arch/arm/mach-tegra/cpuidle-tegra20.c
arch/arm/mach-tegra/cpuidle-tegra20.c
+59
-52
arch/arm/mach-tegra/cpuidle-tegra30.c
arch/arm/mach-tegra/cpuidle-tegra30.c
+9
-18
arch/arm/mach-tegra/irq.c
arch/arm/mach-tegra/irq.c
+2
-1
arch/arm/mach-tegra/pm.c
arch/arm/mach-tegra/pm.c
+32
-22
arch/arm/mach-tegra/pm.h
arch/arm/mach-tegra/pm.h
+0
-4
arch/arm/mach-tegra/reset-handler.S
arch/arm/mach-tegra/reset-handler.S
+0
-11
arch/arm/mach-tegra/reset.h
arch/arm/mach-tegra/reset.h
+2
-7
arch/arm/mach-tegra/sleep-tegra20.S
arch/arm/mach-tegra/sleep-tegra20.S
+0
-170
arch/arm/mach-tegra/sleep-tegra30.S
arch/arm/mach-tegra/sleep-tegra30.S
+3
-3
arch/arm/mach-tegra/sleep.h
arch/arm/mach-tegra/sleep.h
+0
-15
arch/arm/mach-tegra/tegra.c
arch/arm/mach-tegra/tegra.c
+0
-1
include/soc/tegra/irq.h
include/soc/tegra/irq.h
+5
-3
include/soc/tegra/pm.h
include/soc/tegra/pm.h
+31
-0
No files found.
arch/arm/mach-tegra/Makefile
View file @
e8c04e50
...
...
@@ -8,13 +8,13 @@ obj-y += reset.o
obj-y
+=
reset-handler.o
obj-y
+=
sleep.o
obj-y
+=
tegra.o
obj-y
+=
sleep-tegra20.o
obj-y
+=
sleep-tegra30.o
obj-$(CONFIG_CPU_IDLE)
+=
cpuidle.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC)
+=
sleep-tegra20.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC)
+=
pm-tegra20.o
ifeq
($(CONFIG_CPU_IDLE),y)
obj-$(CONFIG_ARCH_TEGRA_2x_SOC)
+=
cpuidle-tegra20.o
endif
obj-$(CONFIG_ARCH_TEGRA_3x_SOC)
+=
sleep-tegra30.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC)
+=
pm-tegra30.o
ifeq
($(CONFIG_CPU_IDLE),y)
obj-$(CONFIG_ARCH_TEGRA_3x_SOC)
+=
cpuidle-tegra30.o
...
...
@@ -22,12 +22,10 @@ endif
obj-$(CONFIG_SMP)
+=
platsmp.o
obj-$(CONFIG_HOTPLUG_CPU)
+=
hotplug.o
obj-$(CONFIG_ARCH_TEGRA_114_SOC)
+=
sleep-tegra30.o
obj-$(CONFIG_ARCH_TEGRA_114_SOC)
+=
pm-tegra30.o
ifeq
($(CONFIG_CPU_IDLE),y)
obj-$(CONFIG_ARCH_TEGRA_114_SOC)
+=
cpuidle-tegra114.o
endif
obj-$(CONFIG_ARCH_TEGRA_124_SOC)
+=
sleep-tegra30.o
obj-$(CONFIG_ARCH_TEGRA_124_SOC)
+=
pm-tegra30.o
ifeq
($(CONFIG_CPU_IDLE),y)
obj-$(CONFIG_ARCH_TEGRA_124_SOC)
+=
cpuidle-tegra114.o
...
...
arch/arm/mach-tegra/cpuidle-tegra114.c
View file @
e8c04e50
...
...
@@ -12,13 +12,14 @@
#include <linux/firmware/trusted_foundations.h>
#include <soc/tegra/pm.h>
#include <asm/cpuidle.h>
#include <asm/smp_plat.h>
#include <asm/suspend.h>
#include <asm/psci.h>
#include "cpuidle.h"
#include "pm.h"
#include "sleep.h"
#ifdef CONFIG_PM_SLEEP
...
...
@@ -34,17 +35,17 @@ static int tegra114_idle_power_down(struct cpuidle_device *dev,
{
local_fiq_disable
();
tegra_set_cpu_in_lp2
();
tegra_
pm_
set_cpu_in_lp2
();
cpu_pm_enter
();
call_firmware_op
(
prepare_idle
,
TF_PM_MODE_LP2_NOFLUSH_L2
);
/* Do suspend by ourselves if the firmware does not implement it */
if
(
call_firmware_op
(
do_idle
,
0
)
==
-
ENOSYS
)
cpu_suspend
(
0
,
tegra30_
sleep_cpu_secondary_finish
);
cpu_suspend
(
0
,
tegra30_
pm_secondary_cpu_suspend
);
cpu_pm_exit
();
tegra_clear_cpu_in_lp2
();
tegra_
pm_
clear_cpu_in_lp2
();
local_fiq_enable
();
...
...
arch/arm/mach-tegra/cpuidle-tegra20.c
View file @
e8c04e50
...
...
@@ -14,10 +14,13 @@
#include <linux/tick.h>
#include <linux/cpuidle.h>
#include <linux/cpu_pm.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <soc/tegra/flowctrl.h>
#include <soc/tegra/irq.h>
#include <soc/tegra/pm.h>
#include <asm/cpuidle.h>
#include <asm/smp_plat.h>
...
...
@@ -25,13 +28,11 @@
#include "cpuidle.h"
#include "iomap.h"
#include "irq.h"
#include "pm.h"
#include "reset.h"
#include "sleep.h"
#ifdef CONFIG_PM_SLEEP
static
bool
abort_flag
;
static
atomic_t
abort_flag
;
static
atomic_t
abort_barrier
;
static
int
tegra20_idle_lp2_coupled
(
struct
cpuidle_device
*
dev
,
struct
cpuidle_driver
*
drv
,
...
...
@@ -65,28 +66,8 @@ static struct cpuidle_driver tegra_idle_driver = {
#ifdef CONFIG_PM_SLEEP
#ifdef CONFIG_SMP
static
int
tegra20_reset_sleeping_cpu_1
(
void
)
{
int
ret
=
0
;
tegra_pen_lock
();
if
(
readb
(
tegra20_cpu1_resettable_status
)
==
CPU_RESETTABLE
)
tegra20_cpu_shutdown
(
1
);
else
ret
=
-
EINVAL
;
tegra_pen_unlock
();
return
ret
;
}
static
void
tegra20_wake_cpu1_from_reset
(
void
)
{
tegra_pen_lock
();
tegra20_cpu_clear_resettable
();
/* enable cpu clock on cpu */
tegra_enable_cpu_clock
(
1
);
...
...
@@ -95,45 +76,74 @@ static void tegra20_wake_cpu1_from_reset(void)
/* unhalt the cpu */
flowctrl_write_cpu_halt
(
1
,
0
);
tegra_pen_unlock
();
}
static
int
tegra20_reset_cpu_1
(
void
)
{
if
(
!
cpu_online
(
1
)
||
!
tegra20_reset_sleeping_cpu_1
())
return
0
;
tegra20_wake_cpu1_from_reset
();
return
-
EBUSY
;
}
#else
static
inline
void
tegra20_wake_cpu1_from_reset
(
void
)
{
}
#endif
static
inline
int
tegra20_reset_cpu_1
(
void
)
static
void
tegra20_report_cpus_state
(
void
)
{
return
0
;
unsigned
long
cpu
,
lcpu
,
csr
;
for_each_cpu
(
lcpu
,
cpu_possible_mask
)
{
cpu
=
cpu_logical_map
(
lcpu
);
csr
=
flowctrl_read_cpu_csr
(
cpu
);
pr_err
(
"cpu%lu: online=%d flowctrl_csr=0x%08lx
\n
"
,
cpu
,
cpu_online
(
lcpu
),
csr
);
}
}
static
int
tegra20_wait_for_secondary_cpu_parking
(
void
)
{
unsigned
int
retries
=
3
;
while
(
retries
--
)
{
unsigned
int
delay_us
=
10
;
unsigned
int
timeout_us
=
500
*
1000
/
delay_us
;
/*
* The primary CPU0 core shall wait for the secondaries
* shutdown in order to power-off CPU's cluster safely.
* The timeout value depends on the current CPU frequency,
* it takes about 40-150us in average and over 1000us in
* a worst case scenario.
*/
do
{
if
(
tegra_cpu_rail_off_ready
())
return
0
;
udelay
(
delay_us
);
}
while
(
timeout_us
--
);
pr_err
(
"secondary CPU taking too long to park
\n
"
);
tegra20_report_cpus_state
();
}
pr_err
(
"timed out waiting secondaries to park
\n
"
);
return
-
ETIMEDOUT
;
}
#endif
static
bool
tegra20_cpu_cluster_power_down
(
struct
cpuidle_device
*
dev
,
struct
cpuidle_driver
*
drv
,
int
index
)
{
while
(
tegra20_cpu_is_resettable_soon
())
cpu_relax
();
bool
ret
;
if
(
tegra20_
reset_cpu_1
()
||
!
tegra_cpu_rail_off_ready
())
if
(
tegra20_
wait_for_secondary_cpu_parking
())
return
false
;
tegra_idle_lp2_last
();
ret
=
!
tegra_pm_enter_lp2
();
if
(
cpu_online
(
1
))
tegra20_wake_cpu1_from_reset
();
return
true
;
return
ret
;
}
#ifdef CONFIG_SMP
...
...
@@ -141,9 +151,7 @@ static bool tegra20_idle_enter_lp2_cpu_1(struct cpuidle_device *dev,
struct
cpuidle_driver
*
drv
,
int
index
)
{
cpu_suspend
(
0
,
tegra20_sleep_cpu_secondary_finish
);
tegra20_cpu_clear_resettable
();
cpu_suspend
(
dev
->
cpu
,
tegra_pm_park_secondary_cpu
);
return
true
;
}
...
...
@@ -163,19 +171,20 @@ static int tegra20_idle_lp2_coupled(struct cpuidle_device *dev,
bool
entered_lp2
=
false
;
if
(
tegra_pending_sgi
())
WRITE_ONCE
(
abort_flag
,
true
);
atomic_set
(
&
abort_flag
,
1
);
cpuidle_coupled_parallel_barrier
(
dev
,
&
abort_barrier
);
if
(
a
bort_flag
)
{
if
(
a
tomic_read
(
&
abort_flag
)
)
{
cpuidle_coupled_parallel_barrier
(
dev
,
&
abort_barrier
);
abort_flag
=
false
;
/* clean flag for next coming */
/* clean flag for next coming */
atomic_set
(
&
abort_flag
,
0
);
return
-
EINTR
;
}
local_fiq_disable
();
tegra_set_cpu_in_lp2
();
tegra_
pm_
set_cpu_in_lp2
();
cpu_pm_enter
();
if
(
dev
->
cpu
==
0
)
...
...
@@ -184,12 +193,10 @@ static int tegra20_idle_lp2_coupled(struct cpuidle_device *dev,
entered_lp2
=
tegra20_idle_enter_lp2_cpu_1
(
dev
,
drv
,
index
);
cpu_pm_exit
();
tegra_clear_cpu_in_lp2
();
tegra_
pm_
clear_cpu_in_lp2
();
local_fiq_enable
();
smp_rmb
();
return
entered_lp2
?
index
:
0
;
}
#endif
...
...
arch/arm/mach-tegra/cpuidle-tegra30.c
View file @
e8c04e50
...
...
@@ -17,12 +17,13 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <soc/tegra/pm.h>
#include <asm/cpuidle.h>
#include <asm/smp_plat.h>
#include <asm/suspend.h>
#include "cpuidle.h"
#include "pm.h"
#include "sleep.h"
#ifdef CONFIG_PM_SLEEP
...
...
@@ -68,9 +69,7 @@ static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev,
return
false
;
}
tegra_idle_lp2_last
();
return
true
;
return
!
tegra_pm_enter_lp2
();
}
#ifdef CONFIG_SMP
...
...
@@ -80,7 +79,7 @@ static bool tegra30_cpu_core_power_down(struct cpuidle_device *dev,
{
smp_wmb
();
cpu_suspend
(
0
,
tegra30_
sleep_cpu_secondary_finish
);
cpu_suspend
(
0
,
tegra30_
pm_secondary_cpu_suspend
);
return
true
;
}
...
...
@@ -98,30 +97,22 @@ static int tegra30_idle_lp2(struct cpuidle_device *dev,
int
index
)
{
bool
entered_lp2
=
false
;
bool
last_cpu
;
local_fiq_disable
();
last_cpu
=
tegra
_set_cpu_in_lp2
();
tegra_pm
_set_cpu_in_lp2
();
cpu_pm_enter
();
if
(
dev
->
cpu
==
0
)
{
if
(
last_cpu
)
entered_lp2
=
tegra30_cpu_cluster_power_down
(
dev
,
drv
,
index
);
else
cpu_do_idle
();
}
else
{
if
(
dev
->
cpu
==
0
)
entered_lp2
=
tegra30_cpu_cluster_power_down
(
dev
,
drv
,
index
);
else
entered_lp2
=
tegra30_cpu_core_power_down
(
dev
,
drv
,
index
);
}
cpu_pm_exit
();
tegra_clear_cpu_in_lp2
();
tegra_
pm_
clear_cpu_in_lp2
();
local_fiq_enable
();
smp_rmb
();
return
(
entered_lp2
)
?
index
:
0
;
}
#endif
...
...
arch/arm/mach-tegra/irq.c
View file @
e8c04e50
...
...
@@ -18,9 +18,10 @@
#include <linux/of.h>
#include <linux/syscore_ops.h>
#include <soc/tegra/irq.h>
#include "board.h"
#include "iomap.h"
#include "irq.h"
#define SGI_MASK 0xFFFF
...
...
arch/arm/mach-tegra/pm.c
View file @
e8c04e50
...
...
@@ -110,7 +110,7 @@ static void suspend_cpu_complex(void)
flowctrl_cpu_suspend_enter
(
cpu
);
}
void
tegra_clear_cpu_in_lp2
(
void
)
void
tegra_
pm_
clear_cpu_in_lp2
(
void
)
{
int
phy_cpu_id
=
cpu_logical_map
(
smp_processor_id
());
u32
*
cpu_in_lp2
=
tegra_cpu_lp2_mask
;
...
...
@@ -123,11 +123,9 @@ void tegra_clear_cpu_in_lp2(void)
spin_unlock
(
&
tegra_lp2_lock
);
}
bool
tegra
_set_cpu_in_lp2
(
void
)
void
tegra_pm
_set_cpu_in_lp2
(
void
)
{
int
phy_cpu_id
=
cpu_logical_map
(
smp_processor_id
());
bool
last_cpu
=
false
;
cpumask_t
*
cpu_lp2_mask
=
tegra_cpu_lp2_mask
;
u32
*
cpu_in_lp2
=
tegra_cpu_lp2_mask
;
spin_lock
(
&
tegra_lp2_lock
);
...
...
@@ -135,22 +133,15 @@ bool tegra_set_cpu_in_lp2(void)
BUG_ON
((
*
cpu_in_lp2
&
BIT
(
phy_cpu_id
)));
*
cpu_in_lp2
|=
BIT
(
phy_cpu_id
);
if
((
phy_cpu_id
==
0
)
&&
cpumask_equal
(
cpu_lp2_mask
,
cpu_online_mask
))
last_cpu
=
true
;
else
if
(
tegra_get_chip_id
()
==
TEGRA20
&&
phy_cpu_id
==
1
)
tegra20_cpu_set_resettable_soon
();
spin_unlock
(
&
tegra_lp2_lock
);
return
last_cpu
;
}
int
tegra_cpu_do_idle
(
void
)
{
return
cpu_do_idle
();
}
static
int
tegra_sleep_cpu
(
unsigned
long
v2p
)
{
if
(
tegra_cpu_car_ops
->
rail_off_ready
&&
WARN_ON
(
!
tegra_cpu_rail_off_ready
()))
return
-
EBUSY
;
/*
* L2 cache disabling using kernel API only allowed when all
* secondary CPU's are offline. Cache have to be disabled with
...
...
@@ -159,9 +150,10 @@ static int tegra_sleep_cpu(unsigned long v2p)
* if any of secondary CPU's is online and this is the LP2-idle
* code-path only for Tegra20/30.
*/
if
(
trusted_foundations_registered
())
outer_disable
();
#ifdef CONFIG_OUTER_CACHE
if
(
trusted_foundations_registered
()
&&
outer_cache
.
disable
)
outer_cache
.
disable
();
#endif
/*
* Note that besides of setting up CPU reset vector this firmware
* call may also do the following, depending on the FW version:
...
...
@@ -202,14 +194,16 @@ static void tegra_pm_set(enum tegra_suspend_mode mode)
tegra_pmc_enter_suspend_mode
(
mode
);
}
void
tegra_idle_lp2_last
(
void
)
int
tegra_pm_enter_lp2
(
void
)
{
int
err
;
tegra_pm_set
(
TEGRA_SUSPEND_LP2
);
cpu_cluster_pm_enter
();
suspend_cpu_complex
();
cpu_suspend
(
PHYS_OFFSET
-
PAGE_OFFSET
,
&
tegra_sleep_cpu
);
err
=
cpu_suspend
(
PHYS_OFFSET
-
PAGE_OFFSET
,
&
tegra_sleep_cpu
);
/*
* Resume L2 cache if it wasn't re-enabled early during resume,
...
...
@@ -221,6 +215,8 @@ void tegra_idle_lp2_last(void)
restore_cpu_complex
();
cpu_cluster_pm_exit
();
return
err
;
}
enum
tegra_suspend_mode
tegra_pm_validate_suspend_mode
(
...
...
@@ -365,7 +361,7 @@ static int tegra_suspend_enter(suspend_state_t state)
tegra_suspend_enter_lp1
();
break
;
case
TEGRA_SUSPEND_LP2
:
tegra_set_cpu_in_lp2
();
tegra_
pm_
set_cpu_in_lp2
();
break
;
default:
break
;
...
...
@@ -386,7 +382,7 @@ static int tegra_suspend_enter(suspend_state_t state)
tegra_suspend_exit_lp1
();
break
;
case
TEGRA_SUSPEND_LP2
:
tegra_clear_cpu_in_lp2
();
tegra_
pm_
clear_cpu_in_lp2
();
break
;
default:
break
;
...
...
@@ -436,4 +432,18 @@ void __init tegra_init_suspend(void)
suspend_set_ops
(
&
tegra_suspend_ops
);
}
int
tegra_pm_park_secondary_cpu
(
unsigned
long
cpu
)
{
if
(
cpu
>
0
)
{
tegra_disable_clean_inv_dcache
(
TEGRA_FLUSH_CACHE_LOUIS
);
if
(
tegra_get_chip_id
()
==
TEGRA20
)
tegra20_hotplug_shutdown
();
else
tegra30_hotplug_shutdown
();
}
return
-
EINVAL
;
}
#endif
arch/arm/mach-tegra/pm.h
View file @
e8c04e50
...
...
@@ -23,10 +23,6 @@ void tegra20_sleep_core_init(void);
void
tegra30_lp1_iram_hook
(
void
);
void
tegra30_sleep_core_init
(
void
);
void
tegra_clear_cpu_in_lp2
(
void
);
bool
tegra_set_cpu_in_lp2
(
void
);
int
tegra_cpu_do_idle
(
void
);
void
tegra_idle_lp2_last
(
void
);
extern
void
(
*
tegra_tear_down_cpu
)(
void
);
#ifdef CONFIG_PM_SLEEP
...
...
arch/arm/mach-tegra/reset-handler.S
View file @
e8c04e50
...
...
@@ -183,17 +183,6 @@ after_errata:
bleq
__die
@
CPU
not
present
(
to
OS
)
#endif
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
/
*
Are
we
on
Tegra20
?
*/
cmp
r6
,
#
TEGRA20
bne
1
f
/
*
If
not
CPU0
,
don
't let CPU0 reset CPU1 now that CPU1 is coming up. */
mov
r0
,
#
CPU_NOT_RESETTABLE
cmp
r10
,
#
0
strbne
r0
,
[
r12
,
#
RESET_DATA
(
RESETTABLE_STATUS
)]
1
:
#endif
/
*
Waking
up
from
LP1
?
*/
ldr
r8
,
[
r12
,
#
RESET_DATA
(
MASK_LP1
)]
tst
r8
,
r11
@
if
in_lp1
...
...
arch/arm/mach-tegra/reset.h
View file @
e8c04e50
...
...
@@ -16,9 +16,8 @@
#define TEGRA_RESET_STARTUP_SECONDARY 3
#define TEGRA_RESET_STARTUP_LP2 4
#define TEGRA_RESET_STARTUP_LP1 5
#define TEGRA_RESET_RESETTABLE_STATUS 6
#define TEGRA_RESET_TF_PRESENT 7
#define TEGRA_RESET_DATA_SIZE 8
#define TEGRA_RESET_TF_PRESENT 6
#define TEGRA_RESET_DATA_SIZE 7
#define RESET_DATA(x) ((TEGRA_RESET_##x)*4)
...
...
@@ -42,10 +41,6 @@ void __tegra_cpu_reset_handler_end(void);
(IO_ADDRESS(TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET + \
((u32)&__tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_LP2] - \
(u32)__tegra_cpu_reset_handler_start)))
#define tegra20_cpu1_resettable_status \
(IO_ADDRESS(TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET + \
((u32)&__tegra_cpu_reset_handler_data[TEGRA_RESET_RESETTABLE_STATUS] - \
(u32)__tegra_cpu_reset_handler_start)))
#endif
#define tegra_cpu_reset_handler_offset \
...
...
arch/arm/mach-tegra/sleep-tegra20.S
View file @
e8c04e50
...
...
@@ -43,9 +43,6 @@
#define APB_MISC_XM2CFGCPADCTRL2 0x8e4
#define APB_MISC_XM2CFGDPADCTRL2 0x8e8
#define __tegra20_cpu1_resettable_status_offset \
(
__tegra_cpu_reset_handler_data_offset
+
RESET_DATA
(
RESETTABLE_STATUS
))
.
macro
pll_enable
,
rd
,
r_car_base
,
pll_base
ldr
\
rd
,
[
\
r_car_base
,
#
\
pll_base
]
tst
\
rd
,
#(
1
<<
30
)
...
...
@@ -90,10 +87,6 @@ ENDPROC(tegra20_hotplug_shutdown)
ENTRY
(
tegra20_cpu_shutdown
)
cmp
r0
,
#
0
reteq
lr
@
must
not
be
called
for
CPU
0
mov32
r1
,
TEGRA_IRAM_RESET_BASE_VIRT
ldr
r2
,
=
__tegra20_cpu1_resettable_status_offset
mov
r12
,
#
CPU_RESETTABLE
strb
r12
,
[
r1
,
r2
]
cpu_to_halt_reg
r1
,
r0
ldr
r3
,
=
TEGRA_FLOW_CTRL_VIRT
...
...
@@ -116,107 +109,6 @@ ENDPROC(tegra20_cpu_shutdown)
#endif
#ifdef CONFIG_PM_SLEEP
/*
*
tegra_pen_lock
*
*
spinlock
implementation
with
no
atomic
test
-
and
-
set
and
no
coherence
*
using
Peterson
's algorithm on strongly-ordered registers
*
used
to
synchronize
a
cpu
waking
up
from
wfi
with
entering
lp2
on
idle
*
*
The
reference
link
of
Peterson
's algorithm:
*
http
:
//
en
.
wikipedia
.
org
/
wiki
/
Peterson
's_algorithm
*
*
SCRATCH37
=
r1
=
!
turn
(
inverted
from
Peterson
's algorithm)
*
on
cpu
0
:
*
r2
=
flag
[
0
]
(
in
SCRATCH38
)
*
r3
=
flag
[
1
]
(
in
SCRATCH39
)
*
on
cpu1
:
*
r2
=
flag
[
1
]
(
in
SCRATCH39
)
*
r3
=
flag
[
0
]
(
in
SCRATCH38
)
*
*
must
be
called
with
MMU
on
*
corrupts
r0
-
r3
,
r12
*/
ENTRY
(
tegra_pen_lock
)
mov32
r3
,
TEGRA_PMC_VIRT
cpu_id
r0
add
r1
,
r3
,
#
PMC_SCRATCH37
cmp
r0
,
#
0
addeq
r2
,
r3
,
#
PMC_SCRATCH38
addeq
r3
,
r3
,
#
PMC_SCRATCH39
addne
r2
,
r3
,
#
PMC_SCRATCH39
addne
r3
,
r3
,
#
PMC_SCRATCH38
mov
r12
,
#
1
str
r12
,
[
r2
]
@
flag
[
cpu
]
=
1
dsb
str
r12
,
[
r1
]
@
!
turn
=
cpu
1
:
dsb
ldr
r12
,
[
r3
]
cmp
r12
,
#
1
@
flag
[!
cpu
]
==
1
?
ldreq
r12
,
[
r1
]
cmpeq
r12
,
r0
@
!
turn
==
cpu
?
beq
1
b
@
while
!
turn
==
cpu
&&
flag
[!
cpu
]
==
1
ret
lr
@
locked
ENDPROC
(
tegra_pen_lock
)
ENTRY
(
tegra_pen_unlock
)
dsb
mov32
r3
,
TEGRA_PMC_VIRT
cpu_id
r0
cmp
r0
,
#
0
addeq
r2
,
r3
,
#
PMC_SCRATCH38
addne
r2
,
r3
,
#
PMC_SCRATCH39
mov
r12
,
#
0
str
r12
,
[
r2
]
ret
lr
ENDPROC
(
tegra_pen_unlock
)
/*
*
tegra20_cpu_clear_resettable
(
void
)
*
*
Called
to
clear
the
"resettable soon"
flag
in
IRAM
variable
when
*
it
is
expected
that
the
secondary
CPU
will
be
idle
soon
.
*/
ENTRY
(
tegra20_cpu_clear_resettable
)
mov32
r1
,
TEGRA_IRAM_RESET_BASE_VIRT
ldr
r2
,
=
__tegra20_cpu1_resettable_status_offset
mov
r12
,
#
CPU_NOT_RESETTABLE
strb
r12
,
[
r1
,
r2
]
ret
lr
ENDPROC
(
tegra20_cpu_clear_resettable
)
/*
*
tegra20_cpu_set_resettable_soon
(
void
)
*
*
Called
to
set
the
"resettable soon"
flag
in
IRAM
variable
when
*
it
is
expected
that
the
secondary
CPU
will
be
idle
soon
.
*/
ENTRY
(
tegra20_cpu_set_resettable_soon
)
mov32
r1
,
TEGRA_IRAM_RESET_BASE_VIRT
ldr
r2
,
=
__tegra20_cpu1_resettable_status_offset
mov
r12
,
#
CPU_RESETTABLE_SOON
strb
r12
,
[
r1
,
r2
]
ret
lr
ENDPROC
(
tegra20_cpu_set_resettable_soon
)
/*
*
tegra20_cpu_is_resettable_soon
(
void
)
*
*
Returns
true
if
the
"resettable soon"
flag
in
IRAM
variable
has
been
*
set
because
it
is
expected
that
the
secondary
CPU
will
be
idle
soon
.
*/
ENTRY
(
tegra20_cpu_is_resettable_soon
)
mov32
r1
,
TEGRA_IRAM_RESET_BASE_VIRT
ldr
r2
,
=
__tegra20_cpu1_resettable_status_offset
ldrb
r12
,
[
r1
,
r2
]
cmp
r12
,
#
CPU_RESETTABLE_SOON
moveq
r0
,
#
1
movne
r0
,
#
0
ret
lr
ENDPROC
(
tegra20_cpu_is_resettable_soon
)
/*
*
tegra20_sleep_core_finish
(
unsigned
long
v2p
)
*
...
...
@@ -242,68 +134,6 @@ ENTRY(tegra20_sleep_core_finish)
ret
r3
ENDPROC
(
tegra20_sleep_core_finish
)
/*
*
tegra20_sleep_cpu_secondary_finish
(
unsigned
long
v2p
)
*
*
Enters
WFI
on
secondary
CPU
by
exiting
coherency
.
*/
ENTRY
(
tegra20_sleep_cpu_secondary_finish
)
stmfd
sp
!,
{
r4
-
r11
,
lr
}
mrc
p15
,
0
,
r11
,
c1
,
c0
,
1
@
save
actlr
before
exiting
coherency
/
*
Flush
and
disable
the
L1
data
cache
*/
mov
r0
,
#
TEGRA_FLUSH_CACHE_LOUIS
bl
tegra_disable_clean_inv_dcache
mov32
r0
,
TEGRA_IRAM_RESET_BASE_VIRT
ldr
r4
,
=
__tegra20_cpu1_resettable_status_offset
mov
r3
,
#
CPU_RESETTABLE
strb
r3
,
[
r0
,
r4
]
bl
tegra_cpu_do_idle
/
*
*
cpu
may
be
reset
while
in
wfi
,
which
will
return
through
*
tegra_resume
to
cpu_resume
*
or
interrupt
may
wake
wfi
,
which
will
return
here
*
cpu
state
is
unchanged
-
MMU
is
on
,
cache
is
on
,
coherency
*
is
off
,
and
the
data
cache
is
off
*
*
r11
contains
the
original
actlr
*/
bl
tegra_pen_lock
mov32
r0
,
TEGRA_IRAM_RESET_BASE_VIRT
ldr
r4
,
=
__tegra20_cpu1_resettable_status_offset
mov
r3
,
#
CPU_NOT_RESETTABLE
strb
r3
,
[
r0
,
r4
]
bl
tegra_pen_unlock
/
*
Re
-
enable
the
data
cache
*/
mrc
p15
,
0
,
r10
,
c1
,
c0
,
0
orr
r10
,
r10
,
#
CR_C
mcr
p15
,
0
,
r10
,
c1
,
c0
,
0
isb
mcr
p15
,
0
,
r11
,
c1
,
c0
,
1
@
reenable
coherency
/
*
Invalidate
the
TLBs
&
BTAC
*/
mov
r1
,
#
0
mcr
p15
,
0
,
r1
,
c8
,
c3
,
0
@
invalidate
shared
TLBs
mcr
p15
,
0
,
r1
,
c7
,
c1
,
6
@
invalidate
shared
BTAC
dsb
isb
/
*
the
cpu
was
running
with
coherency
disabled
,
*
caches
may
be
out
of
date
*/
bl
v7_flush_kern_cache_louis
ldmfd
sp
!,
{
r4
-
r11
,
pc
}
ENDPROC
(
tegra20_sleep_cpu_secondary_finish
)
/*
*
tegra20_tear_down_cpu
*
...
...
arch/arm/mach-tegra/sleep-tegra30.S
View file @
e8c04e50
...
...
@@ -265,11 +265,11 @@ ENTRY(tegra30_sleep_core_finish)
ENDPROC
(
tegra30_sleep_core_finish
)
/*
*
tegra30_
sleep_cpu_secondary_finish
(
unsigned
long
v2p
)
*
tegra30_
pm_secondary_cpu_suspend
(
unsigned
long
unused_arg
)
*
*
Enters
LP2
on
secondary
CPU
by
exiting
coherency
and
powergating
the
CPU
.
*/
ENTRY
(
tegra30_
sleep_cpu_secondary_finish
)
ENTRY
(
tegra30_
pm_secondary_cpu_suspend
)
mov
r7
,
lr
/
*
Flush
and
disable
the
L1
data
cache
*/
...
...
@@ -281,7 +281,7 @@ ENTRY(tegra30_sleep_cpu_secondary_finish)
bl
tegra30_cpu_shutdown
mov
r0
,
#
1
@
never
return
here
ret
r7
ENDPROC
(
tegra30_
sleep_cpu_secondary_finish
)
ENDPROC
(
tegra30_
pm_secondary_cpu_suspend
)
/*
*
tegra30_tear_down_cpu
...
...
arch/arm/mach-tegra/sleep.h
View file @
e8c04e50
...
...
@@ -114,29 +114,14 @@
.
endm
#else
void
tegra_pen_lock
(
void
);
void
tegra_pen_unlock
(
void
);
void
tegra_resume
(
void
);
int
tegra_sleep_cpu_finish
(
unsigned
long
);
void
tegra_disable_clean_inv_dcache
(
u32
flag
);
#ifdef CONFIG_HOTPLUG_CPU
void
tegra20_hotplug_shutdown
(
void
);
void
tegra30_hotplug_shutdown
(
void
);
#endif
void
tegra20_cpu_shutdown
(
int
cpu
);
int
tegra20_cpu_is_resettable_soon
(
void
);
void
tegra20_cpu_clear_resettable
(
void
);
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
void
tegra20_cpu_set_resettable_soon
(
void
);
#else
static
inline
void
tegra20_cpu_set_resettable_soon
(
void
)
{}
#endif
int
tegra20_sleep_cpu_secondary_finish
(
unsigned
long
);
void
tegra20_tear_down_cpu
(
void
);
int
tegra30_sleep_cpu_secondary_finish
(
unsigned
long
);
void
tegra30_tear_down_cpu
(
void
);
#endif
...
...
arch/arm/mach-tegra/tegra.c
View file @
e8c04e50
...
...
@@ -42,7 +42,6 @@
#include "common.h"
#include "cpuidle.h"
#include "iomap.h"
#include "irq.h"
#include "pm.h"
#include "reset.h"
#include "sleep.h"
...
...
arch/arm/mach-
tegra/irq.h
→
include/soc/
tegra/irq.h
View file @
e8c04e50
...
...
@@ -3,9 +3,11 @@
* Copyright (c) 2012, NVIDIA Corporation. All rights reserved.
*/
#ifndef __TEGRA_IRQ_H
#define __TEGRA_IRQ_H
#ifndef __
SOC_
TEGRA_IRQ_H
#define __
SOC_
TEGRA_IRQ_H
#if defined(CONFIG_ARM)
bool
tegra_pending_sgi
(
void
);
#endif
#endif
/* __SOC_TEGRA_IRQ_H */
include/soc/tegra/pm.h
View file @
e8c04e50
...
...
@@ -6,6 +6,8 @@
#ifndef __SOC_TEGRA_PM_H__
#define __SOC_TEGRA_PM_H__
#include <linux/errno.h>
enum
tegra_suspend_mode
{
TEGRA_SUSPEND_NONE
=
0
,
TEGRA_SUSPEND_LP2
,
/* CPU voltage off */
...
...
@@ -20,6 +22,12 @@ tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode);
/* low-level resume entry point */
void
tegra_resume
(
void
);
int
tegra30_pm_secondary_cpu_suspend
(
unsigned
long
arg
);
void
tegra_pm_clear_cpu_in_lp2
(
void
);
void
tegra_pm_set_cpu_in_lp2
(
void
);
int
tegra_pm_enter_lp2
(
void
);
int
tegra_pm_park_secondary_cpu
(
unsigned
long
cpu
);
#else
static
inline
enum
tegra_suspend_mode
tegra_pm_validate_suspend_mode
(
enum
tegra_suspend_mode
mode
)
...
...
@@ -30,6 +38,29 @@ tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode)
static
inline
void
tegra_resume
(
void
)
{
}
static
inline
int
tegra30_pm_secondary_cpu_suspend
(
unsigned
long
arg
)
{
return
-
ENOTSUPP
;
}
static
inline
void
tegra_pm_clear_cpu_in_lp2
(
void
)
{
}
static
inline
void
tegra_pm_set_cpu_in_lp2
(
void
)
{
}
static
inline
int
tegra_pm_enter_lp2
(
void
)
{
return
-
ENOTSUPP
;
}
static
inline
int
tegra_pm_park_secondary_cpu
(
unsigned
long
cpu
)
{
return
-
ENOTSUPP
;
}
#endif
/* CONFIG_PM_SLEEP */
#endif
/* __SOC_TEGRA_PM_H__ */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment