.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* Copyright (c) 2016 The Linux Foundation. All rights reserved. |
---|
2 | | - * |
---|
3 | | - * This program is free software; you can redistribute it and/or modify |
---|
4 | | - * it under the terms of the GNU General Public License version 2 and |
---|
5 | | - * only version 2 as published by the Free Software Foundation. |
---|
6 | | - * |
---|
7 | | - * This program is distributed in the hope that it will be useful, |
---|
8 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
9 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
10 | | - * GNU General Public License for more details. |
---|
11 | | - * |
---|
12 | 3 | */ |
---|
13 | 4 | |
---|
14 | 5 | #include <linux/pm_opp.h> |
---|
.. | .. |
---|
31 | 22 | |
---|
32 | 23 | #define AGC_POWER_CONFIG_PRODUCTION_ID 1 |
---|
33 | 24 | #define AGC_INIT_MSG_VALUE 0xBABEFACE |
---|
| 25 | + |
---|
| 26 | +/* AGC_LM_CONFIG (A540+) */ |
---|
| 27 | +#define AGC_LM_CONFIG (136/4) |
---|
| 28 | +#define AGC_LM_CONFIG_GPU_VERSION_SHIFT 17 |
---|
| 29 | +#define AGC_LM_CONFIG_ENABLE_GPMU_ADAPTIVE 1 |
---|
| 30 | +#define AGC_LM_CONFIG_THROTTLE_DISABLE (2 << 8) |
---|
| 31 | +#define AGC_LM_CONFIG_ISENSE_ENABLE (1 << 4) |
---|
| 32 | +#define AGC_LM_CONFIG_ENABLE_ERROR (3 << 4) |
---|
| 33 | +#define AGC_LM_CONFIG_LLM_ENABLED (1 << 16) |
---|
| 34 | +#define AGC_LM_CONFIG_BCL_DISABLED (1 << 24) |
---|
| 35 | + |
---|
| 36 | +#define AGC_LEVEL_CONFIG (140/4) |
---|
34 | 37 | |
---|
35 | 38 | static struct { |
---|
36 | 39 | uint32_t reg; |
---|
.. | .. |
---|
116 | 119 | } |
---|
117 | 120 | |
---|
118 | 121 | /* Setup thermal limit management */ |
---|
119 | | -static void a5xx_lm_setup(struct msm_gpu *gpu) |
---|
| 122 | +static void a530_lm_setup(struct msm_gpu *gpu) |
---|
120 | 123 | { |
---|
121 | 124 | struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); |
---|
122 | 125 | struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); |
---|
.. | .. |
---|
165 | 168 | gpu_write(gpu, AGC_INIT_MSG_MAGIC, AGC_INIT_MSG_VALUE); |
---|
166 | 169 | } |
---|
167 | 170 | |
---|
| 171 | +#define PAYLOAD_SIZE(_size) ((_size) * sizeof(u32)) |
---|
| 172 | +#define LM_DCVS_LIMIT 1 |
---|
| 173 | +#define LEVEL_CONFIG ~(0x303) |
---|
| 174 | + |
---|
| 175 | +static void a540_lm_setup(struct msm_gpu *gpu) |
---|
| 176 | +{ |
---|
| 177 | + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); |
---|
| 178 | + u32 config; |
---|
| 179 | + |
---|
| 180 | + /* The battery current limiter isn't enabled for A540 */ |
---|
| 181 | + config = AGC_LM_CONFIG_BCL_DISABLED; |
---|
| 182 | + config |= adreno_gpu->rev.patchid << AGC_LM_CONFIG_GPU_VERSION_SHIFT; |
---|
| 183 | + |
---|
| 184 | + /* For now disable GPMU side throttling */ |
---|
| 185 | + config |= AGC_LM_CONFIG_THROTTLE_DISABLE; |
---|
| 186 | + |
---|
| 187 | + /* Until we get clock scaling 0 is always the active power level */ |
---|
| 188 | + gpu_write(gpu, REG_A5XX_GPMU_GPMU_VOLTAGE, 0x80000000 | 0); |
---|
| 189 | + |
---|
| 190 | + /* Fixed at 6000 for now */ |
---|
| 191 | + gpu_write(gpu, REG_A5XX_GPMU_GPMU_PWR_THRESHOLD, 0x80000000 | 6000); |
---|
| 192 | + |
---|
| 193 | + gpu_write(gpu, AGC_MSG_STATE, 0x80000001); |
---|
| 194 | + gpu_write(gpu, AGC_MSG_COMMAND, AGC_POWER_CONFIG_PRODUCTION_ID); |
---|
| 195 | + |
---|
| 196 | + gpu_write(gpu, AGC_MSG_PAYLOAD(0), 5448); |
---|
| 197 | + gpu_write(gpu, AGC_MSG_PAYLOAD(1), 1); |
---|
| 198 | + |
---|
| 199 | + gpu_write(gpu, AGC_MSG_PAYLOAD(2), _get_mvolts(gpu, gpu->fast_rate)); |
---|
| 200 | + gpu_write(gpu, AGC_MSG_PAYLOAD(3), gpu->fast_rate / 1000000); |
---|
| 201 | + |
---|
| 202 | + gpu_write(gpu, AGC_MSG_PAYLOAD(AGC_LM_CONFIG), config); |
---|
| 203 | + gpu_write(gpu, AGC_MSG_PAYLOAD(AGC_LEVEL_CONFIG), LEVEL_CONFIG); |
---|
| 204 | + gpu_write(gpu, AGC_MSG_PAYLOAD_SIZE, |
---|
| 205 | + PAYLOAD_SIZE(AGC_LEVEL_CONFIG + 1)); |
---|
| 206 | + |
---|
| 207 | + gpu_write(gpu, AGC_INIT_MSG_MAGIC, AGC_INIT_MSG_VALUE); |
---|
| 208 | +} |
---|
| 209 | + |
---|
168 | 210 | /* Enable SP/TP cpower collapse */ |
---|
169 | 211 | static void a5xx_pc_init(struct msm_gpu *gpu) |
---|
170 | 212 | { |
---|
.. | .. |
---|
198 | 240 | OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1); |
---|
199 | 241 | OUT_RING(ring, 1); |
---|
200 | 242 | |
---|
201 | | - gpu->funcs->flush(gpu, ring); |
---|
| 243 | + a5xx_flush(gpu, ring, true); |
---|
202 | 244 | |
---|
203 | 245 | if (!a5xx_idle(gpu, ring)) { |
---|
204 | 246 | DRM_ERROR("%s: Unable to load GPMU firmware. GPMU will not be active\n", |
---|
.. | .. |
---|
206 | 248 | return -EINVAL; |
---|
207 | 249 | } |
---|
208 | 250 | |
---|
209 | | - gpu_write(gpu, REG_A5XX_GPMU_WFI_CONFIG, 0x4014); |
---|
| 251 | + if (adreno_is_a530(adreno_gpu)) |
---|
| 252 | + gpu_write(gpu, REG_A5XX_GPMU_WFI_CONFIG, 0x4014); |
---|
210 | 253 | |
---|
211 | 254 | /* Kick off the GPMU */ |
---|
212 | 255 | gpu_write(gpu, REG_A5XX_GPMU_CM3_SYSRESET, 0x0); |
---|
.. | .. |
---|
220 | 263 | DRM_ERROR("%s: GPMU firmware initialization timed out\n", |
---|
221 | 264 | gpu->name); |
---|
222 | 265 | |
---|
| 266 | + if (!adreno_is_a530(adreno_gpu)) { |
---|
| 267 | + u32 val = gpu_read(gpu, REG_A5XX_GPMU_GENERAL_1); |
---|
| 268 | + |
---|
| 269 | + if (val) |
---|
| 270 | + DRM_ERROR("%s: GPMU firmware initialization failed: %d\n", |
---|
| 271 | + gpu->name, val); |
---|
| 272 | + } |
---|
| 273 | + |
---|
223 | 274 | return 0; |
---|
224 | 275 | } |
---|
225 | 276 | |
---|
226 | 277 | /* Enable limits management */ |
---|
227 | 278 | static void a5xx_lm_enable(struct msm_gpu *gpu) |
---|
228 | 279 | { |
---|
| 280 | + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); |
---|
| 281 | + |
---|
| 282 | + /* This init sequence only applies to A530 */ |
---|
| 283 | + if (!adreno_is_a530(adreno_gpu)) |
---|
| 284 | + return; |
---|
| 285 | + |
---|
229 | 286 | gpu_write(gpu, REG_A5XX_GDPM_INT_MASK, 0x0); |
---|
230 | 287 | gpu_write(gpu, REG_A5XX_GDPM_INT_EN, 0x0A); |
---|
231 | 288 | gpu_write(gpu, REG_A5XX_GPMU_GPMU_VOLTAGE_INTR_EN_MASK, 0x01); |
---|
.. | .. |
---|
237 | 294 | |
---|
238 | 295 | int a5xx_power_init(struct msm_gpu *gpu) |
---|
239 | 296 | { |
---|
| 297 | + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); |
---|
240 | 298 | int ret; |
---|
241 | 299 | |
---|
| 300 | + /* Not all A5xx chips have a GPMU */ |
---|
| 301 | + if (adreno_is_a510(adreno_gpu)) |
---|
| 302 | + return 0; |
---|
| 303 | + |
---|
242 | 304 | /* Set up the limits management */ |
---|
243 | | - a5xx_lm_setup(gpu); |
---|
| 305 | + if (adreno_is_a530(adreno_gpu)) |
---|
| 306 | + a530_lm_setup(gpu); |
---|
| 307 | + else if (adreno_is_a540(adreno_gpu)) |
---|
| 308 | + a540_lm_setup(gpu); |
---|
244 | 309 | |
---|
245 | 310 | /* Set up SP/TP power collpase */ |
---|
246 | 311 | a5xx_pc_init(gpu); |
---|
.. | .. |
---|
264 | 329 | uint32_t dwords = 0, offset = 0, bosize; |
---|
265 | 330 | unsigned int *data, *ptr, *cmds; |
---|
266 | 331 | unsigned int cmds_size; |
---|
| 332 | + |
---|
| 333 | + if (adreno_is_a510(adreno_gpu)) |
---|
| 334 | + return; |
---|
267 | 335 | |
---|
268 | 336 | if (a5xx_gpu->gpmu_bo) |
---|
269 | 337 | return; |
---|
.. | .. |
---|
298 | 366 | MSM_BO_UNCACHED | MSM_BO_GPU_READONLY, gpu->aspace, |
---|
299 | 367 | &a5xx_gpu->gpmu_bo, &a5xx_gpu->gpmu_iova); |
---|
300 | 368 | if (IS_ERR(ptr)) |
---|
301 | | - goto err; |
---|
| 369 | + return; |
---|
| 370 | + |
---|
| 371 | + msm_gem_object_set_name(a5xx_gpu->gpmu_bo, "gpmufw"); |
---|
302 | 372 | |
---|
303 | 373 | while (cmds_size > 0) { |
---|
304 | 374 | int i; |
---|
.. | .. |
---|
317 | 387 | |
---|
318 | 388 | msm_gem_put_vaddr(a5xx_gpu->gpmu_bo); |
---|
319 | 389 | a5xx_gpu->gpmu_dwords = dwords; |
---|
320 | | - |
---|
321 | | - return; |
---|
322 | | -err: |
---|
323 | | - if (a5xx_gpu->gpmu_iova) |
---|
324 | | - msm_gem_put_iova(a5xx_gpu->gpmu_bo, gpu->aspace); |
---|
325 | | - if (a5xx_gpu->gpmu_bo) |
---|
326 | | - drm_gem_object_unreference(a5xx_gpu->gpmu_bo); |
---|
327 | | - |
---|
328 | | - a5xx_gpu->gpmu_bo = NULL; |
---|
329 | | - a5xx_gpu->gpmu_iova = 0; |
---|
330 | | - a5xx_gpu->gpmu_dwords = 0; |
---|
331 | 390 | } |
---|