diff --git a/common/dev/include/mp29816a.h b/common/dev/include/mp29816a.h index 44807240cd..68823a7c19 100644 --- a/common/dev/include/mp29816a.h +++ b/common/dev/include/mp29816a.h @@ -24,6 +24,8 @@ bool mp29816a_get_vout_max(sensor_cfg *cfg, uint8_t rail, uint16_t *millivolt); bool mp29816a_get_vout_min(sensor_cfg *cfg, uint8_t rail, uint16_t *millivolt); bool mp29816a_set_vout_max(sensor_cfg *cfg, uint8_t rail, uint16_t *millivolt); bool mp29816a_set_vout_min(sensor_cfg *cfg, uint8_t rail, uint16_t *millivolt); +bool mp29816a_get_iout_oc_warn_limit(sensor_cfg *cfg, uint16_t *value); +bool mp29816a_set_iout_oc_warn_limit(sensor_cfg *cfg, uint16_t value); bool mp29816a_fwupdate(uint8_t bus, uint8_t addr, uint8_t *img_buff, uint32_t img_size); bool mp29816a_get_vout_command(sensor_cfg *cfg, uint8_t rail, uint16_t *millivolt); bool mp29816a_set_vout_command(sensor_cfg *cfg, uint8_t rail, uint16_t *millivolt); diff --git a/common/dev/include/raa228249.h b/common/dev/include/raa228249.h index 45dfdc839b..630c9d7f4b 100644 --- a/common/dev/include/raa228249.h +++ b/common/dev/include/raa228249.h @@ -28,6 +28,8 @@ int raa228249_get_remaining_wr(uint8_t bus, uint8_t addr, uint8_t *remain); bool raa228249_fwupdate(uint8_t bus, uint8_t addr, uint8_t *img_buff, uint32_t img_size); bool raa228249_get_vout_command(sensor_cfg *cfg, uint8_t rail, uint16_t *millivolt); bool raa228249_set_vout_command(sensor_cfg *cfg, uint8_t rail, uint16_t *millivolt); +bool raa228249_get_iout_oc_warn_limit(sensor_cfg *cfg, uint16_t *value); +bool raa228249_set_iout_oc_warn_limit(sensor_cfg *cfg, uint16_t value); bool raa228249_get_vr_status(sensor_cfg *cfg, uint8_t rail, uint8_t vr_status_rail, uint16_t *vr_status); bool raa228249_clear_vr_status(sensor_cfg *cfg, uint8_t rail); diff --git a/common/dev/include/tmp431.h b/common/dev/include/tmp431.h index ddb750214c..78d79f15e3 100644 --- a/common/dev/include/tmp431.h +++ b/common/dev/include/tmp431.h @@ -20,6 +20,7 @@ #include "sensor.h" bool tmp432_get_temp_status(sensor_cfg *cfg, uint8_t *temp_status); +bool tmp432_get_temp_open_status(sensor_cfg *cfg, uint8_t *temp_status); bool tmp432_clear_temp_status(sensor_cfg *cfg); enum TMP431_CHANNELS { diff --git a/common/dev/mp29816a.c b/common/dev/mp29816a.c index ec9e416d09..e421d08b60 100644 --- a/common/dev/mp29816a.c +++ b/common/dev/mp29816a.c @@ -38,6 +38,7 @@ LOG_MODULE_REGISTER(mp29816a); #define MP29816A_VOUT_MAX_REG 0x24 #define MP29816A_VOUT_MIN_REG 0x2B +#define MP29816A_SVI3_IOUT_RPT_REG 0x67 /* --------- PAGE1 ---------- */ #define VR_REG_EXPECTED_USER_CRC 0xED @@ -319,6 +320,74 @@ bool mp29816a_set_vout_min(sensor_cfg *cfg, uint8_t rail, uint16_t *millivolt) return true; } +bool mp29816a_get_iout_oc_warn_limit(sensor_cfg *cfg, uint16_t *value) +{ + CHECK_NULL_ARG_WITH_RETURN(cfg, false); + CHECK_NULL_ARG_WITH_RETURN(value, false); + + uint8_t data[2] = { 0 }; + uint8_t scale_bit = 0; + if (!mp29816a_i2c_read(cfg->port, cfg->target_addr, MP29816A_SVI3_IOUT_RPT_REG, data, + sizeof(data))) { + return false; + } + scale_bit = data[0] & 0x07; + + if (!mp29816a_i2c_read(cfg->port, cfg->target_addr, PMBUS_IOUT_OC_WARN_LIMIT, data, + sizeof(data))) { + return false; + } + + // final value: 8 * data * scale_bit + if (scale_bit == 7) { + // 2A for scale_bit + *value = 8 * (data[0] | (data[1] << 8)) * 2; + } else if (scale_bit < 6 && scale_bit > 0) { + // 1/32, 1/16, 1/8 ... + *value = 8 * (data[0] | (data[1] << 8)) / (2 ^ (6 - scale_bit)); + } else { + // 1A + *value = 8 * (data[0] | (data[1] << 8)); + } + + return true; +} + +bool mp29816a_set_iout_oc_warn_limit(sensor_cfg *cfg, uint16_t value) +{ + CHECK_NULL_ARG_WITH_RETURN(cfg, false); + + uint8_t data[2] = { 0 }; + uint8_t scale_bit = 0; + if (!mp29816a_i2c_read(cfg->port, cfg->target_addr, MP29816A_SVI3_IOUT_RPT_REG, data, + sizeof(data))) { + return false; + } + scale_bit = data[0] & 0x07; + + // final value: (data / scale_bit) / 8 + if (scale_bit == 7) { + // 2A for scale_bit + value = (value / 2) / 8; + } else if (scale_bit < 6 && scale_bit > 0) { + // 1/32, 1/16, 1/8 ... + value = (value * (2 ^ (6 - scale_bit))) / 8; + } else { + // 1A + value = value / 8; + } + + data[0] = value & 0xFF; + data[1] = value >> 8; + + if (!mp29816a_i2c_write(cfg->port, cfg->target_addr, PMBUS_IOUT_OC_WARN_LIMIT, data, + sizeof(data))) { + return false; + } + + return true; +} + static uint8_t mp29816a_do_update(struct cfg_data *cfg_data_list, uint32_t cfg_cnt, uint8_t bus, uint8_t addr) { diff --git a/common/dev/raa228249.c b/common/dev/raa228249.c index 850fe72d74..14b056b7f9 100644 --- a/common/dev/raa228249.c +++ b/common/dev/raa228249.c @@ -519,6 +519,40 @@ bool raa228249_set_vout_command(sensor_cfg *cfg, uint8_t rail, uint16_t *millivo return true; } +bool raa228249_get_iout_oc_warn_limit(sensor_cfg *cfg, uint16_t *value) +{ + CHECK_NULL_ARG_WITH_RETURN(cfg, false); + CHECK_NULL_ARG_WITH_RETURN(value, false); + + uint8_t data[2] = { 0 }; + if (!raa228249_i2c_read(cfg->port, cfg->target_addr, PMBUS_IOUT_OC_WARN_LIMIT, data, + sizeof(data))) { + return false; + } + + // 1 unit = 0.1A + *value = (data[0] | (data[1] << 8)) * 0.1; + return true; +} + +bool raa228249_set_iout_oc_warn_limit(sensor_cfg *cfg, uint16_t value) +{ + CHECK_NULL_ARG_WITH_RETURN(cfg, false); + + /* input value unit: 1A */ + uint8_t data[2] = { 0 }; + uint16_t cal_value = value * 10; + data[0] = cal_value & 0xFF; + data[1] = cal_value >> 8; + + if (!raa228249_i2c_write(cfg->port, cfg->target_addr, PMBUS_IOUT_OC_WARN_LIMIT, data, + sizeof(data))) { + return false; + } + + return true; +} + bool raa228249_get_vr_status(sensor_cfg *cfg, uint8_t rail, uint8_t vr_status_rail, uint16_t *vr_status) { diff --git a/common/dev/tmp431.c b/common/dev/tmp431.c index 9ea715702e..55bd68ca86 100644 --- a/common/dev/tmp431.c +++ b/common/dev/tmp431.c @@ -406,6 +406,28 @@ bool tmp432_get_temp_status(sensor_cfg *cfg, uint8_t *temp_status) return true; } +bool tmp432_get_temp_open_status(sensor_cfg *cfg, uint8_t *temp_status) +{ + CHECK_NULL_ARG_WITH_RETURN(cfg, false); + + I2C_MSG i2c_msg = { 0 }; + uint8_t retry = 5; + i2c_msg.bus = cfg->port; + i2c_msg.target_addr = cfg->target_addr; + i2c_msg.tx_len = 1; + i2c_msg.rx_len = 1; + i2c_msg.data[0] = TMP432_OPEN_STATUS_REG; + + if (i2c_master_read(&i2c_msg, retry)) { + LOG_ERR("TMP[0x%x] get open status reg[0x%d] failed.", cfg->num, + TMP432_OPEN_STATUS_REG); + return false; + } + *temp_status = i2c_msg.data[0]; + + return true; +} + bool tmp432_clear_temp_status(sensor_cfg *cfg) { CHECK_NULL_ARG_WITH_RETURN(cfg, false); diff --git a/common/service/pldm/pldm_monitor.h b/common/service/pldm/pldm_monitor.h index dc7160618e..cee19f193b 100644 --- a/common/service/pldm/pldm_monitor.h +++ b/common/service/pldm/pldm_monitor.h @@ -88,7 +88,8 @@ enum pldm_sensor_operational_state { PLDM_SENSOR_FAILED, PLDM_SENSOR_INITIALIZING, PLDM_SENSOR_SHUTTINGDOWN, - PLDM_SENSOR_INTEST + PLDM_SENSOR_INTEST, + PLDM_SENSOR_OPEN_CIRCUIT, }; enum pldm_effecter_operational_state { diff --git a/common/service/pldm/pldm_oem.h b/common/service/pldm/pldm_oem.h index 6587a3c830..9586b2be4b 100644 --- a/common/service/pldm/pldm_oem.h +++ b/common/service/pldm/pldm_oem.h @@ -195,6 +195,8 @@ enum iris_event_source { IRIS_OWL_W_TRVDD0P75, IRIS_HAMSA_AVDD_PCIE, IRIS_HAMSA_VDDHRXTX_PCIE, + IRIS_4V2, + IRIS_P0V75_AVDD_HCSL, // VR Power Fault 2 IRIS_MEDHA1_VDD, IRIS_MEDHA0_VDD, diff --git a/common/service/sensor/pldm_sensor.c b/common/service/sensor/pldm_sensor.c index 00f60ed577..1973d3a739 100644 --- a/common/service/sensor/pldm_sensor.c +++ b/common/service/sensor/pldm_sensor.c @@ -303,7 +303,10 @@ void pldm_sensor_get_reading(sensor_cfg *pldm_sensor_cfg, uint32_t *update_time, if (pldm_sensor_cfg->post_sensor_read_hook) { if (!pldm_sensor_cfg->post_sensor_read_hook( pldm_sensor_cfg, pldm_sensor_cfg->post_sensor_read_args, &reading)) { - pldm_sensor_cfg->cache_status = PLDM_SENSOR_FAILED; + if (pldm_sensor_cfg->cache_status == SENSOR_OPEN_CIRCUIT) + pldm_sensor_cfg->cache_status = PLDM_SENSOR_OPEN_CIRCUIT; + else + pldm_sensor_cfg->cache_status = PLDM_SENSOR_FAILED; *update_time_ms = k_uptime_get_32(); *update_time = (*update_time_ms / 1000); LOG_DBG("Failed to pose read sensor_num 0x%x of thread %d", sensor_num, diff --git a/common/service/sensor/sensor.h b/common/service/sensor/sensor.h index 04693b4d69..6aea0fe1b4 100644 --- a/common/service/sensor/sensor.h +++ b/common/service/sensor/sensor.h @@ -256,6 +256,7 @@ enum { SENSOR_PEC_ERROR, SENSOR_PARAMETER_NOT_VALID, SENSOR_UNAVAILABLE, + SENSOR_OPEN_CIRCUIT, }; enum { SENSOR_INIT_SUCCESS, SENSOR_INIT_UNSPECIFIED_ERROR }; diff --git a/common/shell/commands/sensor_shell.c b/common/shell/commands/sensor_shell.c index b6cbdd6014..7dea06c040 100644 --- a/common/shell/commands/sensor_shell.c +++ b/common/shell/commands/sensor_shell.c @@ -59,6 +59,8 @@ const char *const sensor_status_name[] = { "sensor_not_present", "pec_error", "parameter_not_valid", + "unavailable", + "open_circuit", }; #ifdef ENABLE_PLDM_SENSOR @@ -71,6 +73,7 @@ const char *const pldm_sensor_status_name[] = { "sensor_initializing", "sensor_shuttingdown", "sensor_intest", + "sensor_open_circuit", }; #endif // clang-format on diff --git a/meta-facebook/sb-rb/boards/npcm400f_evb.conf b/meta-facebook/sb-rb/boards/npcm400f_evb.conf index 01f9f73baa..7f528cce57 100644 --- a/meta-facebook/sb-rb/boards/npcm400f_evb.conf +++ b/meta-facebook/sb-rb/boards/npcm400f_evb.conf @@ -9,18 +9,19 @@ CONFIG_PECI_NPCM4XX=n CONFIG_SPI_NPCM4XX_SPIM=y CONFIG_SPI_NPCM4XX_FIU=y CONFIG_SPIP_NPCM4XX=y -CONFIG_ESPI_NPCM4XX=y -CONFIG_IPMI_KCS_NPCM4XX=y +CONFIG_ESPI_NPCM4XX=n +CONFIG_IPMI_KCS_NPCM4XX=n CONFIG_I2C_NPCM4XX=y CONFIG_I3C_NPCM4XX=y -CONFIG_ADC_NPCM4XX=y -CONFIG_USB_DC_NPCM4XX=y -CONFIG_JTAG_NPCM4XX=y +CONFIG_ADC_NPCM4XX=n +CONFIG_USB_DC_NPCM4XX=n +CONFIG_JTAG_NPCM4XX=n # I3C More actions CONFIG_I3C=y CONFIG_I3C_SLAVE=y CONFIG_I3C_SLAVE_MQUEUE=y +CONFIG_I3C_SHELL=n # PWM Driver CONFIG_PWM=y diff --git a/meta-facebook/sb-rb/boards/npcm400f_evb.overlay b/meta-facebook/sb-rb/boards/npcm400f_evb.overlay index db98e5d4ca..d355a70f53 100644 --- a/meta-facebook/sb-rb/boards/npcm400f_evb.overlay +++ b/meta-facebook/sb-rb/boards/npcm400f_evb.overlay @@ -3,7 +3,7 @@ }; &adc0 { - status = "okay"; + status = "disabled"; }; &uart0 { diff --git a/meta-facebook/sb-rb/prj.conf b/meta-facebook/sb-rb/prj.conf index 02490c9ebe..630fa46b38 100644 --- a/meta-facebook/sb-rb/prj.conf +++ b/meta-facebook/sb-rb/prj.conf @@ -24,14 +24,14 @@ CONFIG_I2C=y CONFIG_THREAD_RUNTIME_STATS=y CONFIG_GPIO_SHELL=y CONFIG_I2C_SLAVE=y -CONFIG_I2C_EEPROM_SLAVE=y -CONFIG_I2C_IPMB_SLAVE=y -CONFIG_ADC=y +CONFIG_I2C_EEPROM_SLAVE=n +CONFIG_I2C_IPMB_SLAVE=n +CONFIG_ADC=n CONFIG_FLASH=y CONFIG_FLASH_SHELL=y CONFIG_SENSOR=y CONFIG_HWINFO=y -CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE=153840 +CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE=143360 CONFIG_REBOOT=y CONFIG_POSIX_CLOCK=y CONFIG_STACK_SENTINEL=y diff --git a/meta-facebook/sb-rb/src/platform/plat_adc.c b/meta-facebook/sb-rb/src/platform/plat_adc.c index 155234b3ce..7930673b95 100644 --- a/meta-facebook/sb-rb/src/platform/plat_adc.c +++ b/meta-facebook/sb-rb/src/platform/plat_adc.c @@ -26,6 +26,7 @@ #include "util_sys.h" #include "plat_i2c_target.h" #include "plat_pldm_sensor.h" +#include "plat_power_capping.h" LOG_MODULE_REGISTER(plat_adc); @@ -37,9 +38,6 @@ LOG_MODULE_REGISTER(plat_adc); #define ADC_SPI_FREQ 6000000 -K_THREAD_STACK_DEFINE(adc_thread_stack, ADC_STACK_SIZE); -struct k_thread adc_poll_thread; - K_THREAD_STACK_DEFINE(adc_rainbow_thread_stack, ADC_STACK_SIZE); struct k_thread adc_rainbow_poll_thread; @@ -51,8 +49,8 @@ float ads7066_val_0 = 0; float ads7066_val_1 = 0; const float ads7066_vref = 2.5; const float ad4058_vref = 2.5; - -const struct spi_cs_control *cs_ctrl; +static uint8_t adc_good_status[2] = { 0xFF, 0xFF }; +static uint8_t final_ucr_status = 0; typedef struct { uint16_t avg_times; // 20ms at a time @@ -65,19 +63,28 @@ typedef struct { float pwr_avg_val; float vr_sum; bool ucr_status; // over current - struct k_work ucr_work; } adc_info_t; //MEDHA0: level 2 , level3 //MEDHA1: level 2 , level3 -adc_info_t adc_info[ADC_IDX_MAX] = { { .avg_times = 20, .ucr = 1255 }, - { .avg_times = 60, .ucr = 1255 }, - { .avg_times = 600, .ucr = 1255 }, - { .avg_times = 800, .ucr = 1255 } }; +adc_info_t adc_info[ADC_IDX_MAX] = { { .avg_times = 20, .ucr = 1600 }, + { .avg_times = 60, .ucr = 1600 }, + { .avg_times = 600, .ucr = 1070 }, + { .avg_times = 800, .ucr = 1070 } }; static const struct device *spi_dev; -static void adc_poll_init() +uint8_t get_adc_good_status(uint8_t idx) +{ + return adc_good_status[idx]; +} + +uint8_t get_final_ucr_status() +{ + return (final_ucr_status & 0xF0); +} + +void adc_poll_init() { for (uint8_t i = ADC_IDX_MEDHA0_1; i < ADC_IDX_MAX; i++) { adc_info[i].sum = 0; @@ -86,6 +93,7 @@ static void adc_poll_init() adc_info[i].vr_sum = 0; adc_info[i].pwr_avg_val = 0; memset(adc_info[i].buf, 0, sizeof(uint16_t) * ADC_AVERGE_TIMES_MAX); + memset(adc_info[i].vr_voltage_buf, 0, sizeof(uint16_t) * ADC_AVERGE_TIMES_MAX); } } @@ -151,39 +159,6 @@ float adc_raw_mv_to_apms(uint16_t v, float vref) return (get_vr_module() == VR_MODULE_MPS) ? 1000 * temp_v * 0.796 : 1000 * temp_v * 0.797; } -static bool adc_ucr_handler(uint8_t idx, bool state) // state is ucr or not -{ - uint8_t data = 0; - if (!plat_read_cpld(CPLD_OFFSET_POWER_CLAMP, &data, 1)) - return false; - - uint8_t bit = (idx == ADC_IDX_MEDHA0_1) ? 7 : - (idx == ADC_IDX_MEDHA1_1) ? 6 : - (idx == ADC_IDX_MEDHA0_2) ? 5 : - (idx == ADC_IDX_MEDHA1_2) ? 4 : - 0xFF; - if (bit == 0xFF) - return false; - - // if ucr, pull up - if (state) - data |= (1 << bit); - else - data &= ~(1 << bit); - - if (!plat_write_cpld(CPLD_OFFSET_POWER_CLAMP, &data)) - return false; - - return true; -} -static void adc_ucr_work_handler(struct k_work *work) -{ - const adc_info_t *adc = CONTAINER_OF(work, adc_info_t, ucr_work); - - uint8_t idx = adc - adc_info; - adc_ucr_handler(idx, adc->ucr_status); -} - uint16_t float_voltage_transfer_to_uint16(float temp_voltage_value) { // Upper:ex. 0.85 → 85 @@ -206,7 +181,6 @@ float uint16_voltage_transfer_to_float(uint16_t temp_voltage_value) float restored = upper_val + lower_val; return restored; } -K_WORK_DEFINE(adc_ucr_work, adc_ucr_work_handler); static void update_adc_info(uint16_t raw_data, uint8_t base_idx, float vref) { @@ -247,9 +221,44 @@ static void update_adc_info(uint16_t raw_data, uint8_t base_idx, float vref) // check status bool pwr_status = (adc->pwr_avg_val >= adc->ucr); - if (adc->ucr_status != pwr_status) { - adc->ucr_status = pwr_status; - k_work_submit(&adc->ucr_work); + adc->ucr_status = pwr_status; + if (pwr_status) { + final_ucr_status |= (1 << (7 - i)); + } else { + final_ucr_status &= ~(1 << (7 - i)); + } + } +} + +static void update_vr_base_power_info() +{ + float float_value = 0; + uint16_t val_medha0 = 0; + uint16_t val_medha1 = 0; + float_value = get_sensor_reading_cache_as_float(SENSOR_NUM_ASIC_P0V85_MEDHA0_VDD_PWR_W); + val_medha0 = (float_value + 500) / 1000; + float_value = get_sensor_reading_cache_as_float(SENSOR_NUM_ASIC_P0V85_MEDHA1_VDD_PWR_W); + val_medha1 = (float_value + 500) / 1000; + + for (uint8_t i = 0; i < ADC_IDX_MAX; i++) { + adc_info_t *adc = &adc_info[i]; + adc->sum -= adc->buf[adc->buf_idx]; + adc->buf[adc->buf_idx] = ((i == ADC_IDX_MEDHA0_1) || (i == ADC_IDX_MEDHA0_2)) ? + val_medha0 : + val_medha1; + adc->sum += adc->buf[adc->buf_idx]; + adc->avg_val = adc->sum / adc->avg_times; + + // decrease buffer idx + adc->buf_idx = (adc->buf_idx + 1) % adc->avg_times; + + // check status + bool pwr_status = (adc->avg_val >= adc->ucr); + adc->ucr_status = pwr_status; + if (pwr_status) { + final_ucr_status |= (1 << (7 - i)); + } else { + final_ucr_status &= ~(1 << (7 - i)); } } } @@ -281,7 +290,7 @@ float get_adc_vr_pwr(uint8_t idx) { return adc_info[idx].pwr_avg_val; } -int ads7066_read_reg(uint8_t reg, uint8_t idx) +int ads7066_read_reg(uint8_t reg, uint8_t idx, uint8_t *out_data) { spi_dev = device_get_binding("SPIP"); if (!spi_dev) { @@ -337,6 +346,7 @@ int ads7066_read_reg(uint8_t reg, uint8_t idx) return ret; } + *out_data = rx_buf[0]; LOG_INF("medha%d ADS7066 read reg 0x%02x: 0x%02x 0x%02x 0x%02x", idx, reg, rx_buf[0], rx_buf[1], rx_buf[2]); return 0; @@ -460,7 +470,7 @@ static void ads7066_read_voltage(uint8_t idx) return; } -int ad4058_read_reg(uint8_t reg, uint8_t idx) +int ad4058_read_reg(uint8_t reg, uint8_t idx, uint8_t *out_data) { spi_dev = device_get_binding("SPIP"); if (!spi_dev) { @@ -517,6 +527,7 @@ int ad4058_read_reg(uint8_t reg, uint8_t idx) return ret; } + *out_data = rx_buf[1]; LOG_HEXDUMP_INF(rx_buf, 3, "ad4058_read_reg"); return 0; } @@ -660,18 +671,6 @@ static void ad4058_read_voltage(uint8_t idx) return; } -void get_ads7066_voltage() -{ - printk(" ads7066 medha0 voltage is %f V\n", ads7066_val_0); - printk(" ads7066 medha1 voltage is %f V\n", ads7066_val_1); -} - -void get_ad4058_voltage() -{ - printk(" ad4058 medha0 voltage is %f V\n", ad4058_val_0); - printk(" ad4058 medha1 voltage is %f V\n", ad4058_val_1); -} - void ads7066_mode_init() { //set auto-sequence mode @@ -686,6 +685,12 @@ void ads7066_mode_init() ads7066_write_reg(0x1, 0x82, i); ads7066_write_reg(0x12, 0x1, i); ads7066_write_reg(0x3, 0x6, i); + + //check and update good status + uint8_t value = 0; + ads7066_read_reg(0x3, i, &value); + adc_good_status[i] = (value & 0x07) == 0x06 ? 0 : 0xFF; + ads7066_write_reg(0x4, 0x8, i); ads7066_write_reg(0x10, 0x11, i); ads7066_write_reg(0x2, 0x10, i); @@ -702,6 +707,12 @@ void ad4058_mode_init() 3.33us * 256 = 0.8ms per sample */ for (int i = 0; i < ADC_RB_IDX_MAX; i++) { + // exit to config mode, check product id + ad4058_write_reg(0xA8, 0x00, i); + uint8_t value = 0; + ad4058_read_reg(0x03, i, &value); + adc_good_status[i] = (value & 0x0F) == 0x07 ? 0 : 0xFF; + ad4058_write_reg(0x27, 0x20, i); ad4058_write_reg(0x23, 0x7, i); ad4058_write_reg(0x21, 0x1, i); @@ -722,20 +733,24 @@ void adc_rainbow_polling_handler(void *p1, void *p2, void *p3) LOG_ERR("Invalid ADC index %d", adc_idx_read); while (1) { - if (adc_poll_flag) { - switch (adc_idx_read) { - case ADI_AD4058: - ad4058_read_voltage(ADC_RB_IDX_MEDHA0); - ad4058_read_voltage(ADC_RB_IDX_MEDHA1); - break; - case TIC_ADS7066: - ads7066_read_voltage(ADC_RB_IDX_MEDHA0); - ads7066_read_voltage(ADC_RB_IDX_MEDHA1); - break; - default: - LOG_DBG("Invalid ADC index %d", adc_idx_read); - break; + if (get_power_capping_source() == CAPPING_SOURCE_ADC) { + if (adc_poll_flag) { + switch (adc_idx_read) { + case ADI_AD4058: + ad4058_read_voltage(ADC_RB_IDX_MEDHA0); + ad4058_read_voltage(ADC_RB_IDX_MEDHA1); + break; + case TIC_ADS7066: + ads7066_read_voltage(ADC_RB_IDX_MEDHA0); + ads7066_read_voltage(ADC_RB_IDX_MEDHA1); + break; + default: + LOG_DBG("Invalid ADC index %d", adc_idx_read); + break; + } } + } else if (get_power_capping_source() == CAPPING_SOURCE_VR) { + update_vr_base_power_info(); } k_msleep(1); } @@ -743,9 +758,6 @@ void adc_rainbow_polling_handler(void *p1, void *p2, void *p3) void plat_adc_rainbow_init(void) { - for (uint8_t i = 0; i < ADC_IDX_MAX; i++) { - k_work_init(&adc_info[i].ucr_work, adc_ucr_work_handler); - } k_thread_create(&adc_rainbow_poll_thread, adc_rainbow_thread_stack, ADC_STACK_SIZE, adc_rainbow_polling_handler, NULL, NULL, NULL, CONFIG_MAIN_THREAD_PRIORITY, 0, K_NO_WAIT); @@ -753,4 +765,4 @@ void plat_adc_rainbow_init(void) k_thread_name_set(&adc_rainbow_poll_thread, "platform adc(rainbow) read"); LOG_INF("ADC(rainbow) polling thread started...\n"); -} \ No newline at end of file +} diff --git a/meta-facebook/sb-rb/src/platform/plat_adc.h b/meta-facebook/sb-rb/src/platform/plat_adc.h index dae120d089..041a9a80da 100644 --- a/meta-facebook/sb-rb/src/platform/plat_adc.h +++ b/meta-facebook/sb-rb/src/platform/plat_adc.h @@ -34,6 +34,9 @@ enum { #define ADI_AD4058 0x0 #define TIC_ADS7066 0x1 +uint8_t get_adc_good_status(uint8_t idx); +uint8_t get_final_ucr_status(); +void adc_poll_init(); void plat_adc_init(void); void adc_set_poll_flag(uint8_t onoff); bool adc_get_poll_flag(); @@ -45,8 +48,6 @@ uint16_t get_adc_ucr(uint8_t idx); void set_adc_ucr(uint8_t idx, uint16_t ucr); bool get_adc_ucr_status(uint8_t idx); void plat_adc_rainbow_init(void); -void get_ads7066_voltage(); -void get_ad4058_voltage(); uint8_t get_adc_type(); float get_ads7066_vref(); float get_ad4058_vref(); @@ -54,9 +55,9 @@ float get_adc_vr_pwr(uint8_t idx); uint16_t float_voltage_transfer_to_uint16(float temp_voltage_value); uint16_t *get_adc_buf(uint16_t idx); float uint16_voltage_transfer_to_float(uint16_t temp_voltage_value); -int ads7066_read_reg(uint8_t reg, uint8_t idx); +int ads7066_read_reg(uint8_t reg, uint8_t idx, uint8_t *out_data); int ads7066_write_reg(uint8_t reg, uint8_t write_val, uint8_t idx); -int ad4058_read_reg(uint8_t reg, uint8_t idx); +int ad4058_read_reg(uint8_t reg, uint8_t idx, uint8_t *out_data); int ad4058_write_reg(uint8_t reg, uint8_t write_val, uint8_t idx); uint16_t *get_vr_buf(uint16_t idx); void read_adc_info(); diff --git a/meta-facebook/sb-rb/src/platform/plat_class.c b/meta-facebook/sb-rb/src/platform/plat_class.c index 7173cd3004..582af8f912 100644 --- a/meta-facebook/sb-rb/src/platform/plat_class.c +++ b/meta-facebook/sb-rb/src/platform/plat_class.c @@ -27,12 +27,14 @@ LOG_MODULE_REGISTER(plat_class); -static uint8_t vr_module = 0; -static uint8_t ubc_module = 0; +static uint8_t vr_module = VR_MODULE_UNKNOWN; +static uint8_t ubc_module = UBC_MODULE_UNKNOWN; +static uint8_t tmp_module = TMP_TMP432; +static uint8_t vr_vendor_module = VENDOR_TYPE_UNKNOWN; static uint8_t mmc_slot = 0; static uint8_t asic_board_id = 0; static uint8_t tray_location = 0; -uint8_t board_rev_id = 0; +static uint8_t board_rev_id = 0; bool plat_cpld_eerprom_read(uint8_t *data, uint16_t offset, uint8_t len) { @@ -58,6 +60,43 @@ bool plat_cpld_eerprom_read(uint8_t *data, uint16_t offset, uint8_t len) return true; } +void init_vr_vendor_module(void) +{ + vr_vendor_module = VENDOR_TYPE_UNKNOWN; + + switch (ubc_module) { + case UBC_MODULE_MPS: + if (vr_module == VR_MODULE_MPS) { + vr_vendor_module = MPS_UBC_AND_MPS_VR; + } else if (vr_module == VR_MODULE_RNS) { + vr_vendor_module = MPS_UBC_AND_RNS_VR; + } + break; + + case UBC_MODULE_DELTA: + if (vr_module == VR_MODULE_MPS) { + vr_vendor_module = DELTA_UBC_AND_MPS_VR; + } else if (vr_module == VR_MODULE_RNS) { + vr_vendor_module = DELTA_UBC_AND_RNS_VR; + } + break; + + case UBC_MODULE_LUXSHARE: + if (vr_module == VR_MODULE_MPS) { + vr_vendor_module = LUXSHURE_UBC_AND_MPS_VR; + } else if (vr_module == VR_MODULE_RNS) { + vr_vendor_module = LUXSHURE_UBC_AND_RNS_VR; + } + break; + + default: + vr_vendor_module = VENDOR_TYPE_UNKNOWN; + break; + } + + LOG_INF("vr_vendor_module=%d (ubc=%d, vr=%d)", vr_vendor_module, ubc_module, vr_module); +} + void init_plat_config() { uint8_t module = 0; @@ -70,7 +109,7 @@ void init_plat_config() uint8_t board_id = 0; plat_read_cpld(CPLD_OFFSET_ASIC_BOARD_ID, &board_id, 1); asic_board_id = board_id & 0x03; - + init_vr_vendor_module(); change_sensor_cfg(asic_board_id, vr_module, ubc_module, board_rev_id); // cpld fru offset 0: slot plat_cpld_eerprom_read(&mmc_slot, 0, 1); @@ -111,3 +150,62 @@ uint8_t get_tray_location() { return tray_location; } + +void pal_show_board_types(const struct shell *shell) +{ + shell_print(shell, "* BOARD_TYPE: (0x%02X)%s", asic_board_id, + (asic_board_id == ASIC_BOARD_ID_RAINBOW) ? "RAINBOW" : + (asic_board_id == ASIC_BOARD_ID_EVB) ? "EVB" : + "not supported"); + + if (asic_board_id == ASIC_BOARD_ID_EVB) { + shell_print(shell, "* BOARD_STAGE: (0x%02X)%s", board_rev_id, + (board_rev_id == REV_ID_EVT1A) ? "REV_ID_EVT1A" : + (board_rev_id == REV_ID_EVT1B) ? "REV_ID_EVT1B" : + (board_rev_id == REV_ID_EVT2) ? "REV_ID_EVT2" : + (board_rev_id == REV_ID_DVT) ? "REV_ID_DVT" : + (board_rev_id == REV_ID_PVT) ? "REV_ID_PVT" : + (board_rev_id == REV_ID_MP) ? "REV_ID_MP" : + "not supported"); + } else if (asic_board_id == ASIC_BOARD_ID_RAINBOW) { + shell_print(shell, "* BOARD_STAGE: (0x%02X)%s", board_rev_id, + (board_rev_id == REV_ID_EVT1A) ? "REV_ID_EVT1A" : + (board_rev_id == REV_ID_EVT1B) ? "REV_ID_EVT1B" : + (board_rev_id == REV_ID_EVT2) ? "REV_ID_EVT2" : + (board_rev_id == REV_ID_DVT) ? "REV_ID_DVT" : + (board_rev_id == REV_ID_PVT) ? "REV_ID_PVT" : + (board_rev_id == REV_ID_MP) ? "REV_ID_MP" : + "not supported"); + } + + shell_print(shell, "* VR_VENDOR_TYPE:(0x%02X)%s", vr_vendor_module, + (vr_vendor_module == DELTA_UBC_AND_MPS_VR) ? "DELTA_UBC_AND_MPS_VR" : + (vr_vendor_module == DELTA_UBC_AND_RNS_VR) ? "DELTA_UBC_AND_RNS_VR" : + (vr_vendor_module == MPS_UBC_AND_MPS_VR) ? "MPS_UBC_AND_MPS_VR" : + (vr_vendor_module == MPS_UBC_AND_RNS_VR) ? "MPS_UBC_AND_RNS_VR" : + (vr_vendor_module == LUXSHURE_UBC_AND_MPS_VR) ? "LUXSHURE_UBC_AND_MPS_VR" : + (vr_vendor_module == LUXSHURE_UBC_AND_RNS_VR) ? "LUXSHURE_UBC_AND_RNS_VR" : + "not supported"); + shell_print(shell, "* UBC_TYPE: (0x%02X)%s", ubc_module, + (ubc_module == UBC_MODULE_DELTA) ? "UBC_DELTA_S54SS4P1A2" : + (ubc_module == UBC_MODULE_MPS) ? "UBC_MPS_MPC12109" : + (ubc_module == UBC_MODULE_LUXSHARE) ? "UBC_LUXSHURE_LX6310" : + "not supported"); + + shell_print(shell, "* VR_TYPE: (0x%02X)%s", vr_module, + (vr_module == VR_MODULE_MPS) ? "VR_MPS_MP2971_MP29816C" : + (vr_module == VR_MODULE_RNS) ? "VR_RNS_RAA229140_RAA228249" : + "not supported"); + + shell_print(shell, "* TMP_TYPE: (0x%02X)%s", tmp_module, + (tmp_module == TMP_TMP432) ? "TMP_TMP75_TMP432" : "not supported"); + + return; +} + +void pal_show_extra_info(const struct shell *shell) +{ + pal_show_board_types(shell); + + return; +} \ No newline at end of file diff --git a/meta-facebook/sb-rb/src/platform/plat_class.h b/meta-facebook/sb-rb/src/platform/plat_class.h index ab045d0b67..4a5a80bf7d 100644 --- a/meta-facebook/sb-rb/src/platform/plat_class.h +++ b/meta-facebook/sb-rb/src/platform/plat_class.h @@ -19,6 +19,16 @@ #include "stdint.h" +enum RB_VR_VENDER_MODULE { + DELTA_UBC_AND_MPS_VR, + DELTA_UBC_AND_RNS_VR, + MPS_UBC_AND_MPS_VR, + MPS_UBC_AND_RNS_VR, + LUXSHURE_UBC_AND_MPS_VR, + LUXSHURE_UBC_AND_RNS_VR, + VENDOR_TYPE_UNKNOWN, +}; + enum VR_MODULE { VR_MODULE_MPS, VR_MODULE_RNS, @@ -33,6 +43,11 @@ enum UBC_MODULE { UBC_MODULE_UNKNOWN, }; +enum TMP_MODULE { + TMP_TMP432, + TMP_TYPE_UNKNOWN, +}; + enum ASIC_BOARD_ID { ASIC_BOARD_ID_RSVD1, ASIC_BOARD_ID_RSVD2, diff --git a/meta-facebook/sb-rb/src/platform/plat_cpld.c b/meta-facebook/sb-rb/src/platform/plat_cpld.c index 864b0529c1..d5655d583b 100644 --- a/meta-facebook/sb-rb/src/platform/plat_cpld.c +++ b/meta-facebook/sb-rb/src/platform/plat_cpld.c @@ -224,8 +224,9 @@ void give_all_vr_pm_alert_sem() void poll_cpld_registers() { uint8_t data = 0; - bool prev_alert_status = false; uint8_t board_id = get_asic_board_id(); + uint8_t asic_rst = 0; + uint8_t prev_asic_rst = 0; while (1) { /* Sleep for the polling interval */ @@ -235,19 +236,6 @@ void poll_cpld_registers() continue; } - LOG_DBG("cpld_polling_alert_status = %d, cpld_polling_enable_flag = %d", - cpld_polling_alert_status, cpld_polling_enable_flag); - - // Check for falling edge of cpld_polling_alert_status (true -> false) - if (prev_alert_status && !cpld_polling_alert_status) { - uint8_t err_type = CPLD_UNEXPECTED_VAL_TRIGGER_CAUSE; - LOG_DBG("cpld_polling_alert_status: true -> false, reset_error_log_states: %x", - err_type); - reset_error_log_states(err_type); - } - // Save current alert status for next loop comparison - prev_alert_status = cpld_polling_alert_status; - if (!cpld_polling_enable_flag) continue; @@ -263,6 +251,70 @@ void poll_cpld_registers() } power_info = (pwr_value_msb<<8)|pwr_value_lsb; + if (get_asic_board_id() == ASIC_BOARD_ID_EVB && get_board_rev_id() >= REV_ID_EVT1B) { + + if (!plat_read_cpld(CPLD_ASIC_RESET_STATUS_REG, &asic_rst, 1)) { + LOG_ERR("Failed to read CPLD_ASIC_RESET_STATUS_REG (0x%02X)", + CPLD_ASIC_RESET_STATUS_REG); + } else { + if (asic_rst != prev_asic_rst) { + LOG_DBG("ASIC reset status changed: 0x%02X -> 0x%02X", + prev_asic_rst, asic_rst); + prev_asic_rst = asic_rst; + + uint8_t hamsa_pwron = (asic_rst >> 5) & 0x1; // HAMSA_POWER_ON_RESET_PLD_L + uint8_t medha0_pwron = (asic_rst >> 4) & 0x1; // MEDHA0_POWER_ON_RESET_PLD_L + uint8_t medha1_pwron = (asic_rst >> 3) & 0x1; // MEDHA1_POWER_ON_RESET_PLD_L + uint8_t hamsa_sys_rst = (asic_rst >> 2) & 0x1; // HAMSA_SYS_RST_PLD_L + uint8_t medha0_sys_rst = (asic_rst >> 1) & 0x1; // MEDHA0_SYS_RST_PLD_L + uint8_t medha1_sys_rst = (asic_rst >> 0) & 0x1; // MEDHA1_SYS_RST_PLD_L + + /* -------- U200070: io0~2 <- bit5~3 -------- + * - io0: HAMSA_POWER_ON_RESET_PLD_L + * - io1: MEDHA0_POWER_ON_RESET_PLD_L + * - io2: MEDHA1_POWER_ON_RESET_PLD_L + */ + uint8_t new_070 = U200070_IO_INIT_VAL; + + new_070 &= ~(BIT(0) | BIT(1) | BIT(2)); + new_070 |= (hamsa_pwron << 0); + new_070 |= (medha0_pwron << 1); + new_070 |= (medha1_pwron << 2); + + set_pca6554apw_ioe_value(U200070_IO_I2C_BUS, U200070_IO_ADDR, + OUTPUT_PORT, new_070); + LOG_DBG("Update U200070 OUTPUT_PORT: 0x%02X -> 0x%02X", + U200070_IO_INIT_VAL, new_070); + + /* -------- U200053: bit2 -> io6 (HAMSA_SYS_RST_PLD_L) -------- */ + uint8_t new_053 = U200053_IO_INIT_VAL; + + new_053 &= ~BIT(6); + new_053 |= (hamsa_sys_rst << 6); + + set_pca6554apw_ioe_value(U200053_IO_I2C_BUS, U200053_IO_ADDR, + OUTPUT_PORT, new_053); + LOG_DBG("Update U200053 OUTPUT_PORT: 0x%02X -> 0x%02X", + U200053_IO_INIT_VAL, new_053); + + /* -------- U200052: bit1/bit0 -> io6/io7 -------- + * - bit1 -> io6 (MEDHA0_SYS_RST_PLD_L) + * - bit0 -> io7 (MEDHA1_SYS_RST_PLD_L) + */ + uint8_t new_052 = U200052_IO_INIT_VAL; + + new_052 &= ~(BIT(6) | BIT(7)); + new_052 |= (medha0_sys_rst << 6); + new_052 |= (medha1_sys_rst << 7); + + set_pca6554apw_ioe_value(U200052_IO_I2C_BUS, U200052_IO_ADDR, + OUTPUT_PORT, new_052); + LOG_DBG("Update U200052 OUTPUT_PORT: 0x%02X -> 0x%02X", + U200052_IO_INIT_VAL, new_052); + } + } + } + for (size_t i = 0; i < ARRAY_SIZE(cpld_info_table); i++) { uint8_t expected_val = ubc_enabled_delayed_status ? cpld_info_table[i].dc_on_defaut : diff --git a/meta-facebook/sb-rb/src/platform/plat_cpld.h b/meta-facebook/sb-rb/src/platform/plat_cpld.h index 39af3d24fc..eac7dfe620 100644 --- a/meta-facebook/sb-rb/src/platform/plat_cpld.h +++ b/meta-facebook/sb-rb/src/platform/plat_cpld.h @@ -24,10 +24,12 @@ #include #define RESET 0x00 +#define VR_EN_PIN_READING_5 0x05 #define CPLD_OFFSET_BOARD_REV_ID 0x14 #define CPLD_OFFSET_VR_VENDER_TYPE 0x15 #define CPLD_OFFSET_POWER_CLAMP 0x25 #define CPLD_OFFSET_USERCODE 0x32 +#define CPLD_OFFSET_POWER_CAPPING_LV1_TIME 0x36 #define CPLD_OFFSET_MMC_PWR_EN 0x38 #define CPLD_OFFSET_ASIC_BOARD_ID 0x3C #define CPLD_OFFSET_ADC_IDX 0xA0 @@ -58,7 +60,10 @@ #define VR_PWRGD_PIN_READING_5_REG 0x0B #define VR_PWRGD_PIN_READING_6_REG 0x0C #define VR_CLK_ENABLE_PIN_CTRL_REG 0xA1 // pin control (1-step only) +#define CPLD_ASIC_RESET_STATUS_REG 0xA2 #define VR_1STEP_FUNC_EN_REG 0xA9 +#define HBM_CATTRIP_LOG_REG 0x27 +#define ASIC_TEMP_OVER_LOG_REG 0x29 #define CPLD_ADDR (0x4C >> 1) #define I2C_BUS_CPLD I2C_BUS11 @@ -104,4 +109,6 @@ void check_ubc_delayed_timer_handler(struct k_timer *timer); bool set_cpld_bit(uint8_t cpld_offset, uint8_t bit, uint8_t value); void give_all_vr_pm_alert_sem(); void get_cpld_polling_power_info(int *reading); +void set_cpld_polling_enable_flag(bool status); +void reset_error_log_states(uint8_t err_type); #endif diff --git a/meta-facebook/sb-rb/src/platform/plat_event.c b/meta-facebook/sb-rb/src/platform/plat_event.c index e75b881a3f..bc7cd16695 100644 --- a/meta-facebook/sb-rb/src/platform/plat_event.c +++ b/meta-facebook/sb-rb/src/platform/plat_event.c @@ -47,6 +47,8 @@ const vr_fault_info vr_fault_table[] = { SENSOR_NUM_ASIC_P0V8_HAMSA_AVDD_PCIE_VOLT_V }, { IRIS_HAMSA_VDDHRXTX_PCIE, VR_POWER_FAULT_1_REG, BIT(2), true, SENSOR_NUM_ASIC_P1V2_HAMSA_VDDHRXTX_PCIE_VOLT_V }, + { IRIS_4V2, VR_POWER_FAULT_1_REG, BIT(1), false }, + { IRIS_P0V75_AVDD_HCSL, VR_POWER_FAULT_1_REG, BIT(0), false }, // VR Power Fault 2 { IRIS_MEDHA1_VDD, VR_POWER_FAULT_2_REG, BIT(7), true, SENSOR_NUM_ASIC_P0V85_MEDHA1_VDD_VOLT_V }, @@ -114,6 +116,7 @@ void process_mtia_vr_power_fault_sel(cpld_info *cpld_info, uint8_t *current_cpld { CHECK_NULL_ARG(cpld_info); CHECK_NULL_ARG(current_cpld_value); + LOG_INF("process_mtia_vr_power_fault_sel"); bool get_ubc_enabled_delayed_status = is_ubc_enabled_delayed_enabled(); uint8_t expected_val = get_ubc_enabled_delayed_status ? cpld_info->dc_on_defaut : cpld_info->dc_off_defaut; @@ -232,4 +235,15 @@ void plat_set_iris_temp_error_log(bool is_assert, uint8_t sensor_id) } set_led_flag(true); k_msleep(500); +} + +void asic_thermtrip_error_log(bool is_assert) +{ + uint16_t error_code = (ASIC_THERMTRIP_TRIGGER_CAUSE << 13); + error_log_event(error_code, (is_assert ? LOG_ASSERT : LOG_DEASSERT)); + + if (is_assert == LOG_ASSERT) { + LOG_INF("Generated IRIS temp error code: 0x%x", error_code); + } + k_msleep(500); } \ No newline at end of file diff --git a/meta-facebook/sb-rb/src/platform/plat_event.h b/meta-facebook/sb-rb/src/platform/plat_event.h index d13707b533..8e8bc8310a 100644 --- a/meta-facebook/sb-rb/src/platform/plat_event.h +++ b/meta-facebook/sb-rb/src/platform/plat_event.h @@ -37,4 +37,5 @@ enum event_type { void process_mtia_vr_power_fault_sel(cpld_info *cpld_info, uint8_t *current_cpld_value); void plat_set_dc_on_log(bool is_assert); void plat_set_iris_temp_error_log(bool is_assert, uint8_t sensor_id); +void asic_thermtrip_error_log(bool is_assert); #endif diff --git a/meta-facebook/sb-rb/src/platform/plat_fru.c b/meta-facebook/sb-rb/src/platform/plat_fru.c index b5b14e5334..dd9a009744 100644 --- a/meta-facebook/sb-rb/src/platform/plat_fru.c +++ b/meta-facebook/sb-rb/src/platform/plat_fru.c @@ -53,38 +53,6 @@ const EEPROM_CFG plat_fru_config[] = { }, }; -#define CHASSIS_CUSTOM_DATA_MAX 24 -#define BOARD_CUSTOM_DATA_MAX 4 - -typedef struct { - uint8_t chassis_type; - char chassis_part_number[32]; - char chassis_serial_number[32]; - char chassis_custom_data[CHASSIS_CUSTOM_DATA_MAX][32]; -} ChassisInfo; - -typedef struct { - uint8_t language; - char board_mfg_date[32]; - char board_mfg[32]; - char board_product[32]; - char board_serial[32]; - char board_part_number[32]; - char board_fru_id[32]; - char board_custom_data[BOARD_CUSTOM_DATA_MAX][32]; -} BoardInfo; - -typedef struct { - uint8_t language; - char product_manufacturer[32]; - char product_name[32]; - char product_part_number[32]; - char product_version[32]; - char product_serial[32]; - char product_asset_tag[32]; - char product_fru_id[32]; -} ProductInfo; - void pal_load_fru_config(void) { memcpy(&fru_config, &plat_fru_config, sizeof(plat_fru_config)); @@ -192,12 +160,6 @@ bool plat_get_cpld_fru_data(uint8_t *data) return true; } -typedef struct { - ChassisInfo chassis; - BoardInfo board; - ProductInfo product; -} FRU_INFO; - FRU_INFO *plat_fru_info = NULL; FRU_INFO *create_fru_info(void) @@ -535,3 +497,8 @@ void print_fru_info(void) printf(" Product FRU ID: %s\n", plat_fru_info->product.product_fru_id); printf("\n"); } + +FRU_INFO *get_fru_info(void) +{ + return plat_fru_info; +} \ No newline at end of file diff --git a/meta-facebook/sb-rb/src/platform/plat_fru.h b/meta-facebook/sb-rb/src/platform/plat_fru.h index 6900b8f014..712452f00a 100644 --- a/meta-facebook/sb-rb/src/platform/plat_fru.h +++ b/meta-facebook/sb-rb/src/platform/plat_fru.h @@ -20,6 +20,9 @@ #define FRU_CFG_NUM MAX_FRU_ID #define LOG_EEPROM_ADDR (0xA0 >> 1) #define CPLD_EEPROM_ADDR (0xA0 >> 1) +#define CHASSIS_CUSTOM_DATA_MAX 24 +#define BOARD_CUSTOM_DATA_MAX 10 +#define PRODUCT_CUSTOM_DATA_MAX 10 enum FRU_ID { LOG_EEPROM_ID = 0x00, @@ -27,10 +30,47 @@ enum FRU_ID { MAX_FRU_ID, }; +typedef struct { + uint8_t chassis_type; + char chassis_part_number[32]; + char chassis_serial_number[32]; + char chassis_custom_data[CHASSIS_CUSTOM_DATA_MAX][32]; +} ChassisInfo; + +typedef struct { + uint8_t language; + char board_mfg_date[32]; + char board_mfg[32]; + char board_product[32]; + char board_serial[32]; + char board_part_number[32]; + char board_fru_id[32]; + char board_custom_data[BOARD_CUSTOM_DATA_MAX][32]; +} BoardInfo; + +typedef struct { + uint8_t language; + char product_manufacturer[32]; + char product_name[32]; + char product_part_number[32]; + char product_version[32]; + char product_serial[32]; + char product_asset_tag[32]; + char product_fru_id[32]; + char product_custom_data[PRODUCT_CUSTOM_DATA_MAX][32]; +} ProductInfo; + +typedef struct { + ChassisInfo chassis; + BoardInfo board; + ProductInfo product; +} FRU_INFO; + bool init_fru_info(void); void print_fru_info(void); bool plat_cpld_fru_read(uint32_t offset, uint8_t *data, uint16_t data_len); bool plat_eeprom_write(uint32_t offset, uint8_t *data, uint16_t data_len); bool plat_eeprom_read(uint32_t offset, uint8_t *data, uint16_t data_len); +FRU_INFO *get_fru_info(void); #endif diff --git a/meta-facebook/sb-rb/src/platform/plat_gpio.c b/meta-facebook/sb-rb/src/platform/plat_gpio.c index d00579b803..89d80ccf3f 100644 --- a/meta-facebook/sb-rb/src/platform/plat_gpio.c +++ b/meta-facebook/sb-rb/src/platform/plat_gpio.c @@ -33,10 +33,13 @@ void gpio_int_default() return; } +// clang-format off + GPIO_CFG plat_gpio_cfg[] = { // chip, number, is_init, is_latch, direction, status, property, int_type, int_cb // GPIO 0 group - { CHIP_GPIO, 0, ENABLE, DISABLE, GPIO_INPUT, GPIO_HIGH, PUSH_PULL, GPIO_INT_DISABLE, NULL }, + { CHIP_GPIO, 0, ENABLE, DISABLE, GPIO_INPUT, GPIO_HIGH, PUSH_PULL, GPIO_INT_EDGE_FALLING, + ISR_ASIC_THERMTRIP_TRIGGER }, { CHIP_GPIO, 1, ENABLE, DISABLE, GPIO_INPUT, GPIO_HIGH, PUSH_PULL, GPIO_INT_EDGE_BOTH, ISR_GPIO_RST_IRIS_PWR_ON_PLD_R1_N }, { CHIP_GPIO, 2, ENABLE, DISABLE, GPIO_OUTPUT, GPIO_LOW, PUSH_PULL, GPIO_INT_DISABLE, NULL }, @@ -151,7 +154,7 @@ GPIO_CFG plat_gpio_cfg[] = { NULL }, { CHIP_GPIO, 57, ENABLE, DISABLE, GPIO_OUTPUT, GPIO_LOW, PUSH_PULL, GPIO_INT_DISABLE, NULL }, - { CHIP_GPIO, 58, DISABLE, DISABLE, GPIO_INPUT, GPIO_LOW, PUSH_PULL, GPIO_INT_DISABLE, + { CHIP_GPIO, 58, ENABLE, DISABLE, GPIO_OUTPUT, GPIO_LOW, PUSH_PULL, GPIO_INT_DISABLE, NULL }, { CHIP_GPIO, 59, DISABLE, DISABLE, GPIO_INPUT, GPIO_LOW, PUSH_PULL, GPIO_INT_DISABLE, NULL }, @@ -184,7 +187,7 @@ GPIO_CFG plat_gpio_cfg[] = { NULL }, { CHIP_GPIO, 73, DISABLE, DISABLE, GPIO_INPUT, GPIO_LOW, PUSH_PULL, GPIO_INT_DISABLE, NULL }, - { CHIP_GPIO, 74, ENABLE, DISABLE, GPIO_OUTPUT, GPIO_LOW, PUSH_PULL, GPIO_INT_DISABLE, + { CHIP_GPIO, 74, DISABLE, DISABLE, GPIO_OUTPUT, GPIO_LOW, PUSH_PULL, GPIO_INT_DISABLE, NULL }, { CHIP_GPIO, 75, DISABLE, DISABLE, GPIO_INPUT, GPIO_LOW, PUSH_PULL, GPIO_INT_DISABLE, NULL }, @@ -201,8 +204,8 @@ GPIO_CFG plat_gpio_cfg[] = { { CHIP_GPIO, 81, ENABLE, DISABLE, GPIO_INPUT, GPIO_LOW, PUSH_PULL, GPIO_INT_DISABLE, NULL }, { CHIP_GPIO, 82, DISABLE, DISABLE, GPIO_INPUT, GPIO_LOW, PUSH_PULL, GPIO_INT_DISABLE, NULL }, - { CHIP_GPIO, 83, ENABLE, DISABLE, GPIO_INPUT, GPIO_LOW, PUSH_PULL, GPIO_INT_DISABLE, NULL }, - { CHIP_GPIO, 84, ENABLE, DISABLE, GPIO_INPUT, GPIO_LOW, PUSH_PULL, GPIO_INT_DISABLE, NULL }, + { CHIP_GPIO, 83, DISABLE, DISABLE, GPIO_INPUT, GPIO_LOW, PUSH_PULL, GPIO_INT_DISABLE, NULL }, + { CHIP_GPIO, 84, DISABLE, DISABLE, GPIO_INPUT, GPIO_LOW, PUSH_PULL, GPIO_INT_DISABLE, NULL }, { CHIP_GPIO, 85, DISABLE, DISABLE, GPIO_INPUT, GPIO_LOW, PUSH_PULL, GPIO_INT_DISABLE, NULL }, { CHIP_GPIO, 86, DISABLE, DISABLE, GPIO_INPUT, GPIO_LOW, PUSH_PULL, GPIO_INT_DISABLE, @@ -288,8 +291,10 @@ GPIO_CFG plat_gpio_cfg[] = { NULL }, }; +// clang-format on + bool pal_load_gpio_config(void) { memcpy(&gpio_cfg[0], &plat_gpio_cfg[0], sizeof(plat_gpio_cfg)); return 1; -}; \ No newline at end of file +}; diff --git a/meta-facebook/sb-rb/src/platform/plat_gpio.h b/meta-facebook/sb-rb/src/platform/plat_gpio.h index b756726bfa..b12f7a06e2 100644 --- a/meta-facebook/sb-rb/src/platform/plat_gpio.h +++ b/meta-facebook/sb-rb/src/platform/plat_gpio.h @@ -117,8 +117,8 @@ void gpio_int_default(); gpio_name_to_num(Reserve_GPIO96) \ gpio_name_to_num(Reserve_GPIO97) #define name_gpioA \ - gpio_name_to_num(MEDHA0_CURRENT_SENSE_0_LS_LVC33_R) \ - gpio_name_to_num(MEDHA0_CURRENT_SENSE_1_LS_LVC33_R) \ + gpio_name_to_num(MEDHA0_PWR_CAP_LV1_LVC33) \ + gpio_name_to_num(MEDHA1_PWR_CAP_LV1_LVC33) \ gpio_name_to_num(Reserve_GPIOA2) \ gpio_name_to_num(MEDHA1_CURRENT_SENSE_0_LS_LVC33_R) \ gpio_name_to_num(MEDHA1_CURRENT_SENSE_1_LS_LVC33_R) \ diff --git a/meta-facebook/sb-rb/src/platform/plat_hook.c b/meta-facebook/sb-rb/src/platform/plat_hook.c index a27f00e22e..1aaa6fa51a 100644 --- a/meta-facebook/sb-rb/src/platform/plat_hook.c +++ b/meta-facebook/sb-rb/src/platform/plat_hook.c @@ -31,6 +31,8 @@ #include "plat_i2c_target.h" #include "shell_plat_average_power.h" #include "plat_ioexp.h" +#include "tmp431.h" +#include "plat_util.h" LOG_MODULE_REGISTER(plat_hook); @@ -118,6 +120,28 @@ bool post_common_sensor_read(sensor_cfg *cfg, void *args, int *const reading) return true; } +bool post_tmp432_read(sensor_cfg *cfg, void *args, int *reading) +{ + CHECK_NULL_ARG_WITH_RETURN(cfg, false); + ARG_UNUSED(args); + ARG_UNUSED(reading); + + uint8_t status = 0; + + if (tmp432_get_temp_open_status(cfg, &status)) { + uint8_t bit = (cfg->offset == TMP432_REMOTE_TEMPERATRUE_1) ? BIT(1) : + (cfg->offset == TMP432_REMOTE_TEMPERATRUE_2) ? BIT(2) : + 0; + // only check BIT(1), BIT(2) + if (status & bit) { + cfg->cache_status = SENSOR_OPEN_CIRCUIT; + return false; + } + } + + return post_common_sensor_read(cfg, args, reading); +} + bool is_mb_dc_on() { /* RST_IRIS_PWR_ON_PLD_R1_N is low active, @@ -229,9 +253,6 @@ bootstrap_mapping_register bootstrap_table[] = { true }, { STRAP_INDEX_HAMSA_CRM_STRAP_1, STRAP_TYPE_CPLD, 0x16, "HAMSA_CRM_STRAP_1", 0, 1, 0x0, 0x0, true }, - { STRAP_INDEX_HAMSA_MFIO12, STRAP_TYPE_CPLD, 0x17, "HAMSA_MFIO12", 7, 1, 0x0, 0x0, false }, - { STRAP_INDEX_HAMSA_MFIO13, STRAP_TYPE_CPLD, 0x17, "HAMSA_MFIO13", 6, 1, 0x0, 0x0, false }, - { STRAP_INDEX_HAMSA_MFIO14, STRAP_TYPE_CPLD, 0x17, "HAMSA_MFIO14", 5, 1, 0x0, 0x0, false }, { STRAP_INDEX_HAMSA_MFIO7, STRAP_TYPE_CPLD, 0x17, "HAMSA_MFIO7", 4, 1, 0x01, 0x01, false }, { STRAP_INDEX_HAMSA_MFIO9, STRAP_TYPE_CPLD, 0x17, "HAMSA_MFIO9", 3, 1, 0x0, 0x0, false }, { STRAP_INDEX_HAMSA_MFIO11, STRAP_TYPE_CPLD, 0x17, "HAMSA_MFIO11", 2, 1, 0x0, 0x0, false }, @@ -283,18 +304,6 @@ bootstrap_mapping_register bootstrap_table[] = { 0x01, false }, { STRAP_INDEX_MEDHA1_DFT_TAP_EN_PLD_L, STRAP_TYPE_CPLD, 0x1d, "MEDHA1_DFT_TAP_EN_PLD_L", 0, 1, 0x01, 0x01, false }, - { STRAP_INDEX_MEDHA0_MFIO_12, STRAP_TYPE_CPLD, 0x1e, "MEDHA0_MFIO_12", 5, 1, 0x0, 0x0, - true }, - { STRAP_INDEX_MEDHA0_MFIO_13, STRAP_TYPE_CPLD, 0x1e, "MEDHA0_MFIO_13", 4, 1, 0x0, 0x0, - true }, - { STRAP_INDEX_MEDHA0_MFIO_14, STRAP_TYPE_CPLD, 0x1e, "MEDHA0_MFIO_14", 3, 1, 0x0, 0x0, - true }, - { STRAP_INDEX_MEDHA1_MFIO_12, STRAP_TYPE_CPLD, 0x1e, "MEDHA1_MFIO_12", 2, 1, 0x0, 0x0, - true }, - { STRAP_INDEX_MEDHA1_MFIO_13, STRAP_TYPE_CPLD, 0x1e, "MEDHA1_MFIO_13", 1, 1, 0x0, 0x0, - true }, - { STRAP_INDEX_MEDHA1_MFIO_14, STRAP_TYPE_CPLD, 0x1e, "MEDHA1_MFIO_14", 0, 1, 0x0, 0x0, - true }, { STRAP_INDEX_FM_JTAG_MEDHA0_JTCE_0_2, STRAP_TYPE_CPLD, 0x1f, "MEDHA0_JTCE_0_2", 3, 3, 0x01, 0x01, true }, { STRAP_INDEX_FM_JTAG_MEDHA1_JTCE_0_2, STRAP_TYPE_CPLD, 0x1f, "MEDHA1_JTCE_0_2", 0, 3, 0x01, @@ -353,6 +362,16 @@ bootstrap_mapping_register bootstrap_table[] = { "MEDHA1_MFIO10", 2, 1, 0x0, 0x0, false }, }; + +void set_bootstrap_table_change_setting_value(uint8_t index, uint8_t value) +{ + if (index >= STRAP_INDEX_MAX) { + LOG_ERR("invalid index:%d", index); + return; + } + bootstrap_table[index].change_setting_value = value; +} + bool vr_rail_name_get(uint8_t rail, uint8_t **name) { CHECK_NULL_ARG_WITH_RETURN(name, false); @@ -879,7 +898,7 @@ bool set_bootstrap_table_val_to_ioexp(void) } // tca6424a only in EVB - if (get_asic_board_id() == ASIC_BOARD_ID_EVB) { + if (is_tca6424a_accessible()) { uint8_t port1_data = 0; uint8_t port2_data = 0; for (uint8_t i = STRAP_INDEX_HAMSA_MFIO6; i <= STRAP_INDEX_MEDHA1_MFIO10; i++) { @@ -902,24 +921,45 @@ bool set_bootstrap_table_val_to_ioexp(void) bool set_ioexp_val_to_bootstrap_table(void) { uint8_t data[2] = { 0x00, 0x00 }; - if (!pca6416a_i2c_read(PCA6414A_OUTPUT_PORT_0, data, 2)) { - LOG_ERR("Can't find bootstrap default from pca6416a"); - return false; + uint8_t direction[2] = { 0x00, 0x00 }; + if (is_mb_dc_on()) { + if (!pca6416a_i2c_read(PCA6414A_OUTPUT_PORT_0, data, 2)) { + LOG_ERR("Can't find bootstrap value from pca6416a"); + return false; + } + if (!pca6416a_i2c_read(PCA6414A_CONFIG_0, direction, 2)) { + LOG_ERR("Can't find bootstrap direction from pca6416a"); + return false; + } + // set when output only + bootstrap_table[STRAP_INDEX_OWL_E_BOOT_SOURCE_0_7].change_setting_value = + (data[0] & (~direction[0])); + bootstrap_table[STRAP_INDEX_OWL_W_BOOT_SOURCE_0_7].change_setting_value = + (data[1] & (~direction[1])); } - bootstrap_table[STRAP_INDEX_OWL_E_BOOT_SOURCE_0_7].change_setting_value = data[0]; - bootstrap_table[STRAP_INDEX_OWL_W_BOOT_SOURCE_0_7].change_setting_value = data[1]; // tca6424a only in EVB - if (get_asic_board_id() == ASIC_BOARD_ID_EVB) { + if (is_tca6424a_accessible()) { if (!tca6424a_i2c_read(TCA6424A_OUTPUT_PORT_1, data, 2)) { - LOG_ERR("Can't find bootstrap default from tca6424a"); + LOG_ERR("Can't find bootstrap value from tca6424a"); + return false; + } + if (!tca6424a_i2c_read(TCA6424A_CONFIG_1, direction, 2)) { + LOG_ERR("Can't find bootstrap direction from tca6424a"); return false; } for (uint8_t i = STRAP_INDEX_HAMSA_MFIO6; i <= STRAP_INDEX_MEDHA1_MFIO10; i++) { // check data from port1 or port2 + uint8_t dir = (bootstrap_table[i].cpld_offsets == TCA6424A_OUTPUT_PORT_1) ? + direction[0] : + direction[1]; uint8_t tmp = (bootstrap_table[i].cpld_offsets == TCA6424A_OUTPUT_PORT_1) ? data[0] : data[1]; + // set when output only + if ((dir >> bootstrap_table[i].bit_offset) & 0x01) { + continue; + } bootstrap_table[i].change_setting_value = (tmp >> bootstrap_table[i].bit_offset) & 0x01; } @@ -1103,16 +1143,45 @@ bool set_bootstrap_val_to_device(uint8_t strap, uint8_t val) switch (type) { case STRAP_TYPE_CPLD: - if (!plat_write_cpld(bootstrap_table[strap].cpld_offsets, &val)) + if (!plat_write_cpld(bootstrap_table[strap].cpld_offsets, &val)) { return false; + } + /* when TEST_STRAP to 0, change MFIO 6 8 10 to INPUT */ + /* when TEST_STRAP to 1, change MFIO 6 8 10 to OUTPUT */ + if (is_tca6424a_accessible()) { + if (bootstrap_table[strap].index == STRAP_INDEX_HAMSA_TEST_STRAP_R) { + if ((val & BIT(bootstrap_table[strap].bit_offset)) == 0) { + set_hamsa_mfio_6_8_10_input(); + } else { + set_hamsa_mfio_6_8_10_output(); + set_bootstrap_table_val_to_ioexp(); + } + } else if (bootstrap_table[strap].index == STRAP_INDEX_MEDHA0_TEST_STRAP) { + if ((val & BIT(bootstrap_table[strap].bit_offset)) == 0) { + set_medha0_mfio_6_8_10_input(); + } else { + set_medha0_mfio_6_8_10_output(); + set_bootstrap_table_val_to_ioexp(); + } + } else if (bootstrap_table[strap].index == STRAP_INDEX_MEDHA1_TEST_STRAP) { + if ((val & BIT(bootstrap_table[strap].bit_offset)) == 0) { + set_medha1_mfio_6_8_10_input(); + } else { + set_medha1_mfio_6_8_10_output(); + set_bootstrap_table_val_to_ioexp(); + } + } + } break; case STRAP_TYPE_IOEXP_PCA6416A: - if (!pca6416a_i2c_write(bootstrap_table[strap].cpld_offsets, &val, 1)) - return false; + if (is_mb_dc_on()) { + if (!pca6416a_i2c_write(bootstrap_table[strap].cpld_offsets, &val, 1)) + return false; + } break; case STRAP_TYPE_IOEXP_TCA6424A: // tca6424a only in EVB - if (get_asic_board_id() == ASIC_BOARD_ID_EVB) { + if (is_tca6424a_accessible()) { if (!tca6424a_i2c_write(bootstrap_table[strap].cpld_offsets, &val, 1)) return false; } @@ -1197,4 +1266,35 @@ uint8_t get_strap_index_max() { return (get_asic_board_id() == ASIC_BOARD_ID_EVB) ? STRAP_INDEX_MAX : STRAP_INDEX_EXCEPT_EVB_MAX; +} + +bool plat_set_vr_reg(uint8_t rail, uint8_t reg, uint8_t *data, uint8_t len) +{ + CHECK_NULL_ARG_WITH_RETURN(data, false); + + bool ret = false; + uint8_t sensor_id = vr_rail_table[rail].sensor_id; + sensor_cfg *cfg = get_sensor_cfg_by_sensor_id(sensor_id); + CHECK_NULL_ARG_WITH_RETURN(cfg, false); + + if ((cfg->pre_sensor_read_hook)) { + if ((cfg->pre_sensor_read_hook)(cfg, cfg->pre_sensor_read_args) == false) { + LOG_DBG("0x%02x read vr reg 0x%02x pre hook fail!", sensor_id, reg); + return false; + } + }; + + if (!plat_i2c_write(cfg->port, cfg->target_addr, reg, data, len)) { + LOG_ERR("0x%02x write vr reg 0x%02x fail!", sensor_id, reg); + goto err; + } + + ret = true; +err: + if (cfg->post_sensor_read_hook) { + if (cfg->post_sensor_read_hook(cfg, cfg->post_sensor_read_args, NULL) == false) { + LOG_ERR("0x%02x read vr reg 0x%02x post hook fail!", sensor_id, reg); + } + } + return ret; } \ No newline at end of file diff --git a/meta-facebook/sb-rb/src/platform/plat_hook.h b/meta-facebook/sb-rb/src/platform/plat_hook.h index 338f6c8b84..0e1b31ffa2 100644 --- a/meta-facebook/sb-rb/src/platform/plat_hook.h +++ b/meta-facebook/sb-rb/src/platform/plat_hook.h @@ -131,9 +131,6 @@ enum PLAT_STRAP_INDEX_E { STRAP_INDEX_HAMSA_LS_STRAP_1, STRAP_INDEX_HAMSA_CRM_STRAP_0, STRAP_INDEX_HAMSA_CRM_STRAP_1, - STRAP_INDEX_HAMSA_MFIO12, - STRAP_INDEX_HAMSA_MFIO13, - STRAP_INDEX_HAMSA_MFIO14, STRAP_INDEX_HAMSA_MFIO7, STRAP_INDEX_HAMSA_MFIO9, STRAP_INDEX_HAMSA_MFIO11, @@ -162,12 +159,6 @@ enum PLAT_STRAP_INDEX_E { STRAP_INDEX_MEDHA1_TRI_L, STRAP_INDEX_MEDHA1_ATPG_MODE_L, STRAP_INDEX_MEDHA1_DFT_TAP_EN_PLD_L, - STRAP_INDEX_MEDHA0_MFIO_12, - STRAP_INDEX_MEDHA0_MFIO_13, - STRAP_INDEX_MEDHA0_MFIO_14, - STRAP_INDEX_MEDHA1_MFIO_12, - STRAP_INDEX_MEDHA1_MFIO_13, - STRAP_INDEX_MEDHA1_MFIO_14, STRAP_INDEX_FM_JTAG_MEDHA0_JTCE_0_2, STRAP_INDEX_FM_JTAG_MEDHA1_JTCE_0_2, STRAP_INDEX_PLD_OWL_E_DFT_TAP_EN_L, @@ -235,6 +226,7 @@ extern vr_vout_user_settings user_settings; extern vr_vout_range_user_settings_struct vout_range_user_settings; extern vr_mapping_sensor vr_rail_table[]; extern bootstrap_mapping_register bootstrap_table[]; +void set_bootstrap_table_change_setting_value(uint8_t index, uint8_t value); bool pre_vr_read(sensor_cfg *cfg, void *args); bool post_vr_read(sensor_cfg *cfg, void *args, int *const reading); bool is_mb_dc_on(); @@ -275,6 +267,9 @@ bool post_ubc_read(sensor_cfg *cfg, void *args, int *reading); bool bootstrap_user_settings_set(void *bootstrap_user_settings); bool vr_vout_user_settings_set(void *user_settings_value); bool set_bootstrap_table_val_to_ioexp(void); +bool set_ioexp_val_to_bootstrap_table(void); bool set_bootstrap_val_to_device(uint8_t strap, uint8_t val); uint8_t get_strap_index_max(); +bool post_tmp432_read(sensor_cfg *cfg, void *args, int *reading); +bool plat_set_vr_reg(uint8_t rail, uint8_t reg, uint8_t *data, uint8_t len); #endif diff --git a/meta-facebook/sb-rb/src/platform/plat_i2c_target.c b/meta-facebook/sb-rb/src/platform/plat_i2c_target.c index 6cbed13325..4bc56fb1db 100644 --- a/meta-facebook/sb-rb/src/platform/plat_i2c_target.c +++ b/meta-facebook/sb-rb/src/platform/plat_i2c_target.c @@ -38,6 +38,8 @@ #include "plat_hook.h" #include "plat_i2c.h" #include "plat_ioexp.h" +#include "plat_fru.h" +#include "plat_power_capping.h" LOG_MODULE_REGISTER(plat_i2c_target); @@ -45,6 +47,8 @@ LOG_MODULE_REGISTER(plat_i2c_target); #define DATA_TABLE_LENGTH_1 1 #define DATA_TABLE_LENGTH_2 2 #define DATA_TABLE_LENGTH_4 4 +#define DATA_TABLE_LENGTH_7 7 +#define DATA_TABLE_LENGTH_13 13 #define DEVICE_TYPE 0x01 #define REGISTER_LAYOUT_VERSION 0x01 #define SENSOR_READING_PDR_INDEX_MAX 50 @@ -57,6 +61,11 @@ LOG_MODULE_REGISTER(plat_i2c_target); #define VR_PWR_BUF_SIZE 38 #define I2C_TARGET_BUS_ASIC I2C_BUS7 // asic bus is I2C_BUS7, I2C_BUS6 is only for test +typedef struct __attribute__((__packed__)) { + uint8_t data_length; + uint8_t fru_data[]; +} plat_fru_data; + static bool command_reply_data_handle(void *arg); void set_bootstrap_element_handler(); K_WORK_DEFINE(set_bootstrap_element_work, set_bootstrap_element_handler); @@ -115,9 +124,94 @@ plat_sensor_init_data *sensor_init_data_table[DATA_TABLE_LENGTH_2] = { NULL }; plat_sensor_reading *sensor_reading_table[DATA_TABLE_LENGTH_4] = { NULL }; plat_inventory_ids *inventory_ids_table[DATA_TABLE_LENGTH_1] = { NULL }; plat_strap_capability *strap_capability_table[DATA_TABLE_LENGTH_1] = { NULL }; +plat_fru_data *fru_board_data_table[DATA_TABLE_LENGTH_13] = { NULL }; +plat_fru_data *fru_product_data_table[DATA_TABLE_LENGTH_7] = { NULL }; plat_i2c_bridge_command_status *i2c_bridge_command_status_table[DATA_TABLE_LENGTH_1] = { NULL }; plat_i2c_bridge_command_response_data *i2c_bridge_command_response_data_table[DATA_TABLE_LENGTH_1] = { NULL }; + +bool get_fru_info_element(telemetry_info *telemetry_info, char **fru_element, + uint8_t *fru_element_size) +{ + CHECK_NULL_ARG_WITH_RETURN(telemetry_info, false); + + FRU_INFO *plat_fru_info = get_fru_info(); + if (!plat_fru_info) + return false; + + switch (telemetry_info->telemetry_offset) { + case FRU_BOARD_PART_NUMBER_REG: + *fru_element = plat_fru_info->board.board_part_number; + break; + case FRU_BOARD_SERIAL_NUMBER_REG: + *fru_element = plat_fru_info->board.board_serial; + break; + case FRU_BOARD_PRODUCT_NAME_REG: + *fru_element = plat_fru_info->board.board_product; + break; + case FRU_BOARD_CUSTOM_DATA_1_REG: + *fru_element = plat_fru_info->board.board_custom_data[0]; + break; + case FRU_BOARD_CUSTOM_DATA_2_REG: + *fru_element = plat_fru_info->board.board_custom_data[1]; + break; + case FRU_BOARD_CUSTOM_DATA_3_REG: + *fru_element = plat_fru_info->board.board_custom_data[2]; + break; + case FRU_BOARD_CUSTOM_DATA_4_REG: + *fru_element = plat_fru_info->board.board_custom_data[3]; + break; + case FRU_BOARD_CUSTOM_DATA_5_REG: + *fru_element = plat_fru_info->board.board_custom_data[4]; + break; + case FRU_BOARD_CUSTOM_DATA_6_REG: + *fru_element = plat_fru_info->board.board_custom_data[5]; + break; + case FRU_BOARD_CUSTOM_DATA_7_REG: + *fru_element = plat_fru_info->board.board_custom_data[6]; + break; + case FRU_BOARD_CUSTOM_DATA_8_REG: + *fru_element = plat_fru_info->board.board_custom_data[7]; + break; + case FRU_BOARD_CUSTOM_DATA_9_REG: + *fru_element = plat_fru_info->board.board_custom_data[8]; + break; + case FRU_BOARD_CUSTOM_DATA_10_REG: + *fru_element = plat_fru_info->board.board_custom_data[9]; + break; + case FRU_PRODUCT_NAME_REG: + *fru_element = plat_fru_info->product.product_name; + break; + case FRU_PRODUCT_PART_NUMBER_REG: + *fru_element = plat_fru_info->product.product_part_number; + break; + case FRU_PRODUCT_PART_VERSION_REG: + *fru_element = plat_fru_info->product.product_version; + break; + case FRU_PRODUCT_SERIAL_NUMBER_REG: + *fru_element = plat_fru_info->product.product_serial; + break; + case FRU_PRODUCT_ASSET_TAG_REG: + *fru_element = plat_fru_info->product.product_asset_tag; + break; + case FRU_PRODUCT_CUSTOM_DATA_1_REG: + *fru_element = plat_fru_info->product.product_custom_data[0]; + break; + case FRU_PRODUCT_CUSTOM_DATA_2_REG: + *fru_element = plat_fru_info->product.product_custom_data[1]; + break; + default: + LOG_ERR("Unknown reg offset: 0x%02x", telemetry_info->telemetry_offset); + break; + } + if (*fru_element) { + *fru_element_size = (uint8_t)strlen(*fru_element); + } else { + *fru_element_size = 0; + } + return true; +} + bool initialize_sensor_data(telemetry_info *telemetry_info, uint8_t *buffer_size) { CHECK_NULL_ARG_WITH_RETURN(telemetry_info, false); @@ -156,6 +250,7 @@ bool initialize_sensor_data(telemetry_info *telemetry_info, uint8_t *buffer_size *buffer_size = (uint8_t)table_size; return true; } + bool initialize_sensor_reading(telemetry_info *telemetry_info, uint8_t *buffer_size) { CHECK_NULL_ARG_WITH_RETURN(telemetry_info, false); @@ -192,6 +287,61 @@ bool initialize_sensor_reading(telemetry_info *telemetry_info, uint8_t *buffer_s LOG_HEXDUMP_DBG(sensor_data, table_size, "sensor_data"); return true; } + +bool initialize_fru_board_data(telemetry_info *telemetry_info, uint8_t *buffer_size) +{ + CHECK_NULL_ARG_WITH_RETURN(telemetry_info, false); + + int table_index = telemetry_info->telemetry_offset - FRU_BOARD_PART_NUMBER_REG; + if (table_index < 0 || table_index >= DATA_TABLE_LENGTH_13) + return false; + + char *fru_string = NULL; + uint8_t fru_length = 0; + if (!get_fru_info_element(telemetry_info, &fru_string, &fru_length)) { + LOG_ERR("Failed to retrieve FRU Element"); + } + + size_t table_size = sizeof(plat_fru_data) + fru_length; + plat_fru_data *sensor_data = + allocate_table((void **)&fru_board_data_table[table_index], table_size); + if (!sensor_data) + return false; + + sensor_data->data_length = fru_length; + memcpy(sensor_data->fru_data, fru_string, fru_length); + + *buffer_size = (uint8_t)table_size; + return true; +} + +bool initialize_fru_product_data(telemetry_info *telemetry_info, uint8_t *buffer_size) +{ + CHECK_NULL_ARG_WITH_RETURN(telemetry_info, false); + + int table_index = telemetry_info->telemetry_offset - FRU_PRODUCT_NAME_REG; + if (table_index < 0 || table_index >= DATA_TABLE_LENGTH_7) + return false; + + char *fru_string = NULL; + uint8_t fru_length = 0; + if (!get_fru_info_element(telemetry_info, &fru_string, &fru_length)) { + LOG_ERR("Failed to retrieve FRU Element"); + } + + size_t table_size = sizeof(plat_fru_data) + fru_length; + plat_fru_data *sensor_data = + allocate_table((void **)&fru_product_data_table[table_index], table_size); + if (!sensor_data) + return false; + + sensor_data->data_length = fru_length; + memcpy(sensor_data->fru_data, fru_string, fru_length); + + *buffer_size = (uint8_t)table_size; + return true; +} + void update_sensor_reading_by_sensor_number(uint8_t sensor_number) { // sensor number is 1-base but index is 0-base @@ -396,23 +546,19 @@ void vr_power_reading(uint8_t *buffer, size_t buf_size) continue; } - uint8_t status = SENSOR_UNAVAILABLE; - int reading = 0; - uint8_t sensor_operational_state = PLDM_SENSOR_STATUSUNKOWN; + uint16_t val = 0; + float float_value = 0; + float_value = get_sensor_reading_cache_as_float(vr_pwr_sensor_table[i]); + val = (float_value + 500) / 1000; - status = pldm_sensor_get_reading_from_cache(vr_pwr_sensor_table[i], &reading, - &sensor_operational_state); - // reading value unit is mW need to convert to W - reading = (reading + 500) / 1000; - uint16_t val = (uint16_t)reading; switch (vr_pwr_sensor_table[i]) { case SENSOR_NUM_ASIC_P0V85_MEDHA0_VDD_PWR_W: memcpy(&buffer[6], &val, 2); - medha0 = reading; + medha0 = float_value; break; case SENSOR_NUM_ASIC_P0V85_MEDHA1_VDD_PWR_W: memcpy(&buffer[8], &val, 2); - medha1 = reading; + medha1 = float_value; break; case SENSOR_NUM_ASIC_P1V1_VDDQC_HBM0246_PWR_W: memcpy(&buffer[10], &val, 2); @@ -457,24 +603,20 @@ void vr_power_reading(uint8_t *buffer, size_t buf_size) // do nothing break; } - LOG_DBG("Sensor 0x%x: status = %d, reading = 0x%x", vr_pwr_sensor_table[i], status, - reading); if (vr_pwr_sensor_table[i] != SENSOR_NUM_ASIC_P0V85_MEDHA0_VDD_PWR_W && vr_pwr_sensor_table[i] != SENSOR_NUM_ASIC_P0V85_MEDHA1_VDD_PWR_W) { - x += reading; + x += float_value; } } int reading; get_cpld_polling_power_info(&reading); - reading = (reading + 500) / 1000; uint16_t val = (uint16_t)reading; memcpy(&buffer[36], &val, 2); - x += reading; - chiplet0 = medha0 + 0.5 * x; - chiplet1 = medha1 + 0.5 * x; - uint16_t val_x = (uint16_t)x; + chiplet0 = ((medha0 + 0.5 * x) + 500) / 1000; + chiplet1 = ((medha1 + 0.5 * x) + 500) / 1000; + uint16_t val_x = (uint16_t)(x + 500) / 1000; uint16_t val_c0 = (uint16_t)chiplet0; uint16_t val_c1 = (uint16_t)chiplet1; memcpy(&buffer[0], &val_x, 2); @@ -528,84 +670,6 @@ void set_vr_pwr_alert_data(uint8_t controller_id, uint8_t alert_level, uint8_t d controller_id, alert_level, write_data_lsb, write_data_msb); LOG_HEXDUMP_DBG(vr_alert_all, sizeof(vr_alert_all), "vr_alert_all"); }; -void get_vr_pwr_alert_data(uint8_t *buffer, size_t buf_size, uint8_t data_type, uint8_t alert_level, - uint8_t controller_id) -{ - if (alert_level >= VR_ALERT_MAX) { - LOG_ERR("Invalid alert level %d", alert_level); - return; - } - - if (data_type >= VR_INFO_TYPE_MAX) { - LOG_ERR("Invalid data type %d", data_type); - return; - } - - if (data_type == VR_THRESHOLD) { - switch (controller_id) { - /* - Response Data - [0] - time window. Unit: us for Level 1, ms for Level 2/3 (LSB, read only) - [1] - time window. Unit: us for Level 1, ms for Level 2/3 (MSB, read only) - */ - case MEDHA0: - // update read data from write data - vr_alert_all[MEDHA0].level[alert_level].read_data_msb = - vr_alert_all[MEDHA0].level[alert_level].threshold_msb; - vr_alert_all[MEDHA0].level[alert_level].read_data_lsb = - vr_alert_all[MEDHA0].level[alert_level].threshold_lsb; - // copy data to buffer - buffer[0] = vr_alert_all[MEDHA0].level[alert_level].read_data_lsb; - buffer[1] = vr_alert_all[MEDHA0].level[alert_level].read_data_msb; - - break; - case MEDHA1: - // update read data from write data - vr_alert_all[MEDHA1].level[alert_level].read_data_msb = - vr_alert_all[MEDHA1].level[alert_level].threshold_msb; - vr_alert_all[MEDHA1].level[alert_level].read_data_lsb = - vr_alert_all[MEDHA1].level[alert_level].threshold_lsb; - // copy data to buffer - buffer[0] = vr_alert_all[MEDHA1].level[alert_level].read_data_lsb; - buffer[1] = vr_alert_all[MEDHA1].level[alert_level].read_data_msb; - break; - default: - LOG_ERR("Invalid controller id %d", controller_id); - break; - } - } else if (data_type == VR_TIME_WINDOW) { - switch (controller_id) { - case MEDHA0: - // update read data from write data - vr_alert_all[MEDHA0].level[alert_level].read_data_msb = - vr_alert_all[MEDHA0].level[alert_level].time_window_msb; - vr_alert_all[MEDHA0].level[alert_level].read_data_lsb = - vr_alert_all[MEDHA0].level[alert_level].time_window_lsb; - // // copy data to buffer - buffer[0] = vr_alert_all[MEDHA0].level[alert_level].read_data_lsb; - buffer[1] = vr_alert_all[MEDHA0].level[alert_level].read_data_msb; - break; - case MEDHA1: - // update read data from write data - vr_alert_all[MEDHA1].level[alert_level].read_data_msb = - vr_alert_all[MEDHA1].level[alert_level].time_window_msb; - vr_alert_all[MEDHA1].level[alert_level].read_data_lsb = - vr_alert_all[MEDHA1].level[alert_level].time_window_lsb; - - // copy data to buffer - buffer[0] = vr_alert_all[MEDHA1].level[alert_level].read_data_lsb; - buffer[1] = vr_alert_all[MEDHA1].level[alert_level].read_data_msb; - break; - default: - LOG_ERR("Invalid controller id %d", controller_id); - break; - } - } else - LOG_ERR("Invalid data type %d", data_type); - LOG_DBG("controller_id %d, alert_level %d, data_type %d, read_data_lsb %d, read_data_msb %d", - controller_id, alert_level, data_type, buffer[0], buffer[1]); - LOG_HEXDUMP_DBG(vr_alert_all, sizeof(vr_alert_all), "vr_alert_all"); -}; telemetry_info telemetry_info_table[] = { { SENSOR_INIT_DATA_0_REG, 0x00, .telemetry_table_init = initialize_sensor_data }, @@ -620,8 +684,29 @@ telemetry_info telemetry_info_table[] = { { I2C_BRIDGE_COMMAND_REG }, { I2C_BRIDGE_COMMAND_STATUS_REG }, { I2C_BRIDGE_COMMAND_RESPONSE_REG }, - { LEVEL_1_2_3_PWR_ALERT_THRESHOLD_REG }, - { LEVEL_1_2_3_PWR_ALERT_TIME_WINDOW_REG }, + { FRU_BOARD_PART_NUMBER_REG, 0x00, .telemetry_table_init = initialize_fru_board_data }, + { FRU_BOARD_SERIAL_NUMBER_REG, 0x00, .telemetry_table_init = initialize_fru_board_data }, + { FRU_BOARD_PRODUCT_NAME_REG, 0x00, .telemetry_table_init = initialize_fru_board_data }, + { FRU_BOARD_CUSTOM_DATA_1_REG, 0x00, .telemetry_table_init = initialize_fru_board_data }, + { FRU_BOARD_CUSTOM_DATA_2_REG, 0x00, .telemetry_table_init = initialize_fru_board_data }, + { FRU_BOARD_CUSTOM_DATA_3_REG, 0x00, .telemetry_table_init = initialize_fru_board_data }, + { FRU_BOARD_CUSTOM_DATA_4_REG, 0x00, .telemetry_table_init = initialize_fru_board_data }, + { FRU_BOARD_CUSTOM_DATA_5_REG, 0x00, .telemetry_table_init = initialize_fru_board_data }, + { FRU_BOARD_CUSTOM_DATA_6_REG, 0x00, .telemetry_table_init = initialize_fru_board_data }, + { FRU_BOARD_CUSTOM_DATA_7_REG, 0x00, .telemetry_table_init = initialize_fru_board_data }, + { FRU_BOARD_CUSTOM_DATA_8_REG, 0x00, .telemetry_table_init = initialize_fru_board_data }, + { FRU_BOARD_CUSTOM_DATA_9_REG, 0x00, .telemetry_table_init = initialize_fru_board_data }, + { FRU_BOARD_CUSTOM_DATA_10_REG, 0x00, .telemetry_table_init = initialize_fru_board_data }, + { FRU_PRODUCT_NAME_REG, 0x00, .telemetry_table_init = initialize_fru_product_data }, + { FRU_PRODUCT_PART_NUMBER_REG, 0x00, .telemetry_table_init = initialize_fru_product_data }, + { FRU_PRODUCT_PART_VERSION_REG, 0x00, .telemetry_table_init = initialize_fru_product_data }, + { FRU_PRODUCT_SERIAL_NUMBER_REG, 0x00, + .telemetry_table_init = initialize_fru_product_data }, + { FRU_PRODUCT_ASSET_TAG_REG, 0x00, .telemetry_table_init = initialize_fru_product_data }, + { FRU_PRODUCT_CUSTOM_DATA_1_REG, 0x00, + .telemetry_table_init = initialize_fru_product_data }, + { FRU_PRODUCT_CUSTOM_DATA_2_REG, 0x00, + .telemetry_table_init = initialize_fru_product_data }, { VR_POWER_READING_REG }, }; @@ -704,6 +789,36 @@ static bool command_reply_data_handle(void *arg) data->target_rd_msg.msg_length, "i2c bridge command response"); } break; + case FRU_BOARD_PART_NUMBER_REG: + case FRU_BOARD_SERIAL_NUMBER_REG: + case FRU_BOARD_PRODUCT_NAME_REG: + case FRU_BOARD_CUSTOM_DATA_1_REG: + case FRU_BOARD_CUSTOM_DATA_2_REG: + case FRU_BOARD_CUSTOM_DATA_3_REG: + case FRU_BOARD_CUSTOM_DATA_4_REG: + case FRU_BOARD_CUSTOM_DATA_5_REG: + case FRU_BOARD_CUSTOM_DATA_6_REG: + case FRU_BOARD_CUSTOM_DATA_7_REG: + case FRU_BOARD_CUSTOM_DATA_8_REG: + case FRU_BOARD_CUSTOM_DATA_9_REG: + case FRU_BOARD_CUSTOM_DATA_10_REG: { + data->target_rd_msg.msg_length = struct_size; + memcpy(data->target_rd_msg.msg, + fru_board_data_table[reg_offset - FRU_BOARD_PART_NUMBER_REG], + struct_size); + } break; + case FRU_PRODUCT_NAME_REG: + case FRU_PRODUCT_PART_NUMBER_REG: + case FRU_PRODUCT_PART_VERSION_REG: + case FRU_PRODUCT_SERIAL_NUMBER_REG: + case FRU_PRODUCT_ASSET_TAG_REG: + case FRU_PRODUCT_CUSTOM_DATA_1_REG: + case FRU_PRODUCT_CUSTOM_DATA_2_REG: { + data->target_rd_msg.msg_length = struct_size; + memcpy(data->target_rd_msg.msg, + fru_product_data_table[reg_offset - FRU_PRODUCT_NAME_REG], + struct_size); + } break; case CONTROL_VOL_VR_ASIC_P0V75_VDDPHY_HBM0246_REG: case CONTROL_VOL_VR_ASIC_P0V75_VDDPHY_HBM1357_REG: case CONTROL_VOL_VR_ASIC_P1V1_VDDQC_HBM0246_REG: @@ -723,6 +838,32 @@ static bool command_reply_data_handle(void *arg) memcpy(data->target_rd_msg.msg, &vout, sizeof(vout)); data->target_rd_msg.msg_length = 2; } break; + case LEVEL_1_PWR_ALERT_THRESHOLD_TIME_REG: + case LEVEL_2_PWR_ALERT_THRESHOLD_TIME_REG: + case LEVEL_3_PWR_ALERT_THRESHOLD_TIME_REG: { + uint8_t lv = 0; + uint16_t tmp_value = 0; + if (reg_offset == LEVEL_1_PWR_ALERT_THRESHOLD_TIME_REG) { + lv = CAPPING_LV_IDX_LV1; + } else if (reg_offset == LEVEL_2_PWR_ALERT_THRESHOLD_TIME_REG) { + lv = CAPPING_LV_IDX_LV2; + } else if (reg_offset == LEVEL_3_PWR_ALERT_THRESHOLD_TIME_REG) { + lv = CAPPING_LV_IDX_LV3; + } + tmp_value = get_power_capping_threshold(CAPPING_VR_IDX_MEDHA0, lv); + data->target_rd_msg.msg[0] = tmp_value & 0xFF; + data->target_rd_msg.msg[1] = tmp_value >> 8; + tmp_value = get_power_capping_time_w(CAPPING_VR_IDX_MEDHA0, lv); + data->target_rd_msg.msg[2] = tmp_value & 0xFF; + data->target_rd_msg.msg[3] = tmp_value >> 8; + tmp_value = get_power_capping_threshold(CAPPING_VR_IDX_MEDHA1, lv); + data->target_rd_msg.msg[4] = tmp_value & 0xFF; + data->target_rd_msg.msg[5] = tmp_value >> 8; + tmp_value = get_power_capping_time_w(CAPPING_VR_IDX_MEDHA1, lv); + data->target_rd_msg.msg[6] = tmp_value & 0xFF; + data->target_rd_msg.msg[7] = tmp_value >> 8; + data->target_rd_msg.msg_length = 8; + } break; case VR_POWER_READING_REG: { data->target_rd_msg.msg_length = VR_PWR_BUF_SIZE; vr_power_reading(data->target_rd_msg.msg, @@ -730,6 +871,23 @@ static bool command_reply_data_handle(void *arg) LOG_HEXDUMP_DBG(data->target_rd_msg.msg, data->target_rd_msg.msg_length, "vr power reading"); } break; + case MEDHA_SENSOR_VALUE_REG: { + data->target_rd_msg.msg_length = 4; + uint16_t sensor_value; + sensor_value = (get_sensor_reading_cache_as_float( + SENSOR_NUM_ASIC_P0V85_MEDHA0_VDD_PWR_W) + + 500) / + 1000; + memcpy(&data->target_rd_msg.msg[0], &sensor_value, + sizeof(sensor_value)); + sensor_value = (get_sensor_reading_cache_as_float( + SENSOR_NUM_ASIC_P0V85_MEDHA1_VDD_PWR_W) + + 500) / + 1000; + memcpy(&data->target_rd_msg.msg[2], &sensor_value, + sizeof(sensor_value)); + + } break; case TRAY_INFO_REG: { /* TRAY_INFO_REG: * Byte0: MMC slot @@ -777,41 +935,6 @@ static bool command_reply_data_handle(void *arg) data->target_rd_msg.msg[0] = 0xFF; break; } - } else if (data->wr_buffer_idx == 3) { - LOG_DBG("Received reg offset(write 3 data): 0x%02x", - data->target_wr_msg.msg[0]); - uint8_t reg_offset = data->target_wr_msg.msg[0]; - switch (reg_offset) { - case LEVEL_1_2_3_PWR_ALERT_THRESHOLD_REG: { - data->target_rd_msg.msg_length = 2; - uint8_t vr_controller = data->target_wr_msg.msg[1]; - uint8_t alert_level = data->target_wr_msg.msg[2]; - get_vr_pwr_alert_data(data->target_rd_msg.msg, - data->target_rd_msg.msg_length, VR_THRESHOLD, - alert_level, vr_controller); - LOG_DBG("vr controller: %d, alert level: %d", vr_controller, - alert_level); - LOG_HEXDUMP_DBG(data->target_rd_msg.msg, - data->target_rd_msg.msg_length, "vr threshold"); - } break; - case LEVEL_1_2_3_PWR_ALERT_TIME_WINDOW_REG: { - data->target_rd_msg.msg_length = 2; - uint8_t vr_controller = data->target_wr_msg.msg[1]; - uint8_t alert_level = data->target_wr_msg.msg[2]; - get_vr_pwr_alert_data(data->target_rd_msg.msg, - data->target_rd_msg.msg_length, - VR_TIME_WINDOW, alert_level, vr_controller); - LOG_DBG("vr controller: %d, alert level: %d", vr_controller, - alert_level); - LOG_HEXDUMP_DBG(data->target_rd_msg.msg, - data->target_rd_msg.msg_length, "vr time window"); - } break; - default: - LOG_ERR("Unknown reg offset: 0x%02x", reg_offset); - data->target_rd_msg.msg_length = 1; - data->target_rd_msg.msg[0] = 0xFF; - break; - } } else { LOG_ERR("Received data length: 0x%02x", data->wr_buffer_idx); data->target_rd_msg.msg_length = 1; @@ -819,7 +942,7 @@ static bool command_reply_data_handle(void *arg) } } LOG_DBG("Reply data length: 0x%02x", data->target_rd_msg.msg_length); - return true; + return false; } /* I2C target init-config table */ @@ -931,6 +1054,7 @@ void i2c_bridge_command_handler(struct k_work *work_item) memcpy(sensor_data_response->response_data, i2c_msg.data, response_data_len); } } + void set_control_voltage_handler(struct k_work *work_item) { const plat_control_voltage *sensor_data = @@ -941,6 +1065,26 @@ void set_control_voltage_handler(struct k_work *work_item) plat_set_vout_command(rail, &millivolt, false, false); } + +void set_power_capping_threshold_time_handler(struct k_work *work_item) +{ + const plat_power_capping_threshold_time_t *sensor_data = + CONTAINER_OF(work_item, plat_power_capping_threshold_time_t, work); + const uint8_t *in_data = sensor_data->in_data; + uint8_t lv = sensor_data->lv; + uint16_t value = 0; + + value = in_data[0] | (in_data[1] << 8); + set_power_capping_threshold(CAPPING_VR_IDX_MEDHA0, lv, value); + value = in_data[2] | (in_data[3] << 8); + set_power_capping_time_w(CAPPING_VR_IDX_MEDHA0, lv, value); + + value = in_data[4] | (in_data[5] << 8); + set_power_capping_threshold(CAPPING_VR_IDX_MEDHA1, lv, value); + value = in_data[6] | (in_data[7] << 8); + set_power_capping_time_w(CAPPING_VR_IDX_MEDHA1, lv, value); +} + void plat_master_write_thread_handler() { int rc = 0; @@ -1021,6 +1165,31 @@ void plat_master_write_thread_handler() k_work_init(&sensor_data->work, set_control_voltage_handler); k_work_submit(&sensor_data->work); } break; + case LEVEL_1_PWR_ALERT_THRESHOLD_TIME_REG: + case LEVEL_2_PWR_ALERT_THRESHOLD_TIME_REG: + case LEVEL_3_PWR_ALERT_THRESHOLD_TIME_REG: { + if (rlen != 9) { + LOG_ERR("Invalid length for offset(write): 0x%02x", reg_offset); + break; + } + + plat_power_capping_threshold_time_t *sensor_data = + malloc(sizeof(plat_power_capping_threshold_time_t)); + if (!sensor_data) { + LOG_ERR("Memory allocation failed!"); + break; + } + if (reg_offset == LEVEL_1_PWR_ALERT_THRESHOLD_TIME_REG) { + sensor_data->lv = CAPPING_LV_IDX_LV1; + } else if (reg_offset == LEVEL_2_PWR_ALERT_THRESHOLD_TIME_REG) { + sensor_data->lv = CAPPING_LV_IDX_LV2; + } else if (reg_offset == LEVEL_3_PWR_ALERT_THRESHOLD_TIME_REG) { + sensor_data->lv = CAPPING_LV_IDX_LV3; + } + memcpy(sensor_data->in_data, &rdata[1], 8); + k_work_init(&sensor_data->work, set_power_capping_threshold_time_handler); + k_work_submit(&sensor_data->work); + } break; case SET_SENSOR_POLLING_COMMAND_REG: { if (rlen != 8) { LOG_ERR("Invalid length for offset: 0x%02x", reg_offset); @@ -1049,42 +1218,6 @@ void plat_master_write_thread_handler() k_work_init(&sensor_data->work, set_sensor_polling_handler); k_work_submit(&sensor_data->work); } break; - /* - Request Data - [0] - VR controller - 0 - MEDHA0 - 1 - MEDHA1 - [1] - alert level - 0 - Level 1 - 1 - Level 2 - 2 - Level 3 - [2] - alert threshold. Unit: W (LSB, write only) - [3] - alert threshold. Unit: W (MSB, write only) - */ - case LEVEL_1_2_3_PWR_ALERT_THRESHOLD_REG: { - if (rlen != 5) { - LOG_ERR("Invalid length for offset(write threshold): 0x%02x", - reg_offset); - break; - } - uint8_t vr_controller = rdata[1]; - uint8_t alert_level = rdata[2]; - uint8_t lsb = rdata[3]; - uint8_t msb = rdata[4]; - set_vr_pwr_alert_data(vr_controller, alert_level, VR_THRESHOLD, lsb, msb); - } break; - case LEVEL_1_2_3_PWR_ALERT_TIME_WINDOW_REG: { - if (rlen != 5) { - LOG_ERR("Invalid length for offset(write time window): 0x%02x", - reg_offset); - break; - } - uint8_t vr_controller = rdata[1]; - uint8_t alert_level = rdata[2]; - uint8_t lsb = rdata[3]; - uint8_t msb = rdata[4]; - set_vr_pwr_alert_data(vr_controller, alert_level, VR_TIME_WINDOW, lsb, msb); - } break; default: LOG_WRN("Unknown reg offset(write): 0x%02x", reg_offset); break; diff --git a/meta-facebook/sb-rb/src/platform/plat_i2c_target.h b/meta-facebook/sb-rb/src/platform/plat_i2c_target.h index b45b63c46b..d53bb0749b 100644 --- a/meta-facebook/sb-rb/src/platform/plat_i2c_target.h +++ b/meta-facebook/sb-rb/src/platform/plat_i2c_target.h @@ -36,6 +36,29 @@ #define I2C_BRIDGE_COMMAND_REG 0x40 #define I2C_BRIDGE_COMMAND_STATUS_REG 0x41 #define I2C_BRIDGE_COMMAND_RESPONSE_REG 0x42 + +#define FRU_BOARD_PART_NUMBER_REG 0x60 +#define FRU_BOARD_SERIAL_NUMBER_REG 0x61 +#define FRU_BOARD_PRODUCT_NAME_REG 0x62 +#define FRU_BOARD_CUSTOM_DATA_1_REG 0x63 +#define FRU_BOARD_CUSTOM_DATA_2_REG 0x64 +#define FRU_BOARD_CUSTOM_DATA_3_REG 0x65 +#define FRU_BOARD_CUSTOM_DATA_4_REG 0x66 +#define FRU_BOARD_CUSTOM_DATA_5_REG 0x67 +#define FRU_BOARD_CUSTOM_DATA_6_REG 0x68 +#define FRU_BOARD_CUSTOM_DATA_7_REG 0x69 +#define FRU_BOARD_CUSTOM_DATA_8_REG 0x6A +#define FRU_BOARD_CUSTOM_DATA_9_REG 0x6B +#define FRU_BOARD_CUSTOM_DATA_10_REG 0x6C + +#define FRU_PRODUCT_NAME_REG 0x70 +#define FRU_PRODUCT_PART_NUMBER_REG 0x71 +#define FRU_PRODUCT_PART_VERSION_REG 0x72 +#define FRU_PRODUCT_SERIAL_NUMBER_REG 0x73 +#define FRU_PRODUCT_ASSET_TAG_REG 0x74 +#define FRU_PRODUCT_CUSTOM_DATA_1_REG 0x75 +#define FRU_PRODUCT_CUSTOM_DATA_2_REG 0x76 + #define CONTROL_VOL_VR_ASIC_P0V75_VDDPHY_HBM0246_REG 0x80 #define CONTROL_VOL_VR_ASIC_P0V75_VDDPHY_HBM1357_REG 0x81 #define CONTROL_VOL_VR_ASIC_P1V1_VDDQC_HBM0246_REG 0x82 @@ -46,9 +69,11 @@ #define CONTROL_VOL_VR_ASIC_P1V8_VPP_HBM1357_REG 0x87 #define CONTROL_VOL_VR_ASIC_P0V85_MEDHA0_VDD_REG 0x88 #define CONTROL_VOL_VR_ASIC_P0V85_MEDHA1_VDD_REG 0x89 -#define LEVEL_1_2_3_PWR_ALERT_THRESHOLD_REG 0x90 -#define LEVEL_1_2_3_PWR_ALERT_TIME_WINDOW_REG 0x91 +#define LEVEL_1_PWR_ALERT_THRESHOLD_TIME_REG 0x90 +#define LEVEL_2_PWR_ALERT_THRESHOLD_TIME_REG 0x91 +#define LEVEL_3_PWR_ALERT_THRESHOLD_TIME_REG 0x92 #define VR_POWER_READING_REG 0x93 +#define MEDHA_SENSOR_VALUE_REG 0x94 #define TRAY_INFO_REG 0x98 #define SET_SENSOR_POLLING_COMMAND_REG 0xF0 @@ -175,6 +200,11 @@ typedef struct __attribute__((__packed__)) { uint8_t rail; uint16_t set_value; } plat_control_voltage; +typedef struct __attribute__((__packed__)) { + struct k_work work; + uint8_t lv; + uint8_t in_data[8]; +} plat_power_capping_threshold_time_t; typedef struct __attribute__((__packed__)) { struct k_work work; uint8_t set_value; diff --git a/meta-facebook/sb-rb/src/platform/plat_init.c b/meta-facebook/sb-rb/src/platform/plat_init.c index 8fe079ca47..cef375bd0d 100644 --- a/meta-facebook/sb-rb/src/platform/plat_init.c +++ b/meta-facebook/sb-rb/src/platform/plat_init.c @@ -33,6 +33,10 @@ #include "plat_hwmon.h" #include "plat_ioexp.h" #include "plat_thermal.h" +#include "plat_gpio.h" +#include "plat_event.h" +#include "plat_vr_test_mode.h" +#include "plat_power_capping.h" LOG_MODULE_REGISTER(plat_init); @@ -65,11 +69,16 @@ void pal_post_init() pldm_assign_gpio_effecter_id(PLAT_EFFECTER_ID_GPIO_HIGH_BYTE); init_fru_info(); plat_adc_rainbow_init(); + plat_power_capping_init(); init_load_eeprom_log(); - // if board id >= EVB EVT1B(FAB2) if (get_asic_board_id() == ASIC_BOARD_ID_EVB && get_board_rev_id() >= REV_ID_EVT1B) { + // if board id >= EVB EVT1B(FAB2) quick_sensor_poll_init(); init_U200052_IO(); + init_U200053_IO(); + // if board id >= EVB EVT1B(FAB3) + if (get_board_rev_id() >= REV_ID_EVT2) + init_U200070_IO(); } // if board id == EVB if (get_asic_board_id() == ASIC_BOARD_ID_EVB) { @@ -82,6 +91,10 @@ void pal_post_init() plat_telemetry_table_init(); ioexp_init(); init_thermal_polling(); + init_vr_test_mode_polling(); + // check the thermtrip open-circuit + if (!gpio_get(FM_ASIC_0_THERMTRIP_R_N)) + asic_thermtrip_error_log(LOG_ASSERT); } #define DEF_PROJ_GPIO_PRIORITY 78 diff --git a/meta-facebook/sb-rb/src/platform/plat_ioexp.c b/meta-facebook/sb-rb/src/platform/plat_ioexp.c index 555157d8bc..6125d2e744 100644 --- a/meta-facebook/sb-rb/src/platform/plat_ioexp.c +++ b/meta-facebook/sb-rb/src/platform/plat_ioexp.c @@ -5,6 +5,7 @@ #include "plat_ioexp.h" #include "plat_class.h" #include "plat_pldm_sensor.h" +#include "plat_hook.h" LOG_MODULE_REGISTER(plat_ioexp); @@ -36,11 +37,58 @@ bool pca6416a_init(void) } // tca6424a +bool is_tca6424a_accessible() +{ + return (get_asic_board_id() == ASIC_BOARD_ID_EVB && is_mb_dc_on()); +} + bool tca6424a_i2c_read(uint8_t offset, uint8_t *data, uint8_t len) { return plat_i2c_read(TCA6424A_BUS, TCA6424A_ADDR, (offset | TCA6424A_AI_BIT), data, len); } +bool tca6424a_i2c_read_drive_value(uint8_t group, uint8_t bit, uint8_t *data) +{ + uint8_t value = 0; + uint8_t confg_reg = 0; + uint8_t input_reg = 0; + uint8_t output_reg = 0; + + if (group == 0) { + confg_reg = TCA6424A_CONFIG_0; + input_reg = TCA6424A_INPUT_PORT_0; + output_reg = TCA6424A_OUTPUT_PORT_0; + } else if (group == 1) { + confg_reg = TCA6424A_CONFIG_1; + input_reg = TCA6424A_INPUT_PORT_1; + output_reg = TCA6424A_OUTPUT_PORT_1; + } else if (group == 2) { + confg_reg = TCA6424A_CONFIG_2; + input_reg = TCA6424A_INPUT_PORT_2; + output_reg = TCA6424A_OUTPUT_PORT_2; + } else { + LOG_ERR("Wrong group!"); + return false; + } + + if (!tca6424a_i2c_read(confg_reg, &value, 1)) { + return false; + } + + if (value & BIT(bit)) { + if (!tca6424a_i2c_read(input_reg, &value, 1)) { + return false; + } + } else { + if (!tca6424a_i2c_read(output_reg, &value, 1)) { + return false; + } + } + *data = (value & BIT(bit)) >> bit; + + return true; +} + bool tca6424a_i2c_write(uint8_t offset, uint8_t *data, uint8_t len) { return plat_i2c_write(TCA6424A_BUS, TCA6424A_ADDR, (offset | TCA6424A_AI_BIT), data, len); @@ -69,9 +117,51 @@ bool tca6424a_i2c_write_bit(uint8_t offset, uint8_t bit, uint8_t val) return true; } +void set_hamsa_mfio_6_8_10_input() +{ + tca6424a_i2c_write_bit(TCA6424A_CONFIG_1, HAMSA_MFIO6, 1); + tca6424a_i2c_write_bit(TCA6424A_CONFIG_1, HAMSA_MFIO8, 1); + tca6424a_i2c_write_bit(TCA6424A_CONFIG_2, HAMSA_MFIO10, 1); +} + +void set_medha0_mfio_6_8_10_input() +{ + tca6424a_i2c_write_bit(TCA6424A_CONFIG_2, MEDHA0_MFIO6, 1); + tca6424a_i2c_write_bit(TCA6424A_CONFIG_2, MEDHA0_MFIO8, 1); + tca6424a_i2c_write_bit(TCA6424A_CONFIG_2, MEDHA0_MFIO10, 1); +} + +void set_medha1_mfio_6_8_10_input() +{ + tca6424a_i2c_write_bit(TCA6424A_CONFIG_2, MEDHA1_MFIO6, 1); + tca6424a_i2c_write_bit(TCA6424A_CONFIG_2, MEDHA1_MFIO8, 1); + tca6424a_i2c_write_bit(TCA6424A_CONFIG_2, MEDHA1_MFIO10, 1); +} + +void set_hamsa_mfio_6_8_10_output() +{ + tca6424a_i2c_write_bit(TCA6424A_CONFIG_1, HAMSA_MFIO6, 0); + tca6424a_i2c_write_bit(TCA6424A_CONFIG_1, HAMSA_MFIO8, 0); + tca6424a_i2c_write_bit(TCA6424A_CONFIG_2, HAMSA_MFIO10, 0); +} + +void set_medha0_mfio_6_8_10_output() +{ + tca6424a_i2c_write_bit(TCA6424A_CONFIG_2, MEDHA0_MFIO6, 0); + tca6424a_i2c_write_bit(TCA6424A_CONFIG_2, MEDHA0_MFIO8, 0); + tca6424a_i2c_write_bit(TCA6424A_CONFIG_2, MEDHA0_MFIO10, 0); +} + +void set_medha1_mfio_6_8_10_output() +{ + tca6424a_i2c_write_bit(TCA6424A_CONFIG_2, MEDHA1_MFIO6, 0); + tca6424a_i2c_write_bit(TCA6424A_CONFIG_2, MEDHA1_MFIO8, 0); + tca6424a_i2c_write_bit(TCA6424A_CONFIG_2, MEDHA1_MFIO10, 0); +} + bool tca6424a_init(void) { - uint8_t data[3] = { 0x00, 0x00, 0x00 }; // all output + uint8_t data[3] = { 0xFD, 0xFF, 0xFD }; // HAMSA_MFIO19 out, OWL_EW_VQPS out if (!tca6424a_i2c_write(TCA6424A_CONFIG_0, data, 3)) return false; @@ -86,13 +176,34 @@ bool tca6424a_init(void) // total void ioexp_init(void) { + // read from IO, save value (if output) to table + set_ioexp_val_to_bootstrap_table(); + if (!pca6416a_init()) LOG_ERR("pca6416a init fail"); - if (get_asic_board_id() == ASIC_BOARD_ID_EVB) { + if (is_tca6424a_accessible()) { if (!tca6424a_init()) LOG_ERR("tca6424a init fail"); } + + // set to output if TEST_STRAP enable + int drive_level = 0; + get_bootstrap_change_drive_level(STRAP_INDEX_HAMSA_TEST_STRAP_R, &drive_level); + if (drive_level == 1) { + set_hamsa_mfio_6_8_10_output(); + } + get_bootstrap_change_drive_level(STRAP_INDEX_MEDHA0_TEST_STRAP, &drive_level); + if (drive_level == 1) { + set_medha0_mfio_6_8_10_output(); + } + get_bootstrap_change_drive_level(STRAP_INDEX_MEDHA1_TEST_STRAP, &drive_level); + if (drive_level == 1) { + set_medha1_mfio_6_8_10_output(); + } + + // set value from table + set_bootstrap_table_val_to_ioexp(); } void set_pca6554apw_ioe_value(uint8_t ioe_bus, uint8_t ioe_addr, uint8_t ioe_reg, uint8_t value) { @@ -145,10 +256,26 @@ void init_U200052_IO() // bit0 to bit5 is input (1) set_pca6554apw_ioe_value(U200052_IO_I2C_BUS, U200052_IO_ADDR, CONFIG, 0x3F); // io6,io7 default output 0 - set_pca6554apw_ioe_value(U200052_IO_I2C_BUS, U200052_IO_ADDR, OUTPUT_PORT, 0x0); + set_pca6554apw_ioe_value(U200052_IO_I2C_BUS, U200052_IO_ADDR, OUTPUT_PORT, + U200052_IO_INIT_VAL); +} +//evb only +void init_U200053_IO() +{ + LOG_INF("init U200053 IO expander"); + // bit0 to bit5 is input (1) + set_pca6554apw_ioe_value(U200053_IO_I2C_BUS, U200053_IO_ADDR, CONFIG, 0xBF); + // io6 default output 1 + set_pca6554apw_ioe_value(U200053_IO_I2C_BUS, U200053_IO_ADDR, OUTPUT_PORT, + U200053_IO_INIT_VAL); +} +//evb2 only +void init_U200070_IO() +{ LOG_INF("init U200070 IO expander"); // bit3 to bit5 is input (1) set_pca6554apw_ioe_value(U200070_IO_I2C_BUS, U200070_IO_ADDR, CONFIG, 0x38); - // io0,io1,io2,io7 default output 0 - set_pca6554apw_ioe_value(U200070_IO_I2C_BUS, U200070_IO_ADDR, OUTPUT_PORT, 0x0); -} \ No newline at end of file + // io0,io1,io2 default output 1 io7 default output 0 + set_pca6554apw_ioe_value(U200070_IO_I2C_BUS, U200070_IO_ADDR, OUTPUT_PORT, + U200070_IO_INIT_VAL); +} diff --git a/meta-facebook/sb-rb/src/platform/plat_ioexp.h b/meta-facebook/sb-rb/src/platform/plat_ioexp.h index 9f18bf257c..29f08c7fb1 100644 --- a/meta-facebook/sb-rb/src/platform/plat_ioexp.h +++ b/meta-facebook/sb-rb/src/platform/plat_ioexp.h @@ -34,20 +34,45 @@ #define TCA6424A_CONFIG_1 0x0D #define TCA6424A_CONFIG_2 0x0E #define U200052_IO_ADDR 0x3A +#define U200053_IO_ADDR 0x3B #define U200070_IO_ADDR 0x3C -#define U200052_IO_I2C_BUS I2C_BUS1 #define U200051_IO_I2C_BUS I2C_BUS1 +#define U200052_IO_I2C_BUS I2C_BUS1 +#define U200053_IO_I2C_BUS I2C_BUS1 #define U200070_IO_I2C_BUS I2C_BUS1 +#define U200052_IO_INIT_VAL 0xC0 +#define U200053_IO_INIT_VAL 0x40 +#define U200070_IO_INIT_VAL 0x07 + #define HAMSA_MFIO19 1 +#define HAMSA_MFIO6 6 +#define HAMSA_MFIO8 7 +#define HAMSA_MFIO10 0 +#define MEDHA0_MFIO6 7 +#define MEDHA0_MFIO8 6 +#define MEDHA0_MFIO10 5 +#define MEDHA1_MFIO6 4 +#define MEDHA1_MFIO8 3 +#define MEDHA1_MFIO10 2 bool pca6416a_i2c_read(uint8_t offset, uint8_t *data, uint8_t len); bool pca6416a_i2c_write(uint8_t offset, uint8_t *data, uint8_t len); +bool is_tca6424a_accessible(); bool tca6424a_i2c_read(uint8_t offset, uint8_t *data, uint8_t len); +bool tca6424a_i2c_read_drive_value(uint8_t group, uint8_t bit, uint8_t *data); bool tca6424a_i2c_write(uint8_t offset, uint8_t *data, uint8_t len); bool tca6424a_i2c_write_bit(uint8_t offset, uint8_t bit, uint8_t val); +void set_hamsa_mfio_6_8_10_input(); +void set_medha0_mfio_6_8_10_input(); +void set_medha1_mfio_6_8_10_input(); +void set_hamsa_mfio_6_8_10_output(); +void set_medha0_mfio_6_8_10_output(); +void set_medha1_mfio_6_8_10_output(); void ioexp_init(void); void init_U200052_IO(); +void init_U200053_IO(); +void init_U200070_IO(); void set_pca6554apw_ioe_value(uint8_t ioe_bus, uint8_t ioe_addr, uint8_t ioe_reg, uint8_t value); int get_pca6554apw_ioe_value(uint8_t ioe_bus, uint8_t ioe_addr, uint8_t ioe_reg, uint8_t *value); diff --git a/meta-facebook/sb-rb/src/platform/plat_isr.c b/meta-facebook/sb-rb/src/platform/plat_isr.c index c8cc6e9ce0..a0a029a92d 100644 --- a/meta-facebook/sb-rb/src/platform/plat_isr.c +++ b/meta-facebook/sb-rb/src/platform/plat_isr.c @@ -30,6 +30,8 @@ #include "plat_i2c.h" #include "shell_iris_power.h" #include "plat_class.h" +#include "plat_vr_test_mode.h" +#include "plat_power_capping.h" LOG_MODULE_REGISTER(plat_isr); @@ -91,14 +93,26 @@ void ISR_GPIO_RST_IRIS_PWR_ON_PLD_R1_N() // dc on if (gpio_get(RST_IRIS_PWR_ON_PLD_R1_N)) { ioexp_init(); - set_bootstrap_table_val_to_ioexp(); if (get_asic_board_id() == ASIC_BOARD_ID_EVB) { init_U200052_IO(); + init_U200053_IO(); + init_U200070_IO(); power_on_p3v3_osfp(); } + for (int i = 0; i < CLK_COMPONENT_MAX; i++) { + clear_clock_status(NULL, i); + } + add_sync_oc_warn_to_work(); } else { LOG_INF("dc off, clear io expander init flag"); set_ioe_init_flag(0); + LOG_INF("dc off, exit the vr test mode"); + vr_test_mode_enable(false); + // when dc offm clear cpld polling alert status + uint8_t err_type = CPLD_UNEXPECTED_VAL_TRIGGER_CAUSE; + LOG_DBG("cpld_polling_alert_status: true -> false, reset_error_log_states: %x", + err_type); + reset_error_log_states(err_type); } } @@ -127,6 +141,11 @@ void ISR_GPIO_SMB_HAMSA_MMC_LVC33_ALERT_N() } } +void ISR_ASIC_THERMTRIP_TRIGGER() +{ + asic_thermtrip_error_log(LOG_ASSERT); +} + bool plat_gpio_immediate_int_cb(uint8_t gpio_num) { bool ret = false; @@ -140,4 +159,4 @@ bool plat_gpio_immediate_int_cb(uint8_t gpio_num) } return ret; -} \ No newline at end of file +} diff --git a/meta-facebook/sb-rb/src/platform/plat_isr.h b/meta-facebook/sb-rb/src/platform/plat_isr.h index 8739949c61..a01d29b5db 100644 --- a/meta-facebook/sb-rb/src/platform/plat_isr.h +++ b/meta-facebook/sb-rb/src/platform/plat_isr.h @@ -23,4 +23,5 @@ void ISR_GPIO_RST_IRIS_PWR_ON_PLD_R1_N(); void set_pwr_steps_on_flag(uint8_t flag_value); uint8_t get_pwr_steps_on_flag(void); void ISR_GPIO_SMB_HAMSA_MMC_LVC33_ALERT_N(); +void ISR_ASIC_THERMTRIP_TRIGGER(); #endif diff --git a/meta-facebook/sb-rb/src/platform/plat_log.c b/meta-facebook/sb-rb/src/platform/plat_log.c index cf05af7337..e28c8afa69 100644 --- a/meta-facebook/sb-rb/src/platform/plat_log.c +++ b/meta-facebook/sb-rb/src/platform/plat_log.c @@ -27,6 +27,9 @@ #include "plat_hook.h" #include "plat_class.h" #include "plat_pldm_sensor.h" +#include "tmp431.h" +#include "plat_gpio.h" +#include "plat_thermal.h" LOG_MODULE_REGISTER(plat_log); @@ -249,7 +252,8 @@ void plat_clear_log() k_msleep(EEPROM_MAX_WRITE_TIME); } log_num = 0; - next_index = 0; + next_index = 1; + next_log_position = 1; } bool vr_fault_get_error_data(uint8_t sensor_id, uint8_t *data) @@ -300,19 +304,44 @@ bool get_error_data(uint16_t error_code, uint8_t *data) CHECK_NULL_ARG_WITH_RETURN(data, false); // temperature error code uint8_t trigger_case = (error_code >> 13) & 0x07; - if (trigger_case == TEMPERATURE_TRIGGER_CAUSE) { + + switch (trigger_case) { + case TEMPERATURE_TRIGGER_CAUSE: { uint8_t temperature_sensoor_num = error_code & 0xFF; LOG_WRN("trigger_case: 0x%x, temperature_sensoor_num: 0x%x", trigger_case, temperature_sensoor_num); - if (!get_raw_data_from_sensor_id(temperature_sensoor_num, 0x02, data, 1)) { - LOG_ERR("Failed to get temperature data"); - return false; - }; + sensor_cfg *cfg = get_sensor_cfg_by_sensor_id(temperature_sensoor_num); + data[0] = get_thermal_status_val_for_log(temperature_sensoor_num); + if (data[0] & TEMP_STATUS_OPEN) { + if (!tmp432_get_temp_open_status(cfg, &data[1])) { + LOG_ERR("Failed to get 0x%02x temperature open status", + temperature_sensoor_num); + return false; + } + } else { + data[1] = get_thermal_limit_status_val_for_log(temperature_sensoor_num); + } // save sensor num to data and keep raw data - data[1] = temperature_sensoor_num; + data[2] = temperature_sensoor_num; LOG_INF("Temperature status: 0x%x, sensor num: 0x%x", data[0], data[1]); return true; } + case ASIC_THERMTRIP_TRIGGER_CAUSE: { + uint8_t cpld_data[3]; + if (!plat_read_cpld(HBM_CATTRIP_LOG_REG, cpld_data, 3)) { + LOG_ERR("Failed to get cpld data"); + return false; + } + data[0] = cpld_data[0]; + data[1] = cpld_data[2]; + return true; + } + case POWER_ON_SEQUENCE_TRIGGER_CAUSE: + case DC_ON_TRIGGER_CAUSE: { + data[0] = gpio_get(RST_IRIS_PWR_ON_PLD_R1_N); + return true; + } + } // Extract CPLD offset and bit position from the error code uint8_t cpld_offset = error_code & 0xFF; @@ -386,24 +415,20 @@ bool get_error_data(uint16_t error_code, uint8_t *data) void error_log_event(uint16_t error_code, bool log_status) { bool log_todo = false; - // if error_code is not temperature error - if (((error_code >> 13) & 0x07) != TEMPERATURE_TRIGGER_CAUSE) { - // Check if the error_code is already logged - for (uint8_t i = 1; i < ARRAY_SIZE(err_code_caches); i++) { - if (err_code_caches[i] == error_code) { - if (log_status == LOG_ASSERT) { - log_todo = false; // Duplicate error, no need to log again - LOG_INF("Duplicate error_code: 0x%x, log_status: %d", - error_code, log_status); - return; - } else if (log_status == LOG_DEASSERT) { - log_todo = true; // The error needs to be cleared - err_code_caches[i] = - 0; // Remove the error code from the cache - LOG_INF("Duplicate error_code: 0x%x, log_status: %d", - error_code, log_status); - return; - } + // Check if the error_code is already logged + for (uint8_t i = 1; i < ARRAY_SIZE(err_code_caches); i++) { + if (err_code_caches[i] == error_code) { + if (log_status == LOG_ASSERT) { + log_todo = false; // Duplicate error, no need to log again + LOG_INF("Duplicate error_code: 0x%x, log_status: %d", error_code, + log_status); + return; + } else if (log_status == LOG_DEASSERT) { + log_todo = true; // The error needs to be cleared + err_code_caches[i] = 0; // Remove the error code from the cache + LOG_INF("Duplicate error_code: 0x%x, log_status: %d", error_code, + log_status); + return; } } } diff --git a/meta-facebook/sb-rb/src/platform/plat_log.h b/meta-facebook/sb-rb/src/platform/plat_log.h index c92ed09f9b..4d4cd07ee9 100644 --- a/meta-facebook/sb-rb/src/platform/plat_log.h +++ b/meta-facebook/sb-rb/src/platform/plat_log.h @@ -107,6 +107,7 @@ enum LOG_ERROR_TRIGGER_CAUSE { AC_ON_TRIGGER_CAUSE = 0b010, DC_ON_TRIGGER_CAUSE = 0b011, TEMPERATURE_TRIGGER_CAUSE = 0b101, + ASIC_THERMTRIP_TRIGGER_CAUSE = 0b110, MAX_TRIGGER_CAUSE = 0b1000, //trigger cause maxium 3 bit }; diff --git a/meta-facebook/sb-rb/src/platform/plat_pldm_fw_update.c b/meta-facebook/sb-rb/src/platform/plat_pldm_fw_update.c index f5f5496007..e94f2fb15b 100644 --- a/meta-facebook/sb-rb/src/platform/plat_pldm_fw_update.c +++ b/meta-facebook/sb-rb/src/platform/plat_pldm_fw_update.c @@ -39,6 +39,7 @@ #define RESET_CPLD_ON 0x3F #define RESET_CPLD_OFF 0x00 #define IRIS_BOOT0_IMG_SIZE 0x1FFFFB +#define PLAT_WAIT_SENSOR_POLLING_END_DELAY_MS 1000 LOG_MODULE_REGISTER(plat_fwupdate); @@ -738,7 +739,7 @@ uint8_t pldm_post_iris_boot_update(void *fw_update_param) } #define ASIC_VERSION_BYTE 0x68 #define I2C_MAX_RETRY 3 -bool get_fw_version_from_asic(uint8_t *data) +void get_fw_version_boot0_from_asic() { I2C_MSG i2c_msg = { .bus = I2C_BUS12, .target_addr = 0x32 }; i2c_msg.tx_len = 1; @@ -748,7 +749,26 @@ bool get_fw_version_from_asic(uint8_t *data) LOG_INF(" boot0 VER : %02d.%02d.%02d", i2c_msg.data[9], i2c_msg.data[8], i2c_msg.data[7]); uint32_t data_p = i2c_msg.data[9] << 16 | i2c_msg.data[8] << 8 | i2c_msg.data[7]; + if (data_p) { + // update temp data + LOG_INF("update boot0 version read from asic"); + version_boot0[0] = data_p; + version_boot0[1] = data_p; + version_boot0[2] = data_p; + } +} +bool get_fw_version_boot1_from_asic(uint8_t *data) +{ + I2C_MSG i2c_msg = { .bus = I2C_BUS12, .target_addr = 0x32 }; + i2c_msg.tx_len = 1; + i2c_msg.rx_len = 11; + i2c_msg.data[0] = ASIC_VERSION_BYTE; + i2c_master_read(&i2c_msg, I2C_MAX_RETRY); + + LOG_INF(" boot1 VER : %02d.%02d.%02d", i2c_msg.data[2], i2c_msg.data[3], i2c_msg.data[4]); + uint32_t data_p = i2c_msg.data[2] << 16 | i2c_msg.data[3] << 8 | i2c_msg.data[4]; memcpy(data, &data_p, 4); + return true; } @@ -763,7 +783,7 @@ static bool get_boot1_fw_version(void *info_p, uint8_t *buf, uint8_t *len) buf_p += strlen(remain_str_p); *len += strlen(remain_str_p); uint8_t *version_tmp = NULL; - uint32_t version = get_fw_version_from_asic(version_tmp); + uint32_t version = get_fw_version_boot1_from_asic(version_tmp); *len += bin2hex((uint8_t *)&version, 4, buf_p, 4); buf_p += 4; @@ -777,6 +797,7 @@ static bool get_boot0_hamsa_fw_version(void *info_p, uint8_t *buf, uint8_t *len) CHECK_NULL_ARG_WITH_RETURN(info_p, false); CHECK_NULL_ARG_WITH_RETURN(buf, false); CHECK_NULL_ARG_WITH_RETURN(len, false); + get_fw_version_boot0_from_asic(); bool ret = false; const char *remain_str_p = "flash hamsa BOOT0: "; uint8_t *buf_p = buf; @@ -811,7 +832,8 @@ static bool get_boot0_medha0_fw_version(void *info_p, uint8_t *buf, uint8_t *len CHECK_NULL_ARG_WITH_RETURN(info_p, false); CHECK_NULL_ARG_WITH_RETURN(buf, false); CHECK_NULL_ARG_WITH_RETURN(len, false); - + // read version from asic first + get_fw_version_boot0_from_asic(); bool ret = false; const char *remain_str_p = "flash medha0 BOOT0: "; uint8_t *buf_p = buf; @@ -845,6 +867,7 @@ static bool get_boot0_medha1_fw_version(void *info_p, uint8_t *buf, uint8_t *len CHECK_NULL_ARG_WITH_RETURN(info_p, false); CHECK_NULL_ARG_WITH_RETURN(buf, false); CHECK_NULL_ARG_WITH_RETURN(len, false); + get_fw_version_boot0_from_asic(); bool ret = false; const char *remain_str_p = "flash medha1 BOOT0: "; uint8_t *buf_p = buf; @@ -1279,6 +1302,10 @@ bool find_sensor_id_and_name_by_firmware_comp_id(uint8_t comp_identifier, uint8_ void plat_reset_prepare() { + set_plat_sensor_polling_enable_flag(false); + set_cpld_polling_enable_flag(false); + k_msleep(PLAT_WAIT_SENSOR_POLLING_END_DELAY_MS); + const char *i2c_labels[] = { "I2C_0", "I2C_1", "I2C_2", "I2C_3", "I2C_4", "I2C_5", "I2C_6", "I2C_7", "I2C_8", "I2C_9", "I2C_10", "I2C_11" }; @@ -1303,3 +1330,8 @@ void pal_warm_reset_prepare() LOG_INF("cmd platform warm reset prepare"); plat_reset_prepare(); } + +void update_temp_boot0_version(uint32_t version, uint8_t index) +{ + version_boot0[index] = version; +} \ No newline at end of file diff --git a/meta-facebook/sb-rb/src/platform/plat_pldm_fw_update.h b/meta-facebook/sb-rb/src/platform/plat_pldm_fw_update.h index e1f3b56564..5ea81ac3de 100644 --- a/meta-facebook/sb-rb/src/platform/plat_pldm_fw_update.h +++ b/meta-facebook/sb-rb/src/platform/plat_pldm_fw_update.h @@ -67,4 +67,5 @@ uint32_t plat_get_image_crc_checksum(uint8_t index); int sb_read_block(uint8_t slv_id, uint8_t cmd, uint8_t *data, uint32_t len); bool plat_get_image_crc_checksum_from_flash(uint8_t index, uint8_t data_type, uint32_t *data); uint32_t plat_get_image_version(uint8_t index); +void update_temp_boot0_version(uint32_t version, uint8_t index); #endif /* _PLAT_FWUPDATE_H_ */ diff --git a/meta-facebook/sb-rb/src/platform/plat_pldm_sensor.c b/meta-facebook/sb-rb/src/platform/plat_pldm_sensor.c index 0fec2a8bf6..c52f036c3a 100644 --- a/meta-facebook/sb-rb/src/platform/plat_pldm_sensor.c +++ b/meta-facebook/sb-rb/src/platform/plat_pldm_sensor.c @@ -30,6 +30,7 @@ static bool plat_sensor_polling_enable_flag = true; static bool plat_sensor_ubc_polling_enable_flag = true; static bool plat_sensor_temp_polling_enable_flag = true; static bool plat_sensor_vr_polling_enable_flag = true; +static uint8_t plat_sensor_one_step_power_enable_flag = 0; static struct pldm_sensor_thread pal_pldm_sensor_thread[MAX_SENSOR_THREAD_ID] = { // thread id, thread name @@ -449,7 +450,7 @@ pldm_sensor_info plat_pldm_sensor_temp_table[] = { .sample_count = SAMPLE_COUNT_DEFAULT, .cache = 0, .cache_status = PLDM_SENSOR_INITIALIZING, - .post_sensor_read_hook = post_common_sensor_read, + .post_sensor_read_hook = post_tmp432_read, }, }, { @@ -518,7 +519,7 @@ pldm_sensor_info plat_pldm_sensor_temp_table[] = { .sample_count = SAMPLE_COUNT_DEFAULT, .cache = 0, .cache_status = PLDM_SENSOR_INITIALIZING, - .post_sensor_read_hook = post_common_sensor_read, + .post_sensor_read_hook = post_tmp432_read, }, }, { @@ -587,7 +588,7 @@ pldm_sensor_info plat_pldm_sensor_temp_table[] = { .sample_count = SAMPLE_COUNT_DEFAULT, .cache = 0, .cache_status = PLDM_SENSOR_INITIALIZING, - .post_sensor_read_hook = post_common_sensor_read, + .post_sensor_read_hook = post_tmp432_read, }, }, { @@ -656,7 +657,7 @@ pldm_sensor_info plat_pldm_sensor_temp_table[] = { .sample_count = SAMPLE_COUNT_DEFAULT, .cache = 0, .cache_status = PLDM_SENSOR_INITIALIZING, - .post_sensor_read_hook = post_common_sensor_read, + .post_sensor_read_hook = post_tmp432_read, }, }, { @@ -725,7 +726,7 @@ pldm_sensor_info plat_pldm_sensor_temp_table[] = { .sample_count = SAMPLE_COUNT_DEFAULT, .cache = 0, .cache_status = PLDM_SENSOR_INITIALIZING, - .post_sensor_read_hook = post_common_sensor_read, + .post_sensor_read_hook = post_tmp432_read, }, }, { @@ -794,7 +795,7 @@ pldm_sensor_info plat_pldm_sensor_temp_table[] = { .sample_count = SAMPLE_COUNT_DEFAULT, .cache = 0, .cache_status = PLDM_SENSOR_INITIALIZING, - .post_sensor_read_hook = post_common_sensor_read, + .post_sensor_read_hook = post_tmp432_read, }, }, { @@ -863,7 +864,7 @@ pldm_sensor_info plat_pldm_sensor_temp_table[] = { .sample_count = SAMPLE_COUNT_DEFAULT, .cache = 0, .cache_status = PLDM_SENSOR_INITIALIZING, - .post_sensor_read_hook = post_common_sensor_read, + .post_sensor_read_hook = post_tmp432_read, }, }, { @@ -932,7 +933,7 @@ pldm_sensor_info plat_pldm_sensor_temp_table[] = { .sample_count = SAMPLE_COUNT_DEFAULT, .cache = 0, .cache_status = PLDM_SENSOR_INITIALIZING, - .post_sensor_read_hook = post_common_sensor_read, + .post_sensor_read_hook = post_tmp432_read, }, }, }; @@ -12245,8 +12246,10 @@ bool get_raw_data_from_sensor_id(uint8_t sensor_id, uint8_t offset, uint8_t *val err: if ((cfg->post_sensor_read_hook)) { - if ((cfg->post_sensor_read_hook)(cfg, cfg->post_sensor_read_args, 0) == false) { - LOG_DBG("%d read raw value post hook fail!", sensor_id); + if ((cfg->post_sensor_read_hook)(cfg, cfg->post_sensor_read_args, 0) == false && + cfg->cache_status != SENSOR_OPEN_CIRCUIT) { + LOG_DBG("%d read raw value post hook fail! %x", sensor_id, + cfg->cache_status); return false; } } @@ -12422,6 +12425,11 @@ void set_plat_sensor_vr_polling_enable_flag(bool value) plat_sensor_vr_polling_enable_flag = value; } +void set_plat_sensor_one_step_enable_flag(uint8_t value) +{ + plat_sensor_one_step_power_enable_flag = value; +} + bool get_plat_sensor_polling_enable_flag() { return plat_sensor_polling_enable_flag; @@ -12442,10 +12450,20 @@ bool get_plat_sensor_vr_polling_enable_flag() return plat_sensor_vr_polling_enable_flag; } +uint8_t get_plat_sensor_one_step_enable_flag() +{ + return plat_sensor_one_step_power_enable_flag; +} + bool is_ubc_access(uint8_t sensor_num) { - return (is_dc_access(sensor_num) && get_plat_sensor_ubc_polling_enable_flag() && - get_plat_sensor_polling_enable_flag()); + if (get_plat_sensor_one_step_enable_flag() == ONE_STEP_POWER_MAGIC_NUMBER) { + return (get_plat_sensor_ubc_polling_enable_flag() && + get_plat_sensor_polling_enable_flag()); + } else { + return (is_dc_access(sensor_num) && get_plat_sensor_ubc_polling_enable_flag() && + get_plat_sensor_polling_enable_flag()); + } } bool is_temp_access(uint8_t cfg_idx) @@ -12456,8 +12474,14 @@ bool is_temp_access(uint8_t cfg_idx) bool is_vr_access(uint8_t sensor_num) { - return (is_dc_access(sensor_num) && get_plat_sensor_vr_polling_enable_flag() && - get_plat_sensor_polling_enable_flag()); + if (get_plat_sensor_one_step_enable_flag() == ONE_STEP_POWER_MAGIC_NUMBER) { + return (get_plat_sensor_vr_polling_enable_flag() && + get_plat_sensor_polling_enable_flag()); + + } else { + return (is_dc_access(sensor_num) && get_plat_sensor_vr_polling_enable_flag() && + get_plat_sensor_polling_enable_flag()); + } } void set_ioe_value(uint8_t ioe_addr, uint8_t ioe_reg, uint8_t value) @@ -12523,7 +12547,7 @@ void init_U200051_IO() // only bit6 is input (1) set_ioe_value(U200051_IO_ADDR, CONFIG, 0x40); // io5,io7 default output 1 - set_ioe_value(U200051_IO_ADDR, OUTPUT_PORT, 0xA0); + set_ioe_value(U200051_IO_ADDR, OUTPUT_PORT, 0x80); } /* quick sensor */ @@ -12536,8 +12560,8 @@ void quick_sensor_poll_handler(void *arug0, void *arug1, void *arug2) uint8_t set_io7_value = 0; uint8_t log_show_flag = 0; while (1) { - //check dc on/off - if (is_mb_dc_on() == false) { + //check dc on/off and polling enable/disable + if (is_mb_dc_on() == false || !get_plat_sensor_polling_enable_flag()) { //dc is off, sleep 1 second k_msleep(1000); continue; @@ -12582,4 +12606,4 @@ void quick_sensor_poll_init() CONFIG_MAIN_THREAD_PRIORITY, 0, K_NO_WAIT); k_thread_name_set(&quick_sensor_poll, "quick_sensor_poll"); return; -} \ No newline at end of file +} diff --git a/meta-facebook/sb-rb/src/platform/plat_pldm_sensor.h b/meta-facebook/sb-rb/src/platform/plat_pldm_sensor.h index d362e00585..9ca48d9401 100644 --- a/meta-facebook/sb-rb/src/platform/plat_pldm_sensor.h +++ b/meta-facebook/sb-rb/src/platform/plat_pldm_sensor.h @@ -313,6 +313,8 @@ #define UPDATE_INTERVAL_60S 60 #define U200051_IO_ADDR (0x72 >> 1) +#define ONE_STEP_POWER_MAGIC_NUMBER 0x56 + enum SENSOR_THREAD_LIST { TEMP_SENSOR_THREAD_ID = 0, VR_SENSOR_THREAD_ID, @@ -335,10 +337,12 @@ void set_plat_sensor_polling_enable_flag(bool value); void set_plat_sensor_ubc_polling_enable_flag(bool value); void set_plat_sensor_temp_polling_enable_flag(bool value); void set_plat_sensor_vr_polling_enable_flag(bool value); +void set_plat_sensor_one_step_enable_flag(uint8_t value); bool get_plat_sensor_polling_enable_flag(); bool get_plat_sensor_ubc_polling_enable_flag(); bool get_plat_sensor_temp_polling_enable_flag(); bool get_plat_sensor_vr_polling_enable_flag(); +uint8_t get_plat_sensor_one_step_enable_flag(); bool is_ubc_access(uint8_t sensor_num); bool is_temp_access(uint8_t cfg_idx); bool is_vr_access(uint8_t sensor_num); diff --git a/meta-facebook/sb-rb/src/platform/plat_power_capping.c b/meta-facebook/sb-rb/src/platform/plat_power_capping.c new file mode 100644 index 0000000000..f8718e3430 --- /dev/null +++ b/meta-facebook/sb-rb/src/platform/plat_power_capping.c @@ -0,0 +1,538 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "raa228249.h" +#include "mp29816a.h" +#include "plat_adc.h" +#include "plat_class.h" +#include "plat_cpld.h" +#include "plat_hook.h" +#include "plat_i2c_target.h" +#include "plat_power_capping.h" +#include "plat_pldm_sensor.h" + +LOG_MODULE_REGISTER(plat_power_capping); + +#define POWER_CAPPING_STACK_SIZE 1024 +K_THREAD_STACK_DEFINE(power_capping_thread_stack, POWER_CAPPING_STACK_SIZE); +struct k_thread power_capping_thread; + +typedef struct { + uint8_t method; + uint8_t source; + uint16_t current_threshold[CAPPING_VR_IDX_MAX]; + uint16_t time_w[CAPPING_VR_IDX_MAX][CAPPING_LV_IDX_MAX]; + uint16_t threshold[CAPPING_VR_IDX_MAX][CAPPING_LV_IDX_MAX]; +} power_capping_info_t; + +static power_capping_info_t power_capping_info = { 0 }; +static const uint16_t cpld_lv1_time_window_list[CPLD_LV1_TIME_WINDOW_NUM] = { 0, 1, 3, 5, + 10, 15, 20, 50 }; +static uint8_t prev_set_ucr_status = 0; +const static uint8_t sensor_id_list[2] = { SENSOR_NUM_ASIC_P0V85_MEDHA0_VDD_VOLT_V, + SENSOR_NUM_ASIC_P0V85_MEDHA1_VDD_VOLT_V }; + +K_WORK_DELAYABLE_DEFINE(sync_vr_oc_work, power_capping_syn_vr_oc_warn_limit); + +void power_capping_syn_vr_oc_warn_limit() +{ + if (!is_mb_dc_on()) { + LOG_WRN("need to DC on!"); + return; + } + + for (uint8_t i = 0; i < ARRAY_SIZE(sensor_id_list); i++) { + uint8_t sensor_id = sensor_id_list[i]; + sensor_cfg *cfg = get_sensor_cfg_by_sensor_id(sensor_id); + + if (cfg == NULL) { + LOG_ERR("Fail to get sensor config: 0x%x", sensor_id); + continue; + } + + if (!cfg->pre_sensor_read_hook) { + LOG_ERR("NULL pre_sensor_read_hook: 0x%x", sensor_id); + continue; + } + + vr_pre_proc_arg *pre_proc_args = cfg->pre_sensor_read_args; + if (pre_proc_args == NULL) { + LOG_ERR("NULL pre_sensor_read_args: 0x%x", sensor_id); + continue; + } + + if (!cfg->pre_sensor_read_hook(cfg, cfg->pre_sensor_read_args)) { + LOG_ERR("sensor id: 0x%x pre-read fail", sensor_id); + /* mutex unlock */ + if (pre_proc_args->mutex) { + k_mutex_unlock(pre_proc_args->mutex); + } + continue; + } + + uint16_t value = 0; + uint16_t voltage_value = 0; + float float_value = 0; + if (get_vr_module() == VR_MODULE_MPS) { + if (mp29816a_get_iout_oc_warn_limit(cfg, &value)) { + if (mp29816a_get_vout_command(cfg, 0, &voltage_value)) { + float_value = voltage_value / 1000.0; + power_capping_info.current_threshold[i] = value; + power_capping_info.threshold[i][CAPPING_LV_IDX_LV1] = + value * float_value; + } else { + LOG_ERR("Can't get VOUT_COMMAND: 0x%x", sensor_id); + } + } else { + LOG_ERR("Can't get IOUT_OC_WARN: 0x%x", sensor_id); + } + } else if (get_vr_module() == VR_MODULE_RNS) { + if (raa228249_get_iout_oc_warn_limit(cfg, &value)) { + if (raa228249_get_vout_command(cfg, 0, &voltage_value)) { + float_value = voltage_value / 1000.0; + power_capping_info.current_threshold[i] = value; + power_capping_info.threshold[i][CAPPING_LV_IDX_LV1] = + value * float_value; + } else { + LOG_ERR("Can't get VOUT_COMMAND: 0x%x", sensor_id); + } + } else { + LOG_ERR("Can't get IOUT_OC_WARN: 0x%x", sensor_id); + } + } else { + LOG_ERR("Unknown VR module: %d", get_vr_module()); + } + + /* mutex unlock */ + if (pre_proc_args->mutex) { + k_mutex_unlock(pre_proc_args->mutex); + } + } +} + +void add_sync_oc_warn_to_work() +{ + k_work_schedule(&sync_vr_oc_work, K_MSEC(1000)); +} + +bool set_power_capping_vr_oc_warn_limit(uint8_t vr_idx, uint16_t value) +{ + /* input value unit: 1A */ + + if (!is_mb_dc_on()) { + LOG_WRN("need to DC on!"); + return false; + } + + uint8_t ret = false; + uint8_t sensor_id = sensor_id_list[vr_idx]; + sensor_cfg *cfg = get_sensor_cfg_by_sensor_id(sensor_id); + + if (cfg == NULL) { + LOG_ERR("Fail to get sensor config: 0x%x", sensor_id); + return false; + } + + if (!cfg->pre_sensor_read_hook) { + LOG_ERR("NULL pre_sensor_read_hook: 0x%x", sensor_id); + return false; + } + + vr_pre_proc_arg *pre_proc_args = cfg->pre_sensor_read_args; + if (pre_proc_args == NULL) { + LOG_ERR("NULL pre_sensor_read_args: 0x%x", sensor_id); + return false; + } + + if (!cfg->pre_sensor_read_hook(cfg, cfg->pre_sensor_read_args)) { + LOG_ERR("sensor id: 0x%x pre-read fail", sensor_id); + /* mutex unlock */ + if (pre_proc_args->mutex) { + k_mutex_unlock(pre_proc_args->mutex); + } + return false; + } + + if (get_vr_module() == VR_MODULE_MPS) { + ret = mp29816a_set_iout_oc_warn_limit(cfg, value); + if (!ret) { + LOG_ERR("Can't set IOUT_OC_WARN 0x%x", sensor_id); + } else { + uint16_t voltage_value = 0; + float float_value = 0; + if (mp29816a_get_vout_command(cfg, 0, &voltage_value)) { + float_value = voltage_value / 1000.0; + power_capping_info.current_threshold[vr_idx] = value / float_value; + } else { + LOG_ERR("Can't get VOUT_COMMAND: 0x%x", sensor_id); + } + } + } else if (get_vr_module() == VR_MODULE_RNS) { + ret = raa228249_set_iout_oc_warn_limit(cfg, value); + if (!ret) { + LOG_ERR("Can't set IOUT_OC_WARN 0x%x", sensor_id); + } else { + uint16_t voltage_value = 0; + float float_value = 0; + if (raa228249_get_vout_command(cfg, 0, &voltage_value)) { + float_value = voltage_value / 1000.0; + power_capping_info.current_threshold[vr_idx] = value / float_value; + } else { + LOG_ERR("Can't get VOUT_COMMAND: 0x%x", sensor_id); + } + } + } else { + LOG_ERR("Unknown VR module: %d", get_vr_module()); + } + + /* mutex unlock */ + if (pre_proc_args->mutex) { + k_mutex_unlock(pre_proc_args->mutex); + } + + return ret; +} + +bool find_cpld_lv1_time_window_idx_by_value(uint8_t *idx, uint16_t value) +{ + for (uint8_t i = 0; i < CPLD_LV1_TIME_WINDOW_NUM; i++) { + if (cpld_lv1_time_window_list[i] == value) { + *idx = i; + return true; + } + } + return false; +} + +uint16_t get_power_capping_avg_power(uint8_t vr_idx, uint8_t lv) +{ + if (vr_idx >= CAPPING_VR_IDX_MAX) { + LOG_ERR("Wrong vr idx %d", vr_idx); + return 0; + } + + if (lv >= CAPPING_LV_IDX_MAX) { + LOG_ERR("Wrong vr lv %d", lv); + return 0; + } + + uint8_t tmp_idx = 0; + switch (lv) { + case CAPPING_LV_IDX_LV1: + break; + case CAPPING_LV_IDX_LV2: + if (vr_idx == CAPPING_VR_IDX_MEDHA0) { + tmp_idx = ADC_IDX_MEDHA0_1; + } else if (vr_idx == CAPPING_VR_IDX_MEDHA1) { + tmp_idx = ADC_IDX_MEDHA1_1; + } + break; + case CAPPING_LV_IDX_LV3: + if (vr_idx == CAPPING_VR_IDX_MEDHA0) { + tmp_idx = ADC_IDX_MEDHA0_2; + } else if (vr_idx == CAPPING_VR_IDX_MEDHA1) { + tmp_idx = ADC_IDX_MEDHA1_2; + } + break; + default: + break; + } + + if (power_capping_info.source == CAPPING_SOURCE_VR) { + return get_adc_averge_val(tmp_idx); + } else if (power_capping_info.source == CAPPING_SOURCE_ADC) { + return (uint16_t)get_adc_vr_pwr(tmp_idx); + } + + return 0; +} + +uint8_t get_power_capping_method() +{ + return power_capping_info.method; +} + +void set_power_capping_method(uint8_t value) +{ + if (value >= CAPPING_M_MAX) { + LOG_ERR("Wrong method %d", value); + return; + } + + power_capping_info.method = value; + + // for credit base, we don't assert LV2 and LV3 + uint8_t data = 0; + if (!plat_read_cpld(CPLD_OFFSET_POWER_CLAMP, &data, 1)) { + LOG_ERR("Can't r cpld offset 0x%02x", CPLD_OFFSET_POWER_CLAMP); + } + + if (value == CAPPING_M_LOOK_UP_TABLE) { + data = (data & 0x09) | 0x06; + if (!plat_write_cpld(CPLD_OFFSET_POWER_CLAMP, &data)) { + LOG_ERR("Can't w cpld offset 0x%02x", CPLD_OFFSET_POWER_CLAMP); + } + } else if (value == CAPPING_M_CREDIT_BASE) { + data = (data & 0x09); + if (!plat_write_cpld(CPLD_OFFSET_POWER_CLAMP, &data)) { + LOG_ERR("Can't w cpld offset 0x%02x", CPLD_OFFSET_POWER_CLAMP); + } else { + prev_set_ucr_status = 0; + } + } +} + +uint8_t get_power_capping_source() +{ + return power_capping_info.source; +} + +void set_power_capping_source(uint8_t value) +{ + if (value >= CAPPING_SOURCE_MAX) { + LOG_ERR("Wrong source %d", value); + return; + } + + power_capping_info.source = value; + + // reset value + adc_poll_init(); +} + +uint16_t get_power_capping_current_threshold(uint8_t vr_idx) +{ + if (vr_idx >= CAPPING_VR_IDX_MAX) { + LOG_ERR("Wrong vr idx %d", vr_idx); + return 0; + } + + return power_capping_info.current_threshold[vr_idx]; +} + +uint16_t get_power_capping_time_w(uint8_t vr_idx, uint8_t lv) +{ + if (vr_idx >= CAPPING_VR_IDX_MAX) { + LOG_ERR("Wrong vr idx %d", vr_idx); + return 0; + } + + if (lv >= CAPPING_LV_IDX_MAX) { + LOG_ERR("Wrong vr lv %d", lv); + return 0; + } + + return power_capping_info.time_w[vr_idx][lv]; +} + +void set_power_capping_time_w(uint8_t vr_idx, uint8_t lv, uint16_t value) +{ + if (vr_idx >= CAPPING_VR_IDX_MAX) { + LOG_ERR("Wrong vr idx %d", vr_idx); + return; + } + + if (lv >= CAPPING_LV_IDX_MAX) { + LOG_ERR("Wrong vr lv %d", lv); + return; + } + + if (value < ADC_AVERGE_TIMES_MIN && value > ADC_AVERGE_TIMES_MAX) { + LOG_ERR("Wrong value %d", value); + return; + } + + uint8_t tmp_idx = 0; + uint8_t data = 0; + switch (lv) { + case CAPPING_LV_IDX_LV1: + if (find_cpld_lv1_time_window_idx_by_value(&tmp_idx, value)) { + data = (tmp_idx << 5); + if (!plat_write_cpld(CPLD_OFFSET_POWER_CAPPING_LV1_TIME, &data)) { + LOG_ERR("can't w cpld offset %d", + CPLD_OFFSET_POWER_CAPPING_LV1_TIME); + return; + } + } else { + LOG_ERR("can't find lv1 time by %d", value); + return; + } + break; + case CAPPING_LV_IDX_LV2: + if (vr_idx == CAPPING_VR_IDX_MEDHA0) { + adc_set_averge_times(ADC_IDX_MEDHA0_1, value); + } else if (vr_idx == CAPPING_VR_IDX_MEDHA1) { + adc_set_averge_times(ADC_IDX_MEDHA1_1, value); + } + break; + case CAPPING_LV_IDX_LV3: + if (vr_idx == CAPPING_VR_IDX_MEDHA0) { + adc_set_averge_times(ADC_IDX_MEDHA0_2, value); + } else if (vr_idx == CAPPING_VR_IDX_MEDHA1) { + adc_set_averge_times(ADC_IDX_MEDHA1_2, value); + } + break; + default: + break; + } + + if (lv == CAPPING_LV_IDX_LV1) { + power_capping_info.time_w[CAPPING_VR_IDX_MEDHA0][lv] = value; + power_capping_info.time_w[CAPPING_VR_IDX_MEDHA1][lv] = value; + } else { + power_capping_info.time_w[vr_idx][lv] = value; + } +} + +uint16_t get_power_capping_threshold(uint8_t vr_idx, uint8_t lv) +{ + if (vr_idx >= CAPPING_VR_IDX_MAX) { + LOG_ERR("Wrong vr idx %d", vr_idx); + return 0; + } + + if (lv >= CAPPING_LV_IDX_MAX) { + LOG_ERR("Wrong vr lv %d", lv); + return 0; + } + + return power_capping_info.threshold[vr_idx][lv]; +} + +void set_power_capping_threshold(uint8_t vr_idx, uint8_t lv, uint16_t value) +{ + if (vr_idx >= CAPPING_VR_IDX_MAX) { + LOG_ERR("Wrong vr idx %d", vr_idx); + return; + } + + if (lv >= CAPPING_LV_IDX_MAX) { + LOG_ERR("Wrong vr lv %d", lv); + return; + } + + switch (lv) { + case CAPPING_LV_IDX_LV1: + if (vr_idx == CAPPING_VR_IDX_MEDHA0) { + if (!set_power_capping_vr_oc_warn_limit(ADC_IDX_MEDHA0_1, value)) { + return; + } + } else if (vr_idx == CAPPING_VR_IDX_MEDHA1) { + if (!set_power_capping_vr_oc_warn_limit(ADC_IDX_MEDHA1_1, value)) { + return; + } + } + break; + case CAPPING_LV_IDX_LV2: + if (vr_idx == CAPPING_VR_IDX_MEDHA0) { + set_adc_ucr(ADC_IDX_MEDHA0_1, value); + } else if (vr_idx == CAPPING_VR_IDX_MEDHA1) { + set_adc_ucr(ADC_IDX_MEDHA1_1, value); + } + break; + case CAPPING_LV_IDX_LV3: + if (vr_idx == CAPPING_VR_IDX_MEDHA0) { + set_adc_ucr(ADC_IDX_MEDHA0_2, value); + } else if (vr_idx == CAPPING_VR_IDX_MEDHA1) { + set_adc_ucr(ADC_IDX_MEDHA1_2, value); + } + break; + default: + break; + } + + power_capping_info.threshold[vr_idx][lv] = value; +} + +void power_capping_handler(void *p1, void *p2, void *p3) +{ + while (1) { + k_msleep(1); + + if (get_power_capping_method() == CAPPING_M_LOOK_UP_TABLE) { + uint8_t final_ucr_status = get_final_ucr_status(); + if (prev_set_ucr_status != final_ucr_status) { + uint8_t data = 0; + if (!plat_read_cpld(CPLD_OFFSET_POWER_CLAMP, &data, 1)) { + continue; + } + + data = (data & 0x0F) | final_ucr_status; + if (plat_write_cpld(CPLD_OFFSET_POWER_CLAMP, &data)) { + prev_set_ucr_status = final_ucr_status; + } + } + } + } +} + +void plat_power_capping_init() +{ + // sync avg_times + uint8_t data = 0; + if (plat_read_cpld(CPLD_OFFSET_POWER_CAPPING_LV1_TIME, &data, 1)) { + uint8_t idx = data >> 5; + if (idx < CPLD_LV1_TIME_WINDOW_NUM) { + power_capping_info.time_w[CAPPING_VR_IDX_MEDHA0][CAPPING_LV_IDX_LV1] = + cpld_lv1_time_window_list[idx]; + power_capping_info.time_w[CAPPING_VR_IDX_MEDHA1][CAPPING_LV_IDX_LV1] = + cpld_lv1_time_window_list[idx]; + } else { + LOG_ERR("invalid cpld lv1 time data 0x%02x", data); + } + } else { + LOG_ERR("can't r cpld offset %d", CPLD_OFFSET_POWER_CAPPING_LV1_TIME); + } + + power_capping_info.time_w[CAPPING_VR_IDX_MEDHA0][CAPPING_LV_IDX_LV2] = + get_adc_averge_times(ADC_IDX_MEDHA0_1); + power_capping_info.time_w[CAPPING_VR_IDX_MEDHA1][CAPPING_LV_IDX_LV2] = + get_adc_averge_times(ADC_IDX_MEDHA1_1); + + power_capping_info.time_w[CAPPING_VR_IDX_MEDHA0][CAPPING_LV_IDX_LV3] = + get_adc_averge_times(ADC_IDX_MEDHA0_2); + power_capping_info.time_w[CAPPING_VR_IDX_MEDHA1][CAPPING_LV_IDX_LV3] = + get_adc_averge_times(ADC_IDX_MEDHA1_2); + + // sync threshold + add_sync_oc_warn_to_work(); + + power_capping_info.threshold[CAPPING_VR_IDX_MEDHA0][CAPPING_LV_IDX_LV2] = + get_adc_ucr(ADC_IDX_MEDHA0_1); + power_capping_info.threshold[CAPPING_VR_IDX_MEDHA1][CAPPING_LV_IDX_LV2] = + get_adc_ucr(ADC_IDX_MEDHA1_1); + + power_capping_info.threshold[CAPPING_VR_IDX_MEDHA0][CAPPING_LV_IDX_LV3] = + get_adc_ucr(ADC_IDX_MEDHA0_2); + power_capping_info.threshold[CAPPING_VR_IDX_MEDHA1][CAPPING_LV_IDX_LV3] = + get_adc_ucr(ADC_IDX_MEDHA1_2); + + // init set capping to 0 + if (plat_read_cpld(CPLD_OFFSET_POWER_CLAMP, &data, 1)) { + data = (data & 0x0F); + plat_write_cpld(CPLD_OFFSET_POWER_CLAMP, &data); + } + + set_power_capping_source(CAPPING_SOURCE_ADC); + + k_thread_create(&power_capping_thread, power_capping_thread_stack, POWER_CAPPING_STACK_SIZE, + power_capping_handler, NULL, NULL, NULL, CONFIG_MAIN_THREAD_PRIORITY, 0, + K_MSEC(3000)); + + k_thread_name_set(&power_capping_thread, "power_capping"); +} diff --git a/meta-facebook/sb-rb/src/platform/plat_power_capping.h b/meta-facebook/sb-rb/src/platform/plat_power_capping.h new file mode 100644 index 0000000000..32e6430c0e --- /dev/null +++ b/meta-facebook/sb-rb/src/platform/plat_power_capping.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef PLAT_POWER_CAPPING_H +#define PLAT_POWER_CAPPING_H + +#define CPLD_LV1_TIME_WINDOW_NUM 8 + +enum { CAPPING_M_LOOK_UP_TABLE = 0, + CAPPING_M_CREDIT_BASE, + CAPPING_M_MAX, +}; + +enum { CAPPING_SOURCE_VR = 0, + CAPPING_SOURCE_ADC, + CAPPING_SOURCE_MAX, +}; + +enum { CAPPING_VR_IDX_MEDHA0 = 0, + CAPPING_VR_IDX_MEDHA1, + CAPPING_VR_IDX_MAX, +}; + +enum { CAPPING_LV_IDX_LV1 = 0, + CAPPING_LV_IDX_LV2, + CAPPING_LV_IDX_LV3, + CAPPING_LV_IDX_MAX, +}; + +#endif + +void power_capping_syn_vr_oc_warn_limit(); +void add_sync_oc_warn_to_work(); +bool find_cpld_lv1_time_window_idx_by_value(uint8_t *idx, uint16_t value); +uint16_t get_power_capping_avg_power(uint8_t vr_idx, uint8_t lv); +uint8_t get_power_capping_method(); +void set_power_capping_method(uint8_t value); +uint8_t get_power_capping_source(); +void set_power_capping_source(uint8_t value); +uint16_t get_power_capping_current_threshold(uint8_t vr_idx); +uint16_t get_power_capping_time_w(uint8_t vr_idx, uint8_t lv); +void set_power_capping_time_w(uint8_t vr_idx, uint8_t lv, uint16_t value); +uint16_t get_power_capping_threshold(uint8_t vr_idx, uint8_t lv); +void set_power_capping_threshold(uint8_t vr_idx, uint8_t lv, uint16_t value); +void plat_power_capping_init(); diff --git a/meta-facebook/sb-rb/src/platform/plat_thermal.c b/meta-facebook/sb-rb/src/platform/plat_thermal.c index faea656ad6..651457468b 100644 --- a/meta-facebook/sb-rb/src/platform/plat_thermal.c +++ b/meta-facebook/sb-rb/src/platform/plat_thermal.c @@ -15,6 +15,7 @@ */ #include "plat_event.h" #include +#include "plat_thermal.h" #include "tmp431.h" #include "sensor.h" #include "plat_log.h" @@ -27,23 +28,12 @@ LOG_MODULE_REGISTER(plat_thermal); #define TMP432_HIGH_LIMIT_STATUS_REG 0x35 + struct k_thread check_thermal_thread; K_KERNEL_STACK_MEMBER(check_thermal_thread_stack, 1024); k_tid_t thermal_tid; bool handler_flag = true; -enum IRIS_TEMP_INDEX_E { - TEMP_STATUS_INDEX_ASIC_MEDHA0_SENSOR0, - TEMP_STATUS_INDEX_ASIC_MEDHA0_SENSOR1, - TEMP_STATUS_INDEX_ASIC_OWL_W, - TEMP_STATUS_INDEX_ASIC_OWL_E, - TEMP_STATUS_INDEX_ASIC_MEDHA1_SENSOR0, - TEMP_STATUS_INDEX_ASIC_MEDHA1_SENSOR1, - TEMP_STATUS_INDEX_ASIC_HAMSA_CRM, - TEMP_STATUS_INDEX_ASIC_HAMSA_LS, - TEMP_STATUS_INDEX_MAX, -}; - const char *temperature_name_table[] = { "ASIC_MEDHA0_SENSOR0", "ASIC_MEDHA0_SENSOR1", "ASIC_OWL_W", "ASIC_OWL_E", "ASIC_MEDHA1_SENSOR0", "ASIC_MEDHA1_SENSOR1", "ASIC_HAMSA_CRM", "ASIC_HAMSA_LS", @@ -54,23 +44,28 @@ typedef struct temp_mapping_sensor_t { uint8_t sensor_id; uint8_t *sensor_name; uint8_t last_status; + bool is_open; + uint8_t log_status_val; // status val for log + uint8_t log_limit_status_val; // limit status val for log } temp_mapping_sensor_t; temp_mapping_sensor_t temp_alert_index_table[] = { { TEMP_STATUS_INDEX_ASIC_MEDHA0_SENSOR0, SENSOR_NUM_ASIC_MEDHA0_SENSOR0_TEMP_C, - "SB_RB_ASIC_MEDHA0_SENSOR0_TEMP", 0 }, + "SB_RB_ASIC_MEDHA0_SENSOR0_TEMP", 0, false }, { TEMP_STATUS_INDEX_ASIC_MEDHA0_SENSOR1, SENSOR_NUM_ASIC_MEDHA0_SENSOR1_TEMP_C, - "SB_RB_ASIC_MEDHA0_SENSOR1_TEMP", 0 }, - { TEMP_STATUS_INDEX_ASIC_OWL_W, SENSOR_NUM_ASIC_OWL_W_TEMP_C, "SB_RB_ASIC_OWL_W_TEMP", 0 }, - { TEMP_STATUS_INDEX_ASIC_OWL_E, SENSOR_NUM_ASIC_OWL_E_TEMP_C, "SB_RB_ASIC_OWL_E_TEMP", 0 }, + "SB_RB_ASIC_MEDHA0_SENSOR1_TEMP", 0, false }, + { TEMP_STATUS_INDEX_ASIC_OWL_W, SENSOR_NUM_ASIC_OWL_W_TEMP_C, "SB_RB_ASIC_OWL_W_TEMP", 0, + false }, + { TEMP_STATUS_INDEX_ASIC_OWL_E, SENSOR_NUM_ASIC_OWL_E_TEMP_C, "SB_RB_ASIC_OWL_E_TEMP", 0, + false }, { TEMP_STATUS_INDEX_ASIC_MEDHA1_SENSOR0, SENSOR_NUM_ASIC_MEDHA1_SENSOR0_TEMP_C, - "SB_RB_ASIC_MEDHA1_SENSOR0_TEMP", 0 }, + "SB_RB_ASIC_MEDHA1_SENSOR0_TEMP", 0, false }, { TEMP_STATUS_INDEX_ASIC_MEDHA1_SENSOR1, SENSOR_NUM_ASIC_MEDHA1_SENSOR1_TEMP_C, - "SB_RB_ASIC_MEDHA1_SENSOR1_TEMP", 0 }, + "SB_RB_ASIC_MEDHA1_SENSOR1_TEMP", 0, false }, { TEMP_STATUS_INDEX_ASIC_HAMSA_CRM, SENSOR_NUM_ASIC_HAMSA_CRM_TEMP_C, - "SB_RB_ASIC_HAMSA_CRM_TEMP", 0 }, + "SB_RB_ASIC_HAMSA_CRM_TEMP", 0, false }, { TEMP_STATUS_INDEX_ASIC_HAMSA_LS, SENSOR_NUM_ASIC_HAMSA_LS_TEMP_C, - "SB_RB_ASIC_HAMSA_LS_TEMP", 0 }, + "SB_RB_ASIC_HAMSA_LS_TEMP", 0, false }, }; void read_temp_status(uint8_t bus, uint8_t target_addr) @@ -80,8 +75,30 @@ void read_temp_status(uint8_t bus, uint8_t target_addr) plat_i2c_read(bus, target_addr, TMP432_HIGH_LIMIT_STATUS_REG, clear_status_data, 1); LOG_DBG("temp status is 0x%x", clear_status_data[0]); } + +uint8_t get_thermal_status_val_for_log(uint8_t sensor_num) +{ + for (uint8_t i = 0; i < ARRAY_SIZE(temp_alert_index_table); i++) { + if (temp_alert_index_table[i].sensor_id == sensor_num) + return temp_alert_index_table[i].log_status_val; + } + + return 0; +} + +uint8_t get_thermal_limit_status_val_for_log(uint8_t sensor_num) +{ + for (uint8_t i = 0; i < ARRAY_SIZE(temp_alert_index_table); i++) { + if (temp_alert_index_table[i].sensor_id == sensor_num) + return temp_alert_index_table[i].log_limit_status_val; + } + + return 0; +} + void check_thermal_handler(void *arg1, void *arg2, void *arg3) { + k_sleep(K_MSEC(1000)); // wait sensor thread ready LOG_INF("check_thermal_handler start"); while (1) { @@ -90,7 +107,7 @@ void check_thermal_handler(void *arg1, void *arg2, void *arg3) k_sleep(K_MSEC(1000)); continue; } - k_sleep(K_MSEC(1000)); + //check temp_alert_index_table all temperature status for (int i = 0; i < ARRAY_SIZE(temp_alert_index_table); i++) { sensor_cfg *temp_cfg = @@ -104,28 +121,71 @@ void check_thermal_handler(void *arg1, void *arg2, void *arg3) //idx will base on 3 plat_get_temp_status(temp_alert_index_table[i].index + 3, &status_data); - // if status 4-bit is high than send error log; - if ((status_data >> 4) & 0x01) { - //check if still high, don't send error log again - if (temp_alert_index_table[i].last_status == 1) { - LOG_DBG("keep error sensor_num 0x%x, bus 0x%x, address 0x%x ", - temp_cfg->num, temp_cfg->port, - temp_cfg->target_addr); - // clear temperature status - read_temp_status(temp_cfg->port, temp_cfg->target_addr); - continue; - } else { - plat_set_iris_temp_error_log( - LOG_ASSERT, temp_alert_index_table[i].sensor_id); - // if last status is 0, set last status to 1 - if (!temp_alert_index_table[i].last_status) { - temp_alert_index_table[i].last_status = 1; + // check status open + if (status_data & TEMP_STATUS_OPEN) { + // check sensor + if (temp_cfg->cache_status == PLDM_SENSOR_OPEN_CIRCUIT) { + if (!temp_alert_index_table[i].is_open) { + temp_alert_index_table[i].log_status_val = + status_data; + plat_set_iris_temp_error_log( + LOG_ASSERT, + temp_alert_index_table[i].sensor_id); + temp_alert_index_table[i].is_open = true; + } + } + } + + // if status BIT(3), BIT(4) is high than send error log; + if (status_data & TEMP_LIMIT_STATUS) { + uint8_t remote_bit = + (temp_cfg->offset == TMP432_REMOTE_TEMPERATRUE_1) ? BIT(1) : + (temp_cfg->offset == TMP432_REMOTE_TEMPERATRUE_2) ? BIT(2) : + 0; + uint8_t limit_status_reg = + (status_data & TEMP_STATUS_H_LIMIT) ? H_LIMIT_STATUS : + (status_data & TEMP_STATUS_L_LIMIT) ? L_LIMIT_STATUS : + 0xFF; + uint8_t limit_status_val = 0; + if (!get_raw_data_from_sensor_id( + temp_alert_index_table[i].sensor_id, limit_status_reg, + &limit_status_val, 1) || + (limit_status_reg == 0xFF)) + LOG_ERR("sensor_num 0x02%x get limit status reg 0x%02x fail", + temp_alert_index_table[i].sensor_id, + limit_status_reg); + // check the corresponding remote port + if (limit_status_val & remote_bit) { + //check if still high, don't send error log again + if (temp_alert_index_table[i].last_status == 1) { + LOG_DBG("keep error sensor_num 0x%x, bus 0x%x, address 0x%x ", + temp_cfg->num, temp_cfg->port, + temp_cfg->target_addr); + // clear temperature status + read_temp_status(temp_cfg->port, + temp_cfg->target_addr); + continue; + } else { + temp_alert_index_table[i].log_status_val = + status_data; + temp_alert_index_table[i].log_limit_status_val = + limit_status_val; + plat_set_iris_temp_error_log( + LOG_ASSERT, + temp_alert_index_table[i].sensor_id); + // if last status is 0, set last status to 1 + if (!temp_alert_index_table[i].last_status) { + temp_alert_index_table[i].last_status = 1; + } } } } else { // if last status is 1, set last status to 0 if (temp_alert_index_table[i].last_status) { temp_alert_index_table[i].last_status = 0; + temp_alert_index_table[i].log_status_val = 0; + plat_set_iris_temp_error_log( + LOG_DEASSERT, temp_alert_index_table[i].sensor_id); LOG_INF("temperature sensor recovered: 0x%x", temp_alert_index_table[i].sensor_id); } @@ -135,6 +195,7 @@ void check_thermal_handler(void *arg1, void *arg2, void *arg3) temp_cfg->port, temp_cfg->target_addr); read_temp_status(temp_cfg->port, temp_cfg->target_addr); } + k_sleep(K_MSEC(1000)); } } diff --git a/meta-facebook/sb-rb/src/platform/plat_thermal.h b/meta-facebook/sb-rb/src/platform/plat_thermal.h index 029c4bdaaf..46ed56a9f8 100644 --- a/meta-facebook/sb-rb/src/platform/plat_thermal.h +++ b/meta-facebook/sb-rb/src/platform/plat_thermal.h @@ -19,6 +19,27 @@ #include +enum IRIS_TEMP_INDEX_E { + TEMP_STATUS_INDEX_ASIC_MEDHA0_SENSOR0, + TEMP_STATUS_INDEX_ASIC_MEDHA0_SENSOR1, + TEMP_STATUS_INDEX_ASIC_OWL_W, + TEMP_STATUS_INDEX_ASIC_OWL_E, + TEMP_STATUS_INDEX_ASIC_MEDHA1_SENSOR0, + TEMP_STATUS_INDEX_ASIC_MEDHA1_SENSOR1, + TEMP_STATUS_INDEX_ASIC_HAMSA_CRM, + TEMP_STATUS_INDEX_ASIC_HAMSA_LS, + TEMP_STATUS_INDEX_MAX, +}; + +#define TEMP_STATUS_H_LIMIT BIT(4) +#define TEMP_STATUS_L_LIMIT BIT(3) +#define TEMP_STATUS_OPEN BIT(2) +#define TEMP_LIMIT_STATUS (TEMP_STATUS_H_LIMIT | TEMP_STATUS_L_LIMIT) +#define H_LIMIT_STATUS 0x35 +#define L_LIMIT_STATUS 0x36 + void init_thermal_polling(void); +uint8_t get_thermal_status_val_for_log(uint8_t sensor_num); +uint8_t get_thermal_limit_status_val_for_log(uint8_t sensor_num); #endif \ No newline at end of file diff --git a/meta-facebook/sb-rb/src/platform/plat_util.c b/meta-facebook/sb-rb/src/platform/plat_util.c index 9ccb623dfa..2fea5a6691 100644 --- a/meta-facebook/sb-rb/src/platform/plat_util.c +++ b/meta-facebook/sb-rb/src/platform/plat_util.c @@ -17,6 +17,7 @@ #include "libutil.h" #include "plat_util.h" #include "plat_i2c.h" +#include "plat_gpio.h" #include LOG_MODULE_REGISTER(plat_util); @@ -64,3 +65,8 @@ bool plat_i2c_write(uint8_t bus, uint8_t addr, uint8_t offset, uint8_t *data, ui } return true; } + +bool is_dc_on(void) +{ + return gpio_get(RST_IRIS_PWR_ON_PLD_R1_N); +} diff --git a/meta-facebook/sb-rb/src/platform/plat_util.h b/meta-facebook/sb-rb/src/platform/plat_util.h index f067582dec..7d97f5a658 100644 --- a/meta-facebook/sb-rb/src/platform/plat_util.h +++ b/meta-facebook/sb-rb/src/platform/plat_util.h @@ -22,5 +22,6 @@ bool plat_i2c_read(uint8_t bus, uint8_t addr, uint8_t offset, uint8_t *data, uint8_t len); bool plat_i2c_write(uint8_t bus, uint8_t addr, uint8_t offset, uint8_t *data, uint8_t len); +bool is_dc_on(void); #endif \ No newline at end of file diff --git a/meta-facebook/sb-rb/src/platform/plat_version.h b/meta-facebook/sb-rb/src/platform/plat_version.h index 41f3e5a0fb..38d3697e83 100644 --- a/meta-facebook/sb-rb/src/platform/plat_version.h +++ b/meta-facebook/sb-rb/src/platform/plat_version.h @@ -28,7 +28,7 @@ #define DEVICE_REVISION 0x80 #define FIRMWARE_REVISION_1 GET_FW_VERSION1(BOARD_ID, PROJECT_STAGE) -#define FIRMWARE_REVISION_2 0x0e +#define FIRMWARE_REVISION_2 0x12 #define IPMI_VERSION 0x02 #define ADDITIONAL_DEVICE_SUPPORT 0xBF @@ -37,7 +37,7 @@ #define BIC_FW_YEAR_MSB 0x20 #define BIC_FW_YEAR_LSB 0x25 -#define BIC_FW_WEEK 0x49 +#define BIC_FW_WEEK 0x53 #define BIC_FW_VER 0x01 #define BIC_FW_platform_0 0x73 // char: s #define BIC_FW_platform_1 0x72 // char: r diff --git a/meta-facebook/sb-rb/src/platform/plat_vr_test_mode.c b/meta-facebook/sb-rb/src/platform/plat_vr_test_mode.c new file mode 100644 index 0000000000..52a01a448c --- /dev/null +++ b/meta-facebook/sb-rb/src/platform/plat_vr_test_mode.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include "plat_util.h" +#include "plat_pldm_sensor.h" +#include "plat_vr_test_mode.h" +#include "plat_hook.h" + +LOG_MODULE_REGISTER(plat_vr_test_mode); + +struct k_thread vr_test_mode_thread; +K_KERNEL_STACK_MEMBER(vr_test_mode_thread_stack, 1024); +k_tid_t vr_test_mode_tid; +bool vr_test_mode_flag = false; + +bool get_vr_test_mode_flag(void) +{ + return vr_test_mode_flag; +} + +const vr_test_mode_setting_t vr_test_mode_table[] = { + // vr_rail, fast ocp: x/10(A), slow ocp: x/10(A), uvp: 1(mV), ovp: 1(mV), v max: 1(mV), lcr(mV), ucr(mV) + { VR_RAIL_E_ASIC_P0V85_MEDHA0_VDD, 14500, 14500, 200, 940, 930, 595, 930 }, + { VR_RAIL_E_ASIC_P0V85_MEDHA1_VDD, 14500, 14500, 200, 940, 930, 595, 930 }, + { VR_RAIL_E_ASIC_P0V9_OWL_E_TRVDD, 170, 170, 200, 1130, 1120, 630, 1120 }, + { VR_RAIL_E_ASIC_P0V75_OWL_E_TRVDD, 110, 110, 200, 1130, 975, 525, 975 }, + { VR_RAIL_E_ASIC_P0V75_MAX_M_VDD, 1200, 1200, 200, 1130, 975, 525, 975 }, + { VR_RAIL_E_ASIC_P0V75_VDDPHY_HBM1357, 1500, 1500, 200, 940, 930, 525, 930 }, + { VR_RAIL_E_ASIC_P0V75_OWL_E_VDD, 1600, 1600, 200, 940, 930, 525, 930 }, + { VR_RAIL_E_ASIC_P0V4_VDDQL_HBM1357, 530, 530, 200, 800, 520, 280, 520 }, + { VR_RAIL_E_ASIC_P1V1_VDDQC_HBM1357, 3200, 3200, 200, 1320, 1310, 770, 1310 }, + { VR_RAIL_E_ASIC_P1V8_VPP_HBM1357, 140, 140, 200, 1980, 1970, 1260, 1970 }, + { VR_RAIL_E_ASIC_P0V75_MAX_N_VDD, 670, 670, 200, 1130, 975, 525, 975 }, + { VR_RAIL_E_ASIC_P0V8_HAMSA_AVDD_PCIE, 500, 400, 200, 1130, 1040, 560, 1040 }, + { VR_RAIL_E_ASIC_P1V2_HAMSA_VDDHRXTX_PCIE, 100, 100, 200, 1320, 1310, 840, 1310 }, + { VR_RAIL_E_ASIC_P0V85_HAMSA_VDD, 1000, 1000, 200, 1063, 1053, 595, 1053 }, + { VR_RAIL_E_ASIC_P1V1_VDDQC_HBM0246, 3200, 3200, 200, 1320, 1310, 770, 1310 }, + { VR_RAIL_E_ASIC_P1V8_VPP_HBM0246, 140, 140, 200, 1980, 1970, 1260, 1970 }, + { VR_RAIL_E_ASIC_P0V4_VDDQL_HBM0246, 530, 530, 200, 800, 520, 280, 520 }, + { VR_RAIL_E_ASIC_P0V75_VDDPHY_HBM0246, 1500, 1500, 200, 940, 930, 525, 930 }, + { VR_RAIL_E_ASIC_P0V75_OWL_W_VDD, 1600, 1500, 200, 940, 930, 525, 930 }, + { VR_RAIL_E_ASIC_P0V75_MAX_S_VDD, 660, 660, 200, 1130, 975, 525, 975 }, + { VR_RAIL_E_ASIC_P0V9_OWL_W_TRVDD, 170, 170, 200, 1130, 1120, 630, 1120 }, + { VR_RAIL_E_ASIC_P0V75_OWL_W_TRVDD, 110, 110, 200, 1130, 975, 525, 975 }, +}; + +const vr_test_mode_setting_t vr_test_mode_table_default[] = { + // vr_rail, fast ocp: x/10(A), slow ocp: x/10(A), uvp: 1(mV), ovp: 1(mV), v max: 1(mV), lcr(mV), ucr(mV) + { VR_RAIL_E_ASIC_P0V85_MEDHA0_VDD, 14500, 14500, 640, 940, 918, 782, 918 }, + { VR_RAIL_E_ASIC_P0V85_MEDHA1_VDD, 14500, 14500, 640, 940, 918, 782, 918 }, + { VR_RAIL_E_ASIC_P0V9_OWL_E_TRVDD, 170, 160, 700, 1010, 954, 846, 954 }, + { VR_RAIL_E_ASIC_P0V75_OWL_E_TRVDD, 110, 100, 575, 910, 795, 705, 795 }, + { VR_RAIL_E_ASIC_P0V75_MAX_M_VDD, 670, 570, 575, 910, 848, 690, 848 }, + { VR_RAIL_E_ASIC_P0V75_VDDPHY_HBM1357, 1230, 1130, 575, 910, 795, 705, 795 }, + { VR_RAIL_E_ASIC_P0V75_OWL_E_VDD, 1600, 1500, 575, 910, 810, 690, 810 }, + { VR_RAIL_E_ASIC_P0V4_VDDQL_HBM1357, 460, 360, 325, 800, 440, 380, 440 }, + { VR_RAIL_E_ASIC_P1V1_VDDQC_HBM1357, 2800, 2700, 900, 1260, 1177, 1067, 1177 }, + { VR_RAIL_E_ASIC_P1V8_VPP_HBM1357, 140, 140, 1400, 1960, 1950, 1746, 1950 }, + { VR_RAIL_E_ASIC_P0V75_MAX_N_VDD, 670, 570, 575, 910, 848, 690, 848 }, + { VR_RAIL_E_ASIC_P0V8_HAMSA_AVDD_PCIE, 500, 400, 635, 940, 848, 752, 848 }, + { VR_RAIL_E_ASIC_P1V2_HAMSA_VDDHRXTX_PCIE, 100, 90, 1000, 1300, 1272, 1128, 1272 }, + { VR_RAIL_E_ASIC_P0V85_HAMSA_VDD, 850, 750, 640, 940, 918, 782, 918 }, + { VR_RAIL_E_ASIC_P1V1_VDDQC_HBM0246, 2800, 2700, 900, 1260, 1177, 1067, 1177 }, + { VR_RAIL_E_ASIC_P1V8_VPP_HBM0246, 140, 140, 1400, 1960, 1950, 1746, 1950 }, + { VR_RAIL_E_ASIC_P0V4_VDDQL_HBM0246, 460, 360, 325, 800, 440, 380, 440 }, + { VR_RAIL_E_ASIC_P0V75_VDDPHY_HBM0246, 1230, 1130, 575, 910, 795, 705, 795 }, + { VR_RAIL_E_ASIC_P0V75_OWL_W_VDD, 1600, 1500, 575, 910, 810, 690, 810 }, + { VR_RAIL_E_ASIC_P0V75_MAX_S_VDD, 580, 480, 575, 910, 848, 690, 848 }, + { VR_RAIL_E_ASIC_P0V9_OWL_W_TRVDD, 170, 160, 700, 1010, 954, 846, 954 }, + { VR_RAIL_E_ASIC_P0V75_OWL_W_TRVDD, 110, 100, 575, 910, 795, 705, 795 }, +}; + +const uint8_t vr_test_mode_table_size = ARRAY_SIZE(vr_test_mode_table); +const uint8_t vr_test_mode_table_dafault_size = ARRAY_SIZE(vr_test_mode_table_default); + +static bool update_vr_reg(uint8_t rail, uint8_t reg, uint16_t val) +{ + uint8_t data[2]; + data[0] = val & 0xFF; + data[1] = (val >> 8) & 0xFF; + + if (!plat_set_vr_reg(rail, reg, data, 2)) { + LOG_ERR("fail to set vr rail %x, reg 0x%02x, val: %x", rail, reg, val); + return false; + } + return true; +} + +static bool set_vr_test_mode_reg(bool is_default) +{ + bool ret = true; + + const vr_test_mode_setting_t *table = + is_default ? vr_test_mode_table_default : vr_test_mode_table; + uint8_t table_size = is_default ? ARRAY_SIZE(vr_test_mode_table_default) : + ARRAY_SIZE(vr_test_mode_table); + + for (uint8_t i = 0; i < table_size; i++) { + const vr_test_mode_setting_t *cfg = &table[i]; + + const struct { + uint8_t offset; + uint16_t val; + const char *name; + } regs[] = { + { VR_FAST_OCP_REG, cfg->fast_ocp, "FAST OCP" }, + { VR_SLOW_OCP_REG, cfg->slow_ocp, "SLOW OCP" }, + { VR_UVP_REG, cfg->uvp, "UVP" }, + { VR_OVP_REG, cfg->ovp, "OVP" }, + { VR_VOUT_MAX_REG, cfg->vout_max, "VOUT MAX" }, + }; + for (size_t j = 0; j < ARRAY_SIZE(regs); j++) { + if (!update_vr_reg(cfg->vr_rail, regs[j].offset, regs[j].val)) { + ret = false; + LOG_ERR("VR rail %x set %s to %d failed", cfg->vr_rail, + regs[j].name, regs[j].val); + } + } + + // vr range + vout_range_user_settings.change_vout_min[i] = cfg->lcr; + vout_range_user_settings.change_vout_max[i] = cfg->ucr; + } + return ret; +} +void vr_test_mode_enable(bool onoff) +{ + vr_test_mode_flag = onoff; + + set_vr_test_mode_reg((onoff ? false : true)); +} + +void vr_test_mode_handler(void *arg1, void *arg2, void *arg3) +{ + k_sleep(K_MSEC(5000)); // wait sensor thread ready + + while (1) { + k_sleep(K_MINUTES(1)); + if (vr_test_mode_flag) + LOG_INF("VR TEST MODE is running!"); + } +} + +void init_vr_test_mode_polling(void) +{ + vr_test_mode_tid = k_thread_create(&vr_test_mode_thread, vr_test_mode_thread_stack, + K_THREAD_STACK_SIZEOF(vr_test_mode_thread_stack), + vr_test_mode_handler, NULL, NULL, NULL, + CONFIG_MAIN_THREAD_PRIORITY, 0, K_NO_WAIT); + k_thread_name_set(&vr_test_mode_thread, "vr_test_mode_mode_thread"); +} \ No newline at end of file diff --git a/meta-facebook/sb-rb/src/platform/plat_vr_test_mode.h b/meta-facebook/sb-rb/src/platform/plat_vr_test_mode.h new file mode 100644 index 0000000000..a831a50422 --- /dev/null +++ b/meta-facebook/sb-rb/src/platform/plat_vr_test_mode.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _PLAT_VR_TEST_MODE_H_ +#define _PLAT_VR_TEST_MODE_H_ + +#define VR_FAST_OCP_REG 0x46 +#define VR_SLOW_OCP_REG 0xEA +#define VR_UVP_REG 0x44 +#define VR_OVP_REG 0x40 +#define VR_VOUT_MAX_REG 0x24 + +#define VR_SLOW_OCP_1_DMA_ADDR 0x00EA +#define VR_SLOW_OCP_2_DMA_ADDR 0x01EA + +typedef struct { + uint8_t vr_rail; + uint16_t fast_ocp; + uint16_t slow_ocp; + uint16_t uvp; + uint16_t ovp; + uint16_t vout_max; + uint16_t lcr; + uint16_t ucr; +} vr_test_mode_setting_t; + +extern const vr_test_mode_setting_t vr_test_mode_table[]; +extern const vr_test_mode_setting_t vr_test_mode_table_default[]; +extern const uint8_t vr_test_mode_table_size; +extern const uint8_t vr_test_mode_table_dafault_size; + +bool get_vr_test_mode_flag(void); +void vr_test_mode_enable(bool onoff); +void init_vr_test_mode_polling(void); +#endif /* _PLAT_VR_TEST_MODE_H_ */ diff --git a/meta-facebook/sb-rb/src/shell/shell_adc.c b/meta-facebook/sb-rb/src/shell/shell_adc.c index 8775427c0a..a5405628ef 100644 --- a/meta-facebook/sb-rb/src/shell/shell_adc.c +++ b/meta-facebook/sb-rb/src/shell/shell_adc.c @@ -18,6 +18,7 @@ #include #include "plat_adc.h" +#include "plat_power_capping.h" void cmd_adc_poll_get(const struct shell *shell, size_t argc, char **argv) { @@ -60,7 +61,22 @@ void cmd_adc_set_averge_times(const struct shell *shell, size_t argc, char **arg return; } - adc_set_averge_times(idx, time); + switch (idx) { + case ADC_IDX_MEDHA0_1: + set_power_capping_time_w(CAPPING_VR_IDX_MEDHA0, CAPPING_LV_IDX_LV2, time); + break; + case ADC_IDX_MEDHA1_1: + set_power_capping_time_w(CAPPING_VR_IDX_MEDHA1, CAPPING_LV_IDX_LV2, time); + break; + case ADC_IDX_MEDHA0_2: + set_power_capping_time_w(CAPPING_VR_IDX_MEDHA0, CAPPING_LV_IDX_LV3, time); + break; + case ADC_IDX_MEDHA1_2: + set_power_capping_time_w(CAPPING_VR_IDX_MEDHA1, CAPPING_LV_IDX_LV3, time); + break; + default: + break; + } shell_warn(shell, "set adc %d averge time to %d", idx, time); } @@ -196,10 +212,31 @@ void cmd_adc_set_ucr(const struct shell *shell, size_t argc, char **argv) return; } - set_adc_ucr(idx, ucr); + switch (idx) { + case ADC_IDX_MEDHA0_1: + set_power_capping_threshold(CAPPING_VR_IDX_MEDHA0, CAPPING_LV_IDX_LV2, ucr); + break; + case ADC_IDX_MEDHA1_1: + set_power_capping_threshold(CAPPING_VR_IDX_MEDHA1, CAPPING_LV_IDX_LV2, ucr); + break; + case ADC_IDX_MEDHA0_2: + set_power_capping_threshold(CAPPING_VR_IDX_MEDHA0, CAPPING_LV_IDX_LV3, ucr); + break; + case ADC_IDX_MEDHA1_2: + set_power_capping_threshold(CAPPING_VR_IDX_MEDHA1, CAPPING_LV_IDX_LV3, ucr); + break; + default: + break; + } shell_warn(shell, "set adc %d ucr to %d", idx, ucr); } +void cmd_adc_get_good_status(const struct shell *shell, size_t argc, char **argv) +{ + shell_info(shell, "%02x %02x", get_adc_good_status(ADC_RB_IDX_MEDHA0), + get_adc_good_status(ADC_RB_IDX_MEDHA1)); +} + SHELL_STATIC_SUBCMD_SET_CREATE(sub_adc_poll_cmds, SHELL_CMD(get, NULL, "adc polling get", cmd_adc_poll_get), SHELL_CMD(set, NULL, "adc polling set", cmd_adc_poll_set), @@ -221,6 +258,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE( SHELL_CMD(val, NULL, "get adc averge val", cmd_adc_get_averge_val), SHELL_CMD(buf_raw, NULL, "get adc buf raw data", cmd_adc_get_buf_raw), SHELL_CMD(buf, NULL, "get adc buf", cmd_adc_get_buf), + SHELL_CMD(get_good_status, NULL, "get adc good status", cmd_adc_get_good_status), SHELL_CMD(ucr, &sub_adc_ucr_cmds, "adc ucr cmds", NULL), SHELL_SUBCMD_SET_END); /* Root of command test */ diff --git a/meta-facebook/sb-rb/src/shell/shell_adc_debug.c b/meta-facebook/sb-rb/src/shell/shell_adc_debug.c index 3e8a61c6b1..b6249e4959 100644 --- a/meta-facebook/sb-rb/src/shell/shell_adc_debug.c +++ b/meta-facebook/sb-rb/src/shell/shell_adc_debug.c @@ -18,44 +18,45 @@ #include #include "plat_adc.h" - static int cmd_adc_debug(const struct shell *shell, size_t argc, char **argv) { + if (argc < 4) { + shell_print( + shell, + "Usage: adc_debug [0:read|1:write] [0:ads7066|1:ad4058] [0:meadha0|1:meadha1] [reg] [value]"); + return 0; + } + uint8_t w_r = strtoul(argv[1], NULL, 10); // 0: read, 1: write - uint8_t adc_type = strtoul(argv[2], NULL, 10);// 0: ads7066, 1: ad4058 - uint8_t meadha_id = strtoul(argv[3], NULL, 16);// 0: meadha0, 1: meadha1 + uint8_t adc_type = strtoul(argv[2], NULL, 10); // 0: ads7066, 1: ad4058 + uint8_t meadha_id = strtoul(argv[3], NULL, 16); // 0: meadha0, 1: meadha1 uint8_t reg = strtoul(argv[4], NULL, 16); uint8_t write_value = strtoul(argv[5], NULL, 16); - // follow shell input - if (adc_type == 0) - { - if (w_r == 0) - { - int ret = ads7066_read_reg(reg, meadha_id); + // follow shell input + if (adc_type == 0) { + if (w_r == 0) { + uint8_t value = 0; + int ret = ads7066_read_reg(reg, meadha_id, &value); if (ret < 0) { shell_error(shell, "read reg fail (err=%d)", ret); return -EINVAL; } - } else if (w_r == 1) - { + } else if (w_r == 1) { int ret = ads7066_write_reg(reg, write_value, meadha_id); if (ret < 0) { shell_error(shell, "write reg fail (err=%d)", ret); return -EINVAL; } } - } - else if (adc_type == 1) - { - if (w_r == 0) - { - int ret = ad4058_read_reg(reg, meadha_id); + } else if (adc_type == 1) { + if (w_r == 0) { + uint8_t value = 0; + int ret = ad4058_read_reg(reg, meadha_id, &value); if (ret < 0) { shell_error(shell, "read reg fail (err=%d)", ret); return -EINVAL; } - } else if (w_r == 1) - { + } else if (w_r == 1) { int ret = ad4058_write_reg(reg, write_value, meadha_id); if (ret < 0) { shell_error(shell, "write reg fail (err=%d)", ret); @@ -63,16 +64,16 @@ static int cmd_adc_debug(const struct shell *shell, size_t argc, char **argv) } } } - - else - { + + else { shell_error(shell, "adc type error"); return -EINVAL; } return 0; } -SHELL_CMD_REGISTER(adc_debug, NULL, - "ADC debug tool\n" - "Usage: adc_debug [0:read|1:write] [0:ads7066|1:ad4058] [0:meadha0|1:meadha1] [reg] [value]", - cmd_adc_debug); +SHELL_CMD_REGISTER( + adc_debug, NULL, + "ADC debug tool\n" + "Usage: adc_debug [0:read|1:write] [0:ads7066|1:ad4058] [0:meadha0|1:meadha1] [reg] [value]", + cmd_adc_debug); diff --git a/meta-facebook/sb-rb/src/shell/shell_bmc_sensor.c b/meta-facebook/sb-rb/src/shell/shell_bmc_sensor.c index 4d6f59b1f2..095ab06a51 100644 --- a/meta-facebook/sb-rb/src/shell/shell_bmc_sensor.c +++ b/meta-facebook/sb-rb/src/shell/shell_bmc_sensor.c @@ -33,23 +33,23 @@ static int cmd_get_bmc_sensor(const struct shell *shell, size_t argc, char **arg uint8_t pwr_value_lsb = 0; uint8_t pwr_value_msb = 0; - if (!plat_read_cpld(CPLD_POWER_INFO_0_REG, &pwr_value_lsb, 1)){ + if (!plat_read_cpld(CPLD_POWER_INFO_0_REG, &pwr_value_lsb, 1)) { shell_error(shell, "LSB read from CPLD fail"); return -1; } - if (!plat_read_cpld(CPLD_POWER_INFO_1_REG, &pwr_value_msb, 1)){ + if (!plat_read_cpld(CPLD_POWER_INFO_1_REG, &pwr_value_msb, 1)) { shell_error(shell, "MSB read from CPLD fail"); return -1; } - shell_info(shell, "P52V_ASIC_SENSE_PWR:%d", (pwr_value_msb<<8)|pwr_value_lsb); + shell_info(shell, "P52V_ASIC_SENSE_PWR : %d", (pwr_value_msb << 8) | pwr_value_lsb); return 0; } -SHELL_STATIC_SUBCMD_SET_CREATE( - sub_bmc_sensor, SHELL_CMD(get, NULL, "get P52V_ASIC_SENSE_PWR from CPLD", cmd_get_bmc_sensor), - SHELL_SUBCMD_SET_END); +SHELL_STATIC_SUBCMD_SET_CREATE(sub_bmc_sensor, + SHELL_CMD(get, NULL, "get P52V_ASIC_SENSE_PWR from CPLD", + cmd_get_bmc_sensor), + SHELL_SUBCMD_SET_END); /* Root of command bmc_sensor */ -SHELL_CMD_REGISTER(bmc_sensor, &sub_bmc_sensor, "bmc_sensor get", - NULL); +SHELL_CMD_REGISTER(bmc_sensor, &sub_bmc_sensor, "bmc_sensor get", NULL); diff --git a/meta-facebook/sb-rb/src/shell/shell_fw_version.c b/meta-facebook/sb-rb/src/shell/shell_fw_version.c index d231615c45..d6d9d5ce0a 100644 --- a/meta-facebook/sb-rb/src/shell/shell_fw_version.c +++ b/meta-facebook/sb-rb/src/shell/shell_fw_version.c @@ -26,6 +26,7 @@ #include "plat_hook.h" #include "plat_class.h" #include "plat_i2c.h" +#include "shell_iris_power.h" LOG_MODULE_REGISTER(shell_fw_version); @@ -47,24 +48,6 @@ static const asic_item_t asic_list[BOOT0_MAX] = { { BOOT0_MEDHA1, "MEDHA1", I2C_BUS12, 0x32 }, }; -bool check_p3v3_p5v_pwrgd(void) -{ - // read p3v3_pwrgf and p5v_pwrgf - // PWRGD_P3V3_R, bit-4, VR_PWRGD_PIN_READING_5_REG - uint8_t offset = VR_PWRGD_PIN_READING_5_REG; - uint8_t reg_data = 0; - if (!plat_read_cpld(offset, ®_data, 1)) { - LOG_ERR("Read CPLD offset 0x%x failed", offset); - } - uint8_t p3v3_value = (reg_data >> 4) & 0x01; - // PWRGD_P5V_R, bit-5, VR_PWRGD_PIN_READING_5_REG - uint8_t p5v_value = (reg_data >> 5) & 0x01; - //if both p3v3 and p5v are all 1, return true - if (p3v3_value == 1 && p5v_value == 1) - return true; - return false; -} - void cmd_get_fw_version_vr(const struct shell *shell, size_t argc, char **argv) { if (argc != 1) { @@ -81,12 +64,11 @@ void cmd_get_fw_version_vr(const struct shell *shell, size_t argc, char **argv) uint8_t sensor_id = 0; char sensor_name[MAX_AUX_SENSOR_NAME_LEN] = { 0 }; - if (check_p3v3_p5v_pwrgd() == false) - { - shell_warn(shell, "PWRGD_P3V3_R and PWRGD_P5V_R is not on, skip get VR version"); + if (check_p3v3_p5v_pwrgd() == false) { + shell_warn(shell, + "PWRGD_P3V3_R and PWRGD_P5V_R is not on, skip get VR version"); continue; } - if (i == COMPNT_HAMSA || i == COMPNT_MEDHA0 || i == COMPNT_MEDHA1) continue; @@ -171,18 +153,38 @@ void cmd_get_fw_version_cpld(const struct shell *shell, size_t argc, char **argv void cmd_get_fw_version_asic(const struct shell *shell, size_t argc, char **argv) { - for (uint8_t idx = BOOT0_HAMSA; idx < BOOT0_MAX; idx++) { - I2C_MSG i2c_msg = { .bus = asic_list[idx].bus, .target_addr = asic_list[idx].addr }; - i2c_msg.tx_len = 1; - i2c_msg.rx_len = 11; - i2c_msg.data[0] = ASIC_VERSION_BYTE; - if (i2c_master_read(&i2c_msg, I2C_MAX_RETRY)) { - shell_warn(shell, "Can't get boot0 version from ASIC"); - return; + I2C_MSG i2c_msg = { .bus = asic_list[BOOT0_HAMSA].bus, + .target_addr = asic_list[BOOT0_HAMSA].addr }; + i2c_msg.tx_len = 1; + i2c_msg.rx_len = 11; + i2c_msg.data[0] = ASIC_VERSION_BYTE; + if (i2c_master_read(&i2c_msg, I2C_MAX_RETRY)) { + shell_warn(shell, "Can't get boot0, boot1 version from ASIC"); + return; + } + shell_print(shell, " boot1 VER from asic: %02d.%02d.%02d", i2c_msg.data[2], i2c_msg.data[3], + i2c_msg.data[4]); + shell_print(shell, " boot0 VER from asic: %02d.%02d.%02d", i2c_msg.data[9], i2c_msg.data[8], + i2c_msg.data[7]); + uint32_t tmp_version_boot0 = i2c_msg.data[9] << 16 | i2c_msg.data[8] << 8 | i2c_msg.data[7]; + // if boot0 version is not 0, update temp data + if (tmp_version_boot0) { + // update temp data + shell_print(shell, "update boot0 version read from asic"); + for (int i = 0; i < BOOT0_MAX; i++) { + update_temp_boot0_version(tmp_version_boot0, i); } - shell_print(shell, "%s boot0 VER : %02d.%02d.%02d| CRC32 : %08x", - asic_list[idx].name, i2c_msg.data[9], i2c_msg.data[8], i2c_msg.data[7], - plat_get_image_crc_checksum(asic_list[idx].id)); + } + // get temp version from temp array + for (int i = 0; i < BOOT0_MAX; i++) { + uint32_t version_tmp = plat_get_image_version(i); + unsigned char tmp_bytes[4]; + tmp_bytes[0] = (version_tmp >> 24) & 0xFF; + tmp_bytes[1] = (version_tmp >> 16) & 0xFF; + tmp_bytes[2] = (version_tmp >> 8) & 0xFF; + tmp_bytes[3] = version_tmp & 0xFF; + shell_print(shell, " boot0 VER from temp array: %02d.%02d.%02d.%02d", tmp_bytes[0], + tmp_bytes[1], tmp_bytes[2], tmp_bytes[3]); } return; } diff --git a/meta-facebook/sb-rb/src/shell/shell_get_mb_pwr_en.c b/meta-facebook/sb-rb/src/shell/shell_get_mb_pwr_en.c new file mode 100644 index 0000000000..86cebb4620 --- /dev/null +++ b/meta-facebook/sb-rb/src/shell/shell_get_mb_pwr_en.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "plat_cpld.h" + +LOG_MODULE_REGISTER(plat_get_mb_pwr_en_shell, LOG_LEVEL_DBG); + +static int cmd_get_mb_pwr_en(const struct shell *shell, size_t argc, char **argv) +{ + uint8_t data = 0; + + if (!plat_read_cpld(VR_EN_PIN_READING_5, &data, 1)) { + shell_error(shell, "read CPLD fail 0x%x", VR_EN_PIN_READING_5); + return -1; + } + + shell_info(shell, "MB PWR_EN : %d", data & BIT(0)); + + return 0; +} + +/* Root of command */ +SHELL_CMD_REGISTER(get_mb_pwr_en, NULL, "get MB PWR EN status", cmd_get_mb_pwr_en); diff --git a/meta-facebook/sb-rb/src/shell/shell_iris_power.c b/meta-facebook/sb-rb/src/shell/shell_iris_power.c index e1012498ca..c1d3b42a95 100644 --- a/meta-facebook/sb-rb/src/shell/shell_iris_power.c +++ b/meta-facebook/sb-rb/src/shell/shell_iris_power.c @@ -9,6 +9,7 @@ #include "plat_ioexp.h" #include "plat_pldm_sensor.h" #include "plat_class.h" +#include "shell_iris_power.h" // iris power command #define enable 0x01 @@ -219,13 +220,6 @@ static steps_on_struct steps_on[] = { { 1, VR_CLK_ENABLE_PIN_CTRL_REG, 4, "HAMSA_PCIE_PERST_B_PLD_N", NO_DEFINED }, //HAMSA_PCIE_PERST_B_PLD_N }; -enum PWR_CLOCK_COMPONENT { - CLK_BUF_100M_U85, - CLK_BUF_100M_U87, - CLK_BUF_100M_U88, - CLK_GEN_100M_U86, - CLK_COMPONENT_MAX -}; typedef struct pwr_clock_compnt_mapping { uint8_t clock_name_index; @@ -253,8 +247,6 @@ void clear_clock_status(const struct shell *shell, uint8_t clock_index) { I2C_MSG i2c_msg = { 0 }; uint8_t retry = 5; - int byte_count; - k_msleep(100); switch (clock_index) { case CLK_BUF_100M_U85: case CLK_BUF_100M_U87: @@ -263,29 +255,36 @@ void clear_clock_status(const struct shell *shell, uint8_t clock_index) i2c_msg.target_addr = pwr_clock_compnt_mapping_table[clock_index].addr; i2c_msg.tx_len = 1; i2c_msg.rx_len = 2; - i2c_msg.data[0] = CLK_BUF_100M_BYTE_COUNT; + i2c_msg.data[0] = CLK_BUF_100M_WRITE_LOCK_CLEAR_LOS_EVENT_OFFSET; if (i2c_master_read(&i2c_msg, retry)) { + if (!shell) { + return; + } shell_error(shell, "Failed to read reg, bus: %d, addr: 0x%x, reg: 0x%x", pwr_clock_compnt_mapping_table[clock_index].bus, pwr_clock_compnt_mapping_table[clock_index].addr, - CLK_BUF_100M_BYTE_COUNT); + CLK_BUF_100M_WRITE_LOCK_CLEAR_LOS_EVENT_OFFSET); return; } - byte_count = i2c_msg.data[1]; - - i2c_msg.tx_len = 3; - i2c_msg.rx_len = 0; - i2c_msg.data[0] = CLK_BUF_100M_WRITE_LOCK_CLEAR_LOS_EVENT_OFFSET; - i2c_msg.data[1] = byte_count; - i2c_msg.data[2] = 0x2; - if (i2c_master_write(&i2c_msg, retry)) { - shell_error(shell, "Failed to write reg, bus: %d, addr: 0x%x, reg: 0x%x", - pwr_clock_compnt_mapping_table[clock_index].bus, - pwr_clock_compnt_mapping_table[clock_index].addr, - CLK_BUF_100M_WRITE_LOCK_CLEAR_LOS_EVENT_OFFSET); - return; + if (i2c_msg.data[1] & BIT(1)) { + i2c_msg.tx_len = 3; + i2c_msg.rx_len = 0; + i2c_msg.data[0] = CLK_BUF_100M_WRITE_LOCK_CLEAR_LOS_EVENT_OFFSET; + i2c_msg.data[1] = 1; + i2c_msg.data[2] = 0x2; + if (i2c_master_write(&i2c_msg, retry)) { + if (!shell) { + return; + } + shell_error(shell, + "Failed to write reg, bus: %d, addr: 0x%x, reg: 0x%x", + pwr_clock_compnt_mapping_table[clock_index].bus, + pwr_clock_compnt_mapping_table[clock_index].addr, + CLK_BUF_100M_WRITE_LOCK_CLEAR_LOS_EVENT_OFFSET); + return; + } } break; case CLK_GEN_100M_U86: @@ -293,32 +292,42 @@ void clear_clock_status(const struct shell *shell, uint8_t clock_index) i2c_msg.target_addr = pwr_clock_compnt_mapping_table[clock_index].addr; i2c_msg.tx_len = 1; i2c_msg.rx_len = 2; - i2c_msg.data[0] = CLK_BUF_100M_BYTE_COUNT; + i2c_msg.data[0] = CLK_GEN_LOSMON_EVENT_OFFSET; if (i2c_master_read(&i2c_msg, retry)) { + if (!shell) { + return; + } shell_error(shell, "Failed to read reg, bus: %d, addr: 0x%x, reg: 0x%x", pwr_clock_compnt_mapping_table[clock_index].bus, pwr_clock_compnt_mapping_table[clock_index].addr, - CLK_BUF_100M_BYTE_COUNT); + CLK_GEN_LOSMON_EVENT_OFFSET); return; } - byte_count = i2c_msg.data[1]; - - i2c_msg.tx_len = 3; - i2c_msg.rx_len = 0; - i2c_msg.data[0] = CLK_GEN_LOSMON_EVENT_OFFSET; - i2c_msg.data[1] = byte_count; - i2c_msg.data[2] = 0x2; - if (i2c_master_write(&i2c_msg, retry)) { - shell_error(shell, "Failed to write reg, bus: %d, addr: 0x%x, reg: 0x%x", - pwr_clock_compnt_mapping_table[clock_index].bus, - pwr_clock_compnt_mapping_table[clock_index].addr, - CLK_GEN_LOSMON_EVENT_OFFSET); - return; + if (i2c_msg.data[1] & BIT(1)) { + i2c_msg.tx_len = 3; + i2c_msg.rx_len = 0; + i2c_msg.data[0] = CLK_GEN_LOSMON_EVENT_OFFSET; + i2c_msg.data[1] = 1; + i2c_msg.data[2] = 0x2; + if (i2c_master_write(&i2c_msg, retry)) { + if (!shell) { + return; + } + shell_error(shell, + "Failed to write reg, bus: %d, addr: 0x%x, reg: 0x%x", + pwr_clock_compnt_mapping_table[clock_index].bus, + pwr_clock_compnt_mapping_table[clock_index].addr, + CLK_GEN_LOSMON_EVENT_OFFSET); + return; + } } break; default: + if (!shell) { + return; + } shell_error(shell, "Type wrong clock"); } @@ -359,6 +368,24 @@ ioe_pwr_on ioe_pwr_on_table[] = { { U200051_IO_I2C_BUS, U200051_IO_ADDR, 5, "FM_P3V3_OSFP_P6_EN" }, }; +bool check_p3v3_p5v_pwrgd(void) +{ + // read p3v3_pwrgf and p5v_pwrgf + // PWRGD_P3V3_R, bit-4, VR_PWRGD_PIN_READING_5_REG + uint8_t offset = VR_PWRGD_PIN_READING_5_REG; + uint8_t reg_data = 0; + if (!plat_read_cpld(offset, ®_data, 1)) { + LOG_ERR("Read CPLD offset 0x%x failed", offset); + } + uint8_t p3v3_value = (reg_data >> 4) & 0x01; + // PWRGD_P5V_R, bit-5, VR_PWRGD_PIN_READING_5_REG + uint8_t p5v_value = (reg_data >> 5) & 0x01; + //if both p3v3 and p5v are all 1, return true + if (p3v3_value == 1 && p5v_value == 1) + return true; + return false; +} + void power_on_p3v3_osfp() { uint8_t write_data = 0; @@ -542,6 +569,7 @@ void cmd_iris_power_on(const struct shell *shell, size_t argc, char **argv) if (gpio_get(RST_IRIS_PWR_ON_PLD_R1_N) == GPIO_HIGH) { shell_print(shell, "iris power on success!"); set_pwr_steps_on_flag(0); + set_plat_sensor_one_step_enable_flag(false); } else { shell_warn(shell, "iris power on fail!"); } @@ -561,6 +589,7 @@ void cmd_iris_power_off(const struct shell *shell, size_t argc, char **argv) power_steps = 0; // init power steps set_pwr_steps_on_flag(0); + set_plat_sensor_one_step_enable_flag(false); } void cmd_iris_power_cycle(const struct shell *shell, size_t argc, char **argv) @@ -571,6 +600,7 @@ void cmd_iris_power_cycle(const struct shell *shell, size_t argc, char **argv) if (!iris_power_control(1)) shell_warn(shell, "iris power cycle(on) fail!"); set_pwr_steps_on_flag(0); + set_plat_sensor_one_step_enable_flag(false); } void cmd_iris_steps_on(const struct shell *shell, size_t argc, char **argv) @@ -617,9 +647,9 @@ void cmd_iris_steps_on(const struct shell *shell, size_t argc, char **argv) } k_msleep(1000); for (int i = 0; i < CLK_COMPONENT_MAX; i++) { - k_msleep(300); + k_msleep(100); clear_clock_status(shell, i); - k_msleep(300); + k_msleep(100); pwr_get_clock_status(shell, i); } } @@ -716,6 +746,12 @@ void cmd_iris_steps_on(const struct shell *shell, size_t argc, char **argv) power_good_status_table_for_steps_on[pwrgd_idx].power_rail_name, value); } + if (strcmp(steps_on[power_steps].name, "FM_P5V_EN") == 0) { + if (check_p3v3_p5v_pwrgd()) { + set_plat_sensor_one_step_enable_flag(ONE_STEP_POWER_MAGIC_NUMBER); + } + } + if (strcmp(steps_on[power_steps].name, "FM_P1V80_EN") == 0) { //if board id is evb, run steps_on_p3v3_osfp if (get_asic_board_id() == ASIC_BOARD_ID_EVB) { @@ -734,6 +770,7 @@ void cmd_iris_disable_steps_on(const struct shell *shell, size_t argc, char **ar set_pwr_steps_on_flag(0); // init value is reverse of power on value uint8_t power_init_value = 0; + set_plat_sensor_one_step_enable_flag(false); for (int i = 0; i < MAX_STEPS; i++) { power_init_value = steps_on[i].power_on_value ^ 1; // set all steps on value to init value diff --git a/meta-facebook/sb-rb/src/shell/shell_iris_power.h b/meta-facebook/sb-rb/src/shell/shell_iris_power.h index cb6a72afff..02656405a0 100644 --- a/meta-facebook/sb-rb/src/shell/shell_iris_power.h +++ b/meta-facebook/sb-rb/src/shell/shell_iris_power.h @@ -17,6 +17,16 @@ #ifndef PLAT_IRIS_POWER_H #define PLAT_IRIS_POWER_H +enum PWR_CLOCK_COMPONENT { + CLK_BUF_100M_U85, + CLK_BUF_100M_U87, + CLK_BUF_100M_U88, + CLK_GEN_100M_U86, + CLK_COMPONENT_MAX +}; + +bool check_p3v3_p5v_pwrgd(void); void power_on_p3v3_osfp(); void pwer_gd_get_status(const struct shell *shell); +void clear_clock_status(const struct shell *shell, uint8_t clock_index); #endif diff --git a/meta-facebook/sb-rb/src/shell/shell_jtag_mux.c b/meta-facebook/sb-rb/src/shell/shell_jtag_mux.c index a30b25787b..25d1365733 100644 --- a/meta-facebook/sb-rb/src/shell/shell_jtag_mux.c +++ b/meta-facebook/sb-rb/src/shell/shell_jtag_mux.c @@ -12,7 +12,7 @@ 011:OWL_W 100:HAMSA */ -enum jtag_mux { MUX_MEDHA_0 = 0, MUX_MEDHA_1, MUX_OWL_E, MUX_OWL_W, MUX_HAMSA, MUX_JTAG_MUX_MAX }; +enum jtag_mux { MUX_HAMSA = 0, MUX_MEDHA_0, MUX_MEDHA_1, MUX_OWL_E, MUX_OWL_W, MUX_JTAG_MUX_MAX }; LOG_MODULE_REGISTER(plat_jtag_mux_shell); diff --git a/meta-facebook/sb-rb/src/shell/shell_log.c b/meta-facebook/sb-rb/src/shell/shell_log.c index 33cc2937f6..1aa0929a65 100644 --- a/meta-facebook/sb-rb/src/shell/shell_log.c +++ b/meta-facebook/sb-rb/src/shell/shell_log.c @@ -32,8 +32,8 @@ const cpld_bit_name_table_t cpld_bit_name_table[] = { { VR_POWER_FAULT_1_REG, "VR Power Fault (1:Power Fault, 0=Normal)", { - "RSVD", - "RSVD", + "P0V75_AVDD_HCSL", + "P4V2", "HAMSA_VDDHRXTX_PCIE", "HAMSA_AVDD_PCIE", "OWL_W_TRVDD0P75", @@ -168,19 +168,27 @@ void cmd_log_dump(const struct shell *shell, size_t argc, char **argv) const char *reg_name = get_cpld_reg_name(cpld_offset); const char *bit_name = get_cpld_bit_name(cpld_offset, bit_position); + shell_print(shell, "sys_time: %lld ms", log.sys_time); + uint8_t err_data_len = 2; //sizeof(log.error_data) + switch (err_type) { case CPLD_UNEXPECTED_VAL_TRIGGER_CAUSE: shell_print(shell, "\t%s", reg_name); shell_print(shell, "\t\t%s", bit_name); + shell_print(shell, "read vr sensor status word(0x79):"); + shell_print(shell, "\tlow byte: 0x%02x", log.error_data[0]); + shell_print(shell, "\thigh byte: 0x%02x", log.error_data[1]); break; case POWER_ON_SEQUENCE_TRIGGER_CAUSE: shell_print(shell, "\tPOWER_ON_SEQUENCE_TRIGGER"); + err_data_len = 1; break; case AC_ON_TRIGGER_CAUSE: shell_print(shell, "\tAC_ON"); break; case DC_ON_TRIGGER_CAUSE: shell_print(shell, "\tDC_ON_DETECTED"); + err_data_len = 1; break; case TEMPERATURE_TRIGGER_CAUSE: shell_print(shell, "\tTEMPERATURE_TRIGGER"); @@ -190,18 +198,41 @@ void cmd_log_dump(const struct shell *shell, size_t argc, char **argv) if (temp_sensor_num == temp_index_table[i].sensor_id) { shell_print(shell, "\t\t%s", temp_index_table[i].sensor_name); + shell_print(shell, "sensor_num 0x%02x status(02h): 0x%02x", + log.error_data[2], log.error_data[0]); + // check whether the open status + if (log.error_data[0] & BIT(2)) + shell_print( + shell, + "sensor_num 0x%02x open status(1Bh): 0x%02x", + log.error_data[2], log.error_data[1]); + else if (log.error_data[0] & BIT(4)) + shell_print( + shell, + "high limit trigger, status(35h): 0x%02x", + log.error_data[1]); + else if (log.error_data[0] & BIT(3)) + shell_print( + shell, + "low limit trigger, status(36h): 0x%02x", + log.error_data[1]); + err_data_len = 3; break; } } break; + case ASIC_THERMTRIP_TRIGGER_CAUSE: + shell_print(shell, "\tASIC_THERMTRIP_TRIGGER"); + shell_print(shell, "read cpld offset(0x27): 0x%02x", log.error_data[0]); + shell_print(shell, "read cpld offset(0x29): 0x%02x", log.error_data[1]); + break; default: shell_print(shell, "Unknown error type: %d", err_type); break; } - shell_print(shell, "sys_time: %lld ms", log.sys_time); shell_print(shell, "error_data:"); - shell_hexdump(shell, log.error_data, sizeof(log.error_data)); + shell_hexdump(shell, log.error_data, err_data_len); shell_print(shell, "cpld register: start offset 0x%02x", CPLD_REGISTER_1ST_PART_START_OFFSET); shell_hexdump(shell, log.cpld_dump, CPLD_REGISTER_1ST_PART_NUM); diff --git a/meta-facebook/sb-rb/src/shell/shell_plat_asic_bspi_mux.c b/meta-facebook/sb-rb/src/shell/shell_plat_asic_bspi_mux.c new file mode 100644 index 0000000000..57791a998b --- /dev/null +++ b/meta-facebook/sb-rb/src/shell/shell_plat_asic_bspi_mux.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "plat_isr.h" +#include "plat_i2c.h" +#include "plat_hook.h" +#include "plat_cpld.h" +#include "plat_ioexp.h" +#include "plat_class.h" +#include "plat_gpio.h" + +#define AEGIS_CPLD_ADDR (0x4C >> 1) + +LOG_MODULE_REGISTER(plat_asic_spi_mux_shell, LOG_LEVEL_DBG); + +enum asic_bspi_name_index +{ + NC_SPI_MEDHA0_CRM_MUX, + NC_SPI_MEDHA1_CRM_MUX, + NC_SPI_HAMSA_CRM_MUX, + MAX_BSPI_IDX, +}; + +typedef struct _asic_bspi_info_ { + uint8_t mux_idx; + uint8_t gpio_idx; + uint8_t *mux_name; +} asic_bspi_info; + +asic_bspi_info asic_bspi_mux_table[] = +{ + { NC_SPI_MEDHA0_CRM_MUX, NC_SPI_MEDHA0_CRM_MUX_IN1, "NC_SPI_MEDHA0_CRM_MUX_IN1" }, + { NC_SPI_MEDHA1_CRM_MUX, NC_SPI_MEDHA1_CRM_MUX_IN1, "NC_SPI_MEDHA1_CRM_MUX_IN1" }, + { NC_SPI_HAMSA_CRM_MUX, NC_SPI_HAMSA_CRM_MUX_IN1, "NC_SPI_HAMSA_CRM_MUX_IN1"}, +}; + +bool bspi_name_get(uint8_t idx, uint8_t **name) +{ + CHECK_NULL_ARG_WITH_RETURN(name, false); + + if (idx >= MAX_BSPI_IDX) { + *name = NULL; + return false; + } + + *name = (uint8_t *)asic_bspi_mux_table[idx].mux_name; + return true; +} + +static int cmd_bspi_get_all(const struct shell *shell, size_t argc, char **argv) +{ + if (get_asic_board_id() != ASIC_BOARD_ID_EVB) + { + shell_warn(shell, "EVB support only!"); + return -1; + } + + shell_print(shell, "%-4s|%-25s", "BSPI name", "1/0 (on/off)"); + for (int i = 0; i < MAX_BSPI_IDX; i++) { + uint8_t *bspi_mux_name = (uint8_t *)asic_bspi_mux_table[i].mux_name; + int on_off_value = gpio_get(asic_bspi_mux_table[i].gpio_idx); + shell_print(shell, "%-4d|%-40s|0x%-40d", i, bspi_mux_name, on_off_value); + } + + return 0; +} + + +static int cmd_bpsi_set(const struct shell *shell, size_t argc, char **argv) +{ + + if (get_asic_board_id() != ASIC_BOARD_ID_EVB) + { + shell_warn(shell, "EVB support only!"); + return -1; + } + + if (argc != 3) { + shell_print(shell, "Usage: bspi mux set %s ", argv[0]); + return -1; + } + + // if dc is not on , it won't work + if (!gpio_get(RST_IRIS_PWR_ON_PLD_R1_N)) + { + shell_warn(shell, "Need to do DC on first or it won't works!"); + return -1; + } + + const char *name = argv[1]; + long set_val = strtol(argv[2], NULL, 10); + if (!strcmp(name, "NC_SPI_MEDHA0_CRM_MUX_IN1")) + { + if (gpio_set(NC_SPI_MEDHA0_CRM_MUX_IN1, set_val) == -1) + { + shell_print(shell, "set NC_SPI_MEDHA0_CRM_MUX_IN1 fail!"); + return 0; + } + + } + else if (!strcmp(name, "NC_SPI_MEDHA1_CRM_MUX_IN1")) + { + if (gpio_set(NC_SPI_MEDHA1_CRM_MUX_IN1, set_val) == -1) + { + shell_print(shell, "set NC_SPI_MEDHA1_CRM_MUX_IN1 fail!"); + return 0; + } + + } + else if (!strcmp(name, "NC_SPI_HAMSA_CRM_MUX_IN1")) + { + if (gpio_set(NC_SPI_HAMSA_CRM_MUX_IN1, set_val) == -1) + { + shell_print(shell, "set NC_SPI_HAMSA_CRM_MUX_IN1 fail!"); + return 0; + } + + } + + shell_print(shell, "Set %s %s success\n", argv[1], argv[2]); + return 0; +} + +static void asic_bspi_mux_name_get_(size_t idx, struct shell_static_entry *entry) +{ + uint8_t *name = NULL; + bspi_name_get((uint8_t)idx, &name); + + entry->syntax = (name) ? (const char *)name : NULL; + entry->handler = NULL; + entry->help = NULL; + entry->subcmd = NULL; +} + +SHELL_DYNAMIC_CMD_CREATE(asic_bspi_mux_name, asic_bspi_mux_name_get_); + +/* level 2 */ +SHELL_STATIC_SUBCMD_SET_CREATE(sub_bspi_get_cmds, + SHELL_CMD(all, NULL, "asic BSPI mux get all", cmd_bspi_get_all), + SHELL_SUBCMD_SET_END); + +/* level 1 */ +SHELL_STATIC_SUBCMD_SET_CREATE(sub_bspi_cmds, + SHELL_CMD(get, &sub_bspi_get_cmds, "get all", NULL), + SHELL_CMD_ARG(set, &asic_bspi_mux_name, + "set |all", + cmd_bpsi_set, 3, 1), + SHELL_SUBCMD_SET_END); + +/* Root of command test */ +SHELL_CMD_REGISTER(asic_bspi, &sub_bspi_cmds, "asic BSPI set/get commands", NULL); diff --git a/meta-facebook/sb-rb/src/shell/shell_plat_asic_mfio_debug.c b/meta-facebook/sb-rb/src/shell/shell_plat_asic_mfio_debug.c new file mode 100644 index 0000000000..fbedc82ded --- /dev/null +++ b/meta-facebook/sb-rb/src/shell/shell_plat_asic_mfio_debug.c @@ -0,0 +1,294 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "plat_isr.h" +#include "plat_i2c.h" +#include "plat_hook.h" +#include "plat_cpld.h" +#include "plat_ioexp.h" +#include "plat_class.h" + +LOG_MODULE_REGISTER(plat_asic_mfio_debug_shell, LOG_LEVEL_DBG); + +#define NC_HAMSA_MFIO20_BIT 2 +#define NC_HAMSA_MFIO21_BIT 3 +#define NC_HAMSA_MFIO22_BIT 4 +#define NC_HAMSA_MFIO23_BIT 5 +#define NC_HAMSA_MFIO24_BIT 6 +#define NC_HAMSA_MFIO25_BIT 7 +#define NC_HAMSA_MFIO26_BIT 0 +#define NC_HAMSA_MFIO27_BIT 1 +#define NC_HAMSA_MFIO28_BIT 2 +#define NC_HAMSA_MFIO29_BIT 3 +#define NC_HAMSA_MFIO30_BIT 4 +#define NC_HAMSA_MFIO31_BIT 5 + +#define PORT_0 0 +#define PORT_1 1 +#define PORT_2 2 + +// unassigned MFIO struct +typedef struct { + const char *name; + uint8_t bit; + uint8_t port; +} unassigned_mifo_pin_map_t; + +typedef struct { + uint8_t config_reg; + uint8_t output_reg; + uint8_t input_reg; +} port_map_t; + +static const port_map_t port_map[] = { + {TCA6424A_CONFIG_0, TCA6424A_OUTPUT_PORT_0, TCA6424A_INPUT_PORT_0}, + {TCA6424A_CONFIG_1, TCA6424A_OUTPUT_PORT_1, TCA6424A_INPUT_PORT_1}, + {TCA6424A_CONFIG_2, TCA6424A_OUTPUT_PORT_2, TCA6424A_INPUT_PORT_2}, +}; + +static const unassigned_mifo_pin_map_t unassigned_mfio_list[] = { + { "NC_HAMSA_MFIO20", NC_HAMSA_MFIO20_BIT, PORT_0 }, + { "NC_HAMSA_MFIO21", NC_HAMSA_MFIO21_BIT, PORT_0 }, + { "NC_HAMSA_MFIO22", NC_HAMSA_MFIO22_BIT, PORT_0 }, + { "NC_HAMSA_MFIO23", NC_HAMSA_MFIO23_BIT, PORT_0 }, + { "NC_HAMSA_MFIO24", NC_HAMSA_MFIO24_BIT, PORT_0 }, + { "NC_HAMSA_MFIO25", NC_HAMSA_MFIO25_BIT, PORT_0 }, + { "NC_HAMSA_MFIO26", NC_HAMSA_MFIO26_BIT, PORT_1 }, + { "NC_HAMSA_MFIO27", NC_HAMSA_MFIO27_BIT, PORT_1 }, + { "NC_HAMSA_MFIO28", NC_HAMSA_MFIO28_BIT, PORT_1 }, + { "NC_HAMSA_MFIO29", NC_HAMSA_MFIO29_BIT, PORT_1 }, + { "NC_HAMSA_MFIO30", NC_HAMSA_MFIO30_BIT, PORT_1 }, + { "NC_HAMSA_MFIO31", NC_HAMSA_MFIO31_BIT, PORT_1 }, +}; + +// asic MFIO 12 13 14 +typedef struct { + const char *name; + uint8_t config_reg; + uint8_t config_bit; + uint8_t input_reg; + uint8_t input_bit; + uint8_t output_reg; + uint8_t output_bit; +} asic_mifo_pin_map_t; + +// name, config reg, config bit, input reg, input bit, output reg, output bit +static const asic_mifo_pin_map_t mfio_list[] = { + { "HAMSA_MFIO12", 0xB8, 2, 0xBA, 2, 0x17, 7 }, + { "HAMSA_MFIO13", 0xB8, 1, 0xBA, 1, 0x17, 6 }, + { "HAMSA_MFIO14", 0xB8, 0, 0xBA, 0, 0x17, 5 }, + { "MEDHA0_MFIO12", 0xB9, 5, 0xBB, 5, 0x1E, 5 }, + { "MEDHA0_MFIO13", 0xB9, 4, 0xBB, 4, 0x1E, 4 }, + { "MEDHA0_MFIO14", 0xB9, 3, 0xBB, 3, 0x1E, 3 }, + { "MEDHA1_MFIO12", 0xB9, 2, 0xBB, 2, 0x1E, 2 }, + { "MEDHA1_MFIO13", 0xB9, 1, 0xBB, 1, 0x1E, 1 }, + { "MEDHA1_MFIO14", 0xB9, 0, 0xBB, 0, 0x1E, 0 }, +}; + +static int cmd_mfio_get_all(const struct shell *shell, size_t argc, char **argv) +{ + shell_print(shell, "%-20s|%-15s|%-25s", "MFIO name", "Input/Output", "value"); + + uint8_t config = 0; + uint8_t config_value = 0; + uint8_t input_value = 0; + uint8_t output_value = 0; + + // asic MFIO + for(int i = 0; i < ARRAY_SIZE(mfio_list); i++){ + if (config != mfio_list[i].config_reg){ + config = mfio_list[i].config_reg; + if (!plat_read_cpld(mfio_list[i].config_reg, &config_value, 1)) { + LOG_DBG("plat_read_cpld failed: offset=0x%02x", config); + shell_error(shell, "read MFIO config from CPLD failed"); + return -1; + } + if (!plat_read_cpld(mfio_list[i].input_reg, &input_value, 1)) { + LOG_DBG("plat_read_cpld failed: offset=0x%02x", config); + shell_error(shell, "read MFIO input from CPLD failed"); + return -1; + } + if (!plat_read_cpld(mfio_list[i].output_reg, &output_value, 1)) { + LOG_DBG("plat_read_cpld failed: offset=0x%02x", config); + shell_error(shell, "read MFIO output from CPLD failed"); + return -1; + } + } + if(config_value & BIT(mfio_list[i].config_bit)) + shell_print(shell, "%-20s|%-15s|%-10d", mfio_list[i].name, "Input", (input_value>>mfio_list[i].input_bit)&1); + else + shell_print(shell, "%-20s|%-15s|%-10d", mfio_list[i].name, "Output", (output_value>>mfio_list[i].output_bit)&1); + + } + + if (get_asic_board_id() != ASIC_BOARD_ID_EVB) { + return 0; + } + + // unassigned MFIO + for(int i = 0; i < ARRAY_SIZE(unassigned_mfio_list); i++){ + if (config != port_map[unassigned_mfio_list[i].port].config_reg){ + config = port_map[unassigned_mfio_list[i].port].config_reg; + if (!tca6424a_i2c_read(port_map[unassigned_mfio_list[i].port].config_reg, &config_value, 1)) { + LOG_DBG("tca6424a_i2c_read failed: offset=0x%02x", port_map[unassigned_mfio_list[i].port].config_reg); + shell_error(shell, "read MFIO config from ioexp failed"); + return -1; + } + if (!tca6424a_i2c_read(port_map[unassigned_mfio_list[i].port].input_reg, &input_value, 1)) { + LOG_DBG("tca6424a_i2c_read failed: offset=0x%02x", port_map[unassigned_mfio_list[i].port].input_reg); + shell_error(shell, "read MFIO input from ioexp failed"); + return -1; + } + if (!tca6424a_i2c_read(port_map[unassigned_mfio_list[i].port].output_reg, &output_value, 1)) { + LOG_DBG("plat_read_cpld failed: offset=0x%02x", port_map[unassigned_mfio_list[i].port].input_reg); + shell_error(shell, "read MFIO output from ioexp failed"); + return -1; + } + } + if((config_value>>unassigned_mfio_list[i].bit)&1) + shell_print(shell, "%-20s|%-15s|%-10d", unassigned_mfio_list[i].name, "Input", (input_value>>unassigned_mfio_list[i].bit)&1); + else + shell_print(shell, "%-20s|%-15s|%-10d", unassigned_mfio_list[i].name, "Output", (output_value>>unassigned_mfio_list[i].bit)&1); + + } + + return 0; +} + +static int cmd_set_mfio_io(const struct shell *shell, size_t argc, char **argv) +{ + uint8_t set_value = strtol(argv[2], NULL, 10); + + for(int i = 0; i < ARRAY_SIZE(mfio_list); i++){ + if(!strcmp(mfio_list[i].name, argv[1])){ + if(!set_cpld_bit(mfio_list[i].config_reg, mfio_list[i].config_bit, set_value)){ + shell_error(shell, "write MFIO config to CPLD failed"); + return -1; + } + shell_print(shell, "set %s as : %s", mfio_list[i].name, (set_value == 0)? "Output": "Input"); + return 0; + } + } + + if (get_asic_board_id() != ASIC_BOARD_ID_EVB) { + goto error; + } + + for(int i = 0; i < ARRAY_SIZE(unassigned_mfio_list); i++){ + if(!strcmp(unassigned_mfio_list[i].name, argv[1])){ + if(!tca6424a_i2c_write_bit(port_map[unassigned_mfio_list[i].port].config_reg,unassigned_mfio_list[i].bit, set_value)){ + shell_error(shell, "write MFIO config to ioexp failed"); + return -1; + } + shell_print(shell, "set %s as : %s", unassigned_mfio_list[i].name, (set_value == 0)? "Output": "Input"); + return 0; + } + } +error: + LOG_ERR("MFIO name not found"); + return -1; +} + +static int cmd_set_mfio_value(const struct shell *shell, size_t argc, char **argv) +{ + uint8_t set_value = strtol(argv[2], NULL, 10); + uint8_t config_value = 0; + + for(int i = 0; i < ARRAY_SIZE(mfio_list); i++){ + if(!strcmp(mfio_list[i].name, argv[1])){ + if (!plat_read_cpld(mfio_list[i].config_reg, &config_value, 1)) { + LOG_DBG("plat_read_cpld failed: offset=0x%02x", mfio_list[i].config_reg); + shell_error(shell, "read MFIO config from CPLD failed"); + return -1; + } + if ((config_value>>mfio_list[i].config_bit)&1){ + shell_error(shell, "Can't set value to Input port"); + return -1; + } + if(!set_cpld_bit(mfio_list[i].output_reg, mfio_list[i].output_bit, set_value)){ + shell_error(shell, "write MFIO output to CPLD failed"); + return -1; + } + shell_print(shell, "set %s value to: %d", mfio_list[i].name, set_value); + return 0; + } + } + if (get_asic_board_id() != ASIC_BOARD_ID_EVB) { + goto error; + } + + for(int i = 0; i < ARRAY_SIZE(unassigned_mfio_list); i++){ + if(!strcmp(unassigned_mfio_list[i].name, argv[1])){ + tca6424a_i2c_read(port_map[unassigned_mfio_list[i].port].config_reg, &config_value, 1); + if ((config_value>>unassigned_mfio_list[i].bit)&1){ + shell_error(shell, "Can't set value to Input port"); + return -1; + } + if(!tca6424a_i2c_write_bit(port_map[unassigned_mfio_list[i].port].output_reg,unassigned_mfio_list[i].bit, set_value)) + return -1; + shell_print(shell, "set %s value to: %d", unassigned_mfio_list[i].name, set_value); + return 0; + } + } + +error: + LOG_ERR("MFIO name not found"); + return -1; +} + +static void mfio_dynamic_get_name(size_t idx, struct shell_static_entry *entry) +{ + entry->syntax = NULL; + entry->handler = NULL; + entry->help = NULL; + entry->subcmd = NULL; + + if (idx < ARRAY_SIZE(mfio_list)){ + entry->syntax = mfio_list[idx].name; + } + if (get_asic_board_id() != ASIC_BOARD_ID_EVB) { + return; + } + if (idx < (ARRAY_SIZE(unassigned_mfio_list)+ARRAY_SIZE(mfio_list))) { + entry->syntax = unassigned_mfio_list[idx-ARRAY_SIZE(mfio_list)].name; + } +} + +SHELL_DYNAMIC_CMD_CREATE(mifo_name, mfio_dynamic_get_name); + +/* level 2 */ +SHELL_STATIC_SUBCMD_SET_CREATE(sub_mfio_get_cmds, + SHELL_CMD(all, NULL, "bootstrap get all", cmd_mfio_get_all), + SHELL_SUBCMD_SET_END); + +SHELL_STATIC_SUBCMD_SET_CREATE(sub_set_cmds, + SHELL_CMD(io, &mifo_name, "set io 1/0, 1 = input, 0 = output", cmd_set_mfio_io), + SHELL_CMD(value, &mifo_name, "set value 1/0, 1 = high, 0 = low", cmd_set_mfio_value), + SHELL_SUBCMD_SET_END); + +/* level 1 */ +SHELL_STATIC_SUBCMD_SET_CREATE(sub_asic_mfio_debug_cmds, + SHELL_CMD(get, &sub_mfio_get_cmds, "get all", NULL), + SHELL_CMD(set, &sub_set_cmds, + "set io/value 1/0", + NULL), + SHELL_SUBCMD_SET_END); + +/* Root of command test */ +SHELL_CMD_REGISTER(asic_mfio_debug, &sub_asic_mfio_debug_cmds, "asic_mfio_debug set/get commands", NULL); diff --git a/meta-facebook/sb-rb/src/shell/shell_plat_bootstrap.c b/meta-facebook/sb-rb/src/shell/shell_plat_bootstrap.c index 526bdf2ce4..5eb683a0fa 100644 --- a/meta-facebook/sb-rb/src/shell/shell_plat_bootstrap.c +++ b/meta-facebook/sb-rb/src/shell/shell_plat_bootstrap.c @@ -22,6 +22,7 @@ #include "plat_hook.h" #include "plat_cpld.h" #include "plat_ioexp.h" +#include "plat_class.h" #define AEGIS_CPLD_ADDR (0x4C >> 1) @@ -60,6 +61,7 @@ static int cmd_bootstrap_get_all(const struct shell *shell, size_t argc, char ** LOG_ERR("Can't find strap_rail_name by rail index: %x", i); continue; } + int drive_level = -1; if (!get_bootstrap_change_drive_level(i, &drive_level)) { @@ -134,6 +136,41 @@ static int cmd_bootstrap_set(const struct shell *shell, size_t argc, char **argv return -1; } + // check TEST_STRAP for MFIO 6 8 10 + int drive_level = -1; + + switch (rail) { + case STRAP_INDEX_HAMSA_MFIO6: + case STRAP_INDEX_HAMSA_MFIO8: + case STRAP_INDEX_HAMSA_MFIO10: + get_bootstrap_change_drive_level(STRAP_INDEX_HAMSA_TEST_STRAP_R, &drive_level); + if (drive_level == 0) { + shell_error(shell, "Can't change due to HAMSA_TEST_STRAP_R is 0x00 "); + return -1; + } + break; + case STRAP_INDEX_MEDHA0_MFIO6: + case STRAP_INDEX_MEDHA0_MFIO8: + case STRAP_INDEX_MEDHA0_MFIO10: + get_bootstrap_change_drive_level(STRAP_INDEX_MEDHA0_TEST_STRAP, &drive_level); + if (drive_level == 0) { + shell_error(shell, "Can't change due to MEDHA0_TEST_STRAP is 0x00"); + return -1; + } + break; + case STRAP_INDEX_MEDHA1_MFIO6: + case STRAP_INDEX_MEDHA1_MFIO8: + case STRAP_INDEX_MEDHA1_MFIO10: + get_bootstrap_change_drive_level(STRAP_INDEX_MEDHA1_TEST_STRAP, &drive_level); + if (drive_level == 0) { + shell_error(shell, "Can't change due to MEDHA1_TEST_STRAP is 0x00 "); + return -1; + } + break; + default: + break; + } + bool is_default = false; if (!strcmp(argv[2], "default")) is_default = true; @@ -149,6 +186,7 @@ static int cmd_bootstrap_set(const struct shell *shell, size_t argc, char **argv shell_error(shell, "Can't find bootstrap_item by rail index: %d", rail); return -1; } + // write change_setting_value to cpld or io-exp if (!set_bootstrap_val_to_device(bootstrap_item.index, change_setting_value)) { LOG_ERR("Can't set bootstrap[%2d]=%02x", bootstrap_item.index, diff --git a/meta-facebook/sb-rb/src/shell/shell_plat_i2c_switch_control.c b/meta-facebook/sb-rb/src/shell/shell_plat_i2c_switch_control.c new file mode 100644 index 0000000000..edb2a71275 --- /dev/null +++ b/meta-facebook/sb-rb/src/shell/shell_plat_i2c_switch_control.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "plat_gpio.h" +#include "plat_pldm_sensor.h" + +LOG_MODULE_REGISTER(plat_i2c_switch_control_shell, LOG_LEVEL_INF); + +static int cmd_i2c_switch_get_all(const struct shell *shell, size_t argc, char **argv) +{ + shell_print(shell, "I2C Switch GPIO status:"); + + shell_print(shell, "HAMSA_SW_EN : %d", gpio_get(HAMSA_SW_EN)); + shell_print(shell, "MEDHA0_SW_EN : %d", gpio_get(MEDHA0_SW_EN)); + shell_print(shell, "MEDHA1_SW_EN : %d", gpio_get(MEDHA1_SW_EN)); + + return 0; +} + +static int cmd_i2c_switch_set_all(const struct shell *shell, size_t argc, char **argv) +{ + /* Usage: i2c_switch_control set all <0|1> */ + if (argc != 2) { + shell_print(shell, "Usage: i2c_switch_control set all <0|1>"); + return -EINVAL; + } + + long set_val = strtol(argv[1], NULL, 10); + if (set_val != 0 && set_val != 1) { + shell_error(shell, "Value must be 0 or 1"); + return -EINVAL; + } + + if (set_val == 1) { + /* stop VR polling before enabling I2C switches */ + if (get_plat_sensor_vr_polling_enable_flag()) { + LOG_INF("Disable VR polling before I2C switch enable"); + set_plat_sensor_vr_polling_enable_flag(false); + } + + gpio_set(HAMSA_SW_EN, 1); + gpio_set(MEDHA0_SW_EN, 1); + gpio_set(MEDHA1_SW_EN, 1); + + shell_print(shell, "Set all I2C switch GPIOs to 1 (VR polling disabled)"); + return 0; + } + + /* set_val == 0 */ + gpio_set(HAMSA_SW_EN, 0); + gpio_set(MEDHA0_SW_EN, 0); + gpio_set(MEDHA1_SW_EN, 0); + + /* restore VR polling after disabling I2C switches */ + if (!get_plat_sensor_vr_polling_enable_flag()) { + LOG_INF("Enable VR polling after I2C switch disable"); + set_plat_sensor_vr_polling_enable_flag(true); + } + + shell_print(shell, "Set all I2C switch GPIOs to 0 (VR polling enabled)"); + return 0; +} + +/* level 2 */ +SHELL_STATIC_SUBCMD_SET_CREATE(sub_get_cmds, + SHELL_CMD(all, NULL, "get all", cmd_i2c_switch_get_all), + SHELL_SUBCMD_SET_END); + +SHELL_STATIC_SUBCMD_SET_CREATE(sub_set_cmds, + SHELL_CMD(all, NULL, "set all <0|1>", cmd_i2c_switch_set_all), + SHELL_SUBCMD_SET_END); + +/* level 1 */ +SHELL_STATIC_SUBCMD_SET_CREATE(sub_i2c_switch_control_cmds, + SHELL_CMD(get, &sub_get_cmds, "get all", NULL), + SHELL_CMD(set, &sub_set_cmds, "set all <0|1>", NULL), + SHELL_SUBCMD_SET_END); + +SHELL_CMD_REGISTER(i2c_switch_control, &sub_i2c_switch_control_cmds, + "I2C switch control (HAMSA/MEDHA0/MEDHA1)", NULL); diff --git a/meta-facebook/sb-rb/src/shell/shell_plat_power_capping.c b/meta-facebook/sb-rb/src/shell/shell_plat_power_capping.c new file mode 100644 index 0000000000..8f9e2c98ba --- /dev/null +++ b/meta-facebook/sb-rb/src/shell/shell_plat_power_capping.c @@ -0,0 +1,243 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "plat_i2c.h" +#include "plat_cpld.h" +#include "plat_adc.h" +#include "plat_power_capping.h" + +typedef struct { + const char *name; + uint8_t vr_idx; + uint8_t lv; +} power_capping_item_t; + +static const power_capping_item_t power_capping_item_list[CAPPING_VR_IDX_MAX * CAPPING_LV_IDX_MAX] = { + { "MEDHA0_LV1", CAPPING_VR_IDX_MEDHA0, CAPPING_LV_IDX_LV1 }, + { "MEDHA0_LV2", CAPPING_VR_IDX_MEDHA0, CAPPING_LV_IDX_LV2 }, + { "MEDHA0_LV3", CAPPING_VR_IDX_MEDHA0, CAPPING_LV_IDX_LV3 }, + { "MEDHA1_LV1", CAPPING_VR_IDX_MEDHA1, CAPPING_LV_IDX_LV1 }, + { "MEDHA1_LV2", CAPPING_VR_IDX_MEDHA1, CAPPING_LV_IDX_LV2 }, + { "MEDHA1_LV3", CAPPING_VR_IDX_MEDHA1, CAPPING_LV_IDX_LV3 }, +}; + +static int cmd_power_capping_get_all(const struct shell *shell, size_t argc, char **argv) +{ + shell_print(shell, "==================Power Capping Info================="); + shell_print(shell, "Method: %d ( 0:LOOK_UP_TABLE, 1:CREDIT_BASE )", + get_power_capping_method()); + shell_print(shell, "Source: %d ( 0:VR, 1:ADC )\n", get_power_capping_source()); + shell_print(shell, "---------------------MEDHA0---------------------"); + shell_print(shell, "MEDHA0 LV1 time window: %4d (us)", + get_power_capping_time_w(CAPPING_VR_IDX_MEDHA0, CAPPING_LV_IDX_LV1)); + shell_print(shell, "MEDHA0 LV1 threshold: %6d (W), %4d (A)\n", + get_power_capping_threshold(CAPPING_VR_IDX_MEDHA0, CAPPING_LV_IDX_LV1), + get_power_capping_current_threshold(CAPPING_VR_IDX_MEDHA0)); + shell_print(shell, "MEDHA0 LV2 time window: %4d (ms)", + get_power_capping_time_w(CAPPING_VR_IDX_MEDHA0, CAPPING_LV_IDX_LV2)); + shell_print(shell, "MEDHA0 LV2 threshold: %6d (W)", + get_power_capping_threshold(CAPPING_VR_IDX_MEDHA0, CAPPING_LV_IDX_LV2)); + shell_print(shell, "MEDHA0 LV2 avg_power: %6d (W)\n", + get_power_capping_avg_power(CAPPING_VR_IDX_MEDHA0, CAPPING_LV_IDX_LV2)); + shell_print(shell, "MEDHA0 LV3 time window: %4d (ms)", + get_power_capping_time_w(CAPPING_VR_IDX_MEDHA0, CAPPING_LV_IDX_LV3)); + shell_print(shell, "MEDHA0 LV3 threshold: %6d (W)", + get_power_capping_threshold(CAPPING_VR_IDX_MEDHA0, CAPPING_LV_IDX_LV3)); + shell_print(shell, "MEDHA0 LV3 avg_power: %6d (W)\n", + get_power_capping_avg_power(CAPPING_VR_IDX_MEDHA0, CAPPING_LV_IDX_LV3)); + shell_print(shell, "---------------------MEDHA1---------------------"); + shell_print(shell, "MEDHA1 LV1 time window: %4d (us)", + get_power_capping_time_w(CAPPING_VR_IDX_MEDHA1, CAPPING_LV_IDX_LV1)); + shell_print(shell, "MEDHA1 LV1 threshold: %6d (W), %4d (A)\n", + get_power_capping_threshold(CAPPING_VR_IDX_MEDHA1, CAPPING_LV_IDX_LV1), + get_power_capping_current_threshold(CAPPING_VR_IDX_MEDHA1)); + shell_print(shell, "MEDHA1 LV2 time window: %4d (ms)", + get_power_capping_time_w(CAPPING_VR_IDX_MEDHA1, CAPPING_LV_IDX_LV2)); + shell_print(shell, "MEDHA1 LV2 threshold: %6d (W)", + get_power_capping_threshold(CAPPING_VR_IDX_MEDHA1, CAPPING_LV_IDX_LV2)); + shell_print(shell, "MEDHA0 LV2 avg_power: %6d (W)\n", + get_power_capping_avg_power(CAPPING_VR_IDX_MEDHA1, CAPPING_LV_IDX_LV2)); + shell_print(shell, "MEDHA1 LV3 time window: %4d (ms)", + get_power_capping_time_w(CAPPING_VR_IDX_MEDHA1, CAPPING_LV_IDX_LV3)); + shell_print(shell, "MEDHA1 LV3 threshold: %6d (W)", + get_power_capping_threshold(CAPPING_VR_IDX_MEDHA1, CAPPING_LV_IDX_LV3)); + shell_print(shell, "MEDHA0 LV3 avg_power: %6d (W)\n", + get_power_capping_avg_power(CAPPING_VR_IDX_MEDHA1, CAPPING_LV_IDX_LV3)); + return 0; +} + +static int cmd_power_capping_set_method(const struct shell *shell, size_t argc, char **argv) +{ + if (!strcmp(argv[0], "LOOK_UP_TABLE")) { + shell_print(shell, "Method set to LOOK_UP_TABLE"); + set_power_capping_method(CAPPING_M_LOOK_UP_TABLE); + } else if (!strcmp(argv[0], "CREDIT_BASE")) { + shell_print(shell, "Method set to CREDIT_BASE"); + set_power_capping_method(CAPPING_M_CREDIT_BASE); + } else { + shell_error(shell, "method should be "); + return -1; + } + + return 0; +} + +static int cmd_power_capping_set_source(const struct shell *shell, size_t argc, char **argv) +{ + if (!strcmp(argv[0], "VR")) { + shell_print(shell, "Source set to VR"); + set_power_capping_source(CAPPING_SOURCE_VR); + } else if (!strcmp(argv[0], "ADC")) { + shell_print(shell, "Source set to ADC"); + set_power_capping_source(CAPPING_SOURCE_ADC); + } else { + shell_error(shell, "source should be "); + return -1; + } + + return 0; +} + +static int cmd_power_capping_set_time_window(const struct shell *shell, size_t argc, char **argv) +{ + uint8_t idx = 0xff; + for (uint8_t id = 0; id < ARRAY_SIZE(power_capping_item_list); id++) { + if (!strcmp(argv[1], power_capping_item_list[id].name)) { + idx = id; + break; + } + } + + if (idx == 0xff) { + shell_error(shell, "Here is the list:"); + for (uint8_t i = 0; i < ARRAY_SIZE(power_capping_item_list); i++) { + shell_print(shell, "%s", power_capping_item_list[i].name); + } + return -1; + } + + uint16_t value = strtol(argv[2], NULL, 10); + if (value < ADC_AVERGE_TIMES_MIN && value > ADC_AVERGE_TIMES_MAX) { + shell_error(shell, "time should be less equal to %d", ADC_AVERGE_TIMES_MAX); + return -1; + } + + if (power_capping_item_list[idx].lv == CAPPING_LV_IDX_LV1) { + uint8_t tmp_idx = 0; + if (!find_cpld_lv1_time_window_idx_by_value(&tmp_idx, value)) { + shell_error(shell, "For LV1, the time(us) should be:"); + shell_print(shell, "{ 0, 1, 3, 5, 10, 15, 20, 50 }"); + return -1; + } + } + + set_power_capping_time_w(power_capping_item_list[idx].vr_idx, + power_capping_item_list[idx].lv, value); + shell_print(shell, "set time_w %s to %d", power_capping_item_list[idx].name, value); + + return 0; +} + +static int cmd_power_capping_set_threshold(const struct shell *shell, size_t argc, char **argv) +{ + uint8_t idx = 0xff; + for (uint8_t id = 0; id < ARRAY_SIZE(power_capping_item_list); id++) { + if (!strcmp(argv[1], power_capping_item_list[id].name)) { + idx = id; + break; + } + } + + if (idx == 0xff) { + shell_error(shell, "Here is the list:"); + for (uint8_t i = 0; i < ARRAY_SIZE(power_capping_item_list); i++) { + shell_print(shell, "%s", power_capping_item_list[i].name); + } + return -1; + } + + uint16_t value = strtol(argv[2], NULL, 10); + set_power_capping_threshold(power_capping_item_list[idx].vr_idx, + power_capping_item_list[idx].lv, value); + shell_print(shell, "set threshold %s to %d", power_capping_item_list[idx].name, value); + + return 0; +} + +static void power_capping_name_get_for_set_cmd(size_t idx, struct shell_static_entry *entry) +{ + entry->syntax = NULL; + entry->handler = NULL; + entry->help = NULL; + entry->subcmd = NULL; + + if (idx < ARRAY_SIZE(power_capping_item_list)) { + entry->syntax = power_capping_item_list[idx].name; + } +} + +SHELL_DYNAMIC_CMD_CREATE(power_capping_name, power_capping_name_get_for_set_cmd); + +/* level 3 */ +SHELL_STATIC_SUBCMD_SET_CREATE( + set_method_subcmds, + SHELL_CMD_ARG(LOOK_UP_TABLE, NULL, "power_capping set method ", + cmd_power_capping_set_method, 1, 0), + SHELL_CMD_ARG(CREDIT_BASE, NULL, "power_capping set method ", + cmd_power_capping_set_method, 1, 0), + SHELL_SUBCMD_SET_END); + +SHELL_STATIC_SUBCMD_SET_CREATE(set_source_subcmds, + SHELL_CMD_ARG(VR, NULL, "power_capping set source ", + cmd_power_capping_set_source, 1, 0), + SHELL_CMD_ARG(ADC, NULL, "power_capping set source ", + cmd_power_capping_set_source, 1, 0), + SHELL_SUBCMD_SET_END); + +/* level 2 */ +SHELL_STATIC_SUBCMD_SET_CREATE(get_subcmds, + SHELL_CMD(all, NULL, "power_capping get all", + cmd_power_capping_get_all), + SHELL_SUBCMD_SET_END); + +SHELL_STATIC_SUBCMD_SET_CREATE( + set_subcmds, + SHELL_CMD_ARG(method, &set_method_subcmds, + "power_capping set method ", NULL, 2, 0), + SHELL_CMD_ARG(source, &set_source_subcmds, "power_capping set source ", NULL, 2, + 0), + SHELL_CMD_ARG(time_window, &power_capping_name, + "power_capping set time_window