2 * Copyright 2016 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.
22 * Author: Huang Rui <ray.huang@amd.com>
25 #include <linux/types.h>
26 #include <linux/kernel.h>
27 #include <linux/slab.h>
28 #include <linux/gfp.h>
31 #include "iceland_smumgr.h"
33 #include "smu_ucode_xfer_vi.h"
35 #include "smu/smu_7_1_1_d.h"
36 #include "smu/smu_7_1_1_sh_mask.h"
37 #include "cgs_common.h"
39 #define ICELAND_SMC_SIZE 0x20000
40 #define BUFFER_SIZE 80000
41 #define MAX_STRING_SIZE 15
42 #define BUFFER_SIZETWO 131072 /*128 *1024*/
45 * Set the address for reading/writing the SMC SRAM space.
46 * @param smumgr the address of the powerplay hardware manager.
47 * @param smcAddress the address in the SMC RAM to access.
49 static int iceland_set_smc_sram_address(struct pp_smumgr
*smumgr
,
50 uint32_t smcAddress
, uint32_t limit
)
52 if (smumgr
== NULL
|| smumgr
->device
== NULL
)
54 PP_ASSERT_WITH_CODE((0 == (3 & smcAddress
)),
55 "SMC address must be 4 byte aligned.",
58 PP_ASSERT_WITH_CODE((limit
> (smcAddress
+ 3)),
59 "SMC address is beyond the SMC RAM area.",
62 cgs_write_register(smumgr
->device
, mmSMC_IND_INDEX_0
, smcAddress
);
63 SMUM_WRITE_FIELD(smumgr
->device
, SMC_IND_ACCESS_CNTL
, AUTO_INCREMENT_IND_0
, 0);
69 * Copy bytes from an array into the SMC RAM space.
71 * @param smumgr the address of the powerplay SMU manager.
72 * @param smcStartAddress the start address in the SMC RAM to copy bytes to.
73 * @param src the byte array to copy the bytes from.
74 * @param byteCount the number of bytes to copy.
76 int iceland_copy_bytes_to_smc(struct pp_smumgr
*smumgr
,
77 uint32_t smcStartAddress
, const uint8_t *src
,
78 uint32_t byteCount
, uint32_t limit
)
81 uint32_t data
, orig_data
;
85 if (smumgr
== NULL
|| smumgr
->device
== NULL
)
87 PP_ASSERT_WITH_CODE((0 == (3 & smcStartAddress
)),
88 "SMC address must be 4 byte aligned.",
91 PP_ASSERT_WITH_CODE((limit
> (smcStartAddress
+ byteCount
)),
92 "SMC address is beyond the SMC RAM area.",
95 addr
= smcStartAddress
;
97 while (byteCount
>= 4) {
99 * Bytes are written into the
100 * SMC address space with the MSB first
102 data
= (src
[0] << 24) + (src
[1] << 16) + (src
[2] << 8) + src
[3];
104 result
= iceland_set_smc_sram_address(smumgr
, addr
, limit
);
109 cgs_write_register(smumgr
->device
, mmSMC_IND_DATA_0
, data
);
116 if (0 != byteCount
) {
117 /* Now write odd bytes left, do a read modify write cycle */
120 result
= iceland_set_smc_sram_address(smumgr
, addr
, limit
);
124 orig_data
= cgs_read_register(smumgr
->device
,
126 extra_shift
= 8 * (4 - byteCount
);
128 while (byteCount
> 0) {
129 data
= (data
<< 8) + *src
++;
133 data
<<= extra_shift
;
134 data
|= (orig_data
& ~((~0UL) << extra_shift
));
136 result
= iceland_set_smc_sram_address(smumgr
, addr
, limit
);
140 cgs_write_register(smumgr
->device
, mmSMC_IND_DATA_0
, data
);
148 * Deassert the reset'pin' (set it to high).
150 * @param smumgr the address of the powerplay hardware manager.
152 static int iceland_start_smc(struct pp_smumgr
*smumgr
)
154 SMUM_WRITE_INDIRECT_FIELD(smumgr
->device
, CGS_IND_REG__SMC
,
155 SMC_SYSCON_RESET_CNTL
, rst_reg
, 0);
160 static void iceland_pp_reset_smc(struct pp_smumgr
*smumgr
)
162 SMUM_WRITE_INDIRECT_FIELD(smumgr
->device
, CGS_IND_REG__SMC
,
163 SMC_SYSCON_RESET_CNTL
,
167 int iceland_program_jump_on_start(struct pp_smumgr
*smumgr
)
169 static const unsigned char pData
[] = { 0xE0, 0x00, 0x80, 0x40 };
171 iceland_copy_bytes_to_smc(smumgr
, 0x0, pData
, 4, sizeof(pData
)+1);
177 * Return if the SMC is currently running.
179 * @param smumgr the address of the powerplay hardware manager.
181 bool iceland_is_smc_ram_running(struct pp_smumgr
*smumgr
)
185 val1
= SMUM_READ_INDIRECT_FIELD(smumgr
->device
, CGS_IND_REG__SMC
,
186 SMC_SYSCON_CLOCK_CNTL_0
, ck_disable
);
187 val2
= cgs_read_ind_register(smumgr
->device
, CGS_IND_REG__SMC
,
190 return ((0 == val1
) && (0x20100 <= val2
));
194 * Send a message to the SMC, and wait for its response.
196 * @param smumgr the address of the powerplay hardware manager.
197 * @param msg the message to send.
198 * @return The response that came from the SMC.
200 static int iceland_send_msg_to_smc(struct pp_smumgr
*smumgr
, uint16_t msg
)
202 if (smumgr
== NULL
|| smumgr
->device
== NULL
)
205 if (!iceland_is_smc_ram_running(smumgr
))
208 SMUM_WAIT_FIELD_UNEQUAL(smumgr
, SMC_RESP_0
, SMC_RESP
, 0);
210 1 == SMUM_READ_FIELD(smumgr
->device
, SMC_RESP_0
, SMC_RESP
),
211 "Failed to send Previous Message.",
214 cgs_write_register(smumgr
->device
, mmSMC_MESSAGE_0
, msg
);
216 SMUM_WAIT_FIELD_UNEQUAL(smumgr
, SMC_RESP_0
, SMC_RESP
, 0);
218 1 == SMUM_READ_FIELD(smumgr
->device
, SMC_RESP_0
, SMC_RESP
),
219 "Failed to send Message.",
226 * Send a message to the SMC with parameter
228 * @param smumgr: the address of the powerplay hardware manager.
229 * @param msg: the message to send.
230 * @param parameter: the parameter to send
231 * @return The response that came from the SMC.
233 static int iceland_send_msg_to_smc_with_parameter(struct pp_smumgr
*smumgr
,
234 uint16_t msg
, uint32_t parameter
)
236 if (smumgr
== NULL
|| smumgr
->device
== NULL
)
239 cgs_write_register(smumgr
->device
, mmSMC_MSG_ARG_0
, parameter
);
241 return iceland_send_msg_to_smc(smumgr
, msg
);
245 * Read a 32bit value from the SMC SRAM space.
246 * ALL PARAMETERS ARE IN HOST BYTE ORDER.
247 * @param smumgr the address of the powerplay hardware manager.
248 * @param smcAddress the address in the SMC RAM to access.
249 * @param value and output parameter for the data read from the SMC SRAM.
251 int iceland_read_smc_sram_dword(struct pp_smumgr
*smumgr
,
252 uint32_t smcAddress
, uint32_t *value
,
257 result
= iceland_set_smc_sram_address(smumgr
, smcAddress
, limit
);
262 *value
= cgs_read_register(smumgr
->device
, mmSMC_IND_DATA_0
);
268 * Write a 32bit value to the SMC SRAM space.
269 * ALL PARAMETERS ARE IN HOST BYTE ORDER.
270 * @param smumgr the address of the powerplay hardware manager.
271 * @param smcAddress the address in the SMC RAM to access.
272 * @param value to write to the SMC SRAM.
274 int iceland_write_smc_sram_dword(struct pp_smumgr
*smumgr
,
275 uint32_t smcAddress
, uint32_t value
,
280 result
= iceland_set_smc_sram_address(smumgr
, smcAddress
, limit
);
285 cgs_write_register(smumgr
->device
, mmSMC_IND_DATA_0
, value
);
290 static int iceland_smu_fini(struct pp_smumgr
*smumgr
)
292 struct iceland_smumgr
*priv
= (struct iceland_smumgr
*)(smumgr
->backend
);
294 smu_free_memory(smumgr
->device
, (void *)priv
->header_buffer
.handle
);
296 if (smumgr
->backend
!= NULL
) {
297 kfree(smumgr
->backend
);
298 smumgr
->backend
= NULL
;
301 cgs_rel_firmware(smumgr
->device
, CGS_UCODE_ID_SMU
);
305 static enum cgs_ucode_id
iceland_convert_fw_type_to_cgs(uint32_t fw_type
)
307 enum cgs_ucode_id result
= CGS_UCODE_ID_MAXIMUM
;
311 result
= CGS_UCODE_ID_SMU
;
314 result
= CGS_UCODE_ID_SDMA0
;
317 result
= CGS_UCODE_ID_SDMA1
;
320 result
= CGS_UCODE_ID_CP_CE
;
322 case UCODE_ID_CP_PFP
:
323 result
= CGS_UCODE_ID_CP_PFP
;
326 result
= CGS_UCODE_ID_CP_ME
;
328 case UCODE_ID_CP_MEC
:
329 result
= CGS_UCODE_ID_CP_MEC
;
331 case UCODE_ID_CP_MEC_JT1
:
332 result
= CGS_UCODE_ID_CP_MEC_JT1
;
334 case UCODE_ID_CP_MEC_JT2
:
335 result
= CGS_UCODE_ID_CP_MEC_JT2
;
338 result
= CGS_UCODE_ID_RLC_G
;
348 * Convert the PPIRI firmware type to SMU type mask.
349 * For MEC, we need to check all MEC related type
351 static uint16_t iceland_get_mask_for_firmware_type(uint16_t firmwareType
)
355 switch (firmwareType
) {
357 result
= UCODE_ID_SDMA0_MASK
;
360 result
= UCODE_ID_SDMA1_MASK
;
363 result
= UCODE_ID_CP_CE_MASK
;
365 case UCODE_ID_CP_PFP
:
366 result
= UCODE_ID_CP_PFP_MASK
;
369 result
= UCODE_ID_CP_ME_MASK
;
371 case UCODE_ID_CP_MEC
:
372 case UCODE_ID_CP_MEC_JT1
:
373 case UCODE_ID_CP_MEC_JT2
:
374 result
= UCODE_ID_CP_MEC_MASK
;
377 result
= UCODE_ID_RLC_G_MASK
;
387 * Check if the FW has been loaded,
388 * SMU will not return if loading has not finished.
390 static int iceland_check_fw_load_finish(struct pp_smumgr
*smumgr
, uint32_t fwType
)
392 uint16_t fwMask
= iceland_get_mask_for_firmware_type(fwType
);
394 if (0 != SMUM_WAIT_VFPF_INDIRECT_REGISTER(smumgr
, SMC_IND
,
395 SOFT_REGISTERS_TABLE_27
, fwMask
, fwMask
)) {
396 pr_err("[ powerplay ] check firmware loading failed\n");
403 /* Populate one firmware image to the data structure */
404 static int iceland_populate_single_firmware_entry(struct pp_smumgr
*smumgr
,
405 uint16_t firmware_type
,
406 struct SMU_Entry
*pentry
)
409 struct cgs_firmware_info info
= {0};
411 result
= cgs_get_firmware_info(
413 iceland_convert_fw_type_to_cgs(firmware_type
),
418 pentry
->id
= (uint16_t)firmware_type
;
419 pentry
->image_addr_high
= smu_upper_32_bits(info
.mc_addr
);
420 pentry
->image_addr_low
= smu_lower_32_bits(info
.mc_addr
);
421 pentry
->meta_data_addr_high
= 0;
422 pentry
->meta_data_addr_low
= 0;
423 pentry
->data_size_byte
= info
.image_size
;
424 pentry
->num_register_entries
= 0;
426 if (firmware_type
== UCODE_ID_RLC_G
)
437 static void iceland_pp_stop_smc_clock(struct pp_smumgr
*smumgr
)
439 SMUM_WRITE_INDIRECT_FIELD(smumgr
->device
, CGS_IND_REG__SMC
,
440 SMC_SYSCON_CLOCK_CNTL_0
,
444 static void iceland_start_smc_clock(struct pp_smumgr
*smumgr
)
446 SMUM_WRITE_INDIRECT_FIELD(smumgr
->device
, CGS_IND_REG__SMC
,
447 SMC_SYSCON_CLOCK_CNTL_0
,
451 int iceland_smu_start_smc(struct pp_smumgr
*smumgr
)
453 /* set smc instruct start point at 0x0 */
454 iceland_program_jump_on_start(smumgr
);
456 /* enable smc clock */
457 iceland_start_smc_clock(smumgr
);
459 /* de-assert reset */
460 iceland_start_smc(smumgr
);
462 SMUM_WAIT_INDIRECT_FIELD(smumgr
, SMC_IND
, FIRMWARE_FLAGS
,
463 INTERRUPTS_ENABLED
, 1);
469 * Upload the SMC firmware to the SMC microcontroller.
471 * @param smumgr the address of the powerplay hardware manager.
472 * @param pFirmware the data structure containing the various sections of the firmware.
474 int iceland_smu_upload_firmware_image(struct pp_smumgr
*smumgr
)
477 uint32_t byte_count
, val
;
479 struct cgs_firmware_info info
= {0};
481 if (smumgr
== NULL
|| smumgr
->device
== NULL
)
484 /* load SMC firmware */
485 cgs_get_firmware_info(smumgr
->device
,
486 iceland_convert_fw_type_to_cgs(UCODE_ID_SMU
), &info
);
488 if (info
.image_size
& 3) {
489 pr_err("[ powerplay ] SMC ucode is not 4 bytes aligned\n");
493 if (info
.image_size
> ICELAND_SMC_SIZE
) {
494 pr_err("[ powerplay ] SMC address is beyond the SMC RAM area\n");
498 /* wait for smc boot up */
499 SMUM_WAIT_INDIRECT_FIELD_UNEQUAL(smumgr
, SMC_IND
,
500 RCU_UC_EVENTS
, boot_seq_done
, 0);
502 /* clear firmware interrupt enable flag */
503 val
= cgs_read_ind_register(smumgr
->device
, CGS_IND_REG__SMC
,
504 ixSMC_SYSCON_MISC_CNTL
);
505 cgs_write_ind_register(smumgr
->device
, CGS_IND_REG__SMC
,
506 ixSMC_SYSCON_MISC_CNTL
, val
| 1);
509 iceland_pp_stop_smc_clock(smumgr
);
512 iceland_pp_reset_smc(smumgr
);
514 cgs_write_register(smumgr
->device
, mmSMC_IND_INDEX_0
,
515 info
.ucode_start_address
);
517 SMUM_WRITE_FIELD(smumgr
->device
, SMC_IND_ACCESS_CNTL
,
518 AUTO_INCREMENT_IND_0
, 1);
520 byte_count
= info
.image_size
;
521 src
= (const uint8_t *)info
.kptr
;
523 while (byte_count
>= 4) {
524 data
= (src
[0] << 24) + (src
[1] << 16) + (src
[2] << 8) + src
[3];
525 cgs_write_register(smumgr
->device
, mmSMC_IND_DATA_0
, data
);
530 SMUM_WRITE_FIELD(smumgr
->device
, SMC_IND_ACCESS_CNTL
,
531 AUTO_INCREMENT_IND_0
, 0);
536 static int iceland_request_smu_reload_fw(struct pp_smumgr
*smumgr
)
538 struct iceland_smumgr
*iceland_smu
=
539 (struct iceland_smumgr
*)(smumgr
->backend
);
542 struct SMU_DRAMData_TOC
*toc
;
544 toc
= (struct SMU_DRAMData_TOC
*)iceland_smu
->pHeader
;
545 toc
->num_entries
= 0;
546 toc
->structure_version
= 1;
549 0 == iceland_populate_single_firmware_entry(smumgr
,
551 &toc
->entry
[toc
->num_entries
++]),
552 "Failed to Get Firmware Entry.\n",
555 0 == iceland_populate_single_firmware_entry(smumgr
,
557 &toc
->entry
[toc
->num_entries
++]),
558 "Failed to Get Firmware Entry.\n",
561 0 == iceland_populate_single_firmware_entry
562 (smumgr
, UCODE_ID_CP_PFP
, &toc
->entry
[toc
->num_entries
++]),
563 "Failed to Get Firmware Entry.\n", return -1);
565 0 == iceland_populate_single_firmware_entry
566 (smumgr
, UCODE_ID_CP_ME
, &toc
->entry
[toc
->num_entries
++]),
567 "Failed to Get Firmware Entry.\n", return -1);
569 0 == iceland_populate_single_firmware_entry
570 (smumgr
, UCODE_ID_CP_MEC
, &toc
->entry
[toc
->num_entries
++]),
571 "Failed to Get Firmware Entry.\n", return -1);
573 0 == iceland_populate_single_firmware_entry
574 (smumgr
, UCODE_ID_CP_MEC_JT1
, &toc
->entry
[toc
->num_entries
++]),
575 "Failed to Get Firmware Entry.\n", return -1);
577 0 == iceland_populate_single_firmware_entry
578 (smumgr
, UCODE_ID_CP_MEC_JT2
, &toc
->entry
[toc
->num_entries
++]),
579 "Failed to Get Firmware Entry.\n", return -1);
581 0 == iceland_populate_single_firmware_entry
582 (smumgr
, UCODE_ID_SDMA0
, &toc
->entry
[toc
->num_entries
++]),
583 "Failed to Get Firmware Entry.\n", return -1);
585 0 == iceland_populate_single_firmware_entry
586 (smumgr
, UCODE_ID_SDMA1
, &toc
->entry
[toc
->num_entries
++]),
587 "Failed to Get Firmware Entry.\n", return -1);
589 if (!iceland_is_smc_ram_running(smumgr
)) {
590 result
= iceland_smu_upload_firmware_image(smumgr
);
594 result
= iceland_smu_start_smc(smumgr
);
599 iceland_send_msg_to_smc_with_parameter(smumgr
,
600 PPSMC_MSG_DRV_DRAM_ADDR_HI
,
601 iceland_smu
->header_buffer
.mc_addr_high
);
603 iceland_send_msg_to_smc_with_parameter(smumgr
,
604 PPSMC_MSG_DRV_DRAM_ADDR_LO
,
605 iceland_smu
->header_buffer
.mc_addr_low
);
607 fw_to_load
= UCODE_ID_RLC_G_MASK
608 + UCODE_ID_SDMA0_MASK
609 + UCODE_ID_SDMA1_MASK
610 + UCODE_ID_CP_CE_MASK
611 + UCODE_ID_CP_ME_MASK
612 + UCODE_ID_CP_PFP_MASK
613 + UCODE_ID_CP_MEC_MASK
614 + UCODE_ID_CP_MEC_JT1_MASK
615 + UCODE_ID_CP_MEC_JT2_MASK
;
618 0 == iceland_send_msg_to_smc_with_parameter(
619 smumgr
, PPSMC_MSG_LoadUcodes
, fw_to_load
),
620 "Fail to Request SMU Load uCode", return 0);
625 static int iceland_request_smu_load_specific_fw(struct pp_smumgr
*smumgr
,
626 uint32_t firmwareType
)
631 static int iceland_start_smu(struct pp_smumgr
*smumgr
)
635 result
= iceland_smu_upload_firmware_image(smumgr
);
639 result
= iceland_smu_start_smc(smumgr
);
643 result
= iceland_request_smu_reload_fw(smumgr
);
649 * Write a 32bit value to the SMC SRAM space.
650 * ALL PARAMETERS ARE IN HOST BYTE ORDER.
651 * @param smumgr the address of the powerplay hardware manager.
652 * @param smcAddress the address in the SMC RAM to access.
653 * @param value to write to the SMC SRAM.
655 static int iceland_smu_init(struct pp_smumgr
*smumgr
)
657 struct iceland_smumgr
*iceland_smu
;
658 uint64_t mc_addr
= 0;
660 /* Allocate memory for backend private data */
661 iceland_smu
= (struct iceland_smumgr
*)(smumgr
->backend
);
662 iceland_smu
->header_buffer
.data_size
=
663 ((sizeof(struct SMU_DRAMData_TOC
) / 4096) + 1) * 4096;
665 smu_allocate_memory(smumgr
->device
,
666 iceland_smu
->header_buffer
.data_size
,
667 CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB
,
670 &iceland_smu
->header_buffer
.kaddr
,
671 &iceland_smu
->header_buffer
.handle
);
673 iceland_smu
->pHeader
= iceland_smu
->header_buffer
.kaddr
;
674 iceland_smu
->header_buffer
.mc_addr_high
= smu_upper_32_bits(mc_addr
);
675 iceland_smu
->header_buffer
.mc_addr_low
= smu_lower_32_bits(mc_addr
);
677 PP_ASSERT_WITH_CODE((NULL
!= iceland_smu
->pHeader
),
679 kfree(smumgr
->backend
);
680 cgs_free_gpu_mem(smumgr
->device
,
681 (cgs_handle_t
)iceland_smu
->header_buffer
.handle
);
687 static const struct pp_smumgr_func iceland_smu_funcs
= {
688 .smu_init
= &iceland_smu_init
,
689 .smu_fini
= &iceland_smu_fini
,
690 .start_smu
= &iceland_start_smu
,
691 .check_fw_load_finish
= &iceland_check_fw_load_finish
,
692 .request_smu_load_fw
= &iceland_request_smu_reload_fw
,
693 .request_smu_load_specific_fw
= &iceland_request_smu_load_specific_fw
,
694 .send_msg_to_smc
= &iceland_send_msg_to_smc
,
695 .send_msg_to_smc_with_parameter
= &iceland_send_msg_to_smc_with_parameter
,
696 .download_pptable_settings
= NULL
,
697 .upload_pptable_settings
= NULL
,
700 int iceland_smum_init(struct pp_smumgr
*smumgr
)
702 struct iceland_smumgr
*iceland_smu
= NULL
;
704 iceland_smu
= kzalloc(sizeof(struct iceland_smumgr
), GFP_KERNEL
);
706 if (iceland_smu
== NULL
)
709 smumgr
->backend
= iceland_smu
;
710 smumgr
->smumgr_funcs
= &iceland_smu_funcs
;