/******************************************************************************
*
* Copyright (C) 2018 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
* XILINX  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 xqspipsu.h
* @addtogroup qspipsu_v1_7
* @{
* @details
*
* This is the header file for the implementation of QSPIPSU driver.
* Generic QSPI interface allows for communication to any QSPI slave device.
* GQSPI contains a GENFIFO into which the bus transfers required are to be
* pushed with appropriate configuration. The controller provides TX and RX
* FIFO's and a DMA to be used for RX transfers. The controller executes each
* GENFIFO entry noting the configuration and places data on the bus as required
*
* The different options in GENFIFO are as follows:
* IMM_DATA : Can be one byte of data to be transmitted, number of clocks or
*            number of bytes in transfer.
* DATA_XFER : Indicates that data/clocks need to be transmitted or received.
* EXPONENT : e when 2^e bytes are involved in transfer.
* SPI_MODE : SPI/Dual SPI/Quad SPI
* CS : Lower or Upper CS or Both
* Bus : Lower or Upper Bus or Both
* TX : When selected, controller transmits data in IMM or fetches number of
*      bytes mentioned form TX FIFO. If not selected, dummies are pumped.
* RX : When selected, controller receives and fills the RX FIFO/allows RX DMA
*      of requested number of bytes. If not selected, RX data is discarded.
* Stripe : Byte stripe over lower and upper bus or not.
* Poll : Polls response to match for to a set value (used along with POLL_CFG
*        registers) and then proceeds to next GENFIFO entry.
*        This feature is not currently used in the driver.
*
* GENFIFO has manual and auto start options.
* All DMA requests need a 4-byte aligned destination address buffer and
* size of transfer should also be a multiple of 4.
* This driver supports DMA RX and IO RX.
*
* Initialization:
* This driver uses the GQSPI controller with RX DMA. It supports both
* interrupt and polled transfers. Manual start of GENFIFO is used.
* XQspiPsu_CfgInitialize() initializes the instance variables.
* Additional setting can be done using SetOptions/ClearOptions functions
* and SelectSlave function.
*
* Transfer:
* Polled or Interrupt transfers can be done. The transfer function needs the
* message(s) to be transmitted in the form of an array of type XQspiPsu_Msg.
* This is supposed to contain the byte count and any TX/RX buffers as required.
* Flags can be used indicate further information such as whether the message
* should be striped. The transfer functions form and write GENFIFO entries,
* check the status of the transfer and report back to the application
* when done.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver   Who Date     Changes
* ----- --- -------- -----------------------------------------------.
* 1.0   hk  08/21/14 First release
*       sk  03/13/15 Added IO mode support.
*       hk  03/18/15 Switch to I/O mode before clearing RX FIFO.
*                    Clear and disbale DMA interrupts/status in abort.
*                    Use DMA DONE bit instead of BUSY as recommended.
*       sk  04/24/15 Modified the code according to MISRAC-2012.
*       sk  06/17/15 Removed NULL checks for Rx/Tx buffers. As
*                    writing/reading from 0x0 location is permitted.
* 1.1   sk  04/12/16 Added debug message prints.
* 1.2	nsk 07/01/16 Added LQSPI support
*		     Modified XQspiPsu_Select() macro in xqspipsu.h
*		     Added XQspiPsu_GetLqspiConfigReg() in xqspipsu.h
*		     Added required macros in xqspipsu_hw.h
*		     Modified XQspiPsu_SetOptions() to support
*		     LQSPI options and updated OptionsTable in
*		     xqspipsu_options.c
*       rk  07/15/16 Added support for TapDelays at different frequencies.
*	nsk 08/05/16 Added example support PollData and PollTimeout
*		     Added  XQSPIPSU_MSG_FLAG_POLL macro in xqspipsu.h
*		     Added XQspiPsu_Create_PollConfigData and
*		     XQspiPsu_PollData() functions in xqspipsu.c
* 1.3	nsk 09/16/16 Update PollData and Polltimeout support for dual parallel
*	             configuration. Updated XQspiPsu_PollData() and
*	             XQspiPsu_Create_PollConfigData() functions in xqspipsu.c
*                    and also modified the polldata example
*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
*                    generation.
*       ms  04/05/17 Modified Comment lines in functions of qspipsu
*                    examples to recognize it as documentation block
*                    and modified filename tag to include them in
*                    doxygen examples.
* 1.4	tjs 05/26/17 Added support for accessing upper DDR (0x800000000)
*		     while booting images from QSPI
* 1.5	tjs	08/08/17 Added index.html file for importing examples from system.mss
* 1.5	nsk 08/14/17 Added CCI support
* 1.5	tjs 09/14/17 Modified the checks for 4 byte addressing and commands.
* 1.6	tjs 10/16/17 Flow for accessing flash is made similar to u-boot and linux
* 					 For CR-984966
* 1.6   tjs 11/02/17 Resolved the compilation errors for ICCARM. CR-988625
* 1.7   tjs 11/16/17 Removed the unsupported 4 Byte write and sector erase
*                    commands.
* 1.7	tjs	12/01/17 Added support for MT25QL02G Flash from Micron. CR-990642
* 1.7	tjs 12/19/17 Added support for S25FL064L from Spansion. CR-990724
* 1.7	tjs 01/11/18 Added support for MX66L1G45G flash from Macronix CR-992367
* 1.7	tjs	01/16/18 Removed the check for DMA MSB to be written. (CR#992560)
* 1.7	tjs	01/17/18 Added support to toggle the WP pin of flash. (PR#2448)
*                    Added XQspiPsu_SetWP() in xqspipsu_options.c
*                    Added XQspiPsu_WriteProtectToggle() in xqspipsu.c and
*                    also added write protect example.
* 1.7	tjs	03/14/18 Added support in EL1 NS mode (CR#974882)
* 1.7	tjs 26/03/18 In dual parallel mode enable both CS when issuing Write
*		     		 enable command. CR-998478
* </pre>
*
******************************************************************************/
#ifndef XQSPIPSU_H_		/* prevent circular inclusions */
#define XQSPIPSU_H_		/* by using protection macros */

