]> git.sur5r.net Git - freertos/blob
0a3bed959003f64c2e3c0b10eafe6209b5189589
[freertos] /
1 /******************************************************************************
2 *
3 * (c) Copyright 2010-14 Xilinx, Inc. All rights reserved.
4 *
5 * This file contains confidential and proprietary information of Xilinx, Inc.
6 * and is protected under U.S. and international copyright and other
7 * intellectual property laws.
8 *
9 * DISCLAIMER
10 * This disclaimer is not a license and does not grant any rights to the
11 * materials distributed herewith. Except as otherwise provided in a valid
12 * license issued to you by Xilinx, and to the maximum extent permitted by
13 * applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL
14 * FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS,
15 * IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
16 * MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE;
17 * and (2) Xilinx shall not be liable (whether in contract or tort, including
18 * negligence, or under any other theory of liability) for any loss or damage
19 * of any kind or nature related to, arising under or in connection with these
20 * materials, including for any direct, or any indirect, special, incidental,
21 * or consequential loss or damage (including loss of data, profits, goodwill,
22 * or any type of loss or damage suffered as a result of any action brought by
23 * a third party) even if such damage or loss was reasonably foreseeable or
24 * Xilinx had been advised of the possibility of the same.
25 *
26 * CRITICAL APPLICATIONS
27 * Xilinx products are not designed or intended to be fail-safe, or for use in
28 * any application requiring fail-safe performance, such as life-support or
29 * safety devices or systems, Class III medical devices, nuclear facilities,
30 * applications related to the deployment of airbags, or any other applications
31 * that could lead to death, personal injury, or severe property or
32 * environmental damage (individually and collectively, "Critical
33 * Applications"). Customer assumes the sole risk and liability of any use of
34 * Xilinx products in Critical Applications, subject only to applicable laws
35 * and regulations governing limitations on product liability.
36 *
37 * THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE
38 * AT ALL TIMES.
39 *
40 ******************************************************************************/
41 /*****************************************************************************/
42 /**
43 *
44 * @file xiicps_options.c
45 *
46 * Contains functions for the configuration of the XIccPs driver.
47 *
48 * <pre>
49 * MODIFICATION HISTORY:
50 *
51 * Ver   Who     Date     Changes
52 * ----- ------  -------- -----------------------------------------------
53 * 1.00a drg/jz  01/30/10 First release
54 * 1.02a sg      08/29/12 Updated the logic to arrive at the best divisors
55 *                        to achieve I2C clock with minimum error.
56 *                        This is a fix for CR #674195
57 * 1.03a hk  05/04/13 Initialized BestDivA and BestDivB to 0.
58 *                        This is fix for CR#704398 to remove warning.
59 * 2.0   hk  03/07/14 Limited frequency set when 100KHz or 400KHz is
60 *                    selected. This is a hardware limitation. CR#779290.
61 * 2.1   hk  04/24/14 Fix for CR# 761060 - provision for repeated start.
62 *
63 * </pre>
64 *
65 ******************************************************************************/
66
67 /***************************** Include Files *********************************/
68
69 #include "xiicps.h"
70
71 /************************** Constant Definitions *****************************/
72
73
74 /**************************** Type Definitions *******************************/
75
76
77 /***************** Macros (Inline Functions) Definitions *********************/
78
79
80 /************************** Function Prototypes ******************************/
81
82
83 /************************** Variable Definitions *****************************/
84 /*
85  * Create the table of options which are processed to get/set the device
86  * options. These options are table driven to allow easy maintenance and
87  * expansion of the options.
88  */
89 typedef struct {
90                 u32 Option;
91                 u32 Mask;
92 } OptionsMap;
93
94 static OptionsMap OptionsTable[] = {
95                 {XIICPS_7_BIT_ADDR_OPTION, XIICPS_CR_NEA_MASK},
96                 {XIICPS_10_BIT_ADDR_OPTION, XIICPS_CR_NEA_MASK},
97                 {XIICPS_SLAVE_MON_OPTION, XIICPS_CR_SLVMON_MASK},
98                 {XIICPS_REP_START_OPTION, XIICPS_CR_HOLD_MASK},
99 };
100
101 #define XIICPS_NUM_OPTIONS      (sizeof(OptionsTable) / sizeof(OptionsMap))
102
103 /*****************************************************************************/
104 /**
105 *
106 * This function sets the options for the IIC device driver. The options control
107 * how the device behaves relative to the IIC bus. The device must be idle
108 * rather than busy transferring data before setting these device options.
109 *
110 * @param        InstancePtr is a pointer to the XIicPs instance.
111 * @param        Options contains the specified options to be set. This is a bit
112 *               mask where a 1 means to turn the option on. One or more bit
113 *               values may be contained in the mask. See the bit definitions
114 *               named XIICPS_*_OPTION in xiicps.h.
115 *
116 * @return
117 *               - XST_SUCCESS if options are successfully set.
118 *               - XST_DEVICE_IS_STARTED if the device is currently transferring
119 *               data. The transfer must complete or be aborted before setting
120 *               options.
121 *
122 * @note         None.
123 *
124 ******************************************************************************/
125 int XIicPs_SetOptions(XIicPs *InstancePtr, u32 Options)
126 {
127         u32 ControlReg;
128         unsigned int Index;
129
130         Xil_AssertNonvoid(InstancePtr != NULL);
131         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
132
133         ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
134                                       XIICPS_CR_OFFSET);
135
136         /*
137          * If repeated start option is requested, set the flag.
138          * The hold bit in CR will be written by driver when the next transfer
139          * is initiated.
140          */
141         if (Options & XIICPS_REP_START_OPTION) {
142                 InstancePtr->IsRepeatedStart = 1;
143                 Options = Options & (~XIICPS_REP_START_OPTION);
144         }
145
146         /*
147          * Loop through the options table, turning the option on.
148          */
149         for (Index = 0; Index < XIICPS_NUM_OPTIONS; Index++) {
150                 if (Options & OptionsTable[Index].Option) {
151                         /*
152                          * 10-bit option is specially treated, because it is
153                          * using the 7-bit option, so turning it on means
154                          * turning 7-bit option off.
155                          */
156                         if (OptionsTable[Index].Option &
157                                 XIICPS_10_BIT_ADDR_OPTION) {
158                                 /* Turn 7-bit off */
159                                 ControlReg &= ~OptionsTable[Index].Mask;
160                         } else {
161                                 /* Turn 7-bit on */
162                                 ControlReg |= OptionsTable[Index].Mask;
163                         }
164                 }
165         }
166
167         /*
168          * Now write to the control register. Leave it to the upper layers
169          * to restart the device.
170          */
171         XIicPs_WriteReg(InstancePtr->Config.BaseAddress, XIICPS_CR_OFFSET,
172                           ControlReg);
173
174         /*
175          * Keep a copy of what options this instance has.
176          */
177         InstancePtr->Options = XIicPs_GetOptions(InstancePtr);
178
179         return XST_SUCCESS;
180 }
181
182 /*****************************************************************************/
183 /**
184 *
185 * This function clears the options for the IIC device driver. The options
186 * control how the device behaves relative to the IIC bus. The device must be
187 * idle rather than busy transferring data before setting these device options.
188 *
189 * @param        InstancePtr is a pointer to the XIicPs instance.
190 * @param        Options contains the specified options to be cleared. This is a
191 *               bit mask where a 1 means to turn the option off. One or more bit
192 *               values may be contained in the mask. See the bit definitions
193 *               named XIICPS_*_OPTION in xiicps.h.
194 *
195 * @return
196 *               - XST_SUCCESS if options are successfully set.
197 *               - XST_DEVICE_IS_STARTED if the device is currently transferring
198 *               data. The transfer must complete or be aborted before setting
199 *               options.
200 *
201 * @note         None
202 *
203 ******************************************************************************/
204 int XIicPs_ClearOptions(XIicPs *InstancePtr, u32 Options)
205 {
206         u32 ControlReg;
207         unsigned int Index;
208
209         Xil_AssertNonvoid(InstancePtr != NULL);
210         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
211
212         ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
213                                         XIICPS_CR_OFFSET);
214
215         /*
216          * If repeated start option is cleared, set the flag.
217          * The hold bit in CR will be cleared by driver when the
218          * following transfer ends.
219          */
220         if (Options & XIICPS_REP_START_OPTION) {
221                 InstancePtr->IsRepeatedStart = 0;
222                 Options = Options & (~XIICPS_REP_START_OPTION);
223         }
224
225         /*
226          * Loop through the options table and clear the specified options.
227          */
228         for (Index = 0; Index < XIICPS_NUM_OPTIONS; Index++) {
229                 if (Options & OptionsTable[Index].Option) {
230
231                         /*
232                          * 10-bit option is specially treated, because it is
233                          * using the 7-bit option, so clearing it means turning
234                          * 7-bit option on.
235                          */
236                         if (OptionsTable[Index].Option &
237                                                 XIICPS_10_BIT_ADDR_OPTION) {
238
239                                 /* Turn 7-bit on */
240                                 ControlReg |= OptionsTable[Index].Mask;
241                         } else {
242
243                                 /* Turn 7-bit off */
244                                 ControlReg &= ~OptionsTable[Index].Mask;
245                         }
246                 }
247         }
248
249
250         /*
251          * Now write the control register. Leave it to the upper layers
252          * to restart the device.
253          */
254         XIicPs_WriteReg(InstancePtr->Config.BaseAddress, XIICPS_CR_OFFSET,
255                           ControlReg);
256
257         /*
258          * Keep a copy of what options this instance has.
259          */
260         InstancePtr->Options = XIicPs_GetOptions(InstancePtr);
261
262         return XST_SUCCESS;
263 }
264
265 /*****************************************************************************/
266 /**
267 *
268 * This function gets the options for the IIC device. The options control how
269 * the device behaves relative to the IIC bus.
270 *
271 * @param        InstancePtr is a pointer to the XIicPs instance.
272 *
273 * @return       32 bit mask of the options, where a 1 means the option is on,
274 *               and a 0 means to the option is off. One or more bit values may
275 *               be contained in the mask. See the bit definitions named
276 *               XIICPS_*_OPTION in the file xiicps.h.
277 *
278 * @note         None.
279 *
280 ******************************************************************************/
281 u32 XIicPs_GetOptions(XIicPs *InstancePtr)
282 {
283         u32 OptionsFlag = 0;
284         u32 ControlReg;
285         unsigned int Index;
286
287         Xil_AssertNonvoid(InstancePtr != NULL);
288         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
289
290         /*
291          * Read control register to find which options are currently set.
292          */
293         ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
294                                       XIICPS_CR_OFFSET);
295
296         /*
297          * Loop through the options table to determine which options are set.
298          */
299         for (Index = 0; Index < XIICPS_NUM_OPTIONS; Index++) {
300                 if (ControlReg & OptionsTable[Index].Mask) {
301                         OptionsFlag |= OptionsTable[Index].Option;
302                 }
303                 if ((ControlReg & XIICPS_CR_NEA_MASK) == 0) {
304                         OptionsFlag |= XIICPS_10_BIT_ADDR_OPTION;
305                 }
306         }
307
308         if (InstancePtr->IsRepeatedStart) {
309                 OptionsFlag |= XIICPS_REP_START_OPTION;
310         }
311         return OptionsFlag;
312 }
313
314 /*****************************************************************************/
315 /**
316 *
317 * This function sets the serial clock rate for the IIC device. The device
318 * must be idle rather than busy transferring data before setting these device
319 * options.
320 *
321 * The data rate is set by values in the control register. The formula for
322 * determining the correct register values is:
323 * Fscl = Fpclk/(22 x (divisor_a+1) x (divisor_b+1))
324 * See the hardware data sheet for a full explanation of setting the serial
325 * clock rate.
326 *
327 * @param        InstancePtr is a pointer to the XIicPs instance.
328 * @param        FsclHz is the clock frequency in Hz. The two most common clock
329 *               rates are 100KHz and 400KHz.
330 *
331 * @return
332 *               - XST_SUCCESS if options are successfully set.
333 *               - XST_DEVICE_IS_STARTED if the device is currently transferring
334 *               data. The transfer must complete or be aborted before setting
335 *               options.
336 *               - XST_FAILURE if the Fscl frequency can not be set.
337 *
338 * @note         The clock can not be faster than the input clock divide by 22.
339 *
340 ******************************************************************************/
341 int XIicPs_SetSClk(XIicPs *InstancePtr, u32 FsclHz)
342 {
343         u32 Div_a;
344         u32 Div_b;
345         u32 ActualFscl;
346         u32 Temp;
347         u32 TempLimit;
348         u32 LastError;
349         u32 BestError;
350         u32 CurrentError;
351         u32 ControlReg;
352         u32 CalcDivA;
353         u32 CalcDivB;
354         u32 BestDivA = 0;
355         u32 BestDivB = 0;
356
357         Xil_AssertNonvoid(InstancePtr != NULL);
358         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
359         Xil_AssertNonvoid(FsclHz > 0);
360
361         if (0 != XIicPs_In32((InstancePtr->Config.BaseAddress) +
362                                         XIICPS_TRANS_SIZE_OFFSET)) {
363                 return 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) / (22 * FsclHz);
370
371         /*
372          * If the answer is negative or 0, the Fscl input is out of range.
373          */
374         if (0 == Temp) {
375                 return 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(FsclHz > 384600) {
384                 FsclHz = 384600;
385         }
386
387         if((FsclHz <= 100000) && (FsclHz > 90000)) {
388                 FsclHz = 90000;
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) % (22 * FsclHz)) ?
397                                                         Temp + 1 : Temp;
398         BestError = FsclHz;
399
400         for ( ; Temp <= TempLimit ; Temp++)
401         {
402                 LastError = FsclHz;
403                 CalcDivA = 0;
404                 CalcDivB = 0;
405                 CurrentError = 0;
406
407                 for (Div_b = 0; Div_b < 64; Div_b++) {
408
409                         Div_a = Temp / (Div_b + 1);
410
411                         if (Div_a != 0)
412                                 Div_a = Div_a - 1;
413
414                         if (Div_a > 3)
415                                 continue;
416
417                         ActualFscl = (InstancePtr->Config.InputClockHz) /
418                                                 (22 * (Div_a + 1) * (Div_b + 1));
419
420                         if (ActualFscl > FsclHz)
421                                 CurrentError = (ActualFscl - FsclHz);
422                         else
423                                 CurrentError = (FsclHz - ActualFscl);
424
425                         if (LastError > CurrentError) {
426                                 CalcDivA = Div_a;
427                                 CalcDivB = Div_b;
428                                 LastError = CurrentError;
429                         }
430                 }
431
432                 /*
433                  * Used to capture the best divisors.
434                  */
435                 if (LastError < BestError) {
436                         BestError = LastError;
437                         BestDivA = CalcDivA;
438                         BestDivB = CalcDivB;
439                 }
440         }
441
442
443         /*
444          * Read the control register and mask the Divisors.
445          */
446         ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
447                                           XIICPS_CR_OFFSET);
448         ControlReg &= ~(XIICPS_CR_DIV_A_MASK | XIICPS_CR_DIV_B_MASK);
449         ControlReg |= (BestDivA << XIICPS_CR_DIV_A_SHIFT) |
450                 (BestDivB << XIICPS_CR_DIV_B_SHIFT);
451
452         XIicPs_WriteReg(InstancePtr->Config.BaseAddress, XIICPS_CR_OFFSET,
453                           ControlReg);
454
455         return XST_SUCCESS;
456 }
457
458 /*****************************************************************************/
459 /**
460 *
461 * This function gets the serial clock rate for the IIC device. The device
462 * must be idle rather than busy transferring data before setting these device
463 * options.
464 *
465 * @param        InstancePtr is a pointer to the XIicPs instance.
466 *
467 * @return       The value of the IIC clock to the nearest Hz based on the
468 *               control register settings. The actual value may not be exact to
469 *               to integer math rounding errors.
470 *
471 * @note         None.
472 *
473 ******************************************************************************/
474 u32 XIicPs_GetSClk(XIicPs *InstancePtr)
475 {
476         u32 ControlReg;
477         u32 ActualFscl;
478         u32 Div_a;
479         u32 Div_b;
480
481         Xil_AssertNonvoid(InstancePtr != NULL);
482         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
483
484         ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
485                                           XIICPS_CR_OFFSET);
486
487         Div_a = (ControlReg & XIICPS_CR_DIV_A_MASK) >> XIICPS_CR_DIV_A_SHIFT;
488         Div_b = (ControlReg & XIICPS_CR_DIV_B_MASK) >> XIICPS_CR_DIV_B_SHIFT;
489
490         ActualFscl = (InstancePtr->Config.InputClockHz) /
491                 (22 * (Div_a + 1) * (Div_b + 1));
492
493         return ActualFscl;
494 }
495