]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_R5_UltraScale_MPSoC/RTOSDemo_R5_bsp/psu_cortexr5_0/libsrc/iicps_v3_6/src/xiicps_options.c
Update Zynq, MPSoc Cortex-A53 and MPSoc Cortex-R5 demo projects to build with the...
[freertos] / FreeRTOS / Demo / CORTEX_R5_UltraScale_MPSoC / RTOSDemo_R5_bsp / psu_cortexr5_0 / libsrc / iicps_v3_6 / src / xiicps_options.c
1 /******************************************************************************
2 *
3 * Copyright (C) 2010 - 2016 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_5
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 * 3.3   kvn 05/05/16 Modified latest code for MISRA-C:2012 Compliance.
59 *
60 * </pre>
61 *
62 ******************************************************************************/
63
64 /***************************** Include Files *********************************/
65
66 #include "xiicps.h"
67
68 /************************** Constant Definitions *****************************/
69
70
71 /**************************** Type Definitions *******************************/
72
73
74 /***************** Macros (Inline Functions) Definitions *********************/
75
76
77 /************************** Function Prototypes ******************************/
78
79
80 /************************** Variable Definitions *****************************/
81 /*
82  * Create the table of options which are processed to get/set the device
83  * options. These options are table driven to allow easy maintenance and
84  * expansion of the options.
85  */
86 typedef struct {
87                 u32 Option;
88                 u32 Mask;
89 } OptionsMap;
90
91 static OptionsMap OptionsTable[] = {
92                 {XIICPS_7_BIT_ADDR_OPTION, XIICPS_CR_NEA_MASK},
93                 {XIICPS_10_BIT_ADDR_OPTION, XIICPS_CR_NEA_MASK},
94                 {XIICPS_SLAVE_MON_OPTION, XIICPS_CR_SLVMON_MASK},
95                 {XIICPS_REP_START_OPTION, XIICPS_CR_HOLD_MASK},
96 };
97
98 #define XIICPS_NUM_OPTIONS      (sizeof(OptionsTable) / sizeof(OptionsMap))
99
100 /*****************************************************************************/
101 /**
102 *
103 * This function sets the options for the IIC device driver. The options control
104 * how the device behaves relative to the IIC bus. The device must be idle
105 * rather than busy transferring data before setting these device options.
106 *
107 * @param        InstancePtr is a pointer to the XIicPs instance.
108 * @param        Options contains the specified options to be set. This is a bit
109 *               mask where a 1 means to turn the option on. One or more bit
110 *               values may be contained in the mask. See the bit definitions
111 *               named XIICPS_*_OPTION in xiicps.h.
112 *
113 * @return
114 *               - XST_SUCCESS if options are successfully set.
115 *               - XST_DEVICE_IS_STARTED if the device is currently transferring
116 *               data. The transfer must complete or be aborted before setting
117 *               options.
118 *
119 * @note         None.
120 *
121 ******************************************************************************/
122 s32 XIicPs_SetOptions(XIicPs *InstancePtr, u32 Options)
123 {
124         u32 ControlReg;
125         u32 Index;
126         u32 OptionsVar = Options;
127
128         Xil_AssertNonvoid(InstancePtr != NULL);
129         Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
130
131         ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
132                                       XIICPS_CR_OFFSET);
133
134         /*
135          * If repeated start option is requested, set the flag.
136          * The hold bit in CR will be written by driver when the next transfer
137          * is initiated.
138          */
139         if ((OptionsVar & (u32)XIICPS_REP_START_OPTION) != (u32)0 ) {
140                 InstancePtr->IsRepeatedStart = 1;
141                 OptionsVar = OptionsVar & (~XIICPS_REP_START_OPTION);
142         }
143
144         /*
145          * Loop through the options table, turning the option on.
146          */
147         for (Index = 0U; Index < XIICPS_NUM_OPTIONS; Index++) {
148                 if ((OptionsVar & OptionsTable[Index].Option) != (u32)0x0U) {
149                         /*
150                          * 10-bit option is specially treated, because it is
151                          * using the 7-bit option, so turning it on means
152                          * turning 7-bit option off.
153                          */
154                         if ((OptionsTable[Index].Option &
155                                 XIICPS_10_BIT_ADDR_OPTION) != (u32)0x0U) {
156                                 /* Turn 7-bit off */
157                                 ControlReg &= ~OptionsTable[Index].Mask;
158                         } else {
159                                 /* Turn 7-bit on */
160                                 ControlReg |= OptionsTable[Index].Mask;
161                         }
162                 }
163         }
164
165         /*
166          * Now write to the control register. Leave it to the upper layers
167          * to restart the device.
168          */
169         XIicPs_WriteReg(InstancePtr->Config.BaseAddress, XIICPS_CR_OFFSET,
170                           ControlReg);
171
172         /*
173          * Keep a copy of what options this instance has.
174          */
175         InstancePtr->Options = XIicPs_GetOptions(InstancePtr);
176
177         return (s32)XST_SUCCESS;
178 }
179
180 /*****************************************************************************/
181 /**
182 *
183 * This function clears the options for the IIC device driver. The options
184 * control how the device behaves relative to the IIC bus. The device must be
185 * idle rather than busy transferring data before setting these device options.
186 *
187 * @param        InstancePtr is a pointer to the XIicPs instance.
188 * @param        Options contains the specified options to be cleared. This is a
189 *               bit mask where a 1 means to turn the option off. One or more bit
190 *               values may be contained in the mask. See the bit definitions
191 *               named XIICPS_*_OPTION in xiicps.h.
192 *
193 * @return
194 *               - XST_SUCCESS if options are successfully set.
195 *               - XST_DEVICE_IS_STARTED if the device is currently transferring
196 *               data. The transfer must complete or be aborted before setting
197 *               options.
198 *
199 * @note         None
200 *
201 ******************************************************************************/
202 s32 XIicPs_ClearOptions(XIicPs *InstancePtr, u32 Options)
203 {
204         u32 ControlReg;
205         u32 Index;
206         u32 OptionsVar = Options;
207
208         Xil_AssertNonvoid(InstancePtr != NULL);
209         Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
210
211         ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
212                                         XIICPS_CR_OFFSET);
213
214         /*
215          * If repeated start option is cleared, set the flag.
216          * The hold bit in CR will be cleared by driver when the
217          * following transfer ends.
218          */
219         if ((OptionsVar & XIICPS_REP_START_OPTION) != (u32)0x0U ) {
220                 InstancePtr->IsRepeatedStart = 0;
221                 OptionsVar = OptionsVar & (~XIICPS_REP_START_OPTION);
222         }
223
224         /*
225          * Loop through the options table and clear the specified options.
226          */
227         for (Index = 0U; Index < XIICPS_NUM_OPTIONS; Index++) {
228                 if ((OptionsVar & OptionsTable[Index].Option) != (u32)0x0U) {
229
230                         /*
231                          * 10-bit option is specially treated, because it is
232                          * using the 7-bit option, so clearing it means turning
233                          * 7-bit option on.
234                          */
235                         if ((OptionsTable[Index].Option &
236                                 XIICPS_10_BIT_ADDR_OPTION) != (u32)0x0U) {
237
238                                 /* Turn 7-bit on */
239                                 ControlReg |= OptionsTable[Index].Mask;
240                         } else {
241
242                                 /* Turn 7-bit off */
243                                 ControlReg &= ~OptionsTable[Index].Mask;
244                         }
245                 }
246         }
247
248
249         /*
250          * Now write the control register. Leave it to the upper layers
251          * to restart the device.
252          */
253         XIicPs_WriteReg(InstancePtr->Config.BaseAddress, XIICPS_CR_OFFSET,
254                           ControlReg);
255
256         /*
257          * Keep a copy of what options this instance has.
258          */
259         InstancePtr->Options = XIicPs_GetOptions(InstancePtr);
260
261         return XST_SUCCESS;
262 }
263
264 /*****************************************************************************/
265 /**
266 *
267 * This function gets the options for the IIC device. The options control how
268 * the device behaves relative to the IIC bus.
269 *
270 * @param        InstancePtr is a pointer to the XIicPs instance.
271 *
272 * @return       32 bit mask of the options, where a 1 means the option is on,
273 *               and a 0 means to the option is off. One or more bit values may
274 *               be contained in the mask. See the bit definitions named
275 *               XIICPS_*_OPTION in the file xiicps.h.
276 *
277 * @note         None.
278 *
279 ******************************************************************************/
280 u32 XIicPs_GetOptions(XIicPs *InstancePtr)
281 {
282         u32 OptionsFlag = 0U;
283         u32 ControlReg;
284         u32 Index;
285
286         Xil_AssertNonvoid(InstancePtr != NULL);
287         Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
288
289         /*
290          * Read control register to find which options are currently set.
291          */
292         ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
293                                       XIICPS_CR_OFFSET);
294
295         /*
296          * Loop through the options table to determine which options are set.
297          */
298         for (Index = 0U; Index < XIICPS_NUM_OPTIONS; Index++) {
299                 if ((ControlReg & OptionsTable[Index].Mask) != (u32)0x0U) {
300                         OptionsFlag |= OptionsTable[Index].Option;
301                 }
302                 if ((ControlReg & XIICPS_CR_NEA_MASK) == (u32)0x0U) {
303                         OptionsFlag |= XIICPS_10_BIT_ADDR_OPTION;
304                 }
305         }
306
307         if (InstancePtr->IsRepeatedStart != 0 ) {
308                 OptionsFlag |= XIICPS_REP_START_OPTION;
309         }
310         return OptionsFlag;
311 }
312
313 /*****************************************************************************/
314 /**
315 *
316 * This function sets the serial clock rate for the IIC device. The device
317 * must be idle rather than busy transferring data before setting these device
318 * options.
319 *
320 * The data rate is set by values in the control register. The formula for
321 * determining the correct register values is:
322 * Fscl = Fpclk/(22 x (divisor_a+1) x (divisor_b+1))
323 * See the hardware data sheet for a full explanation of setting the serial
324 * clock rate.
325 *
326 * @param        InstancePtr is a pointer to the XIicPs instance.
327 * @param        FsclHz is the clock frequency in Hz. The two most common clock
328 *               rates are 100KHz and 400KHz.
329 *
330 * @return
331 *               - XST_SUCCESS if options are successfully set.
332 *               - XST_DEVICE_IS_STARTED if the device is currently transferring
333 *               data. The transfer must complete or be aborted before setting
334 *               options.
335 *               - XST_FAILURE if the Fscl frequency can not be set.
336 *
337 * @note         The clock can not be faster than the input clock divide by 22.
338 *
339 ******************************************************************************/
340 s32 XIicPs_SetSClk(XIicPs *InstancePtr, u32 FsclHz)
341 {
342         u32 Div_a;
343         u32 Div_b;
344         u32 ActualFscl;
345         u32 Temp;
346         u32 TempLimit;
347         u32 LastError;
348         u32 BestError;
349         u32 CurrentError;
350         u32 ControlReg;
351         u32 CalcDivA;
352         u32 CalcDivB;
353         u32 BestDivA;
354         u32 BestDivB;
355         u32 FsclHzVar = FsclHz;
356
357         Xil_AssertNonvoid(InstancePtr != NULL);
358         Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
359         Xil_AssertNonvoid(FsclHzVar > 0U);
360
361         if (0U != XIicPs_In32((InstancePtr->Config.BaseAddress) +
362                                         XIICPS_TRANS_SIZE_OFFSET)) {
363                 return (s32)XST_DEVICE_IS_STARTED;
364         }
365
366         /*
367          * Assume Div_a is 0 and calculate (divisor_a+1) x (divisor_b+1).
368          */
369         Temp = (InstancePtr->Config.InputClockHz) / ((u32)22U * FsclHzVar);
370
371         /*
372          * If the answer is negative or 0, the Fscl input is out of range.
373          */
374         if ((u32)(0U) == Temp) {
375                 return (s32)XST_FAILURE;
376         }
377
378         /*
379          * If frequency 400KHz is selected, 384.6KHz should be set.
380          * If frequency 100KHz is selected, 90KHz should be set.
381          * This is due to a hardware limitation.
382          */
383         if(FsclHzVar > (u32)384600U) {
384                 FsclHzVar = (u32)384600U;
385         }
386
387         if((FsclHzVar <= (u32)100000U) && (FsclHzVar > (u32)90000U)) {
388                 FsclHzVar = (u32)90000U;
389         }
390
391         /*
392          * TempLimit helps in iterating over the consecutive value of Temp to
393          * find the closest clock rate achievable with divisors.
394          * Iterate over the next value only if fractional part is involved.
395          */
396         TempLimit = (((InstancePtr->Config.InputClockHz) %
397                         ((u32)22 * FsclHzVar)) !=       (u32)0x0U) ?
398                                                 Temp + (u32)1U : Temp;
399         BestError = FsclHzVar;
400
401         BestDivA = 0U;
402         BestDivB = 0U;
403         for ( ; Temp <= TempLimit ; Temp++)
404         {
405                 LastError = FsclHzVar;
406                 CalcDivA = 0U;
407                 CalcDivB = 0U;
408
409                 for (Div_b = 0U; Div_b < 64U; Div_b++) {
410
411                         Div_a = Temp / (Div_b + 1U);
412
413                         if (Div_a != 0U){
414                                 Div_a = Div_a - (u32)1U;
415                         }
416                         if (Div_a > 3U){
417                                 continue;
418                         }
419                         ActualFscl = (InstancePtr->Config.InputClockHz) /
420                                                 (22U * (Div_a + 1U) * (Div_b + 1U));
421
422                         if (ActualFscl > FsclHzVar){
423                                 CurrentError = (ActualFscl - FsclHzVar);}
424                         else{
425                                 CurrentError = (FsclHzVar - ActualFscl);}
426
427                         if (LastError > CurrentError) {
428                                 CalcDivA = Div_a;
429                                 CalcDivB = Div_b;
430                                 LastError = CurrentError;
431                         }
432                 }
433
434                 /*
435                  * Used to capture the best divisors.
436                  */
437                 if (LastError < BestError) {
438                         BestError = LastError;
439                         BestDivA = CalcDivA;
440                         BestDivB = CalcDivB;
441                 }
442         }
443
444
445         /*
446          * Read the control register and mask the Divisors.
447          */
448         ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
449                                           (u32)XIICPS_CR_OFFSET);
450         ControlReg &= ~((u32)XIICPS_CR_DIV_A_MASK | (u32)XIICPS_CR_DIV_B_MASK);
451         ControlReg |= (BestDivA << XIICPS_CR_DIV_A_SHIFT) |
452                 (BestDivB << XIICPS_CR_DIV_B_SHIFT);
453
454         XIicPs_WriteReg(InstancePtr->Config.BaseAddress, (u32)XIICPS_CR_OFFSET,
455                           ControlReg);
456
457         return (s32)XST_SUCCESS;
458 }
459
460 /*****************************************************************************/
461 /**
462 *
463 * This function gets the serial clock rate for the IIC device. The device
464 * must be idle rather than busy transferring data before setting these device
465 * options.
466 *
467 * @param        InstancePtr is a pointer to the XIicPs instance.
468 *
469 * @return       The value of the IIC clock to the nearest Hz based on the
470 *               control register settings. The actual value may not be exact to
471 *               to integer math rounding errors.
472 *
473 * @note         None.
474 *
475 ******************************************************************************/
476 u32 XIicPs_GetSClk(XIicPs *InstancePtr)
477 {
478         u32 ControlReg;
479         u32 ActualFscl;
480         u32 Div_a;
481         u32 Div_b;
482
483         Xil_AssertNonvoid(InstancePtr != NULL);
484         Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
485
486         ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
487                                           XIICPS_CR_OFFSET);
488
489         Div_a = (ControlReg & XIICPS_CR_DIV_A_MASK) >> XIICPS_CR_DIV_A_SHIFT;
490         Div_b = (ControlReg & XIICPS_CR_DIV_B_MASK) >> XIICPS_CR_DIV_B_SHIFT;
491
492         ActualFscl = (InstancePtr->Config.InputClockHz) /
493                 (22U * (Div_a + 1U) * (Div_b + 1U));
494
495         return ActualFscl;
496 }
497 /** @} */