zephyr/ext/hal/nxp/imx/drivers/i2c_imx.c

168 lines
6.7 KiB
C

/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "i2c_imx.h"
/*******************************************************************************
* Constant
******************************************************************************/
static const uint32_t i2cClkDivTab[][2] =
{
{22, 0x20}, {24, 0x21}, {26, 0x22}, {28, 0x23}, {30, 0x00}, {32, 0x24}, {36, 0x25}, {40, 0x26},
{42, 0x03}, {44, 0x27}, {48, 0x28}, {52, 0x05}, {56, 0x29}, {60, 0x06}, {64, 0x2A}, {72, 0x2B},
{80, 0x2C}, {88, 0x09}, {96, 0x2D}, {104, 0x0A}, {112, 0x2E}, {128, 0x2F}, {144, 0x0C}, {160, 0x30},
{192, 0x31}, {224, 0x32}, {240, 0x0F}, {256, 0x33}, {288, 0x10}, {320, 0x34}, {384, 0x35}, {448, 0x36},
{480, 0x13}, {512, 0x37}, {576, 0x14}, {640, 0x38}, {768, 0x39}, {896, 0x3A}, {960, 0x17}, {1024, 0x3B},
{1152, 0x18}, {1280, 0x3C}, {1536, 0x3D}, {1792, 0x3E}, {1920, 0x1B}, {2048, 0x3F}, {2304, 0x1C}, {2560, 0x1D},
{3072, 0x1E}, {3840, 0x1F}
};
/*******************************************************************************
* Code
******************************************************************************/
/*******************************************************************************
* I2C Initialization and Configuration functions
******************************************************************************/
/*FUNCTION**********************************************************************
*
* Function Name : I2C_Init
* Description : Initialize I2C module with given initialize structure.
*
*END**************************************************************************/
void I2C_Init(I2C_Type* base, const i2c_init_config_t* initConfig)
{
assert(initConfig);
/* Disable I2C Module. */
I2C_I2CR_REG(base) &= ~I2C_I2CR_IEN_MASK;
/* Reset I2C register to its default value. */
I2C_Deinit(base);
/* Set I2C Module own Slave Address. */
I2C_SetSlaveAddress(base, initConfig->slaveAddress);
/* Set I2C BaudRate according to i2c initialize struct. */
I2C_SetBaudRate(base, initConfig->clockRate, initConfig->baudRate);
}
/*FUNCTION**********************************************************************
*
* Function Name : I2C_Deinit
* Description : This function reset I2C module register content to
* its default value.
*
*END**************************************************************************/
void I2C_Deinit(I2C_Type* base)
{
/* Disable I2C Module */
I2C_I2CR_REG(base) &= ~I2C_I2CR_IEN_MASK;
/* Reset I2C Module Register content to default value */
I2C_IADR_REG(base) = 0x0;
I2C_IFDR_REG(base) = 0x0;
I2C_I2CR_REG(base) = 0x0;
}
/*FUNCTION**********************************************************************
*
* Function Name : I2C_SetBaudRate
* Description : This function is used to set the baud rate of I2C Module.
*
*END**************************************************************************/
void I2C_SetBaudRate(I2C_Type* base, uint32_t clockRate, uint32_t baudRate)
{
uint32_t clockDiv;
uint8_t clkDivIndex = 0;
assert(baudRate <= 400000);
/* Calculate accurate baudRate divider. */
clockDiv = clockRate / baudRate;
if (clockDiv < i2cClkDivTab[0][0])
{
/* If clock divider is too small, using smallest legal divider */
clkDivIndex = 0;
}
else if (clockDiv > i2cClkDivTab[sizeof(i2cClkDivTab)/sizeof(i2cClkDivTab[0]) - 1][0])
{
/* If clock divider is too large, using largest legal divider */
clkDivIndex = sizeof(i2cClkDivTab)/sizeof(i2cClkDivTab[0]) - 1;
}
else
{
while (i2cClkDivTab[clkDivIndex][0] < clockDiv)
clkDivIndex++;
}
I2C_IFDR_REG(base) = i2cClkDivTab[clkDivIndex][1];
}
/*******************************************************************************
* I2C Bus Control functions
******************************************************************************/
/*FUNCTION**********************************************************************
*
* Function Name : I2C_SetAckBit
* Description : This function is used to set the Transmit Acknowledge
* action when receive data from other device.
*
*END**************************************************************************/
void I2C_SetAckBit(I2C_Type* base, bool ack)
{
if (ack)
I2C_I2CR_REG(base) &= ~I2C_I2CR_TXAK_MASK;
else
I2C_I2CR_REG(base) |= I2C_I2CR_TXAK_MASK;
}
/*******************************************************************************
* Interrupts and flags management functions
******************************************************************************/
/*FUNCTION**********************************************************************
*
* Function Name : I2C_SetIntCmd
* Description : Enables or disables I2C interrupt requests.
*
*END**************************************************************************/
void I2C_SetIntCmd(I2C_Type* base, bool enable)
{
if (enable)
I2C_I2CR_REG(base) |= I2C_I2CR_IIEN_MASK;
else
I2C_I2CR_REG(base) &= ~I2C_I2CR_IIEN_MASK;
}
/*******************************************************************************
* EOF
******************************************************************************/