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