![]() |
|
|||
File indexing completed on 2025-05-11 08:24:05
0001 /****************************************************************************** 0002 * Copyright (C) 2014 - 2022 Xilinx, Inc. All rights reserved. 0003 * SPDX-License-Identifier: MIT 0004 ******************************************************************************/ 0005 0006 /*****************************************************************************/ 0007 /** 0008 * 0009 * @file xqspipsu_options.c 0010 * @addtogroup Overview 0011 * @{ 0012 * 0013 * This file implements functions to configure the QSPIPSU component, 0014 * specifically some optional settings, clock and flash related information. 0015 * 0016 * <pre> 0017 * MODIFICATION HISTORY: 0018 * 0019 * Ver Who Date Changes 0020 * ----- --- -------- ----------------------------------------------- 0021 * 1.0 hk 08/21/14 First release 0022 * sk 03/13/15 Added IO mode support. 0023 * sk 04/24/15 Modified the code according to MISRAC-2012. 0024 * 1.1 sk 04/12/16 Added debug message prints. 0025 * 1.2 nsk 07/01/16 Modified XQspiPsu_SetOptions() to support 0026 * LQSPI options and updated OptionsTable 0027 * rk 07/15/16 Added support for TapDelays at different frequencies. 0028 * 1.7 tjs 01/17/18 Added support to toggle the WP pin of flash. (PR#2448) 0029 * 1.7 tjs 03/14/18 Added support in EL1 NS mode. (CR#974882) 0030 * 1.8 tjs 05/02/18 Added support for IS25LP064 and IS25WP064. 0031 * 1.8 tjs 07/26/18 Resolved cppcheck errors. (CR#1006336) 0032 * 1.9 tjs 04/17/18 Updated register addresses as per the latest revision 0033 * of versal (CR#999610) 0034 * 1.9 aru 01/17/19 Fixes violations according to MISRAC-2012 0035 * in safety mode and modified the code such as 0036 * Added Xil_MemCpy inplace of memcpy,Declared the pointer param 0037 * as Pointer to const, declared XQspi_Set_TapDelay() as static. 0038 * 1.9 akm 03/08/19 Set recommended clock and data tap delay values for 40MHZ, 0039 * 100MHZ and 150MHZ frequencies(CR#1023187) 0040 * 1.10 akm 08/22/19 Set recommended tap delay values for 37.5MHZ, 100MHZ and 0041 * 150MHZ frequencies in Versal. 0042 * 1.11 akm 11/07/19 Removed LQSPI register access in Versal. 0043 * 1.11 akm 11/15/19 Fixed Coverity deadcode warning in 0044 * XQspipsu_Calculate_Tapdelay(). 0045 * 1.11 akm 03/09/20 Reorganize the source code, enable qspi controller and 0046 * interrupts in XQspiPsu_CfgInitialize() API. 0047 * 1.13 akm 01/04/21 Fix MISRA-C violations. 0048 * 1.15 akm 03/03/22 Enable tapdelay settings for applications on Microblaze 0049 * platform. 0050 * 0051 * </pre> 0052 * 0053 ******************************************************************************/ 0054 0055 /***************************** Include Files *********************************/ 0056 0057 #include "xqspipsu_control.h" 0058 0059 /************************** Constant Definitions *****************************/ 0060 0061 /**************************** Type Definitions *******************************/ 0062 0063 /***************** Macros (Inline Functions) Definitions *********************/ 0064 0065 /************************** Function Prototypes ******************************/ 0066 0067 /************************** Variable Definitions *****************************/ 0068 0069 /** 0070 * Create the table of options which are processed to get/set the device 0071 * options. These options are table driven to allow easy maintenance and 0072 * expansion of the options. 0073 */ 0074 typedef struct { 0075 u32 Option; /**< Get/Set the device option */ 0076 u32 Mask; /**< Mask */ 0077 } OptionsMap; 0078 0079 static OptionsMap OptionsTable[] = { 0080 {XQSPIPSU_CLK_ACTIVE_LOW_OPTION, XQSPIPSU_CFG_CLK_POL_MASK}, 0081 {XQSPIPSU_CLK_PHASE_1_OPTION, XQSPIPSU_CFG_CLK_PHA_MASK}, 0082 {XQSPIPSU_MANUAL_START_OPTION, XQSPIPSU_CFG_GEN_FIFO_START_MODE_MASK}, 0083 #if !defined (versal) 0084 {XQSPIPSU_LQSPI_MODE_OPTION, XQSPIPSU_CFG_WP_HOLD_MASK}, 0085 #endif 0086 }; 0087 0088 /** 0089 * Number of options in option table 0090 */ 0091 #define XQSPIPSU_NUM_OPTIONS (sizeof(OptionsTable) / sizeof(OptionsMap)) 0092 0093 /*****************************************************************************/ 0094 /** 0095 * 0096 * This function sets the options for the QSPIPSU device driver.The options 0097 * control how the device behaves relative to the QSPIPSU bus. The device must be 0098 * idle rather than busy transferring data before setting these device options. 0099 * 0100 * @param InstancePtr is a pointer to the XQspiPsu instance. 0101 * @param Options contains the specified options to be set. This is a bit 0102 * mask where a 1 indicates the option should be turned ON and 0103 * a 0 indicates no action. One or more bit values may be 0104 * contained in the mask. See the bit definitions named 0105 * XQSPIPSU_*_OPTIONS in the file xqspipsu.h. 0106 * 0107 * @return 0108 * - XST_SUCCESS if options are successfully set. 0109 * - XST_DEVICE_BUSY if the device is currently transferring data. 0110 * The transfer must complete or be aborted before setting options. 0111 * 0112 * @note 0113 * This function is not thread-safe. 0114 * 0115 ******************************************************************************/ 0116 s32 XQspiPsu_SetOptions(XQspiPsu *InstancePtr, u32 Options) 0117 { 0118 u32 ConfigReg; 0119 u32 Index; 0120 #if !defined (versal) 0121 u32 QspiPsuOptions; 0122 #endif 0123 s32 Status; 0124 u32 OptionsVal; 0125 OptionsVal = Options; 0126 0127 Xil_AssertNonvoid(InstancePtr != NULL); 0128 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); 0129 0130 /* 0131 * Do not allow to modify the Control Register while a transfer is in 0132 * progress. Not thread-safe. 0133 */ 0134 if (InstancePtr->IsBusy == (u32)TRUE) { 0135 Status = (s32)XST_DEVICE_BUSY; 0136 } else { 0137 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, 0138 XQSPIPSU_CFG_OFFSET); 0139 #if !defined (versal) 0140 QspiPsuOptions = OptionsVal & XQSPIPSU_LQSPI_MODE_OPTION; 0141 OptionsVal &= (~XQSPIPSU_LQSPI_MODE_OPTION); 0142 #endif 0143 /* 0144 * Loop through the options table, turning the option on 0145 * depending on whether the bit is set in the incoming options flag. 0146 */ 0147 for (Index = 0U; Index < XQSPIPSU_NUM_OPTIONS; Index++) { 0148 if ((OptionsVal & OptionsTable[Index].Option) == 0149 OptionsTable[Index].Option) { 0150 /* Turn it on */ 0151 ConfigReg |= OptionsTable[Index].Mask; 0152 } else { 0153 /* Turn it off */ 0154 ConfigReg &= ~(OptionsTable[Index].Mask); 0155 } 0156 } 0157 /* 0158 * Now write the control register. Leave it to the upper layers 0159 * to restart the device. 0160 */ 0161 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET, 0162 ConfigReg); 0163 0164 if ((OptionsVal & XQSPIPSU_MANUAL_START_OPTION) != (u32)FALSE) { 0165 InstancePtr->IsManualstart = (u8)TRUE; 0166 } 0167 #if !defined (versal) 0168 if ((QspiPsuOptions & XQSPIPSU_LQSPI_MODE_OPTION) != (u32)FALSE) { 0169 if ((Options & XQSPIPSU_LQSPI_LESS_THEN_SIXTEENMB) != (u32)FALSE) { 0170 XQspiPsu_WriteReg(XQSPIPS_BASEADDR,XQSPIPSU_LQSPI_CR_OFFSET,XQSPIPS_LQSPI_CR_RST_STATE); 0171 } else { 0172 XQspiPsu_WriteReg(XQSPIPS_BASEADDR,XQSPIPSU_LQSPI_CR_OFFSET,XQSPIPS_LQSPI_CR_4_BYTE_STATE); 0173 } 0174 XQspiPsu_WriteReg(XQSPIPS_BASEADDR,XQSPIPSU_CFG_OFFSET,XQSPIPS_LQSPI_CFG_RST_STATE); 0175 /* Enable the QSPI controller */ 0176 XQspiPsu_WriteReg(XQSPIPS_BASEADDR,XQSPIPSU_EN_OFFSET,XQSPIPSU_EN_MASK); 0177 } else { 0178 /* 0179 * Check for the LQSPI configuration options. 0180 */ 0181 ConfigReg = XQspiPsu_ReadReg(XQSPIPS_BASEADDR,XQSPIPSU_LQSPI_CR_OFFSET); 0182 ConfigReg &= ~(XQSPIPSU_LQSPI_CR_LINEAR_MASK); 0183 XQspiPsu_WriteReg(XQSPIPS_BASEADDR,XQSPIPSU_LQSPI_CR_OFFSET, ConfigReg); 0184 } 0185 #endif 0186 Status = (s32)XST_SUCCESS; 0187 } 0188 return Status; 0189 } 0190 0191 /*****************************************************************************/ 0192 /** 0193 * 0194 * This function resets the options for the QSPIPSU device driver.The options 0195 * control how the device behaves relative to the QSPIPSU bus. The device must be 0196 * idle rather than busy transferring data before setting these device options. 0197 * 0198 * @param InstancePtr is a pointer to the XQspiPsu instance. 0199 * @param Options contains the specified options to be set. This is a bit 0200 * mask where a 1 indicates the option should be turned OFF and 0201 * a 0 indicates no action. One or more bit values may be 0202 * contained in the mask. See the bit definitions named 0203 * XQSPIPSU_*_OPTIONS in the file xqspipsu.h. 0204 * 0205 * @return 0206 * - XST_SUCCESS if options are successfully set. 0207 * - XST_DEVICE_BUSY if the device is currently transferring data. 0208 * The transfer must complete or be aborted before setting options. 0209 * 0210 * @note 0211 * This function is not thread-safe. 0212 * 0213 ******************************************************************************/ 0214 s32 XQspiPsu_ClearOptions(XQspiPsu *InstancePtr, u32 Options) 0215 { 0216 u32 ConfigReg; 0217 u32 Index; 0218 s32 Status; 0219 0220 Xil_AssertNonvoid(InstancePtr != NULL); 0221 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); 0222 0223 /* 0224 * Do not allow to modify the Control Register while a transfer is in 0225 * progress. Not thread-safe. 0226 */ 0227 if (InstancePtr->IsBusy == (u32)TRUE) { 0228 Status = (s32)XST_DEVICE_BUSY; 0229 } else { 0230 0231 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, 0232 XQSPIPSU_CFG_OFFSET); 0233 0234 /* 0235 * Loop through the options table, turning the option on 0236 * depending on whether the bit is set in the incoming options flag. 0237 */ 0238 for (Index = 0U; Index < XQSPIPSU_NUM_OPTIONS; Index++) { 0239 if ((Options & OptionsTable[Index].Option) != (u32)FALSE) { 0240 /* Turn it off */ 0241 ConfigReg &= ~OptionsTable[Index].Mask; 0242 } 0243 } 0244 /* 0245 * Now write the control register. Leave it to the upper layers 0246 * to restart the device. 0247 */ 0248 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET, 0249 ConfigReg); 0250 0251 if ((Options & XQSPIPSU_MANUAL_START_OPTION) != (u32)FALSE) { 0252 InstancePtr->IsManualstart = (u8)FALSE; 0253 } 0254 0255 Status = (s32)XST_SUCCESS; 0256 } 0257 0258 return Status; 0259 } 0260 0261 /*****************************************************************************/ 0262 /** 0263 * 0264 * This function gets the options for the QSPIPSU device. The options control how 0265 * the device behaves relative to the QSPIPSU bus. 0266 * 0267 * @param InstancePtr is a pointer to the XQspiPsu instance. 0268 * 0269 * @return 0270 * 0271 * Options contains the specified options currently set. This is a bit value 0272 * where a 1 means the option is on, and a 0 means the option is off. 0273 * See the bit definitions named XQSPIPSU_*_OPTIONS in file xqspipsu.h. 0274 * 0275 * @note None. 0276 * 0277 ******************************************************************************/ 0278 u32 XQspiPsu_GetOptions(const XQspiPsu *InstancePtr) 0279 { 0280 u32 OptionsFlag = 0; 0281 u32 ConfigReg; 0282 u32 Index; 0283 0284 Xil_AssertNonvoid(InstancePtr != NULL); 0285 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); 0286 0287 /* Loop through the options table to grab options */ 0288 for (Index = 0U; Index < XQSPIPSU_NUM_OPTIONS; Index++) { 0289 /* 0290 * Get the current options from QSPIPSU configuration register. 0291 */ 0292 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, 0293 XQSPIPSU_CFG_OFFSET); 0294 if ((ConfigReg & OptionsTable[Index].Mask) != (u32)FALSE) { 0295 OptionsFlag |= OptionsTable[Index].Option; 0296 } 0297 } 0298 return OptionsFlag; 0299 } 0300 0301 /*****************************************************************************/ 0302 /** 0303 * 0304 * Configures the clock according to the prescaler passed. 0305 * 0306 * 0307 * @param InstancePtr is a pointer to the XQspiPsu instance. 0308 * @param Prescaler - clock prescaler to be set. 0309 * 0310 * @return 0311 * - XST_SUCCESS if successful. 0312 * - XST_DEVICE_IS_STARTED if the device is already started. 0313 * - XST_DEVICE_BUSY if the device is currently transferring data. 0314 * It must be stopped to re-initialize. 0315 * 0316 * @note None. 0317 * 0318 ******************************************************************************/ 0319 s32 XQspiPsu_SetClkPrescaler(const XQspiPsu *InstancePtr, u8 Prescaler) 0320 { 0321 u32 ConfigReg; 0322 s32 Status; 0323 0324 Xil_AssertNonvoid(InstancePtr != NULL); 0325 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); 0326 Xil_AssertNonvoid(Prescaler <= XQSPIPSU_CR_PRESC_MAXIMUM); 0327 0328 /* 0329 * Do not allow the slave select to change while a transfer is in 0330 * progress. Not thread-safe. 0331 */ 0332 if (InstancePtr->IsBusy == (u32)TRUE) { 0333 Status = (s32)XST_DEVICE_BUSY; 0334 } else { 0335 /* 0336 * Read the configuration register, mask out the relevant bits, and set 0337 * them with the shifted value passed into the function. Write the 0338 * results back to the configuration register. 0339 */ 0340 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, 0341 XQSPIPSU_CFG_OFFSET); 0342 0343 ConfigReg &= ~(u32)XQSPIPSU_CFG_BAUD_RATE_DIV_MASK; 0344 ConfigReg |= (u32) ((u32)Prescaler & (u32)XQSPIPSU_CR_PRESC_MAXIMUM) << 0345 XQSPIPSU_CFG_BAUD_RATE_DIV_SHIFT; 0346 0347 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET, 0348 ConfigReg); 0349 0350 #if defined (ARMR5) || defined (__aarch64__) || defined (__MICROBLAZE__) 0351 Status = XQspipsu_Calculate_Tapdelay(InstancePtr,Prescaler); 0352 #else 0353 Status = (s32)XST_SUCCESS; 0354 #endif 0355 } 0356 return Status; 0357 } 0358 0359 /*****************************************************************************/ 0360 /** 0361 * 0362 * This function should be used to tell the QSPIPSU driver the HW flash 0363 * configuration being used. This API should be called at least once in the 0364 * application. If desired, it can be called multiple times when switching 0365 * between communicating to different flahs devices/using different configs. 0366 * 0367 * @param InstancePtr is a pointer to the XQspiPsu instance. 0368 * @param FlashCS - Flash Chip Select. 0369 * @param FlashBus - Flash Bus (Upper, Lower or Both). 0370 * 0371 * @return 0372 * - XST_SUCCESS if successful. 0373 * - XST_DEVICE_IS_STARTED if the device is already started. 0374 * It must be stopped to re-initialize. 0375 * 0376 * @note If this function is not called at least once in the application, 0377 * the driver assumes there is a single flash connected to the 0378 * lower bus and CS line. 0379 * 0380 ******************************************************************************/ 0381 void XQspiPsu_SelectFlash(XQspiPsu *InstancePtr, u8 FlashCS, u8 FlashBus) 0382 { 0383 Xil_AssertVoid(InstancePtr != NULL); 0384 Xil_AssertVoid(FlashCS > 0U); 0385 Xil_AssertVoid(FlashBus > 0U); 0386 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); 0387 0388 #ifdef DEBUG 0389 xil_printf("\nXQspiPsu_SelectFlash\r\n"); 0390 #endif 0391 0392 /* 0393 * Bus and CS lines selected here will be updated in the instance and 0394 * used for subsequent GENFIFO entries during transfer. 0395 */ 0396 0397 /* Choose slave select line */ 0398 switch (FlashCS) { 0399 case XQSPIPSU_SELECT_FLASH_CS_BOTH: 0400 InstancePtr->GenFifoCS = (u32)XQSPIPSU_GENFIFO_CS_LOWER | 0401 (u32)XQSPIPSU_GENFIFO_CS_UPPER; 0402 break; 0403 case XQSPIPSU_SELECT_FLASH_CS_UPPER: 0404 InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_UPPER; 0405 break; 0406 case XQSPIPSU_SELECT_FLASH_CS_LOWER: 0407 InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_LOWER; 0408 break; 0409 default: 0410 InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_LOWER; 0411 break; 0412 } 0413 0414 /* Choose bus */ 0415 switch (FlashBus) { 0416 case XQSPIPSU_SELECT_FLASH_BUS_BOTH: 0417 InstancePtr->GenFifoBus = (u32)XQSPIPSU_GENFIFO_BUS_LOWER | 0418 (u32)XQSPIPSU_GENFIFO_BUS_UPPER; 0419 break; 0420 case XQSPIPSU_SELECT_FLASH_BUS_UPPER: 0421 InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_UPPER; 0422 break; 0423 case XQSPIPSU_SELECT_FLASH_BUS_LOWER: 0424 InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_LOWER; 0425 break; 0426 default: 0427 InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_LOWER; 0428 break; 0429 } 0430 #ifdef DEBUG 0431 xil_printf("\nGenFifoCS is %08x and GenFifoBus is %08x\r\n", 0432 InstancePtr->GenFifoCS, InstancePtr->GenFifoBus); 0433 #endif 0434 0435 } 0436 0437 /*****************************************************************************/ 0438 /** 0439 * 0440 * This function sets the Read mode for the QSPIPSU device driver.The device 0441 * must be idle rather than busy transferring data before setting Read mode 0442 * options. 0443 * 0444 * @param InstancePtr is a pointer to the XQspiPsu instance. 0445 * @param Mode contains the specified Mode to be set. See the 0446 * bit definitions named XQSPIPSU_READMODE_* in the file xqspipsu.h. 0447 * 0448 * @return 0449 * - XST_SUCCESS if options are successfully set. 0450 * - XST_DEVICE_BUSY if the device is currently transferring data. 0451 * The transfer must complete or be aborted before setting Mode. 0452 * 0453 * @note 0454 * This function is not thread-safe. 0455 * 0456 ******************************************************************************/ 0457 s32 XQspiPsu_SetReadMode(XQspiPsu *InstancePtr, u32 Mode) 0458 { 0459 u32 ConfigReg; 0460 s32 Status; 0461 0462 #ifdef DEBUG 0463 xil_printf("\nXQspiPsu_SetReadMode\r\n"); 0464 #endif 0465 0466 Xil_AssertNonvoid(InstancePtr != NULL); 0467 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); 0468 Xil_AssertNonvoid((Mode == XQSPIPSU_READMODE_DMA) || (Mode == XQSPIPSU_READMODE_IO)); 0469 0470 /* 0471 * Do not allow to modify the Control Register while a transfer is in 0472 * progress. Not thread-safe. 0473 */ 0474 if (InstancePtr->IsBusy == (u32)TRUE) { 0475 Status = (s32)XST_DEVICE_BUSY; 0476 } else { 0477 0478 InstancePtr->ReadMode = Mode; 0479 0480 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, 0481 XQSPIPSU_CFG_OFFSET); 0482 0483 if (Mode == XQSPIPSU_READMODE_DMA) { 0484 ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK; 0485 ConfigReg |= XQSPIPSU_CFG_MODE_EN_DMA_MASK; 0486 } else { 0487 ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK; 0488 } 0489 0490 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET, 0491 ConfigReg); 0492 0493 Status = (s32)XST_SUCCESS; 0494 } 0495 #ifdef DEBUG 0496 xil_printf("\nRead Mode is %08x\r\n", InstancePtr->ReadMode); 0497 #endif 0498 return Status; 0499 } 0500 0501 /*****************************************************************************/ 0502 /** 0503 * 0504 * This function sets the Write Protect and Hold options for the QSPIPSU device 0505 * driver.The device must be idle rather than busy transferring data before 0506 * setting Write Protect and Hold options. 0507 * 0508 * @param InstancePtr is a pointer to the XQspiPsu instance. 0509 * @param Value of the WP_HOLD bit in configuration register 0510 * 0511 * @return None 0512 * 0513 * @note 0514 * This function is not thread-safe. This function can only be used with single 0515 * flash configuration and x1/x2 data mode. This function cannot be used with 0516 * x4 data mode and dual parallel and stacked flash configuration. 0517 * 0518 ******************************************************************************/ 0519 void XQspiPsu_SetWP(const XQspiPsu *InstancePtr, u8 Value) 0520 { 0521 u32 ConfigReg; 0522 Xil_AssertVoid(InstancePtr != NULL); 0523 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); 0524 Xil_AssertVoid(InstancePtr->IsBusy != TRUE); 0525 0526 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, 0527 XQSPIPSU_CFG_OFFSET); 0528 ConfigReg |= (u32)((u32)Value << XQSPIPSU_CFG_WP_HOLD_SHIFT); 0529 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET, 0530 ConfigReg); 0531 } 0532 /** @} */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |