1 /******************************************************************************
2 *  Filename:       i2c.c
3 *
4 *  Description:    Driver for the I2C module
5 *
6 *  Copyright (c) 2015 - 2022, Texas Instruments Incorporated
7 *  All rights reserved.
8 *
9 *  Redistribution and use in source and binary forms, with or without
10 *  modification, are permitted provided that the following conditions are met:
11 *
12 *  1) Redistributions of source code must retain the above copyright notice,
13 *     this list of conditions and the following disclaimer.
14 *
15 *  2) Redistributions in binary form must reproduce the above copyright notice,
16 *     this list of conditions and the following disclaimer in the documentation
17 *     and/or other materials provided with the distribution.
18 *
19 *  3) Neither the name of the ORGANIZATION nor the names of its contributors may
20 *     be used to endorse or promote products derived from this software without
21 *     specific prior written permission.
22 *
23 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 *  POSSIBILITY OF SUCH DAMAGE.
34 *
35 ******************************************************************************/
36 
37 #include "i2c.h"
38 
39 //*****************************************************************************
40 //
41 // Handle support for DriverLib in ROM:
42 // This section will undo prototype renaming made in the header file
43 //
44 //*****************************************************************************
45 #if !defined(DOXYGEN)
46     #undef  I2CMasterInitExpClk
47     #define I2CMasterInitExpClk             NOROM_I2CMasterInitExpClk
48     #undef  I2CMasterErr
49     #define I2CMasterErr                    NOROM_I2CMasterErr
50     #undef  I2CIntRegister
51     #define I2CIntRegister                  NOROM_I2CIntRegister
52     #undef  I2CIntUnregister
53     #define I2CIntUnregister                NOROM_I2CIntUnregister
54 #endif
55 
56 //*****************************************************************************
57 //
58 // Initializes the I2C Master block
59 //
60 //*****************************************************************************
61 void
I2CMasterInitExpClk(uint32_t ui32Base,uint32_t ui32I2CClk,bool bFast)62 I2CMasterInitExpClk(uint32_t ui32Base, uint32_t ui32I2CClk,
63                     bool bFast)
64 {
65     uint32_t ui32SCLFreq;
66     uint32_t ui32TPR;
67 
68     // Check the arguments.
69     ASSERT(I2CBaseValid(ui32Base));
70 
71     // Must enable the device before doing anything else.
72     I2CMasterEnable(ui32Base);
73 
74     // Get the desired SCL speed.
75     if(bFast == true)
76     {
77         ui32SCLFreq = 400000;
78     }
79     else
80     {
81         ui32SCLFreq = 100000;
82     }
83 
84     // Compute the clock divider that achieves the fastest speed less than or
85     // equal to the desired speed. The numerator is biased to favor a larger
86     // clock divider so that the resulting clock is always less than or equal
87     // to the desired clock, never greater.
88     ui32TPR = ((ui32I2CClk + (2 * 10 * ui32SCLFreq) - 1) / (2 * 10 * ui32SCLFreq)) - 1;
89     HWREG(ui32Base + I2C_O_MTPR) = ui32TPR;
90 }
91 
92 //*****************************************************************************
93 //
94 // Gets the error status of the I2C Master module
95 //
96 //*****************************************************************************
97 uint32_t
I2CMasterErr(uint32_t ui32Base)98 I2CMasterErr(uint32_t ui32Base)
99 {
100     uint32_t ui32Err;
101 
102     // Check the arguments.
103     ASSERT(I2CBaseValid(ui32Base));
104 
105     // Get the raw error state.
106     ui32Err = HWREG(ui32Base + I2C_O_MSTAT);
107 
108     // If the I2C master is busy, then all the other status bits are invalid,
109     // and there is no error to report.
110     if(ui32Err & I2C_MSTAT_BUSY)
111     {
112         return(I2C_MASTER_ERR_NONE);
113     }
114 
115     // Check for errors.
116     if(ui32Err & (I2C_MSTAT_ERR | I2C_MSTAT_ARBLST))
117     {
118         return(ui32Err & (I2C_MSTAT_ARBLST | I2C_MSTAT_DATACK_N | I2C_MSTAT_ADRACK_N));
119     }
120     else
121     {
122         return(I2C_MASTER_ERR_NONE);
123     }
124 }
125 
126 //*****************************************************************************
127 //
128 // Registers an interrupt handler for the I2C module
129 //
130 //*****************************************************************************
131 void
I2CIntRegister(uint32_t ui32Base,void (* pfnHandler)(void))132 I2CIntRegister(uint32_t ui32Base, void (*pfnHandler)(void))
133 {
134     uint32_t ui32Int;
135 
136     // Check the arguments.
137     ASSERT(I2CBaseValid(ui32Base));
138 
139     // Get the interrupt number.
140     ui32Int = INT_I2C_IRQ;
141 
142     // Register the interrupt handler.
143     IntRegister(ui32Int, pfnHandler);
144 
145     // Enable the I2C interrupt.
146     IntEnable(ui32Int);
147 }
148 
149 //*****************************************************************************
150 //
151 // Unregisters an interrupt handler for the I2C module
152 //
153 //*****************************************************************************
154 void
I2CIntUnregister(uint32_t ui32Base)155 I2CIntUnregister(uint32_t ui32Base)
156 {
157     uint32_t ui32Int;
158 
159     // Check the arguments.
160     ASSERT(I2CBaseValid(ui32Base));
161 
162     // Get the interrupt number.
163     ui32Int = INT_I2C_IRQ;
164 
165     // Disable the interrupt.
166     IntDisable(ui32Int);
167 
168     // Unregister the interrupt handler.
169     IntUnregister(ui32Int);
170 }
171