409 lines
13 KiB
C
409 lines
13 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 i2c3_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>
|
|
|
|
/* Setting value for PFC */
|
|
#define IP0SR4_SDA3 (0xF0000000U) /* bit[31:28] */
|
|
#define IP0SR4_SCL3 (0x0F000000U) /* bit[27:24] */
|
|
#define GPSR4_SDA3 (0x00000080U) /* bit7 */
|
|
#define GPSR4_SCL3 (0x00000040U) /* bit6 */
|
|
#define MODSEL4_SDA3 (0x00000080U) /* bit7 */
|
|
#define MODSEL4_SCL3 (0x00000040U) /* bit6 */
|
|
#define PUEN4_SDA3 (0x00000080U) /* bit7 */
|
|
#define PUEN4_SCL3 (0x00000040U) /* bit6 */
|
|
|
|
static void i2c3_init_pin_function(void);
|
|
|
|
void i2c3_init(void)
|
|
{
|
|
/*
|
|
* Module Standby setting for I2C3 is not nessesary
|
|
* because H/W initial value is 'Enables supply of the clock signal'.
|
|
*/
|
|
|
|
/* PFC setting for I2C3. */
|
|
i2c3_init_pin_function();
|
|
|
|
/* CDFD=0, HLSE=0, SME=0 */
|
|
mem_write32((uintptr_t)I2C3_ICCCR2, 0x00000000U);
|
|
/* SCGD=H'3, CDF=H'6 */
|
|
mem_write32((uintptr_t)I2C3_ICCCR, (SET_SCGD | SET_CDF));
|
|
|
|
mem_write32((uintptr_t)I2C3_ICSCR, 0x00000000U);
|
|
mem_write32((uintptr_t)I2C3_ICSSR, 0x00000000U);
|
|
mem_write32((uintptr_t)I2C3_ICSIER, 0x00000000U);
|
|
mem_write32((uintptr_t)I2C3_ICSAR, 0x00000000U);
|
|
mem_write32((uintptr_t)I2C3_ICMCR, (FLAG_MDBS | FLAG_MIE));
|
|
mem_write32((uintptr_t)I2C3_ICMSR, 0x00000000U);
|
|
mem_write32((uintptr_t)I2C3_ICMIER, 0x00000000U);
|
|
mem_write32((uintptr_t)I2C3_ICMAR, 0x00000000U);
|
|
}
|
|
/* End of function i2c3_init(void) */
|
|
|
|
static void i2c3_init_pin_function(void)
|
|
{
|
|
uint32_t data;
|
|
|
|
/* SDA3, SCL3 -> 0 */
|
|
data = mem_read32((uintptr_t)PFC_IP0SR4_RW);
|
|
data &= ~(IP0SR4_SDA3 | IP0SR4_SCL3);
|
|
pfc_reg_write(PFC_IP0SR4_RW, data);
|
|
|
|
/* SDA3, SCL3 -> 1 */
|
|
data = mem_read32((uintptr_t)PFC_GPSR4_RW);
|
|
data |= (GPSR4_SDA3 | GPSR4_SCL3);
|
|
pfc_reg_write(PFC_GPSR4_RW, data);
|
|
|
|
/* Select SDA3 and SCL3 to I2C mode */
|
|
data = mem_read32((uintptr_t)PFC_MODSEL4_RW);
|
|
data |= (MODSEL4_SDA3 | MODSEL4_SCL3);
|
|
pfc_reg_write(PFC_MODSEL4_RW, data);
|
|
|
|
/* SDA3, SCL3 -> 0 */
|
|
data = mem_read32((uintptr_t)PFC_PUEN4_RW);
|
|
data &= ~(PUEN4_SDA3 | PUEN4_SCL3);
|
|
pfc_reg_write(PFC_PUEN4_RW, data);
|
|
}
|
|
/* End of function i2c3_init_pin_function(void) */
|
|
|
|
void i2c3_write(uint32_t slaveAdd, uint32_t regAdd, uint32_t setData)
|
|
{
|
|
uint32_t data;
|
|
uint32_t err_count = 0U;
|
|
uint32_t status;
|
|
|
|
while(true)
|
|
{
|
|
data = mem_read32((uintptr_t)I2C3_ICMCR);
|
|
data &= (FLAG_FSCL | FLAG_FSDA);
|
|
if(data == FLAG_FSCL)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
status = I2C_NG;
|
|
while(I2C_NG == status)
|
|
{
|
|
/* Set MDBS and MIE (initialize) */
|
|
mem_write32((uintptr_t)I2C3_ICMCR, (FLAG_MDBS | FLAG_MIE));
|
|
/* Set slave address */
|
|
slaveAdd &= ~FLG_RW; /* write mode */
|
|
mem_write32((uintptr_t)I2C3_ICMAR, slaveAdd);
|
|
/* Set register address */
|
|
mem_write32((uintptr_t)I2C3_ICTXD, regAdd);
|
|
|
|
while(true)
|
|
{
|
|
data = mem_read32((uintptr_t)I2C3_ICMCR);
|
|
data &= (FLAG_FSCL | FLAG_FSDA);
|
|
if(data == FLAG_FSCL)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Set MDBS, MIE and ESG */
|
|
mem_write32((uintptr_t)I2C3_ICMCR, (FLAG_MDBS | FLAG_MIE | FLAG_ESG)); /* start condition */
|
|
|
|
/* MDE(master data empty) & MAT(master address transmitted */
|
|
status = i2c3_err_check(FLAG_MDE, FLAG_MAT, (FLAG_MNR|FLAG_MAL));
|
|
if(I2C_NG == status)
|
|
{
|
|
err_count++;
|
|
if(err_count > ERR_MAX)
|
|
{
|
|
ERROR("1:I2C data write error\n");
|
|
panic;
|
|
}
|
|
}
|
|
}
|
|
|
|
mem_write32((uintptr_t)I2C3_ICMCR, (FLAG_MDBS | FLAG_MIE));
|
|
|
|
status = I2C_NG;
|
|
while(I2C_NG == status)
|
|
{
|
|
/* MDE and MAT clear */
|
|
data = mem_read32((uintptr_t)I2C3_ICMSR);
|
|
data &= (FLAG_MNR | FLAG_MAL | FLAG_MST | FLAG_MDT | FLAG_MDR);
|
|
mem_write32((uintptr_t)I2C3_ICMSR, data);
|
|
/* MDE(master data empty) & MDT(master data transmitted) */
|
|
status = i2c3_err_check(FLAG_MDE, FLAG_MDT, FLAG_MNR);
|
|
if(I2C_NG == status)
|
|
{
|
|
err_count++;
|
|
if(err_count > ERR_MAX)
|
|
{
|
|
ERROR("2:I2C data write error\n");
|
|
panic;
|
|
}
|
|
}
|
|
}
|
|
|
|
status = I2C_NG;
|
|
while(I2C_NG == status)
|
|
{
|
|
/* send voltage */
|
|
mem_write32((uintptr_t)I2C3_ICTXD, setData);
|
|
/* MDE and MAT clear */
|
|
data = mem_read32((uintptr_t)I2C3_ICMSR);
|
|
data &= (FLAG_MNR | FLAG_MAL | FLAG_MST | FLAG_MDR | FLAG_MAT);
|
|
mem_write32((uintptr_t)I2C3_ICMSR, data);
|
|
/* MDE(master data empty) & MDT(master data transmitted) */
|
|
status = i2c3_err_check(FLAG_MDE, FLAG_MDT, FLAG_MNR);
|
|
if(I2C_NG == status)
|
|
{
|
|
err_count++;
|
|
if(err_count > ERR_MAX)
|
|
{
|
|
ERROR("3:I2C data write error\n");
|
|
panic;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Set MDBS, MIE and FSB */
|
|
mem_write32((uintptr_t)I2C3_ICMCR, (FLAG_MDBS | FLAG_MIE | FLAG_FSB)); /* stop condition */
|
|
mem_write32((uintptr_t)I2C3_ICMSR, 0x00000000U); /* MST(master stop transmitted) clear */
|
|
|
|
while(true)
|
|
{
|
|
data = mem_read32((uintptr_t)I2C3_ICMSR);
|
|
if((data & FLAG_MST) != 0U) /* MST(master stop transmitted) */
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
mem_write32((uintptr_t)I2C3_ICMSR, 0x00000000U);
|
|
mem_write32((uintptr_t)I2C3_ICMCR, (FLAG_MDBS | FLAG_MIE));
|
|
|
|
}
|
|
/* End of function i2c3_write(uint32_t slaveAdd, uint32_t regAdd, uint32_t setData) */
|
|
|
|
void i2c3_read(uint32_t slaveAdd, uint32_t regAdd, uint32_t *revData)
|
|
{
|
|
uint32_t data;
|
|
uint32_t err_count = 0;
|
|
uint32_t status;
|
|
|
|
while(true)
|
|
{
|
|
data = mem_read32((uintptr_t)I2C3_ICMCR);
|
|
data &= (FLAG_FSCL | FLAG_FSDA);
|
|
if(data == FLAG_FSCL)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
status = I2C_NG;
|
|
while(I2C_NG == status)
|
|
{
|
|
/* Set MDBS and MIE (initialize) */
|
|
mem_write32((uintptr_t)I2C3_ICMCR, (FLAG_MDBS | FLAG_MIE));
|
|
/* Set slave address */
|
|
slaveAdd &= ~FLG_RW; /* write mode */
|
|
mem_write32((uintptr_t)I2C3_ICMAR, slaveAdd);
|
|
/* Set register address */
|
|
mem_write32((uintptr_t)I2C3_ICTXD, regAdd);
|
|
|
|
while(true)
|
|
{
|
|
data = mem_read32((uintptr_t)I2C3_ICMCR);
|
|
data &= (FLAG_FSCL | FLAG_FSDA);
|
|
if(data == FLAG_FSCL)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Set MDBS, MIE and ESG */
|
|
mem_write32((uintptr_t)I2C3_ICMCR, (FLAG_MDBS | FLAG_MIE | FLAG_ESG)); /* start condition */
|
|
|
|
/* MDE(master data empty) & MAT(master address transmitted */
|
|
status = i2c3_err_check(FLAG_MDE, FLAG_MAT, (FLAG_MNR|FLAG_MAL));
|
|
if(I2C_NG == status)
|
|
{
|
|
err_count++;
|
|
if(err_count > ERR_MAX)
|
|
{
|
|
ERROR("1:I2C data read error\n");
|
|
panic;
|
|
}
|
|
}
|
|
}
|
|
|
|
mem_write32((uintptr_t)I2C3_ICMCR, (FLAG_MDBS | FLAG_MIE));
|
|
|
|
status = I2C_NG;
|
|
while(I2C_NG == status)
|
|
{
|
|
/* MDE and MAT clear */
|
|
data = mem_read32((uintptr_t)I2C3_ICMSR);
|
|
data &= 0x000000F6U;
|
|
mem_write32((uintptr_t)I2C3_ICMSR, data);
|
|
/* MDE(master data empty) */
|
|
status = i2c3_err_check(FLAG_MDE, FLAG_NONE, FLAG_MNR);
|
|
if(I2C_NG == status)
|
|
{
|
|
err_count++;
|
|
if(err_count > ERR_MAX)
|
|
{
|
|
ERROR("2:I2C data read error\n");
|
|
panic;
|
|
}
|
|
}
|
|
}
|
|
|
|
status = I2C_NG;
|
|
while(I2C_NG == status)
|
|
{
|
|
/* Set slave address */
|
|
slaveAdd |= FLG_RW; /* read mode */
|
|
mem_write32((uintptr_t)I2C3_ICMAR, slaveAdd);
|
|
/* Set MDBS, MIE and ESG */
|
|
mem_write32((uintptr_t)I2C3_ICMCR, (FLAG_MDBS | FLAG_MIE | FLAG_ESG)); /* start condition */
|
|
mem_write32((uintptr_t)I2C3_ICMSR, 0x00000000U);
|
|
|
|
/* MDR(master data recieved) & MAT(master address transmitted) */
|
|
status = i2c3_err_check(FLAG_MDR, FLAG_MAT, (FLAG_MNR|FLAG_MAL));
|
|
if(I2C_NG == status)
|
|
{
|
|
err_count++;
|
|
if(err_count > ERR_MAX)
|
|
{
|
|
ERROR("3:I2C data read error\n");
|
|
panic;
|
|
}
|
|
}
|
|
}
|
|
|
|
status = I2C_NG;
|
|
while(I2C_NG == status)
|
|
{
|
|
/* Set MDBS, MIE and FSB */
|
|
mem_write32((uintptr_t)I2C3_ICMCR, (FLAG_MDBS | FLAG_MIE | FLAG_FSB)); /* stop condition */
|
|
/* MDE and MAT clear */
|
|
data = mem_read32((uintptr_t)I2C3_ICMSR);
|
|
data &= 0x000000FCU;
|
|
mem_write32((uintptr_t)I2C3_ICMSR, data);
|
|
status = i2c3_err_check(FLAG_MDR, FLAG_NONE, FLAG_MNR);
|
|
if(I2C_NG == status)
|
|
{
|
|
err_count++;
|
|
if(err_count > ERR_MAX)
|
|
{
|
|
ERROR("4:I2C data read error\n");
|
|
panic;
|
|
}
|
|
}
|
|
if(I2C_OK == status)
|
|
{
|
|
*revData = mem_read32((uintptr_t)I2C3_ICRXD) & 0x000000FFU;
|
|
}
|
|
mem_write32((uintptr_t)I2C3_ICMSR, 0x00000000U); /* MST(master stop transmitted) clear */
|
|
}
|
|
|
|
while(true)
|
|
{
|
|
data = mem_read32((uintptr_t)I2C3_ICMSR);
|
|
if((data & FLAG_MST) != 0U)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
mem_write32((uintptr_t)I2C3_ICMSR, 0x00000000U);
|
|
mem_write32((uintptr_t)I2C3_ICMCR, (FLAG_MDBS | FLAG_MIE));
|
|
}
|
|
/* End of function i2c3_read(uint32_t slaveAdd, uint32_t regAdd, uint32_t *revData) */
|
|
|
|
uint32_t i2c3_err_check(uint32_t first, uint32_t second, uint32_t error)
|
|
{
|
|
uint32_t data;
|
|
uint32_t status = I2C_OK;
|
|
|
|
while(true)
|
|
{
|
|
data = mem_read32((uintptr_t)I2C3_ICMSR);
|
|
if((data & first) != 0U)
|
|
{
|
|
if((second == FLAG_NONE) || ((data & second) != 0U))
|
|
{
|
|
status = I2C_OK;
|
|
break;
|
|
}
|
|
}
|
|
if((data & error) != 0U)
|
|
{
|
|
mem_write32((uintptr_t)I2C3_ICMSR, ~error);
|
|
status = I2C_NG;
|
|
break;
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
/* End of function i2c3_err_check(uint32_t first, uint32_t second, uint32_t error) */
|
|
|
|
void i2c3_release(void)
|
|
{
|
|
mem_write32((uintptr_t)I2C3_ICCCR2, 0x00000000U);
|
|
mem_write32((uintptr_t)I2C3_ICCCR, 0x00000000U);
|
|
mem_write32((uintptr_t)I2C3_ICSCR, 0x00000000U);
|
|
mem_write32((uintptr_t)I2C3_ICSSR, 0x00000000U);
|
|
mem_write32((uintptr_t)I2C3_ICSIER, 0x00000000U);
|
|
mem_write32((uintptr_t)I2C3_ICSAR, 0x00000000U);
|
|
mem_write32((uintptr_t)I2C3_ICMCR, 0x00000000U);
|
|
mem_write32((uintptr_t)I2C3_ICMSR, 0x00000000U);
|
|
mem_write32((uintptr_t)I2C3_ICMIER, 0x00000000U);
|
|
mem_write32((uintptr_t)I2C3_ICMAR, 0x00000000U);
|
|
}
|
|
/* End of function i2c3_release(void) */
|