Files
Tool/IPL/Customer/Mobis/Gen4_ICUMX_Loader/ip/san/v4h.c
2025-12-24 17:21:08 +09:00

459 lines
16 KiB
C

/*******************************************************************************
* 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 <stdbool.h>
#include <stdint.h>
#include <cpg.h>
#include <cpg_register.h>
#include <i2c.h>
#include <i2c_register.h>
#include <log.h>
#include <mem_io.h>
#include <pfc.h>
#include <pfc_register.h>
#include <micro_wait.h>
/* 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 <D_LENGTH_FUSA_CTRL_CVM; idx++){
write_data_buffer[0] = g_ary_cvm_vthsense[idx2];
write_data_buffer[1] = g_ary_cvm_vthsense[idx2+1];
dac8_value_tmp = g_ary_cvm_vthref[idx];
dac_i2c_tmp = R_IICA0_Master_Send(0x60 << 1, (uint8_t * )write_data_buffer , 2, 50); // Write to external DAC (ADC2)
delay_1ms(1);
idx2 += 2;
R_DAC0_Set_ConversionValue(dac8_value_tmp); // Write to internal DAC (ADC1)
g_ary_fusa_chk_cvm_status[idx] = r_pmic_i2c_read(D_PMIC_I2C_PROT_ADDRESS, 0x0D);
comms_rtn_code_tmp = r_pmic_i2c_write(D_PMIC_I2C_PROT_ADDRESS, 0x0D, 0x01); // Start next slot test
delay_1ms(2);
}
// Check to see if CVM passed
pmic_data_tmp = r_pmic_i2c_read(D_PMIC_I2C_PROT_ADDRESS, 0x0D);
while(pmic_data_tmp != 0x80 ){
pmic_data_tmp = r_pmic_i2c_read(D_PMIC_I2C_PROT_ADDRESS, 0x0D);
pmic_data_tmp &= 0x80;
}
R_DAC0_Set_ConversionValue(26U); // Set ADC1 value back to be within protection limits
write_data_buffer[0] = 0x03;
write_data_buffer[1] = 0xF0;
dac_i2c_tmp = R_IICA0_Master_Send(0x60 << 1, (uint8_t * )write_data_buffer , 2, 200); // Set ADC2 value back to be within protection limits
*/
uint32_t data, data2;
i2c5_write(PMIC_ADDR_P, FUSA_CHK_CVM1, CVM_TEST_START);
for(int i = 0; i < D_LENGTH_FUSA_CTRL_CVM; i++) {
micro_wait(2U);
i2c5_write(PMIC_ADDR_P, FUSA_CHK_CVM1, CVM_TEST_START);
}
do {
i2c5_read(PMIC_ADDR_P, FUSA_CHK_CVM1, &data);
} while ((data & CVM_TEST_DONE) == 0);
i2c5_read(PMIC_ADDR_P, FUSA_STATUS_CVM1, &data);
i2c5_read(PMIC_ADDR_P, FUSA_STATUS_CVM2, &data2);
NOTICE("CVM Test: 0x%x, 0x%x\n", data, data2);
}
#define FUSA_STATUS_1 (0x10)
#define SOC_ACTIVATED (1U << 4)
#define SCS_POWER_OFF (0x0 << 5)
#define SCS_SELF_DIAG (0x1 << 5)
#define SCS_POWER_UP (0x2 << 5)
#define SCS_SOC_ACTIV (0x3 << 5)
#define SCS_ACTIVE (0x4 << 5)
#define SCS_RESET (0x5 << 5)
#define SCS_ERROR (0x6 << 5)
#define SCS_LOCK (0x7 << 5)
#define SAS_IDLE (0x0)
#define SAS_EXT_PIN_CHK_1 (0x4)
#define SAS_SINT_CHK (0x5)
#define SAS_EXT_PIN_CHK_2 (0x6)
#define SAS_START_WDT (0x7)
void check_SoC_Activation(void) {
#if LOG_LEVEL >= 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) {}