diff options
author | Chris Cain <cjcain@us.ibm.com> | 2019-01-09 17:21:57 -0600 |
---|---|---|
committer | Christopher J. Cain <cjcain@us.ibm.com> | 2019-01-29 15:46:29 -0600 |
commit | f7b1e2a3bcae240b8a9d47b7997f82367c11e1bd (patch) | |
tree | 020d3b0ca82037487b71a2868f26c0051df23c22 | |
parent | d03cb7413705fe805cb41d5bc259d825fc814e3d (diff) | |
download | talos-occ-f7b1e2a3bcae240b8a9d47b7997f82367c11e1bd.tar.gz talos-occ-f7b1e2a3bcae240b8a9d47b7997f82367c11e1bd.zip |
Add support for a second voltage sense from APSS
Change-Id: I8c356e2962c0e25c0335dc7af7dc79fc0702df60
RTC: 202003
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/70401
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Martha Broyles <mbroyles@us.ibm.com>
Reviewed-by: William A. Bryan <wilbryan@us.ibm.com>
Reviewed-by: Christopher J. Cain <cjcain@us.ibm.com>
-rwxr-xr-x | src/occ_405/amec/amec_master_smh.c | 5 | ||||
-rwxr-xr-x | src/occ_405/amec/amec_sensors_power.c | 143 | ||||
-rwxr-xr-x | src/occ_405/cmdh/cmdh_fsp_cmds.c | 53 | ||||
-rwxr-xr-x | src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c | 186 | ||||
-rw-r--r-- | src/occ_405/occ_service_codes.h | 5 | ||||
-rwxr-xr-x | src/occ_405/occ_sys_config.c | 4 | ||||
-rwxr-xr-x | src/occ_405/occ_sys_config.h | 10 |
7 files changed, 335 insertions, 71 deletions
diff --git a/src/occ_405/amec/amec_master_smh.c b/src/occ_405/amec/amec_master_smh.c index 33d6c13..df3e2cb 100755 --- a/src/occ_405/amec/amec_master_smh.c +++ b/src/occ_405/amec/amec_master_smh.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2017 */ +/* Contributors Listed Below - COPYRIGHT 2011,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -441,7 +441,8 @@ void amec_mst_check_under_pcap(void) if((l_apss_func_id != ADC_RESERVED) && (l_apss_func_id != ADC_12V_SENSE) && (l_apss_func_id != ADC_GND_REMOTE_SENSE) && - (l_apss_func_id != ADC_12V_STANDBY_CURRENT) ) + (l_apss_func_id != ADC_12V_STANDBY_CURRENT) && + (l_apss_func_id != ADC_VOLT_SENSE_2)) { l_trace[l_trace_idx] = (i << 24) | (l_apss_func_id << 16) | (AMECSENSOR_PTR(PWRAPSSCH0 + i)->sample); l_trace_idx++; diff --git a/src/occ_405/amec/amec_sensors_power.c b/src/occ_405/amec/amec_sensors_power.c index bf13cb4..6ad3406 100755 --- a/src/occ_405/amec/amec_sensors_power.c +++ b/src/occ_405/amec/amec_sensors_power.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2018 */ +/* Contributors Listed Below - COPYRIGHT 2011,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -84,6 +84,10 @@ extern task_t G_task_table[TASK_END]; extern uint16_t G_configured_mbas; extern uint8_t G_injected_epow_asserted; +extern uint8_t G_gpu_volt_type[MAX_GPU_DOMAINS][MAX_NUM_GPU_PER_DOMAIN]; + +#define GPU0_USING_VOLT2(proc, channel) ((channel == G_sysConfigData.apss_adc_map.gpu[proc][0]) && (G_gpu_volt_type[proc][0] == 2)) +#define GPU1_USING_VOLT2(proc, channel) ((channel == G_sysConfigData.apss_adc_map.gpu[proc][1]) && (G_gpu_volt_type[proc][1] == 2)) //*************************************************************************/ // Code @@ -152,7 +156,7 @@ uint32_t amec_value_from_apss_adc(uint8_t i_chan) * gain adjusted output: 1024mV * 10,000 mA/V = 10,240,000 (mV . mA)/V * Reduced value: adjusted/1000 = 10,240 mA * - * Note that in the case of the remote ground and 12V sense the gain + * Note that in the case of the remote ground and voltage sense the gain * values are in V/V so the returned value is actually in mVs. * * Max returnable value is 4,294,967,295 mA or approx. 4.3 MA @@ -193,6 +197,7 @@ uint32_t amec_value_from_apss_adc(uint8_t i_chan) #define ADCMULT_TO_UNITS 1000000 #define ADCMULT_ROUND ADCMULT_TO_UNITS/2 +#define ROUND_POWER(value) ((((uint64_t)value) + ADCMULT_ROUND) / ADCMULT_TO_UNITS) // Function Specification // // Name: amec_update_apss_sensors @@ -218,7 +223,6 @@ bool amec_update_apss_sensors(void) uint8_t l_proc = G_pbax_id.chip_id; uint32_t temp32 = 0; uint8_t l_idx = 0; - uint32_t l_bulk_current_sum = 0; // Check GPIO_EPOW. Skip everything if asserted if (epow_gpio_asserted()) @@ -233,25 +237,22 @@ bool amec_update_apss_sensors(void) for (l_idx = 0; l_idx < MAX_APSS_ADC_CHANNELS; l_idx++) { // These values returned are gain adjusted. The APSS readings for - // the remote ground and 12V sense are returned in mVs, all other + // the remote ground and voltage sense are returned in mVs, all other // readings are treated as mAs. G_lastValidAdcValue[l_idx] = amec_value_from_apss_adc(l_idx); - - // Add up all channels now, we will subtract ones later that don't - // count towards the system power - l_bulk_current_sum += G_lastValidAdcValue[l_idx]; } // -------------------------------------------------------------- - // Convert 12Vsense into interim value - this has to happen first + // Convert voltages into interim value - this has to happen first // -------------------------------------------------------------- // Calculations involving bulk_voltage must be 64bit so final result // does not get truncated (before dividing by ADCMULT_TO_UNITS) uint64_t l_bulk_voltage = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.sense_12v); + uint64_t l_bulk_voltage_2 = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.sense_volt2); if (OCC_MASTER == G_occ_role) { - // Update channel sensors for all channels (except 12v sense and gnd) + // Update channel sensors for all channels (except voltage sense and gnd) for (l_idx = 0; l_idx < MAX_APSS_ADC_CHANNELS; l_idx++) { if(l_idx == G_sysConfigData.apss_adc_map.current_12v_stby) @@ -261,9 +262,18 @@ bool amec_update_apss_sensors(void) sensor_update(AMECSENSOR_PTR(CUR12VSTBY), (uint16_t) temp32); } else if((l_idx != G_sysConfigData.apss_adc_map.sense_12v) && + (l_idx != G_sysConfigData.apss_adc_map.sense_volt2) && (l_idx != G_sysConfigData.apss_adc_map.remote_gnd)) { - temp32 = ((ADC_CONVERTED_VALUE(l_idx) * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS; + uint64_t l_bulk_v = l_bulk_voltage; + if ( GPU0_USING_VOLT2(0, l_idx) || GPU1_USING_VOLT2(0, l_idx) || + GPU0_USING_VOLT2(1, l_idx) || GPU1_USING_VOLT2(1, l_idx) || + (l_idx == G_sysConfigData.apss_adc_map.total_current_volt2) ) + { + // Channel is using Voltge 2 + l_bulk_v = l_bulk_voltage_2; + } + temp32 = ROUND_POWER(ADC_CONVERTED_VALUE(l_idx) * l_bulk_v); sensor_update(AMECSENSOR_PTR(PWRAPSSCH0 + l_idx), (uint16_t) temp32); } } @@ -291,7 +301,7 @@ bool amec_update_apss_sensors(void) { uint32_t l_vdd = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.vdd[l_proc]); uint32_t l_vcs_vio_vpcie = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.vcs_vio_vpcie[l_proc]); - temp32 = ((l_vcs_vio_vpcie + l_vdd) * l_bulk_voltage)/ADCMULT_TO_UNITS; + temp32 = ROUND_POWER((l_vcs_vio_vpcie + l_vdd) * l_bulk_voltage); sensor_update(AMECSENSOR_PTR(PWRPROC), (uint16_t) temp32); } @@ -300,7 +310,7 @@ bool amec_update_apss_sensors(void) { uint32_t l_vd = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.vdd[l_idx]); uint32_t l_vpcie = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.vcs_vio_vpcie[l_idx]); - g_amec->proc_snr_pwr[l_idx] = ((l_vpcie + l_vd) * l_bulk_voltage)/ADCMULT_TO_UNITS; + g_amec->proc_snr_pwr[l_idx] = ROUND_POWER((l_vpcie + l_vd) * l_bulk_voltage); } // All readings from APSS come back as milliUnits, so if we want @@ -317,14 +327,14 @@ bool amec_update_apss_sensors(void) // Fans: Add up all Fan channels temp32 = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.fans[0]); temp32 += ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.fans[1]); - temp32 = ((temp32 * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS; + temp32 = ROUND_POWER(temp32 * l_bulk_voltage); sensor_update( AMECSENSOR_PTR(PWRFAN), (uint16_t)temp32); // I/O: Add up all I/O channels temp32 = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.io[0]); temp32 += ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.io[1]); temp32 += ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.io[2]); - temp32 = ((temp32 * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS; + temp32 = ROUND_POWER(temp32 * l_bulk_voltage); sensor_update( AMECSENSOR_PTR(PWRIO), (uint16_t)temp32); // Memory: Add up all channels for the same processor. @@ -337,7 +347,7 @@ bool amec_update_apss_sensors(void) { temp32 += ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.mem_cache); } - temp32 = ((temp32 * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS; + temp32 = ROUND_POWER(temp32 * l_bulk_voltage); sensor_update( AMECSENSOR_PTR(PWRMEM), (uint16_t)temp32); // Save off the combined power from all memory @@ -347,46 +357,103 @@ bool amec_update_apss_sensors(void) l_temp += ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.memory[l_idx][1]); l_temp += ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.memory[l_idx][2]); l_temp += ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.memory[l_idx][3]); - g_amec->mem_snr_pwr[l_idx] = ((l_temp * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS; + g_amec->mem_snr_pwr[l_idx] = ROUND_POWER(l_temp * l_bulk_voltage); } // Storage/Media temp32 = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.storage_media[0]); temp32 += ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.storage_media[1]); - temp32 = ((temp32 * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS; + temp32 = ROUND_POWER(temp32 * l_bulk_voltage); sensor_update( AMECSENSOR_PTR(PWRSTORE), (uint16_t)temp32); // Save total GPU adapter for this proc if (l_proc < MAX_GPU_DOMAINS) { - temp32 = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.gpu[l_proc][0]); - temp32 += ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.gpu[l_proc][1]); - temp32 += ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.gpu[l_proc][2]); - temp32 = ((temp32 * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS; + // GPU0 + uint64_t l_bulk_v = l_bulk_voltage; + if (G_gpu_volt_type[l_proc][0] == 2) + { + l_bulk_v = l_bulk_voltage_2; + } + temp32 = l_bulk_v * ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.gpu[l_proc][0]); + // GPU1 + if (G_gpu_volt_type[l_proc][1] == 2) + { + l_bulk_v = l_bulk_voltage_2; + } + else + { + l_bulk_v = l_bulk_voltage; + } + temp32 += l_bulk_v * ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.gpu[l_proc][1]); + // GPU2 + temp32 += l_bulk_voltage * ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.gpu[l_proc][2]); + temp32 = ROUND_POWER(temp32); sensor_update( AMECSENSOR_PTR(PWRGPU), (uint16_t)temp32); } // ---------------------------------------------------- // Convert Raw Bulk Power from APSS into sensors // ---------------------------------------------------- - // We don't get this adc channel in some systems, we have to add it manually. - // With valid sysconfig data the code here should automatically use what - // is provided by the APSS if it is available, or manually sum it up if not. - temp32 = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.total_current_12v); - temp32 = ((temp32 * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS; - - // To calculated the total 12V current based on a sum of all ADC channels, - // Subract adc channels that don't measure power - l_bulk_current_sum -= ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.sense_12v); - l_bulk_current_sum -= ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.remote_gnd); - l_bulk_current_sum -= ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.current_12v_stby); - - // If we don't have a ADC channel that measures the bulk 12v power, use - // the ADC sum instead - if(0 == temp32) + // Not all systems provide a total system current/power, in which case it must be calculated. + temp32 = 0; + const uint32_t syspwr_volt1 = l_bulk_voltage * ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.total_current_12v); + const uint32_t syspwr_volt2 = l_bulk_voltage_2 * ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.total_current_volt2); + if(0 != syspwr_volt1) + { + // Total System Power (voltage 1 (12V)) was provided, use directly + temp32 = syspwr_volt1; + if (0 != syspwr_volt2) + { + // Total System Power (voltage 2) was provided, use directly + temp32 += syspwr_volt2; + } + else + { + // No Total System Power (voltage 2) - Add powers for GPUs using voltage 2 + for (l_idx = 0; l_idx < MAX_APSS_ADC_CHANNELS; l_idx++) + { + if ( GPU0_USING_VOLT2(0, l_idx) || GPU1_USING_VOLT2(0, l_idx) || + GPU0_USING_VOLT2(1, l_idx) || GPU1_USING_VOLT2(1, l_idx) ) + { + temp32 += l_bulk_voltage_2 * G_lastValidAdcValue[l_idx]; + } + } + } + } + else { - temp32 = ((l_bulk_current_sum * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS; + // No Total System Power (voltage 1 (12V)) - Add powers for channels using voltage 1 + for (l_idx = 0; l_idx < MAX_APSS_ADC_CHANNELS; l_idx++) + { + if ( (0 != syspwr_volt2) && + ( GPU0_USING_VOLT2(0, l_idx) || GPU1_USING_VOLT2(0, l_idx) || + GPU0_USING_VOLT2(1, l_idx) || GPU1_USING_VOLT2(1, l_idx) ) ) + { + // Total System Power (voltage 2) was provided, so skip GPU channels using voltage 2 + continue; + } + + uint64_t l_bulk_v = l_bulk_voltage; + if ( GPU0_USING_VOLT2(0, l_idx) || GPU1_USING_VOLT2(0, l_idx) || + GPU0_USING_VOLT2(1, l_idx) || GPU1_USING_VOLT2(1, l_idx) || + (l_idx == G_sysConfigData.apss_adc_map.total_current_volt2) ) + { + // GPU (or total current) is using voltage 2 + l_bulk_v = l_bulk_voltage_2; + } + + if ((l_idx != G_sysConfigData.apss_adc_map.sense_12v) && + (l_idx != G_sysConfigData.apss_adc_map.remote_gnd) && + (l_idx != G_sysConfigData.apss_adc_map.current_12v_stby) && + (l_idx != G_sysConfigData.apss_adc_map.sense_volt2)) + { + // Add power for this channel + temp32 += l_bulk_v * G_lastValidAdcValue[l_idx]; + } + } } + temp32 = ROUND_POWER(temp32); sensor_update(AMECSENSOR_PTR(PWRSYS), (uint16_t)temp32); // Calculate average frequency of all OCCs. diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds.c b/src/occ_405/cmdh/cmdh_fsp_cmds.c index 47cb457..042e71b 100755 --- a/src/occ_405/cmdh/cmdh_fsp_cmds.c +++ b/src/occ_405/cmdh/cmdh_fsp_cmds.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2018 */ +/* Contributors Listed Below - COPYRIGHT 2011,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -559,26 +559,45 @@ ERRL_RC cmdh_poll_v20(cmdh_fsp_rsp_t * o_rsp_ptr) cmdh_poll_power_sensor_t l_pwrSensorList[MAX_APSS_ADC_CHANNELS]; for (k = 0; k < MAX_APSS_ADC_CHANNELS; k++) { - if ((G_apss_ch_to_function[k] != ADC_12V_SENSE) && - (G_apss_ch_to_function[k] != ADC_GND_REMOTE_SENSE) && - (G_apss_ch_to_function[k] != ADC_12V_STANDBY_CURRENT)) + const uint8_t function_id = G_apss_ch_to_function[k]; + if ((function_id != ADC_12V_SENSE) && + (function_id != ADC_GND_REMOTE_SENSE) && + (function_id != ADC_12V_STANDBY_CURRENT) && + (function_id != ADC_VOLT_SENSE_2)) { // only return channel power for GPU if the GPU is present - if( ( (G_apss_ch_to_function[k] != ADC_GPU_0_0) && - (G_apss_ch_to_function[k] != ADC_GPU_0_1) && - (G_apss_ch_to_function[k] != ADC_GPU_0_2) && - (G_apss_ch_to_function[k] != ADC_GPU_1_0) && - (G_apss_ch_to_function[k] != ADC_GPU_1_1) && - (G_apss_ch_to_function[k] != ADC_GPU_1_2) ) || - ( (G_apss_ch_to_function[k] == ADC_GPU_0_0) && (G_first_sys_gpu_config & 0x01) ) || - ( (G_apss_ch_to_function[k] == ADC_GPU_0_1) && (G_first_sys_gpu_config & 0x02) ) || - ( (G_apss_ch_to_function[k] == ADC_GPU_0_2) && (G_first_sys_gpu_config & 0x04) ) || - ( (G_apss_ch_to_function[k] == ADC_GPU_1_0) && (G_first_sys_gpu_config & 0x08) ) || - ( (G_apss_ch_to_function[k] == ADC_GPU_1_1) && (G_first_sys_gpu_config & 0x10) ) || - ( (G_apss_ch_to_function[k] == ADC_GPU_1_2) && (G_first_sys_gpu_config & 0x20) ) ) + bool include = FALSE; + if ( (function_id == ADC_GPU_0_0) || + ((function_id >= ADC_GPU_0_1) && (function_id <= ADC_GPU_VOLT2_1_1)) ) + { + // GPU channel: include if has a non-zero reading or if GPU is present + if ( ( G_amec_sensor_list[PWRAPSSCH0 + k]->sample > 0) || + ( ((ADC_GPU_0_0 == function_id) || (ADC_GPU_VOLT2_0_0 == function_id)) && + (G_first_sys_gpu_config & 0x01) ) || + ( ((ADC_GPU_0_1 == function_id) || (ADC_GPU_VOLT2_0_1 == function_id)) && + (G_first_sys_gpu_config & 0x02) ) || + ( ( ADC_GPU_0_2 == function_id) && + (G_first_sys_gpu_config & 0x04) ) || + ( ((ADC_GPU_1_0 == function_id) || (ADC_GPU_VOLT2_1_0 == function_id)) && + (G_first_sys_gpu_config & 0x08) ) || + ( ((ADC_GPU_1_1 == function_id) || (ADC_GPU_VOLT2_1_1 == function_id)) && + (G_first_sys_gpu_config & 0x10) ) || + ( ( ADC_GPU_1_2 == function_id) && + (G_first_sys_gpu_config & 0x20) ) ) + { + // GPU is present + include = TRUE; + } + } + else + { + // non-GPU channel + include = TRUE; + } + if (include) { l_pwrSensorList[l_sensorHeader.count].id = G_amec_sensor_list[PWRAPSSCH0 + k]->ipmi_sid; - l_pwrSensorList[l_sensorHeader.count].function_id = G_apss_ch_to_function[k]; + l_pwrSensorList[l_sensorHeader.count].function_id = function_id; l_pwrSensorList[l_sensorHeader.count].apss_channel = k; l_pwrSensorList[l_sensorHeader.count].reserved = 0; l_pwrSensorList[l_sensorHeader.count].current = G_amec_sensor_list[PWRAPSSCH0 + k]->sample; diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c index 920b88e..23f9b29 100755 --- a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c +++ b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2018 */ +/* Contributors Listed Below - COPYRIGHT 2011,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -113,6 +113,10 @@ cmdh_ips_config_data_t G_ips_config_data = {0}; bool G_mem_monitoring_allowed = FALSE; +// Save which voltage the GPU is using (1 = default (12V), 2 = 2nd voltage (54V)) +uint8_t G_gpu_volt_type[MAX_GPU_DOMAINS][MAX_NUM_GPU_PER_DOMAIN] = {{0}}; +bool G_found_volt2 = FALSE; + // Will get set when receiving APSS config data PWR_READING_TYPE G_pwr_reading_type = PWR_READING_TYPE_NONE; @@ -545,6 +549,7 @@ errlHndl_t data_store_freq_data(const cmdh_fsp_cmd_t * i_cmd_ptr, errlHndl_t apss_store_adc_channel(const eApssAdcChannelAssignments i_func_id, const uint8_t i_channel_num ) { errlHndl_t l_err = NULL; + bool l_gpu_volt_conflict = FALSE; // Check function ID and channel number if ( (i_func_id >= NUM_ADC_ASSIGNMENT_TYPES) || @@ -635,6 +640,10 @@ errlHndl_t apss_store_adc_channel(const eApssAdcChannelAssignments i_func_id, co l_adc_function = &G_sysConfigData.apss_adc_map.sense_12v; break; + case ADC_VOLT_SENSE_2: + l_adc_function = &G_sysConfigData.apss_adc_map.sense_volt2; + break; + case ADC_GND_REMOTE_SENSE: l_adc_function = &G_sysConfigData.apss_adc_map.remote_gnd; break; @@ -643,6 +652,10 @@ errlHndl_t apss_store_adc_channel(const eApssAdcChannelAssignments i_func_id, co l_adc_function = &G_sysConfigData.apss_adc_map.total_current_12v; break; + case ADC_TOTAL_SYS_CURRENT_2: + l_adc_function = &G_sysConfigData.apss_adc_map.total_current_volt2; + break; + case ADC_MEM_CACHE: l_adc_function = &G_sysConfigData.apss_adc_map.mem_cache; break; @@ -652,11 +665,27 @@ errlHndl_t apss_store_adc_channel(const eApssAdcChannelAssignments i_func_id, co break; case ADC_GPU_0_0: - l_adc_function = &G_sysConfigData.apss_adc_map.gpu[0][0]; + if (G_gpu_volt_type[0][0] != 2) + { + G_gpu_volt_type[0][0] = 1; + l_adc_function = &G_sysConfigData.apss_adc_map.gpu[0][0]; + } + else + { + l_gpu_volt_conflict = TRUE; + } break; case ADC_GPU_0_1: - l_adc_function = &G_sysConfigData.apss_adc_map.gpu[0][1]; + if (G_gpu_volt_type[0][1] != 2) + { + G_gpu_volt_type[0][1] = 1; + l_adc_function = &G_sysConfigData.apss_adc_map.gpu[0][1]; + } + else + { + l_gpu_volt_conflict = TRUE; + } break; case ADC_GPU_0_2: @@ -664,17 +693,85 @@ errlHndl_t apss_store_adc_channel(const eApssAdcChannelAssignments i_func_id, co break; case ADC_GPU_1_0: - l_adc_function = &G_sysConfigData.apss_adc_map.gpu[1][0]; + if (G_gpu_volt_type[1][0] != 2) + { + G_gpu_volt_type[1][0] = 1; + l_adc_function = &G_sysConfigData.apss_adc_map.gpu[1][0]; + } + else + { + l_gpu_volt_conflict = TRUE; + } break; case ADC_GPU_1_1: - l_adc_function = &G_sysConfigData.apss_adc_map.gpu[1][1]; + if (G_gpu_volt_type[1][1] != 2) + { + G_gpu_volt_type[1][1] = 1; + l_adc_function = &G_sysConfigData.apss_adc_map.gpu[1][1]; + } + else + { + l_gpu_volt_conflict = TRUE; + } break; case ADC_GPU_1_2: l_adc_function = &G_sysConfigData.apss_adc_map.gpu[1][2]; break; + case ADC_GPU_VOLT2_0_0: + if (G_gpu_volt_type[0][0] != 1) + { + G_found_volt2 = TRUE; + G_gpu_volt_type[0][0] = 2; + l_adc_function = &G_sysConfigData.apss_adc_map.gpu[0][0]; + } + else + { + l_gpu_volt_conflict = TRUE; + } + break; + + case ADC_GPU_VOLT2_0_1: + if (G_gpu_volt_type[0][1] != 1) + { + G_found_volt2 = TRUE; + G_gpu_volt_type[0][1] = 2; + l_adc_function = &G_sysConfigData.apss_adc_map.gpu[0][1]; + } + else + { + l_gpu_volt_conflict = TRUE; + } + break; + + case ADC_GPU_VOLT2_1_0: + if (G_gpu_volt_type[1][0] != 1) + { + G_found_volt2 = TRUE; + G_gpu_volt_type[1][0] = 2; + l_adc_function = &G_sysConfigData.apss_adc_map.gpu[1][0]; + } + else + { + l_gpu_volt_conflict = TRUE; + } + break; + + case ADC_GPU_VOLT2_1_1: + if (G_gpu_volt_type[1][1] != 1) + { + G_found_volt2 = TRUE; + G_gpu_volt_type[1][1] = 2; + l_adc_function = &G_sysConfigData.apss_adc_map.gpu[1][1]; + } + else + { + l_gpu_volt_conflict = TRUE; + } + break; + default: // It should never happen CMDH_TRAC_ERR("apss_store_adc_channel: Invalid function ID: 0x%x", i_func_id); @@ -693,7 +790,6 @@ errlHndl_t apss_store_adc_channel(const eApssAdcChannelAssignments i_func_id, co } else { - CMDH_TRAC_ERR("apss_store_adc_channel: Function ID is duplicated (id:0x%x, channel:%d)", i_func_id, i_channel_num); /* @ @@ -721,6 +817,33 @@ errlHndl_t apss_store_adc_channel(const eApssAdcChannelAssignments i_func_id, co ERRL_CALLOUT_PRIORITY_HIGH); } } + else if (l_gpu_volt_conflict) + { + CMDH_TRAC_ERR("apss_store_adc_channel: GPU has conflicting voltage function ids (0x%02X)", i_func_id); + /* @ + * @errortype + * @moduleid DATA_STORE_APSS_DATA + * @reasoncode INVALID_INPUT_DATA + * @userdata1 function ID + * @userdata2 channel number + * @userdata4 ERC_APSS_GPU_VOLTAGE_CONFLICT + * @devdesc Function ID conflict for GPU voltage + */ + l_err = createErrl(DATA_STORE_APSS_DATA, + INVALID_INPUT_DATA, + ERC_APSS_GPU_VOLTAGE_CONFLICT, + ERRL_SEV_UNRECOVERABLE, + NULL, + DEFAULT_TRACE_SIZE, + (uint32_t)i_func_id, + (uint32_t)i_channel_num); + + // Callout firmware + addCalloutToErrl(l_err, + ERRL_CALLOUT_TYPE_COMPONENT_ID, + ERRL_COMPONENT_ID_FIRMWARE, + ERRL_CALLOUT_PRIORITY_HIGH); + } } return l_err; @@ -780,6 +903,7 @@ void apss_store_ipmi_sensor_id(const uint16_t i_channel, const apss_cfg_adc_v20_ break; case ADC_12V_SENSE: + case ADC_VOLT_SENSE_2: //None break; @@ -788,6 +912,7 @@ void apss_store_ipmi_sensor_id(const uint16_t i_channel, const apss_cfg_adc_v20_ break; case ADC_TOTAL_SYS_CURRENT: + case ADC_TOTAL_SYS_CURRENT_2: //None break; @@ -802,6 +927,8 @@ void apss_store_ipmi_sensor_id(const uint16_t i_channel, const apss_cfg_adc_v20_ case ADC_GPU_0_0: case ADC_GPU_0_1: case ADC_GPU_0_2: + case ADC_GPU_VOLT2_0_0: + case ADC_GPU_VOLT2_0_1: if((i_adc->ipmisensorId != 0) && (l_proc == 0)) { AMECSENSOR_PTR(PWRGPU)->ipmi_sid = i_adc->ipmisensorId; @@ -811,6 +938,8 @@ void apss_store_ipmi_sensor_id(const uint16_t i_channel, const apss_cfg_adc_v20_ case ADC_GPU_1_0: case ADC_GPU_1_1: case ADC_GPU_1_2: + case ADC_GPU_VOLT2_1_0: + case ADC_GPU_VOLT2_1_1: if((i_adc->ipmisensorId != 0) && (l_proc == 1)) { AMECSENSOR_PTR(PWRGPU)->ipmi_sid = i_adc->ipmisensorId; @@ -833,9 +962,11 @@ void apss_store_ipmi_sensor_id(const uint16_t i_channel, const apss_cfg_adc_v20_ //no sensor IDs to be reported in the poll command. } - //Only store sensor ids for power sensors. 12V sensor and gnd remote sensors do not report power used. - if ((i_adc->assignment != ADC_12V_SENSE) && (i_adc->assignment != ADC_GND_REMOTE_SENSE) && - (i_adc->assignment != ADC_12V_STANDBY_CURRENT)) + //Only store sensor ids for power sensors. voltage and gnd remote sensors do not report power used. + if ((i_adc->assignment != ADC_12V_SENSE) && + (i_adc->assignment != ADC_GND_REMOTE_SENSE) && + (i_adc->assignment != ADC_12V_STANDBY_CURRENT) && + (i_adc->assignment != ADC_VOLT_SENSE_2)) { AMECSENSOR_PTR(PWRAPSSCH0 + i_channel)->ipmi_sid = i_adc->ipmisensorId; CNFG_DBG("apss_store_ipmi_sensor_id: SID[0x%08X] stored as 0x%08X for channel %d", @@ -1027,6 +1158,7 @@ errlHndl_t data_store_apss_config_v20(const cmdh_apss_config_v20_t * i_cmd_ptr, G_pwr_reading_type = PWR_READING_TYPE_NONE; } + bool l_found_volt2_sense = FALSE; for(l_channel=0;(l_channel < l_num_channels) && (NULL == l_err);l_channel++) { G_sysConfigData.apss_cal[l_channel].gnd_select = i_cmd_ptr->adc[l_channel].gnd_select; @@ -1037,6 +1169,11 @@ errlHndl_t data_store_apss_config_v20(const cmdh_apss_config_v20_t * i_cmd_ptr, l_err = apss_store_adc_channel(i_cmd_ptr->adc[l_channel].assignment, l_channel); if (l_err == NULL) { + if (i_cmd_ptr->adc[l_channel].assignment == ADC_VOLT_SENSE_2) + { + l_found_volt2_sense = TRUE; + } + //Write sensor IDs to the appropriate powr sensors. apss_store_ipmi_sensor_id(l_channel, &(i_cmd_ptr->adc[l_channel])); @@ -1054,6 +1191,31 @@ errlHndl_t data_store_apss_config_v20(const cmdh_apss_config_v20_t * i_cmd_ptr, G_sysConfigData.apss_cal[l_channel].offset); } + if ((NULL == l_err) && G_found_volt2 && (!l_found_volt2_sense)) + { + CMDH_TRAC_ERR("data_store_apss_config_v20: Found GPU using 2nd voltage but no ADC_VOLT_SENSE_2 supplied"); + /* @ + * @errortype + * @moduleid DATA_STORE_APSS_DATA + * @reasoncode INVALID_INPUT_DATA + * @userdata4 ERC_APSS_MISSING_ADC_VOLT_SENSE_2 + * @devdesc ADC_VOLT_SENSE_2 was not provided + */ + l_err = createErrl(DATA_STORE_APSS_DATA, + INVALID_INPUT_DATA, + ERC_APSS_MISSING_ADC_VOLT_SENSE_2, + ERRL_SEV_UNRECOVERABLE, + NULL, + DEFAULT_TRACE_SIZE, + 0, + 0); + // Callout firmware + addCalloutToErrl(l_err, + ERRL_CALLOUT_TYPE_COMPONENT_ID, + ERRL_COMPONENT_ID_FIRMWARE, + ERRL_CALLOUT_PRIORITY_HIGH); + } + if( (NULL == l_err) && (G_pwr_reading_type == PWR_READING_TYPE_APSS) ) // only APSS has GPIO config { @@ -1094,9 +1256,11 @@ errlHndl_t data_store_apss_config(const cmdh_fsp_cmd_t * i_cmd_ptr, uint32_t l_v20_data_sz = sizeof(cmdh_apss_config_v20_t) - sizeof(cmdh_fsp_cmd_header_t); - // Set to default value + // Set to default values memset(&G_sysConfigData.apss_adc_map, SYSCFG_INVALID_ADC_CHAN, sizeof(G_sysConfigData.apss_adc_map)); memset(&G_sysConfigData.apss_gpio_map, SYSCFG_INVALID_PIN, sizeof(G_sysConfigData.apss_gpio_map)); + memset(G_gpu_volt_type, 0, sizeof(G_gpu_volt_type)); + G_found_volt2 = FALSE; // only version 0x20 supported and data length must be at least 4 if( (l_cmd_ptr->version != DATA_APSS_VERSION20) || (l_data_length < 4)) @@ -1126,7 +1290,7 @@ errlHndl_t data_store_apss_config(const cmdh_fsp_cmd_t * i_cmd_ptr, if(l_invalid_data) { G_pwr_reading_type = PWR_READING_TYPE_NONE; - CMDH_TRAC_ERR("data_store_apss_config: Invalid System Data packet. Given Version:0x%02X length:0x%04X", + CMDH_TRAC_ERR("data_store_apss_config: Invalid APSS Config Data packet. Given Version:0x%02X length:0x%04X", l_cmd_ptr->version, l_data_length); /* @ diff --git a/src/occ_405/occ_service_codes.h b/src/occ_405/occ_service_codes.h index 59e7ce9..d54244e 100644 --- a/src/occ_405/occ_service_codes.h +++ b/src/occ_405/occ_service_codes.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2018 */ +/* Contributors Listed Below - COPYRIGHT 2011,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -202,6 +202,9 @@ enum occExtReasonCode ERC_AMEC_CENT_TEMP_TIMEOUT = 0x0032, ERC_AMEC_GPE1_TIMEOUT = 0x0033, + ERC_APSS_MISSING_ADC_VOLT_SENSE_2 = 0x0038, + ERC_APSS_GPU_VOLTAGE_CONFLICT = 0x0039, + ERC_CMDH_MBOX_REQST_FAILURE = 0x0040, ERC_CMDH_INTERNAL_FAILURE = 0x0041, ERC_CMDH_THRM_DATA_MISSING = 0x0042, diff --git a/src/occ_405/occ_sys_config.c b/src/occ_405/occ_sys_config.c index 7255246..9b11da3 100755 --- a/src/occ_405/occ_sys_config.c +++ b/src/occ_405/occ_sys_config.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2017 */ +/* Contributors Listed Below - COPYRIGHT 2011,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -152,6 +152,8 @@ occSysConfigData_t G_sysConfigData = .gpu[1][0] = SYSCFG_INVALID_ADC_CHAN, .gpu[1][1] = SYSCFG_INVALID_ADC_CHAN, .gpu[1][2] = SYSCFG_INVALID_ADC_CHAN, + .sense_volt2 = SYSCFG_INVALID_ADC_CHAN, + .total_current_volt2 = SYSCFG_INVALID_ADC_CHAN, }, .apssGpioPortsMode = {0, 0}, diff --git a/src/occ_405/occ_sys_config.h b/src/occ_405/occ_sys_config.h index 0b16aa5..33ea0be 100755 --- a/src/occ_405/occ_sys_config.h +++ b/src/occ_405/occ_sys_config.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2017 */ +/* Contributors Listed Below - COPYRIGHT 2011,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -148,6 +148,12 @@ typedef enum ADC_GPU_1_0 = 0x1F, ADC_GPU_1_1 = 0x20, ADC_GPU_1_2 = 0x21, + ADC_GPU_VOLT2_0_0 = 0x22, + ADC_GPU_VOLT2_0_1 = 0x23, + ADC_GPU_VOLT2_1_0 = 0x24, + ADC_GPU_VOLT2_1_1 = 0x25, + ADC_VOLT_SENSE_2 = 0x26, + ADC_TOTAL_SYS_CURRENT_2 = 0x27, NUM_ADC_ASSIGNMENT_TYPES // This should always be the last member } eApssAdcChannelAssignments; @@ -225,6 +231,8 @@ typedef struct uint8_t mem_cache; uint8_t current_12v_stby; uint8_t gpu[MAX_GPU_DOMAINS][MAX_NUM_GPU_PER_DOMAIN]; + uint8_t sense_volt2; + uint8_t total_current_volt2; } apssAdcChannelData_t; typedef struct |