Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
Arm Trusted Firmware
Commits
c38b36d8
Commit
c38b36d8
authored
Jan 26, 2017
by
danh-arm
Committed by
GitHub
Jan 26, 2017
Browse files
Merge pull request #814 from freedomtan/patches-for-8173-crbook-osi-0110
Patches for 8173 crbook
parents
d7aa7b44
201d535f
Changes
11
Show whitespace changes
Inline
Side-by-side
plat/mediatek/mt8173/aarch64/plat_helpers.S
View file @
c38b36d8
...
...
@@ -34,6 +34,7 @@
.
globl
plat_secondary_cold_boot_setup
.
globl
plat_report_exception
.
globl
platform_is_primary_cpu
.
globl
plat_my_core_pos
.
globl
plat_crash_console_init
.
globl
plat_crash_console_putc
...
...
@@ -59,6 +60,22 @@ func platform_is_primary_cpu
ret
endfunc
platform_is_primary_cpu
#if !ENABLE_PLAT_COMPAT
/
*
-----------------------------------------------------
*
unsigned
int
plat_my_core_pos
(
void
)
;
*
*
result
:
CorePos
=
CoreId
+
(
ClusterId
<<
2
)
*
-----------------------------------------------------
*/
func
plat_my_core_pos
mrs
x0
,
mpidr_el1
and
x1
,
x0
,
#
MPIDR_CPU_MASK
and
x0
,
x0
,
#
MPIDR_CLUSTER_MASK
add
x0
,
x1
,
x0
,
LSR
#
6
ret
endfunc
plat_my_core_pos
#endif
/
*
---------------------------------------------
*
int
plat_crash_console_init
(
void
)
*
Function
to
initialize
the
crash
console
...
...
plat/mediatek/mt8173/bl31_plat_setup.c
View file @
c38b36d8
...
...
@@ -27,7 +27,6 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <arm_gic.h>
#include <assert.h>
#include <bl_common.h>
#include <common_def.h>
...
...
@@ -37,6 +36,7 @@
#include <mcucfg.h>
#include <mmio.h>
#include <mtcmos.h>
#include <plat_arm.h>
#include <plat_private.h>
#include <platform.h>
#include <spm.h>
...
...
@@ -159,11 +159,13 @@ void bl31_platform_setup(void)
generic_delay_timer_init
();
/* Initialize the gic cpu and distributor interfaces */
plat_m
t
_gic_init
();
arm_gic_
setup
();
plat_
ar
m_gic_
driver_
init
();
plat_
arm_gic_
init
();
#if ENABLE_PLAT_COMPAT
/* Topologies are best known to the platform. */
mt_setup_topology
();
#endif
/* Initialize spm at boot time */
spm_boot_init
();
...
...
plat/mediatek/mt8173/drivers/spm/spm_hotplug.c
View file @
c38b36d8
...
...
@@ -27,6 +27,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <arch.h>
#include <mmio.h>
#include <mt8173_def.h>
#include <platform.h>
...
...
@@ -258,7 +259,9 @@ void spm_hotplug_on(unsigned long mpidr)
{
unsigned
long
linear_id
;
linear_id
=
platform_get_core_pos
(
mpidr
);
linear_id
=
((
mpidr
&
MPIDR_CLUSTER_MASK
)
>>
6
)
|
(
mpidr
&
MPIDR_CPU_MASK
);
spm_lock_get
();
if
(
is_hotplug_ready
()
==
0
)
{
spm_mcdi_wakeup_all_cores
();
...
...
@@ -277,7 +280,9 @@ void spm_hotplug_off(unsigned long mpidr)
{
unsigned
long
linear_id
;
linear_id
=
platform_get_core_pos
(
mpidr
);
linear_id
=
((
mpidr
&
MPIDR_CLUSTER_MASK
)
>>
6
)
|
(
mpidr
&
MPIDR_CPU_MASK
);
spm_lock_get
();
if
(
is_hotplug_ready
()
==
0
)
{
spm_mcdi_wakeup_all_cores
();
...
...
plat/mediatek/mt8173/drivers/spm/spm_mcdi.c
View file @
c38b36d8
...
...
@@ -511,7 +511,10 @@ void spm_mcdi_prepare_for_off_state(unsigned long mpidr, unsigned int afflvl)
void
spm_mcdi_finish_for_on_state
(
unsigned
long
mpidr
,
unsigned
int
afflvl
)
{
unsigned
long
linear_id
=
platform_get_core_pos
(
mpidr
);
unsigned
long
linear_id
;
linear_id
=
((
mpidr
&
MPIDR_CLUSTER_MASK
)
>>
6
)
|
(
mpidr
&
MPIDR_CPU_MASK
);
spm_lock_get
();
spm_mcdi_clear_cputop_pwrctrl_for_cluster_on
(
mpidr
);
...
...
plat/mediatek/mt8173/include/mt8173_def.h
View file @
c38b36d8
...
...
@@ -126,4 +126,51 @@
#define MT_IRQ_SEC_SGI_6 14
#define MT_IRQ_SEC_SGI_7 15
/*
* Macros for local power states in MTK platforms encoded by State-ID field
* within the power-state parameter.
*/
/* Local power state for power domains in Run state. */
#define MTK_LOCAL_STATE_RUN 0
/* Local power state for retention. Valid only for CPU power domains */
#define MTK_LOCAL_STATE_RET 1
/* Local power state for OFF/power-down. Valid for CPU and cluster power
* domains
*/
#define MTK_LOCAL_STATE_OFF 2
#if PSCI_EXTENDED_STATE_ID
/*
* Macros used to parse state information from State-ID if it is using the
* recommended encoding for State-ID.
*/
#define MTK_LOCAL_PSTATE_WIDTH 4
#define MTK_LOCAL_PSTATE_MASK ((1 << MTK_LOCAL_PSTATE_WIDTH) - 1)
/* Macros to construct the composite power state */
/* Make composite power state parameter till power level 0 */
#define mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
(((lvl0_state) << PSTATE_ID_SHIFT) | ((type) << PSTATE_TYPE_SHIFT))
#else
#define mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
(((lvl0_state) << PSTATE_ID_SHIFT) | \
((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \
((type) << PSTATE_TYPE_SHIFT))
#endif
/* __PSCI_EXTENDED_STATE_ID__ */
/* Make composite power state parameter till power level 1 */
#define mtk_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \
(((lvl1_state) << MTK_LOCAL_PSTATE_WIDTH) | \
mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type))
/* Make composite power state parameter till power level 2 */
#define mtk_make_pwrstate_lvl2( \
lvl2_state, lvl1_state, lvl0_state, pwr_lvl, type) \
(((lvl2_state) << (MTK_LOCAL_PSTATE_WIDTH * 2)) | \
mtk_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type))
#endif
/* __MT8173_DEF_H__ */
plat/mediatek/mt8173/include/plat_macros.S
View file @
c38b36d8
...
...
@@ -29,7 +29,8 @@
*/
#include <cci.h>
#include <gic_v2.h>
#include <gic_common.h>
#include <gicv2.h>
#include <mt8173_def.h>
.
section
.
rodata.
gic_reg_name
,
"aS"
...
...
plat/mediatek/mt8173/include/plat_private.h
View file @
c38b36d8
...
...
@@ -45,9 +45,6 @@ void plat_cci_init(void);
void
plat_cci_enable
(
void
);
void
plat_cci_disable
(
void
);
/* Declarations for plat_mt_gic.c */
void
plat_mt_gic_init
(
void
);
/* Declarations for plat_topology.c */
int
mt_setup_topology
(
void
);
...
...
plat/mediatek/mt8173/include/platform_def.h
View file @
c38b36d8
...
...
@@ -31,6 +31,8 @@
#ifndef __PLATFORM_DEF_H__
#define __PLATFORM_DEF_H__
#include "mt8173_def.h"
/*******************************************************************************
* Platform binary types for linking
...
...
@@ -56,6 +58,11 @@
#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2
#if !ENABLE_PLAT_COMPAT
#define PLAT_MAX_PWR_LVL 2
#define PLAT_MAX_RET_STATE 1
#define PLAT_MAX_OFF_STATE 2
#endif
#define PLATFORM_SYSTEM_COUNT 1
#define PLATFORM_CLUSTER_COUNT 2
#define PLATFORM_CLUSTER0_CORE_COUNT 4
...
...
@@ -111,7 +118,8 @@
/*******************************************************************************
* Platform specific page table and MMU setup constants
******************************************************************************/
#define ADDR_SPACE_SIZE (1ull << 32)
#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32)
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32)
#define MAX_XLAT_TABLES 4
#define MAX_MMAP_REGIONS 16
...
...
@@ -127,4 +135,19 @@
#define CACHE_WRITEBACK_SHIFT 6
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
#define PLAT_ARM_GICD_BASE BASE_GICD_BASE
#define PLAT_ARM_GICC_BASE BASE_GICC_BASE
#define PLAT_ARM_G1S_IRQS MT_IRQ_SEC_SGI_0, \
MT_IRQ_SEC_SGI_1, \
MT_IRQ_SEC_SGI_2, \
MT_IRQ_SEC_SGI_3, \
MT_IRQ_SEC_SGI_4, \
MT_IRQ_SEC_SGI_5, \
MT_IRQ_SEC_SGI_6, \
MT_IRQ_SEC_SGI_7
#define PLAT_ARM_G0_IRQS
#endif
/* __PLATFORM_DEF_H__ */
plat/mediatek/mt8173/plat_pm.c
View file @
c38b36d8
...
...
@@ -29,17 +29,18 @@
*/
#include <arch_helpers.h>
#include <arm_gic.h>
#include <assert.h>
#include <bakery_lock.h>
#include <cci.h>
#include <console.h>
#include <debug.h>
#include <errno.h>
#include <gicv2.h>
#include <mcucfg.h>
#include <mmio.h>
#include <mt8173_def.h>
#include <mt_cpuxgpt.h>
/* generic_timer_backup() */
#include <plat_arm.h>
#include <plat_private.h>
#include <power_tracer.h>
#include <psci.h>
...
...
@@ -49,6 +50,44 @@
#include <spm_mcdi.h>
#include <spm_suspend.h>
#if !ENABLE_PLAT_COMPAT
#define MTK_PWR_LVL0 0
#define MTK_PWR_LVL1 1
#define MTK_PWR_LVL2 2
/* Macros to read the MTK power domain state */
#define MTK_CORE_PWR_STATE(state) (state)->pwr_domain_state[MTK_PWR_LVL0]
#define MTK_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[MTK_PWR_LVL1]
#define MTK_SYSTEM_PWR_STATE(state) ((PLAT_MAX_PWR_LVL > MTK_PWR_LVL1) ?\
(state)->pwr_domain_state[MTK_PWR_LVL2] : 0)
#endif
#if PSCI_EXTENDED_STATE_ID
/*
* The table storing the valid idle power states. Ensure that the
* array entries are populated in ascending order of state-id to
* enable us to use binary search during power state validation.
* The table must be terminated by a NULL entry.
*/
const
unsigned
int
mtk_pm_idle_states
[]
=
{
/* State-id - 0x001 */
mtk_make_pwrstate_lvl2
(
MTK_LOCAL_STATE_RUN
,
MTK_LOCAL_STATE_RUN
,
MTK_LOCAL_STATE_RET
,
MTK_PWR_LVL0
,
PSTATE_TYPE_STANDBY
),
/* State-id - 0x002 */
mtk_make_pwrstate_lvl2
(
MTK_LOCAL_STATE_RUN
,
MTK_LOCAL_STATE_RUN
,
MTK_LOCAL_STATE_OFF
,
MTK_PWR_LVL0
,
PSTATE_TYPE_POWERDOWN
),
/* State-id - 0x022 */
mtk_make_pwrstate_lvl2
(
MTK_LOCAL_STATE_RUN
,
MTK_LOCAL_STATE_OFF
,
MTK_LOCAL_STATE_OFF
,
MTK_PWR_LVL1
,
PSTATE_TYPE_POWERDOWN
),
#if PLAT_MAX_PWR_LVL > MTK_PWR_LVL1
/* State-id - 0x222 */
mtk_make_pwrstate_lvl2
(
MTK_LOCAL_STATE_OFF
,
MTK_LOCAL_STATE_OFF
,
MTK_LOCAL_STATE_OFF
,
MTK_PWR_LVL2
,
PSTATE_TYPE_POWERDOWN
),
#endif
0
,
};
#endif
struct
core_context
{
unsigned
long
timer_data
[
8
];
unsigned
int
count
;
...
...
@@ -219,6 +258,7 @@ static void mt_platform_restore_context(unsigned long mpidr)
mt_cpu_restore
(
mpidr
);
}
#if ENABLE_PLAT_COMPAT
/*******************************************************************************
* Private function which is used to determine if any platform actions
* should be performed for the specified affinity instance given its
...
...
@@ -270,11 +310,25 @@ static void plat_affinst_standby(unsigned int power_state)
wfi
();
}
}
#else
static
void
plat_cpu_standby
(
plat_local_state_t
cpu_state
)
{
unsigned
int
scr
;
scr
=
read_scr_el3
();
write_scr_el3
(
scr
|
SCR_IRQ_BIT
);
isb
();
dsb
();
wfi
();
write_scr_el3
(
scr
);
}
#endif
/*******************************************************************************
* MTK_platform handler called when an affinity instance is about to be turned
* on. The level and mpidr determine the affinity instance.
******************************************************************************/
#if ENABLE_PLAT_COMPAT
static
int
plat_affinst_on
(
unsigned
long
mpidr
,
unsigned
long
sec_entrypoint
,
unsigned
int
afflvl
,
...
...
@@ -308,6 +362,32 @@ static int plat_affinst_on(unsigned long mpidr,
return
rc
;
}
#else
static
uintptr_t
secure_entrypoint
;
static
int
plat_power_domain_on
(
unsigned
long
mpidr
)
{
int
rc
=
PSCI_E_SUCCESS
;
unsigned
long
cpu_id
;
unsigned
long
cluster_id
;
uintptr_t
rv
;
cpu_id
=
mpidr
&
MPIDR_CPU_MASK
;
cluster_id
=
mpidr
&
MPIDR_CLUSTER_MASK
;
if
(
cluster_id
)
rv
=
(
uintptr_t
)
&
mt8173_mcucfg
->
mp1_rv_addr
[
cpu_id
].
rv_addr_lw
;
else
rv
=
(
uintptr_t
)
&
mt8173_mcucfg
->
mp0_rv_addr
[
cpu_id
].
rv_addr_lw
;
mmio_write_32
(
rv
,
secure_entrypoint
);
INFO
(
"mt_on[%ld:%ld], entry %x
\n
"
,
cluster_id
,
cpu_id
,
mmio_read_32
(
rv
));
spm_hotplug_on
(
mpidr
);
return
rc
;
}
#endif
/*******************************************************************************
* MTK_platform handler called when an affinity instance is about to be turned
...
...
@@ -321,6 +401,7 @@ static int plat_affinst_on(unsigned long mpidr,
* dealt with. So do not write & read global variables across calls. It will be
* wise to do flush a write to the global to prevent unpredictable results.
******************************************************************************/
#if ENABLE_PLAT_COMPAT
static
void
plat_affinst_off
(
unsigned
int
afflvl
,
unsigned
int
state
)
{
unsigned
long
mpidr
=
read_mpidr_el1
();
...
...
@@ -330,7 +411,7 @@ static void plat_affinst_off(unsigned int afflvl, unsigned int state)
return
;
/* Prevent interrupts from spuriously waking up this cpu */
arm_
gic_cpuif_d
eactivat
e
();
gic
v2
_cpuif_d
isabl
e
();
spm_hotplug_off
(
mpidr
);
...
...
@@ -343,6 +424,26 @@ static void plat_affinst_off(unsigned int afflvl, unsigned int state)
trace_power_flow
(
mpidr
,
CLUSTER_DOWN
);
}
}
#else
static
void
plat_power_domain_off
(
const
psci_power_state_t
*
state
)
{
unsigned
long
mpidr
=
read_mpidr_el1
();
/* Prevent interrupts from spuriously waking up this cpu */
gicv2_cpuif_disable
();
spm_hotplug_off
(
mpidr
);
trace_power_flow
(
mpidr
,
CPU_DOWN
);
if
(
MTK_CLUSTER_PWR_STATE
(
state
)
==
MTK_LOCAL_STATE_OFF
)
{
/* Disable coherency if this cluster is to be turned off */
plat_cci_disable
();
trace_power_flow
(
mpidr
,
CLUSTER_DOWN
);
}
}
#endif
/*******************************************************************************
* MTK_platform handler called when an affinity instance is about to be
...
...
@@ -356,6 +457,7 @@ static void plat_affinst_off(unsigned int afflvl, unsigned int state)
* dealt with. So do not write & read global variables across calls. It will be
* wise to do flush a write to the global to prevent unpredictable results.
******************************************************************************/
#if ENABLE_PLAT_COMPAT
static
void
plat_affinst_suspend
(
unsigned
long
sec_entrypoint
,
unsigned
int
afflvl
,
unsigned
int
state
)
...
...
@@ -396,9 +498,50 @@ static void plat_affinst_suspend(unsigned long sec_entrypoint,
generic_timer_backup
();
spm_system_suspend
();
/* Prevent interrupts from spuriously waking up this cpu */
arm_gic_cpuif_deactivate
();
gicv2_cpuif_disable
();
}
}
#else
static
void
plat_power_domain_suspend
(
const
psci_power_state_t
*
state
)
{
unsigned
long
mpidr
=
read_mpidr_el1
();
unsigned
long
cluster_id
;
unsigned
long
cpu_id
;
uintptr_t
rv
;
cpu_id
=
mpidr
&
MPIDR_CPU_MASK
;
cluster_id
=
mpidr
&
MPIDR_CLUSTER_MASK
;
if
(
cluster_id
)
rv
=
(
uintptr_t
)
&
mt8173_mcucfg
->
mp1_rv_addr
[
cpu_id
].
rv_addr_lw
;
else
rv
=
(
uintptr_t
)
&
mt8173_mcucfg
->
mp0_rv_addr
[
cpu_id
].
rv_addr_lw
;
mmio_write_32
(
rv
,
secure_entrypoint
);
if
(
MTK_SYSTEM_PWR_STATE
(
state
)
!=
MTK_LOCAL_STATE_OFF
)
{
spm_mcdi_prepare_for_off_state
(
mpidr
,
MTK_PWR_LVL0
);
if
(
MTK_CLUSTER_PWR_STATE
(
state
)
==
MTK_LOCAL_STATE_OFF
)
spm_mcdi_prepare_for_off_state
(
mpidr
,
MTK_PWR_LVL1
);
}
mt_platform_save_context
(
mpidr
);
/* Perform the common cluster specific operations */
if
(
MTK_CLUSTER_PWR_STATE
(
state
)
==
MTK_LOCAL_STATE_OFF
)
{
/* Disable coherency if this cluster is to be turned off */
plat_cci_disable
();
}
if
(
MTK_SYSTEM_PWR_STATE
(
state
)
==
MTK_LOCAL_STATE_OFF
)
{
disable_scu
(
mpidr
);
generic_timer_backup
();
spm_system_suspend
();
/* Prevent interrupts from spuriously waking up this cpu */
gicv2_cpuif_disable
();
}
}
#endif
/*******************************************************************************
* MTK_platform handler called when an affinity instance has just been powered
...
...
@@ -407,6 +550,7 @@ static void plat_affinst_suspend(unsigned long sec_entrypoint,
* was turned off prior to wakeup and do what's necessary to setup it up
* correctly.
******************************************************************************/
#if ENABLE_PLAT_COMPAT
static
void
plat_affinst_on_finish
(
unsigned
int
afflvl
,
unsigned
int
state
)
{
unsigned
long
mpidr
=
read_mpidr_el1
();
...
...
@@ -423,16 +567,45 @@ static void plat_affinst_on_finish(unsigned int afflvl, unsigned int state)
}
/* Enable the gic cpu interface */
arm_gic_cpuif_setup
();
arm_gic_pcpu_distif_setup
();
gicv2_cpuif_enable
();
gicv2_pcpu_distif_init
();
trace_power_flow
(
mpidr
,
CPU_UP
);
}
#else
void
mtk_system_pwr_domain_resume
(
void
);
static
void
plat_power_domain_on_finish
(
const
psci_power_state_t
*
state
)
{
unsigned
long
mpidr
=
read_mpidr_el1
();
assert
(
state
->
pwr_domain_state
[
MPIDR_AFFLVL0
]
==
MTK_LOCAL_STATE_OFF
);
if
((
PLAT_MAX_PWR_LVL
>
MTK_PWR_LVL1
)
&&
(
state
->
pwr_domain_state
[
MTK_PWR_LVL2
]
==
MTK_LOCAL_STATE_OFF
))
mtk_system_pwr_domain_resume
();
if
(
state
->
pwr_domain_state
[
MPIDR_AFFLVL1
]
==
MTK_LOCAL_STATE_OFF
)
{
plat_cci_enable
();
trace_power_flow
(
mpidr
,
CLUSTER_UP
);
}
if
((
PLAT_MAX_PWR_LVL
>
MTK_PWR_LVL1
)
&&
(
state
->
pwr_domain_state
[
MTK_PWR_LVL2
]
==
MTK_LOCAL_STATE_OFF
))
return
;
/* Enable the gic cpu interface */
gicv2_cpuif_enable
();
gicv2_pcpu_distif_init
();
trace_power_flow
(
mpidr
,
CPU_UP
);
}
#endif
/*******************************************************************************
* MTK_platform handler called when an affinity instance has just been powered
* on after having been suspended earlier. The level and mpidr determine the
* affinity instance.
******************************************************************************/
#if ENABLE_PLAT_COMPAT
static
void
plat_affinst_suspend_finish
(
unsigned
int
afflvl
,
unsigned
int
state
)
{
unsigned
long
mpidr
=
read_mpidr_el1
();
...
...
@@ -443,8 +616,7 @@ static void plat_affinst_suspend_finish(unsigned int afflvl, unsigned int state)
if
(
afflvl
>=
MPIDR_AFFLVL2
)
{
/* Enable the gic cpu interface */
arm_gic_setup
();
arm_gic_cpuif_setup
();
plat_arm_gic_init
();
spm_system_suspend_finish
();
enable_scu
(
mpidr
);
}
...
...
@@ -461,14 +633,56 @@ static void plat_affinst_suspend_finish(unsigned int afflvl, unsigned int state)
if
(
afflvl
<
MPIDR_AFFLVL2
)
spm_mcdi_finish_for_on_state
(
mpidr
,
afflvl
);
arm_
gic_pcpu_distif_
setup
();
gic
v2
_pcpu_distif_
init
();
}
#else
static
void
plat_power_domain_suspend_finish
(
const
psci_power_state_t
*
state
)
{
unsigned
long
mpidr
=
read_mpidr_el1
();
if
(
state
->
pwr_domain_state
[
MTK_PWR_LVL0
]
==
MTK_LOCAL_STATE_RET
)
return
;
if
(
MTK_SYSTEM_PWR_STATE
(
state
)
==
MTK_LOCAL_STATE_OFF
)
{
/* Enable the gic cpu interface */
plat_arm_gic_init
();
spm_system_suspend_finish
();
enable_scu
(
mpidr
);
}
/* Perform the common cluster specific operations */
if
(
MTK_CLUSTER_PWR_STATE
(
state
)
==
MTK_LOCAL_STATE_OFF
)
{
/* Enable coherency if this cluster was off */
plat_cci_enable
();
}
mt_platform_restore_context
(
mpidr
);
if
(
MTK_SYSTEM_PWR_STATE
(
state
)
!=
MTK_LOCAL_STATE_OFF
)
{
spm_mcdi_finish_for_on_state
(
mpidr
,
MTK_PWR_LVL0
);
if
(
MTK_CLUSTER_PWR_STATE
(
state
)
==
MTK_LOCAL_STATE_OFF
)
spm_mcdi_finish_for_on_state
(
mpidr
,
MTK_PWR_LVL1
);
}
gicv2_pcpu_distif_init
();
}
#endif
#if ENABLE_PLAT_COMPAT
static
unsigned
int
plat_get_sys_suspend_power_state
(
void
)
{
/* StateID: 0, StateType: 1(power down), PowerLevel: 2(system) */
return
psci_make_powerstate
(
0
,
1
,
2
);
}
#else
static
void
plat_get_sys_suspend_power_state
(
psci_power_state_t
*
req_state
)
{
assert
(
PLAT_MAX_PWR_LVL
>=
2
);
for
(
int
i
=
MPIDR_AFFLVL0
;
i
<=
PLAT_MAX_PWR_LVL
;
i
++
)
req_state
->
pwr_domain_state
[
i
]
=
MTK_LOCAL_STATE_OFF
;
}
#endif
/*******************************************************************************
* MTK handlers to shutdown/reboot the system
...
...
@@ -500,6 +714,94 @@ static void __dead2 plat_system_reset(void)
panic
();
}
#if !ENABLE_PLAT_COMPAT
#if !PSCI_EXTENDED_STATE_ID
static
int
plat_validate_power_state
(
unsigned
int
power_state
,
psci_power_state_t
*
req_state
)
{
int
pstate
=
psci_get_pstate_type
(
power_state
);
int
pwr_lvl
=
psci_get_pstate_pwrlvl
(
power_state
);
int
i
;
assert
(
req_state
);
if
(
pwr_lvl
>
PLAT_MAX_PWR_LVL
)
return
PSCI_E_INVALID_PARAMS
;
/* Sanity check the requested state */
if
(
pstate
==
PSTATE_TYPE_STANDBY
)
{
/*
* It's possible to enter standby only on power level 0
* Ignore any other power level.
*/
if
(
pwr_lvl
!=
0
)
return
PSCI_E_INVALID_PARAMS
;
req_state
->
pwr_domain_state
[
MTK_PWR_LVL0
]
=
MTK_LOCAL_STATE_RET
;
}
else
{
for
(
i
=
0
;
i
<=
pwr_lvl
;
i
++
)
req_state
->
pwr_domain_state
[
i
]
=
MTK_LOCAL_STATE_OFF
;
}
/*
* We expect the 'state id' to be zero.
*/
if
(
psci_get_pstate_id
(
power_state
))
return
PSCI_E_INVALID_PARAMS
;
return
PSCI_E_SUCCESS
;
}
#else
int
plat_validate_power_state
(
unsigned
int
power_state
,
psci_power_state_t
*
req_state
)
{
unsigned
int
state_id
;
int
i
;
assert
(
req_state
);
/*
* Currently we are using a linear search for finding the matching
* entry in the idle power state array. This can be made a binary
* search if the number of entries justify the additional complexity.
*/
for
(
i
=
0
;
!!
mtk_pm_idle_states
[
i
];
i
++
)
{
if
(
power_state
==
mtk_pm_idle_states
[
i
])
break
;
}
/* Return error if entry not found in the idle state array */
if
(
!
mtk_pm_idle_states
[
i
])
return
PSCI_E_INVALID_PARAMS
;
i
=
0
;
state_id
=
psci_get_pstate_id
(
power_state
);
/* Parse the State ID and populate the state info parameter */
while
(
state_id
)
{
req_state
->
pwr_domain_state
[
i
++
]
=
state_id
&
MTK_LOCAL_PSTATE_MASK
;
state_id
>>=
MTK_LOCAL_PSTATE_WIDTH
;
}
return
PSCI_E_SUCCESS
;
}
#endif
void
mtk_system_pwr_domain_resume
(
void
)
{
console_init
(
MT8173_UART0_BASE
,
MT8173_UART_CLOCK
,
MT8173_BAUDRATE
);
/* Assert system power domain is available on the platform */
assert
(
PLAT_MAX_PWR_LVL
>=
MTK_PWR_LVL2
);
plat_arm_gic_init
();
}
#endif
#if ENABLE_PLAT_COMPAT
/*******************************************************************************
* Export the platform handlers to enable psci to invoke them
******************************************************************************/
...
...
@@ -524,3 +826,54 @@ int platform_setup_pm(const plat_pm_ops_t **plat_ops)
*
plat_ops
=
&
plat_plat_pm_ops
;
return
0
;
}
#else
static
const
plat_psci_ops_t
plat_plat_pm_ops
=
{
.
cpu_standby
=
plat_cpu_standby
,
.
pwr_domain_on
=
plat_power_domain_on
,
.
pwr_domain_on_finish
=
plat_power_domain_on_finish
,
.
pwr_domain_off
=
plat_power_domain_off
,
.
pwr_domain_suspend
=
plat_power_domain_suspend
,
.
pwr_domain_suspend_finish
=
plat_power_domain_suspend_finish
,
.
system_off
=
plat_system_off
,
.
system_reset
=
plat_system_reset
,
.
validate_power_state
=
plat_validate_power_state
,
.
get_sys_suspend_power_state
=
plat_get_sys_suspend_power_state
,
};
int
plat_setup_psci_ops
(
uintptr_t
sec_entrypoint
,
const
plat_psci_ops_t
**
psci_ops
)
{
*
psci_ops
=
&
plat_plat_pm_ops
;
secure_entrypoint
=
sec_entrypoint
;
return
0
;
}
/*
* The PSCI generic code uses this API to let the platform participate in state
* coordination during a power management operation. It compares the platform
* specific local power states requested by each cpu for a given power domain
* and returns the coordinated target power state that the domain should
* enter. A platform assigns a number to a local power state. This default
* implementation assumes that the platform assigns these numbers in order of
* increasing depth of the power state i.e. for two power states X & Y, if X < Y
* then X represents a shallower power state than Y. As a result, the
* coordinated target local power state for a power domain will be the minimum
* of the requested local power states.
*/
plat_local_state_t
plat_get_target_pwr_state
(
unsigned
int
lvl
,
const
plat_local_state_t
*
states
,
unsigned
int
ncpu
)
{
plat_local_state_t
target
=
PLAT_MAX_OFF_STATE
,
temp
;
assert
(
ncpu
);
do
{
temp
=
*
states
++
;
if
(
temp
<
target
)
target
=
temp
;
}
while
(
--
ncpu
);
return
target
;
}
#endif
plat/mediatek/mt8173/plat_topology.c
View file @
c38b36d8
...
...
@@ -31,6 +31,7 @@
#include <platform_def.h>
#include <psci.h>
#if ENABLE_PLAT_COMPAT
unsigned
int
plat_get_aff_count
(
unsigned
int
aff_lvl
,
unsigned
long
mpidr
)
{
/* Report 1 (absent) instance at levels higher that the cluster level */
...
...
@@ -54,3 +55,55 @@ int mt_setup_topology(void)
/* [TODO] Make topology configurable via SCC */
return
0
;
}
#else
const
unsigned
char
mtk_power_domain_tree_desc
[]
=
{
/* No of root nodes */
PLATFORM_SYSTEM_COUNT
,
/* No of children for the root node */
PLATFORM_CLUSTER_COUNT
,
/* No of children for the first cluster node */
PLATFORM_CLUSTER0_CORE_COUNT
,
/* No of children for the second cluster node */
PLATFORM_CLUSTER1_CORE_COUNT
};
/*******************************************************************************
* This function returns the MT8173 default topology tree information.
******************************************************************************/
const
unsigned
char
*
plat_get_power_domain_tree_desc
(
void
)
{
return
mtk_power_domain_tree_desc
;
}
/*******************************************************************************
* This function implements a part of the critical interface between the psci
* generic layer and the platform that allows the former to query the platform
* to convert an MPIDR to a unique linear index. An error code (-1) is returned
* in case the MPIDR is invalid.
******************************************************************************/
int
plat_core_pos_by_mpidr
(
u_register_t
mpidr
)
{
unsigned
int
cluster_id
,
cpu_id
;
mpidr
&=
MPIDR_AFFINITY_MASK
;
if
(
mpidr
&
~
(
MPIDR_CLUSTER_MASK
|
MPIDR_CPU_MASK
))
return
-
1
;
cluster_id
=
(
mpidr
>>
MPIDR_AFF1_SHIFT
)
&
MPIDR_AFFLVL_MASK
;
cpu_id
=
(
mpidr
>>
MPIDR_AFF0_SHIFT
)
&
MPIDR_AFFLVL_MASK
;
if
(
cluster_id
>=
PLATFORM_CLUSTER_COUNT
)
return
-
1
;
/*
* Validate cpu_id by checking whether it represents a CPU in
* one of the two clusters present on the platform.
*/
if
(
cpu_id
>=
PLATFORM_MAX_CPUS_PER_CLUSTER
)
return
-
1
;
return
(
cpu_id
+
(
cluster_id
*
4
));
}
#endif
plat/mediatek/mt8173/platform.mk
View file @
c38b36d8
...
...
@@ -33,6 +33,8 @@ MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT}
PLAT_INCLUDES
:=
-I
${MTK_PLAT}
/common/
\
-I
${MTK_PLAT}
/common/drivers/uart/
\
-Iinclude
/plat/arm/common
\
-Iinclude
/plat/arm/common/aarch64
\
-I
${MTK_PLAT_SOC}
/drivers/crypt/
\
-I
${MTK_PLAT_SOC}
/drivers/mtcmos/
\
-I
${MTK_PLAT_SOC}
/drivers/pmic/
\
...
...
@@ -44,12 +46,13 @@ PLAT_INCLUDES := -I${MTK_PLAT}/common/ \
PLAT_BL_COMMON_SOURCES
:=
lib/xlat_tables/xlat_tables_common.c
\
lib/xlat_tables/aarch64/xlat_tables.c
\
plat/common/aarch64/plat_common.c
\
plat/common/plat_gic.c
plat/arm/common/arm_gicv2.c
\
plat/common/plat_gicv2.c
BL31_SOURCES
+=
drivers/arm/cci/cci.c
\
drivers/arm/gic/
arm_gic
.c
\
drivers/arm/gic/gic
_
v2.c
\
drivers/arm/gic/
gic_v3
.c
\
drivers/arm/gic/
common/gic_common
.c
\
drivers/arm/gic/
v2/
gicv2
_main
.c
\
drivers/arm/gic/
v2/gicv2_helpers
.c
\
drivers/console/aarch64/console.S
\
drivers/delay_timer/delay_timer.c
\
drivers/delay_timer/generic_delay_timer.c
\
...
...
@@ -73,7 +76,6 @@ BL31_SOURCES += drivers/arm/cci/cci.c \
${MTK_PLAT_SOC}
/drivers/spm/spm_mcdi.c
\
${MTK_PLAT_SOC}
/drivers/spm/spm_suspend.c
\
${MTK_PLAT_SOC}
/drivers/timer/mt_cpuxgpt.c
\
${MTK_PLAT_SOC}
/plat_mt_gic.c
\
${MTK_PLAT_SOC}
/plat_pm.c
\
${MTK_PLAT_SOC}
/plat_sip_calls.c
\
${MTK_PLAT_SOC}
/plat_topology.c
\
...
...
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