qspips_v3_2: Added new minor version for qspips.

This patch add new minor version for qspips and deprecated
the older version.

Signed-off-by: P L Sai Krishna <lakshmis@xilinx.com>
This commit is contained in:
P L Sai Krishna 2015-02-05 16:49:30 +05:30 committed by Suneel Garapati
parent ebc7a9922b
commit ee80739962
21 changed files with 9754 additions and 0 deletions

View file

@ -0,0 +1,42 @@
###############################################################################
#
# Copyright (C) 2011 - 2014 Xilinx, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# Use of the Software is limited solely to applications:
# (a) running on a Xilinx device, or
# (b) that interact with a Xilinx device through a bus or interconnect.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Except as contained in this notice, the name of the Xilinx shall not be used
# in advertising or otherwise to promote the sale, use or other dealings in
# this Software without prior written authorization from Xilinx.
#
###############################################################################
OPTION psf_version = 2.1;
BEGIN driver qspips
OPTION supported_peripherals = (ps7_qspi);
OPTION driver_state = ACTIVE;
OPTION copyfiles = all;
OPTION VERSION = 3.2;
OPTION NAME = qspips;
END driver

View file

@ -0,0 +1,52 @@
###############################################################################
#
# Copyright (C) 2011 - 2014 Xilinx, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# Use of the Software is limited solely to applications:
# (a) running on a Xilinx device, or
# (b) that interact with a Xilinx device through a bus or interconnect.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Except as contained in this notice, the name of the Xilinx shall not be used
# in advertising or otherwise to promote the sale, use or other dealings in
# this Software without prior written authorization from Xilinx.
#
###############################################################################
##############################################################################
#
# Modification History
#
# Ver Who Date Changes
# ----- ---- -------- -----------------------------------------------
# 1.00a sdm 11/22/11 Created
# 2.02a hk 26/03/13 Added C_QSPI_MODE
#
##############################################################################
#uses "xillib.tcl"
proc generate {drv_handle} {
::hsi::utils::define_zynq_include_file $drv_handle "xparameters.h" "XQspiPs" "NUM_INSTANCES" "DEVICE_ID" "C_S_AXI_BASEADDR" "C_S_AXI_HIGHADDR" "C_QSPI_CLK_FREQ_HZ" "C_QSPI_MODE"
::hsi::utils::define_zynq_config_file $drv_handle "xqspips_g.c" "XQspiPs" "DEVICE_ID" "C_S_AXI_BASEADDR" "C_QSPI_CLK_FREQ_HZ" "C_QSPI_MODE"
::hsi::utils::define_zynq_canonical_xpars $drv_handle "xparameters.h" "XQspiPs" "DEVICE_ID" "C_S_AXI_BASEADDR" "C_S_AXI_HIGHADDR" "C_QSPI_CLK_FREQ_HZ" "C_QSPI_MODE"
}

View file

@ -0,0 +1,40 @@
/******************************************************************************
*
* Copyright (C) 2011 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
#ifndef QSPIPS_HEADER_H /* prevent circular inclusions */
#define QSPIPS_HEADER_H /* by using protection macros */
#include "xil_types.h"
#include "xil_assert.h"
#include "xstatus.h"
int QspiPsSelfTestExample(u16 DeviceId);
#endif

View file

