]> git.gir.st - tmk_keyboard.git/blob - tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/hal/i2c/fsl_i2c_hal.c
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[tmk_keyboard.git] / tool / mbed / mbed-sdk / libraries / mbed / targets / hal / TARGET_Freescale / TARGET_KPSDK_MCUS / TARGET_KPSDK_CODE / hal / i2c / fsl_i2c_hal.c
1 /*
2 * Copyright (c) 2013 - 2014, 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 "fsl_i2c_hal.h"
32 #include "fsl_misc_utilities.h" /* For ARRAY_SIZE*/
33
34 /*******************************************************************************
35 * Definitions
36 ******************************************************************************/
37
38 /*!
39 * @brief An entry in the I2C divider table.
40 *
41 * This struct pairs the value of the I2C_F.ICR bitfield with the resulting
42 * clock divider value.
43 */
44 typedef struct I2CDividerTableEntry {
45 uint8_t icr; /*!< F register ICR value.*/
46 uint16_t sclDivider; /*!< SCL clock divider.*/
47 } i2c_divider_table_entry_t;
48
49 /*******************************************************************************
50 * Variables
51 ******************************************************************************/
52
53 /*!
54 * @brief I2C divider values.
55 *
56 * This table is taken from the I2C Divider and Hold values section of the
57 * reference manual. In the original table there are, in some cases, multiple
58 * entries with the same divider but different hold values. This table
59 * includes only one entry for every divider, selecting the lowest hold value.
60 */
61 const i2c_divider_table_entry_t kI2CDividerTable[] = {
62 /* ICR Divider*/
63 { 0x00, 20 },
64 { 0x01, 22 },
65 { 0x02, 24 },
66 { 0x03, 26 },
67 { 0x04, 28 },
68 { 0x05, 30 },
69 { 0x09, 32 },
70 { 0x06, 34 },
71 { 0x0a, 36 },
72 { 0x07, 40 },
73 { 0x0c, 44 },
74 { 0x0d, 48 },
75 { 0x0e, 56 },
76 { 0x12, 64 },
77 { 0x0f, 68 },
78 { 0x13, 72 },
79 { 0x14, 80 },
80 { 0x15, 88 },
81 { 0x19, 96 },
82 { 0x16, 104 },
83 { 0x1a, 112 },
84 { 0x17, 128 },
85 { 0x1c, 144 },
86 { 0x1d, 160 },
87 { 0x1e, 192 },
88 { 0x22, 224 },
89 { 0x1f, 240 },
90 { 0x23, 256 },
91 { 0x24, 288 },
92 { 0x25, 320 },
93 { 0x26, 384 },
94 { 0x2a, 448 },
95 { 0x27, 480 },
96 { 0x2b, 512 },
97 { 0x2c, 576 },
98 { 0x2d, 640 },
99 { 0x2e, 768 },
100 { 0x32, 896 },
101 { 0x2f, 960 },
102 { 0x33, 1024 },
103 { 0x34, 1152 },
104 { 0x35, 1280 },
105 { 0x36, 1536 },
106 { 0x3a, 1792 },
107 { 0x37, 1920 },
108 { 0x3b, 2048 },
109 { 0x3c, 2304 },
110 { 0x3d, 2560 },
111 { 0x3e, 3072 },
112 { 0x3f, 3840 }
113 };
114
115 /*******************************************************************************
116 * Code
117 ******************************************************************************/
118 /*FUNCTION**********************************************************************
119 *
120 * Function Name : I2C_HAL_Init
121 * Description : Initialize I2C peripheral to reset state.
122 *
123 *END**************************************************************************/
124 void I2C_HAL_Init(uint32_t baseAddr)
125 {
126
127 HW_I2C_A1_WR(baseAddr, 0u);
128 HW_I2C_F_WR(baseAddr, 0u);
129 HW_I2C_C1_WR(baseAddr, 0u);
130 HW_I2C_S_WR(baseAddr, 0u);
131 HW_I2C_D_WR(baseAddr, 0u);
132 HW_I2C_C2_WR(baseAddr, 0u);
133 HW_I2C_FLT_WR(baseAddr, 0u);
134 HW_I2C_RA_WR(baseAddr, 0u);
135
136 #if FSL_FEATURE_I2C_HAS_SMBUS
137 HW_I2C_SMB_WR(baseAddr, 0u);
138 HW_I2C_A2_WR(baseAddr, 0xc2u);
139 HW_I2C_SLTH_WR(baseAddr, 0u);
140 HW_I2C_SLTL_WR(baseAddr, 0u);
141 #endif /* FSL_FEATURE_I2C_HAS_SMBUS*/
142 }
143
144 /*FUNCTION**********************************************************************
145 *
146 * Function Name : I2C_HAL_SetBaudRate
147 * Description : Sets the I2C bus frequency for master transactions.
148 *
149 *END**************************************************************************/
150 i2c_status_t I2C_HAL_SetBaudRate(uint32_t baseAddr, uint32_t sourceClockInHz, uint32_t kbps,
151 uint32_t * absoluteError_Hz)
152 {
153 uint32_t mult, i, multiplier;
154 uint32_t hz = kbps * 1000u;
155 uint32_t bestError = 0xffffffffu;
156 uint32_t bestMult = 0u;
157 uint32_t bestIcr = 0u;
158
159 /* Check if the requested frequency is greater than the max supported baud.*/
160 if ((kbps * 1000U) > (sourceClockInHz / (1U * 20U)))
161 {
162 return kStatus_I2C_OutOfRange;
163 }
164
165 /* Search for the settings with the lowest error.
166 * mult is the MULT field of the I2C_F register, and ranges from 0-2. It selects the
167 * multiplier factor for the divider. */
168 for (mult = 0u; (mult <= 2u) && (bestError != 0); ++mult)
169 {
170 multiplier = 1u << mult;
171
172 /* Scan table to find best match.*/
173 for (i = 0u; i < ARRAY_SIZE(kI2CDividerTable); ++i)
174 {
175 uint32_t computedRate = sourceClockInHz / (multiplier * kI2CDividerTable[i].sclDivider);
176 uint32_t absError = hz > computedRate ? hz - computedRate : computedRate - hz;
177
178 if (absError < bestError)
179 {
180 bestMult = mult;
181 bestIcr = kI2CDividerTable[i].icr;
182 bestError = absError;
183
184 /* If the error is 0, then we can stop searching
185 * because we won't find a better match.*/
186 if (absError == 0)
187 {
188 break;
189 }
190 }
191 }
192 }
193
194 /* Set the resulting error.*/
195 if (absoluteError_Hz)
196 {
197 *absoluteError_Hz = bestError;
198 }
199
200 /* Set frequency register based on best settings.*/
201 HW_I2C_F_WR(baseAddr, BF_I2C_F_MULT(bestMult) | BF_I2C_F_ICR(bestIcr));
202
203 return kStatus_I2C_Success;
204 }
205
206 /*FUNCTION**********************************************************************
207 *
208 * Function Name : I2C_HAL_SendStart
209 * Description : Send a START or Repeated START signal on the I2C bus.
210 * This function is used to initiate a new master mode transfer by sending the
211 * START signal. It is also used to send a Repeated START signal when a transfer
212 * is already in progress.
213 *
214 *END**************************************************************************/
215 void I2C_HAL_SendStart(uint32_t baseAddr)
216 {
217 /* Check if we're in a master mode transfer.*/
218 if (BR_I2C_C1_MST(baseAddr))
219 {
220 #if FSL_FEATURE_I2C_HAS_ERRATA_6070
221 /* Errata 6070: Repeat start cannot be generated if the I2Cx_F[MULT] field is set to a
222 * non- zero value.
223 * The workaround is to either always keep MULT set to 0, or to temporarily set it to
224 * 0 while performing the repeated start and then restore it.*/
225 uint32_t savedMult = 0;
226 if (BR_I2C_F_MULT(baseAddr) != 0)
227 {
228 savedMult = BR_I2C_F_MULT(baseAddr);
229 BW_I2C_F_MULT(baseAddr, 0U);
230 }
231 #endif /* FSL_FEATURE_I2C_HAS_ERRATA_6070*/
232
233 /* We are already in a transfer, so send a repeated start.*/
234 BW_I2C_C1_RSTA(baseAddr, 1U);
235
236 #if FSL_FEATURE_I2C_HAS_ERRATA_6070
237 if (savedMult)
238 {
239 BW_I2C_F_MULT(baseAddr, savedMult);
240 }
241 #endif /* FSL_FEATURE_I2C_HAS_ERRATA_6070*/
242 }
243 else
244 {
245 /* Initiate a transfer by sending the start signal.*/
246 HW_I2C_C1_SET(baseAddr, BM_I2C_C1_MST | BM_I2C_C1_TX);
247 }
248 }
249
250 /*FUNCTION**********************************************************************
251 *
252 * Function Name : I2C_HAL_SetAddress7bit
253 * Description : Sets the primary 7-bit slave address.
254 *
255 *END**************************************************************************/
256 void I2C_HAL_SetAddress7bit(uint32_t baseAddr, uint8_t address)
257 {
258 /* Set 7-bit slave address.*/
259 HW_I2C_A1_WR(baseAddr, address << 1U);
260
261 /* Disable the address extension option, selecting 7-bit mode.*/
262 BW_I2C_C2_ADEXT(baseAddr, 0U);
263 }
264
265 /*FUNCTION**********************************************************************
266 *
267 * Function Name : I2C_HAL_SetAddress10bit
268 * Description : Sets the primary slave address and enables 10-bit address mode.
269 *
270 *END**************************************************************************/
271 void I2C_HAL_SetAddress10bit(uint32_t baseAddr, uint16_t address)
272 {
273
274 uint8_t temp;
275
276 /* Set bottom 7 bits of slave address.*/
277 temp = address & 0x7FU;
278 HW_I2C_A1_WR(baseAddr, temp << 1U);
279
280 /* Enable 10-bit address extension.*/
281 BW_I2C_C2_ADEXT(baseAddr, 1U);
282
283 /* Set top 3 bits of slave address.*/
284 BW_I2C_C2_AD(baseAddr, (address & 0x0380U) >> 7U);
285 }
286
287 /*******************************************************************************
288 * EOF
289 ******************************************************************************/
290
291
Imprint / Impressum