/******************************************************************************* * DISCLAIMER * This software is supplied by Renesas Electronics Corporation and is only * intended for use with Renesas products. No other uses are authorized. This * software is owned by Renesas Electronics Corporation and is protected under * all applicable laws, including copyright laws. * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING * THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT * LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. * TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS * ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE * FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR * ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * Renesas reserves the right, without notice, to make changes to this software * and to discontinue the availability of this software. By using this software, * you agree to the additional terms and conditions found by accessing the * following link: * http://www.renesas.com/disclaimer * Copyright 2023-2024 Renesas Electronics Corporation All rights reserved. *******************************************************************************/ /******************************************************************************* * DESCRIPTION : I2C driver ******************************************************************************/ /****************************************************************************** * @file i2c.c * - Version : 0.02 * @brief I2C driver. * . *****************************************************************************/ /****************************************************************************** * History : DD.MM.YYYY Version Description * : 16.11.2023 0.01 First Release * : 24.06.2024 0.02 Remove pre-process branch of i2c5_read(). *****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include /* Setting value for PFC */ #define GPSR4_TSN0_MDIO (0x00000001U) /* bit0 */ #define PMIC_ADDR ((0x54) << 1) /* regulation register */ #define PMIC_ADDR_P ((0x55) << 1) /* protection register */ #define PMIC_ADDR_OTP ((0x64) << 1) /* OTP register ? */ void PMIC_SM_27A(void) { /* // PRESET -> PRESETOUT Check // Set SDI and EN High, and Presetout low MCU_VMONOUT0 = B_PIN_STATE_HIGH; MCU_VMONOUT1 = B_PIN_STATE_HIGH; MCU_SDI4 = B_PIN_STATE_HIGH; MCU_ERROROUT_M = B_PIN_STATE_HIGH; MCU_PRESET_OUT = B_PIN_STATE_LOW; MCU_EN_PIN = B_PIN_STATE_HIGH; delay_1ms(20); // Set delay to wait for LBIST to finish while (PMIC_GLOBAL_PGOOD != B_PIN_STATE_HIGH){} // Wait for PGOOD to go high while (PMIC_PRESETB != B_PIN_STATE_HIGH) {} // Wait for PRESET to go high delay_1ms(6); // Set delay to pass 25% of TIMEOUT_PRESET_CHK_TOUT MCU_PRESET_OUT = B_PIN_STATE_HIGH; // Set PRESETOUT High */ // from RAA271005_SAN.pdf page 91 // PRESET# Check is executed by the PMIC automatically // // PGOOD_PMIC(TSN0_MDIO, GP4_00) // /* Set GPSR to GPIO */ // data = mem_read32((uintptr_t)PFC_GPSR4_RW); // data &= ~(GPSR4_TSN0_MDIO); // pfc_reg_write(PFC_GPSR4_RW, data); // /* PUEN disable */ // data = mem_read32((uintptr_t)PFC_PUEN4_RW); // data &= ~(GPSR4_TSN0_MDIO); // pfc_reg_write(PFC_PUEN4_RW, data); // /* skip POSNEG // data = mem_read32((uintptr_t)PFC_PUEN4_RW); // data |= (GPSR4_TSN0_MDIO); // mem_write32((uintptr_t)PFC_PUEN4_RW, data); // */ // /* skip INOUTSEL // data = mem_read32((uintptr_t)PFC_INOUTSEL4_RW); // data &= ~(GPSR4_TSN0_MDIO); // mem_write32((uintptr_t)PFC_INOUTSEL4_RW, data); // */ // /* INEN */ // data = mem_read32((uintptr_t)PFC_INEN4_RW); // data |= (GPSR4_TSN0_MDIO); // mem_write32((uintptr_t)PFC_INEN4_RW, data); // /* INDT */ // do { // data = mem_read32((uintptr_t)PFC_INDT4_R); // } while ((data & GPSR4_TSN0_MDIO) != 0); } #define D_SINT_CODE 0x2A #define FUSA_CTRL_2 (0x09) #define FUSA_CTRL_3 (0x0A) #define FUSA_SOC_CHK_1 (0x15) // SINT Check void PMIC_SM_27B(void) { uint32_t data = D_SINT_CODE; i2c5_write(PMIC_ADDR_P, FUSA_CTRL_2, data); i2c5_read(PMIC_ADDR_P, FUSA_SOC_CHK_1, &data); NOTICE("SINT Check = 0x%x\n", data); i2c5_write(PMIC_ADDR_P, FUSA_CTRL_3, data); } #define FUSA_CTRL_4 (0x0B) #define EXT_PIN_CHK_EN (1U << 5) #define EXT_PIN_CHK_SD1 (1U << 4) #define EXT_PIN_CHK_SD2 (1U << 2) #define EXT_PIN_CHK_SD3 (1U << 1) #define EXT_PIN_CHK_SD4 (1U << 0) /* To read/write an adress after 0x100, it is necessary to write a value to IO_PAGE and access the target address after changing the page. */ #define FUSA_CTRL_D (0x11D) // EXT PINCHECK2 void PMIC_SM_27C(void) { /* // SDI1 Test pmic_rtn_code_tmp = r_pmic_i2c_write(D_PMIC_I2C_PROT_ADDRESS, 0x0B, 0xFF); // Tell the PMIC to look for all SDIs to be high, to do this we set all bits (0xFF) delay_1us(1); MCU_ERROROUT_M = B_PIN_STATE_LOW; // Set SDI1 LOW pmic_rtn_code_tmp = r_pmic_i2c_write(D_PMIC_I2C_PROT_ADDRESS, 0x0B, 0xEF); // Check for the SDI1 to be low delay_1us(1); MCU_ERROROUT_M = B_PIN_STATE_HIGH; // Set SDI1 HIGH // SDI2 Test pmic_rtn_code_tmp = r_pmic_i2c_write(D_PMIC_I2C_PROT_ADDRESS, 0x0B, 0xFF); // Tell the PMIC to look for all SDIs to be high, to do this we set all bits (0xFF) delay_1us(1); MCU_VMONOUT0 = B_PIN_STATE_LOW; // Set SDI2 LOW pmic_rtn_code_tmp = r_pmic_i2c_write(D_PMIC_I2C_PROT_ADDRESS, 0x0B, 0xFB); // Check for the SDI2 to be low delay_1us(1); MCU_VMONOUT0 = B_PIN_STATE_HIGH; // Set SDI2 HIGH // SDI3 Test pmic_rtn_code_tmp = r_pmic_i2c_write(D_PMIC_I2C_PROT_ADDRESS, 0x0B, 0xFF); // Tell the PMIC to look for all SDIs to be high, to do this we set all bits (0xFF) delay_1us(1); MCU_VMONOUT1 = B_PIN_STATE_LOW; // Set SDI3 LOW pmic_rtn_code_tmp = r_pmic_i2c_write(D_PMIC_I2C_PROT_ADDRESS, 0x0B, 0xFC); // Check for the SDI3 to be low delay_1us(1); MCU_VMONOUT1 = B_PIN_STATE_HIGH; // Set SDI3 HIGH // SDI4 Test pmic_rtn_code_tmp = r_pmic_i2c_write(D_PMIC_I2C_PROT_ADDRESS, 0x0B, 0xFF); // Tell the PMIC to look for all SDIs to be high, to do this we set all bits (0xFF) delay_1us(1); MCU_SDI4 = B_PIN_STATE_LOW; // Set SDI4 LOW pmic_rtn_code_tmp = r_pmic_i2c_write(D_PMIC_I2C_PROT_ADDRESS, 0x0B, 0xFE); // Check for the SDI4 to be low delay_1us(1); MCU_SDI4 = B_PIN_STATE_HIGH; // Set SDI4 HIGH comms_rtrncode_tmp = r_pmic_i2c_write(D_PMIC_I2C_PROT_ADDRESS, 0x0B, 0x00); // Must clear out 0x0B after external pin check 2 complete */ uint32_t data = 0xFF; NOTICE("EXT PINCHECK2\n"); // SDI1,2,3,4 Test // Tell the PMIC to look for all SDIs to be high, to do this we set all bits (0xFF) i2c5_write(PMIC_ADDR_P, FUSA_CTRL_4, data); micro_wait(1U); // Must clear out 0x0B after external pin check 2 complete i2c5_write(PMIC_ADDR_P, FUSA_CTRL_4, 0x0); } #define D_LENGTH_FUSA_CTRL_CVM 4 // Based on how many CVM slots is enabled #define FUSA_CHK_CVM1 (0x0D) #define CVM_TEST_START (1U << 0) #define CVM_TEST_DONE (1U << 7) #define FUSA_STATUS_CVM1 (0x0E) #define CVM_TEST_FAIL_3 (0x3U << 6) #define CVM_TEST_FAIL_2 (0x3U << 4) #define CVM_TEST_FAIL_1 (0x3U << 2) #define FUSA_STATUS_CVM2 (0x0F) #define CVM_TEST_FAIL_6 (0x3U << 4) #define CVM_TEST_FAIL_5 (0x3U << 2) #define CVM_TEST_FAIL_4 (0x3U << 0) #define FUSA_CHK_CVM2H (0x10D) #define FUSA_CHK_CVM2L (0x10E) #define FUSA_CHK_CVM3H (0x10F) #define FUSA_CHK_CVM3L (0x110) #define FUSA_CHK_CVM4H (0x111) #define FUSA_CHK_CVM4L (0x112) #define FUSA_CHK_CVM5H (0x113) #define FUSA_CHK_CVM5L (0x114) #define FUSA_CTRL_CVM1 (0x125) #define FUSA_CTRL_CVM2 (0x126) #define FUSA_CTRL_CVM3 (0x127) #define FUSA_CTRL_CVM4 (0x128) #define FUSA_CTRL_CVM5 (0x129) #define FUSA_CTRL_CVM6 (0x12A) #define ADCMON_MASK_ExtINPs (0x133) #define FaultMask_EXT_0_Prot (1U << 0) #define FaultMask_EXT_1_Prot (1U << 0) // CVM Test void PMIC_SM_27D(void) { /* //Array that holds the 8bit dac information ADC1 uint8_t g_ary_cvm_vthref[4] = { 0x0F, //2 0x3A, //3 0x60, //4 0x3A //3 }; //Array that holds the 12bit dac information ADC2 uint8_t g_ary_cvm_vthsense[8] = { 0x03, 0xE1, 0x00, 0xD3, 0x00, 0xD3, 0x03, 0xE1 }; D_LENGTH_FUSA_CTRL_CVM = 4; // Based on how many CVM slots is enabled comms_rtn_code_tmp = r_pmic_i2c_write(D_PMIC_I2C_PROT_ADDRESS, 0x0D, 0x01); // Start CVM Test delay_1ms(1); for(idx = 0; idx = LOG_NOTICE uint32_t data = 0xFF; char *str, *str2, *str3; i2c5_read(PMIC_ADDR_P, FUSA_STATUS_1, &data); if ((data & SOC_ACTIVATED) != 0) str = "PASSED"; else str = "FAILED"; switch (data & (0x7 << 5)) { case SCS_POWER_OFF: str2 = "power off"; break; case SCS_SELF_DIAG: str2 = "self diagnosis"; break; case SCS_POWER_UP : str2 = "power up sequence"; break; case SCS_SOC_ACTIV: str2 = "SoC activation"; break; case SCS_ACTIVE: str2 = "ACTIVE"; break; case SCS_RESET: str2 = "RESET"; break; case SCS_ERROR: str2 = "ERROR"; break; case SCS_LOCK: str2 = "LOCK"; break; default: str2 = "unknown"; break; } switch (data & 0x7) { case SAS_IDLE: str3 = "idle"; break; case SAS_EXT_PIN_CHK_1: str3 = "EXT PIN check(1)"; break; case SAS_SINT_CHK: str3 = "SINT check"; break; case SAS_EXT_PIN_CHK_2: str3 = "EXT PIN check(2)"; break; case SAS_START_WDT: str3 = "start WDT"; break; default: str3 = "unknown"; break; } NOTICE("SoC Activation: %s(%s), %s, 0x%x\n", str, str3, str2, data); #endif } #define WDT_KICK_REG (0x95) #define WDT_LFSR (0x96) #define WDT_CFG0 (0x107) #define WDT_CFG0_QNA (0x1 << 2) #define WDT_CFG0_16QNA (0x1 << 1) #define WDT_CFG0_EN (0x1 << 0) #define WDT_CFG3 (0x10A) void PMIC_SM_12_wdt(void) { uint32_t tmp, question, answer0; i2c5_read(PMIC_ADDR_P, WDT_CFG0, &tmp); if ((tmp & WDT_CFG0_EN) == 0) { NOTICE("WDT is disabled\n"); i2c5_read(PMIC_ADDR_P, 0x01, &tmp); /* set PAGE to 0x00 */ return; } i2c5_read(PMIC_ADDR_P, WDT_LFSR, &question); // Read the question if ((tmp & WDT_CFG0_16QNA) == 0) { // Grab only the first two bits to figure out what to do tmp = question >> 6; answer0 = question & 0x3F; micro_wait(4U); if (tmp == 0x1) { answer0 = (answer0 << 1) | (tmp << 6); } else if (tmp == 0x2) { answer0 = (answer0 >> 1) | (tmp << 6); } else if (tmp == 0x3) { answer0 = (~answer0) | (tmp << 6); } /* else if (tmp == 0x0) { // answer0 = (answer0) | (tmp << 6); } */ i2c5_write(PMIC_ADDR_P, WDT_KICK_REG, answer0); NOTICE("4Q&A: DONE\n"); } else { static uint8_t g_ary_wdt_answer[] = { 0x00, 0x4F, 0x16, 0x59, 0x8a, 0xc5, 0x9c, 0xd3, 0x2d, 0x62, 0x3b, 0x74, 0xa7, 0xe8, 0xb1, 0xfe, }; uint32_t err_cnt = 0; // Grab the upper nibble to respond to, logic shift the lower nibble away tmp = question >> 4; answer0 = g_ary_wdt_answer[tmp]; i2c5_write(PMIC_ADDR_P, WDT_KICK_REG, answer0); i2c5_read(PMIC_ADDR_P, WDT_CFG3, &question); err_cnt |= (question & 0xFF) << 24; // Check WDT Error counter micro_wait(4U); // For the second answer, take the first answer and flip the upper nibble i2c5_write(PMIC_ADDR_P, WDT_KICK_REG, (answer0 ^ 0xF0) & 0xFF); i2c5_read(PMIC_ADDR_P, WDT_CFG3, &question); err_cnt |= (question & 0xFF) << 16; // Check WDT Error counter micro_wait(4U); // For the third answer, take the first answer and flip the lower nibble i2c5_write(PMIC_ADDR_P, WDT_KICK_REG, (answer0 ^ 0x0F) & 0xFF); i2c5_read(PMIC_ADDR_P, WDT_CFG3, &question); err_cnt |= (question & 0xFF) << 8; // Check WDT Error counter micro_wait(4U); // For the fourth answer, take the first answer and invert the whole byte i2c5_write(PMIC_ADDR_P, WDT_KICK_REG, (answer0 ^ 0xFF) & 0xFF); i2c5_read(PMIC_ADDR_P, WDT_CFG3, &question); err_cnt |= (question & 0xFF) << 0; // Check WDT Error counter if (err_cnt) { NOTICE("16Q&A: Error 0x%x\n", err_cnt); } else { NOTICE("16Q&A: DONE\n"); } i2c5_read(PMIC_ADDR_P, 0x01, &tmp); /* set PAGE to 0x00 */ } } // External Pin Check for ECM void SM_6_3_1(void) {} // External Pin Check for RST void SM_6_3_2(void) {} // initial Toggle Test void SM_5_3_6(void) {} // check POST result of other than "stop" type hierachies void SM_5_1(void) {} // read Back Test for Integrity Check void SM_6_23(void) {} // self test for AES-ACC void SM_4_21(void) {} // self check for Field BIST void SM_5_1_6(void) {} // self check for Field BIST void SM_5_2_6(void) {} // write access protection check at start-up void SM_6_2(void) {} // timeout monitoring for confirmation of PHY start void SM_6_11(void) {} // initial loopback test using PWM void SM_6_14_6(void) {} // integrity check for Program Code void SM_6_22(void) {} // start-up test for THS void SM_6_24_2(void) {} // start-up test for CVM void SM_6_24_3(void) {} // Power isolation Cell Error Detector Test at start-up void SM_6_29(void) {} // clock monitor test at start-up void SM_6_30(void) {}