@ -0,0 +1,139 @@
###############################################################################
#
# Copyright (C) 2011 - 2014 Xilinx, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# Use of the Software is limited solely to applications:
# (a) running on a Xilinx device, or
# (b) that interact with a Xilinx device through a bus or interconnect.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Except as contained in this notice, the name of the Xilinx shall not be used
# in advertising or otherwise to promote the sale, use or other dealings in
# this Software without prior written authorization from Xilinx.
#
###############################################################################
###############################################################################
#
# MODIFICATION HISTORY:
# Ver Who Date Changes
# -------- ------ -------- ------------------------------------
# 3.0 adk 12/10/13 Updated as per the New Tcl API's
##############################################################################
# Uses $XILINX_EDK/bin/lib/xillib_sw.tcl
# -----------------------------------------------------------------
# Software Project Types (swproj):
# 0 : MemoryTest - Calls basic memorytest routines from common driver dir
# 1 : PeripheralTest - Calls any existing polled_example and/or selftest
# -----------------------------------------------------------------
# -----------------------------------------------------------------
# TCL Procedures:
# -----------------------------------------------------------------
proc gen_include_files {swproj mhsinst} {
if {$swproj == 0} {
return ""
}
if {$swproj == 1} {
set inc_file_lines { xqspips.h qspips_header.h}
}
return $inc_file_lines
}
proc gen_src_files {swproj mhsinst} {
if {$swproj == 0} {
return ""
}
if {$swproj == 1} {
set inc_file_lines {examples/xqspips_selftest_example.c data/qspips_header.h}
return $inc_file_lines
}
}
proc gen_testfunc_def {swproj mhsinst} {
return ""
}
proc gen_init_code {swproj mhsinst} {
if {$swproj == 0} {
return ""
}
if {$swproj == 1} {
return ""
}
}
proc gen_testfunc_call {swproj mhsinst} {
if {$swproj == 0} {
return ""
}
set ipname [common::get_property NAME $mhsinst]
set deviceid [::hsi::utils::get_ip_param_name $mhsinst "DEVICE_ID"]
set stdout [common::get_property CONFIG.STDOUT [hsi::get_os]]
if { $stdout == "" || $stdout == "none" } {
set hasStdout 0
} else {
set hasStdout 1
}
set testfunc_call ""
if {${hasStdout} == 0} {
append testfunc_call "
{
int Status;
Status = QspiPsSelfTestExample(${deviceid});
}"
} else {
append testfunc_call "
{
int Status;
print(\"\\r\\n Running QspiSelfTestExample() for ${ipname}...\\r\\n\");
Status = QspiPsSelfTestExample(${deviceid});
if (Status == 0) {
print(\"QspiPsSelfTestExample PASSED\\r\\n\");
}
else {
print(\"QspiPsSelfTestExample FAILED\\r\\n\");
}
}"
}
return $testfunc_call
}

View file

@ -0,0 +1,23 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Driver example applications</title>
<link rel="stylesheet" type="text/css" href="../help.css">
</head>
<body bgcolor="#FFFFFF">
<h1> Example Applications for the driver qspips_v3_1 </h1>
<HR>
<ul>
<li>xqspips_g128_flash_example.c <a href="xqspips_g128_flash_example.c">(source)</a> </li>
<li>xqspips_dual_flash_stack_lqspi_example.c <a href="xqspips_dual_flash_stack_lqspi_example.c">(source)</a> </li>
<li>xqspips_dual_flash_lqspi_example.c <a href="xqspips_dual_flash_lqspi_example.c">(source)</a> </li>
<li>xqspips_flash_intr_example.c <a href="xqspips_flash_intr_example.c">(source)</a> </li>
<li>xqspips_flash_lqspi_example.c <a href="xqspips_flash_lqspi_example.c">(source)</a> </li>
<li>xqspips_flash_polled_example.c <a href="xqspips_flash_polled_example.c">(source)</a> </li>
<li>xqspips_selftest_example.c <a href="xqspips_selftest_example.c">(source)</a> </li>
</ul>
<p><font face="Times New Roman" color="#800000">Copyright <20> 1995-2014 Xilinx, Inc. All rights reserved.</font></p>
</body>
</html>

View file

@ -0,0 +1,642 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xqspips_dual_flash_lqspi_example.c
*
* This file contains a design example using the QSPI driver (XQspiPs) in
* Linear QSPI mode, with two serial FLASH devices on seperate buses. With
* two flash memories on seperate buses, even numbered bits in data words are
* written to the lower memory and odd numbered bits are written to the upper
* memory. This example writes to the two flash memories in QSPI mode and reads
* the data back from the flash memories, in Linear QSPI mode.
* It is recommended to use Manual CS + Auto start for best performance.
*
* The hardware which this example runs on, must have a serial FLASH (Numonyx
* N25Q, Winbond W25Q, or Spansion S25FL) for it to run. This example has been
* tested with the Numonyx Serial Flash (N25Q128).
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00 sdm 11/25/10 First release
* 2.00a kka 22/08/12 Updated the example as XQspiPs_PolledTransfer API has
* changed. Changed the prescalar to use divide by 8.
* The user can change the prescalar to a maximum of
* divide by 2 based on the reference clock in the
* system.
* Set the Holdb_dr bit in the configuration register using
* XQSPIPS_HOLD_B_DRIVE_OPTION. Setting this bit
* drives the HOLD bit of the QSPI controller.
* This is required for QSPI to be used in Non QSPI boot
* mode else there needs to be an external pullup on this
* line.
*</pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* SDK generated parameters */
#include "xqspips.h" /* QSPI device driver */
#include "xil_printf.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define QSPI_DEVICE_ID XPAR_XQSPIPS_0_DEVICE_ID
/*
* The following constants define the commands which may be sent to the FLASH
* device.
*/
#define WRITE_STATUS_CMD 0x01
#define WRITE_CMD 0x02
#define READ_CMD 0x03
#define WRITE_DISABLE_CMD 0x04
#define READ_STATUS_CMD 0x05
#define WRITE_ENABLE_CMD 0x06
#define FAST_READ_CMD 0x0B
#define DUAL_READ_CMD 0x3B
#define QUAD_READ_CMD 0x6B
#define BULK_ERASE_CMD 0xC7
#define SEC_ERASE_CMD 0xD8
#define READ_ID 0x9F
/*
* The following constants define the offsets within a FlashBuffer data
* type for each kind of data. Note that the read data offset is not the
* same as the write data because the QSPI driver is designed to allow full
* duplex transfers such that the number of bytes received is the number
* sent and received.
*/
#define COMMAND_OFFSET 0 /* FLASH instruction */
#define ADDRESS_1_OFFSET 1 /* MSB byte of address to read or write */
#define ADDRESS_2_OFFSET 2 /* Middle byte of address to read or write */
#define ADDRESS_3_OFFSET 3 /* LSB byte of address to read or write */
#define DATA_OFFSET 4 /* Start of Data for Read/Write */
#define DUMMY_OFFSET 4 /* Dummy byte offset for fast, dual and quad
reads */
#define DUMMY_SIZE 1 /* Number of dummy bytes for fast, dual and
quad reads */
#define RD_ID_SIZE 4 /* Read ID command + 3 bytes ID response */
#define BULK_ERASE_SIZE 1 /* Bulk Erase command size */
#define SEC_ERASE_SIZE 4 /* Sector Erase command + Sector address */
/*
* The following constants specify the extra bytes which are sent to the
* FLASH on the QSPI interface, that are not data, but control information
* which includes the command and address
*/
#define OVERHEAD_SIZE 4
/*
* The following constants specify the page size, sector size, and number of
* pages and sectors for the FLASH. The page size specifies a max number of
* bytes that can be written to the FLASH with a single transfer.
*/
#define SECTOR_SIZE 0x20000 /* half from each flash */
#define NUM_SECTORS 0x100
#define NUM_PAGES 0x10000
#define PAGE_SIZE 512 /* 256 bytes from each flash */
/*
* The following defines are for dual flash interface.
*/
#define LQSPI_CR_FAST_QUAD_READ 0x0000006B /* Fast Quad Read output */
#define LQSPI_CR_1_DUMMY_BYTE 0x00000100 /* 1 Dummy Byte between
address and return data */
#define DUAL_QSPI_CONFIG_WRITE (XQSPIPS_LQSPI_CR_TWO_MEM_MASK | \
XQSPIPS_LQSPI_CR_SEP_BUS_MASK | \
LQSPI_CR_1_DUMMY_BYTE | \
LQSPI_CR_FAST_QUAD_READ)
#define DUAL_QSPI_CONFIG_QUAD_READ (XQSPIPS_LQSPI_CR_LINEAR_MASK | \
XQSPIPS_LQSPI_CR_TWO_MEM_MASK | \
XQSPIPS_LQSPI_CR_SEP_BUS_MASK | \
LQSPI_CR_1_DUMMY_BYTE | \
LQSPI_CR_FAST_QUAD_READ)
/*
* Number of flash pages to be written.
*/
#define PAGE_COUNT 32
/*
* Flash address to which data is ot be written.
*/
#define TEST_ADDRESS 0x0000
#define UNIQUE_VALUE 0x3
/*
* The following constants specify the max amount of data and the size of the
* the buffer required to hold the data and overhead to transfer the data to
* and from the FLASH.
*/
#define MAX_DATA PAGE_COUNT * PAGE_SIZE
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
void FlashErase(XQspiPs *QspiPtr, u32 Address, u32 ByteCount);
void FlashWrite(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command);
void FlashRead(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command);
int LinearQspiFlashExample(XQspiPs *QspiInstancePtr, u16 QspiDeviceId);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XQspiPs QspiInstance;
/*
* The following variable allows a test value to be added to the values that
* are written to the FLASH such that unique values can be generated to
* guarantee the writes to the FLASH were successful
*/
int Test = 0x2;
/*
* The following variables are used to read and write to the flash and they
* are global to avoid having large buffers on the stack
*/
u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE];
u8 WriteBuffer[PAGE_SIZE + DATA_OFFSET];
/*****************************************************************************/
/**
*
* Main function to call the QSPI Flash example.
*
* @param None
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main(void)
{
int Status;
xil_printf("Linear QSPI Dual FLASH Example Test \r\n");
/*
* Run the Qspi Interrupt example.
*/
Status = LinearQspiFlashExample(&QspiInstance, QSPI_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("Linear QSPI Dual FLASH Example Test Failed\r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran Linear QSPI Dual FLASH Example Test\r\n");
return XST_SUCCESS;
}
/*****************************************************************************
*
* The purpose of this function is to illustrate how to use the XQspiPs
* device driver in Linear mode. This function writes data to the serial
* FLASH in QSPI mode and reads data in Linear QSPI mode.
*
* @param None.
*
* @return XST_SUCCESS if successful, else XST_FAILURE.
*
* @note None.
*
*****************************************************************************/
int LinearQspiFlashExample(XQspiPs *QspiInstancePtr, u16 QspiDeviceId)
{
int Status;
u8 UniqueValue;
int Count;
int Page;
XQspiPs_Config *QspiConfig;
/*
* Initialize the QSPI driver so that it's ready to use
*/
QspiConfig = XQspiPs_LookupConfig(QspiDeviceId);
if (NULL == QspiConfig) {
return XST_FAILURE;
}
Status = XQspiPs_CfgInitialize(QspiInstancePtr, QspiConfig,
QspiConfig->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform a self-test to check hardware build
*/
Status = XQspiPs_SelfTest(QspiInstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable two flash memories on seperate buses
*/
XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_QSPI_CONFIG_WRITE);
/*
* Set the QSPI device as a master and enable manual CS, manual start
* and flash interface mode options and drive HOLD_B pin high.
*/
XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_FORCE_SSELECT_OPTION |
XQSPIPS_MANUAL_START_OPTION |
XQSPIPS_HOLD_B_DRIVE_OPTION);
XQspiPs_SetClkPrescaler(QspiInstancePtr, XQSPIPS_CLK_PRESCALE_8);
/*
* Initialize the write buffer for a pattern to write to the FLASH
* and the read buffer to zero so it can be verified after the read, the
* test value that is added to the unique value allows the value to be
* changed in a debug environment to guarantee
*/
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE;
Count++, UniqueValue++) {
WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue + Test);
}
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
/*
* Assert the FLASH chip select.
*/
XQspiPs_SetSlaveSelect(QspiInstancePtr);
/*
* Erase the flash sectors
*/
FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA);
/*
* Write data to the two flash memories on seperate buses, starting from
* TEST_ADDRESS. This is same as writing to a single flash memory. The
* LQSPI controller takes care of splitting the data words and writing
* them to the two flash memories. The user needs to take care of the
* address translation
*/
for (Page = 0; Page < PAGE_COUNT; Page++) {
FlashWrite(QspiInstancePtr, ((Page * PAGE_SIZE) +
TEST_ADDRESS) / 2, PAGE_SIZE, WRITE_CMD);
}
/*
* Read from the two flash memories on seperate buses in LQSPI mode.
*/
XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_LQSPI_MODE_OPTION |
XQSPIPS_HOLD_B_DRIVE_OPTION);
XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_QSPI_CONFIG_QUAD_READ);
Status = XQspiPs_LqspiRead(QspiInstancePtr, ReadBuffer, TEST_ADDRESS,
MAX_DATA);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (ReadBuffer[Count] != WriteBuffer[DATA_OFFSET +
(Count % PAGE_SIZE)]) {
return XST_FAILURE;
}
}
/*
* Set the QSPI device as a master and enable manual CS, manual start
* and flash interface mode options and drive HOLD_B pin high.
*/
XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_FORCE_SSELECT_OPTION |
XQSPIPS_HOLD_B_DRIVE_OPTION);
/*
* Initialize the write buffer for a pattern to write to the FLASH
* and the read buffer to zero so it can be verified after the read, the
* test value that is added to the unique value allows the value to be
* changed in a debug environment to guarantee
*/
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE;
Count++, UniqueValue++) {
WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue + Test);
}
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
/*
* Erase the flash sectors
*/
FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA);
/*
* Write data to the two flash memories on seperate buses, starting from
* TEST_ADDRESS. This is same as writing to a single flash memory. The
* LQSPI controller takes care of splitting the data words and writing
* them to the two flash memories. The user needs to take care of the
* address translation
*/
for (Page = 0; Page < PAGE_COUNT; Page++) {
FlashWrite(QspiInstancePtr, ((Page * PAGE_SIZE) +
TEST_ADDRESS) / 2, PAGE_SIZE, WRITE_CMD);
}
/*
* Read from the two flash memories on seperate buses in LQSPI mode.
*/
XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_LQSPI_MODE_OPTION |
XQSPIPS_HOLD_B_DRIVE_OPTION);
XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_QSPI_CONFIG_QUAD_READ);
Status = XQspiPs_LqspiRead(QspiInstancePtr, ReadBuffer, TEST_ADDRESS,
MAX_DATA);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (ReadBuffer[Count] != WriteBuffer[DATA_OFFSET +
(Count % PAGE_SIZE)]) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/******************************************************************************
*
*
* This function writes to the serial FLASH connected to the QSPI interface.
* All the data put into the buffer must be in the same page of the device with
* page boundaries being on 256 byte boundaries.
*
* @param QspiPtr is a pointer to the QSPI driver component to use.
* @param Address contains the address to write data to in the FLASH.
* @param ByteCount contains the number of bytes to write.
* @param Command is the command used to write data to the flash. QSPI
* device supports only Page Program command to write data to the
* flash.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void FlashWrite(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command)
{
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */
u8 FlashStatus[2];
/*
* Send the write enable command to the FLASH so that it can be
* written to, this needs to be sent as a seperate transfer before
* the write
*/
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* Setup the write command with the specified address and data for the
* FLASH
*/
WriteBuffer[COMMAND_OFFSET] = Command;
WriteBuffer[ADDRESS_1_OFFSET] = (u8)((Address & 0xFF0000) >> 16);
WriteBuffer[ADDRESS_2_OFFSET] = (u8)((Address & 0xFF00) >> 8);
WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF);
/*
* Send the write command, address, and data to the FLASH to be
* written, no receive buffer is specified since there is nothing to
* receive
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
ByteCount + OVERHEAD_SIZE);
/*
* Wait for the write command to the FLASH to be completed, it takes
* some time for the data to be written
*/
while (1) {
/*
* Poll the status register of the FLASH to determine when it
* completes, by sending a read status command and receiving the
* status byte
*/
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd, FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop waiting,
* if a value of 0xFF in the status byte is read from the
* device and this loop never exits, the device slave select is
* possibly incorrect such that the device status is not being
* read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
}
/******************************************************************************
*
*
* This function erases the sectors in the serial FLASH connected to the
* QSPI interface.
*
* @param QspiPtr is a pointer to the QSPI driver component to use.
* @param Address contains the address of the first sector which needs to
* be erased.
* @param ByteCount contains the total size to be erased.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void FlashErase(XQspiPs *QspiPtr, u32 Address, u32 ByteCount)
{
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */
u8 FlashStatus[2];
u32 RealAddr;
int Sector;
/*
* If erase size is same as the total size of the flash, use bulk erase
* command
*/
if (ByteCount == (NUM_SECTORS * SECTOR_SIZE)) {
/*
* Send the write enable command to the FLASH so that it can be
* written to, this needs to be sent as a seperate transfer
* before the erase
*/
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* Setup the bulk erase command
*/
WriteBuffer[COMMAND_OFFSET] = BULK_ERASE_CMD;
/*
* Send the bulk erase command; no receive buffer is specified
* since there is nothing to receive
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
BULK_ERASE_SIZE);
/*
* Wait for the erase command to the FLASH to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,
FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop
* waiting; if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
return;
}
/*
* If the erase size is less than the total size of the flash, use
* sector erase command
*/
for (Sector = 0; Sector < ((ByteCount / SECTOR_SIZE) + 1); Sector++) {
/*
* Send the write enable command to the SEEPOM so that it can be
* written to, this needs to be sent as a seperate transfer
* before the write
*/
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* The effective sector address in each flash is the actual
* address / 2
*/
RealAddr = Address / 2;
/*
* Setup the write command with the specified address and data
* for the FLASH
*/
WriteBuffer[COMMAND_OFFSET] = SEC_ERASE_CMD;
WriteBuffer[ADDRESS_1_OFFSET] = (u8)(RealAddr >> 16);
WriteBuffer[ADDRESS_2_OFFSET] = (u8)(RealAddr >> 8);
WriteBuffer[ADDRESS_3_OFFSET] = (u8)(RealAddr & 0xFF);
/*
* Send the sector erase command and address; no receive buffer
* is specified since there is nothing to receive
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
SEC_ERASE_SIZE);
/*
* Wait for the sector erse command to the FLASH to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,
FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop
* waiting, if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
Address += SECTOR_SIZE;
}
}

View file

@ -0,0 +1,918 @@
/******************************************************************************
*
* Copyright (C) 2013 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xqspips_dual_flash_lqspi_example.c
*
* This file contains a design example using the QSPI driver (XQspiPs) in
* Linear QSPI mode, with two serial Flash devices in stacked mode.
* One flash s accessed at a time on a common bus by using separate selects.
* This example writes to the two flash memories in QSPI mode and reads
* the data back from the flash memories, in Linear QSPI mode.
* It is recommended to use Manual CS + Auto start for best performance.
*
* The hardware which this example runs on, must have a serial Flash (Numonyx
* N25Q, Winbond W25Q, or Spansion S25FL) for it to run. This example has been
* tested with the Winbond Serial Flash (W25Q128) and Spansion S25FL.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 2.02a hk 05/07/13 First release
*
*</pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* SDK generated parameters */
#include "xqspips.h" /* QSPI device driver */
#include "xil_printf.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define QSPI_DEVICE_ID XPAR_XQSPIPS_0_DEVICE_ID
/*
* The following constants define the commands which may be sent to the Flash
* device.
*/
#define WRITE_STATUS_CMD 0x01
#define WRITE_CMD 0x02
#define READ_CMD 0x03
#define WRITE_DISABLE_CMD 0x04
#define READ_STATUS_CMD 0x05
#define WRITE_ENABLE_CMD 0x06
#define FAST_READ_CMD 0x0B
#define DUAL_READ_CMD 0x3B
#define QUAD_READ_CMD 0x6B
#define BULK_ERASE_CMD 0xC7
#define SEC_ERASE_CMD 0xD8
#define READ_ID 0x9F
#define READ_CONFIG_CMD 0x35
#define WRITE_CONFIG_CMD 0x01
/*
* The following constants define the offsets within a FlashBuffer data
* type for each kind of data. Note that the read data offset is not the
* same as the write data because the QSPI driver is designed to allow full
* duplex transfers such that the number of bytes received is the number
* sent and received.
*/
#define COMMAND_OFFSET 0 /* Flash instruction */
#define ADDRESS_1_OFFSET 1 /* MSB byte of address to read or write */
#define ADDRESS_2_OFFSET 2 /* Middle byte of address to read or write */
#define ADDRESS_3_OFFSET 3 /* LSB byte of address to read or write */
#define DATA_OFFSET 4 /* Start of Data for Read/Write */
#define DUMMY_OFFSET 4 /* Dummy byte offset for fast, dual and quad
reads */
#define DUMMY_SIZE 1 /* Number of dummy bytes for fast, dual and
quad reads */
#define RD_ID_SIZE 4 /* Read ID command + 3 bytes ID response */
#define BULK_ERASE_SIZE 1 /* Bulk Erase command size */
#define SEC_ERASE_SIZE 4 /* Sector Erase command + Sector address */
#define RD_CFG_SIZE 2 /* 1 byte Configuration register + RD CFG command*/
#define WR_CFG_SIZE 3 /* WRR command + 1 byte each Status and Config Reg*/
/*
* The following constants specify the extra bytes which are sent to the
* Flash on the QSPI interface, that are not data, but control information
* which includes the command and address
*/
#define OVERHEAD_SIZE 4
/*
* The following constants specify the page size, sector size, and number of
* pages and sectors for the Flash. The page size specifies a max number of
* bytes that can be written to the Flash with a single transfer.
*/
#define SECTOR_SIZE 0x10000
#define NUM_SECTORS 0x200 /* 100 sectors from each flash */
#define NUM_PAGES 0x20000 /* 10000 pages from each flash */
#define PAGE_SIZE 256
/*
* The following defines are for dual flash stacked mode interface.
*/
#define LQSPI_CR_FAST_QUAD_READ 0x0000006B /* Fast Quad Read output */
#define LQSPI_CR_1_DUMMY_BYTE 0x00000100 /* 1 Dummy Byte between
address and return data */
#define LQSPI_CR_FAST_READ 0x0000000B /* Fast Read */
#define LQSPI_CR_NORMAL_READ 0x00000003 /* Fast Read */
#define DUAL_STACK_CONFIG_WRITE (XQSPIPS_LQSPI_CR_TWO_MEM_MASK | \
LQSPI_CR_1_DUMMY_BYTE | \
LQSPI_CR_FAST_QUAD_READ)
#define DUAL_STACK_CONFIG_QUAD_READ (XQSPIPS_LQSPI_CR_LINEAR_MASK | \
XQSPIPS_LQSPI_CR_TWO_MEM_MASK | \
LQSPI_CR_1_DUMMY_BYTE | \
LQSPI_CR_FAST_QUAD_READ)
/*
* Number of flash pages to be written.
*/
#define PAGE_COUNT 16
/*
* Flash address to which data is to be written.
*/
/*
* Test address defined so as to cover both flash devices
*/
#define TEST_ADDRESS 0xFFF800
#define UNIQUE_VALUE 0x0C
/*
* The following constants specify the max amount of data and the size of the
* the buffer required to hold the data and overhead to transfer the data to
* and from the Flash.
*/
#define MAX_DATA PAGE_COUNT * PAGE_SIZE
/*
* Base address of Flash1 and Flash2
*/
#define FLASH1BASE 0x0000000
#define FLASH2BASE 0x1000000
/*
* Mask for sector start address
*/
#define SECTORMASK 0xFFF0000
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
void FlashErase(XQspiPs *QspiPtr, u32 Address, u32 ByteCount);
void FlashWrite(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command);
int DualStackExample(XQspiPs *QspiInstancePtr, u16 QspiDeviceId);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XQspiPs QspiInstance;
/*
* The following variable allows a test value to be added to the values that
* are written to the Flash such that unique values can be generated to
* guarantee the writes to the Flash were successful
*/
int Test = 2;
/*
* The following variables are used to read and write to the flash and they
* are global to avoid having large buffers on the stack
*/
u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE];
u8 WriteBuffer[PAGE_SIZE + DATA_OFFSET];
/*****************************************************************************/
/**
*
* Main function to call the QSPI Dual Stack example.
*
* @param None
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main(void)
{
int Status;
xil_printf("QSPI Dual Stack Example Test \r\n");
/*
* Run the QSPI Dual Stack example.
*/
Status = DualStackExample(&QspiInstance, QSPI_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("QSPI Dual Stack Example Test Failed\r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran QSPI Dual Stack Example Test\r\n");
return XST_SUCCESS;
}
/*****************************************************************************
*
* The purpose of this function is to illustrate how to use the XQspiPs
* device driver with two Flash devices in Stacked mode.
* This function writes data to the serial Flash in QSPI mode and
* reads data in Linear QSPI mode.
*
* @param None.
*
* @return XST_SUCCESS if successful, else XST_FAILURE.
*
* @note None.
*
*****************************************************************************/
int DualStackExample(XQspiPs *QspiInstancePtr, u16 QspiDeviceId)
{
int Status;
u8 UniqueValue;
int Count;
int Page;
XQspiPs_Config *QspiConfig;
/*
* Initialize the QSPI driver so that it's ready to use
*/
QspiConfig = XQspiPs_LookupConfig(QspiDeviceId);
if (NULL == QspiConfig) {
return XST_FAILURE;
}
Status = XQspiPs_CfgInitialize(QspiInstancePtr, QspiConfig,
QspiConfig->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform a self-test to check hardware build
*/
Status = XQspiPs_SelfTest(QspiInstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Check if two flash devices are connected in stacked mode
*/
if(QspiConfig->ConnectionMode != XQSPIPS_CONNECTION_MODE_STACKED) {
xil_printf("QSPI not connected in Stacked Configuration \n");
return XST_FAILURE;
}
XQspiPs_SetClkPrescaler(QspiInstancePtr, XQSPIPS_CLK_PRESCALE_8);
/*
* Set the QSPI device as a master and enable manual CS, manual start
* and flash interface mode options and drive HOLD_B pin high.
*/
XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_FORCE_SSELECT_OPTION |
XQSPIPS_MANUAL_START_OPTION |
XQSPIPS_HOLD_B_DRIVE_OPTION);
/*
* Enable two flash memories, shared bus (NOT separate bus0,
* L_PAGE selected by default
*/
XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_STACK_CONFIG_WRITE);
/*
* Assert the Flash chip select.
*/
XQspiPs_SetSlaveSelect(QspiInstancePtr);
/*
* Initialize the write buffer for a pattern to write to the Flash
* and the read buffer to zero so it can be verified after the read, the
* test value that is added to the unique value allows the value to be
* changed in a debug environment to guarantee
*/
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE;
Count++, UniqueValue++) {
WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue + Test);
}
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
/*
* Erase the flash sectors
*/
FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA);
/*
* The two stacked 16MB memories are equivalent to one continuous 32MB.
* Write data to the two flash memories on the same bus one at a time,
* starting from TEST_ADDRESS. Flash_Write and Flash_Erase functions
* will select the lower or upper memory based on the address.
*/
for (Page = 0; Page < PAGE_COUNT; Page++) {
FlashWrite(QspiInstancePtr, ((Page * PAGE_SIZE) +
TEST_ADDRESS), PAGE_SIZE, WRITE_CMD);
}
/*
* Read from the two flash memories one after the other using
* LQSPI mode. The LQSPI controller takes care of selecting
* the lower or upper memory based on address bit 25.
*/
XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_LQSPI_MODE_OPTION |
XQSPIPS_HOLD_B_DRIVE_OPTION);
XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_STACK_CONFIG_QUAD_READ);
Status = XQspiPs_LqspiRead(QspiInstancePtr, ReadBuffer, TEST_ADDRESS,
MAX_DATA);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (ReadBuffer[Count] != (u8)(UniqueValue + Test)) {
return XST_FAILURE;
}
}
/*
* Set the QSPI device as a master and enable manual CS, manual start
* and flash interface mode options and drive HOLD_B pin high.
*/
XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_FORCE_SSELECT_OPTION |
XQSPIPS_HOLD_B_DRIVE_OPTION);
/*
* Initialize the write buffer for a pattern to write to the Flash
* and the read buffer to zero so it can be verified after the read, the
* test value that is added to the unique value allows the value to be
* changed in a debug environment to guarantee
*/
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE;
Count++, UniqueValue++) {
WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue + Test);
}
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
/*
* Erase the flash sectors
*/
FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA);
/*
* The two stacked 16MB memories are equivalent to one continuous 32MB.
* Write data to the two flash memories on the same bus one at a time,
* starting from TEST_ADDRESS. Flash_Write and Flash_Erase functions
* will select the lower or upper memory based on the address.
*/
for (Page = 0; Page < PAGE_COUNT; Page++) {
FlashWrite(QspiInstancePtr, ((Page * PAGE_SIZE) +
TEST_ADDRESS), PAGE_SIZE, WRITE_CMD);
}
/*
* Read from the two flash memories one after the other using
* LQSPI mode. The LQSPI controller takes care of selecting
* the lower or upper memory based on address bit 25.
*/
XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_LQSPI_MODE_OPTION |
XQSPIPS_HOLD_B_DRIVE_OPTION);
XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_STACK_CONFIG_QUAD_READ);
Status = XQspiPs_LqspiRead(QspiInstancePtr, ReadBuffer, TEST_ADDRESS,
MAX_DATA);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (ReadBuffer[Count] != (u8)(UniqueValue + Test)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/******************************************************************************
*
*
* This function writes to the serial Flash connected to the QSPI interface.
* All the data put into the buffer must be in the same page of the device with
* page boundaries being on 256 byte boundaries.
*
* @param QspiPtr is a pointer to the QSPI driver component to use.
* @param Address contains the address to write data to in the Flash.
* @param ByteCount contains the number of bytes to write.
* @param Command is the command used to write data to the flash. QSPI
* device supports only Page Program command to write data to the
* flash.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void FlashWrite(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command)
{
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* Must send 2 bytes */
u8 FlashStatus[2];
u32 LqspiCr;
u32 RealAddr;
/*
* Get the current LQSPI configuration register value
*/
LqspiCr = XQspiPs_GetLqspiConfigReg(QspiPtr);
/* Select lower or upper Flash based on address */
if(Address & FLASH2BASE) {
/*
* Set selection to U_PAGE
*/
XQspiPs_SetLqspiConfigReg(QspiPtr,
LqspiCr | XQSPIPS_LQSPI_CR_U_PAGE_MASK);
/*
* Subtract 16MB when accessing second flash
*/
RealAddr = Address & (~FLASH2BASE);
}else{
/*
* Set selection to L_PAGE
*/
XQspiPs_SetLqspiConfigReg(QspiPtr,
LqspiCr & (~XQSPIPS_LQSPI_CR_U_PAGE_MASK));
RealAddr = Address;
}
/*
* Assert the Flash chip select.
*/
XQspiPs_SetSlaveSelect(QspiPtr);
/*
* Send the write enable command to the Flash so that it can be
* written to, this needs to be sent as a separate transfer before
* the write
*/
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* Setup the write command with the specified address and data for the
* Flash
*/
WriteBuffer[COMMAND_OFFSET] = Command;
WriteBuffer[ADDRESS_1_OFFSET] = (u8)((RealAddr & 0xFF0000) >> 16);
WriteBuffer[ADDRESS_2_OFFSET] = (u8)((RealAddr & 0xFF00) >> 8);
WriteBuffer[ADDRESS_3_OFFSET] = (u8)(RealAddr & 0xFF);
/*
* Send the write command, address, and data to the Flash to be
* written, no receive buffer is specified since there is nothing to
* receive
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
ByteCount + OVERHEAD_SIZE);
/*
* Wait for the write command to the Flash to be completed, it takes
* some time for the data to be written
*/
while (1) {
/*
* Poll the status register of the Flash to determine when it
* completes, by sending a read status command and receiving the
* status byte
*/
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd, FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop waiting,
* if a value of 0xFF in the status byte is read from the
* device and this loop never exits, the device slave select is
* possibly incorrect such that the device status is not being
* read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
}
/******************************************************************************
*
*
* This function erases the sectors in the serial Flash connected to the
* QSPI interface.
*
* @param QspiPtr is a pointer to the QSPI driver component to use.
* @param Address contains the address of the first sector which needs to
* be erased.
* @param ByteCount contains the total size to be erased.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void FlashErase(XQspiPs *QspiPtr, u32 Address, u32 ByteCount)
{
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* Must send 2 bytes */
u8 FlashStatus[2];
u32 RealAddr;
int Sector;
u32 LqspiCr;
u32 NumSect;
/*
* If erase size is same as the total size of the two flash devices,
* use bulk erase command on both flash devices.
*/
if (ByteCount == (NUM_SECTORS * SECTOR_SIZE)) {
/*
* Get the current LQSPI configuration register value
*/
LqspiCr = XQspiPs_GetLqspiConfigReg(QspiPtr);
/*
* Set selection to L_PAGE
*/
XQspiPs_SetLqspiConfigReg(QspiPtr,
LqspiCr & (~XQSPIPS_LQSPI_CR_U_PAGE_MASK));
/*
* Assert the Flash chip select.
*/
XQspiPs_SetSlaveSelect(QspiPtr);
/*
* Send the write enable command to the Flash so that it can be
* written to, this needs to be sent as a separate transfer
* before the erase
*/
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* Setup the bulk erase command
*/
WriteBuffer[COMMAND_OFFSET] = BULK_ERASE_CMD;
/*
* Send the bulk erase command; no receive buffer is specified
* since there is nothing to receive
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
BULK_ERASE_SIZE);
/*
* Wait for the erase command to the Flash to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,
FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop
* waiting; if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
/*
* Get the current LQSPI configuration register value
*/
LqspiCr = XQspiPs_GetLqspiConfigReg(QspiPtr);
/*
* Set selection to U_PAGE
*/
XQspiPs_SetLqspiConfigReg(QspiPtr,
LqspiCr | XQSPIPS_LQSPI_CR_U_PAGE_MASK);
/*
* Assert the Flash chip select.
*/
XQspiPs_SetSlaveSelect(QspiPtr);
/*
* Send the write enable command to the Flash so that it can be
* written to, this needs to be sent as a separate transfer
* before the erase
*/
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* Setup the bulk erase command
*/
WriteBuffer[COMMAND_OFFSET] = BULK_ERASE_CMD;
/*
* Send the bulk erase command; no receive buffer is specified
* since there is nothing to receive
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
BULK_ERASE_SIZE);
/*
* Wait for the erase command to the Flash to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,
FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop
* waiting; if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
return;
}
/*
* If entire first flash needs + some sectors in the second flash
* need to be erased, then bulk erase first flash here and
* second flash sectors will be erased in the following loop.
*/
if ((Address == FLASH1BASE) &&
(ByteCount == (NUM_SECTORS * SECTOR_SIZE) / 2)) {
/*
* Get the current LQSPI configuration register value
*/
LqspiCr = XQspiPs_GetLqspiConfigReg(QspiPtr);
/*
* Set selection to L_PAGE
*/
XQspiPs_SetLqspiConfigReg(QspiPtr,
LqspiCr & (~XQSPIPS_LQSPI_CR_U_PAGE_MASK));
/*
* Assert the Flash chip select.
*/
XQspiPs_SetSlaveSelect(QspiPtr);
/*
* Send the write enable command to the Flash so that it can be
* written to, this needs to be sent as a separate transfer
* before the erase
*/
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* Setup the bulk erase command
*/
WriteBuffer[COMMAND_OFFSET] = BULK_ERASE_CMD;
/*
* Send the bulk erase command; no receive buffer is specified
* since there is nothing to receive
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
BULK_ERASE_SIZE);
/*
* Wait for the erase command to the Flash to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,
FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop
* waiting; if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
/*
* Increment address to second flash
*/
Address = FLASH2BASE;
}
/*
* If the erase size is less than the total size of the either flash,
* use sector erase command.
*/
/*
* Calculate no. of sectors to erase based on byte count
*/
NumSect = ByteCount/SECTOR_SIZE + 1;
/*
* If ByteCount to k sectors,
* but the address range spans from N to N+k+1 sectors, then
* increment no. of sectors to be erased
*/
if( ((Address + ByteCount) & SECTORMASK) ==
((Address + (NumSect*SECTOR_SIZE)) & SECTORMASK) ) {
NumSect++;
}
/*
* Check condition - This is for the case when the byte count is
* less than a sector but the address range spreads over two sectors
*/
for (Sector = 0; Sector < NumSect; Sector++) {
/*
* Get the current LQSPI configuration register value
*/
LqspiCr = XQspiPs_GetLqspiConfigReg(QspiPtr);
/* Select lower or upper Flash based on sector address */
if(Address & FLASH2BASE) {
/*
* Set selection to U_PAGE
*/
XQspiPs_SetLqspiConfigReg(QspiPtr,
LqspiCr | XQSPIPS_LQSPI_CR_U_PAGE_MASK);
/*
* Subtract 16MB when accessing second flash
*/
RealAddr = Address & (~FLASH2BASE);
}else{
/*
* Set selection to L_PAGE
*/
XQspiPs_SetLqspiConfigReg(QspiPtr,
LqspiCr & (~XQSPIPS_LQSPI_CR_U_PAGE_MASK));
RealAddr = Address;
}
/*
* Assert the Flash chip select.
*/
XQspiPs_SetSlaveSelect(QspiPtr);
/*
* Send the write enable command to the SEEPOM so that it can be
* written to, this needs to be sent as a separate transfer
* before the write
*/
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* Setup the write command with the specified address and data
* for the Flash
*/
WriteBuffer[COMMAND_OFFSET] = SEC_ERASE_CMD;
WriteBuffer[ADDRESS_1_OFFSET] = (u8)(RealAddr >> 16);
WriteBuffer[ADDRESS_2_OFFSET] = (u8)(RealAddr >> 8);
WriteBuffer[ADDRESS_3_OFFSET] = (u8)(RealAddr & 0xFF);
/*
* Send the sector erase command and address; no receive buffer
* is specified since there is nothing to receive
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
SEC_ERASE_SIZE);
/*
* Wait for the sector erase command to the Flash to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,
FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop
* waiting, if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
Address += SECTOR_SIZE;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,644 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xqspips_flash_lqspi_example.c
*
*
* This file contains a design example using the QSPI driver (XQspiPs) in
* Linear QSPI mode with a serial FLASH device. The example writes to the flash
* in QSPI mode and reads it back in Linear QSPI mode. This examples performs
* some transfers in Auto mode and Manual start mode, to illustrate the modes
* available. It is recommended to use Manual CS + Auto start for
* best performance.
* The hardware which this example runs on, must have a serial FLASH (Numonyx
* N25Q, Winbond W25Q, or Spansion S25FL) for it to run. This example has been
* tested with the Numonyx Serial Flash (N25Q128).
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00 sdm 11/25/10 First release
* 2.00a kka 22/08/12 Updated the example as XQspiPs_PolledTransfer API has
* changed. Changed the prescalar to use divide by 8.
* The user can change the prescalar to a maximum of
* divide by 2 based on the reference clock in the
* system.
* Set the Holdb_dr bit in the configuration register using
* XQSPIPS_HOLD_B_DRIVE_OPTION. Setting this bit
* drives the HOLD bit of the QSPI controller.
* This is required for QSPI to be used in Non QSPI boot
* mode else there needs to be an external pullup on this
* line. See http://www.xilinx.com/support/answers/47596.htm
* 2.01a sg 02/03/13 Created a function FlashReadID.
*
*</pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* SDK generated parameters */
#include "xqspips.h" /* QSPI device driver */
#include "xil_printf.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define QSPI_DEVICE_ID XPAR_XQSPIPS_0_DEVICE_ID
/*
* The following constants define the commands which may be sent to the FLASH
* device.
*/
#define WRITE_STATUS_CMD 0x01
#define WRITE_CMD 0x02
#define READ_CMD 0x03
#define WRITE_DISABLE_CMD 0x04
#define READ_STATUS_CMD 0x05
#define WRITE_ENABLE_CMD 0x06
#define FAST_READ_CMD 0x0B
#define DUAL_READ_CMD 0x3B
#define QUAD_READ_CMD 0x6B
#define BULK_ERASE_CMD 0xC7
#define SEC_ERASE_CMD 0xD8
#define READ_ID 0x9F
/*
* The following constants define the offsets within a FlashBuffer data
* type for each kind of data. Note that the read data offset is not the
* same as the write data because the QSPI driver is designed to allow full
* duplex transfers such that the number of bytes received is the number
* sent and received.
*/
#define COMMAND_OFFSET 0 /* FLASH instruction */
#define ADDRESS_1_OFFSET 1 /* MSB byte of address to read or write */
#define ADDRESS_2_OFFSET 2 /* Middle byte of address to read or write */
#define ADDRESS_3_OFFSET 3 /* LSB byte of address to read or write */
#define DATA_OFFSET 4 /* Start of Data for Read/Write */
#define DUMMY_OFFSET 4 /* Dummy byte offset for fast, dual and quad
reads */
#define DUMMY_SIZE 1 /* Number of dummy bytes for fast, dual and
quad reads */
#define RD_ID_SIZE 4 /* Read ID command + 3 bytes ID response */
#define BULK_ERASE_SIZE 1 /* Bulk Erase command size */
#define SEC_ERASE_SIZE 4 /* Sector Erase command + Sector address */
/*
* The following constants specify the extra bytes which are sent to the
* FLASH on the QSPI interface, that are not data, but control information
* which includes the command and address
*/
#define OVERHEAD_SIZE 4
/*
* The following constants specify the page size, sector size, and number of
* pages and sectors for the FLASH. The page size specifies a max number of
* bytes that can be written to the FLASH with a single transfer.
*/
#define SECTOR_SIZE 0x10000
#define NUM_SECTORS 0x100
#define NUM_PAGES 0x10000
#define PAGE_SIZE 256
/*
* Number of flash pages to be written.
*/
#define PAGE_COUNT 16
/*
* Flash address to which data is ot be written.
*/
#define TEST_ADDRESS 0x00055000
#define UNIQUE_VALUE 0x05
/*
* The following constants specify the max amount of data and the size of the
* the buffer required to hold the data and overhead to transfer the data to
* and from the FLASH.
*/
#define MAX_DATA PAGE_COUNT * PAGE_SIZE
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
void FlashErase(XQspiPs *QspiPtr, u32 Address, u32 ByteCount);
void FlashWrite(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command);
int FlashReadID(void);
int LinearQspiFlashExample(XQspiPs *QspiInstancePtr, u16 QspiDeviceId);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XQspiPs QspiInstance;
/*
* The following variable allows a test value to be added to the values that
* are written to the FLASH such that unique values can be generated to
* guarantee the writes to the FLASH were successful
*/
int Test = 5;
/*
* The following variables are used to read and write to the flash and they
* are global to avoid having large buffers on the stack
*/
u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE];
u8 WriteBuffer[PAGE_SIZE + DATA_OFFSET];
/*****************************************************************************/
/**
*
* Main function to call the QSPI Flash example.
*
* @param None
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main(void)
{
int Status;
xil_printf("Linear QSPI FLASH Example Test \r\n");
/*
* Run the Qspi Interrupt example.
*/
Status = LinearQspiFlashExample(&QspiInstance, QSPI_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("Linear QSPI FLASH Example Test Failed\r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran Linear QSPI FLASH Example Test\r\n");
return XST_SUCCESS;
}
/*****************************************************************************
*
* The purpose of this function is to illustrate how to use the XQspiPs
* device driver in Linear mode. This function writes data to the serial
* FLASH in QSPI mode and reads data in Linear QSPI mode.
*
* @param None.
*
* @return XST_SUCCESS if successful, else XST_FAILURE.
*
* @note None.
*
*****************************************************************************/
int LinearQspiFlashExample(XQspiPs *QspiInstancePtr, u16 QspiDeviceId)
{
int Status;
u8 UniqueValue;
int Count;
int Page;
XQspiPs_Config *QspiConfig;
/*
* Initialize the QSPI driver so that it's ready to use
*/
QspiConfig = XQspiPs_LookupConfig(QspiDeviceId);
if (NULL == QspiConfig) {
return XST_FAILURE;
}
Status = XQspiPs_CfgInitialize(QspiInstancePtr, QspiConfig,
QspiConfig->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform a self-test to check hardware build
*/
Status = XQspiPs_SelfTest(QspiInstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Initialize the write buffer for a pattern to write to the FLASH
* and the read buffer to zero so it can be verified after the read, the
* test value that is added to the unique value allows the value to be
* changed in a debug environment to guarantee
*/
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE;
Count++, UniqueValue++) {
WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue + Test);
}
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
/*
* Set the prescaler for QSPI clock
*/
XQspiPs_SetClkPrescaler(QspiInstancePtr, XQSPIPS_CLK_PRESCALE_8);
/*
* Set Manual Start and Manual Chip select options and drive the
* HOLD_B high.
*/
XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_FORCE_SSELECT_OPTION |
XQSPIPS_MANUAL_START_OPTION |
XQSPIPS_HOLD_B_DRIVE_OPTION);
/*
* Assert the FLASH chip select.
*/
XQspiPs_SetSlaveSelect(QspiInstancePtr);
FlashReadID();
/*
* Erase the flash.
*/
FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA);
/*
* Write the data in the write buffer to the serial FLASH a page at a
* time, starting from TEST_ADDRESS
*/
for (Page = 0; Page < PAGE_COUNT; Page++) {
FlashWrite(QspiInstancePtr, (Page * PAGE_SIZE) + TEST_ADDRESS,
PAGE_SIZE, WRITE_CMD);
}
/*
* Read from the flash in LQSPI mode.
*/
XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_LQSPI_MODE_OPTION |
XQSPIPS_HOLD_B_DRIVE_OPTION);
Status = XQspiPs_LqspiRead(QspiInstancePtr, ReadBuffer, TEST_ADDRESS,
MAX_DATA);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (ReadBuffer[Count] != (u8)(UniqueValue + Test)) {
return XST_FAILURE;
}
}
/*
* Initialize the write buffer for a pattern to write to the FLASH
* and the read buffer to zero so it can be verified after the read, the
* test value that is added to the unique value allows the value to be
* changed in a debug environment to guarantee
*/
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE;
Count++, UniqueValue++) {
WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue + Test);
}
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
/*
* Set Auto Start and Manual Chip select options and drive the
* HOLD_B high.
*/
XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_FORCE_SSELECT_OPTION |
XQSPIPS_HOLD_B_DRIVE_OPTION);
/*
* Erase the flash.
*/
FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA);
/*
* Write the data in the write buffer to the serial FLASH a page at a
* time, starting from TEST_ADDRESS
*/
for (Page = 0; Page < PAGE_COUNT; Page++) {
FlashWrite(QspiInstancePtr, (Page * PAGE_SIZE) + TEST_ADDRESS,
PAGE_SIZE, WRITE_CMD);
}
/*
* Read from the flash in LQSPI mode.
*/
XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_LQSPI_MODE_OPTION |
XQSPIPS_HOLD_B_DRIVE_OPTION);
Status = XQspiPs_LqspiRead(QspiInstancePtr, ReadBuffer, TEST_ADDRESS,
MAX_DATA);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (ReadBuffer[Count] != (u8)(UniqueValue + Test)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/******************************************************************************
*
*
* This function writes to the serial FLASH connected to the QSPI interface.
* All the data put into the buffer must be in the same page of the device with
* page boundaries being on 256 byte boundaries.
*
* @param QspiPtr is a pointer to the QSPI driver component to use.
* @param Address contains the address to write data to in the FLASH.
* @param ByteCount contains the number of bytes to write.
* @param Command is the command used to write data to the flash. QSPI
* device supports only Page Program command to write data to the
* flash.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void FlashWrite(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command)
{
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */
u8 FlashStatus[2];
/*
* Send the write enable command to the FLASH so that it can be
* written to, this needs to be sent as a seperate transfer before
* the write
*/
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* Setup the write command with the specified address and data for the
* FLASH
*/
WriteBuffer[COMMAND_OFFSET] = Command;
WriteBuffer[ADDRESS_1_OFFSET] = (u8)((Address & 0xFF0000) >> 16);
WriteBuffer[ADDRESS_2_OFFSET] = (u8)((Address & 0xFF00) >> 8);
WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF);
/*
* Send the write command, address, and data to the FLASH to be
* written, no receive buffer is specified since there is nothing to
* receive
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
ByteCount + OVERHEAD_SIZE);
/*
* Wait for the write command to the FLASH to be completed, it takes
* some time for the data to be written
*/
while (1) {
/*
* Poll the status register of the FLASH to determine when it
* completes, by sending a read status command and receiving the
* status byte
*/
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd, FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop waiting,
* if a value of 0xFF in the status byte is read from the
* device and this loop never exits, the device slave select is
* possibly incorrect such that the device status is not being
* read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
}
/******************************************************************************
*
*
* This function erases the sectors in the serial FLASH connected to the
* QSPI interface.
*
* @param QspiPtr is a pointer to the QSPI driver component to use.
* @param Address contains the address of the first sector which needs to
* be erased.
* @param ByteCount contains the total size to be erased.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void FlashErase(XQspiPs *QspiPtr, u32 Address, u32 ByteCount)
{
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */
u8 FlashStatus[2];
int Sector;
/*
* If erase size is same as the total size of the flash, use bulk erase
* command
*/
if (ByteCount == (NUM_SECTORS * SECTOR_SIZE)) {
/*
* Send the write enable command to the FLASH so that it can be
* written to, this needs to be sent as a seperate transfer
* before the erase
*/
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* Setup the bulk erase command
*/
WriteBuffer[COMMAND_OFFSET] = BULK_ERASE_CMD;
/*
* Send the bulk erase command; no receive buffer is specified
* since there is nothing to receive
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
BULK_ERASE_SIZE);
/*
* Wait for the erase command to the FLASH to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,
FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop
* waiting; if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
return;
}
/*
* If the erase size is less than the total size of the flash, use
* sector erase command
*/
for (Sector = 0; Sector < ((ByteCount / SECTOR_SIZE) + 1); Sector++) {
/*
* Send the write enable command to the SEEPOM so that it can be
* written to, this needs to be sent as a seperate transfer
* before the write
*/
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* Setup the write command with the specified address and data
* for the FLASH
*/
WriteBuffer[COMMAND_OFFSET] = SEC_ERASE_CMD;
WriteBuffer[ADDRESS_1_OFFSET] = (u8)(Address >> 16);
WriteBuffer[ADDRESS_2_OFFSET] = (u8)(Address >> 8);
WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF);
/*
* Send the sector erase command and address; no receive buffer
* is specified since there is nothing to receive
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
SEC_ERASE_SIZE);
/*
* Wait for the sector erse command to the FLASH to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,
FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop
* waiting, if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
Address += SECTOR_SIZE;
}
}
/******************************************************************************
*
* This function reads serial FLASH ID connected to the SPI interface.
*
* @param None.
*
* @return XST_SUCCESS if read id, otherwise XST_FAILURE.
*
* @note None.
*
******************************************************************************/
int FlashReadID(void)
{
int Status;
/*
* Read ID in Auto mode.
*/
WriteBuffer[COMMAND_OFFSET] = READ_ID;
WriteBuffer[ADDRESS_1_OFFSET] = 0x23; /* 3 dummy bytes */
WriteBuffer[ADDRESS_2_OFFSET] = 0x08;
WriteBuffer[ADDRESS_3_OFFSET] = 0x09;
Status = XQspiPs_PolledTransfer(&QspiInstance, WriteBuffer, ReadBuffer,
RD_ID_SIZE);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
xil_printf("FlashID=0x%x 0x%x 0x%x\n\r", ReadBuffer[1], ReadBuffer[2],
ReadBuffer[3]);
return XST_SUCCESS;
}

View file

@ -0,0 +1,806 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xqspips_flash_polled_example.c
*
*
* This file contains a design example using the QSPI driver (XQspiPs) in
* polled mode with a serial FLASH device. This examples performs
* some transfers in Auto mode and Manual start mode, to illustrate the modes
* available. It is recommended to use Manual CS + Auto start for
* best performance.
* The hardware which this example runs on. must have a serial FLASH (Numonyx
* N25Q, Winbond W25Q, or Spansion S25FL) for it to run. This example has been
* tested with the Numonyx Serial Flash (N25Q128).
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00 sdm 11/25/10 First release
* 1.01 srt 06/12/12 Changed to meet frequency requirements of READ command
* for CR 663787
* 2.00a kka 22/08/12 Updated the example as XQspiPs_PolledTransfer API has
* changed. Changed the prescalar to use divide by 8.
* The user can change the prescalar to a maximum of
* divide by 2 based on the reference clock in the
* system.
* Set the Holdb_dr bit in the configuration register using
* XQSPIPS_HOLD_B_DRIVE_OPTION. Setting this bit
* drives the HOLD bit of the QSPI controller.
* This is required for QSPI to be used in Non QSPI boot
* mode else there needs to be an external pullup on this
* line.
* See http://www.xilinx.com/support/answers/47596.htm.
* 2.01a sg 02/03/13 Created a function FlashReadID. Removed multiple
* initialization using SetOptions.
*
*</pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* SDK generated parameters */
#include "xqspips.h" /* QSPI device driver */
#include "xil_printf.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define QSPI_DEVICE_ID XPAR_XQSPIPS_0_DEVICE_ID
/*
* The following constants define the commands which may be sent to the FLASH
* device.
*/
#define WRITE_STATUS_CMD 0x01
#define WRITE_CMD 0x02
#define READ_CMD 0x03
#define WRITE_DISABLE_CMD 0x04
#define READ_STATUS_CMD 0x05
#define WRITE_ENABLE_CMD 0x06
#define FAST_READ_CMD 0x0B
#define DUAL_READ_CMD 0x3B
#define QUAD_READ_CMD 0x6B
#define BULK_ERASE_CMD 0xC7
#define SEC_ERASE_CMD 0xD8
#define READ_ID 0x9F
/*
* The following constants define the offsets within a FlashBuffer data
* type for each kind of data. Note that the read data offset is not the
* same as the write data because the QSPI driver is designed to allow full
* duplex transfers such that the number of bytes received is the number
* sent and received.
*/
#define COMMAND_OFFSET 0 /* FLASH instruction */
#define ADDRESS_1_OFFSET 1 /* MSB byte of address to read or write */
#define ADDRESS_2_OFFSET 2 /* Middle byte of address to read or write */
#define ADDRESS_3_OFFSET 3 /* LSB byte of address to read or write */
#define DATA_OFFSET 4 /* Start of Data for Read/Write */
#define DUMMY_OFFSET 4 /* Dummy byte offset for fast, dual and quad
reads */
#define DUMMY_SIZE 1 /* Number of dummy bytes for fast, dual and
quad reads */
#define RD_ID_SIZE 4 /* Read ID command + 3 bytes ID response */
#define BULK_ERASE_SIZE 1 /* Bulk Erase command size */
#define SEC_ERASE_SIZE 4 /* Sector Erase command + Sector address */
/*
* The following constants specify the extra bytes which are sent to the
* FLASH on the QSPI interface, that are not data, but control information
* which includes the command and address
*/
#define OVERHEAD_SIZE 4
/*
* The following constants specify the page size, sector size, and number of
* pages and sectors for the FLASH. The page size specifies a max number of
* bytes that can be written to the FLASH with a single transfer.
*/
#define SECTOR_SIZE 0x10000
#define NUM_SECTORS 0x100
#define NUM_PAGES 0x10000
#define PAGE_SIZE 256
/*
* Number of flash pages to be written.
*/
#define PAGE_COUNT 16
/*
* Flash address to which data is ot be written.
*/
#define TEST_ADDRESS 0x00055000
#define UNIQUE_VALUE 0x05
/*
* The following constants specify the max amount of data and the size of the
* the buffer required to hold the data and overhead to transfer the data to
* and from the FLASH.
*/
#define MAX_DATA PAGE_COUNT * PAGE_SIZE
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
void FlashErase(XQspiPs *QspiPtr, u32 Address, u32 ByteCount);
void FlashWrite(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command);
void FlashRead(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command);
int FlashReadID(void);
int QspiFlashPolledExample(XQspiPs *QspiInstancePtr, u16 QspiDeviceId);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XQspiPs QspiInstance;
/*
* The following variable allows a test value to be added to the values that
* are written to the FLASH such that unique values can be generated to
* guarantee the writes to the FLASH were successful
*/
int Test = 5;
/*
* The following variables are used to read and write to the flash and they
* are global to avoid having large buffers on the stack
*/
u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE];
u8 WriteBuffer[PAGE_SIZE + DATA_OFFSET];
/*****************************************************************************/
/**
*
* Main function to call the QSPI Flash example.
*
* @param None
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main(void)
{
int Status;
xil_printf("QSPI FLASH Polled Example Test \r\n");
/*
* Run the Qspi Interrupt example.
*/
Status = QspiFlashPolledExample(&QspiInstance, QSPI_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("QSPI FLASH Polled Example Test Failed\r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran QSPI FLASH Polled Example Test\r\n");
return XST_SUCCESS;
}
/*****************************************************************************
*
* The purpose of this function is to illustrate how to use the XQspiPs
* device driver in polled mode. This function writes and reads data
* from a serial FLASH.
*
* @param None.
*
* @return XST_SUCCESS if successful, else XST_FAILURE.
*
* @note None.
*
*****************************************************************************/
int QspiFlashPolledExample(XQspiPs *QspiInstancePtr, u16 QspiDeviceId)
{
int Status;
u8 *BufferPtr;
u8 UniqueValue;
int Count;
int Page;
XQspiPs_Config *QspiConfig;
/*
* Initialize the QSPI driver so that it's ready to use
*/
QspiConfig = XQspiPs_LookupConfig(QspiDeviceId);
if (NULL == QspiConfig) {
return XST_FAILURE;
}
Status = XQspiPs_CfgInitialize(QspiInstancePtr, QspiConfig,
QspiConfig->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform a self-test to check hardware build
*/
Status = XQspiPs_SelfTest(QspiInstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Initialize the write buffer for a pattern to write to the FLASH
* and the read buffer to zero so it can be verified after the read,
* the test value that is added to the unique value allows the value
* to be changed in a debug environment to guarantee
*/
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE;
Count++, UniqueValue++) {
WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue + Test);
}
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
/*
* Set Manual Start and Manual Chip select options and drive HOLD_B
* pin high.
*/
XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_MANUAL_START_OPTION |
XQSPIPS_FORCE_SSELECT_OPTION |
XQSPIPS_HOLD_B_DRIVE_OPTION);
/*
* Set the prescaler for QSPI clock
*/
XQspiPs_SetClkPrescaler(QspiInstancePtr, XQSPIPS_CLK_PRESCALE_8);
/*
* Assert the FLASH chip select.
*/
XQspiPs_SetSlaveSelect(QspiInstancePtr);
FlashReadID();
/*
* Erase the flash.
*/
FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA);
/*
* Write the data in the write buffer to the serial FLASH a page at a
* time, starting from TEST_ADDRESS
*/
for (Page = 0; Page < PAGE_COUNT; Page++) {
FlashWrite(QspiInstancePtr, (Page * PAGE_SIZE) + TEST_ADDRESS,
PAGE_SIZE, WRITE_CMD);
}
/*
* Read the contents of the FLASH from TEST_ADDRESS, using Normal Read
* command. Change the prescaler as the READ command operates at a
* lower frequency.
*/
FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, READ_CMD);
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = &ReadBuffer[DATA_OFFSET];
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue + Test)) {
return XST_FAILURE;
}
}
/*
* Read the contents of the FLASH from TEST_ADDRESS, using Fast Read
* command
*/
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, FAST_READ_CMD);
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = &ReadBuffer[DATA_OFFSET + DUMMY_SIZE];
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue + Test)) {
return XST_FAILURE;
}
}
/*
* Read the contents of the FLASH from TEST_ADDRESS, using Dual Read
* command
*/
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, DUAL_READ_CMD);
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = &ReadBuffer[DATA_OFFSET + DUMMY_SIZE];
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue + Test)) {
return XST_FAILURE;
}
}
/*
* Read the contents of the FLASH from TEST_ADDRESS, using Quad Read
* command
*/
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, QUAD_READ_CMD);
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = &ReadBuffer[DATA_OFFSET + DUMMY_SIZE];
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue + Test)) {
return XST_FAILURE;
}
}
/*
* Initialize the write buffer for a pattern to write to the FLASH
* and the read buffer to zero so it can be verified after the read,
* the test value that is added to the unique value allows the value
* to be changed in a debug environment to guarantee
*/
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE;
Count++, UniqueValue++) {
WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue + Test);
}
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
/*
* Set Auto Start and Manual Chip select options and drive HOLD_B
* pin high.
*/
XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_FORCE_SSELECT_OPTION |
XQSPIPS_HOLD_B_DRIVE_OPTION);
/*
* Erase the flash.
*/
FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA);
/*
* Write the data in the write buffer to the serial FLASH a page at a
* time, starting from TEST_ADDRESS
*/
for (Page = 0; Page < PAGE_COUNT; Page++) {
FlashWrite(QspiInstancePtr, (Page * PAGE_SIZE) + TEST_ADDRESS,
PAGE_SIZE, WRITE_CMD);
}
/*
* Read the contents of the FLASH from TEST_ADDRESS, using Normal Read
* command. Change the prescaler as the READ command operates at a
* lower frequency.
*/
FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, READ_CMD);
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = &ReadBuffer[DATA_OFFSET];
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue + Test)) {
return XST_FAILURE;
}
}
/*
* Read the contents of the FLASH from TEST_ADDRESS, using Fast Read
* command
*/
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, FAST_READ_CMD);
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = &ReadBuffer[DATA_OFFSET + DUMMY_SIZE];
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue + Test)) {
return XST_FAILURE;
}
}
/*
* Read the contents of the FLASH from TEST_ADDRESS, using Dual Read
* command
*/
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, DUAL_READ_CMD);
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = &ReadBuffer[DATA_OFFSET + DUMMY_SIZE];
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue + Test)) {
return XST_FAILURE;
}
}
/*
* Read the contents of the FLASH from TEST_ADDRESS, using Quad Read
* command
*/
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, QUAD_READ_CMD);
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = &ReadBuffer[DATA_OFFSET + DUMMY_SIZE];
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue + Test)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/******************************************************************************
*
*
* This function writes to the serial FLASH connected to the QSPI interface.
* All the data put into the buffer must be in the same page of the device with
* page boundaries being on 256 byte boundaries.
*
* @param QspiPtr is a pointer to the QSPI driver component to use.
* @param Address contains the address to write data to in the FLASH.
* @param ByteCount contains the number of bytes to write.
* @param Command is the command used to write data to the flash. QSPI
* device supports only Page Program command to write data to the
* flash.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void FlashWrite(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command)
{
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */
u8 FlashStatus[2];
/*
* Send the write enable command to the FLASH so that it can be
* written to, this needs to be sent as a seperate transfer before
* the write
*/
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* Setup the write command with the specified address and data for the
* FLASH
*/
WriteBuffer[COMMAND_OFFSET] = Command;
WriteBuffer[ADDRESS_1_OFFSET] = (u8)((Address & 0xFF0000) >> 16);
WriteBuffer[ADDRESS_2_OFFSET] = (u8)((Address & 0xFF00) >> 8);
WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF);
/*
* Send the write command, address, and data to the FLASH to be
* written, no receive buffer is specified since there is nothing to
* receive
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
ByteCount + OVERHEAD_SIZE);
/*
* Wait for the write command to the FLASH to be completed, it takes
* some time for the data to be written
*/
while (1) {
/*
* Poll the status register of the FLASH to determine when it
* completes, by sending a read status command and receiving the
* status byte
*/
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd, FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop waiting,
* if a value of 0xFF in the status byte is read from the
* device and this loop never exits, the device slave select is
* possibly incorrect such that the device status is not being
* read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
}
/******************************************************************************
*
* This function reads from the serial FLASH connected to the
* QSPI interface.
*
* @param QspiPtr is a pointer to the QSPI driver component to use.
* @param Address contains the address to read data from in the FLASH.
* @param ByteCount contains the number of bytes to read.
* @param Command is the command used to read data from the flash. QSPI
* device supports one of the Read, Fast Read, Dual Read and Fast
* Read commands to read data from the flash.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void FlashRead(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command)
{
/*
* Setup the write command with the specified address and data for the
* FLASH
*/
WriteBuffer[COMMAND_OFFSET] = Command;
WriteBuffer[ADDRESS_1_OFFSET] = (u8)((Address & 0xFF0000) >> 16);
WriteBuffer[ADDRESS_2_OFFSET] = (u8)((Address & 0xFF00) >> 8);
WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF);
if ((Command == FAST_READ_CMD) || (Command == DUAL_READ_CMD) ||
(Command == QUAD_READ_CMD)) {
ByteCount += DUMMY_SIZE;
}
/*
* Send the read command to the FLASH to read the specified number
* of bytes from the FLASH, send the read command and address and
* receive the specified number of bytes of data in the data buffer
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, ReadBuffer,
ByteCount + OVERHEAD_SIZE);
}
/******************************************************************************
*
*
* This function erases the sectors in the serial FLASH connected to the
* QSPI interface.
*
* @param QspiPtr is a pointer to the QSPI driver component to use.
* @param Address contains the address of the first sector which needs to
* be erased.
* @param ByteCount contains the total size to be erased.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void FlashErase(XQspiPs *QspiPtr, u32 Address, u32 ByteCount)
{
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */
u8 FlashStatus[2];
int Sector;
/*
* If erase size is same as the total size of the flash, use bulk erase
* command
*/
if (ByteCount == (NUM_SECTORS * SECTOR_SIZE)) {
/*
* Send the write enable command to the FLASH so that it can be
* written to, this needs to be sent as a seperate transfer
* before the erase
*/
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* Setup the bulk erase command
*/
WriteBuffer[COMMAND_OFFSET] = BULK_ERASE_CMD;
/*
* Send the bulk erase command; no receive buffer is specified
* since there is nothing to receive
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
BULK_ERASE_SIZE);
/*
* Wait for the erase command to the FLASH to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,
FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop
* waiting; if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
return;
}
/*
* If the erase size is less than the total size of the flash, use
* sector erase command
*/
for (Sector = 0; Sector < ((ByteCount / SECTOR_SIZE) + 1); Sector++) {
/*
* Send the write enable command to the SEEPOM so that it can be
* written to, this needs to be sent as a seperate transfer
* before the write
*/
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* Setup the write command with the specified address and data
* for the FLASH
*/
WriteBuffer[COMMAND_OFFSET] = SEC_ERASE_CMD;
WriteBuffer[ADDRESS_1_OFFSET] = (u8)(Address >> 16);
WriteBuffer[ADDRESS_2_OFFSET] = (u8)(Address >> 8);
WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF);
/*
* Send the sector erase command and address; no receive buffer
* is specified since there is nothing to receive
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
SEC_ERASE_SIZE);
/*
* Wait for the sector erse command to the FLASH to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,
FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop
* waiting, if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
Address += SECTOR_SIZE;
}
}
/******************************************************************************
*
* This function reads serial FLASH ID connected to the SPI interface.
*
* @param None.
*
* @return XST_SUCCESS if read id, otherwise XST_FAILURE.
*
* @note None.
*
******************************************************************************/
int FlashReadID(void)
{
int Status;
/*
* Read ID in Auto mode.
*/
WriteBuffer[COMMAND_OFFSET] = READ_ID;
WriteBuffer[ADDRESS_1_OFFSET] = 0x23; /* 3 dummy bytes */
WriteBuffer[ADDRESS_2_OFFSET] = 0x08;
WriteBuffer[ADDRESS_3_OFFSET] = 0x09;
Status = XQspiPs_PolledTransfer(&QspiInstance, WriteBuffer, ReadBuffer,
RD_ID_SIZE);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
xil_printf("FlashID=0x%x 0x%x 0x%x\n\r", ReadBuffer[1], ReadBuffer[2],
ReadBuffer[3]);
return XST_SUCCESS;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,157 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/******************************************************************************/
/**
* @file xqspips_selftest_example.c
*
* This file contains an example for using the QSPI Hardware, it does a simple
* hardware connection check.
*
* @note
*
* None
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------ -------- -----------------------------------------------
* 1.00 drg/jz 01/25/10 First release.
* </pre>
*
*******************************************************************************/
/***************************** Include Files **********************************/
#include "xparameters.h"
#include "xqspips.h"
#include "xil_printf.h"
/************************** Constant Definitions ******************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define QSPI_DEVICE_ID XPAR_XQSPIPS_0_DEVICE_ID
/**************************** Type Definitions ********************************/
/***************** Macros (Inline Functions) Definitions **********************/
/************************** Function Prototypes *******************************/
int QspiPsSelfTestExample(u16 DeviceId);
/************************** Variable Definitions ******************************/
XQspiPs Qspi; /* The instance of the QSPI device */
/******************************************************************************/
/**
* Main function to call the Qspi Selftest example.
*
* @param None
*
* @return XST_SUCCESS if successful, XST_FAILURE if unsuccessful
*
* @note None
*
*******************************************************************************/
#ifndef TESTAPP_GEN
int main(void)
{
int Status;
xil_printf("QSPI Selftest Example \r\n");
/*
* Call the example , specify the device ID that is generated in
* xparameters.h
*/
Status = QspiPsSelfTestExample(QSPI_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("QSPI Selftest Example Failed\r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran QSPI Selftest Example\r\n");
return XST_SUCCESS;
}
#endif
/*****************************************************************************/
/**
*
* This function does a selftest on the QSPI device and XQspiPs driver as an
* example. The purpose of this function is to illustrate the usage of the
* XQspiPs driver.
*
*
* @param DeviceId is the XPAR_<QSPIPS_instance>_DEVICE_ID value from
* xparameters.h
*
* @return XST_SUCCESS if successful, XST_FAILURE if unsuccessful
*
* @note None
*
****************************************************************************/
int QspiPsSelfTestExample(u16 DeviceId)
{
int Status;
XQspiPs_Config *QspiConfig;
/*
* Initialize the QSPI device.
*/
QspiConfig = XQspiPs_LookupConfig(DeviceId);
if (NULL == QspiConfig) {
return XST_FAILURE;
}
Status = XQspiPs_CfgInitialize(&Qspi, QspiConfig, QspiConfig->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform a self-test to check hardware build.
*/
Status = XQspiPs_SelfTest(&Qspi);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}

View file

@ -0,0 +1,40 @@
COMPILER=
ARCHIVER=
CP=cp
COMPILER_FLAGS=
EXTRA_COMPILER_FLAGS=
LIB=libxil.a
CC_FLAGS = $(COMPILER_FLAGS)
ECC_FLAGS = $(EXTRA_COMPILER_FLAGS)
RELEASEDIR=../../../lib
INCLUDEDIR=../../../include
INCLUDES=-I./. -I${INCLUDEDIR}
OUTS = *.o
LIBSOURCES:=*.c
INCLUDEFILES:=*.h
OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c)))
libs: banner xqspips_libs clean
%.o: %.c
${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $<
banner:
echo "Compiling qspips"
xqspips_libs: ${OBJECTS}
$(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS}
.PHONY: include
include: xqspips_includes
xqspips_includes:
${CP} ${INCLUDEFILES} ${INCLUDEDIR}
clean:
rm -rf ${OBJECTS}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,782 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xqspips.h
*
* This file contains the implementation of the XQspiPs driver. It supports only
* master mode. User documentation for the driver functions is contained in this
* file in the form of comment blocks at the front of each function.
*
* A QSPI device connects to an QSPI bus through a 4-wire serial interface.
* The QSPI bus is a full-duplex, synchronous bus that facilitates communication
* between one master and one slave. The device is always full-duplex,
* which means that for every byte sent, one is received, and vice-versa.
* The master controls the clock, so it can regulate when it wants to
* send or receive data. The slave is under control of the master, it must
* respond quickly since it has no control of the clock and must send/receive
* data as fast or as slow as the master does.
*
* <b> Linear Mode </b>
* The Linear Quad-SPI Controller extends the existing Quad-SPI Controller<EFBFBD>s
* functionality by adding a linear addressing scheme that allows the SPI flash
* memory subsystem to behave like a typical ROM device. The new feature hides
* the normal SPI protocol from a master reading from the SPI flash memory. The
* feature improves both the user friendliness and the overall read memory
* throughput over that of the current Quad-SPI Controller by lessening the
* amount of software overheads required and by the use of the faster AXI
* interface.
*
* <b>Initialization & Configuration</b>
*
* The XQspiPs_Config structure is used by the driver to configure itself. This
* configuration structure is typically created by the tool-chain based on HW
* build properties.
*
* To support multiple runtime loading and initialization strategies employed by
* various operating systems, the driver instance can be initialized in the
* following way:
* - XQspiPs_LookupConfig(DeviceId) - Use the device identifier to find
* static configuration structure defined in xqspips_g.c. This is setup
* by the tools. For some operating systems the config structure will be
* initialized by the software and this call is not needed.
* - XQspiPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a
* configuration structure provided by the caller. If running in a system
* with address translation, the provided virtual memory base address
* replaces the physical address present in the configuration structure.
*
* <b>Multiple Masters</b>
*
* More than one master can exist, but arbitration is the responsibility of
* the higher layer software. The device driver does not perform any type of
* arbitration.
*
* <b>Modes of Operation</b>
*
* There are four modes to perform a data transfer and the selection of a mode
* is based on Chip Select(CS) and Start. These two options individually, can
* be controlled either by software(Manual) or hardware(Auto).
* - Auto CS: Chip select is automatically asserted as soon as the first word
* is written into the TXFIFO and de asserted when the TXFIFO becomes
* empty
* - Manual CS: Software must assert and de assert CS.
* - Auto Start: Data transmission starts as soon as there is data in the
* TXFIFO and stalls when the TXFIFO is empty
* - Manual Start: Software must start data transmission at the beginning of
* the transaction or whenever the TXFIFO has become empty
*
* The preferred combination is Manual CS and Auto Start.
* In this combination, the software asserts CS before loading any data into
* TXFIFO. In Auto Start mode, whenever data is in TXFIFO, controller sends it
* out until TXFIFO becomes empty. The software reads the RXFIFO whenever the
* data is available. If no further data, software disables CS.
*
* Risks/challenges of other combinations:
* - Manual CS and Manual Start: Manual Start bit should be set after each
* TXFIFO write otherwise there could be a race condition where the TXFIFO
* becomes empty before the new word is written. In that case the
* transmission stops.
* - Auto CS with Manual or Auto Start: It is very difficult for software to
* keep the TXFIFO filled. Whenever the TXFIFO runs empty, CS is de asserted.
* This results in a single transaction to be split into multiple pieces each
* with its own chip select. This will result in garbage data to be sent.
*
* <b>Interrupts</b>
*
* The user must connect the interrupt handler of the driver,
* XQspiPs_InterruptHandler, to an interrupt system such that it will be
* called when an interrupt occurs. This function does not save and restore
* the processor context such that the user must provide this processing.
*
* The driver handles the following interrupts:
* - Data Transmit Register/FIFO Underflow
* - Data Receive Register/FIFO Not Empty
* - Data Transmit Register/FIFO Overwater
* - Data Receive Register/FIFO Overrun
*
* The Data Transmit Register/FIFO Overwater interrupt -- indicates that the
* QSPI device has transmitted the data available to transmit, and now its data
* register and FIFO is ready to accept more data. The driver uses this
* interrupt to indicate progress while sending data. The driver may have
* more data to send, in which case the data transmit register and FIFO is
* filled for subsequent transmission. When this interrupt arrives and all
* the data has been sent, the driver invokes the status callback with a
* value of XST_SPI_TRANSFER_DONE to inform the upper layer software that
* all data has been sent.
*
* The Data Transmit Register/FIFO Underflow interrupt -- indicates that,
* as slave, the QSPI device was required to transmit but there was no data
* available to transmit in the transmit register (or FIFO). This may not
* be an error if the master is not expecting data. But in the case where
* the master is expecting data, this serves as a notification of such a
* condition. The driver reports this condition to the upper layer
* software through the status handler.
*
* The Data Receive Register/FIFO Overrun interrupt -- indicates that the QSPI
* device received data and subsequently dropped the data because the data
* receive register and FIFO was full. The driver reports this condition to the
* upper layer software through the status handler. This likely indicates a
* problem with the higher layer protocol, or a problem with the slave
* performance.
*
*
* <b>Polled Operation</b>
*
* Transfer in polled mode is supported through a separate interface function
* XQspiPs_PolledTransfer(). Unlike the transfer function in the interrupt mode,
* this function blocks until all data has been sent/received.
*
* <b>Device Busy</b>
*
* Some operations are disallowed when the device is busy. The driver tracks
* whether a device is busy. The device is considered busy when a data transfer
* request is outstanding, and is considered not busy only when that transfer
* completes (or is aborted with a mode fault error).
*
* <b>Device Configuration</b>
*
* The device can be configured in various ways during the FPGA implementation
* process. Configuration parameters are stored in the xqspips_g.c file or
* passed in via XQspiPs_CfgInitialize(). A table is defined where each entry
* contains configuration information for an QSPI device, including the base
* address for the device.
*
* <b>RTOS Independence</b>
*
* This driver is intended to be RTOS and processor independent. It works with
* physical addresses only. Any needs for dynamic memory management, threads or
* thread mutual exclusion, virtual memory, or cache control must be satisfied
* by the layer above this driver.
*
* NOTE: This driver was always tested with endianess set to little-endian.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00a sdm 11/25/10 First release, based on the PS SPI driver...
* 1.01a sdm 11/22/11 Added TCL file for generating QSPI parameters
* in xparameters.h
* 2.00a kka 07/25/12 Added a few register defines for CR 670297
* Removed code related to mode fault for CR 671468
* The XQspiPs_SetSlaveSelect has been modified to remove
* the argument of the slave select as the QSPI controller
* only supports one slave.
* XQspiPs_GetSlaveSelect API has been removed
* Added a flag ShiftReadData to the instance structure
*. and is used in the XQspiPs_GetReadData API.
* The ShiftReadData Flag indicates whether the data
* read from the Rx FIFO needs to be shifted
* in cases where the data is less than 4 bytes
* Removed the selection for the following options:
* Master mode (XQSPIPS_MASTER_OPTION) and
* Flash interface mode (XQSPIPS_FLASH_MODE_OPTION) option
* as the QSPI driver supports the Master mode
* and Flash Interface mode and doesnot support
* Slave mode or the legacy mode.
* Modified the XQspiPs_PolledTransfer and XQspiPs_Transfer
* APIs so that the last argument (IsInst) specifying whether
* it is instruction or data has been removed. The first byte
* in the SendBufPtr argument of these APIs specify the
* instruction to be sent to the Flash Device.
* This version of the driver fixes CRs 670197/663787/
* 670297/671468.
* Added the option for setting the Holdb_dr bit in the
* configuration options, XQSPIPS_HOLD_B_DRIVE_OPTION
* is the option to be used for setting this bit in the
* configuration register.
* The XQspiPs_PolledTransfer function has been updated
* to fill the data to fifo depth.
* 2.01a sg 02/03/13 Added flash opcodes for DUAL_IO_READ,QUAD_IO_READ.
* Added macros for Set/Get Rx Watermark. Changed QSPI
* Enable/Disable macro argument from BaseAddress to
* Instance Pointer. Added DelayNss argument to SetDelays
* and GetDelays API's.
* Created macros XQspiPs_IsManualStart and
* XQspiPs_IsManualChipSelect.
* Changed QSPI transfer logic for polled and interrupt
* modes to be based on filled tx fifo count and receive
* based on it. RXNEMPTY interrupt is not used.
* Added assertions to XQspiPs_LqspiRead function.
* SetDelays and GetDelays API's include DelayNss parameter.
* Added defines for DelayNss,Rx Watermark,Interrupts
* which need write to clear. Removed Read zeros mask from
* LQSPI Config register. Renamed Fixed burst error to
* data FSM error in LQSPI Status register.
*
* 2.02a hk 05/07/13 Added ConnectionMode to config structure.
* Corresponds to C_QSPI_MODE - 0:Single, 1:Stacked, 2:Parallel
* Added enable and disable to the XQspiPs_LqspiRead() function
* Removed XQspi_Reset() in Set_Options() function when
* LQSPI_MODE_OPTION is set.
* Added instructions for bank selection, die erase and
* flag status register to the flash instruction table
* Handling for instructions not in flash instruction
* table added. Checking for Tx FIFO empty when switching from
* TXD1/2/3 to TXD0 added. If WRSR instruction is sent with
* byte count 3 (spansion), instruction size and TXD register
* changed accordingly. CR# 712502 and 703869.
* Added prefix to constant definitions for ConnectionMode
* Added (#ifdef linear base address) in the Linear read function.
* Changed XPAR_XQSPIPS_0_LINEAR_BASEADDR to
* XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR in
* XQspiPs_LqspiRead function. Fix for CR#718141.
*
* 2.03a hk 09/17/13 Modified polled and interrupt transfers to make use of
* thresholds. This is to improve performance.
* Added API's for QSPI reset and
* linear mode initialization for boot.
* Added RX and TX threshold reset to one in XQspiPs_Abort.
* Added RX threshold reset(1) after transfer in polled and
* interrupt transfers. Made changes to make sure threshold
* change is done only when no transfer is in progress.
* Updated linear init API for parallel and stacked modes.
* CR#737760.
* 3.1 hk 08/13/14 When writing to the configuration register, set/reset
* required bits leaving reserved bits untouched. CR# 796813.
*
* </pre>
*
******************************************************************************/
#ifndef XQSPIPS_H /* prevent circular inclusions */
#define XQSPIPS_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
#include "xstatus.h"
#include "xqspips_hw.h"
#include <string.h>
/************************** Constant Definitions *****************************/
/** @name Configuration options
*
* The following options are supported to enable/disable certain features of
* an QSPI device. Each of the options is a bit mask, so more than one may be
* specified.
*
*
* The <b>Active Low Clock option</b> configures the device's clock polarity.
* Setting this option means the clock is active low and the SCK signal idles
* high. By default, the clock is active high and SCK idles low.
*
* The <b>Clock Phase option</b> configures the QSPI device for one of two
* transfer formats. A clock phase of 0, the default, means data is valid on
* the first SCK edge (rising or falling) after the slave select (SS) signal
* has been asserted. A clock phase of 1 means data is valid on the second SCK
* edge (rising or falling) after SS has been asserted.
*
*
* The <b>QSPI Force Slave Select option</b> is used to enable manual control of
* the slave select signal.
* 0: The SPI_SS signal is controlled by the QSPI controller during
* transfers. (Default)
* 1: The SPI_SS signal is forced active (driven low) regardless of any
* transfers in progress.
*
* NOTE: The driver will handle setting and clearing the Slave Select when
* the user sets the "FORCE_SSELECT_OPTION". Using this option will allow the
* QSPI clock to be set to a faster speed. If the QSPI clock is too fast, the
* processor cannot empty and refill the FIFOs before the TX FIFO is empty
* When the QSPI hardware is controlling the Slave Select signals, this
* will cause slave to be de-selected and terminate the transfer.
*
* The <b>Manual Start option</b> is used to enable manual control of
* the Start command to perform data transfer.
* 0: The Start command is controlled by the QSPI controller during
* transfers(Default). Data transmission starts as soon as there is data in
* the TXFIFO and stalls when the TXFIFO is empty
* 1: The Start command must be issued by software to perform data transfer.
* Bit 15 of Configuration register is used to issue Start command. This bit
* must be set whenever TXFIFO is filled with new data.
*
* NOTE: The driver will set the Manual Start Enable bit in Configuration
* Register, if Manual Start option is selected. Software will issue
* Manual Start command whenever TXFIFO is filled with data. When there is
* no further data, driver will clear the Manual Start Enable bit.
*
* @{
*/
#define XQSPIPS_CLK_ACTIVE_LOW_OPTION 0x2 /**< Active Low Clock option */
#define XQSPIPS_CLK_PHASE_1_OPTION 0x4 /**< Clock Phase one option */
#define XQSPIPS_FORCE_SSELECT_OPTION 0x10 /**< Force Slave Select */
#define XQSPIPS_MANUAL_START_OPTION 0x20 /**< Manual Start enable */
#define XQSPIPS_LQSPI_MODE_OPTION 0x80 /**< Linear QPSI mode */
#define XQSPIPS_HOLD_B_DRIVE_OPTION 0x100 /**< Drive HOLD_B Pin */
/*@}*/
/** @name QSPI Clock Prescaler options
* The QSPI Clock Prescaler Configuration bits are used to program master mode
* bit rate. The bit rate can be programmed in divide-by-two decrements from
* pclk/2 to pclk/256.
*
* @{
*/
#define XQSPIPS_CLK_PRESCALE_2 0x00 /**< PCLK/2 Prescaler */
#define XQSPIPS_CLK_PRESCALE_4 0x01 /**< PCLK/4 Prescaler */
#define XQSPIPS_CLK_PRESCALE_8 0x02 /**< PCLK/8 Prescaler */
#define XQSPIPS_CLK_PRESCALE_16 0x03 /**< PCLK/16 Prescaler */
#define XQSPIPS_CLK_PRESCALE_32 0x04 /**< PCLK/32 Prescaler */
#define XQSPIPS_CLK_PRESCALE_64 0x05 /**< PCLK/64 Prescaler */
#define XQSPIPS_CLK_PRESCALE_128 0x06 /**< PCLK/128 Prescaler */
#define XQSPIPS_CLK_PRESCALE_256 0x07 /**< PCLK/256 Prescaler */
/*@}*/
/** @name Callback events
*
* These constants specify the handler events that are passed to
* a handler from the driver. These constants are not bit masks such that
* only one will be passed at a time to the handler.
*
* @{
*/
#define XQSPIPS_EVENT_TRANSFER_DONE 2 /**< Transfer done */
#define XQSPIPS_EVENT_TRANSMIT_UNDERRUN 3 /**< TX FIFO empty */
#define XQSPIPS_EVENT_RECEIVE_OVERRUN 4 /**< Receive data loss because
RX FIFO full */
/*@}*/
/** @name Flash commands
*
* The following constants define most of the commands supported by flash
* devices. Users can add more commands supported by the flash devices
*
* @{
*/
#define XQSPIPS_FLASH_OPCODE_WRSR 0x01 /* Write status register */
#define XQSPIPS_FLASH_OPCODE_PP 0x02 /* Page program */
#define XQSPIPS_FLASH_OPCODE_NORM_READ 0x03 /* Normal read data bytes */
#define XQSPIPS_FLASH_OPCODE_WRDS 0x04 /* Write disable */
#define XQSPIPS_FLASH_OPCODE_RDSR1 0x05 /* Read status register 1 */
#define XQSPIPS_FLASH_OPCODE_WREN 0x06 /* Write enable */
#define XQSPIPS_FLASH_OPCODE_FAST_READ 0x0B /* Fast read data bytes */
#define XQSPIPS_FLASH_OPCODE_BE_4K 0x20 /* Erase 4KiB block */
#define XQSPIPS_FLASH_OPCODE_RDSR2 0x35 /* Read status register 2 */
#define XQSPIPS_FLASH_OPCODE_DUAL_READ 0x3B /* Dual read data bytes */
#define XQSPIPS_FLASH_OPCODE_BE_32K 0x52 /* Erase 32KiB block */
#define XQSPIPS_FLASH_OPCODE_QUAD_READ 0x6B /* Quad read data bytes */
#define XQSPIPS_FLASH_OPCODE_ERASE_SUS 0x75 /* Erase suspend */
#define XQSPIPS_FLASH_OPCODE_ERASE_RES 0x7A /* Erase resume */
#define XQSPIPS_FLASH_OPCODE_RDID 0x9F /* Read JEDEC ID */
#define XQSPIPS_FLASH_OPCODE_BE 0xC7 /* Erase whole flash block */
#define XQSPIPS_FLASH_OPCODE_SE 0xD8 /* Sector erase (usually 64KB)*/
#define XQSPIPS_FLASH_OPCODE_DUAL_IO_READ 0xBB /* Read data using Dual I/O */
#define XQSPIPS_FLASH_OPCODE_QUAD_IO_READ 0xEB /* Read data using Quad I/O */
#define XQSPIPS_FLASH_OPCODE_BRWR 0x17 /* Bank Register Write */
#define XQSPIPS_FLASH_OPCODE_BRRD 0x16 /* Bank Register Read */
/* Extende Address Register Write - Micron's equivalent of Bank Register */
#define XQSPIPS_FLASH_OPCODE_EARWR 0xC5
/* Extende Address Register Read - Micron's equivalent of Bank Register */
#define XQSPIPS_FLASH_OPCODE_EARRD 0xC8
#define XQSPIPS_FLASH_OPCODE_DIE_ERASE 0xC4
#define XQSPIPS_FLASH_OPCODE_READ_FLAG_SR 0x70
#define XQSPIPS_FLASH_OPCODE_CLEAR_FLAG_SR 0x50
#define XQSPIPS_FLASH_OPCODE_READ_LOCK_REG 0xE8 /* Lock register Read */
#define XQSPIPS_FLASH_OPCODE_WRITE_LOCK_REG 0xE5 /* Lock Register Write */
/*@}*/
/** @name Instruction size
*
* The following constants define numbers 1 to 4.
* Used to identify whether TXD0,1,2 or 3 is to be used.
*
* @{
*/
#define XQSPIPS_SIZE_ONE 1
#define XQSPIPS_SIZE_TWO 2
#define XQSPIPS_SIZE_THREE 3
#define XQSPIPS_SIZE_FOUR 4
/*@}*/
/** @name ConnectionMode
*
* The following constants are the possible values of ConnectionMode in
* Config structure.
*
* @{
*/
#define XQSPIPS_CONNECTION_MODE_SINGLE 0
#define XQSPIPS_CONNECTION_MODE_STACKED 1
#define XQSPIPS_CONNECTION_MODE_PARALLEL 2
/*@}*/
/** @name FIFO threshold value
*
* This is the Rx FIFO threshold (in words) that was found to be most
* optimal in terms of performance
*
* @{
*/
#define XQSPIPS_RXFIFO_THRESHOLD_OPT 32
/*@}*/
/**************************** Type Definitions *******************************/
/**
* The handler data type allows the user to define a callback function to
* handle the asynchronous processing for the QSPI device. The application
* using this driver is expected to define a handler of this type to support
* interrupt driven mode. The handler executes in an interrupt context, so
* only minimal processing should be performed.
*
* @param CallBackRef is the callback reference passed in by the upper
* layer when setting the callback functions, and passed back to
* the upper layer when the callback is invoked. Its type is
* not important to the driver, so it is a void pointer.
* @param StatusEvent holds one or more status events that have occurred.
* See the XQspiPs_SetStatusHandler() for details on the status
* events that can be passed in the callback.
* @param ByteCount indicates how many bytes of data were successfully
* transferred. This may be less than the number of bytes
* requested if the status event indicates an error.
*/
typedef void (*XQspiPs_StatusHandler) (void *CallBackRef, u32 StatusEvent,
unsigned ByteCount);
/**
* This typedef contains configuration information for the device.
*/
typedef struct {
u16 DeviceId; /**< Unique ID of device */
u32 BaseAddress; /**< Base address of the device */
u32 InputClockHz; /**< Input clock frequency */
u8 ConnectionMode; /**< Single, Stacked and Parallel mode */
} XQspiPs_Config;
/**
* The XQspiPs driver instance data. The user is required to allocate a
* variable of this type for every QSPI device in the system. A pointer
* to a variable of this type is then passed to the driver API functions.
*/
typedef struct {
XQspiPs_Config Config; /**< Configuration structure */
u32 IsReady; /**< Device is initialized and ready */
u8 *SendBufferPtr; /**< Buffer to send (state) */
u8 *RecvBufferPtr; /**< Buffer to receive (state) */
int RequestedBytes; /**< Number of bytes to transfer (state) */
int RemainingBytes; /**< Number of bytes left to transfer(state) */
u32 IsBusy; /**< A transfer is in progress (state) */
XQspiPs_StatusHandler StatusHandler;
void *StatusRef; /**< Callback reference for status handler */
u32 ShiftReadData; /**< Flag to indicate whether the data
* read from the Rx FIFO needs to be shifted
* in cases where the data is less than 4
* bytes
*/
} XQspiPs;
/***************** Macros (Inline Functions) Definitions *********************/
/****************************************************************************/
/*
*
* Check in OptionsTable if Manual Start Option is enabled or disabled.
*
* @param InstancePtr is a pointer to the XQspiPs instance.
*
* @return
* - TRUE if option is set
* - FALSE if option is not set
*
* @note C-Style signature:
* u8 XQspiPs_IsManualStart(XQspiPs *InstancePtr);
*
*****************************************************************************/
#define XQspiPs_IsManualStart(InstancePtr) \
((XQspiPs_GetOptions(InstancePtr) & \
XQSPIPS_MANUAL_START_OPTION) ? TRUE : FALSE)
/****************************************************************************/
/*
*
* Check in OptionsTable if Manual Chip Select Option is enabled or disabled.
*
* @param InstancePtr is a pointer to the XSpiPs instance.
*
* @return
* - TRUE if option is set
* - FALSE if option is not set
*
* @note C-Style signature:
* u8 XQspiPs_IsManualChipSelect(XQspiPs *InstancePtr);
*
*****************************************************************************/
#define XQspiPs_IsManualChipSelect(InstancePtr) \
((XQspiPs_GetOptions(InstancePtr) & \
XQSPIPS_FORCE_SSELECT_OPTION) ? TRUE : FALSE)
/****************************************************************************/
/**
*
* Set the contents of the slave idle count register.
*
* @param InstancePtr is a pointer to the XQspiPs instance.
* @param RegisterValue is the value to be written, valid values are
* 0-255.
*
* @return None
*
* @note
* C-Style signature:
* void XQspiPs_SetSlaveIdle(XQspiPs *InstancePtr, u32 RegisterValue)
*
*****************************************************************************/
#define XQspiPs_SetSlaveIdle(InstancePtr, RegisterValue) \
XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \
XQSPIPS_SICR_OFFSET, (RegisterValue))
/****************************************************************************/
/**
*
* Get the contents of the slave idle count register. Use the XQSPIPS_SICR_*
* constants defined in xqspips_hw.h to interpret the bit-mask returned.
*
* @param InstancePtr is a pointer to the XQspiPs instance.
*
* @return An 8-bit value representing Slave Idle Count.
*
* @note C-Style signature:
* u32 XQspiPs_GetSlaveIdle(XQspiPs *InstancePtr)
*
*****************************************************************************/
#define XQspiPs_GetSlaveIdle(InstancePtr) \
XQspiPs_In32(((InstancePtr)->Config.BaseAddress) + \
XQSPIPS_SICR_OFFSET)
/****************************************************************************/
/**
*
* Set the contents of the transmit FIFO watermark register.
*
* @param InstancePtr is a pointer to the XQspiPs instance.
* @param RegisterValue is the value to be written, valid values are 1-63.
*
* @return None.
*
* @note
* C-Style signature:
* void XQspiPs_SetTXWatermark(XQspiPs *InstancePtr, u32 RegisterValue)
*
*****************************************************************************/
#define XQspiPs_SetTXWatermark(InstancePtr, RegisterValue) \
XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \
XQSPIPS_TXWR_OFFSET, (RegisterValue))
/****************************************************************************/
/**
*
* Get the contents of the transmit FIFO watermark register.
* Valid values are in the range 1-63.
*
* @param InstancePtr is a pointer to the XQspiPs instance.
*
* @return A 6-bit value representing Tx Watermark level.
*
* @note C-Style signature:
* u32 XQspiPs_GetTXWatermark(XQspiPs *InstancePtr)
*
*****************************************************************************/
#define XQspiPs_GetTXWatermark(InstancePtr) \
XQspiPs_In32((InstancePtr->Config.BaseAddress) + XQSPIPS_TXWR_OFFSET)
/****************************************************************************/
/**
*
* Set the contents of the receive FIFO watermark register.
*
* @param InstancePtr is a pointer to the XQspiPs instance.
* @param RegisterValue is the value to be written, valid values are 1-63.
*
* @return None.
*
* @note
* C-Style signature:
* void XQspiPs_SetRXWatermark(XQspiPs *InstancePtr, u32 RegisterValue)
*
*****************************************************************************/
#define XQspiPs_SetRXWatermark(InstancePtr, RegisterValue) \
XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \
XQSPIPS_RXWR_OFFSET, (RegisterValue))
/****************************************************************************/
/**
*
* Get the contents of the receive FIFO watermark register.
* Valid values are in the range 1-63.
*
* @param InstancePtr is a pointer to the XQspiPs instance.
*
* @return A 6-bit value representing Rx Watermark level.
*
* @note C-Style signature:
* u32 XQspiPs_GetRXWatermark(XQspiPs *InstancePtr)
*
*****************************************************************************/
#define XQspiPs_GetRXWatermark(InstancePtr) \
XQspiPs_In32((InstancePtr->Config.BaseAddress) + XQSPIPS_RXWR_OFFSET)
/****************************************************************************/
/**
*
* Enable the device and uninhibit master transactions.
*
* @param InstancePtr is a pointer to the XQspiPs instance.
*
* @return None.
*
* @note C-Style signature:
* void XQspiPs_Enable(XQspiPs *InstancePtr)
*
*****************************************************************************/
#define XQspiPs_Enable(InstancePtr) \
XQspiPs_Out32((InstancePtr->Config.BaseAddress) + XQSPIPS_ER_OFFSET, \
XQSPIPS_ER_ENABLE_MASK)
/****************************************************************************/
/**
*
* Disable the device.
*
* @param InstancePtr is a pointer to the XQspiPs instance.
*
* @return None.
*
* @note C-Style signature:
* void XQspiPs_Disable(XQspiPs *InstancePtr)
*
*****************************************************************************/
#define XQspiPs_Disable(InstancePtr) \
XQspiPs_Out32((InstancePtr->Config.BaseAddress) + XQSPIPS_ER_OFFSET, 0)
/****************************************************************************/
/**
*
* Set the contents of the Linear QSPI Configuration register.
*
* @param InstancePtr is a pointer to the XQspiPs instance.
* @param RegisterValue is the value to be written to the Linear QSPI
* configuration register.
*
* @return None.
*
* @note
* C-Style signature:
* void XQspiPs_SetLqspiConfigReg(XQspiPs *InstancePtr,
* u32 RegisterValue)
*
*****************************************************************************/
#define XQspiPs_SetLqspiConfigReg(InstancePtr, RegisterValue) \
XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \
XQSPIPS_LQSPI_CR_OFFSET, (RegisterValue))
/****************************************************************************/
/**
*
* Get the contents of the Linear QSPI Configuration register.
*
* @param InstancePtr is a pointer to the XQspiPs instance.
*
* @return A 32-bit value representing the contents of the LQSPI Config
* register.
*
* @note C-Style signature:
* u32 XQspiPs_GetLqspiConfigReg(u32 *InstancePtr)
*
*****************************************************************************/
#define XQspiPs_GetLqspiConfigReg(InstancePtr) \
XQspiPs_In32((InstancePtr->Config.BaseAddress) + \
XQSPIPS_LQSPI_CR_OFFSET)
/************************** Function Prototypes ******************************/
/*
* Initialization function, implemented in xqspips_sinit.c
*/
XQspiPs_Config *XQspiPs_LookupConfig(u16 DeviceId);
/*
* Functions implemented in xqspips.c
*/
int XQspiPs_CfgInitialize(XQspiPs *InstancePtr, XQspiPs_Config * Config,
u32 EffectiveAddr);
void XQspiPs_Reset(XQspiPs *InstancePtr);
void XQspiPs_Abort(XQspiPs *InstancePtr);
int XQspiPs_Transfer(XQspiPs *InstancePtr, u8 *SendBufPtr, u8 *RecvBufPtr,
unsigned ByteCount);
int XQspiPs_PolledTransfer(XQspiPs *InstancePtr, u8 *SendBufPtr,
u8 *RecvBufPtr, unsigned ByteCount);
int XQspiPs_LqspiRead(XQspiPs *InstancePtr, u8 *RecvBufPtr,
u32 Address, unsigned ByteCount);
int XQspiPs_SetSlaveSelect(XQspiPs *InstancePtr);
void XQspiPs_SetStatusHandler(XQspiPs *InstancePtr, void *CallBackRef,
XQspiPs_StatusHandler FuncPtr);
void XQspiPs_InterruptHandler(void *InstancePtr);
/*
* Functions for selftest, in xqspips_selftest.c
*/
int XQspiPs_SelfTest(XQspiPs *InstancePtr);
/*
* Functions for options, in xqspips_options.c
*/
int XQspiPs_SetOptions(XQspiPs *InstancePtr, u32 Options);
u32 XQspiPs_GetOptions(XQspiPs *InstancePtr);
int XQspiPs_SetClkPrescaler(XQspiPs *InstancePtr, u8 Prescaler);
u8 XQspiPs_GetClkPrescaler(XQspiPs *InstancePtr);
int XQspiPs_SetDelays(XQspiPs *InstancePtr, u8 DelayNss, u8 DelayBtwn,
u8 DelayAfter, u8 DelayInit);
void XQspiPs_GetDelays(XQspiPs *InstancePtr, u8 *DelayNss, u8 *DelayBtwn,
u8 *DelayAfter, u8 *DelayInit);
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */

