]> git.sur5r.net Git - freertos/blob
97eee8cfdeaf370c883c68d9406502b8fcfe67c1
[freertos] /
1 /******************************************************************************
2 *
3 * Copyright (C) 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 xqspipsu_options.c
36 * @addtogroup qspipsu_v1_0
37 * @{
38 *
39 * This file implements funcitons to configure the QSPIPSU component,
40 * specifically some optional settings, clock and flash related information.
41 *
42 * <pre>
43 * MODIFICATION HISTORY:
44 *
45 * Ver   Who Date     Changes
46 * ----- --- -------- -----------------------------------------------
47 * 1.0   hk  08/21/14 First release
48 *       sk  03/13/15 Added IO mode support.
49 *       sk  04/24/15 Modified the code according to MISRAC-2012.
50 *
51 * </pre>
52 *
53 ******************************************************************************/
54
55 /***************************** Include Files *********************************/
56
57 #include "xqspipsu.h"
58
59 /************************** Constant Definitions *****************************/
60
61 /**************************** Type Definitions *******************************/
62
63 /***************** Macros (Inline Functions) Definitions *********************/
64
65 /************************** Function Prototypes ******************************/
66
67 /************************** Variable Definitions *****************************/
68
69 /*
70  * Create the table of options which are processed to get/set the device
71  * options. These options are table driven to allow easy maintenance and
72  * expansion of the options.
73  */
74 typedef struct {
75         u32 Option;
76         u32 Mask;
77 } OptionsMap;
78
79 static OptionsMap OptionsTable[] = {
80         {XQSPIPSU_CLK_ACTIVE_LOW_OPTION, XQSPIPSU_CFG_CLK_POL_MASK},
81         {XQSPIPSU_CLK_PHASE_1_OPTION, XQSPIPSU_CFG_CLK_PHA_MASK},
82         {XQSPIPSU_MANUAL_START_OPTION, XQSPIPSU_CFG_GEN_FIFO_START_MODE_MASK},
83 };
84
85 #define XQSPIPSU_NUM_OPTIONS    (sizeof(OptionsTable) / sizeof(OptionsMap))
86
87 /*****************************************************************************/
88 /**
89 *
90 * This function sets the options for the QSPIPSU device driver.The options
91 * control how the device behaves relative to the QSPIPSU bus. The device must be
92 * idle rather than busy transferring data before setting these device options.
93 *
94 * @param        InstancePtr is a pointer to the XQspiPsu instance.
95 * @param        Options contains the specified options to be set. This is a bit
96 *               mask where a 1 indicates the option should be turned ON and
97 *               a 0 indicates no action. One or more bit values may be
98 *               contained in the mask. See the bit definitions named
99 *               XQSPIPSU_*_OPTIONS in the file xqspipsu.h.
100 *
101 * @return
102 *               - XST_SUCCESS if options are successfully set.
103 *               - XST_DEVICE_BUSY if the device is currently transferring data.
104 *               The transfer must complete or be aborted before setting options.
105 *
106 * @note
107 * This function is not thread-safe.
108 *
109 ******************************************************************************/
110 s32 XQspiPsu_SetOptions(XQspiPsu *InstancePtr, u32 Options)
111 {
112         u32 ConfigReg;
113         u32 Index;
114         u32 QspiPsuOptions;
115         s32 Status;
116
117         Xil_AssertNonvoid(InstancePtr != NULL);
118         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
119
120         /*
121          * Do not allow to modify the Control Register while a transfer is in
122          * progress. Not thread-safe.
123          */
124         if (InstancePtr->IsBusy == TRUE) {
125                 Status = (s32)XST_DEVICE_BUSY;
126         } else {
127
128                 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
129                                               XQSPIPSU_CFG_OFFSET);
130
131                 /*
132                  * Loop through the options table, turning the option on
133                  * depending on whether the bit is set in the incoming options flag.
134                  */
135                 for (Index = 0U; Index < XQSPIPSU_NUM_OPTIONS; Index++) {
136                         if ((Options & OptionsTable[Index].Option) != FALSE) {
137                                 /* Turn it on */
138                                 ConfigReg |= OptionsTable[Index].Mask;
139                         }
140                 }
141
142                 /*
143                  * Now write the control register. Leave it to the upper layers
144                  * to restart the device.
145                  */
146                 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
147                                  ConfigReg);
148
149                 if ((Options & XQSPIPSU_MANUAL_START_OPTION) != FALSE) {
150                         InstancePtr->IsManualstart = TRUE;
151                 }
152
153                 Status = XST_SUCCESS;
154         }
155
156         return Status;
157 }
158
159 /*****************************************************************************/
160 /**
161 *
162 * This function resets the options for the QSPIPSU device driver.The options
163 * control how the device behaves relative to the QSPIPSU bus. The device must be
164 * idle rather than busy transferring data before setting these device options.
165 *
166 * @param        InstancePtr is a pointer to the XQspiPsu instance.
167 * @param        Options contains the specified options to be set. This is a bit
168 *               mask where a 1 indicates the option should be turned OFF and
169 *               a 0 indicates no action. One or more bit values may be
170 *               contained in the mask. See the bit definitions named
171 *               XQSPIPSU_*_OPTIONS in the file xqspipsu.h.
172 *
173 * @return
174 *               - XST_SUCCESS if options are successfully set.
175 *               - XST_DEVICE_BUSY if the device is currently transferring data.
176 *               The transfer must complete or be aborted before setting options.
177 *
178 * @note
179 * This function is not thread-safe.
180 *
181 ******************************************************************************/
182 s32 XQspiPsu_ClearOptions(XQspiPsu *InstancePtr, u32 Options)
183 {
184         u32 ConfigReg;
185         u32 Index;
186         u32 QspiPsuOptions;
187         s32 Status;
188
189         Xil_AssertNonvoid(InstancePtr != NULL);
190         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
191
192         /*
193          * Do not allow to modify the Control Register while a transfer is in
194          * progress. Not thread-safe.
195          */
196         if (InstancePtr->IsBusy == TRUE) {
197                 Status = (s32)XST_DEVICE_BUSY;
198         } else {
199
200                 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
201                                               XQSPIPSU_CFG_OFFSET);
202
203                 /*
204                  * Loop through the options table, turning the option on
205                  * depending on whether the bit is set in the incoming options flag.
206                  */
207                 for (Index = 0U; Index < XQSPIPSU_NUM_OPTIONS; Index++) {
208                         if ((Options & OptionsTable[Index].Option) != FALSE) {
209                                 /* Turn it off */
210                                 ConfigReg &= ~OptionsTable[Index].Mask;
211                         }
212                 }
213
214                 /*
215                  * Now write the control register. Leave it to the upper layers
216                  * to restart the device.
217                  */
218                 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
219                                  ConfigReg);
220
221                 if ((Options & XQSPIPSU_MANUAL_START_OPTION) != FALSE) {
222                         InstancePtr->IsManualstart = FALSE;
223                 }
224
225                 Status = XST_SUCCESS;
226         }
227
228         return Status;
229 }
230
231 /*****************************************************************************/
232 /**
233 *
234 * This function gets the options for the QSPIPSU device. The options control how
235 * the device behaves relative to the QSPIPSU bus.
236 *
237 * @param        InstancePtr is a pointer to the XQspiPsu instance.
238 *
239 * @return
240 *
241 * Options contains the specified options currently set. This is a bit value
242 * where a 1 means the option is on, and a 0 means the option is off.
243 * See the bit definitions named XQSPIPSU_*_OPTIONS in file xqspipsu.h.
244 *
245 * @note         None.
246 *
247 ******************************************************************************/
248 u32 XQspiPsu_GetOptions(XQspiPsu *InstancePtr)
249 {
250         u32 OptionsFlag = 0;
251         u32 ConfigReg;
252         u32 Index;
253
254         Xil_AssertNonvoid(InstancePtr != NULL);
255         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
256
257         /*
258          * Get the current options from QSPIPSU configuration register.
259          */
260         ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
261                                       XQSPIPSU_CFG_OFFSET);
262
263         /* Loop through the options table to grab options */
264         for (Index = 0U; Index < XQSPIPSU_NUM_OPTIONS; Index++) {
265                 if ((ConfigReg & OptionsTable[Index].Mask) != FALSE) {
266                         OptionsFlag |= OptionsTable[Index].Option;
267                 }
268         }
269
270         return OptionsFlag;
271 }
272
273 /*****************************************************************************/
274 /**
275 *
276 * Configures the clock according to the prescaler passed.
277 *
278 *
279 * @param        InstancePtr is a pointer to the XQspiPsu instance.
280 * @param        Prescaler - clock prescaler to be set.
281 *
282 * @return
283 *               - XST_SUCCESS if successful.
284 *               - XST_DEVICE_IS_STARTED if the device is already started.
285 *               It must be stopped to re-initialize.
286 *
287 * @note         None.
288 *
289 ******************************************************************************/
290 s32 XQspiPsu_SetClkPrescaler(XQspiPsu *InstancePtr, u8 Prescaler)
291 {
292         u32 ConfigReg;
293         s32 Status;
294
295         Xil_AssertNonvoid(InstancePtr != NULL);
296         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
297         Xil_AssertNonvoid(Prescaler <= XQSPIPSU_CR_PRESC_MAXIMUM);
298
299         /*
300          * Do not allow the slave select to change while a transfer is in
301          * progress. Not thread-safe.
302          */
303         if (InstancePtr->IsBusy == TRUE) {
304                 Status = (s32)XST_DEVICE_BUSY;
305         } else {
306
307                 /*
308                  * Read the configuration register, mask out the relevant bits, and set
309                  * them with the shifted value passed into the function. Write the
310                  * results back to the configuration register.
311                  */
312                 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
313                                               XQSPIPSU_CFG_OFFSET);
314
315                 ConfigReg &= (u32)(~XQSPIPSU_CFG_BAUD_RATE_DIV_MASK);
316                 ConfigReg |= (u32) ((u32)Prescaler & (u32)XQSPIPSU_CR_PRESC_MAXIMUM) <<
317                                     XQSPIPSU_CFG_BAUD_RATE_DIV_SHIFT;
318
319                 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
320                                   XQSPIPSU_CFG_OFFSET, ConfigReg);
321
322                 Status = XST_SUCCESS;
323         }
324
325         return Status;
326 }
327
328 /*****************************************************************************/
329 /**
330 *
331 * This funciton should be used to tell the QSPIPSU driver the HW flash
332 * configuration being used. This API should be called atleast once in the
333 * application. If desired, it can be called multiple times when switching
334 * between communicating to different flahs devices/using different configs.
335 *
336 * @param        InstancePtr is a pointer to the XQspiPsu instance.
337 * @param        FlashCS - Flash Chip Select.
338 * @param        FlashBus - Flash Bus (Upper, Lower or Both).
339 *
340 * @return
341 *               - XST_SUCCESS if successful.
342 *               - XST_DEVICE_IS_STARTED if the device is already started.
343 *               It must be stopped to re-initialize.
344 *
345 * @note         If this funciton is not called atleast once in the application,
346 *               the driver assumes there is a single flash connected to the
347 *               lower bus and CS line.
348 *
349 ******************************************************************************/
350 void XQspiPsu_SelectFlash(XQspiPsu *InstancePtr, u8 FlashCS, u8 FlashBus)
351 {
352         Xil_AssertVoid(InstancePtr != NULL);
353
354         /*
355          * Bus and CS lines selected here will be updated in the instance and
356          * used for subsequent GENFIFO entries during transfer.
357          */
358
359         /* Choose slave select line */
360         switch (FlashCS) {
361                 case XQSPIPSU_SELECT_FLASH_CS_BOTH:
362                         InstancePtr->GenFifoCS = (u32)XQSPIPSU_GENFIFO_CS_LOWER |
363                                                 (u32)XQSPIPSU_GENFIFO_CS_UPPER;
364                         break;
365                 case XQSPIPSU_SELECT_FLASH_CS_UPPER:
366                         InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_UPPER;
367                         break;
368                 case XQSPIPSU_SELECT_FLASH_CS_LOWER:
369                         InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_LOWER;
370                         break;
371                 default:
372                         InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_LOWER;
373                         break;
374         }
375
376         /* Choose bus */
377         switch (FlashBus) {
378                 case XQSPIPSU_SELECT_FLASH_BUS_BOTH:
379                         InstancePtr->GenFifoBus = (u32)XQSPIPSU_GENFIFO_BUS_LOWER |
380                                                 (u32)XQSPIPSU_GENFIFO_BUS_UPPER;
381                         break;
382                 case XQSPIPSU_SELECT_FLASH_BUS_UPPER:
383                         InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_UPPER;
384                         break;
385                 case XQSPIPSU_SELECT_FLASH_BUS_LOWER:
386                         InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_LOWER;
387                         break;
388                 default:
389                         InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_LOWER;
390                         break;
391         }
392 }
393
394 /*****************************************************************************/
395 /**
396 *
397 * This function sets the Read mode for the QSPIPSU device driver.The device
398 * must be idle rather than busy transferring data before setting Read mode
399 * options.
400 *
401 * @param        InstancePtr is a pointer to the XQspiPsu instance.
402 * @param        Mode contains the specified Mode to be set. See the
403 *               bit definitions named XQSPIPSU_READMODE_* in the file xqspipsu.h.
404 *
405 * @return
406 *               - XST_SUCCESS if options are successfully set.
407 *               - XST_DEVICE_BUSY if the device is currently transferring data.
408 *               The transfer must complete or be aborted before setting Mode.
409 *
410 * @note
411 * This function is not thread-safe.
412 *
413 ******************************************************************************/
414 s32 XQspiPsu_SetReadMode(XQspiPsu *InstancePtr, u32 Mode)
415 {
416         u32 ConfigReg;
417         s32 Status;
418
419         Xil_AssertNonvoid(InstancePtr != NULL);
420         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
421
422         /*
423          * Do not allow to modify the Control Register while a transfer is in
424          * progress. Not thread-safe.
425          */
426         if (InstancePtr->IsBusy == TRUE) {
427                 Status = (s32)XST_DEVICE_BUSY;
428         } else {
429
430                 InstancePtr->ReadMode = Mode;
431
432                 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
433                                               XQSPIPSU_CFG_OFFSET);
434
435                 if (Mode == XQSPIPSU_READMODE_DMA) {
436                         ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK;
437                         ConfigReg |= XQSPIPSU_CFG_MODE_EN_DMA_MASK;
438                 } else {
439                         ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK;
440                 }
441
442                 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
443                                  ConfigReg);
444
445                 Status = XST_SUCCESS;
446         }
447         return Status;
448 }
449 /** @} */