xref: /rk3399_ARM-atf/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c (revision 82cb2c1ad9897473743f08437d0a3995bed561b9)
1 /*
2  * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <arch.h>
8 #include <arch_helpers.h>
9 #include <debug.h>
10 #include <denver.h>
11 #include <mmio.h>
12 #include <mce_private.h>
13 #include <sys/errno.h>
14 #include <t18x_ari.h>
15 
16 extern void nvg_set_request_data(uint64_t req, uint64_t data);
17 extern void nvg_set_request(uint64_t req);
18 extern uint64_t nvg_get_result(void);
19 
20 int nvg_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time)
21 {
22 	/* check for allowed power state */
23 	if (state != TEGRA_ARI_CORE_C0 && state != TEGRA_ARI_CORE_C1 &&
24 	    state != TEGRA_ARI_CORE_C6 && state != TEGRA_ARI_CORE_C7) {
25 		ERROR("%s: unknown cstate (%d)\n", __func__, state);
26 		return EINVAL;
27 	}
28 
29 	/* time (TSC ticks) until the core is expected to get a wake event */
30 	nvg_set_request_data(TEGRA_NVG_CHANNEL_WAKE_TIME, wake_time);
31 
32 	/* set the core cstate */
33 	write_actlr_el1(state);
34 
35 	return 0;
36 }
37 
38 /*
39  * This request allows updating of CLUSTER_CSTATE, CCPLEX_CSTATE and
40  * SYSTEM_CSTATE values.
41  */
42 int nvg_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex,
43 		uint32_t system, uint8_t sys_state_force, uint32_t wake_mask,
44 		uint8_t update_wake_mask)
45 {
46 	uint64_t val = 0;
47 
48 	/* update CLUSTER_CSTATE? */
49 	if (cluster)
50 		val |= (cluster & CLUSTER_CSTATE_MASK) |
51 			CLUSTER_CSTATE_UPDATE_BIT;
52 
53 	/* update CCPLEX_CSTATE? */
54 	if (ccplex)
55 		val |= (ccplex & CCPLEX_CSTATE_MASK) << CCPLEX_CSTATE_SHIFT |
56 			CCPLEX_CSTATE_UPDATE_BIT;
57 
58 	/* update SYSTEM_CSTATE? */
59 	if (system)
60 		val |= ((system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) |
61 		       ((sys_state_force << SYSTEM_CSTATE_FORCE_UPDATE_SHIFT) |
62 			SYSTEM_CSTATE_UPDATE_BIT);
63 
64 	/* update wake mask value? */
65 	if (update_wake_mask)
66 		val |= CSTATE_WAKE_MASK_UPDATE_BIT;
67 
68 	/* set the wake mask */
69 	val &= CSTATE_WAKE_MASK_CLEAR;
70 	val |= ((uint64_t)wake_mask << CSTATE_WAKE_MASK_SHIFT);
71 
72 	/* set the updated cstate info */
73 	nvg_set_request_data(TEGRA_NVG_CHANNEL_CSTATE_INFO, val);
74 
75 	return 0;
76 }
77 
78 int nvg_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time)
79 {
80 	/* sanity check crossover type */
81 	if (type > TEGRA_ARI_CROSSOVER_CCP3_SC1)
82 		return EINVAL;
83 
84 	/*
85 	 * The crossover threshold limit types start from
86 	 * TEGRA_CROSSOVER_TYPE_C1_C6 to TEGRA_CROSSOVER_TYPE_CCP3_SC7. The
87 	 * command indices for updating the threshold can be generated
88 	 * by adding the type to the NVG_SET_THRESHOLD_CROSSOVER_C1_C6
89 	 * command index.
90 	 */
91 	nvg_set_request_data(TEGRA_NVG_CHANNEL_CROSSOVER_C1_C6 + type,
92 		(uint64_t)time);
93 
94 	return 0;
95 }
96 
97 uint64_t nvg_read_cstate_stats(uint32_t ari_base, uint32_t state)
98 {
99 	/* sanity check state */
100 	if (state == 0)
101 		return EINVAL;
102 
103 	/*
104 	 * The cstate types start from NVG_READ_CSTATE_STATS_SC7_ENTRIES
105 	 * to NVG_GET_LAST_CSTATE_ENTRY_A57_3. The command indices for
106 	 * reading the threshold can be generated by adding the type to
107 	 * the NVG_CLEAR_CSTATE_STATS command index.
108 	 */
109 	nvg_set_request(TEGRA_NVG_CHANNEL_CSTATE_STATS_CLEAR + state);
110 
111 	return (int64_t)nvg_get_result();
112 }
113 
114 int nvg_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats)
115 {
116 	uint64_t val;
117 
118 	/*
119 	 * The only difference between a CSTATE_STATS_WRITE and
120 	 * CSTATE_STATS_READ is the usage of the 63:32 in the request.
121 	 * 63:32 are set to '0' for a read, while a write contains the
122 	 * actual stats value to be written.
123 	 */
124 	val = ((uint64_t)stats << MCE_CSTATE_STATS_TYPE_SHIFT) | state;
125 
126 	/*
127 	 * The cstate types start from NVG_READ_CSTATE_STATS_SC7_ENTRIES
128 	 * to NVG_GET_LAST_CSTATE_ENTRY_A57_3. The command indices for
129 	 * reading the threshold can be generated by adding the type to
130 	 * the NVG_CLEAR_CSTATE_STATS command index.
131 	 */
132 	nvg_set_request_data(TEGRA_NVG_CHANNEL_CSTATE_STATS_CLEAR + state, val);
133 
134 	return 0;
135 }
136 
137 int nvg_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time)
138 {
139 	/* This does not apply to the Denver cluster */
140 	return 0;
141 }
142 
143 int nvg_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time)
144 {
145 	uint64_t val;
146 
147 	/* check for allowed power state */
148 	if (state != TEGRA_ARI_CORE_C0 && state != TEGRA_ARI_CORE_C1 &&
149 	    state != TEGRA_ARI_CORE_C6 && state != TEGRA_ARI_CORE_C7) {
150 		ERROR("%s: unknown cstate (%d)\n", __func__, state);
151 		return EINVAL;
152 	}
153 
154 	/*
155 	 * Request format -
156 	 * 63:32 = wake time
157 	 * 31:0 = C-state for this core
158 	 */
159 	val = ((uint64_t)wake_time << MCE_SC7_WAKE_TIME_SHIFT) |
160 			(state & MCE_SC7_ALLOWED_MASK);
161 
162 	/* issue command to check if SC7 is allowed */
163 	nvg_set_request_data(TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED, val);
164 
165 	/* 1 = SC7 allowed, 0 = SC7 not allowed */
166 	return !!nvg_get_result();
167 }
168 
169 int nvg_online_core(uint32_t ari_base, uint32_t core)
170 {
171 	int cpu = read_mpidr() & MPIDR_CPU_MASK;
172 	int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
173 
174 	/* sanity check code id */
175 	if ((core >= MCE_CORE_ID_MAX) || (cpu == core)) {
176 		ERROR("%s: unsupported core id (%d)\n", __func__, core);
177 		return EINVAL;
178 	}
179 
180 	/*
181 	 * The Denver cluster has 2 CPUs only - 0, 1.
182 	 */
183 	if (impl == DENVER_IMPL && ((core == 2) || (core == 3))) {
184 		ERROR("%s: unknown core id (%d)\n", __func__, core);
185 		return EINVAL;
186 	}
187 
188 	/* get a core online */
189 	nvg_set_request_data(TEGRA_NVG_CHANNEL_ONLINE_CORE, core & MCE_CORE_ID_MASK);
190 
191 	return 0;
192 }
193 
194 int nvg_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable)
195 {
196 	int val;
197 
198 	/*
199 	 * If the enable bit is cleared, Auto-CC3 will be disabled by setting
200 	 * the SW visible voltage/frequency request registers for all non
201 	 * floorswept cores valid independent of StandbyWFI and disabling
202 	 * the IDLE voltage/frequency request register. If set, Auto-CC3
203 	 * will be enabled by setting the ARM SW visible voltage/frequency
204 	 * request registers for all non floorswept cores to be enabled by
205 	 * StandbyWFI or the equivalent signal, and always keeping the IDLE
206 	 * voltage/frequency request register enabled.
207 	 */
208 	val = (((freq & MCE_AUTO_CC3_FREQ_MASK) << MCE_AUTO_CC3_FREQ_SHIFT) |\
209 		((volt & MCE_AUTO_CC3_VTG_MASK) << MCE_AUTO_CC3_VTG_SHIFT) |\
210 		(enable ? MCE_AUTO_CC3_ENABLE_BIT : 0));
211 
212 	nvg_set_request_data(TEGRA_NVG_CHANNEL_CC3_CTRL, val);
213 
214 	return 0;
215 }
216