#ifdef __cplusplus
extern "C" {
#endif

/***************************** Include Files *********************************/

#include "xstatus.h"
#include "xqspipsu_hw.h"
#include "xil_cache.h"

/**************************** Type Definitions *******************************/
/**
 * The handler data type allows the user to define a callback function to
 * handle the asynchronous processing for the QSPIPSU 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 XQspiPsu_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 (*XQspiPsu_StatusHandler) (void *CallBackRef, u32 StatusEvent,
					u32 ByteCount);

/**
 * This typedef contains configuration information for a flash message.
 */
typedef struct {
	u8 *TxBfrPtr;
	u8 *RxBfrPtr;
	u32 ByteCount;
	u32 BusWidth;
	u32 Flags;
	u8 PollData;
	u32 PollTimeout;
	u8 PollStatusCmd;
	u8 PollBusMask;
} XQspiPsu_Msg;

/**
 * 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 */
	u8  BusWidth; 	/**< Bus width available on board */
	u8 IsCacheCoherent; /**< Describes whether Cache Coherent or not */
} XQspiPsu_Config;

/**
 * The XQspiPsu driver instance data. The user is required to allocate a
 * variable of this type for every QSPIPSU device in the system. A pointer
 * to a variable of this type is then passed to the driver API functions.
 */
typedef struct {
	XQspiPsu_Config Config;	 /**< Configuration structure */
	u32 IsReady;		 /**< Device is initialized and ready */

	u8 *SendBufferPtr;	 /**< Buffer to send (state) */
	u8 *RecvBufferPtr;	 /**< Buffer to receive (state) */
	u8 *GenFifoBufferPtr;	 /**< Gen FIFO entries */
	s32 TxBytes;	 /**< Number of bytes to transfer (state) */
	s32 RxBytes;	 /**< Number of bytes left to transfer(state) */
	s32 GenFifoEntries;	 /**< Number of Gen FIFO entries remaining */
	u32 IsBusy;		 /**< A transfer is in progress (state) */
	u32 ReadMode;		 /**< DMA or IO mode */
	u32 GenFifoCS;
	u32 GenFifoBus;
	s32 NumMsg;
	s32 MsgCnt;
	s32 IsUnaligned;
	u8 IsManualstart;
	XQspiPsu_Msg *Msg;
	XQspiPsu_StatusHandler StatusHandler;
	void *StatusRef;  	 /**< Callback reference for status handler */
} XQspiPsu;

/***************** Macros (Inline Functions) Definitions *********************/

#define XQSPIPSU_READMODE_DMA	0x0U
#define XQSPIPSU_READMODE_IO	0x1U

#define XQSPIPSU_SELECT_FLASH_CS_LOWER	0x1U
#define XQSPIPSU_SELECT_FLASH_CS_UPPER	0x2U
#define XQSPIPSU_SELECT_FLASH_CS_BOTH	0x3U

#define XQSPIPSU_SELECT_FLASH_BUS_LOWER	0x1U
#define XQSPIPSU_SELECT_FLASH_BUS_UPPER	0x2U
#define XQSPIPSU_SELECT_FLASH_BUS_BOTH	0x3U

#define XQSPIPSU_SELECT_MODE_SPI	0x1U
#define XQSPIPSU_SELECT_MODE_DUALSPI	0x2U
#define XQSPIPSU_SELECT_MODE_QUADSPI	0x4U

#define XQSPIPSU_GENFIFO_CS_SETUP	0x05U
#define XQSPIPSU_GENFIFO_CS_HOLD	0x04U

