blob: e59cac94cd30899af00aba158604f5f55de627ad [file] [log] [blame]
Jorge Ramirez-Ortiza29d9a62017-06-28 10:11:31 +02001/*
2 * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch_helpers.h>
Jorge Ramirez-Ortiza29d9a62017-06-28 10:11:31 +02008#include <assert.h>
9#include <bl_common.h>
10#include <console.h>
11#include <context.h>
12#include <context_mgmt.h>
13#include <debug.h>
14#include <mmio.h>
15#include <plat_arm.h>
16#include <platform.h>
17#include <psci.h>
18#include "hi3798cv200.h"
19#include "plat_private.h"
20#include "platform_def.h"
21
22#define REG_PERI_CPU_RVBARADDR 0xF8A80034
23#define REG_PERI_CPU_AARCH_MODE 0xF8A80030
24
25#define REG_CPU_LP_CPU_SW_BEGIN 10
26#define CPU_REG_COREPO_SRST 12
27#define CPU_REG_CORE_SRST 8
28
29static void poplar_cpu_standby(plat_local_state_t cpu_state)
30{
31 dsb();
32 wfi();
33}
34
35static int poplar_pwr_domain_on(u_register_t mpidr)
36{
37 unsigned int cpu = plat_core_pos_by_mpidr(mpidr);
38 unsigned int regval, regval_bak;
39
40 /* Select 400MHz before start slave cores */
41 regval_bak = mmio_read_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP));
42 mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), 0x206);
43 mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), 0x606);
44
45 /* Clear the slave cpu arm_por_srst_req reset */
46 regval = mmio_read_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST));
47 regval &= ~(1 << (cpu + CPU_REG_COREPO_SRST));
48 mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST), regval);
49
50 /* Clear the slave cpu reset */
51 regval = mmio_read_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST));
52 regval &= ~(1 << (cpu + CPU_REG_CORE_SRST));
53 mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST), regval);
54
55 /* Restore cpu frequency */
56 regval = regval_bak & (~(1 << REG_CPU_LP_CPU_SW_BEGIN));
57 mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), regval);
58 mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), regval_bak);
59
60 return PSCI_E_SUCCESS;
61}
62
63static void poplar_pwr_domain_off(const psci_power_state_t *target_state)
64{
65 assert(0);
66}
67
68static void poplar_pwr_domain_suspend(const psci_power_state_t *target_state)
69{
70 assert(0);
71}
72
73static void poplar_pwr_domain_on_finish(const psci_power_state_t *target_state)
74{
75 assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
76 PLAT_MAX_OFF_STATE);
77
78 /* Enable the gic cpu interface */
79 plat_arm_gic_pcpu_init();
80
81 /* Program the gic per-cpu distributor or re-distributor interface */
82 plat_arm_gic_cpuif_enable();
83}
84
85static void poplar_pwr_domain_suspend_finish(
86 const psci_power_state_t *target_state)
87{
88 assert(0);
89}
90
91static void __dead2 poplar_system_off(void)
92{
93 ERROR("Poplar System Off: operation not handled.\n");
94 panic();
95}
96
97static void __dead2 poplar_system_reset(void)
98{
99 mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0xc00), 0x1ACCE551);
100 mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0x0), 0x00000100);
101 mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0x8), 0x00000003);
102
103 wfi();
104 ERROR("Poplar System Reset: operation not handled.\n");
105 panic();
106}
107
108static int32_t poplar_validate_power_state(unsigned int power_state,
109 psci_power_state_t *req_state)
110{
111 VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
112
113 int pstate = psci_get_pstate_type(power_state);
114
115 assert(req_state);
116
117 /* Sanity check the requested state */
118 if (pstate == PSTATE_TYPE_STANDBY)
119 req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE;
120 else
121 req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE;
122
123 /* We expect the 'state id' to be zero */
124 if (psci_get_pstate_id(power_state))
125 return PSCI_E_INVALID_PARAMS;
126
127 return PSCI_E_SUCCESS;
128}
129
130static int poplar_validate_ns_entrypoint(uintptr_t entrypoint)
131{
132 /*
133 * Check if the non secure entrypoint lies within the non
134 * secure DRAM.
135 */
136 if ((entrypoint >= DDR_BASE) && (entrypoint < (DDR_BASE + DDR_SIZE)))
137 return PSCI_E_SUCCESS;
138
139 return PSCI_E_INVALID_ADDRESS;
140}
141
142static void poplar_get_sys_suspend_power_state(psci_power_state_t *req_state)
143{
144 int i;
145
146 for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
147 req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
148}
149
150static const plat_psci_ops_t poplar_plat_psci_ops = {
151 .cpu_standby = poplar_cpu_standby,
152 .pwr_domain_on = poplar_pwr_domain_on,
153 .pwr_domain_off = poplar_pwr_domain_off,
154 .pwr_domain_suspend = poplar_pwr_domain_suspend,
155 .pwr_domain_on_finish = poplar_pwr_domain_on_finish,
156 .pwr_domain_suspend_finish = poplar_pwr_domain_suspend_finish,
157 .system_off = poplar_system_off,
158 .system_reset = poplar_system_reset,
159 .validate_power_state = poplar_validate_power_state,
160 .validate_ns_entrypoint = poplar_validate_ns_entrypoint,
161 .get_sys_suspend_power_state = poplar_get_sys_suspend_power_state,
162};
163
164int plat_setup_psci_ops(uintptr_t sec_entrypoint,
165 const plat_psci_ops_t **psci_ops)
166{
167 *psci_ops = &poplar_plat_psci_ops;
168
169 mmio_write_32((uintptr_t)REG_PERI_CPU_AARCH_MODE, 0xF);
170 mmio_write_32((uintptr_t)REG_PERI_CPU_RVBARADDR, sec_entrypoint);
171 return 0;
172}