1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * o Redistributions of source code must retain the above copyright notice, this list
9  *   of conditions and the following disclaimer.
10  *
11  * o Redistributions in binary form must reproduce the above copyright notice, this
12  *   list of conditions and the following disclaimer in the documentation and/or
13  *   other materials provided with the distribution.
14  *
15  * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
16  *   contributors may be used to endorse or promote products derived from this
17  *   software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "i2c_imx.h"
32 
33 /*******************************************************************************
34  * Constant
35  ******************************************************************************/
36 static const uint32_t i2cClkDivTab[][2] =
37 {
38     {22, 0x20},   {24, 0x21},   {26, 0x22},   {28, 0x23},   {30, 0x00},   {32, 0x24},   {36, 0x25},   {40, 0x26},
39     {42, 0x03},   {44, 0x27},   {48, 0x28},   {52, 0x05},   {56, 0x29},   {60, 0x06},   {64, 0x2A},   {72, 0x2B},
40     {80, 0x2C},   {88, 0x09},   {96, 0x2D},   {104, 0x0A},  {112, 0x2E},  {128, 0x2F},  {144, 0x0C},  {160, 0x30},
41     {192, 0x31},  {224, 0x32},  {240, 0x0F},  {256, 0x33},  {288, 0x10},  {320, 0x34},  {384, 0x35},  {448, 0x36},
42     {480, 0x13},  {512, 0x37},  {576, 0x14},  {640, 0x38},  {768, 0x39},  {896, 0x3A},  {960, 0x17},  {1024, 0x3B},
43     {1152, 0x18}, {1280, 0x3C}, {1536, 0x3D}, {1792, 0x3E}, {1920, 0x1B}, {2048, 0x3F}, {2304, 0x1C}, {2560, 0x1D},
44     {3072, 0x1E}, {3840, 0x1F}
45 };
46 
47 /*******************************************************************************
48  * Code
49  ******************************************************************************/
50 
51 /*******************************************************************************
52  * I2C Initialization and Configuration functions
53  ******************************************************************************/
54 /*FUNCTION**********************************************************************
55  *
56  * Function Name : I2C_Init
57  * Description   : Initialize I2C module with given initialize structure.
58  *
59  *END**************************************************************************/
I2C_Init(I2C_Type * base,const i2c_init_config_t * initConfig)60 void I2C_Init(I2C_Type* base, const i2c_init_config_t* initConfig)
61 {
62     assert(initConfig);
63 
64     /* Disable I2C Module. */
65     I2C_I2CR_REG(base) &= ~I2C_I2CR_IEN_MASK;
66 
67     /* Reset I2C register to its default value. */
68     I2C_Deinit(base);
69 
70     /* Set I2C Module own Slave Address. */
71     I2C_SetSlaveAddress(base, initConfig->slaveAddress);
72 
73     /* Set I2C BaudRate according to i2c initialize struct. */
74     I2C_SetBaudRate(base, initConfig->clockRate, initConfig->baudRate);
75 }
76 
77 /*FUNCTION**********************************************************************
78  *
79  * Function Name : I2C_Deinit
80  * Description   : This function reset I2C module register content to
81  *                 its default value.
82  *
83  *END**************************************************************************/
I2C_Deinit(I2C_Type * base)84 void I2C_Deinit(I2C_Type* base)
85 {
86     /* Disable I2C Module */
87     I2C_I2CR_REG(base) &= ~I2C_I2CR_IEN_MASK;
88 
89     /* Reset I2C Module Register content to default value */
90     I2C_IADR_REG(base) = 0x0;
91     I2C_IFDR_REG(base) = 0x0;
92     I2C_I2CR_REG(base) = 0x0;
93 }
94 
95 /*FUNCTION**********************************************************************
96  *
97  * Function Name : I2C_SetBaudRate
98  * Description   : This function is used to set the baud rate of I2C Module.
99  *
100  *END**************************************************************************/
I2C_SetBaudRate(I2C_Type * base,uint32_t clockRate,uint32_t baudRate)101 void I2C_SetBaudRate(I2C_Type* base, uint32_t clockRate, uint32_t baudRate)
102 {
103     uint32_t clockDiv;
104     uint8_t clkDivIndex = 0;
105 
106     assert(baudRate <= 400000);
107 
108     /* Calculate accurate baudRate divider. */
109     clockDiv = clockRate / baudRate;
110 
111     if (clockDiv < i2cClkDivTab[0][0])
112     {
113         /* If clock divider is too small, using smallest legal divider */
114         clkDivIndex = 0;
115     }
116     else if (clockDiv > i2cClkDivTab[sizeof(i2cClkDivTab)/sizeof(i2cClkDivTab[0]) - 1][0])
117     {
118         /* If clock divider is too large, using largest legal divider */
119         clkDivIndex = sizeof(i2cClkDivTab)/sizeof(i2cClkDivTab[0]) - 1;
120     }
121     else
122     {
123         while (i2cClkDivTab[clkDivIndex][0] < clockDiv)
124             clkDivIndex++;
125     }
126 
127     I2C_IFDR_REG(base) = i2cClkDivTab[clkDivIndex][1];
128 }
129 
130 /*******************************************************************************
131  * I2C Bus Control functions
132  ******************************************************************************/
133 /*FUNCTION**********************************************************************
134  *
135  * Function Name : I2C_SetAckBit
136  * Description   : This function is used to set the Transmit Acknowledge
137  *                 action when receive data from other device.
138  *
139  *END**************************************************************************/
I2C_SetAckBit(I2C_Type * base,bool ack)140 void I2C_SetAckBit(I2C_Type* base, bool ack)
141 {
142     if (ack)
143         I2C_I2CR_REG(base) &= ~I2C_I2CR_TXAK_MASK;
144     else
145         I2C_I2CR_REG(base) |= I2C_I2CR_TXAK_MASK;
146 }
147 
148 /*******************************************************************************
149  * Interrupts and flags management functions
150  ******************************************************************************/
151 /*FUNCTION**********************************************************************
152  *
153  * Function Name : I2C_SetIntCmd
154  * Description   : Enables or disables I2C interrupt requests.
155  *
156  *END**************************************************************************/
I2C_SetIntCmd(I2C_Type * base,bool enable)157 void I2C_SetIntCmd(I2C_Type* base, bool enable)
158 {
159     if (enable)
160         I2C_I2CR_REG(base) |= I2C_I2CR_IIEN_MASK;
161     else
162         I2C_I2CR_REG(base) &= ~I2C_I2CR_IIEN_MASK;
163 }
164 
165 /*******************************************************************************
166  * EOF
167  ******************************************************************************/
168