1 /******************************************************************************
3 * Copyright (C) 2014 Xilinx, Inc. All rights reserved.
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:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
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.
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
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.
31 ******************************************************************************/
32 /*****************************************************************************/
35 * @file xqspipsu_options.c
36 * @addtogroup qspipsu_v1_0
39 * This file implements funcitons to configure the QSPIPSU component,
40 * specifically some optional settings, clock and flash related information.
43 * MODIFICATION HISTORY:
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.
53 ******************************************************************************/
55 /***************************** Include Files *********************************/
59 /************************** Constant Definitions *****************************/
61 /**************************** Type Definitions *******************************/
63 /***************** Macros (Inline Functions) Definitions *********************/
65 /************************** Function Prototypes ******************************/
67 /************************** Variable Definitions *****************************/
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.
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},
85 #define XQSPIPSU_NUM_OPTIONS (sizeof(OptionsTable) / sizeof(OptionsMap))
87 /*****************************************************************************/
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.
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.
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.
107 * This function is not thread-safe.
109 ******************************************************************************/
110 s32 XQspiPsu_SetOptions(XQspiPsu *InstancePtr, u32 Options)
117 Xil_AssertNonvoid(InstancePtr != NULL);
118 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
121 * Do not allow to modify the Control Register while a transfer is in
122 * progress. Not thread-safe.
124 if (InstancePtr->IsBusy == TRUE) {
125 Status = (s32)XST_DEVICE_BUSY;
128 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
129 XQSPIPSU_CFG_OFFSET);
132 * Loop through the options table, turning the option on
133 * depending on whether the bit is set in the incoming options flag.
135 for (Index = 0U; Index < XQSPIPSU_NUM_OPTIONS; Index++) {
136 if ((Options & OptionsTable[Index].Option) != FALSE) {
138 ConfigReg |= OptionsTable[Index].Mask;
143 * Now write the control register. Leave it to the upper layers
144 * to restart the device.
146 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
149 if ((Options & XQSPIPSU_MANUAL_START_OPTION) != FALSE) {
150 InstancePtr->IsManualstart = TRUE;
153 Status = XST_SUCCESS;
159 /*****************************************************************************/
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.
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.
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.
179 * This function is not thread-safe.
181 ******************************************************************************/
182 s32 XQspiPsu_ClearOptions(XQspiPsu *InstancePtr, u32 Options)
189 Xil_AssertNonvoid(InstancePtr != NULL);
190 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
193 * Do not allow to modify the Control Register while a transfer is in
194 * progress. Not thread-safe.
196 if (InstancePtr->IsBusy == TRUE) {
197 Status = (s32)XST_DEVICE_BUSY;
200 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
201 XQSPIPSU_CFG_OFFSET);
204 * Loop through the options table, turning the option on
205 * depending on whether the bit is set in the incoming options flag.
207 for (Index = 0U; Index < XQSPIPSU_NUM_OPTIONS; Index++) {
208 if ((Options & OptionsTable[Index].Option) != FALSE) {
210 ConfigReg &= ~OptionsTable[Index].Mask;
215 * Now write the control register. Leave it to the upper layers
216 * to restart the device.
218 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
221 if ((Options & XQSPIPSU_MANUAL_START_OPTION) != FALSE) {
222 InstancePtr->IsManualstart = FALSE;
225 Status = XST_SUCCESS;
231 /*****************************************************************************/
234 * This function gets the options for the QSPIPSU device. The options control how
235 * the device behaves relative to the QSPIPSU bus.
237 * @param InstancePtr is a pointer to the XQspiPsu instance.
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.
247 ******************************************************************************/
248 u32 XQspiPsu_GetOptions(XQspiPsu *InstancePtr)
254 Xil_AssertNonvoid(InstancePtr != NULL);
255 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
258 * Get the current options from QSPIPSU configuration register.
260 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
261 XQSPIPSU_CFG_OFFSET);
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;
273 /*****************************************************************************/
276 * Configures the clock according to the prescaler passed.
279 * @param InstancePtr is a pointer to the XQspiPsu instance.
280 * @param Prescaler - clock prescaler to be set.
283 * - XST_SUCCESS if successful.
284 * - XST_DEVICE_IS_STARTED if the device is already started.
285 * It must be stopped to re-initialize.
289 ******************************************************************************/
290 s32 XQspiPsu_SetClkPrescaler(XQspiPsu *InstancePtr, u8 Prescaler)
295 Xil_AssertNonvoid(InstancePtr != NULL);
296 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
297 Xil_AssertNonvoid(Prescaler <= XQSPIPSU_CR_PRESC_MAXIMUM);
300 * Do not allow the slave select to change while a transfer is in
301 * progress. Not thread-safe.
303 if (InstancePtr->IsBusy == TRUE) {
304 Status = (s32)XST_DEVICE_BUSY;
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.
312 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
313 XQSPIPSU_CFG_OFFSET);
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;
319 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
320 XQSPIPSU_CFG_OFFSET, ConfigReg);
322 Status = XST_SUCCESS;
328 /*****************************************************************************/
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.
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).
341 * - XST_SUCCESS if successful.
342 * - XST_DEVICE_IS_STARTED if the device is already started.
343 * It must be stopped to re-initialize.
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.
349 ******************************************************************************/
350 void XQspiPsu_SelectFlash(XQspiPsu *InstancePtr, u8 FlashCS, u8 FlashBus)
352 Xil_AssertVoid(InstancePtr != NULL);
355 * Bus and CS lines selected here will be updated in the instance and
356 * used for subsequent GENFIFO entries during transfer.
359 /* Choose slave select line */
361 case XQSPIPSU_SELECT_FLASH_CS_BOTH:
362 InstancePtr->GenFifoCS = (u32)XQSPIPSU_GENFIFO_CS_LOWER |
363 (u32)XQSPIPSU_GENFIFO_CS_UPPER;
365 case XQSPIPSU_SELECT_FLASH_CS_UPPER:
366 InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_UPPER;
368 case XQSPIPSU_SELECT_FLASH_CS_LOWER:
369 InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_LOWER;
372 InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_LOWER;
378 case XQSPIPSU_SELECT_FLASH_BUS_BOTH:
379 InstancePtr->GenFifoBus = (u32)XQSPIPSU_GENFIFO_BUS_LOWER |
380 (u32)XQSPIPSU_GENFIFO_BUS_UPPER;
382 case XQSPIPSU_SELECT_FLASH_BUS_UPPER:
383 InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_UPPER;
385 case XQSPIPSU_SELECT_FLASH_BUS_LOWER:
386 InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_LOWER;
389 InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_LOWER;
394 /*****************************************************************************/
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
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.
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.
411 * This function is not thread-safe.
413 ******************************************************************************/
414 s32 XQspiPsu_SetReadMode(XQspiPsu *InstancePtr, u32 Mode)
419 Xil_AssertNonvoid(InstancePtr != NULL);
420 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
423 * Do not allow to modify the Control Register while a transfer is in
424 * progress. Not thread-safe.
426 if (InstancePtr->IsBusy == TRUE) {
427 Status = (s32)XST_DEVICE_BUSY;
430 InstancePtr->ReadMode = Mode;
432 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
433 XQSPIPSU_CFG_OFFSET);
435 if (Mode == XQSPIPSU_READMODE_DMA) {
436 ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK;
437 ConfigReg |= XQSPIPSU_CFG_MODE_EN_DMA_MASK;
439 ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK;
442 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
445 Status = XST_SUCCESS;