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