]> git.sur5r.net Git - freertos/blob
5d7427a4814eec4e617ab953ec1625b54d7c281c
[freertos] /
1 /******************************************************************************
2 *
3 * Copyright (C) 2010 - 2015 Xilinx, Inc.  All rights reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 *
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
30 *
31 ******************************************************************************/
32 /*****************************************************************************/
33 /**
34 *
35 * @file xiicps_options.c
36 * @addtogroup iicps_v3_0
37 * @{
38 *
39 * Contains functions for the configuration of the XIccPs driver.
40 *
41 * <pre>
42 * MODIFICATION HISTORY:
43 *
44 * Ver   Who     Date     Changes
45 * ----- ------  -------- -----------------------------------------------
46 * 1.00a drg/jz  01/30/10 First release
47 * 1.02a sg      08/29/12 Updated the logic to arrive at the best divisors
48 *                        to achieve I2C clock with minimum error.
49 *                        This is a fix for CR #674195
50 * 1.03a hk  05/04/13 Initialized BestDivA and BestDivB to 0.
51 *                        This is fix for CR#704398 to remove warning.
52 * 2.0   hk  03/07/14 Limited frequency set when 100KHz or 400KHz is
53 *                    selected. This is a hardware limitation. CR#779290.
54 * 2.1   hk  04/24/14 Fix for CR# 761060 - provision for repeated start.
55 * 2.3   sk      10/07/14 Repeated start feature removed.
56 * 3.0   sk      12/06/14 Implemented Repeated start feature.
57 *                       01/31/15 Modified the code according to MISRAC 2012 Compliant.
58 *
59 * </pre>
60 *
61 ******************************************************************************/
62
63 /***************************** Include Files *********************************/
64
65 #include "xiicps.h"
66
67 /************************** Constant Definitions *****************************/
68
69
70 /**************************** Type Definitions *******************************/
71
72
73 /***************** Macros (Inline Functions) Definitions *********************/
74
75
76 /************************** Function Prototypes ******************************/
77
78
79 /************************** Variable Definitions *****************************/
80 /*
81  * Create the table of options which are processed to get/set the device
82  * options. These options are table driven to allow easy maintenance and
83  * expansion of the options.
84  */
85 typedef struct {
86                 u32 Option;
87                 u32 Mask;
88 } OptionsMap;
89
90 static OptionsMap OptionsTable[] = {
91                 {XIICPS_7_BIT_ADDR_OPTION, XIICPS_CR_NEA_MASK},
92                 {XIICPS_10_BIT_ADDR_OPTION, XIICPS_CR_NEA_MASK},
93                 {XIICPS_SLAVE_MON_OPTION, XIICPS_CR_SLVMON_MASK},
94                 {XIICPS_REP_START_OPTION, XIICPS_CR_HOLD_MASK},
95 };
96
97 #define XIICPS_NUM_OPTIONS      (sizeof(OptionsTable) / sizeof(OptionsMap))
98
99 /*****************************************************************************/
100 /**
101 *
102 * This function sets the options for the IIC device driver. The options control
103 * how the device behaves relative to the IIC bus. The device must be idle
104 * rather than busy transferring data before setting these device options.
105 *
106 * @param        InstancePtr is a pointer to the XIicPs instance.
107 * @param        Options contains the specified options to be set. This is a bit
108 *               mask where a 1 means to turn the option on. One or more bit
109 *               values may be contained in the mask. See the bit definitions
110 *               named XIICPS_*_OPTION in xiicps.h.
111 *
112 * @return
113 *               - XST_SUCCESS if options are successfully set.
114 *               - XST_DEVICE_IS_STARTED if the device is currently transferring
115 *               data. The transfer must complete or be aborted before setting
116 *               options.
117 *
118 * @note         None.
119 *
120 ******************************************************************************/
121 s32 XIicPs_SetOptions(XIicPs *InstancePtr, u32 Options)
122 {
123         u32 ControlReg;
124         u32 Index;
125         u32 OptionsVar = Options;
126
127         Xil_AssertNonvoid(InstancePtr != NULL);
128         Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
129
130         ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
131                                       XIICPS_CR_OFFSET);
132
133         /*
134          * If repeated start option is requested, set the flag.
135          * The hold bit in CR will be written by driver when the next transfer
136          * is initiated.
137          */
138         if ((OptionsVar & XIICPS_REP_START_OPTION) != 0U ) {
139                 InstancePtr->IsRepeatedStart = 1;
140                 OptionsVar = OptionsVar & (~XIICPS_REP_START_OPTION);
141         }
142
143         /*
144          * Loop through the options table, turning the option on.
145          */
146         for (Index = 0U; Index < XIICPS_NUM_OPTIONS; Index++) {
147                 if ((OptionsVar & OptionsTable[Index].Option) != (u32)0x0U) {
148                         /*
149                          * 10-bit option is specially treated, because it is
150                          * using the 7-bit option, so turning it on means
151                          * turning 7-bit option off.
152                          */
153                         if ((OptionsTable[Index].Option &
154                                 XIICPS_10_BIT_ADDR_OPTION) != (u32)0x0U) {
155                                 /* Turn 7-bit off */
156                                 ControlReg &= ~OptionsTable[Index].Mask;
157                         } else {
158                                 /* Turn 7-bit on */
159                                 ControlReg |= OptionsTable[Index].Mask;
160                         }
161                 }
162         }
163
164         /*
165          * Now write to the control register. Leave it to the upper layers
166          * to restart the device.
167          */
168         XIicPs_WriteReg(InstancePtr->Config.BaseAddress, XIICPS_CR_OFFSET,
169                           ControlReg);
170
171         /*
172          * Keep a copy of what options this instance has.
173          */
174         InstancePtr->Options = XIicPs_GetOptions(InstancePtr);
175
176         return (s32)XST_SUCCESS;
177 }
178
179 /*****************************************************************************/
180 /**
181 *
182 * This function clears the options for the IIC device driver. The options
183 * control how the device behaves relative to the IIC bus. The device must be
184 * idle rather than busy transferring data before setting these device options.
185 *
186 * @param        InstancePtr is a pointer to the XIicPs instance.
187 * @param        Options contains the specified options to be cleared. This is a
188 *               bit mask where a 1 means to turn the option off. One or more bit
189 *               values may be contained in the mask. See the bit definitions
190 *               named XIICPS_*_OPTION in xiicps.h.
191 *
192 * @return
193 *               - XST_SUCCESS if options are successfully set.
194 *               - XST_DEVICE_IS_STARTED if the device is currently transferring
195 *               data. The transfer must complete or be aborted before setting
196 *               options.
197 *
198 * @note         None
199 *
200 ******************************************************************************/
201 s32 XIicPs_ClearOptions(XIicPs *InstancePtr, u32 Options)
202 {
203         u32 ControlReg;
204         u32 Index;
205         u32 OptionsVar = Options;
206
207         Xil_AssertNonvoid(InstancePtr != NULL);
208         Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
209
210         ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
211                                         XIICPS_CR_OFFSET);
212
213         /*
214          * If repeated start option is cleared, set the flag.
215          * The hold bit in CR will be cleared by driver when the
216          * following transfer ends.
217          */
218         if ((OptionsVar & XIICPS_REP_START_OPTION) != (u32)0x0U ) {
219                 InstancePtr->IsRepeatedStart = 0;
220                 OptionsVar = OptionsVar & (~XIICPS_REP_START_OPTION);
221         }
222
223         /*
224          * Loop through the options table and clear the specified options.
225          */
226         for (Index = 0U; Index < XIICPS_NUM_OPTIONS; Index++) {
227                 if ((OptionsVar & OptionsTable[Index].Option) != (u32)0x0U) {
228
229                         /*
230                          * 10-bit option is specially treated, because it is
231                          * using the 7-bit option, so clearing it means turning
232                          * 7-bit option on.
233                          */
234                         if ((OptionsTable[Index].Option &
235                                 XIICPS_10_BIT_ADDR_OPTION) != (u32)0x0U) {
236
237                                 /* Turn 7-bit on */
238                                 ControlReg |= OptionsTable[Index].Mask;
239                         } else {
240
241                                 /* Turn 7-bit off */
242                                 ControlReg &= ~OptionsTable[Index].Mask;
243                         }
244                 }
245         }
246
247
248         /*
249          * Now write the control register. Leave it to the upper layers
250          * to restart the device.
251          */
252         XIicPs_WriteReg(InstancePtr->Config.BaseAddress, XIICPS_CR_OFFSET,
253                           ControlReg);
254
255         /*
256          * Keep a copy of what options this instance has.
257          */
258         InstancePtr->Options = XIicPs_GetOptions(InstancePtr);
259
260         return XST_SUCCESS;
261 }
262
263 /*****************************************************************************/
264 /**
265 *
266 * This function gets the options for the IIC device. The options control how
267 * the device behaves relative to the IIC bus.
268 *
269 * @param        InstancePtr is a pointer to the XIicPs instance.
270 *
271 * @return       32 bit mask of the options, where a 1 means the option is on,
272 *               and a 0 means to the option is off. One or more bit values may
273 *               be contained in the mask. See the bit definitions named
274 *               XIICPS_*_OPTION in the file xiicps.h.
275 *
276 * @note         None.
277 *
278 ******************************************************************************/
279 u32 XIicPs_GetOptions(XIicPs *InstancePtr)
280 {
281         u32 OptionsFlag = 0U;
282         u32 ControlReg;
283         u32 Index;
284
285         Xil_AssertNonvoid(InstancePtr != NULL);
286         Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
287
288         /*
289          * Read control register to find which options are currently set.
290          */
291         ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
292                                       XIICPS_CR_OFFSET);
293
294         /*
295          * Loop through the options table to determine which options are set.
296          */
297         for (Index = 0U; Index < XIICPS_NUM_OPTIONS; Index++) {
298                 if ((ControlReg & OptionsTable[Index].Mask) != (u32)0x0U) {
299                         OptionsFlag |= OptionsTable[Index].Option;
300                 }
301                 if ((ControlReg & XIICPS_CR_NEA_MASK) == (u32)0x0U) {
302                         OptionsFlag |= XIICPS_10_BIT_ADDR_OPTION;
303                 }
304         }
305
306         if (InstancePtr->IsRepeatedStart != 0 ) {
307                 OptionsFlag |= XIICPS_REP_START_OPTION;
308         }
309         return OptionsFlag;
310 }
311
312 /*****************************************************************************/
313 /**
314 *
315 * This function sets the serial clock rate for the IIC device. The device
316 * must be idle rather than busy transferring data before setting these device
317 * options.
318 *
319 * The data rate is set by values in the control register. The formula for
320 * determining the correct register values is:
321 * Fscl = Fpclk/(22 x (divisor_a+1) x (divisor_b+1))
322 * See the hardware data sheet for a full explanation of setting the serial
323 * clock rate.
324 *
325 * @param        InstancePtr is a pointer to the XIicPs instance.
326 * @param        FsclHz is the clock frequency in Hz. The two most common clock
327 *               rates are 100KHz and 400KHz.
328 *
329 * @return
330 *               - XST_SUCCESS if options are successfully set.
331 *               - XST_DEVICE_IS_STARTED if the device is currently transferring
332 *               data. The transfer must complete or be aborted before setting
333 *               options.
334 *               - XST_FAILURE if the Fscl frequency can not be set.
335 *
336 * @note         The clock can not be faster than the input clock divide by 22.
337 *
338 ******************************************************************************/
339 s32 XIicPs_SetSClk(XIicPs *InstancePtr, u32 FsclHz)
340 {
341         u32 Div_a;
342         u32 Div_b;
343         u32 ActualFscl;
344         u32 Temp;
345         u32 TempLimit;
346         u32 LastError;
347         u32 BestError;
348         u32 CurrentError;
349         u32 ControlReg;
350         u32 CalcDivA;
351         u32 CalcDivB;
352         u32 BestDivA = 0;
353         u32 BestDivB = 0;
354         u32 FsclHzVar = FsclHz;
355
356         Xil_AssertNonvoid(InstancePtr != NULL);
357         Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
358         Xil_AssertNonvoid(FsclHzVar > 0U);
359
360         if (0U != XIicPs_In32((InstancePtr->Config.BaseAddress) +
361                                         XIICPS_TRANS_SIZE_OFFSET)) {
362                 return (s32)XST_DEVICE_IS_STARTED;
363         }
364
365         /*
366          * Assume Div_a is 0 and calculate (divisor_a+1) x (divisor_b+1).
367          */
368         Temp = (InstancePtr->Config.InputClockHz) / ((u32)22U * FsclHzVar);
369
370         /*
371          * If the answer is negative or 0, the Fscl input is out of range.
372          */
373         if ((u32)(0U) == Temp) {
374                 return (s32)XST_FAILURE;
375         }
376
377         /*
378          * If frequency 400KHz is selected, 384.6KHz should be set.
379          * If frequency 100KHz is selected, 90KHz should be set.
380          * This is due to a hardware limitation.
381          */
382         if(FsclHzVar > 384600U) {
383                 FsclHzVar = 384600U;
384         }
385
386         if((FsclHzVar <= 100000U) && (FsclHzVar > 90000U)) {
387                 FsclHzVar = 90000U;
388         }
389
390         /*
391          * TempLimit helps in iterating over the consecutive value of Temp to
392          * find the closest clock rate achievable with divisors.
393          * Iterate over the next value only if fractional part is involved.
394          */
395         TempLimit = (((InstancePtr->Config.InputClockHz) %
396                         ((u32)22 * FsclHzVar)) !=       (u32)0x0U) ?
397                                                 Temp + (u32)1U : Temp;
398         BestError = FsclHzVar;
399
400         BestDivA = 0U;
401         BestDivB = 0U;
402         for ( ; Temp <= TempLimit ; Temp++)
403         {
404                 LastError = FsclHzVar;
405                 CalcDivA = 0U;
406                 CalcDivB = 0U;
407
408                 for (Div_b = 0U; Div_b < 64U; Div_b++) {
409
410                         Div_a = Temp / (Div_b + 1U);
411
412                         if (Div_a != 0U){
413                                 Div_a = Div_a - (u32)1U;
414                         }
415                         if (Div_a > 3U){
416                                 continue;
417                         }
418                         ActualFscl = (InstancePtr->Config.InputClockHz) /
419                                                 (22U * (Div_a + 1U) * (Div_b + 1U));
420
421                         if (ActualFscl > FsclHzVar){
422                                 CurrentError = (ActualFscl - FsclHzVar);}
423                         else{
424                                 CurrentError = (FsclHzVar - ActualFscl);}
425
426                         if (LastError > CurrentError) {
427                                 CalcDivA = Div_a;
428                                 CalcDivB = Div_b;
429                                 LastError = CurrentError;
430                         }
431                 }
432
433                 /*
434                  * Used to capture the best divisors.
435                  */
436                 if (LastError < BestError) {
437                         BestError = LastError;
438                         BestDivA = CalcDivA;
439                         BestDivB = CalcDivB;
440                 }
441         }
442
443
444         /*
445          * Read the control register and mask the Divisors.
446          */
447         ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
448                                           (u32)XIICPS_CR_OFFSET);
449         ControlReg &= ~((u32)XIICPS_CR_DIV_A_MASK | (u32)XIICPS_CR_DIV_B_MASK);
450         ControlReg |= (BestDivA << XIICPS_CR_DIV_A_SHIFT) |
451                 (BestDivB << XIICPS_CR_DIV_B_SHIFT);
452
453         XIicPs_WriteReg(InstancePtr->Config.BaseAddress, (u32)XIICPS_CR_OFFSET,
454                           ControlReg);
455
456         return (s32)XST_SUCCESS;
457 }
458
459 /*****************************************************************************/
460 /**
461 *
462 * This function gets the serial clock rate for the IIC device. The device
463 * must be idle rather than busy transferring data before setting these device
464 * options.
465 *
466 * @param        InstancePtr is a pointer to the XIicPs instance.
467 *
468 * @return       The value of the IIC clock to the nearest Hz based on the
469 *               control register settings. The actual value may not be exact to
470 *               to integer math rounding errors.
471 *
472 * @note         None.
473 *
474 ******************************************************************************/
475 u32 XIicPs_GetSClk(XIicPs *InstancePtr)
476 {
477         u32 ControlReg;
478         u32 ActualFscl;
479         u32 Div_a;
480         u32 Div_b;
481
482         Xil_AssertNonvoid(InstancePtr != NULL);
483         Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
484
485         ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
486                                           XIICPS_CR_OFFSET);
487
488         Div_a = (ControlReg & XIICPS_CR_DIV_A_MASK) >> XIICPS_CR_DIV_A_SHIFT;
489         Div_b = (ControlReg & XIICPS_CR_DIV_B_MASK) >> XIICPS_CR_DIV_B_SHIFT;
490
491         ActualFscl = (InstancePtr->Config.InputClockHz) /
492                 (22U * (Div_a + 1U) * (Div_b + 1U));
493
494         return ActualFscl;
495 }
496 /** @} */