View file

@ -0,0 +1,80 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xqspips_g.c
*
* This file contains a configuration table that specifies the configuration of
* QSPI devices in the system.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00 sdm 11/25/10 First release
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xqspips.h"
#include "xparameters.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Prototypes ******************************/
/**
* This table contains configuration information for each QSPI device
* in the system.
*/
XQspiPs_Config XQspiPs_ConfigTable[XPAR_XQSPIPS_NUM_INSTANCES] = {
{
XPAR_XQSPIPS_0_DEVICE_ID, /* Device ID for instance */
XPAR_XQSPIPS_0_BASEADDR, /* Device base address */
XPAR_XQSPIPS_0_QSPI_CLK_FREQ_HZ,
XPAR_XQSPIPS_0_QSPI_MODE
},
};

View file

@ -0,0 +1,221 @@
/******************************************************************************
*
* Copyright (C) 2013 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xqspips_hw.c
*
* Contains low level functions, primarily reset related.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 2.03a hk 09/17/13 First release
* 3.1 hk 06/19/14 When writing to the configuration register, set/reset
* required bits leaving reserved bits untouched. CR# 796813.
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xqspips_hw.h"
#include "xqspips.h"
/************************** Constant Definitions *****************************/
/** @name Pre-scaler value for divided by 4
*
* Pre-scaler value for divided by 4
*
* @{
*/
#define XQSPIPS_CR_PRESC_DIV_BY_4 0x01
/* @} */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Definitions *****************************/
/*****************************************************************************/
/**
*
* Resets QSPI by disabling the device and bringing it to reset state through
* register writes.
*
* @param None
*
* @return None.
*
* @note None.
*
******************************************************************************/
void XQspiPs_ResetHw(u32 BaseAddress)
{
u32 ConfigReg;
/*
* Disable interrupts
*/
XQspiPs_WriteReg(BaseAddress, XQSPIPS_IDR_OFFSET,
XQSPIPS_IXR_DISABLE_ALL);
/*
* Disable device
*/
XQspiPs_WriteReg(BaseAddress, XQSPIPS_ER_OFFSET,
0);
/*
* De-assert slave select lines.
*/
ConfigReg = XQspiPs_ReadReg(BaseAddress, XQSPIPS_CR_OFFSET);
ConfigReg |= (XQSPIPS_CR_SSCTRL_MASK | XQSPIPS_CR_SSFORCE_MASK);
XQspiPs_WriteReg(BaseAddress, XQSPIPS_CR_OFFSET, ConfigReg);
/*
* Write default value to RX and TX threshold registers
* RX threshold should be set to 1 here because the corresponding
* status bit is used next to clear the RXFIFO
*/
XQspiPs_WriteReg(BaseAddress, XQSPIPS_TXWR_OFFSET,
(XQSPIPS_TXWR_RESET_VALUE & XQSPIPS_TXWR_MASK));
XQspiPs_WriteReg(BaseAddress, XQSPIPS_RXWR_OFFSET,
(XQSPIPS_RXWR_RESET_VALUE & XQSPIPS_RXWR_MASK));
/*
* Clear RXFIFO
*/
while ((XQspiPs_ReadReg(BaseAddress,XQSPIPS_SR_OFFSET) &
XQSPIPS_IXR_RXNEMPTY_MASK) != 0) {
XQspiPs_ReadReg(BaseAddress, XQSPIPS_RXD_OFFSET);
}
/*
* Clear status register by reading register and
* writing 1 to clear the write to clear bits
*/
XQspiPs_ReadReg(BaseAddress, XQSPIPS_SR_OFFSET);
XQspiPs_WriteReg(BaseAddress, XQSPIPS_SR_OFFSET,
XQSPIPS_IXR_WR_TO_CLR_MASK);
/*
* Write default value to configuration register
*/
ConfigReg = XQspiPs_ReadReg(BaseAddress, XQSPIPS_CR_OFFSET);
ConfigReg |= XQSPIPS_CR_RESET_MASK_SET;
ConfigReg &= ~XQSPIPS_CR_RESET_MASK_CLR;
XQspiPs_WriteReg(BaseAddress, XQSPIPS_CR_OFFSET, ConfigReg);
/*
* De-select linear mode
*/
XQspiPs_WriteReg(BaseAddress, XQSPIPS_LQSPI_CR_OFFSET,
0x0);
}
/*****************************************************************************/
/**
*
* Initializes QSPI to Linear mode with default QSPI boot settings.
*
* @param None
*
* @return None.
*
* @note None.
*
******************************************************************************/
void XQspiPs_LinearInit(u32 BaseAddress)
{
u32 BaudRateDiv;
u32 LinearCfg;
u32 ConfigReg;
/*
* Baud rate divisor for dividing by 4. Value of CR bits [5:3]
* should be set to 0x001; hence shift the value and use the mask.
*/
BaudRateDiv = ( (XQSPIPS_CR_PRESC_DIV_BY_4) <<
XQSPIPS_CR_PRESC_SHIFT) & XQSPIPS_CR_PRESC_MASK;
/*
* Write configuration register with default values, slave selected &
* pre-scaler value for divide by 4
*/
ConfigReg = XQspiPs_ReadReg(BaseAddress, XQSPIPS_CR_OFFSET);
ConfigReg |= (XQSPIPS_CR_RESET_MASK_SET | BaudRateDiv);
ConfigReg &= ~(XQSPIPS_CR_RESET_MASK_CLR | XQSPIPS_CR_SSCTRL_MASK);
XQspiPs_WriteReg(BaseAddress, XQSPIPS_CR_OFFSET, ConfigReg);
/*
* Write linear configuration register with default value -
* enable linear mode and use fast read.
*/
if(XPAR_XQSPIPS_0_QSPI_MODE == XQSPIPS_CONNECTION_MODE_SINGLE){
LinearCfg = XQSPIPS_LQSPI_CR_RST_STATE;
}else if(XPAR_XQSPIPS_0_QSPI_MODE ==
XQSPIPS_CONNECTION_MODE_STACKED){
LinearCfg = XQSPIPS_LQSPI_CR_RST_STATE |
XQSPIPS_LQSPI_CR_TWO_MEM_MASK;
}else if(XPAR_XQSPIPS_0_QSPI_MODE ==
XQSPIPS_CONNECTION_MODE_PARALLEL){
LinearCfg = XQSPIPS_LQSPI_CR_RST_STATE |
XQSPIPS_LQSPI_CR_TWO_MEM_MASK |
XQSPIPS_LQSPI_CR_SEP_BUS_MASK;
}
XQspiPs_WriteReg(BaseAddress, XQSPIPS_LQSPI_CR_OFFSET,
LinearCfg);
/*
* Enable device
*/
XQspiPs_WriteReg(BaseAddress, XQSPIPS_ER_OFFSET,
XQSPIPS_ER_ENABLE_MASK);
}

