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:
parent
ebc7a9922b
commit
ee80739962
21 changed files with 9754 additions and 0 deletions
42
XilinxProcessorIPLib/drivers/qspips/data/qspips.mdd
Executable file
42
XilinxProcessorIPLib/drivers/qspips/data/qspips.mdd
Executable 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
|
52
XilinxProcessorIPLib/drivers/qspips/data/qspips.tcl
Executable file
52
XilinxProcessorIPLib/drivers/qspips/data/qspips.tcl
Executable 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"
|
||||
|
||||
}
|
40
XilinxProcessorIPLib/drivers/qspips/data/qspips_header.h
Normal file
40
XilinxProcessorIPLib/drivers/qspips/data/qspips_header.h
Normal 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
|
139
XilinxProcessorIPLib/drivers/qspips/data/qspips_tapp.tcl
Executable file
139
XilinxProcessorIPLib/drivers/qspips/data/qspips_tapp.tcl
Executable 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
|
||||
}
|
23
XilinxProcessorIPLib/drivers/qspips/examples/index.html
Executable file
23
XilinxProcessorIPLib/drivers/qspips/examples/index.html
Executable 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>
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
@ -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;
|
||||
}
|
|
@ -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
|
@ -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;
|
||||
}
|
40
XilinxProcessorIPLib/drivers/qspips/src/Makefile
Normal file
40
XilinxProcessorIPLib/drivers/qspips/src/Makefile
Normal 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}
|
1555
XilinxProcessorIPLib/drivers/qspips/src/xqspips.c
Normal file
1555
XilinxProcessorIPLib/drivers/qspips/src/xqspips.c
Normal file
File diff suppressed because it is too large
Load diff
782
XilinxProcessorIPLib/drivers/qspips/src/xqspips.h
Normal file
782
XilinxProcessorIPLib/drivers/qspips/src/xqspips.h
Normal 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 */
|
80
XilinxProcessorIPLib/drivers/qspips/src/xqspips_g.c
Normal file
80
XilinxProcessorIPLib/drivers/qspips/src/xqspips_g.c
Normal 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
|
||||
},
|
||||
};
|
221
XilinxProcessorIPLib/drivers/qspips/src/xqspips_hw.c
Normal file
221
XilinxProcessorIPLib/drivers/qspips/src/xqspips_hw.c
Normal 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);
|
||||
|
||||
}
|
385
XilinxProcessorIPLib/drivers/qspips/src/xqspips_hw.h
Normal file
385
XilinxProcessorIPLib/drivers/qspips/src/xqspips_hw.h
Normal 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 */
|
425
XilinxProcessorIPLib/drivers/qspips/src/xqspips_options.c
Normal file
425
XilinxProcessorIPLib/drivers/qspips/src/xqspips_options.c
Normal 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);
|
||||
}
|
136
XilinxProcessorIPLib/drivers/qspips/src/xqspips_selftest.c
Normal file
136
XilinxProcessorIPLib/drivers/qspips/src/xqspips_selftest.c
Normal 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;
|
||||
}
|
97
XilinxProcessorIPLib/drivers/qspips/src/xqspips_sinit.c
Normal file
97
XilinxProcessorIPLib/drivers/qspips/src/xqspips_sinit.c
Normal 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;
|
||||
}
|
Loading…
Add table
Reference in a new issue