#define XQSPIPSU_CLK_ACTIVE_LOW_OPTION	0x2U
#define XQSPIPSU_CLK_PHASE_1_OPTION	0x4U
#define XQSPIPSU_MANUAL_START_OPTION	0x8U
#define XQSPIPSU_LQSPI_MODE_OPTION	0x20U

#define XQSPIPSU_GENFIFO_EXP_START	0x100U

#define XQSPIPSU_DMA_BYTES_MAX		0x10000000U

#define XQSPIPSU_CLK_PRESCALE_2		0x00U
#define XQSPIPSU_CLK_PRESCALE_4		0x01U
#define XQSPIPSU_CLK_PRESCALE_8		0x02U
#define XQSPIPSU_CLK_PRESCALE_16		0x03U
#define XQSPIPSU_CLK_PRESCALE_32		0x04U
#define XQSPIPSU_CLK_PRESCALE_64		0x05U
#define XQSPIPSU_CLK_PRESCALE_128	0x06U
#define XQSPIPSU_CLK_PRESCALE_256	0x07U
#define XQSPIPSU_CR_PRESC_MAXIMUM	7U

#define XQSPIPSU_CONNECTION_MODE_SINGLE		0U
#define XQSPIPSU_CONNECTION_MODE_STACKED	1U
#define XQSPIPSU_CONNECTION_MODE_PARALLEL	2U

/*QSPI Frequencies*/
#define XQSPIPSU_FREQ_40MHZ 40000000
#define XQSPIPSU_FREQ_100MHZ 100000000
#define XQSPIPSU_FREQ_150MHZ 150000000

/* Add more flags as required */
#define XQSPIPSU_MSG_FLAG_STRIPE	0x1U
#define XQSPIPSU_MSG_FLAG_RX		0x2U
#define XQSPIPSU_MSG_FLAG_TX		0x4U
#define XQSPIPSU_MSG_FLAG_POLL		0x8U

/* GQSPI configuration to toggle WP of flash*/
#define XQSPIPSU_SET_WP					1

#define XQspiPsu_Select(InstancePtr, Mask)	XQspiPsu_Out32(((InstancePtr)->Config.BaseAddress) + XQSPIPSU_SEL_OFFSET, Mask)

#define XQspiPsu_Enable(InstancePtr)	XQspiPsu_Out32(((InstancePtr)->Config.BaseAddress) + XQSPIPSU_EN_OFFSET, XQSPIPSU_EN_MASK)

#define XQspiPsu_Disable(InstancePtr)	XQspiPsu_Out32(((InstancePtr)->Config.BaseAddress) + XQSPIPSU_EN_OFFSET, 0x0U)

#define XQspiPsu_GetLqspiConfigReg(InstancePtr)   XQspiPsu_In32((XQSPIPS_BASEADDR) + XQSPIPSU_LQSPI_CR_OFFSET)


/************************** Function Prototypes ******************************/

/* Initialization and reset */
XQspiPsu_Config *XQspiPsu_LookupConfig(u16 DeviceId);
s32 XQspiPsu_CfgInitialize(XQspiPsu *InstancePtr, XQspiPsu_Config *ConfigPtr,
				u32 EffectiveAddr);
void XQspiPsu_Reset(XQspiPsu *InstancePtr);
void XQspiPsu_Abort(XQspiPsu *InstancePtr);

/* Transfer functions and handlers */
s32 XQspiPsu_PolledTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
				u32 NumMsg);
s32 XQspiPsu_InterruptTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
				u32 NumMsg);
s32 XQspiPsu_InterruptHandler(XQspiPsu *InstancePtr);
void XQspiPsu_SetStatusHandler(XQspiPsu *InstancePtr, void *CallBackRef,
				XQspiPsu_StatusHandler FuncPointer);

/* Configuration functions */
s32 XQspiPsu_SetClkPrescaler(XQspiPsu *InstancePtr, u8 Prescaler);
void XQspiPsu_SelectFlash(XQspiPsu *InstancePtr, u8 FlashCS, u8 FlashBus);
s32 XQspiPsu_SetOptions(XQspiPsu *InstancePtr, u32 Options);
s32 XQspiPsu_ClearOptions(XQspiPsu *InstancePtr, u32 Options);
u32 XQspiPsu_GetOptions(XQspiPsu *InstancePtr);
s32 XQspiPsu_SetReadMode(XQspiPsu *InstancePtr, u32 Mode);
void XQspiPsu_SetWP(XQspiPsu *InstancePtr, u8 Value);
void XQspiPsu_WriteProtectToggle(XQspiPsu *InstancePtr, u32 Toggle);

#ifdef __cplusplus
}
#endif


#endif /* XQSPIPSU_H_ */
/** @} */