View file

@ -0,0 +1,385 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xqspips_hw.h
*
* This header file contains the identifiers and basic HW access driver
* functions (or macros) that can be used to access the device. Other driver
* functions are defined in xqspips.h.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00 sdm 11/25/10 First release
* 2.00a ka 07/25/12 Added a few register defines for CR 670297
* and removed some defines of reserved fields for
* CR 671468
* Added define XQSPIPS_CR_HOLD_B_MASK for Holdb_dr
* bit in Configuration register.
* 2.01a sg 02/03/13 Added defines for DelayNss,Rx Watermark,Interrupts
* which need write to clear. Removed Read zeros mask from
* LQSPI Config register.
* 2.03a hk 08/22/13 Added prototypes of API's for QSPI reset and
* linear mode initialization for boot. Added related
* constant definitions.
* 3.1 hk 08/13/14 Changed definition of CR reset value masks to set/reset
* required bits leaving reserved bits untouched. CR# 796813.
*
* </pre>
*
******************************************************************************/
#ifndef XQSPIPS_HW_H /* prevent circular inclusions */
#define XQSPIPS_HW_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
#include "xil_types.h"
#include "xil_assert.h"
#include "xil_io.h"
#include "xparameters.h"
/************************** Constant Definitions *****************************/
/** @name Register Map
*
* Register offsets from the base address of an QSPI device.
* @{
*/
#define XQSPIPS_CR_OFFSET 0x00 /**< Configuration Register */
#define XQSPIPS_SR_OFFSET 0x04 /**< Interrupt Status */
#define XQSPIPS_IER_OFFSET 0x08 /**< Interrupt Enable */
#define XQSPIPS_IDR_OFFSET 0x0c /**< Interrupt Disable */
#define XQSPIPS_IMR_OFFSET 0x10 /**< Interrupt Enabled Mask */
#define XQSPIPS_ER_OFFSET 0x14 /**< Enable/Disable Register */
#define XQSPIPS_DR_OFFSET 0x18 /**< Delay Register */
#define XQSPIPS_TXD_00_OFFSET 0x1C /**< Transmit 4-byte inst/data */
#define XQSPIPS_RXD_OFFSET 0x20 /**< Data Receive Register */
#define XQSPIPS_SICR_OFFSET 0x24 /**< Slave Idle Count */
#define XQSPIPS_TXWR_OFFSET 0x28 /**< Transmit FIFO Watermark */
#define XQSPIPS_RXWR_OFFSET 0x2C /**< Receive FIFO Watermark */
#define XQSPIPS_GPIO_OFFSET 0x30 /**< GPIO Register */
#define XQSPIPS_LPBK_DLY_ADJ_OFFSET 0x38 /**< Loopback Delay Adjust Reg */
#define XQSPIPS_TXD_01_OFFSET 0x80 /**< Transmit 1-byte inst */
#define XQSPIPS_TXD_10_OFFSET 0x84 /**< Transmit 2-byte inst */
#define XQSPIPS_TXD_11_OFFSET 0x88 /**< Transmit 3-byte inst */
#define XQSPIPS_LQSPI_CR_OFFSET 0xA0 /**< Linear QSPI config register */
#define XQSPIPS_LQSPI_SR_OFFSET 0xA4 /**< Linear QSPI status register */
#define XQSPIPS_MOD_ID_OFFSET 0xFC /**< Module ID register */
/* @} */
/** @name Configuration Register
*
* This register contains various control bits that
* affect the operation of the QSPI device. Read/Write.
* @{
*/
#define XQSPIPS_CR_IFMODE_MASK 0x80000000 /**< Flash mem interface mode */
#define XQSPIPS_CR_ENDIAN_MASK 0x04000000 /**< Tx/Rx FIFO endianness */
#define XQSPIPS_CR_MANSTRT_MASK 0x00010000 /**< Manual Transmission Start */
#define XQSPIPS_CR_MANSTRTEN_MASK 0x00008000 /**< Manual Transmission Start
Enable */
#define XQSPIPS_CR_SSFORCE_MASK 0x00004000 /**< Force Slave Select */
#define XQSPIPS_CR_SSCTRL_MASK 0x00000400 /**< Slave Select Decode */
#define XQSPIPS_CR_SSCTRL_SHIFT 10 /**< Slave Select Decode shift */
#define XQSPIPS_CR_DATA_SZ_MASK 0x000000C0 /**< Size of word to be
transferred */
#define XQSPIPS_CR_PRESC_MASK 0x00000038 /**< Prescaler Setting */
#define XQSPIPS_CR_PRESC_SHIFT 3 /**< Prescaler shift */
#define XQSPIPS_CR_PRESC_MAXIMUM 0x07 /**< Prescaler maximum value */
#define XQSPIPS_CR_CPHA_MASK 0x00000004 /**< Phase Configuration */
#define XQSPIPS_CR_CPOL_MASK 0x00000002 /**< Polarity Configuration */
#define XQSPIPS_CR_MSTREN_MASK 0x00000001 /**< Master Mode Enable */
#define XQSPIPS_CR_HOLD_B_MASK 0x00080000 /**< HOLD_B Pin Drive Enable */
#define XQSPIPS_CR_REF_CLK_MASK 0x00000100 /**< Ref clk bit - should be 0 */
/* Deselect the Slave select line and set the transfer size to 32 at reset */
#define XQSPIPS_CR_RESET_MASK_SET XQSPIPS_CR_IFMODE_MASK | \
XQSPIPS_CR_SSCTRL_MASK | \
XQSPIPS_CR_DATA_SZ_MASK | \
XQSPIPS_CR_MSTREN_MASK | \
XQSPIPS_CR_SSFORCE_MASK | \
XQSPIPS_CR_HOLD_B_MASK
#define XQSPIPS_CR_RESET_MASK_CLR XQSPIPS_CR_CPOL_MASK | \
XQSPIPS_CR_CPHA_MASK | \
XQSPIPS_CR_PRESC_MASK | \
XQSPIPS_CR_MANSTRTEN_MASK | \
XQSPIPS_CR_MANSTRT_MASK | \
XQSPIPS_CR_ENDIAN_MASK | \
XQSPIPS_CR_REF_CLK_MASK
/* @} */
/** @name QSPI Interrupt Registers
*
* <b>QSPI Status Register</b>
*
* This register holds the interrupt status flags for an QSPI device. Some
* of the flags are level triggered, which means that they are set as long
* as the interrupt condition exists. Other flags are edge triggered,
* which means they are set once the interrupt condition occurs and remain
* set until they are cleared by software. The interrupts are cleared by
* writing a '1' to the interrupt bit position in the Status Register.
* Read/Write.
*
* <b>QSPI Interrupt Enable Register</b>
*
* This register is used to enable chosen interrupts for an QSPI device.
* Writing a '1' to a bit in this register sets the corresponding bit in the
* QSPI Interrupt Mask register. Write only.
*
* <b>QSPI Interrupt Disable Register </b>
*
* This register is used to disable chosen interrupts for an QSPI device.
* Writing a '1' to a bit in this register clears the corresponding bit in the
* QSPI Interrupt Mask register. Write only.
*
* <b>QSPI Interrupt Mask Register</b>
*
* This register shows the enabled/disabled interrupts of an QSPI device.
* Read only.
*
* All four registers have the same bit definitions. They are only defined once
* for each of the Interrupt Enable Register, Interrupt Disable Register,
* Interrupt Mask Register, and Channel Interrupt Status Register
* @{
*/
#define XQSPIPS_IXR_TXUF_MASK 0x00000040 /**< QSPI Tx FIFO Underflow */
#define XQSPIPS_IXR_RXFULL_MASK 0x00000020 /**< QSPI Rx FIFO Full */
#define XQSPIPS_IXR_RXNEMPTY_MASK 0x00000010 /**< QSPI Rx FIFO Not Empty */
#define XQSPIPS_IXR_TXFULL_MASK 0x00000008 /**< QSPI Tx FIFO Full */
#define XQSPIPS_IXR_TXOW_MASK 0x00000004 /**< QSPI Tx FIFO Overwater */
#define XQSPIPS_IXR_RXOVR_MASK 0x00000001 /**< QSPI Rx FIFO Overrun */
#define XQSPIPS_IXR_DFLT_MASK 0x00000025 /**< QSPI default interrupts
mask */
#define XQSPIPS_IXR_WR_TO_CLR_MASK 0x00000041 /**< Interrupts which
need write to clear */
#define XQSPIPS_ISR_RESET_STATE 0x00000004 /**< Default to tx/rx empty */
#define XQSPIPS_IXR_DISABLE_ALL 0x0000007D /**< Disable all interrupts */
/* @} */
/** @name Enable Register
*
* This register is used to enable or disable an QSPI device.
* Read/Write
* @{
*/
#define XQSPIPS_ER_ENABLE_MASK 0x00000001 /**< QSPI Enable Bit Mask */
/* @} */
/** @name Delay Register
*
* This register is used to program timing delays in
* slave mode. Read/Write
* @{
*/
#define XQSPIPS_DR_NSS_MASK 0xFF000000 /**< Delay to de-assert slave select
between two words mask */
#define XQSPIPS_DR_NSS_SHIFT 24 /**< Delay to de-assert slave select
between two words shift */
#define XQSPIPS_DR_BTWN_MASK 0x00FF0000 /**< Delay Between Transfers
mask */
#define XQSPIPS_DR_BTWN_SHIFT 16 /**< Delay Between Transfers shift */
#define XQSPIPS_DR_AFTER_MASK 0x0000FF00 /**< Delay After Transfers mask */
#define XQSPIPS_DR_AFTER_SHIFT 8 /**< Delay After Transfers shift */
#define XQSPIPS_DR_INIT_MASK 0x000000FF /**< Delay Initially mask */
/* @} */
/** @name Slave Idle Count Registers
*
* This register defines the number of pclk cycles the slave waits for a the
* QSPI clock to become stable in quiescent state before it can detect the start
* of the next transfer in CPHA = 1 mode.
* Read/Write
*
* @{
*/
#define XQSPIPS_SICR_MASK 0x000000FF /**< Slave Idle Count Mask */
/* @} */
/** @name Transmit FIFO Watermark Register
*
* This register defines the watermark setting for the Transmit FIFO.
*
* @{
*/
#define XQSPIPS_TXWR_MASK 0x0000003F /**< Transmit Watermark Mask */
#define XQSPIPS_TXWR_RESET_VALUE 0x00000001 /**< Transmit Watermark
* register reset value */
/* @} */
/** @name Receive FIFO Watermark Register
*
* This register defines the watermark setting for the Receive FIFO.
*
* @{
*/
#define XQSPIPS_RXWR_MASK 0x0000003F /**< Receive Watermark Mask */
#define XQSPIPS_RXWR_RESET_VALUE 0x00000001 /**< Receive Watermark
* register reset value */
/* @} */
/** @name FIFO Depth
*
* This macro provides the depth of transmit FIFO and receive FIFO.
*
* @{
*/
#define XQSPIPS_FIFO_DEPTH 63 /**< FIFO depth (words) */
/* @} */
/** @name Linear QSPI Configuration Register
*
* This register contains various control bits that
* affect the operation of the Linear QSPI controller. Read/Write.
*
* @{
*/
#define XQSPIPS_LQSPI_CR_LINEAR_MASK 0x80000000 /**< LQSPI mode enable */
#define XQSPIPS_LQSPI_CR_TWO_MEM_MASK 0x40000000 /**< Both memories or one */
#define XQSPIPS_LQSPI_CR_SEP_BUS_MASK 0x20000000 /**< Seperate memory bus */
#define XQSPIPS_LQSPI_CR_U_PAGE_MASK 0x10000000 /**< Upper memory page */
#define XQSPIPS_LQSPI_CR_MODE_EN_MASK 0x02000000 /**< Enable mode bits */
#define XQSPIPS_LQSPI_CR_MODE_ON_MASK 0x01000000 /**< Mode on */
#define XQSPIPS_LQSPI_CR_MODE_BITS_MASK 0x00FF0000 /**< Mode value for dual I/O
or quad I/O */
#define XQSPIPS_LQSPI_CR_DUMMY_MASK 0x00000700 /**< Number of dummy bytes
between addr and return
read data */
#define XQSPIPS_LQSPI_CR_INST_MASK 0x000000FF /**< Read instr code */
#define XQSPIPS_LQSPI_CR_RST_STATE 0x8000016B /**< Default CR value */
/* @} */
/** @name Linear QSPI Status Register
*
* This register contains various status bits of the Linear QSPI controller.
* Read/Write.
*
* @{
*/
#define XQSPIPS_LQSPI_SR_D_FSM_ERR_MASK 0x00000004 /**< AXI Data FSM Error
received */
#define XQSPIPS_LQSPI_SR_WR_RECVD_MASK 0x00000002 /**< AXI write command
received */
/* @} */
/** @name Loopback Delay Adjust Register
*
* This register contains various bit masks of Loopback Delay Adjust Register.
*
* @{
*/
#define XQSPIPS_LPBK_DLY_ADJ_USE_LPBK_MASK 0x00000020 /**< Loopback Bit */
/* @} */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
#define XQspiPs_In32 Xil_In32
#define XQspiPs_Out32 Xil_Out32
/****************************************************************************/
/**
* Read a register.
*
* @param BaseAddress contains the base address of the device.
* @param RegOffset contains the offset from the 1st register of the
* device to the target register.
*
* @return The value read from the register.
*
* @note C-Style signature:
* u32 XQspiPs_ReadReg(u32 BaseAddress. int RegOffset)
*
******************************************************************************/
#define XQspiPs_ReadReg(BaseAddress, RegOffset) \
XQspiPs_In32((BaseAddress) + (RegOffset))
/***************************************************************************/
/**
* Write to a register.
*
* @param BaseAddress contains the base address of the device.
* @param RegOffset contains the offset from the 1st register of the
* device to target register.
* @param RegisterValue is the value to be written to the register.
*
* @return None.
*
* @note C-Style signature:
* void XQspiPs_WriteReg(u32 BaseAddress, int RegOffset,
* u32 RegisterValue)
*
******************************************************************************/
#define XQspiPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \
XQspiPs_Out32((BaseAddress) + (RegOffset), (RegisterValue))
/************************** Function Prototypes ******************************/
/*
* Functions implemented in xqspips_hw.c
*/
void XQspiPs_ResetHw(u32 BaseAddress);
void XQspiPs_LinearInit(u32 BaseAddress);
/************************** Variable Definitions *****************************/
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */

