2018-05-11 14:54:50 +08:00
/*
* Copyright 2018 Advanced Micro Devices , Inc .
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the " Software " ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sublicense ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL
* THE COPYRIGHT HOLDER ( S ) OR AUTHOR ( S ) BE LIABLE FOR ANY CLAIM , DAMAGES OR
* OTHER LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE ,
* ARISING FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE .
*/
# include <linux/firmware.h>
# include "amdgpu.h"
# include "amdgpu_psp.h"
# include "amdgpu_ucode.h"
# include "soc15_common.h"
# include "psp_v11_0.h"
# include "mp/mp_11_0_offset.h"
# include "mp/mp_11_0_sh_mask.h"
# include "gc/gc_9_0_offset.h"
# include "sdma0/sdma0_4_0_offset.h"
# include "nbio/nbio_7_4_offset.h"
MODULE_FIRMWARE ( " amdgpu/vega20_sos.bin " ) ;
2018-10-11 21:48:00 +08:00
MODULE_FIRMWARE ( " amdgpu/vega20_ta.bin " ) ;
2018-05-11 14:54:50 +08:00
/* address block */
# define smnMP1_FIRMWARE_FLAGS 0x3010024
static int
psp_v11_0_get_fw_type ( struct amdgpu_firmware_info * ucode , enum psp_gfx_fw_type * type )
{
switch ( ucode - > ucode_id ) {
case AMDGPU_UCODE_ID_SDMA0 :
* type = GFX_FW_TYPE_SDMA0 ;
break ;
case AMDGPU_UCODE_ID_SDMA1 :
* type = GFX_FW_TYPE_SDMA1 ;
break ;
case AMDGPU_UCODE_ID_CP_CE :
* type = GFX_FW_TYPE_CP_CE ;
break ;
case AMDGPU_UCODE_ID_CP_PFP :
* type = GFX_FW_TYPE_CP_PFP ;
break ;
case AMDGPU_UCODE_ID_CP_ME :
* type = GFX_FW_TYPE_CP_ME ;
break ;
case AMDGPU_UCODE_ID_CP_MEC1 :
* type = GFX_FW_TYPE_CP_MEC ;
break ;
case AMDGPU_UCODE_ID_CP_MEC1_JT :
* type = GFX_FW_TYPE_CP_MEC_ME1 ;
break ;
case AMDGPU_UCODE_ID_CP_MEC2 :
* type = GFX_FW_TYPE_CP_MEC ;
break ;
case AMDGPU_UCODE_ID_CP_MEC2_JT :
* type = GFX_FW_TYPE_CP_MEC_ME2 ;
break ;
case AMDGPU_UCODE_ID_RLC_G :
* type = GFX_FW_TYPE_RLC_G ;
break ;
case AMDGPU_UCODE_ID_SMC :
* type = GFX_FW_TYPE_SMU ;
break ;
case AMDGPU_UCODE_ID_UVD :
* type = GFX_FW_TYPE_UVD ;
break ;
case AMDGPU_UCODE_ID_VCE :
* type = GFX_FW_TYPE_VCE ;
break ;
2018-08-14 14:53:52 -04:00
case AMDGPU_UCODE_ID_UVD1 :
* type = GFX_FW_TYPE_UVD1 ;
break ;
2018-05-11 14:54:50 +08:00
case AMDGPU_UCODE_ID_MAXIMUM :
default :
return - EINVAL ;
}
return 0 ;
}
static int psp_v11_0_init_microcode ( struct psp_context * psp )
{
struct amdgpu_device * adev = psp - > adev ;
const char * chip_name ;
char fw_name [ 30 ] ;
int err = 0 ;
2018-10-11 21:48:00 +08:00
const struct psp_firmware_header_v1_0 * sos_hdr ;
const struct ta_firmware_header_v1_0 * ta_hdr ;
2018-05-11 14:54:50 +08:00
DRM_DEBUG ( " \n " ) ;
switch ( adev - > asic_type ) {
case CHIP_VEGA20 :
chip_name = " vega20 " ;
break ;
default :
BUG ( ) ;
}
snprintf ( fw_name , sizeof ( fw_name ) , " amdgpu/%s_sos.bin " , chip_name ) ;
err = request_firmware ( & adev - > psp . sos_fw , fw_name , adev - > dev ) ;
if ( err )
goto out ;
err = amdgpu_ucode_validate ( adev - > psp . sos_fw ) ;
if ( err )
goto out ;
2018-10-11 21:48:00 +08:00
sos_hdr = ( const struct psp_firmware_header_v1_0 * ) adev - > psp . sos_fw - > data ;
adev - > psp . sos_fw_version = le32_to_cpu ( sos_hdr - > header . ucode_version ) ;
adev - > psp . sos_feature_version = le32_to_cpu ( sos_hdr - > ucode_feature_version ) ;
adev - > psp . sos_bin_size = le32_to_cpu ( sos_hdr - > sos_size_bytes ) ;
adev - > psp . sys_bin_size = le32_to_cpu ( sos_hdr - > header . ucode_size_bytes ) -
le32_to_cpu ( sos_hdr - > sos_size_bytes ) ;
adev - > psp . sys_start_addr = ( uint8_t * ) sos_hdr +
le32_to_cpu ( sos_hdr - > header . ucode_array_offset_bytes ) ;
2018-05-11 14:54:50 +08:00
adev - > psp . sos_start_addr = ( uint8_t * ) adev - > psp . sys_start_addr +
2018-10-11 21:48:00 +08:00
le32_to_cpu ( sos_hdr - > sos_offset_bytes ) ;
snprintf ( fw_name , sizeof ( fw_name ) , " amdgpu/%s_ta.bin " , chip_name ) ;
err = request_firmware ( & adev - > psp . ta_fw , fw_name , adev - > dev ) ;
if ( err )
goto out ;
err = amdgpu_ucode_validate ( adev - > psp . ta_fw ) ;
if ( err )
goto out ;
ta_hdr = ( const struct ta_firmware_header_v1_0 * ) adev - > psp . ta_fw - > data ;
adev - > psp . ta_xgmi_ucode_version = le32_to_cpu ( ta_hdr - > ta_xgmi_ucode_version ) ;
adev - > psp . ta_xgmi_ucode_size = le32_to_cpu ( ta_hdr - > ta_xgmi_size_bytes ) ;
adev - > psp . ta_xgmi_start_addr = ( uint8_t * ) ta_hdr +
le32_to_cpu ( ta_hdr - > header . ucode_array_offset_bytes ) ;
2018-05-11 14:54:50 +08:00
return 0 ;
out :
if ( err ) {
dev_err ( adev - > dev ,
" psp v11.0: Failed to load firmware \" %s \" \n " ,
fw_name ) ;
release_firmware ( adev - > psp . sos_fw ) ;
adev - > psp . sos_fw = NULL ;
}
return err ;
}
static int psp_v11_0_bootloader_load_sysdrv ( struct psp_context * psp )
{
int ret ;
uint32_t psp_gfxdrv_command_reg = 0 ;
struct amdgpu_device * adev = psp - > adev ;
uint32_t sol_reg ;
/* Check sOS sign of life register to confirm sys driver and sOS
* are already been loaded .
*/
sol_reg = RREG32_SOC15 ( MP0 , 0 , mmMP0_SMN_C2PMSG_81 ) ;
if ( sol_reg )
return 0 ;
/* Wait for bootloader to signify that is ready having bit 31 of C2PMSG_35 set to 1 */
ret = psp_wait_for ( psp , SOC15_REG_OFFSET ( MP0 , 0 , mmMP0_SMN_C2PMSG_35 ) ,
0x80000000 , 0x80000000 , false ) ;
if ( ret )
return ret ;
memset ( psp - > fw_pri_buf , 0 , PSP_1_MEG ) ;
/* Copy PSP System Driver binary to memory */
memcpy ( psp - > fw_pri_buf , psp - > sys_start_addr , psp - > sys_bin_size ) ;
2018-10-16 18:47:54 -04:00
/* Provide the sys driver to bootloader */
2018-05-11 14:54:50 +08:00
WREG32_SOC15 ( MP0 , 0 , mmMP0_SMN_C2PMSG_36 ,
( uint32_t ) ( psp - > fw_pri_mc_addr > > 20 ) ) ;
psp_gfxdrv_command_reg = 1 < < 16 ;
WREG32_SOC15 ( MP0 , 0 , mmMP0_SMN_C2PMSG_35 ,
psp_gfxdrv_command_reg ) ;
/* there might be handshake issue with hardware which needs delay */
mdelay ( 20 ) ;
ret = psp_wait_for ( psp , SOC15_REG_OFFSET ( MP0 , 0 , mmMP0_SMN_C2PMSG_35 ) ,
0x80000000 , 0x80000000 , false ) ;
return ret ;
}
static int psp_v11_0_bootloader_load_sos ( struct psp_context * psp )
{
int ret ;
unsigned int psp_gfxdrv_command_reg = 0 ;
struct amdgpu_device * adev = psp - > adev ;
uint32_t sol_reg ;
/* Check sOS sign of life register to confirm sys driver and sOS
* are already been loaded .
*/
sol_reg = RREG32_SOC15 ( MP0 , 0 , mmMP0_SMN_C2PMSG_81 ) ;
if ( sol_reg )
return 0 ;
/* Wait for bootloader to signify that is ready having bit 31 of C2PMSG_35 set to 1 */
ret = psp_wait_for ( psp , SOC15_REG_OFFSET ( MP0 , 0 , mmMP0_SMN_C2PMSG_35 ) ,
0x80000000 , 0x80000000 , false ) ;
if ( ret )
return ret ;
memset ( psp - > fw_pri_buf , 0 , PSP_1_MEG ) ;
/* Copy Secure OS binary to PSP memory */
memcpy ( psp - > fw_pri_buf , psp - > sos_start_addr , psp - > sos_bin_size ) ;
2018-10-16 18:47:54 -04:00
/* Provide the PSP secure OS to bootloader */
2018-05-11 14:54:50 +08:00
WREG32_SOC15 ( MP0 , 0 , mmMP0_SMN_C2PMSG_36 ,
( uint32_t ) ( psp - > fw_pri_mc_addr > > 20 ) ) ;
psp_gfxdrv_command_reg = 2 < < 16 ;
WREG32_SOC15 ( MP0 , 0 , mmMP0_SMN_C2PMSG_35 ,
psp_gfxdrv_command_reg ) ;
/* there might be handshake issue with hardware which needs delay */
mdelay ( 20 ) ;
ret = psp_wait_for ( psp , SOC15_REG_OFFSET ( MP0 , 0 , mmMP0_SMN_C2PMSG_81 ) ,
RREG32_SOC15 ( MP0 , 0 , mmMP0_SMN_C2PMSG_81 ) ,
0 , true ) ;
return ret ;
}
static int psp_v11_0_prep_cmd_buf ( struct amdgpu_firmware_info * ucode ,
struct psp_gfx_cmd_resp * cmd )
{
int ret ;
uint64_t fw_mem_mc_addr = ucode - > mc_addr ;
memset ( cmd , 0 , sizeof ( struct psp_gfx_cmd_resp ) ) ;
cmd - > cmd_id = GFX_CMD_ID_LOAD_IP_FW ;
cmd - > cmd . cmd_load_ip_fw . fw_phy_addr_lo = lower_32_bits ( fw_mem_mc_addr ) ;
cmd - > cmd . cmd_load_ip_fw . fw_phy_addr_hi = upper_32_bits ( fw_mem_mc_addr ) ;
cmd - > cmd . cmd_load_ip_fw . fw_size = ucode - > ucode_size ;
ret = psp_v11_0_get_fw_type ( ucode , & cmd - > cmd . cmd_load_ip_fw . fw_type ) ;
if ( ret )
DRM_ERROR ( " Unknown firmware type \n " ) ;
return ret ;
}
static int psp_v11_0_ring_init ( struct psp_context * psp ,
enum psp_ring_type ring_type )
{
int ret = 0 ;
struct psp_ring * ring ;
struct amdgpu_device * adev = psp - > adev ;
ring = & psp - > km_ring ;
ring - > ring_type = ring_type ;
/* allocate 4k Page of Local Frame Buffer memory for ring */
ring - > ring_size = 0x1000 ;
ret = amdgpu_bo_create_kernel ( adev , ring - > ring_size , PAGE_SIZE ,
AMDGPU_GEM_DOMAIN_VRAM ,
& adev - > firmware . rbuf ,
& ring - > ring_mem_mc_addr ,
( void * * ) & ring - > ring_mem ) ;
if ( ret ) {
ring - > ring_size = 0 ;
return ret ;
}
return 0 ;
}
static int psp_v11_0_ring_create ( struct psp_context * psp ,
enum psp_ring_type ring_type )
{
int ret = 0 ;
unsigned int psp_ring_reg = 0 ;
struct psp_ring * ring = & psp - > km_ring ;
struct amdgpu_device * adev = psp - > adev ;
/* Write low address of the ring to C2PMSG_69 */
psp_ring_reg = lower_32_bits ( ring - > ring_mem_mc_addr ) ;
WREG32_SOC15 ( MP0 , 0 , mmMP0_SMN_C2PMSG_69 , psp_ring_reg ) ;
/* Write high address of the ring to C2PMSG_70 */
psp_ring_reg = upper_32_bits ( ring - > ring_mem_mc_addr ) ;
WREG32_SOC15 ( MP0 , 0 , mmMP0_SMN_C2PMSG_70 , psp_ring_reg ) ;
/* Write size of ring to C2PMSG_71 */
psp_ring_reg = ring - > ring_size ;
WREG32_SOC15 ( MP0 , 0 , mmMP0_SMN_C2PMSG_71 , psp_ring_reg ) ;
/* Write the ring initialization command to C2PMSG_64 */
psp_ring_reg = ring_type ;
psp_ring_reg = psp_ring_reg < < 16 ;
WREG32_SOC15 ( MP0 , 0 , mmMP0_SMN_C2PMSG_64 , psp_ring_reg ) ;
/* there might be handshake issue with hardware which needs delay */
mdelay ( 20 ) ;
/* Wait for response flag (bit 31) in C2PMSG_64 */
ret = psp_wait_for ( psp , SOC15_REG_OFFSET ( MP0 , 0 , mmMP0_SMN_C2PMSG_64 ) ,
0x80000000 , 0x8000FFFF , false ) ;
return ret ;
}
static int psp_v11_0_ring_stop ( struct psp_context * psp ,
enum psp_ring_type ring_type )
{
int ret = 0 ;
struct amdgpu_device * adev = psp - > adev ;
/* Write the ring destroy command to C2PMSG_64 */
WREG32_SOC15 ( MP0 , 0 , mmMP0_SMN_C2PMSG_64 , GFX_CTRL_CMD_ID_DESTROY_RINGS ) ;
/* there might be handshake issue with hardware which needs delay */
mdelay ( 20 ) ;
/* Wait for response flag (bit 31) in C2PMSG_64 */
ret = psp_wait_for ( psp , SOC15_REG_OFFSET ( MP0 , 0 , mmMP0_SMN_C2PMSG_64 ) ,
0x80000000 , 0x80000000 , false ) ;
return ret ;
}
static int psp_v11_0_ring_destroy ( struct psp_context * psp ,
enum psp_ring_type ring_type )
{
int ret = 0 ;
struct psp_ring * ring = & psp - > km_ring ;
struct amdgpu_device * adev = psp - > adev ;
ret = psp_v11_0_ring_stop ( psp , ring_type ) ;
if ( ret )
DRM_ERROR ( " Fail to stop psp ring \n " ) ;
amdgpu_bo_free_kernel ( & adev - > firmware . rbuf ,
& ring - > ring_mem_mc_addr ,
( void * * ) & ring - > ring_mem ) ;
return ret ;
}
static int psp_v11_0_cmd_submit ( struct psp_context * psp ,
struct amdgpu_firmware_info * ucode ,
uint64_t cmd_buf_mc_addr , uint64_t fence_mc_addr ,
int index )
{
unsigned int psp_write_ptr_reg = 0 ;
struct psp_gfx_rb_frame * write_frame = psp - > km_ring . ring_mem ;
struct psp_ring * ring = & psp - > km_ring ;
struct psp_gfx_rb_frame * ring_buffer_start = ring - > ring_mem ;
struct psp_gfx_rb_frame * ring_buffer_end = ring_buffer_start +
ring - > ring_size / sizeof ( struct psp_gfx_rb_frame ) - 1 ;
struct amdgpu_device * adev = psp - > adev ;
uint32_t ring_size_dw = ring - > ring_size / 4 ;
uint32_t rb_frame_size_dw = sizeof ( struct psp_gfx_rb_frame ) / 4 ;
/* KM (GPCOM) prepare write pointer */
psp_write_ptr_reg = RREG32_SOC15 ( MP0 , 0 , mmMP0_SMN_C2PMSG_67 ) ;
/* Update KM RB frame pointer to new frame */
/* write_frame ptr increments by size of rb_frame in bytes */
/* psp_write_ptr_reg increments by size of rb_frame in DWORDs */
if ( ( psp_write_ptr_reg % ring_size_dw ) = = 0 )
write_frame = ring_buffer_start ;
else
write_frame = ring_buffer_start + ( psp_write_ptr_reg / rb_frame_size_dw ) ;
/* Check invalid write_frame ptr address */
if ( ( write_frame < ring_buffer_start ) | | ( ring_buffer_end < write_frame ) ) {
DRM_ERROR ( " ring_buffer_start = %p; ring_buffer_end = %p; write_frame = %p \n " ,
ring_buffer_start , ring_buffer_end , write_frame ) ;
DRM_ERROR ( " write_frame is pointing to address out of bounds \n " ) ;
return - EINVAL ;
}
/* Initialize KM RB frame */
memset ( write_frame , 0 , sizeof ( struct psp_gfx_rb_frame ) ) ;
/* Update KM RB frame */
write_frame - > cmd_buf_addr_hi = upper_32_bits ( cmd_buf_mc_addr ) ;
write_frame - > cmd_buf_addr_lo = lower_32_bits ( cmd_buf_mc_addr ) ;
write_frame - > fence_addr_hi = upper_32_bits ( fence_mc_addr ) ;
write_frame - > fence_addr_lo = lower_32_bits ( fence_mc_addr ) ;
write_frame - > fence_value = index ;
/* Update the write Pointer in DWORDs */
psp_write_ptr_reg = ( psp_write_ptr_reg + rb_frame_size_dw ) % ring_size_dw ;
WREG32_SOC15 ( MP0 , 0 , mmMP0_SMN_C2PMSG_67 , psp_write_ptr_reg ) ;
return 0 ;
}
static int
psp_v11_0_sram_map ( struct amdgpu_device * adev ,
unsigned int * sram_offset , unsigned int * sram_addr_reg_offset ,
unsigned int * sram_data_reg_offset ,
enum AMDGPU_UCODE_ID ucode_id )
{
int ret = 0 ;
switch ( ucode_id ) {
/* TODO: needs to confirm */
#if 0
case AMDGPU_UCODE_ID_SMC :
* sram_offset = 0 ;
* sram_addr_reg_offset = 0 ;
* sram_data_reg_offset = 0 ;
break ;
# endif
case AMDGPU_UCODE_ID_CP_CE :
* sram_offset = 0x0 ;
* sram_addr_reg_offset = SOC15_REG_OFFSET ( GC , 0 , mmCP_CE_UCODE_ADDR ) ;
* sram_data_reg_offset = SOC15_REG_OFFSET ( GC , 0 , mmCP_CE_UCODE_DATA ) ;
break ;
case AMDGPU_UCODE_ID_CP_PFP :
* sram_offset = 0x0 ;
* sram_addr_reg_offset = SOC15_REG_OFFSET ( GC , 0 , mmCP_PFP_UCODE_ADDR ) ;
* sram_data_reg_offset = SOC15_REG_OFFSET ( GC , 0 , mmCP_PFP_UCODE_DATA ) ;
break ;
case AMDGPU_UCODE_ID_CP_ME :
* sram_offset = 0x0 ;
* sram_addr_reg_offset = SOC15_REG_OFFSET ( GC , 0 , mmCP_HYP_ME_UCODE_ADDR ) ;
* sram_data_reg_offset = SOC15_REG_OFFSET ( GC , 0 , mmCP_HYP_ME_UCODE_DATA ) ;
break ;
case AMDGPU_UCODE_ID_CP_MEC1 :
* sram_offset = 0x10000 ;
* sram_addr_reg_offset = SOC15_REG_OFFSET ( GC , 0 , mmCP_MEC_ME1_UCODE_ADDR ) ;
* sram_data_reg_offset = SOC15_REG_OFFSET ( GC , 0 , mmCP_MEC_ME1_UCODE_DATA ) ;
break ;
case AMDGPU_UCODE_ID_CP_MEC2 :
* sram_offset = 0x10000 ;
* sram_addr_reg_offset = SOC15_REG_OFFSET ( GC , 0 , mmCP_HYP_MEC2_UCODE_ADDR ) ;
* sram_data_reg_offset = SOC15_REG_OFFSET ( GC , 0 , mmCP_HYP_MEC2_UCODE_DATA ) ;
break ;
case AMDGPU_UCODE_ID_RLC_G :
* sram_offset = 0x2000 ;
* sram_addr_reg_offset = SOC15_REG_OFFSET ( GC , 0 , mmRLC_GPM_UCODE_ADDR ) ;
* sram_data_reg_offset = SOC15_REG_OFFSET ( GC , 0 , mmRLC_GPM_UCODE_DATA ) ;
break ;
case AMDGPU_UCODE_ID_SDMA0 :
* sram_offset = 0x0 ;
* sram_addr_reg_offset = SOC15_REG_OFFSET ( SDMA0 , 0 , mmSDMA0_UCODE_ADDR ) ;
* sram_data_reg_offset = SOC15_REG_OFFSET ( SDMA0 , 0 , mmSDMA0_UCODE_DATA ) ;
break ;
/* TODO: needs to confirm */
#if 0
case AMDGPU_UCODE_ID_SDMA1 :
* sram_offset = ;
* sram_addr_reg_offset = ;
break ;
case AMDGPU_UCODE_ID_UVD :
* sram_offset = ;
* sram_addr_reg_offset = ;
break ;
case AMDGPU_UCODE_ID_VCE :
* sram_offset = ;
* sram_addr_reg_offset = ;
break ;
# endif
case AMDGPU_UCODE_ID_MAXIMUM :
default :
ret = - EINVAL ;
break ;
}
return ret ;
}
static bool psp_v11_0_compare_sram_data ( struct psp_context * psp ,
struct amdgpu_firmware_info * ucode ,
enum AMDGPU_UCODE_ID ucode_type )
{
int err = 0 ;
unsigned int fw_sram_reg_val = 0 ;
unsigned int fw_sram_addr_reg_offset = 0 ;
unsigned int fw_sram_data_reg_offset = 0 ;
unsigned int ucode_size ;
uint32_t * ucode_mem = NULL ;
struct amdgpu_device * adev = psp - > adev ;
err = psp_v11_0_sram_map ( adev , & fw_sram_reg_val , & fw_sram_addr_reg_offset ,
& fw_sram_data_reg_offset , ucode_type ) ;
if ( err )
return false ;
WREG32 ( fw_sram_addr_reg_offset , fw_sram_reg_val ) ;
ucode_size = ucode - > ucode_size ;
ucode_mem = ( uint32_t * ) ucode - > kaddr ;
while ( ucode_size ) {
fw_sram_reg_val = RREG32 ( fw_sram_data_reg_offset ) ;
if ( * ucode_mem ! = fw_sram_reg_val )
return false ;
ucode_mem + + ;
/* 4 bytes */
ucode_size - = 4 ;
}
return true ;
}
static int psp_v11_0_mode1_reset ( struct psp_context * psp )
{
int ret ;
uint32_t offset ;
struct amdgpu_device * adev = psp - > adev ;
offset = SOC15_REG_OFFSET ( MP0 , 0 , mmMP0_SMN_C2PMSG_64 ) ;
ret = psp_wait_for ( psp , offset , 0x80000000 , 0x8000FFFF , false ) ;
if ( ret ) {
DRM_INFO ( " psp is not working correctly before mode1 reset! \n " ) ;
return - EINVAL ;
}
/*send the mode 1 reset command*/
WREG32 ( offset , GFX_CTRL_CMD_ID_MODE1_RST ) ;
mdelay ( 1000 ) ;
offset = SOC15_REG_OFFSET ( MP0 , 0 , mmMP0_SMN_C2PMSG_33 ) ;
ret = psp_wait_for ( psp , offset , 0x80000000 , 0x80000000 , false ) ;
if ( ret ) {
DRM_INFO ( " psp mode 1 reset failed! \n " ) ;
return - EINVAL ;
}
DRM_INFO ( " psp mode1 reset succeed \n " ) ;
return 0 ;
}
2018-08-14 13:30:00 -04:00
/* TODO: Fill in follow functions once PSP firmware interface for XGMI is ready.
* For now , return success and hack the hive_id so high level code can
* start testing
*/
static int psp_v11_0_xgmi_get_topology_info ( struct psp_context * psp ,
int number_devices , struct psp_xgmi_topology_info * topology )
{
2018-09-29 22:30:44 +08:00
struct ta_xgmi_shared_memory * xgmi_cmd ;
struct ta_xgmi_cmd_get_topology_info_input * topology_info_input ;
struct ta_xgmi_cmd_get_topology_info_output * topology_info_output ;
int i ;
int ret ;
if ( ! topology | | topology - > num_nodes > TA_XGMI__MAX_CONNECTED_NODES )
return - EINVAL ;
xgmi_cmd = ( struct ta_xgmi_shared_memory * ) psp - > xgmi_context . xgmi_shared_buf ;
memset ( xgmi_cmd , 0 , sizeof ( struct ta_xgmi_shared_memory ) ) ;
/* Fill in the shared memory with topology information as input */
topology_info_input = & xgmi_cmd - > xgmi_in_message . get_topology_info ;
xgmi_cmd - > cmd_id = TA_COMMAND_XGMI__GET_GET_TOPOLOGY_INFO ;
topology_info_input - > num_nodes = number_devices ;
for ( i = 0 ; i < topology_info_input - > num_nodes ; i + + ) {
topology_info_input - > nodes [ i ] . node_id = topology - > nodes [ i ] . node_id ;
topology_info_input - > nodes [ i ] . num_hops = topology - > nodes [ i ] . num_hops ;
topology_info_input - > nodes [ i ] . is_sharing_enabled = topology - > nodes [ i ] . is_sharing_enabled ;
topology_info_input - > nodes [ i ] . sdma_engine = topology - > nodes [ i ] . sdma_engine ;
}
/* Invoke xgmi ta to get the topology information */
ret = psp_xgmi_invoke ( psp , TA_COMMAND_XGMI__GET_GET_TOPOLOGY_INFO ) ;
if ( ret )
return ret ;
/* Read the output topology information from the shared memory */
topology_info_output = & xgmi_cmd - > xgmi_out_message . get_topology_info ;
topology - > num_nodes = xgmi_cmd - > xgmi_out_message . get_topology_info . num_nodes ;
for ( i = 0 ; i < topology - > num_nodes ; i + + ) {
topology - > nodes [ i ] . node_id = topology_info_output - > nodes [ i ] . node_id ;
topology - > nodes [ i ] . num_hops = topology_info_output - > nodes [ i ] . num_hops ;
topology - > nodes [ i ] . is_sharing_enabled = topology_info_output - > nodes [ i ] . is_sharing_enabled ;
topology - > nodes [ i ] . sdma_engine = topology_info_output - > nodes [ i ] . sdma_engine ;
}
2018-08-14 13:30:00 -04:00
return 0 ;
}
static int psp_v11_0_xgmi_set_topology_info ( struct psp_context * psp ,
int number_devices , struct psp_xgmi_topology_info * topology )
{
2018-09-29 22:32:42 +08:00
struct ta_xgmi_shared_memory * xgmi_cmd ;
struct ta_xgmi_cmd_get_topology_info_input * topology_info_input ;
int i ;
if ( ! topology | | topology - > num_nodes > TA_XGMI__MAX_CONNECTED_NODES )
return - EINVAL ;
xgmi_cmd = ( struct ta_xgmi_shared_memory * ) psp - > xgmi_context . xgmi_shared_buf ;
memset ( xgmi_cmd , 0 , sizeof ( struct ta_xgmi_shared_memory ) ) ;
topology_info_input = & xgmi_cmd - > xgmi_in_message . get_topology_info ;
xgmi_cmd - > cmd_id = TA_COMMAND_XGMI__SET_TOPOLOGY_INFO ;
topology_info_input - > num_nodes = number_devices ;
for ( i = 0 ; i < topology_info_input - > num_nodes ; i + + ) {
topology_info_input - > nodes [ i ] . node_id = topology - > nodes [ i ] . node_id ;
topology_info_input - > nodes [ i ] . num_hops = topology - > nodes [ i ] . num_hops ;
topology_info_input - > nodes [ i ] . is_sharing_enabled = topology - > nodes [ i ] . is_sharing_enabled ;
topology_info_input - > nodes [ i ] . sdma_engine = topology - > nodes [ i ] . sdma_engine ;
}
/* Invoke xgmi ta to set topology information */
return psp_xgmi_invoke ( psp , TA_COMMAND_XGMI__SET_TOPOLOGY_INFO ) ;
2018-08-14 13:30:00 -04:00
}
static u64 psp_v11_0_xgmi_get_hive_id ( struct psp_context * psp )
{
2018-09-29 12:17:42 +08:00
struct ta_xgmi_shared_memory * xgmi_cmd ;
int ret ;
xgmi_cmd = ( struct ta_xgmi_shared_memory * ) psp - > xgmi_context . xgmi_shared_buf ;
memset ( xgmi_cmd , 0 , sizeof ( struct ta_xgmi_shared_memory ) ) ;
2018-08-14 13:30:00 -04:00
2018-09-29 12:17:42 +08:00
xgmi_cmd - > cmd_id = TA_COMMAND_XGMI__GET_HIVE_ID ;
2018-08-14 13:30:00 -04:00
2018-09-29 12:17:42 +08:00
/* Invoke xgmi ta to get hive id */
ret = psp_xgmi_invoke ( psp , xgmi_cmd - > cmd_id ) ;
if ( ret )
return 0 ;
else
return xgmi_cmd - > xgmi_out_message . get_hive_id . hive_id ;
2018-08-14 13:30:00 -04:00
}
2018-09-28 21:50:37 +08:00
static u64 psp_v11_0_xgmi_get_node_id ( struct psp_context * psp )
{
struct ta_xgmi_shared_memory * xgmi_cmd ;
int ret ;
xgmi_cmd = ( struct ta_xgmi_shared_memory * ) psp - > xgmi_context . xgmi_shared_buf ;
memset ( xgmi_cmd , 0 , sizeof ( struct ta_xgmi_shared_memory ) ) ;
xgmi_cmd - > cmd_id = TA_COMMAND_XGMI__GET_NODE_ID ;
/* Invoke xgmi ta to get the node id */
ret = psp_xgmi_invoke ( psp , xgmi_cmd - > cmd_id ) ;
if ( ret )
return 0 ;
else
return xgmi_cmd - > xgmi_out_message . get_node_id . node_id ;
}
2018-05-11 14:54:50 +08:00
static const struct psp_funcs psp_v11_0_funcs = {
. init_microcode = psp_v11_0_init_microcode ,
. bootloader_load_sysdrv = psp_v11_0_bootloader_load_sysdrv ,
. bootloader_load_sos = psp_v11_0_bootloader_load_sos ,
. prep_cmd_buf = psp_v11_0_prep_cmd_buf ,
. ring_init = psp_v11_0_ring_init ,
. ring_create = psp_v11_0_ring_create ,
. ring_stop = psp_v11_0_ring_stop ,
. ring_destroy = psp_v11_0_ring_destroy ,
. cmd_submit = psp_v11_0_cmd_submit ,
. compare_sram_data = psp_v11_0_compare_sram_data ,
. mode1_reset = psp_v11_0_mode1_reset ,
2018-08-14 13:30:00 -04:00
. xgmi_get_topology_info = psp_v11_0_xgmi_get_topology_info ,
. xgmi_set_topology_info = psp_v11_0_xgmi_set_topology_info ,
. xgmi_get_hive_id = psp_v11_0_xgmi_get_hive_id ,
2018-09-28 21:50:37 +08:00
. xgmi_get_node_id = psp_v11_0_xgmi_get_node_id ,
2018-05-11 14:54:50 +08:00
} ;
void psp_v11_0_set_psp_funcs ( struct psp_context * psp )
{
psp - > funcs = & psp_v11_0_funcs ;
}