/*
 * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * o Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * o Redistributions in binary form must reproduce the above copyright notice, this
 *   list of conditions and the following disclaimer in the documentation and/or
 *   other materials provided with the distribution.
 *
 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#ifndef _SPI_FLASH_H_
#define _SPI_FLASH_H_


#include "fsl_spi_abstraction.h"

/*!
 * @addtogroup spi_flash_common
 * @{
 */

/*!
 * @file
 */

#define SPI_FLASH_AT26_FAMILY

#define ROUND(a,b)	(((a) + (b)) & ~((b) - 1))
#define sf_offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)

/*******************************************************************************
 * Definitions
 ******************************************************************************/

/*!
 * @brief SPI Flash common structure.
 *
 * For every spi flash chip driver, add this structure to chip structure.
 * This structure is for spi flash framework and describes common features
 * of spi flash.
 * Normally, in spi_flash_alloc function, @c read, @c write and @c erase member will be
 * set to common accordingly functions in spi_flash.c. If flash chip need a special handle
 * function, they should be changed in flash chip's probe function.
 */
typedef struct SpiFlash {
	uint32_t	instance;	/*!< SPI bus index.*/
	spi_slave_dev *spi;		/*!< SPI slave device instance.*/

	const char	*name;		/*!< SPI flash chip name. Chip name is added in each spi flash's chip driver file.*/

	uint32_t	size;		/*!< Total flash size.*/
	uint32_t	page_size;	/*!< Write (page) size*/
	uint32_t	sector_size;	/*!< Erase (sector) size*/

	int32_t	(*read)(struct SpiFlash *flash, uint32_t offset,	/*!< Read function pointer.*/
				size_t len, uint8_t *buf);
	int32_t	(*write)(struct SpiFlash *flash, uint32_t offset,	/*!< Write function pointer.*/
				size_t len, const uint8_t *buf);
	int32_t	(*erase)(struct SpiFlash *flash, uint32_t offset,	/*!< Erase function pointer.*/
				size_t len);
} spi_flash;

#if defined(__cplusplus)
extern "C" {
#endif

/*!
 * @brief     Allocate a new spi flash structure.
 *
 * The structure is allocated and cleared with default values for
 * read, write and erase, which the caller can modify. The caller must set
 * up size, page_size and sector_size.
 *
 * Use the helper macro spi_flash_alloc() to call this.
 *
 * @param[in] offset       Offset of struct spi_slave within slave structure.
 * @param[in] size         Size of slave structure.
 * @param[in] spi          SPI slave.
 * @param[in] name         Name of SPI flash device.
 */
void *spi_flash_alloc(int32_t offset, int32_t size, void *sf, spi_slave_dev *spi,
			 const char *name);

/*!
 * @brief    Probe a spi flash.
 *
 * @param[in] bus          spi master device index.
 * @param[in] cs           spi slave device SS pin index.
 * @param[in] max_hz       max hz supported by spi flash.
 * @param[in] mode         clock phase and polarity mode.
 *
 * @return    spi_flash    instance for a detected spi flash.
 */
spi_flash *spi_flash_probe(uint32_t bus, uint32_t cs,
		uint32_t max_hz, uint32_t spi_mode);

/*!
 * @brief    Alloc access functions for a detected spi flash.
 *
 * @param[in] offset       spi_flash structure offset in spi flash structure.
 * @param[in] size         size of spi flash structure.
 * @param[in] spi          spi slave device for the spi flash.
 * @param[in] name         id of the spi flash.
 *
 * @return    pointer      pointer of spi flash sturcture.
 */
void spi_flash_free(spi_flash *flash);

/*!
 * @brief    Common funcion to read data from a spi flash.
 *
 * @param[in] flash        spi flash structure.
 * @param[in] offset       offset in spi flash.
 * @param[in] len          data length.
 * @param[in] buf          output data buffer.
 *
 * @return    status       error code.
 */
static inline int32_t spi_flash_read(spi_flash *flash, uint32_t offset,
		size_t len, void *buf)
{
	return flash->read(flash, offset, len, buf);
}

/*!
 * @brief    Common funcion to write multiply page of data to a spi flash.
 *
 * @param[in] flash        spi flash structure.
 * @param[in] offset       offset in spi flash.
 * @param[in] len          data length.
 * @param[in] buf          input data buffer.
 *
 * @return    status       error code.
 */
static inline int32_t spi_flash_write(spi_flash *flash, uint32_t offset,
		size_t len, const void *buf)
{
	return flash->write(flash, offset, len, buf);
}

/*!
 * @brief    Common funcion erase blocks in a spi flash.
 *
 * @param[in] flash        spi flash structure.
 * @param[in] offset       offset in spi flash to erase from.
 * @param[in] len          length in spi flash to be erased.
 *
 * @return    status       error code.
 */
static inline int32_t spi_flash_erase(spi_flash *flash, uint32_t offset,
		size_t len)
{
	return flash->erase(flash, offset, len);
}

#if defined(__cplusplus)
}
#endif

/*!
 * @}
 */

#endif /* _SPI_FLASH_H_ */

/*******************************************************************************
 * EOF
 ******************************************************************************/
