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
0ceb3e1e
Commit
0ceb3e1e
authored
Jun 01, 2017
by
danh-arm
Committed by
GitHub
Jun 01, 2017
Browse files
Merge pull request #957 from hzhuang1/finish_hikey_psci
Finish hikey psci
parents
2bd26faf
1e54813a
Changes
4
Hide whitespace changes
Inline
Side-by-side
plat/hisilicon/hikey/hikey_bl31_setup.c
View file @
0ceb3e1e
...
...
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <arm_gic.h>
#include <assert.h>
#include <bl_common.h>
...
...
@@ -88,6 +89,7 @@ void bl31_early_platform_setup(bl31_params_t *from_bl2,
/* Initialize CCI driver */
cci_init
(
CCI400_BASE
,
cci_map
,
ARRAY_SIZE
(
cci_map
));
cci_enable_snoop_dvm_reqs
(
MPIDR_AFFLVL1_VAL
(
read_mpidr_el1
()));
/*
* Copy BL3-2 and BL3-3 entry point information.
...
...
plat/hisilicon/hikey/hikey_pm.c
View file @
0ceb3e1e
...
...
@@ -15,21 +15,19 @@
#include <hisi_sram_map.h>
#include <mmio.h>
#include <psci.h>
#include <sp804_delay_timer.h>
#include "hikey_def.h"
#define HIKEY_CLUSTER_STATE_ON 0
#define HIKEY_CLUSTER_STATE_OFF 1
#define CORE_PWR_STATE(state) \
((state)->pwr_domain_state[MPIDR_AFFLVL0])
#define CLUSTER_PWR_STATE(state) \
((state)->pwr_domain_state[MPIDR_AFFLVL1])
#define SYSTEM_PWR_STATE(state) \
((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
static
uintptr_t
hikey_sec_entrypoint
;
/* There're two clusters in HiKey. */
static
int
hikey_cluster_state
[]
=
{
HIKEY_CLUSTER_STATE_OFF
,
HIKEY_CLUSTER_STATE_OFF
};
/*******************************************************************************
* Handler called when a power domain is about to be turned on. The
* level and mpidr determine the affinity instance.
******************************************************************************/
static
int
hikey_pwr_domain_on
(
u_register_t
mpidr
)
{
int
cpu
,
cluster
;
...
...
@@ -54,14 +52,14 @@ static void hikey_pwr_domain_on_finish(const psci_power_state_t *target_state)
mpidr
=
read_mpidr
();
cluster
=
MPIDR_AFFLVL1_VAL
(
mpidr
);
cpu
=
MPIDR_AFFLVL0_VAL
(
mpidr
);
if
(
hikey_cluster_state
[
cluster
]
==
HIKEY_CLUSTER_STATE_OFF
)
{
/*
* Enable CCI coherency for this cluster.
* No need for locks as no other cpu is active at the moment.
*/
/*
* Enable CCI coherency for this cluster.
* No need for locks as no other cpu is active at the moment.
*/
if
(
CLUSTER_PWR_STATE
(
target_state
)
==
PLAT_MAX_OFF_STATE
)
cci_enable_snoop_dvm_reqs
(
MPIDR_AFFLVL1_VAL
(
mpidr
));
hikey_cluster_state
[
cluster
]
=
HIKEY_CLUSTER_STATE_ON
;
}
/* Zero the jump address in the mailbox for this cpu */
hisi_pwrc_set_core_bx_addr
(
cpu
,
cluster
,
0
);
...
...
@@ -72,35 +70,133 @@ static void hikey_pwr_domain_on_finish(const psci_power_state_t *target_state)
gicv2_cpuif_enable
();
}
/*******************************************************************************
* Handler called when a power domain is about to be turned off. The
* target_state encodes the power state that each level should transition to.
******************************************************************************/
void
hikey_pwr_domain_off
(
const
psci_power_state_t
*
target_state
)
{
unsigned
long
mpidr
;
int
cpu
,
cluster
;
gicv2_cpuif_disable
();
mpidr
=
read_mpidr
();
cluster
=
MPIDR_AFFLVL1_VAL
(
mpidr
);
cpu
=
MPIDR_AFFLVL0_VAL
(
mpidr
);
if
(
target_state
->
pwr_domain_state
[
MPIDR_AFFLVL1
]
==
PLAT_MAX_OFF_STATE
)
{
gicv2_cpuif_disable
();
hisi_ipc_cpu_off
(
cpu
,
cluster
);
if
(
CLUSTER_PWR_STATE
(
target_state
)
==
PLAT_MAX_OFF_STATE
)
{
hisi_ipc_spin_lock
(
HISI_IPC_SEM_CPUIDLE
);
cci_disable_snoop_dvm_reqs
(
MPIDR_AFFLVL1_VAL
(
mpidr
));
hisi_ipc_spin_unlock
(
HISI_IPC_SEM_CPUIDLE
);
hisi_ipc_cluster_off
(
cpu
,
cluster
);
hikey_cluster_state
[
cluster
]
=
HIKEY_CLUSTER_STATE_OFF
;
}
hisi_ipc_cpu_off
(
cpu
,
cluster
);
}
/*******************************************************************************
* Handler to reboot the system.
******************************************************************************/
static
void
hikey_pwr_domain_suspend
(
const
psci_power_state_t
*
target_state
)
{
u_register_t
mpidr
=
read_mpidr_el1
();
unsigned
int
cpu
=
mpidr
&
MPIDR_CPU_MASK
;
unsigned
int
cluster
=
(
mpidr
&
MPIDR_CLUSTER_MASK
)
>>
MPIDR_AFFINITY_BITS
;
if
(
CORE_PWR_STATE
(
target_state
)
!=
PLAT_MAX_OFF_STATE
)
return
;
if
(
CORE_PWR_STATE
(
target_state
)
==
PLAT_MAX_OFF_STATE
)
{
/* Program the jump address for the target cpu */
hisi_pwrc_set_core_bx_addr
(
cpu
,
cluster
,
hikey_sec_entrypoint
);
gicv2_cpuif_disable
();
if
(
SYSTEM_PWR_STATE
(
target_state
)
!=
PLAT_MAX_OFF_STATE
)
hisi_ipc_cpu_suspend
(
cpu
,
cluster
);
}
/* Perform the common cluster specific operations */
if
(
CLUSTER_PWR_STATE
(
target_state
)
==
PLAT_MAX_OFF_STATE
)
{
hisi_ipc_spin_lock
(
HISI_IPC_SEM_CPUIDLE
);
cci_disable_snoop_dvm_reqs
(
MPIDR_AFFLVL1_VAL
(
mpidr
));
hisi_ipc_spin_unlock
(
HISI_IPC_SEM_CPUIDLE
);
if
(
SYSTEM_PWR_STATE
(
target_state
)
==
PLAT_MAX_OFF_STATE
)
{
hisi_pwrc_set_cluster_wfi
(
1
);
hisi_pwrc_set_cluster_wfi
(
0
);
hisi_ipc_psci_system_off
();
}
else
hisi_ipc_cluster_suspend
(
cpu
,
cluster
);
}
}
static
void
hikey_pwr_domain_suspend_finish
(
const
psci_power_state_t
*
target_state
)
{
unsigned
long
mpidr
;
unsigned
int
cluster
,
cpu
;
/* Nothing to be done on waking up from retention from CPU level */
if
(
CORE_PWR_STATE
(
target_state
)
!=
PLAT_MAX_OFF_STATE
)
return
;
/* Get the mpidr for this cpu */
mpidr
=
read_mpidr_el1
();
cluster
=
(
mpidr
&
MPIDR_CLUSTER_MASK
)
>>
MPIDR_AFF1_SHIFT
;
cpu
=
mpidr
&
MPIDR_CPU_MASK
;
/* Enable CCI coherency for cluster */
if
(
CLUSTER_PWR_STATE
(
target_state
)
==
PLAT_MAX_OFF_STATE
)
cci_enable_snoop_dvm_reqs
(
MPIDR_AFFLVL1_VAL
(
mpidr
));
hisi_pwrc_set_core_bx_addr
(
cpu
,
cluster
,
0
);
if
(
SYSTEM_PWR_STATE
(
target_state
)
==
PLAT_MAX_OFF_STATE
)
{
gicv2_distif_init
();
gicv2_pcpu_distif_init
();
gicv2_cpuif_enable
();
}
else
{
gicv2_pcpu_distif_init
();
gicv2_cpuif_enable
();
}
}
static
void
hikey_get_sys_suspend_power_state
(
psci_power_state_t
*
req_state
)
{
int
i
;
for
(
i
=
MPIDR_AFFLVL0
;
i
<=
PLAT_MAX_PWR_LVL
;
i
++
)
req_state
->
pwr_domain_state
[
i
]
=
PLAT_MAX_OFF_STATE
;
}
static
void
__dead2
hikey_system_off
(
void
)
{
NOTICE
(
"%s: off system
\n
"
,
__func__
);
/* Pull down GPIO_0_0 to trigger PMIC shutdown */
mmio_write_32
(
0xF8001810
,
0x2
);
/* Pinmux */
mmio_write_8
(
0xF8011400
,
1
);
/* Pin direction */
mmio_write_8
(
0xF8011004
,
0
);
/* Pin output value */
/* Wait for 2s to power off system by PMIC */
sp804_timer_init
(
SP804_TIMER0_BASE
,
10
,
192
);
mdelay
(
2000
);
/*
* PMIC shutdown depends on two conditions: GPIO_0_0 (PWR_HOLD) low,
* and VBUS_DET < 3.6V. For HiKey, VBUS_DET is connected to VDD_4V2
* through Jumper 1-2. So, to complete shutdown, user needs to manually
* remove Jumper 1-2.
*/
NOTICE
(
"+------------------------------------------+
\n
"
);
NOTICE
(
"| IMPORTANT: Remove Jumper 1-2 to shutdown |
\n
"
);
NOTICE
(
"| DANGER: SoC is still burning. DANGER! |
\n
"
);
NOTICE
(
"| Board will be reboot to avoid overheat |
\n
"
);
NOTICE
(
"+------------------------------------------+
\n
"
);
/* Send the system reset request */
mmio_write_32
(
AO_SC_SYS_STAT0
,
0x48698284
);
wfi
();
panic
();
}
static
void
__dead2
hikey_system_reset
(
void
)
{
/* Send the system reset request */
...
...
@@ -112,9 +208,6 @@ static void __dead2 hikey_system_reset(void)
panic
();
}
/*******************************************************************************
* Handler called to check the validity of the power state parameter.
******************************************************************************/
int
hikey_validate_power_state
(
unsigned
int
power_state
,
psci_power_state_t
*
req_state
)
{
...
...
@@ -153,9 +246,6 @@ int hikey_validate_power_state(unsigned int power_state,
return
PSCI_E_SUCCESS
;
}
/*******************************************************************************
* Handler called to check the validity of the non secure entrypoint.
******************************************************************************/
static
int
hikey_validate_ns_entrypoint
(
uintptr_t
entrypoint
)
{
/*
...
...
@@ -168,26 +258,20 @@ static int hikey_validate_ns_entrypoint(uintptr_t entrypoint)
return
PSCI_E_INVALID_ADDRESS
;
}
/*******************************************************************************
* Export the platform handlers to enable psci to invoke them
******************************************************************************/
static
const
plat_psci_ops_t
hikey_psci_ops
=
{
.
cpu_standby
=
NULL
,
.
pwr_domain_on
=
hikey_pwr_domain_on
,
.
pwr_domain_on_finish
=
hikey_pwr_domain_on_finish
,
.
pwr_domain_off
=
hikey_pwr_domain_off
,
.
pwr_domain_suspend
=
NULL
,
.
pwr_domain_suspend_finish
=
NULL
,
.
system_off
=
NULL
,
.
pwr_domain_suspend
=
hikey_pwr_domain_suspend
,
.
pwr_domain_suspend_finish
=
hikey_pwr_domain_suspend_finish
,
.
system_off
=
hikey_system_off
,
.
system_reset
=
hikey_system_reset
,
.
validate_power_state
=
hikey_validate_power_state
,
.
validate_ns_entrypoint
=
hikey_validate_ns_entrypoint
,
.
get_sys_suspend_power_state
=
NULL
,
.
get_sys_suspend_power_state
=
hikey_get_sys_suspend_power_state
,
};
/*******************************************************************************
* Export the platform specific power ops and initialize Power Controller
******************************************************************************/
int
plat_setup_psci_ops
(
uintptr_t
sec_entrypoint
,
const
plat_psci_ops_t
**
psci_ops
)
{
...
...
@@ -197,6 +281,5 @@ int plat_setup_psci_ops(uintptr_t sec_entrypoint,
* Initialize PSCI ops struct
*/
*
psci_ops
=
&
hikey_psci_ops
;
return
0
;
}
plat/hisilicon/hikey/hikey_topology.c
View file @
0ceb3e1e
...
...
@@ -18,8 +18,10 @@ const unsigned char hikey_power_domain_tree_desc[] = {
1
,
/* Number of clusters */
PLATFORM_CLUSTER_COUNT
,
/* Number of CPU cores */
PLATFORM_CORE_COUNT
/* Number of children for the first cluster node */
PLATFORM_CORE_COUNT_PER_CLUSTER
,
/* Number of children for the second cluster node */
PLATFORM_CORE_COUNT_PER_CLUSTER
,
};
/*******************************************************************************
...
...
plat/hisilicon/hikey/platform.mk
View file @
0ceb3e1e
...
...
@@ -65,6 +65,8 @@ HIKEY_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
plat/common/plat_gicv2.c
BL31_SOURCES
+=
drivers/arm/cci/cci.c
\
drivers/arm/sp804/sp804_delay_timer.c
\
drivers/delay_timer/delay_timer.c
\
lib/cpus/aarch64/cortex_a53.S
\
plat/common/aarch64/plat_psci_common.c
\
plat/hisilicon/hikey/aarch64/hikey_helpers.S
\
...
...
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