2 * Copyright 2015 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
24 #include <linux/delay.h>
25 #include <linux/gfp.h>
26 #include <linux/kernel.h>
27 #include <linux/ktime.h>
28 #include <linux/slab.h>
29 #include <linux/types.h>
31 #include "cgs_common.h"
32 #include "smu/smu_8_0_d.h"
33 #include "smu/smu_8_0_sh_mask.h"
35 #include "smu8_fusion.h"
36 #include "smu8_smumgr.h"
38 #include "smu_ucode_xfer_cz.h"
39 #include "gca/gfx_8_0_d.h"
40 #include "gca/gfx_8_0_sh_mask.h"
43 #define SIZE_ALIGN_32(x) (((x) + 31) / 32 * 32)
45 static const enum smu8_scratch_entry firmware_list
[] = {
46 SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0
,
47 SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1
,
48 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE
,
49 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP
,
50 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME
,
51 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1
,
52 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2
,
53 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G
,
56 static uint32_t smu8_get_argument(struct pp_hwmgr
*hwmgr
)
58 if (hwmgr
== NULL
|| hwmgr
->device
== NULL
)
61 return cgs_read_register(hwmgr
->device
,
62 mmSMU_MP1_SRBM2P_ARG_0
);
65 /* Send a message to the SMC, and wait for its response.*/
66 static int smu8_send_msg_to_smc_with_parameter(struct pp_hwmgr
*hwmgr
,
67 uint16_t msg
, uint32_t parameter
)
73 if (hwmgr
== NULL
|| hwmgr
->device
== NULL
)
76 result
= PHM_WAIT_FIELD_UNEQUAL(hwmgr
,
77 SMU_MP1_SRBM2P_RESP_0
, CONTENT
, 0);
79 /* Read the last message to SMU, to report actual cause */
80 uint32_t val
= cgs_read_register(hwmgr
->device
,
81 mmSMU_MP1_SRBM2P_MSG_0
);
82 pr_err("%s(0x%04x) aborted; SMU still servicing msg (0x%04x)\n",
86 t_start
= ktime_get();
88 cgs_write_register(hwmgr
->device
, mmSMU_MP1_SRBM2P_ARG_0
, parameter
);
90 cgs_write_register(hwmgr
->device
, mmSMU_MP1_SRBM2P_RESP_0
, 0);
91 cgs_write_register(hwmgr
->device
, mmSMU_MP1_SRBM2P_MSG_0
, msg
);
93 result
= PHM_WAIT_FIELD_UNEQUAL(hwmgr
,
94 SMU_MP1_SRBM2P_RESP_0
, CONTENT
, 0);
96 elapsed_us
= ktime_us_delta(ktime_get(), t_start
);
98 WARN(result
, "%s(0x%04x, %#x) timed out after %lld us\n",
99 __func__
, msg
, parameter
, elapsed_us
);
104 static int smu8_send_msg_to_smc(struct pp_hwmgr
*hwmgr
, uint16_t msg
)
106 return smu8_send_msg_to_smc_with_parameter(hwmgr
, msg
, 0);
109 static int smu8_set_smc_sram_address(struct pp_hwmgr
*hwmgr
,
110 uint32_t smc_address
, uint32_t limit
)
112 if (hwmgr
== NULL
|| hwmgr
->device
== NULL
)
115 if (0 != (3 & smc_address
)) {
116 pr_err("SMC address must be 4 byte aligned\n");
120 if (limit
<= (smc_address
+ 3)) {
121 pr_err("SMC address beyond the SMC RAM area\n");
125 cgs_write_register(hwmgr
->device
, mmMP0PUB_IND_INDEX_0
,
126 SMN_MP1_SRAM_START_ADDR
+ smc_address
);
131 static int smu8_write_smc_sram_dword(struct pp_hwmgr
*hwmgr
,
132 uint32_t smc_address
, uint32_t value
, uint32_t limit
)
136 if (hwmgr
== NULL
|| hwmgr
->device
== NULL
)
139 result
= smu8_set_smc_sram_address(hwmgr
, smc_address
, limit
);
141 cgs_write_register(hwmgr
->device
, mmMP0PUB_IND_DATA_0
, value
);
146 static int smu8_check_fw_load_finish(struct pp_hwmgr
*hwmgr
,
150 uint32_t index
= SMN_MP1_SRAM_START_ADDR
+
151 SMU8_FIRMWARE_HEADER_LOCATION
+
152 offsetof(struct SMU8_Firmware_Header
, UcodeLoadStatus
);
154 if (hwmgr
== NULL
|| hwmgr
->device
== NULL
)
157 cgs_write_register(hwmgr
->device
, mmMP0PUB_IND_INDEX
, index
);
159 for (i
= 0; i
< hwmgr
->usec_timeout
; i
++) {
161 (cgs_read_register(hwmgr
->device
, mmMP0PUB_IND_DATA
) & firmware
))
166 if (i
>= hwmgr
->usec_timeout
) {
167 pr_err("SMU check loaded firmware failed.\n");
174 static int smu8_load_mec_firmware(struct pp_hwmgr
*hwmgr
)
179 struct cgs_firmware_info info
= {0};
181 if (hwmgr
== NULL
|| hwmgr
->device
== NULL
)
184 ret
= cgs_get_firmware_info(hwmgr
->device
,
185 CGS_UCODE_ID_CP_MEC
, &info
);
190 /* Disable MEC parsing/prefetching */
191 tmp
= cgs_read_register(hwmgr
->device
,
193 tmp
= PHM_SET_FIELD(tmp
, CP_MEC_CNTL
, MEC_ME1_HALT
, 1);
194 tmp
= PHM_SET_FIELD(tmp
, CP_MEC_CNTL
, MEC_ME2_HALT
, 1);
195 cgs_write_register(hwmgr
->device
, mmCP_MEC_CNTL
, tmp
);
197 tmp
= cgs_read_register(hwmgr
->device
,
198 mmCP_CPC_IC_BASE_CNTL
);
200 tmp
= PHM_SET_FIELD(tmp
, CP_CPC_IC_BASE_CNTL
, VMID
, 0);
201 tmp
= PHM_SET_FIELD(tmp
, CP_CPC_IC_BASE_CNTL
, ATC
, 0);
202 tmp
= PHM_SET_FIELD(tmp
, CP_CPC_IC_BASE_CNTL
, CACHE_POLICY
, 0);
203 tmp
= PHM_SET_FIELD(tmp
, CP_CPC_IC_BASE_CNTL
, MTYPE
, 1);
204 cgs_write_register(hwmgr
->device
, mmCP_CPC_IC_BASE_CNTL
, tmp
);
206 reg_data
= lower_32_bits(info
.mc_addr
) &
207 PHM_FIELD_MASK(CP_CPC_IC_BASE_LO
, IC_BASE_LO
);
208 cgs_write_register(hwmgr
->device
, mmCP_CPC_IC_BASE_LO
, reg_data
);
210 reg_data
= upper_32_bits(info
.mc_addr
) &
211 PHM_FIELD_MASK(CP_CPC_IC_BASE_HI
, IC_BASE_HI
);
212 cgs_write_register(hwmgr
->device
, mmCP_CPC_IC_BASE_HI
, reg_data
);
217 static uint8_t smu8_translate_firmware_enum_to_arg(struct pp_hwmgr
*hwmgr
,
218 enum smu8_scratch_entry firmware_enum
)
222 switch (firmware_enum
) {
223 case SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0
:
224 ret
= UCODE_ID_SDMA0
;
226 case SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1
:
227 if (hwmgr
->chip_id
== CHIP_STONEY
)
228 ret
= UCODE_ID_SDMA0
;
230 ret
= UCODE_ID_SDMA1
;
232 case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE
:
233 ret
= UCODE_ID_CP_CE
;
235 case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP
:
236 ret
= UCODE_ID_CP_PFP
;
238 case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME
:
239 ret
= UCODE_ID_CP_ME
;
241 case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1
:
242 ret
= UCODE_ID_CP_MEC_JT1
;
244 case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2
:
245 if (hwmgr
->chip_id
== CHIP_STONEY
)
246 ret
= UCODE_ID_CP_MEC_JT1
;
248 ret
= UCODE_ID_CP_MEC_JT2
;
250 case SMU8_SCRATCH_ENTRY_UCODE_ID_GMCON_RENG
:
251 ret
= UCODE_ID_GMCON_RENG
;
253 case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G
:
254 ret
= UCODE_ID_RLC_G
;
256 case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH
:
257 ret
= UCODE_ID_RLC_SCRATCH
;
259 case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM
:
260 ret
= UCODE_ID_RLC_SRM_ARAM
;
262 case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM
:
263 ret
= UCODE_ID_RLC_SRM_DRAM
;
265 case SMU8_SCRATCH_ENTRY_UCODE_ID_DMCU_ERAM
:
266 ret
= UCODE_ID_DMCU_ERAM
;
268 case SMU8_SCRATCH_ENTRY_UCODE_ID_DMCU_IRAM
:
269 ret
= UCODE_ID_DMCU_IRAM
;
271 case SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING
:
272 ret
= TASK_ARG_INIT_MM_PWR_LOG
;
274 case SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_HALT
:
275 case SMU8_SCRATCH_ENTRY_DATA_ID_SYS_CLOCKGATING
:
276 case SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_RING_REGS
:
277 case SMU8_SCRATCH_ENTRY_DATA_ID_NONGFX_REINIT
:
278 case SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_START
:
279 case SMU8_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS
:
280 ret
= TASK_ARG_REG_MMIO
;
282 case SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE
:
283 ret
= TASK_ARG_INIT_CLK_TABLE
;
290 static enum cgs_ucode_id
smu8_convert_fw_type_to_cgs(uint32_t fw_type
)
292 enum cgs_ucode_id result
= CGS_UCODE_ID_MAXIMUM
;
296 result
= CGS_UCODE_ID_SDMA0
;
299 result
= CGS_UCODE_ID_SDMA1
;
302 result
= CGS_UCODE_ID_CP_CE
;
304 case UCODE_ID_CP_PFP
:
305 result
= CGS_UCODE_ID_CP_PFP
;
308 result
= CGS_UCODE_ID_CP_ME
;
310 case UCODE_ID_CP_MEC_JT1
:
311 result
= CGS_UCODE_ID_CP_MEC_JT1
;
313 case UCODE_ID_CP_MEC_JT2
:
314 result
= CGS_UCODE_ID_CP_MEC_JT2
;
317 result
= CGS_UCODE_ID_RLC_G
;
326 static int smu8_smu_populate_single_scratch_task(
327 struct pp_hwmgr
*hwmgr
,
328 enum smu8_scratch_entry fw_enum
,
329 uint8_t type
, bool is_last
)
332 struct smu8_smumgr
*smu8_smu
= hwmgr
->smu_backend
;
333 struct TOC
*toc
= (struct TOC
*)smu8_smu
->toc_buffer
.kaddr
;
334 struct SMU_Task
*task
= &toc
->tasks
[smu8_smu
->toc_entry_used_count
++];
337 task
->arg
= smu8_translate_firmware_enum_to_arg(hwmgr
, fw_enum
);
338 task
->next
= is_last
? END_OF_TASK_LIST
: smu8_smu
->toc_entry_used_count
;
340 for (i
= 0; i
< smu8_smu
->scratch_buffer_length
; i
++)
341 if (smu8_smu
->scratch_buffer
[i
].firmware_ID
== fw_enum
)
344 if (i
>= smu8_smu
->scratch_buffer_length
) {
345 pr_err("Invalid Firmware Type\n");
349 task
->addr
.low
= lower_32_bits(smu8_smu
->scratch_buffer
[i
].mc_addr
);
350 task
->addr
.high
= upper_32_bits(smu8_smu
->scratch_buffer
[i
].mc_addr
);
351 task
->size_bytes
= smu8_smu
->scratch_buffer
[i
].data_size
;
353 if (SMU8_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS
== fw_enum
) {
354 struct smu8_ih_meta_data
*pIHReg_restore
=
355 (struct smu8_ih_meta_data
*)smu8_smu
->scratch_buffer
[i
].kaddr
;
356 pIHReg_restore
->command
=
357 METADATA_CMD_MODE0
| METADATA_PERFORM_ON_LOAD
;
363 static int smu8_smu_populate_single_ucode_load_task(
364 struct pp_hwmgr
*hwmgr
,
365 enum smu8_scratch_entry fw_enum
,
369 struct smu8_smumgr
*smu8_smu
= hwmgr
->smu_backend
;
370 struct TOC
*toc
= (struct TOC
*)smu8_smu
->toc_buffer
.kaddr
;
371 struct SMU_Task
*task
= &toc
->tasks
[smu8_smu
->toc_entry_used_count
++];
373 task
->type
= TASK_TYPE_UCODE_LOAD
;
374 task
->arg
= smu8_translate_firmware_enum_to_arg(hwmgr
, fw_enum
);
375 task
->next
= is_last
? END_OF_TASK_LIST
: smu8_smu
->toc_entry_used_count
;
377 for (i
= 0; i
< smu8_smu
->driver_buffer_length
; i
++)
378 if (smu8_smu
->driver_buffer
[i
].firmware_ID
== fw_enum
)
381 if (i
>= smu8_smu
->driver_buffer_length
) {
382 pr_err("Invalid Firmware Type\n");
386 task
->addr
.low
= lower_32_bits(smu8_smu
->driver_buffer
[i
].mc_addr
);
387 task
->addr
.high
= upper_32_bits(smu8_smu
->driver_buffer
[i
].mc_addr
);
388 task
->size_bytes
= smu8_smu
->driver_buffer
[i
].data_size
;
393 static int smu8_smu_construct_toc_for_rlc_aram_save(struct pp_hwmgr
*hwmgr
)
395 struct smu8_smumgr
*smu8_smu
= hwmgr
->smu_backend
;
397 smu8_smu
->toc_entry_aram
= smu8_smu
->toc_entry_used_count
;
398 smu8_smu_populate_single_scratch_task(hwmgr
,
399 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM
,
400 TASK_TYPE_UCODE_SAVE
, true);
405 static int smu8_smu_initialize_toc_empty_job_list(struct pp_hwmgr
*hwmgr
)
408 struct smu8_smumgr
*smu8_smu
= hwmgr
->smu_backend
;
409 struct TOC
*toc
= (struct TOC
*)smu8_smu
->toc_buffer
.kaddr
;
411 for (i
= 0; i
< NUM_JOBLIST_ENTRIES
; i
++)
412 toc
->JobList
[i
] = (uint8_t)IGNORE_JOB
;
417 static int smu8_smu_construct_toc_for_vddgfx_enter(struct pp_hwmgr
*hwmgr
)
419 struct smu8_smumgr
*smu8_smu
= hwmgr
->smu_backend
;
420 struct TOC
*toc
= (struct TOC
*)smu8_smu
->toc_buffer
.kaddr
;
422 toc
->JobList
[JOB_GFX_SAVE
] = (uint8_t)smu8_smu
->toc_entry_used_count
;
423 smu8_smu_populate_single_scratch_task(hwmgr
,
424 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH
,
425 TASK_TYPE_UCODE_SAVE
, false);
427 smu8_smu_populate_single_scratch_task(hwmgr
,
428 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM
,
429 TASK_TYPE_UCODE_SAVE
, true);
435 static int smu8_smu_construct_toc_for_vddgfx_exit(struct pp_hwmgr
*hwmgr
)
437 struct smu8_smumgr
*smu8_smu
= hwmgr
->smu_backend
;
438 struct TOC
*toc
= (struct TOC
*)smu8_smu
->toc_buffer
.kaddr
;
440 toc
->JobList
[JOB_GFX_RESTORE
] = (uint8_t)smu8_smu
->toc_entry_used_count
;
442 smu8_smu_populate_single_ucode_load_task(hwmgr
,
443 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE
, false);
444 smu8_smu_populate_single_ucode_load_task(hwmgr
,
445 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP
, false);
446 smu8_smu_populate_single_ucode_load_task(hwmgr
,
447 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME
, false);
448 smu8_smu_populate_single_ucode_load_task(hwmgr
,
449 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1
, false);
451 if (hwmgr
->chip_id
== CHIP_STONEY
)
452 smu8_smu_populate_single_ucode_load_task(hwmgr
,
453 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1
, false);
455 smu8_smu_populate_single_ucode_load_task(hwmgr
,
456 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2
, false);
458 smu8_smu_populate_single_ucode_load_task(hwmgr
,
459 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G
, false);
461 /* populate scratch */
462 smu8_smu_populate_single_scratch_task(hwmgr
,
463 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH
,
464 TASK_TYPE_UCODE_LOAD
, false);
466 smu8_smu_populate_single_scratch_task(hwmgr
,
467 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM
,
468 TASK_TYPE_UCODE_LOAD
, false);
470 smu8_smu_populate_single_scratch_task(hwmgr
,
471 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM
,
472 TASK_TYPE_UCODE_LOAD
, true);
477 static int smu8_smu_construct_toc_for_power_profiling(struct pp_hwmgr
*hwmgr
)
479 struct smu8_smumgr
*smu8_smu
= hwmgr
->smu_backend
;
481 smu8_smu
->toc_entry_power_profiling_index
= smu8_smu
->toc_entry_used_count
;
483 smu8_smu_populate_single_scratch_task(hwmgr
,
484 SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING
,
485 TASK_TYPE_INITIALIZE
, true);
489 static int smu8_smu_construct_toc_for_bootup(struct pp_hwmgr
*hwmgr
)
491 struct smu8_smumgr
*smu8_smu
= hwmgr
->smu_backend
;
493 smu8_smu
->toc_entry_initialize_index
= smu8_smu
->toc_entry_used_count
;
495 smu8_smu_populate_single_ucode_load_task(hwmgr
,
496 SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0
, false);
497 if (hwmgr
->chip_id
!= CHIP_STONEY
)
498 smu8_smu_populate_single_ucode_load_task(hwmgr
,
499 SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1
, false);
500 smu8_smu_populate_single_ucode_load_task(hwmgr
,
501 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE
, false);
502 smu8_smu_populate_single_ucode_load_task(hwmgr
,
503 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP
, false);
504 smu8_smu_populate_single_ucode_load_task(hwmgr
,
505 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME
, false);
506 smu8_smu_populate_single_ucode_load_task(hwmgr
,
507 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1
, false);
508 if (hwmgr
->chip_id
!= CHIP_STONEY
)
509 smu8_smu_populate_single_ucode_load_task(hwmgr
,
510 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2
, false);
511 smu8_smu_populate_single_ucode_load_task(hwmgr
,
512 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G
, true);
517 static int smu8_smu_construct_toc_for_clock_table(struct pp_hwmgr
*hwmgr
)
519 struct smu8_smumgr
*smu8_smu
= hwmgr
->smu_backend
;
521 smu8_smu
->toc_entry_clock_table
= smu8_smu
->toc_entry_used_count
;
523 smu8_smu_populate_single_scratch_task(hwmgr
,
524 SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE
,
525 TASK_TYPE_INITIALIZE
, true);
530 static int smu8_smu_construct_toc(struct pp_hwmgr
*hwmgr
)
532 struct smu8_smumgr
*smu8_smu
= hwmgr
->smu_backend
;
534 smu8_smu
->toc_entry_used_count
= 0;
535 smu8_smu_initialize_toc_empty_job_list(hwmgr
);
536 smu8_smu_construct_toc_for_rlc_aram_save(hwmgr
);
537 smu8_smu_construct_toc_for_vddgfx_enter(hwmgr
);
538 smu8_smu_construct_toc_for_vddgfx_exit(hwmgr
);
539 smu8_smu_construct_toc_for_power_profiling(hwmgr
);
540 smu8_smu_construct_toc_for_bootup(hwmgr
);
541 smu8_smu_construct_toc_for_clock_table(hwmgr
);
546 static int smu8_smu_populate_firmware_entries(struct pp_hwmgr
*hwmgr
)
548 struct smu8_smumgr
*smu8_smu
= hwmgr
->smu_backend
;
549 uint32_t firmware_type
;
552 enum cgs_ucode_id ucode_id
;
553 struct cgs_firmware_info info
= {0};
555 smu8_smu
->driver_buffer_length
= 0;
557 for (i
= 0; i
< ARRAY_SIZE(firmware_list
); i
++) {
559 firmware_type
= smu8_translate_firmware_enum_to_arg(hwmgr
,
562 ucode_id
= smu8_convert_fw_type_to_cgs(firmware_type
);
564 ret
= cgs_get_firmware_info(hwmgr
->device
,
568 smu8_smu
->driver_buffer
[i
].mc_addr
= info
.mc_addr
;
570 smu8_smu
->driver_buffer
[i
].data_size
= info
.image_size
;
572 smu8_smu
->driver_buffer
[i
].firmware_ID
= firmware_list
[i
];
573 smu8_smu
->driver_buffer_length
++;
580 static int smu8_smu_populate_single_scratch_entry(
581 struct pp_hwmgr
*hwmgr
,
582 enum smu8_scratch_entry scratch_type
,
583 uint32_t ulsize_byte
,
584 struct smu8_buffer_entry
*entry
)
586 struct smu8_smumgr
*smu8_smu
= hwmgr
->smu_backend
;
587 uint32_t ulsize_aligned
= SIZE_ALIGN_32(ulsize_byte
);
589 entry
->data_size
= ulsize_byte
;
590 entry
->kaddr
= (char *) smu8_smu
->smu_buffer
.kaddr
+
591 smu8_smu
->smu_buffer_used_bytes
;
592 entry
->mc_addr
= smu8_smu
->smu_buffer
.mc_addr
+ smu8_smu
->smu_buffer_used_bytes
;
593 entry
->firmware_ID
= scratch_type
;
595 smu8_smu
->smu_buffer_used_bytes
+= ulsize_aligned
;
600 static int smu8_download_pptable_settings(struct pp_hwmgr
*hwmgr
, void **table
)
602 struct smu8_smumgr
*smu8_smu
= hwmgr
->smu_backend
;
605 for (i
= 0; i
< smu8_smu
->scratch_buffer_length
; i
++) {
606 if (smu8_smu
->scratch_buffer
[i
].firmware_ID
607 == SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE
)
611 *table
= (struct SMU8_Fusion_ClkTable
*)smu8_smu
->scratch_buffer
[i
].kaddr
;
613 smu8_send_msg_to_smc_with_parameter(hwmgr
,
614 PPSMC_MSG_SetClkTableAddrHi
,
615 upper_32_bits(smu8_smu
->scratch_buffer
[i
].mc_addr
));
617 smu8_send_msg_to_smc_with_parameter(hwmgr
,
618 PPSMC_MSG_SetClkTableAddrLo
,
619 lower_32_bits(smu8_smu
->scratch_buffer
[i
].mc_addr
));
621 smu8_send_msg_to_smc_with_parameter(hwmgr
, PPSMC_MSG_ExecuteJob
,
622 smu8_smu
->toc_entry_clock_table
);
624 smu8_send_msg_to_smc(hwmgr
, PPSMC_MSG_ClkTableXferToDram
);
629 static int smu8_upload_pptable_settings(struct pp_hwmgr
*hwmgr
)
631 struct smu8_smumgr
*smu8_smu
= hwmgr
->smu_backend
;
634 for (i
= 0; i
< smu8_smu
->scratch_buffer_length
; i
++) {
635 if (smu8_smu
->scratch_buffer
[i
].firmware_ID
636 == SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE
)
640 smu8_send_msg_to_smc_with_parameter(hwmgr
,
641 PPSMC_MSG_SetClkTableAddrHi
,
642 upper_32_bits(smu8_smu
->scratch_buffer
[i
].mc_addr
));
644 smu8_send_msg_to_smc_with_parameter(hwmgr
,
645 PPSMC_MSG_SetClkTableAddrLo
,
646 lower_32_bits(smu8_smu
->scratch_buffer
[i
].mc_addr
));
648 smu8_send_msg_to_smc_with_parameter(hwmgr
, PPSMC_MSG_ExecuteJob
,
649 smu8_smu
->toc_entry_clock_table
);
651 smu8_send_msg_to_smc(hwmgr
, PPSMC_MSG_ClkTableXferToSmu
);
656 static int smu8_request_smu_load_fw(struct pp_hwmgr
*hwmgr
)
658 struct smu8_smumgr
*smu8_smu
= hwmgr
->smu_backend
;
659 uint32_t smc_address
;
660 uint32_t fw_to_check
= 0;
663 amdgpu_ucode_init_bo(hwmgr
->adev
);
665 smu8_smu_populate_firmware_entries(hwmgr
);
667 smu8_smu_construct_toc(hwmgr
);
669 smc_address
= SMU8_FIRMWARE_HEADER_LOCATION
+
670 offsetof(struct SMU8_Firmware_Header
, UcodeLoadStatus
);
672 smu8_write_smc_sram_dword(hwmgr
, smc_address
, 0, smc_address
+4);
674 smu8_send_msg_to_smc_with_parameter(hwmgr
,
675 PPSMC_MSG_DriverDramAddrHi
,
676 upper_32_bits(smu8_smu
->toc_buffer
.mc_addr
));
678 smu8_send_msg_to_smc_with_parameter(hwmgr
,
679 PPSMC_MSG_DriverDramAddrLo
,
680 lower_32_bits(smu8_smu
->toc_buffer
.mc_addr
));
682 smu8_send_msg_to_smc(hwmgr
, PPSMC_MSG_InitJobs
);
684 smu8_send_msg_to_smc_with_parameter(hwmgr
,
685 PPSMC_MSG_ExecuteJob
,
686 smu8_smu
->toc_entry_aram
);
687 smu8_send_msg_to_smc_with_parameter(hwmgr
, PPSMC_MSG_ExecuteJob
,
688 smu8_smu
->toc_entry_power_profiling_index
);
690 smu8_send_msg_to_smc_with_parameter(hwmgr
,
691 PPSMC_MSG_ExecuteJob
,
692 smu8_smu
->toc_entry_initialize_index
);
694 fw_to_check
= UCODE_ID_RLC_G_MASK
|
695 UCODE_ID_SDMA0_MASK
|
696 UCODE_ID_SDMA1_MASK
|
697 UCODE_ID_CP_CE_MASK
|
698 UCODE_ID_CP_ME_MASK
|
699 UCODE_ID_CP_PFP_MASK
|
700 UCODE_ID_CP_MEC_JT1_MASK
|
701 UCODE_ID_CP_MEC_JT2_MASK
;
703 if (hwmgr
->chip_id
== CHIP_STONEY
)
704 fw_to_check
&= ~(UCODE_ID_SDMA1_MASK
| UCODE_ID_CP_MEC_JT2_MASK
);
706 ret
= smu8_check_fw_load_finish(hwmgr
, fw_to_check
);
708 pr_err("SMU firmware load failed\n");
712 ret
= smu8_load_mec_firmware(hwmgr
);
714 pr_err("Mec Firmware load failed\n");
721 static int smu8_start_smu(struct pp_hwmgr
*hwmgr
)
723 struct amdgpu_device
*adev
;
725 uint32_t index
= SMN_MP1_SRAM_START_ADDR
+
726 SMU8_FIRMWARE_HEADER_LOCATION
+
727 offsetof(struct SMU8_Firmware_Header
, Version
);
729 if (hwmgr
== NULL
|| hwmgr
->device
== NULL
)
734 cgs_write_register(hwmgr
->device
, mmMP0PUB_IND_INDEX
, index
);
735 hwmgr
->smu_version
= cgs_read_register(hwmgr
->device
, mmMP0PUB_IND_DATA
);
736 pr_info("smu version %02d.%02d.%02d\n",
737 ((hwmgr
->smu_version
>> 16) & 0xFF),
738 ((hwmgr
->smu_version
>> 8) & 0xFF),
739 (hwmgr
->smu_version
& 0xFF));
740 adev
->pm
.fw_version
= hwmgr
->smu_version
>> 8;
742 return smu8_request_smu_load_fw(hwmgr
);
745 static int smu8_smu_init(struct pp_hwmgr
*hwmgr
)
748 struct smu8_smumgr
*smu8_smu
;
750 smu8_smu
= kzalloc(sizeof(struct smu8_smumgr
), GFP_KERNEL
);
751 if (smu8_smu
== NULL
)
754 hwmgr
->smu_backend
= smu8_smu
;
756 smu8_smu
->toc_buffer
.data_size
= 4096;
757 smu8_smu
->smu_buffer
.data_size
=
758 ALIGN(UCODE_ID_RLC_SCRATCH_SIZE_BYTE
, 32) +
759 ALIGN(UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE
, 32) +
760 ALIGN(UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE
, 32) +
761 ALIGN(sizeof(struct SMU8_MultimediaPowerLogData
), 32) +
762 ALIGN(sizeof(struct SMU8_Fusion_ClkTable
), 32);
764 ret
= amdgpu_bo_create_kernel((struct amdgpu_device
*)hwmgr
->adev
,
765 smu8_smu
->toc_buffer
.data_size
,
767 AMDGPU_GEM_DOMAIN_VRAM
,
768 &smu8_smu
->toc_buffer
.handle
,
769 &smu8_smu
->toc_buffer
.mc_addr
,
770 &smu8_smu
->toc_buffer
.kaddr
);
774 ret
= amdgpu_bo_create_kernel((struct amdgpu_device
*)hwmgr
->adev
,
775 smu8_smu
->smu_buffer
.data_size
,
777 AMDGPU_GEM_DOMAIN_VRAM
,
778 &smu8_smu
->smu_buffer
.handle
,
779 &smu8_smu
->smu_buffer
.mc_addr
,
780 &smu8_smu
->smu_buffer
.kaddr
);
784 if (0 != smu8_smu_populate_single_scratch_entry(hwmgr
,
785 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH
,
786 UCODE_ID_RLC_SCRATCH_SIZE_BYTE
,
787 &smu8_smu
->scratch_buffer
[smu8_smu
->scratch_buffer_length
++])) {
788 pr_err("Error when Populate Firmware Entry.\n");
792 if (0 != smu8_smu_populate_single_scratch_entry(hwmgr
,
793 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM
,
794 UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE
,
795 &smu8_smu
->scratch_buffer
[smu8_smu
->scratch_buffer_length
++])) {
796 pr_err("Error when Populate Firmware Entry.\n");
799 if (0 != smu8_smu_populate_single_scratch_entry(hwmgr
,
800 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM
,
801 UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE
,
802 &smu8_smu
->scratch_buffer
[smu8_smu
->scratch_buffer_length
++])) {
803 pr_err("Error when Populate Firmware Entry.\n");
807 if (0 != smu8_smu_populate_single_scratch_entry(hwmgr
,
808 SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING
,
809 sizeof(struct SMU8_MultimediaPowerLogData
),
810 &smu8_smu
->scratch_buffer
[smu8_smu
->scratch_buffer_length
++])) {
811 pr_err("Error when Populate Firmware Entry.\n");
815 if (0 != smu8_smu_populate_single_scratch_entry(hwmgr
,
816 SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE
,
817 sizeof(struct SMU8_Fusion_ClkTable
),
818 &smu8_smu
->scratch_buffer
[smu8_smu
->scratch_buffer_length
++])) {
819 pr_err("Error when Populate Firmware Entry.\n");
826 amdgpu_bo_free_kernel(&smu8_smu
->smu_buffer
.handle
,
827 &smu8_smu
->smu_buffer
.mc_addr
,
828 &smu8_smu
->smu_buffer
.kaddr
);
830 amdgpu_bo_free_kernel(&smu8_smu
->toc_buffer
.handle
,
831 &smu8_smu
->toc_buffer
.mc_addr
,
832 &smu8_smu
->toc_buffer
.kaddr
);
838 static int smu8_smu_fini(struct pp_hwmgr
*hwmgr
)
840 struct smu8_smumgr
*smu8_smu
;
842 if (hwmgr
== NULL
|| hwmgr
->device
== NULL
)
845 smu8_smu
= hwmgr
->smu_backend
;
847 amdgpu_bo_free_kernel(&smu8_smu
->toc_buffer
.handle
,
848 &smu8_smu
->toc_buffer
.mc_addr
,
849 &smu8_smu
->toc_buffer
.kaddr
);
850 amdgpu_bo_free_kernel(&smu8_smu
->smu_buffer
.handle
,
851 &smu8_smu
->smu_buffer
.mc_addr
,
852 &smu8_smu
->smu_buffer
.kaddr
);
859 static bool smu8_dpm_check_smu_features(struct pp_hwmgr
*hwmgr
,
860 unsigned long check_feature
)
863 unsigned long features
;
865 result
= smu8_send_msg_to_smc_with_parameter(hwmgr
, PPSMC_MSG_GetFeatureStatus
, 0);
867 features
= smum_get_argument(hwmgr
);
868 if (features
& check_feature
)
875 static bool smu8_is_dpm_running(struct pp_hwmgr
*hwmgr
)
877 if (smu8_dpm_check_smu_features(hwmgr
, SMU_EnabledFeatureScoreboard_SclkDpmOn
))
882 const struct pp_smumgr_func smu8_smu_funcs
= {
884 .smu_init
= smu8_smu_init
,
885 .smu_fini
= smu8_smu_fini
,
886 .start_smu
= smu8_start_smu
,
887 .check_fw_load_finish
= smu8_check_fw_load_finish
,
888 .request_smu_load_fw
= NULL
,
889 .request_smu_load_specific_fw
= NULL
,
890 .get_argument
= smu8_get_argument
,
891 .send_msg_to_smc
= smu8_send_msg_to_smc
,
892 .send_msg_to_smc_with_parameter
= smu8_send_msg_to_smc_with_parameter
,
893 .download_pptable_settings
= smu8_download_pptable_settings
,
894 .upload_pptable_settings
= smu8_upload_pptable_settings
,
895 .is_dpm_running
= smu8_is_dpm_running
,