View file

@ -0,0 +1,425 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xqspips_options.c
*
* Contains functions for the configuration of the XQspiPs driver component.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00 sdm 11/25/10 First release
* 2.00a kka 07/25/12 Removed the selection for the following options:
* Master mode (XQSPIPS_MASTER_OPTION) and
* Flash interface mode (XQSPIPS_FLASH_MODE_OPTION) option
* as the QSPI driver supports the Master mode
* and Flash Interface mode. The driver doesnot support
* Slave mode or the legacy mode.
* Added the option for setting the Holdb_dr bit in the
* configuration options, XQSPIPS_HOLD_B_DRIVE_OPTION
* is the option to be used for setting this bit in the
* configuration register.
* 2.01a sg 02/03/13 SetDelays and GetDelays API's include DelayNss parameter.
*
* 2.02a hk 26/03/13 Removed XQspi_Reset() in Set_Options() function when
* LQSPI_MODE_OPTION is set. Moved Enable() to XQpsiPs_LqspiRead().
*</pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xqspips.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Definitions *****************************/
/*
* Create the table of options which are processed to get/set the device
* options. These options are table driven to allow easy maintenance and
* expansion of the options.
*/
typedef struct {
u32 Option;
u32 Mask;
} OptionsMap;
static OptionsMap OptionsTable[] = {
{XQSPIPS_CLK_ACTIVE_LOW_OPTION, XQSPIPS_CR_CPOL_MASK},
{XQSPIPS_CLK_PHASE_1_OPTION, XQSPIPS_CR_CPHA_MASK},
{XQSPIPS_FORCE_SSELECT_OPTION, XQSPIPS_CR_SSFORCE_MASK},
{XQSPIPS_MANUAL_START_OPTION, XQSPIPS_CR_MANSTRTEN_MASK},
{XQSPIPS_HOLD_B_DRIVE_OPTION, XQSPIPS_CR_HOLD_B_MASK},
};
#define XQSPIPS_NUM_OPTIONS (sizeof(OptionsTable) / sizeof(OptionsMap))
/*****************************************************************************/
/**
*
* This function sets the options for the QSPI device driver. The options control
* how the device behaves relative to the QSPI bus. The device must be idle
* rather than busy transferring data before setting these device options.
*
* @param InstancePtr is a pointer to the XQspiPs instance.
* @param Options contains the specified options to be set. This is a bit
* mask where a 1 means to turn the option on, and a 0 means to
* turn the option off. One or more bit values may be contained in
* the mask. See the bit definitions named XQSPIPS_*_OPTIONS in
* the file xqspips.h.
*
* @return
* - XST_SUCCESS if options are successfully set.
* - XST_DEVICE_BUSY if the device is currently transferring data.
* The transfer must complete or be aborted before setting options.
*
* @note
* This function is not thread-safe.
*
******************************************************************************/
int XQspiPs_SetOptions(XQspiPs *InstancePtr, u32 Options)
{
u32 ConfigReg;
unsigned int Index;
u32 QspiOptions;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* Do not allow to modify the Control Register while a transfer is in
* progress. Not thread-safe.
*/
if (InstancePtr->IsBusy) {
return XST_DEVICE_BUSY;
}
QspiOptions = Options & XQSPIPS_LQSPI_MODE_OPTION;
Options &= ~XQSPIPS_LQSPI_MODE_OPTION;
ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress,
XQSPIPS_CR_OFFSET);
/*
* Loop through the options table, turning the option on or off
* depending on whether the bit is set in the incoming options flag.
*/
for (Index = 0; Index < XQSPIPS_NUM_OPTIONS; Index++) {
if (Options & OptionsTable[Index].Option) {
/* Turn it on */
ConfigReg |= OptionsTable[Index].Mask;
} else {
/* Turn it off */
ConfigReg &= ~(OptionsTable[Index].Mask);
}
}
/*
* Now write the control register. Leave it to the upper layers
* to restart the device.
*/
XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPS_CR_OFFSET,
ConfigReg);
/*
* Check for the LQSPI configuration options.
*/
ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress,
XQSPIPS_LQSPI_CR_OFFSET);
if (QspiOptions & XQSPIPS_LQSPI_MODE_OPTION) {
XQspiPs_WriteReg(InstancePtr->Config.BaseAddress,
XQSPIPS_LQSPI_CR_OFFSET,
XQSPIPS_LQSPI_CR_RST_STATE);
XQspiPs_SetSlaveSelect(InstancePtr);
} else {
ConfigReg &= ~XQSPIPS_LQSPI_CR_LINEAR_MASK;
XQspiPs_WriteReg(InstancePtr->Config.BaseAddress,
XQSPIPS_LQSPI_CR_OFFSET, ConfigReg);
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function gets the options for the QSPI device. The options control how
* the device behaves relative to the QSPI bus.
*
* @param InstancePtr is a pointer to the XQspiPs instance.
*
* @return
*
* Options contains the specified options currently set. This is a bit value
* where a 1 means the option is on, and a 0 means the option is off.
* See the bit definitions named XQSPIPS_*_OPTIONS in file xqspips.h.
*
* @note None.
*
******************************************************************************/
u32 XQspiPs_GetOptions(XQspiPs *InstancePtr)
{
u32 OptionsFlag = 0;
u32 ConfigReg;
unsigned int Index;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* Get the current options from QSPI configuration register.
*/
ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress,
XQSPIPS_CR_OFFSET);
/*
* Loop through the options table to grab options
*/
for (Index = 0; Index < XQSPIPS_NUM_OPTIONS; Index++) {
if (ConfigReg & OptionsTable[Index].Mask) {
OptionsFlag |= OptionsTable[Index].Option;
}
}
/*
* Check for the LQSPI configuration options.
*/
ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress,
XQSPIPS_LQSPI_CR_OFFSET);
if ((ConfigReg & XQSPIPS_LQSPI_CR_LINEAR_MASK) != 0) {
OptionsFlag |= XQSPIPS_LQSPI_MODE_OPTION;
}
return OptionsFlag;
}
/*****************************************************************************/
/**
*
* This function sets the clock prescaler for an QSPI device. The device
* must be idle rather than busy transferring data before setting these device
* options.
*
* @param InstancePtr is a pointer to the XQspiPs instance.
* @param Prescaler is the value that determine how much the clock should
* be divided by. Use the XQSPIPS_CLK_PRESCALE_* constants defined
* in xqspips.h for this setting.
*
* @return
* - XST_SUCCESS if options are successfully set.
* - XST_DEVICE_BUSY if the device is currently transferring data.
* The transfer must complete or be aborted before setting options.
*
* @note
* This function is not thread-safe.
*
******************************************************************************/
int XQspiPs_SetClkPrescaler(XQspiPs *InstancePtr, u8 Prescaler)
{
u32 ConfigReg;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertNonvoid(Prescaler <= XQSPIPS_CR_PRESC_MAXIMUM);
/*
* Do not allow the slave select to change while a transfer is in
* progress. Not thread-safe.
*/
if (InstancePtr->IsBusy) {
return XST_DEVICE_BUSY;
}
/*
* Read the configuration register, mask out the interesting bits, and set
* them with the shifted value passed into the function. Write the
* results back to the configuration register.
*/
ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress,
XQSPIPS_CR_OFFSET);
ConfigReg &= ~XQSPIPS_CR_PRESC_MASK;
ConfigReg |= (u32) (Prescaler & XQSPIPS_CR_PRESC_MAXIMUM) <<
XQSPIPS_CR_PRESC_SHIFT;
XQspiPs_WriteReg(InstancePtr->Config.BaseAddress,
XQSPIPS_CR_OFFSET,
ConfigReg);
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function gets the clock prescaler of an QSPI device.
*
* @param InstancePtr is a pointer to the XQspiPs instance.
*
* @return The prescaler value.
*
* @note None.
*
*
******************************************************************************/
u8 XQspiPs_GetClkPrescaler(XQspiPs *InstancePtr)
{
u32 ConfigReg;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress,
XQSPIPS_CR_OFFSET);
ConfigReg &= XQSPIPS_CR_PRESC_MASK;
return (u8)(ConfigReg >> XQSPIPS_CR_PRESC_SHIFT);
}
/*****************************************************************************/
/**
*
* This function sets the delay register for the QSPI device driver.
* The delay register controls the Delay Between Transfers, Delay After
* Transfers, and the Delay Initially. The default value is 0x0. The range of
* each delay value is 0-255.
*
* @param InstancePtr is a pointer to the XQspiPs instance.
* @param DelayNss is the delay to de-assert slave select between
* two word transfers.
* @param DelayBtwn is the delay between one Slave Select being
* de-activated and the activation of another slave. The delay is
* the number of master clock periods given by DelayBtwn + 2.
* @param DelayAfter define the delay between the last bit of the current
* byte transfer and the first bit of the next byte transfer.
* The delay in number of master clock periods is given as:
* CHPA=0:DelayInit+DelayAfter+3
* CHPA=1:DelayAfter+1
* @param DelayInit is the delay between asserting the slave select signal
* and the first bit transfer. The delay int number of master clock
* periods is DelayInit+1.
*
* @return
* - XST_SUCCESS if delays are successfully set.
* - XST_DEVICE_BUSY if the device is currently transferring data.
* The transfer must complete or be aborted before setting options.
*
* @note None.
*
******************************************************************************/
int XQspiPs_SetDelays(XQspiPs *InstancePtr, u8 DelayNss, u8 DelayBtwn,
u8 DelayAfter, u8 DelayInit)
{
u32 DelayRegister;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* Do not allow the delays to change while a transfer is in
* progress. Not thread-safe.
*/
if (InstancePtr->IsBusy) {
return XST_DEVICE_BUSY;
}
/* Shift, Mask and OR the values to build the register settings */
DelayRegister = (u32) DelayNss << XQSPIPS_DR_NSS_SHIFT;
DelayRegister |= (u32) DelayBtwn << XQSPIPS_DR_BTWN_SHIFT;
DelayRegister |= (u32) DelayAfter << XQSPIPS_DR_AFTER_SHIFT;
DelayRegister |= (u32) DelayInit;
XQspiPs_WriteReg(InstancePtr->Config.BaseAddress,
XQSPIPS_DR_OFFSET, DelayRegister);
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function gets the delay settings for an QSPI device.
* The delay register controls the Delay Between Transfers, Delay After
* Transfers, and the Delay Initially. The default value is 0x0.
*
* @param InstancePtr is a pointer to the XQspiPs instance.
* @param DelayNss is a pointer to the Delay to de-assert slave select
* between two word transfers.
* @param DelayBtwn is a pointer to the Delay Between transfers value.
* This is a return parameter.
* @param DelayAfter is a pointer to the Delay After transfer value.
* This is a return parameter.
* @param DelayInit is a pointer to the Delay Initially value. This is
* a return parameter.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void XQspiPs_GetDelays(XQspiPs *InstancePtr, u8 *DelayNss, u8 *DelayBtwn,
u8 *DelayAfter, u8 *DelayInit)
{
u32 DelayRegister;
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
DelayRegister = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress,
XQSPIPS_DR_OFFSET);
*DelayInit = (u8)(DelayRegister & XQSPIPS_DR_INIT_MASK);
*DelayAfter = (u8)((DelayRegister & XQSPIPS_DR_AFTER_MASK) >>
XQSPIPS_DR_AFTER_SHIFT);
*DelayBtwn = (u8)((DelayRegister & XQSPIPS_DR_BTWN_MASK) >>
XQSPIPS_DR_BTWN_SHIFT);
*DelayNss = (u8)((DelayRegister & XQSPIPS_DR_NSS_MASK) >>
XQSPIPS_DR_NSS_SHIFT);
}

