From 9c63762e00a20f22fc8a4509071d90786513e16a Mon Sep 17 00:00:00 2001 From: Doug Gilbert Date: Wed, 20 Sep 2017 14:56:59 -0500 Subject: Enable hardware GPU power brake Change-Id: I39ae6205cef6ae06cacc0eb2c8a0a4288b8081c8 RTC: 179617 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/46800 Tested-by: FSP CI Jenkins Reviewed-by: Martha Broyles Reviewed-by: Christopher J. Cain Reviewed-by: William A. Bryan --- src/common/gpe_err.h | 2 + src/common/gpu_structs.h | 14 ++++++ src/common/ipc_func_ids.h | 1 + src/include/registers/p9_misc_scom_addresses.h | 10 ++++ src/occ_405/gpu/gpu.c | 66 ++++++++++++++++++++++++ src/occ_405/gpu/gpu_service_codes.h | 1 + src/occ_gpe1/gpe_gpu_init.c | 69 ++++++++++++++++++++++++++ src/occ_gpe1/ipc_func_tables.c | 3 +- src/occ_gpe1/topfiles.mk | 2 +- 9 files changed, 166 insertions(+), 2 deletions(-) create mode 100644 src/include/registers/p9_misc_scom_addresses.h create mode 100644 src/occ_gpe1/gpe_gpu_init.c diff --git a/src/common/gpe_err.h b/src/common/gpe_err.h index 3bb1fa0..23d55d2 100644 --- a/src/common/gpe_err.h +++ b/src/common/gpe_err.h @@ -55,4 +55,6 @@ #define GPE_RC_GPU_DRIVER_CHANGE 0x81 // GPU in transition or just completed phase change #define GPE_RC_GPU_CMD_NOT_SUPPORTED 0x82 // GPU rejected command with no support #define GPE_RC_GPU_CMD_FAILED 0x83 // An error occurred in the last GPU operation +#define GPE_RC_GPU_INIT_FAILED 0x84 // Failed to init GPU + #endif //_GPE_ERR_H diff --git a/src/common/gpu_structs.h b/src/common/gpu_structs.h index ba522e5..98567d7 100644 --- a/src/common/gpu_structs.h +++ b/src/common/gpu_structs.h @@ -98,5 +98,19 @@ typedef struct uint64_t data[3]; } gpu_sm_args_t; +typedef struct +{ + uint32_t pib_master; + uint32_t bus_voltage; + uint32_t port[MAX_GPUS]; + uint32_t addr[MAX_GPUS]; +} gpu_i2c_info_t; + +typedef struct +{ + GpeErrorStruct error; + gpu_i2c_info_t gpu_i2c; +} gpu_init_args_t; + #endif // _GPU_STRUCTS_H diff --git a/src/common/ipc_func_ids.h b/src/common/ipc_func_ids.h index 9d3dd33..cdd80fb 100644 --- a/src/common/ipc_func_ids.h +++ b/src/common/ipc_func_ids.h @@ -73,6 +73,7 @@ IPC_FUNCIDS_TABLE_START IPC_FUNC_ID(IPC_ST_24_X_7_FUNCID) IPC_FUNC_ID(IPC_ST_MEM_POWER_CONTROL_FUNCID) IPC_FUNC_ID(IPC_ST_GPU_SM_FUNCID) + IPC_FUNC_ID(IPC_ST_GPE_GPU_INIT_FUNCID) IPC_FUNCIDS_ST_END(OCCHW_INST_ID_GPE1) //Functions that are only supported by GPE2 should be defined here diff --git a/src/include/registers/p9_misc_scom_addresses.h b/src/include/registers/p9_misc_scom_addresses.h new file mode 100644 index 0000000..480bff4 --- /dev/null +++ b/src/include/registers/p9_misc_scom_addresses.h @@ -0,0 +1,10 @@ +#if !defined(_P9_MISC_SCOM_ADDRESSES_H_) +#define _P9_MISC_SCOM_ADDRESSES_H_ + +#define PU_GPIO_INPUT 0x000B0050 +#define PU_GPIO_OUTPUT 0x000B0051 +#define PU_GPIO_OUTPUT_OR 0x000B0052 +#define PU_GPIO_OUTPUT_CLR 0x000B0053 +#define PU_GPIO_OUTPUT_EN 0x000B0054 + +#endif diff --git a/src/occ_405/gpu/gpu.c b/src/occ_405/gpu/gpu.c index 1a27565..0be5c9f 100755 --- a/src/occ_405/gpu/gpu.c +++ b/src/occ_405/gpu/gpu.c @@ -81,9 +81,11 @@ uint32_t G_gpu_reset_cause = 0; // GPE Requests GpeRequest G_gpu_op_request; +GpeRequest G_gpu_init_request; // GPE arguments GPE_BUFFER(gpu_sm_args_t G_gpu_op_req_args); +GPE_BUFFER(gpu_init_args_t G_gpu_init_args); gpu_sm_args_t G_new_gpu_req_args = {{{{0}}}}; @@ -444,6 +446,49 @@ void disable_all_gpus(void) } } + +// schedule request to init gpu info on gpe1 +void schedule_gpe_gpu_init_req() +{ + errlHndl_t err = NULL; + int rc = 0; + + memset(&G_gpu_init_args, 0, sizeof(G_gpu_init_args)); + // Need to add gpu i2c info + // G_gpu_init_args.gpu_i2c + + + rc = gpe_request_schedule(&G_gpu_init_request); + if (rc) + { + INTR_TRAC_ERR + ("schedule_gpe_gpu_init_req: gpe gpu init schedule failed w/rc=0x%08X", rc); + /* + * @errortype + * @moduleid GPU_MID_GPE_GPU_INIT_SCHED_REQ + * @reasoncode SSX_GENERIC_FAILURE + * @userdata1 GPE schedule returned code + * @userdata4 ERC_GPU_SCHEDULE_FAILURE + * @devdesc Failed to schedule GPE GPU initial request + */ + err = createErrl(GPU_MID_GPE_GPU_INIT_SCHED_REQ, + SSX_GENERIC_FAILURE, + ERC_GPU_SCHEDULE_FAILURE, + ERRL_SEV_PREDICTIVE, + NULL, + DEFAULT_TRACE_SIZE, + rc, + 0); + commitErrl(&err); + + // release I2C lock to the host for this engine and stop monitoring + occ_i2c_lock_release(GPU_I2C_ENGINE); + G_gpu_monitoring_allowed = FALSE; + } + +} + + // Create GPU IPC requests void gpu_ipc_init() { @@ -467,6 +512,22 @@ void gpu_ipc_init() TRAC_ERR("gpu_ipc_init: Failed to create GPE1 IPC request for GPU op req (rc=%d)", rc); break; } + + // Initialize GPU support on GPE1 + GPU_DBG("gpu_ipc_init: Creating GPE1 IPC request for GPU initialization"); + rc = gpe_request_create(&G_gpu_init_request, + &G_async_gpe_queue1, + IPC_ST_GPE_GPU_INIT_FUNCID, + &G_gpu_init_args, + SSX_WAIT_FOREVER, + NULL, // no callback + NULL, // no args + ASYNC_CALLBACK_IMMEDIATE); + if (rc) + { + TRAC_ERR("gpu_ipc_init: Failed to create GPE1 GPU init request. (rc=%d)", rc); + break; + } } while(0); @@ -495,6 +556,11 @@ void gpu_ipc_init() occ_i2c_lock_release(GPU_I2C_ENGINE); G_gpu_monitoring_allowed = FALSE; } + else + { + // gpe gpu init only needs to be done once, so do it here. + schedule_gpe_gpu_init_req(); + } } // Called after a failure reading core temp for a specified GPU. The error will diff --git a/src/occ_405/gpu/gpu_service_codes.h b/src/occ_405/gpu/gpu_service_codes.h index 4ea7c6f..bf69cff 100755 --- a/src/occ_405/gpu/gpu_service_codes.h +++ b/src/occ_405/gpu/gpu_service_codes.h @@ -42,6 +42,7 @@ enum gpuModuleId GPU_MID_GPU_CHECK_DRIVER_LOADED = GPU_COMP_ID | 0x09, GPU_MID_GPU_READ_PWR_LIMIT = GPU_COMP_ID | 0x0A, GPU_MID_GPU_SET_PWR_LIMIT = GPU_COMP_ID | 0x0B, + GPU_MID_GPE_GPU_INIT_SCHED_REQ = GPU_COMP_ID | 0x0C, }; #endif /* #ifndef _GPU_SERVICE_CODES_H_ */ diff --git a/src/occ_gpe1/gpe_gpu_init.c b/src/occ_gpe1/gpe_gpu_init.c new file mode 100644 index 0000000..a293905 --- /dev/null +++ b/src/occ_gpe1/gpe_gpu_init.c @@ -0,0 +1,69 @@ +#include "pk.h" +#include "ppe42_scom.h" +#include "gpu_structs.h" +#include "ipc_async_cmd.h" +#include "gpe_err.h" +#include "gpe_util.h" +#include "p9_misc_scom_addresses.h" + +gpu_i2c_info_t G_gpu_i2c __attribute__((section(".sbss.G_gpu_i2c"))); + +void gpe_gpu_init(ipc_msg_t* cmd, void* arg) +{ + int rc = 0; + int i; + ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)cmd; + gpu_init_args_t *args = (gpu_init_args_t*)async_cmd->cmd_data; + + args->error.ffdc = 0; + + // Prevent MCK attention on scom failes (PK kernel fix?) + mtmsr((mfmsr() & ~(MSR_SIBRC | MSR_SIBRCA)) | MSR_SEM); + + // According to Jordan Keuseman, Setting PV_CP0_P_PRV_GPIO0 pin on the + // processor chip to low enables HW to automatically apply GPU power brake. + // GPIO1 (GPU_PWR_BRAKE_FORCE_N) will not be controlled by FW, so needs to + // be configured as input. + uint64_t data64 = 0x8000000000000000ull; + rc = putscom_abs(PU_GPIO_OUTPUT_CLR,data64); + if(rc) + { + PK_TRACE("gpe_gpu_init: PU_GPIO0_OUTPUT failed. rc:0x%08x",rc); + gpe_set_ffdc(&(args->error), 0, GPE_RC_GPU_INIT_FAILED, rc); + } + + rc = getscom_abs(PU_GPIO_OUTPUT_EN, &data64); + if(rc) + { + PK_TRACE("gpe_gpu_init: Read PU_GPIO0_OUTPUT_EN failed. rc:0x%08x",rc); + gpe_set_ffdc(&(args->error), 0, GPE_RC_GPU_INIT_FAILED, rc); + } + + // pin0 as output, pin1 as input, pin3 unchanged + data64 &= 0xBfffffffffffffffull; + data64 |= 0x8000000000000000ull; + + rc = putscom_abs(PU_GPIO_OUTPUT_EN, data64); + + if(rc) + { + PK_TRACE("gpe_gpu_init: PU_GPIO0_OUTPUT_EN failed. rc:0x%08x",rc); + gpe_set_ffdc(&(args->error), 0, GPE_RC_GPU_INIT_FAILED, rc); + } + + // Get i2c data + G_gpu_i2c.pib_master = args->gpu_i2c.pib_master; + G_gpu_i2c.bus_voltage = args->gpu_i2c.bus_voltage; + for(i = 0; i < MAX_GPUS; ++i) + { + G_gpu_i2c.port[i] = args->gpu_i2c.port[i]; + G_gpu_i2c.addr[i] = args->gpu_i2c.addr[i]; + } + + rc = ipc_send_rsp(cmd, IPC_RC_SUCCESS); + if(rc) + { + PK_TRACE("E>gpu_init: Failed to send response back. Halting GPE1", rc); + pk_halt(); + } +} diff --git a/src/occ_gpe1/ipc_func_tables.c b/src/occ_gpe1/ipc_func_tables.c index ea1d6f8..a7fe5ea 100644 --- a/src/occ_gpe1/ipc_func_tables.c +++ b/src/occ_gpe1/ipc_func_tables.c @@ -32,6 +32,7 @@ void gpe1_nop(ipc_msg_t* cmd, void* arg); void gpe_reset_mem_deadman(ipc_msg_t* cmd, void* arg); void gpe_24x7(ipc_msg_t* cmd, void* arg); void gpe_mem_power_control(ipc_msg_t* cmd, void* arg); +void gpe_gpu_init(ipc_msg_t* cmd, void* arg); #ifdef OCC_GPU_SUPPORT void gpe_gpu_sm(ipc_msg_t* cmd, void* arg); @@ -82,7 +83,7 @@ IPC_HANDLER(gpe_reset_mem_deadman, 0) // 3 - IPC_ST_RESET_MEM_DEADMAN IPC_HANDLER(gpe_24x7, 0) // 4 - IPC_ST_24_X_7_FUNCID IPC_HANDLER(gpe_mem_power_control, 0) // 5 - IPC_ST_MEM_POWER_CONTROL_FUNCID IPC_HANDLER(gpe_gpu_sm, 0) // 6 - IPC_ST_GPU_SM_FUNCID -IPC_HANDLER_DEFAULT // 7 +IPC_HANDLER(gpe_gpu_init, 0) // 7 - IPC_ST_GPE_GPU_INIT_FUNCID IPC_HANDLER_DEFAULT // 8 IPC_HANDLER_DEFAULT // 9 IPC_HANDLER_DEFAULT // 10 diff --git a/src/occ_gpe1/topfiles.mk b/src/occ_gpe1/topfiles.mk index 6dbae16..d0c2c2f 100644 --- a/src/occ_gpe1/topfiles.mk +++ b/src/occ_gpe1/topfiles.mk @@ -25,7 +25,7 @@ TOP-C-SOURCES = gpe1_main.c gpe1_dimm_read.c gpe1_dimm_reset.c nop.c \ pk_app_irq_table.c ipc_func_tables.c gpe1_dimm_control.c \ - gpe1_24x7.c gpe1_memory_power_control.c + gpe1_24x7.c gpe1_memory_power_control.c gpe_gpu_init.c TOP-S-SOURCES = -- cgit v1.2.1