summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDoug Gilbert <dgilbert@us.ibm.com>2017-09-20 14:56:59 -0500
committerWilliam A. Bryan <wilbryan@us.ibm.com>2017-10-10 13:02:41 -0400
commit9c63762e00a20f22fc8a4509071d90786513e16a (patch)
tree5e2484abcfeae088d6b20f562535881978800d5e
parentba4e81e804275ced6c1793f818e5fc1fd8d1ecae (diff)
downloadtalos-occ-9c63762e00a20f22fc8a4509071d90786513e16a.tar.gz
talos-occ-9c63762e00a20f22fc8a4509071d90786513e16a.zip
Enable hardware GPU power brake
Change-Id: I39ae6205cef6ae06cacc0eb2c8a0a4288b8081c8 RTC: 179617 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/46800 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Martha Broyles <mbroyles@us.ibm.com> Reviewed-by: Christopher J. Cain <cjcain@us.ibm.com> Reviewed-by: William A. Bryan <wilbryan@us.ibm.com>
-rw-r--r--src/common/gpe_err.h2
-rw-r--r--src/common/gpu_structs.h14
-rw-r--r--src/common/ipc_func_ids.h1
-rw-r--r--src/include/registers/p9_misc_scom_addresses.h10
-rwxr-xr-xsrc/occ_405/gpu/gpu.c66
-rwxr-xr-xsrc/occ_405/gpu/gpu_service_codes.h1
-rw-r--r--src/occ_gpe1/gpe_gpu_init.c69
-rw-r--r--src/occ_gpe1/ipc_func_tables.c3
-rw-r--r--src/occ_gpe1/topfiles.mk2
9 files changed, 166 insertions, 2 deletions
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 =
OpenPOWER on IntegriCloud