View file

@ -0,0 +1,136 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xqspips_selftest.c
*
* This file contains the implementation of selftest function for the QSPI
* device.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00 sdm 11/25/10 First release
* 2.01a sg 02/03/13 Delay Register test is added with DelayNss parameter.
* 3.1 hk 06/19/14 Remove checks for CR and ISR register values as they are
* reset in the previous step.
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xqspips.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Definitions *****************************/
/*****************************************************************************/
/**
*
* Runs a self-test on the driver/device. The self-test is destructive in that
* a reset of the device is performed in order to check the reset values of
* the registers and to get the device into a known state.
*
* Upon successful return from the self-test, the device is reset.
*
* @param InstancePtr is a pointer to the XQspiPs instance.
*
* @return
* - XST_SUCCESS if successful
* - XST_REGISTER_ERROR indicates a register did not read or write
* correctly.
*
* @note None.
*
******************************************************************************/
int XQspiPs_SelfTest(XQspiPs *InstancePtr)
{
int Status;
u8 DelayTestNss;
u8 DelayTestBtwn;
u8 DelayTestAfter;
u8 DelayTestInit;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* Reset the QSPI device to leave it in a known good state
*/
XQspiPs_Reset(InstancePtr);
DelayTestNss = 0x5A;
DelayTestBtwn = 0xA5;
DelayTestAfter = 0xAA;
DelayTestInit = 0x55;
/*
* Write and read the delay register, just to be sure there is some
* hardware out there.
*/
Status = XQspiPs_SetDelays(InstancePtr, DelayTestNss, DelayTestBtwn,
DelayTestAfter, DelayTestInit);
if (Status != XST_SUCCESS) {
return Status;
}
XQspiPs_GetDelays(InstancePtr, &DelayTestNss, &DelayTestBtwn,
&DelayTestAfter, &DelayTestInit);
if ((0x5A != DelayTestNss) || (0xA5 != DelayTestBtwn) ||
(0xAA != DelayTestAfter) || (0x55 != DelayTestInit)) {
return XST_REGISTER_ERROR;
}
Status = XQspiPs_SetDelays(InstancePtr, 0, 0, 0, 0);
if (Status != XST_SUCCESS) {
return Status;
}
/*
* Reset the QSPI device to leave it in a known good state
*/
XQspiPs_Reset(InstancePtr);
return XST_SUCCESS;
}

View file

@ -0,0 +1,97 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xqspips_sinit.c
*
* The implementation of the XQspiPs component's static initialization
* functionality.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00 sdm 11/25/10 First release
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xstatus.h"
#include "xqspips.h"
#include "xparameters.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Definitions *****************************/
extern XQspiPs_Config XQspiPs_ConfigTable[];
/*****************************************************************************/
/**
*
* Looks up the device configuration based on the unique device ID. A table
* contains the configuration info for each device in the system.
*
* @param DeviceId contains the ID of the device to look up the
* configuration for.
*
* @return
*
* A pointer to the configuration found or NULL if the specified device ID was
* not found. See xqspips.h for the definition of XQspiPs_Config.
*
* @note None.
*
******************************************************************************/
XQspiPs_Config *XQspiPs_LookupConfig(u16 DeviceId)
{
XQspiPs_Config *CfgPtr = NULL;
int Index;
for (Index = 0; Index < XPAR_XQSPIPS_NUM_INSTANCES; Index++) {
if (XQspiPs_ConfigTable[Index].DeviceId == DeviceId) {
CfgPtr = &XQspiPs_ConfigTable[Index];
break;
}
}
return CfgPtr;
}