xref: /rk3399_ARM-atf/plat/hisilicon/hikey960/hikey960_pm.c (revision fdae60b6ba27c216fd86d13b7432a1ff4f57dd84)
128b02e23SHaojian Zhuang /*
228b02e23SHaojian Zhuang  * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
328b02e23SHaojian Zhuang  *
428b02e23SHaojian Zhuang  * SPDX-License-Identifier: BSD-3-Clause
528b02e23SHaojian Zhuang  */
628b02e23SHaojian Zhuang 
728b02e23SHaojian Zhuang #include <arch_helpers.h>
828b02e23SHaojian Zhuang #include <assert.h>
928b02e23SHaojian Zhuang #include <cci.h>
1028b02e23SHaojian Zhuang #include <console.h>
1128b02e23SHaojian Zhuang #include <debug.h>
1228b02e23SHaojian Zhuang #include <gicv2.h>
1328b02e23SHaojian Zhuang #include <hi3660.h>
1428b02e23SHaojian Zhuang #include <hi3660_crg.h>
1528b02e23SHaojian Zhuang #include <mmio.h>
1628b02e23SHaojian Zhuang #include <psci.h>
1728b02e23SHaojian Zhuang #include "drivers/pwrc/hisi_pwrc.h"
1828b02e23SHaojian Zhuang 
1928b02e23SHaojian Zhuang #include "hikey960_def.h"
2028b02e23SHaojian Zhuang #include "hikey960_private.h"
2128b02e23SHaojian Zhuang 
2228b02e23SHaojian Zhuang #define CORE_PWR_STATE(state) \
2328b02e23SHaojian Zhuang 	((state)->pwr_domain_state[MPIDR_AFFLVL0])
2428b02e23SHaojian Zhuang #define CLUSTER_PWR_STATE(state) \
2528b02e23SHaojian Zhuang 	((state)->pwr_domain_state[MPIDR_AFFLVL1])
2628b02e23SHaojian Zhuang #define SYSTEM_PWR_STATE(state) \
2728b02e23SHaojian Zhuang 	((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
2828b02e23SHaojian Zhuang 
29*fdae60b6SLeo Yan #define PSTATE_WIDTH		4
30*fdae60b6SLeo Yan #define PSTATE_MASK		((1 << PSTATE_WIDTH) - 1)
31*fdae60b6SLeo Yan 
32*fdae60b6SLeo Yan #define MAKE_PWRSTATE(lvl2_state, lvl1_state, lvl0_state, pwr_lvl, type) \
33*fdae60b6SLeo Yan 		(((lvl2_state) << (PSTATE_ID_SHIFT + PSTATE_WIDTH * 2)) | \
34*fdae60b6SLeo Yan 		 ((lvl1_state) << (PSTATE_ID_SHIFT + PSTATE_WIDTH)) | \
35*fdae60b6SLeo Yan 		 ((lvl0_state) << (PSTATE_ID_SHIFT)) | \
36*fdae60b6SLeo Yan 		 ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \
37*fdae60b6SLeo Yan 		 ((type) << PSTATE_TYPE_SHIFT))
38*fdae60b6SLeo Yan 
39*fdae60b6SLeo Yan /*
40*fdae60b6SLeo Yan  * The table storing the valid idle power states. Ensure that the
41*fdae60b6SLeo Yan  * array entries are populated in ascending order of state-id to
42*fdae60b6SLeo Yan  * enable us to use binary search during power state validation.
43*fdae60b6SLeo Yan  * The table must be terminated by a NULL entry.
44*fdae60b6SLeo Yan  */
45*fdae60b6SLeo Yan const unsigned int hikey960_pwr_idle_states[] = {
46*fdae60b6SLeo Yan 	/* State-id - 0x001 */
47*fdae60b6SLeo Yan 	MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE,
48*fdae60b6SLeo Yan 		      PLAT_MAX_STB_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY),
49*fdae60b6SLeo Yan 	/* State-id - 0x002 */
50*fdae60b6SLeo Yan 	MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE,
51*fdae60b6SLeo Yan 		      PLAT_MAX_RET_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY),
52*fdae60b6SLeo Yan 	/* State-id - 0x003 */
53*fdae60b6SLeo Yan 	MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE,
54*fdae60b6SLeo Yan 		      PLAT_MAX_OFF_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN),
55*fdae60b6SLeo Yan 	/* State-id - 0x033 */
56*fdae60b6SLeo Yan 	MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_OFF_STATE,
57*fdae60b6SLeo Yan 		      PLAT_MAX_OFF_STATE, MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN),
58*fdae60b6SLeo Yan 	0,
59*fdae60b6SLeo Yan };
60*fdae60b6SLeo Yan 
6128b02e23SHaojian Zhuang #define DMAC_GLB_REG_SEC	0x694
6228b02e23SHaojian Zhuang #define AXI_CONF_BASE		0x820
6328b02e23SHaojian Zhuang 
6428b02e23SHaojian Zhuang static uintptr_t hikey960_sec_entrypoint;
6528b02e23SHaojian Zhuang 
6628b02e23SHaojian Zhuang static void hikey960_pwr_domain_standby(plat_local_state_t cpu_state)
6728b02e23SHaojian Zhuang {
6828b02e23SHaojian Zhuang 	unsigned long scr;
6928b02e23SHaojian Zhuang 	unsigned int val = 0;
7028b02e23SHaojian Zhuang 
71*fdae60b6SLeo Yan 	assert(cpu_state == PLAT_MAX_STB_STATE ||
72*fdae60b6SLeo Yan 	       cpu_state == PLAT_MAX_RET_STATE);
7328b02e23SHaojian Zhuang 
7428b02e23SHaojian Zhuang 	scr = read_scr_el3();
7528b02e23SHaojian Zhuang 
7628b02e23SHaojian Zhuang 	/* Enable Physical IRQ and FIQ to wake the CPU*/
7728b02e23SHaojian Zhuang 	write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
7828b02e23SHaojian Zhuang 
79*fdae60b6SLeo Yan 	if (cpu_state == PLAT_MAX_RET_STATE)
8028b02e23SHaojian Zhuang 		set_retention_ticks(val);
81*fdae60b6SLeo Yan 
8228b02e23SHaojian Zhuang 	wfi();
83*fdae60b6SLeo Yan 
84*fdae60b6SLeo Yan 	if (cpu_state == PLAT_MAX_RET_STATE)
8528b02e23SHaojian Zhuang 		clr_retention_ticks(val);
8628b02e23SHaojian Zhuang 
8728b02e23SHaojian Zhuang 	/*
8828b02e23SHaojian Zhuang 	 * Restore SCR to the original value, synchronisazion of
8928b02e23SHaojian Zhuang 	 * scr_el3 is done by eret while el3_exit to save some
9028b02e23SHaojian Zhuang 	 * execution cycles.
9128b02e23SHaojian Zhuang 	 */
9228b02e23SHaojian Zhuang 	write_scr_el3(scr);
9328b02e23SHaojian Zhuang }
9428b02e23SHaojian Zhuang 
9528b02e23SHaojian Zhuang static int hikey960_pwr_domain_on(u_register_t mpidr)
9628b02e23SHaojian Zhuang {
9728b02e23SHaojian Zhuang 	unsigned int core = mpidr & MPIDR_CPU_MASK;
9828b02e23SHaojian Zhuang 	unsigned int cluster =
9928b02e23SHaojian Zhuang 		(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
10028b02e23SHaojian Zhuang 	int cluster_stat = cluster_is_powered_on(cluster);
10128b02e23SHaojian Zhuang 
10228b02e23SHaojian Zhuang 	hisi_set_cpu_boot_flag(cluster, core);
10328b02e23SHaojian Zhuang 
10428b02e23SHaojian Zhuang 	mmio_write_32(CRG_REG_BASE + CRG_RVBAR(cluster, core),
10528b02e23SHaojian Zhuang 		      hikey960_sec_entrypoint >> 2);
10628b02e23SHaojian Zhuang 
10728b02e23SHaojian Zhuang 	if (cluster_stat)
10828b02e23SHaojian Zhuang 		hisi_powerup_core(cluster, core);
10928b02e23SHaojian Zhuang 	else
11028b02e23SHaojian Zhuang 		hisi_powerup_cluster(cluster, core);
11128b02e23SHaojian Zhuang 
11228b02e23SHaojian Zhuang 	return PSCI_E_SUCCESS;
11328b02e23SHaojian Zhuang }
11428b02e23SHaojian Zhuang 
11528b02e23SHaojian Zhuang static void
11628b02e23SHaojian Zhuang hikey960_pwr_domain_on_finish(const psci_power_state_t *target_state)
11728b02e23SHaojian Zhuang {
11828b02e23SHaojian Zhuang 	if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
11928b02e23SHaojian Zhuang 		cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
12028b02e23SHaojian Zhuang 
12128b02e23SHaojian Zhuang 	gicv2_pcpu_distif_init();
12228b02e23SHaojian Zhuang 	gicv2_cpuif_enable();
12328b02e23SHaojian Zhuang }
12428b02e23SHaojian Zhuang 
12528b02e23SHaojian Zhuang void hikey960_pwr_domain_off(const psci_power_state_t *target_state)
12628b02e23SHaojian Zhuang {
12728b02e23SHaojian Zhuang 	unsigned long mpidr = read_mpidr_el1();
12828b02e23SHaojian Zhuang 	unsigned int core = mpidr & MPIDR_CPU_MASK;
12928b02e23SHaojian Zhuang 	unsigned int cluster =
13028b02e23SHaojian Zhuang 		(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
13128b02e23SHaojian Zhuang 
13228b02e23SHaojian Zhuang 	clr_ex();
13328b02e23SHaojian Zhuang 	isb();
13428b02e23SHaojian Zhuang 	dsbsy();
13528b02e23SHaojian Zhuang 
13628b02e23SHaojian Zhuang 	gicv2_cpuif_disable();
13728b02e23SHaojian Zhuang 
13828b02e23SHaojian Zhuang 	hisi_clear_cpu_boot_flag(cluster, core);
13928b02e23SHaojian Zhuang 	hisi_powerdn_core(cluster, core);
14028b02e23SHaojian Zhuang 
14128b02e23SHaojian Zhuang 	/* check if any core is powered up */
1420aedca71SLeo Yan 	if (hisi_test_cpu_down(cluster, core)) {
14328b02e23SHaojian Zhuang 
14428b02e23SHaojian Zhuang 		cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
14528b02e23SHaojian Zhuang 
14628b02e23SHaojian Zhuang 		isb();
14728b02e23SHaojian Zhuang 		dsbsy();
14828b02e23SHaojian Zhuang 
14928b02e23SHaojian Zhuang 		hisi_powerdn_cluster(cluster, core);
15028b02e23SHaojian Zhuang 	}
15128b02e23SHaojian Zhuang }
15228b02e23SHaojian Zhuang 
15328b02e23SHaojian Zhuang static void __dead2 hikey960_system_reset(void)
15428b02e23SHaojian Zhuang {
15528b02e23SHaojian Zhuang 	mmio_write_32(SCTRL_SCPEREN1_REG,
15628b02e23SHaojian Zhuang 		      SCPEREN1_WAIT_DDR_SELFREFRESH_DONE_BYPASS);
15728b02e23SHaojian Zhuang 	mmio_write_32(SCTRL_SCSYSSTAT_REG, 0xdeadbeef);
15828b02e23SHaojian Zhuang 	panic();
15928b02e23SHaojian Zhuang }
16028b02e23SHaojian Zhuang 
16128b02e23SHaojian Zhuang int hikey960_validate_power_state(unsigned int power_state,
16228b02e23SHaojian Zhuang 			       psci_power_state_t *req_state)
16328b02e23SHaojian Zhuang {
164*fdae60b6SLeo Yan 	unsigned int state_id;
16528b02e23SHaojian Zhuang 	int i;
16628b02e23SHaojian Zhuang 
16728b02e23SHaojian Zhuang 	assert(req_state);
16828b02e23SHaojian Zhuang 
16928b02e23SHaojian Zhuang 	/*
170*fdae60b6SLeo Yan 	 *  Currently we are using a linear search for finding the matching
171*fdae60b6SLeo Yan 	 *  entry in the idle power state array. This can be made a binary
172*fdae60b6SLeo Yan 	 *  search if the number of entries justify the additional complexity.
17328b02e23SHaojian Zhuang 	 */
174*fdae60b6SLeo Yan 	for (i = 0; !!hikey960_pwr_idle_states[i]; i++) {
175*fdae60b6SLeo Yan 		if (power_state == hikey960_pwr_idle_states[i])
176*fdae60b6SLeo Yan 			break;
17728b02e23SHaojian Zhuang 	}
17828b02e23SHaojian Zhuang 
179*fdae60b6SLeo Yan 	/* Return error if entry not found in the idle state array */
180*fdae60b6SLeo Yan 	if (!hikey960_pwr_idle_states[i])
18128b02e23SHaojian Zhuang 		return PSCI_E_INVALID_PARAMS;
18228b02e23SHaojian Zhuang 
183*fdae60b6SLeo Yan 	i = 0;
184*fdae60b6SLeo Yan 	state_id = psci_get_pstate_id(power_state);
185*fdae60b6SLeo Yan 
186*fdae60b6SLeo Yan 	/* Parse the State ID and populate the state info parameter */
187*fdae60b6SLeo Yan 	while (state_id) {
188*fdae60b6SLeo Yan 		req_state->pwr_domain_state[i++] = state_id & PSTATE_MASK;
189*fdae60b6SLeo Yan 		state_id >>= PSTATE_WIDTH;
190*fdae60b6SLeo Yan 	}
191*fdae60b6SLeo Yan 
19228b02e23SHaojian Zhuang 	return PSCI_E_SUCCESS;
19328b02e23SHaojian Zhuang }
19428b02e23SHaojian Zhuang 
19528b02e23SHaojian Zhuang static int hikey960_validate_ns_entrypoint(uintptr_t entrypoint)
19628b02e23SHaojian Zhuang {
19728b02e23SHaojian Zhuang 	/*
19828b02e23SHaojian Zhuang 	 * Check if the non secure entrypoint lies within the non
19928b02e23SHaojian Zhuang 	 * secure DRAM.
20028b02e23SHaojian Zhuang 	 */
20128b02e23SHaojian Zhuang 	if ((entrypoint > DDR_BASE) && (entrypoint < (DDR_BASE + DDR_SIZE)))
20228b02e23SHaojian Zhuang 		return PSCI_E_SUCCESS;
20328b02e23SHaojian Zhuang 
20428b02e23SHaojian Zhuang 	return PSCI_E_INVALID_ADDRESS;
20528b02e23SHaojian Zhuang }
20628b02e23SHaojian Zhuang 
20728b02e23SHaojian Zhuang static void hikey960_pwr_domain_suspend(const psci_power_state_t *target_state)
20828b02e23SHaojian Zhuang {
20928b02e23SHaojian Zhuang 	u_register_t mpidr = read_mpidr_el1();
21028b02e23SHaojian Zhuang 	unsigned int core = mpidr & MPIDR_CPU_MASK;
21128b02e23SHaojian Zhuang 	unsigned int cluster =
21228b02e23SHaojian Zhuang 		(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
21328b02e23SHaojian Zhuang 
21428b02e23SHaojian Zhuang 	if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
21528b02e23SHaojian Zhuang 		return;
21628b02e23SHaojian Zhuang 
21728b02e23SHaojian Zhuang 	if (CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
21828b02e23SHaojian Zhuang 		clr_ex();
21928b02e23SHaojian Zhuang 		isb();
22028b02e23SHaojian Zhuang 		dsbsy();
22128b02e23SHaojian Zhuang 
22228b02e23SHaojian Zhuang 		gicv2_cpuif_disable();
22328b02e23SHaojian Zhuang 
22428b02e23SHaojian Zhuang 		hisi_cpuidle_lock(cluster, core);
22528b02e23SHaojian Zhuang 		hisi_set_cpuidle_flag(cluster, core);
22628b02e23SHaojian Zhuang 		hisi_cpuidle_unlock(cluster, core);
22728b02e23SHaojian Zhuang 
22828b02e23SHaojian Zhuang 		mmio_write_32(CRG_REG_BASE + CRG_RVBAR(cluster, core),
22928b02e23SHaojian Zhuang 		      hikey960_sec_entrypoint >> 2);
23028b02e23SHaojian Zhuang 
23128b02e23SHaojian Zhuang 		hisi_enter_core_idle(cluster, core);
23228b02e23SHaojian Zhuang 	}
23328b02e23SHaojian Zhuang 
23428b02e23SHaojian Zhuang 	/* Perform the common cluster specific operations */
23528b02e23SHaojian Zhuang 	if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
23628b02e23SHaojian Zhuang 		hisi_cpuidle_lock(cluster, core);
23728b02e23SHaojian Zhuang 		hisi_disable_pdc(cluster);
23828b02e23SHaojian Zhuang 
23928b02e23SHaojian Zhuang 		/* check if any core is powered up */
24028b02e23SHaojian Zhuang 		if (hisi_test_pwrdn_allcores(cluster, core)) {
24128b02e23SHaojian Zhuang 
24228b02e23SHaojian Zhuang 			cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
24328b02e23SHaojian Zhuang 
24428b02e23SHaojian Zhuang 			isb();
24528b02e23SHaojian Zhuang 			dsbsy();
24628b02e23SHaojian Zhuang 
24728b02e23SHaojian Zhuang 			/* mask the pdc wakeup irq, then
24828b02e23SHaojian Zhuang 			 * enable pdc to power down the core
24928b02e23SHaojian Zhuang 			 */
25028b02e23SHaojian Zhuang 			hisi_pdc_mask_cluster_wakeirq(cluster);
25128b02e23SHaojian Zhuang 			hisi_enable_pdc(cluster);
25228b02e23SHaojian Zhuang 
25328b02e23SHaojian Zhuang 			hisi_cpuidle_unlock(cluster, core);
25428b02e23SHaojian Zhuang 
25528b02e23SHaojian Zhuang 			/* check the SR flag bit to determine
25628b02e23SHaojian Zhuang 			 * CLUSTER_IDLE_IPC or AP_SR_IPC to send
25728b02e23SHaojian Zhuang 			 */
25828b02e23SHaojian Zhuang 			if (hisi_test_ap_suspend_flag(cluster))
25928b02e23SHaojian Zhuang 				hisi_enter_ap_suspend(cluster, core);
26028b02e23SHaojian Zhuang 			else
26128b02e23SHaojian Zhuang 				hisi_enter_cluster_idle(cluster, core);
26228b02e23SHaojian Zhuang 		} else {
26328b02e23SHaojian Zhuang 			/* enable pdc */
26428b02e23SHaojian Zhuang 			hisi_enable_pdc(cluster);
26528b02e23SHaojian Zhuang 			hisi_cpuidle_unlock(cluster, core);
26628b02e23SHaojian Zhuang 		}
26728b02e23SHaojian Zhuang 	}
26828b02e23SHaojian Zhuang }
26928b02e23SHaojian Zhuang 
27028b02e23SHaojian Zhuang static void hikey960_sr_dma_reinit(void)
27128b02e23SHaojian Zhuang {
27228b02e23SHaojian Zhuang 	unsigned int ctr = 0;
27328b02e23SHaojian Zhuang 
27428b02e23SHaojian Zhuang 	mmio_write_32(DMAC_BASE + DMAC_GLB_REG_SEC, 0x3);
27528b02e23SHaojian Zhuang 
27628b02e23SHaojian Zhuang 	/* 1~15 channel is set non_secure */
27728b02e23SHaojian Zhuang 	for (ctr = 1; ctr <= 15; ctr++)
27828b02e23SHaojian Zhuang 		mmio_write_32(DMAC_BASE + AXI_CONF_BASE + ctr * (0x40),
27928b02e23SHaojian Zhuang 			      (1 << 6) | (1 << 18));
28028b02e23SHaojian Zhuang }
28128b02e23SHaojian Zhuang 
28228b02e23SHaojian Zhuang static void
28328b02e23SHaojian Zhuang hikey960_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
28428b02e23SHaojian Zhuang {
28528b02e23SHaojian Zhuang 	unsigned long mpidr = read_mpidr_el1();
2864af7fcb8STao Wang 	unsigned int core = mpidr & MPIDR_CPU_MASK;
28728b02e23SHaojian Zhuang 	unsigned int cluster =
28828b02e23SHaojian Zhuang 		(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
28928b02e23SHaojian Zhuang 
29028b02e23SHaojian Zhuang 	/* Nothing to be done on waking up from retention from CPU level */
29128b02e23SHaojian Zhuang 	if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
29228b02e23SHaojian Zhuang 		return;
29328b02e23SHaojian Zhuang 
2944af7fcb8STao Wang 	hisi_cpuidle_lock(cluster, core);
2954af7fcb8STao Wang 	hisi_clear_cpuidle_flag(cluster, core);
2964af7fcb8STao Wang 	hisi_cpuidle_unlock(cluster, core);
2974af7fcb8STao Wang 
29828b02e23SHaojian Zhuang 	if (hisi_test_ap_suspend_flag(cluster)) {
29928b02e23SHaojian Zhuang 		hikey960_sr_dma_reinit();
30028b02e23SHaojian Zhuang 		gicv2_cpuif_enable();
30128b02e23SHaojian Zhuang 		console_init(PL011_UART6_BASE, PL011_UART_CLK_IN_HZ,
30228b02e23SHaojian Zhuang 			     PL011_BAUDRATE);
30328b02e23SHaojian Zhuang 	}
30428b02e23SHaojian Zhuang 
30528b02e23SHaojian Zhuang 	hikey960_pwr_domain_on_finish(target_state);
30628b02e23SHaojian Zhuang }
30728b02e23SHaojian Zhuang 
30828b02e23SHaojian Zhuang static void hikey960_get_sys_suspend_power_state(psci_power_state_t *req_state)
30928b02e23SHaojian Zhuang {
31028b02e23SHaojian Zhuang 	int i;
31128b02e23SHaojian Zhuang 
31228b02e23SHaojian Zhuang 	for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
31328b02e23SHaojian Zhuang 		req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
31428b02e23SHaojian Zhuang }
31528b02e23SHaojian Zhuang 
31628b02e23SHaojian Zhuang static const plat_psci_ops_t hikey960_psci_ops = {
31728b02e23SHaojian Zhuang 	.cpu_standby			= hikey960_pwr_domain_standby,
31828b02e23SHaojian Zhuang 	.pwr_domain_on			= hikey960_pwr_domain_on,
31928b02e23SHaojian Zhuang 	.pwr_domain_on_finish		= hikey960_pwr_domain_on_finish,
32028b02e23SHaojian Zhuang 	.pwr_domain_off			= hikey960_pwr_domain_off,
32128b02e23SHaojian Zhuang 	.pwr_domain_suspend		= hikey960_pwr_domain_suspend,
32228b02e23SHaojian Zhuang 	.pwr_domain_suspend_finish	= hikey960_pwr_domain_suspend_finish,
32328b02e23SHaojian Zhuang 	.system_off			= NULL,
32428b02e23SHaojian Zhuang 	.system_reset			= hikey960_system_reset,
32528b02e23SHaojian Zhuang 	.validate_power_state		= hikey960_validate_power_state,
32628b02e23SHaojian Zhuang 	.validate_ns_entrypoint		= hikey960_validate_ns_entrypoint,
32728b02e23SHaojian Zhuang 	.get_sys_suspend_power_state	= hikey960_get_sys_suspend_power_state,
32828b02e23SHaojian Zhuang };
32928b02e23SHaojian Zhuang 
33028b02e23SHaojian Zhuang int plat_setup_psci_ops(uintptr_t sec_entrypoint,
33128b02e23SHaojian Zhuang 			const plat_psci_ops_t **psci_ops)
33228b02e23SHaojian Zhuang {
33328b02e23SHaojian Zhuang 	hikey960_sec_entrypoint = sec_entrypoint;
33428b02e23SHaojian Zhuang 
33528b02e23SHaojian Zhuang 	INFO("%s: sec_entrypoint=0x%lx\n", __func__,
33628b02e23SHaojian Zhuang 	     (unsigned long)hikey960_sec_entrypoint);
33728b02e23SHaojian Zhuang 
33828b02e23SHaojian Zhuang 	/*
33928b02e23SHaojian Zhuang 	 * Initialize PSCI ops struct
34028b02e23SHaojian Zhuang 	 */
34128b02e23SHaojian Zhuang 	*psci_ops = &hikey960_psci_ops;
34228b02e23SHaojian Zhuang 	return 0;
34328b02e23SHaojian Zhuang }
344