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