/*
 * @brief Secondary loader protocol structures and manifest constants
 *
 * @note
 * Copyright(C) NXP Semiconductors, 2014
 * All rights reserved.
 *
 * @par
 * Software that is described herein is for illustrative purposes only
 * which provides customers with programming information regarding the
 * LPC products.  This software is supplied "AS IS" without any warranties of
 * any kind, and NXP Semiconductors and its licensor disclaim any and
 * all warranties, express or implied, including all implied warranties of
 * merchantability, fitness for a particular purpose and non-infringement of
 * intellectual property rights.  NXP Semiconductors assumes no responsibility
 * or liability for the use of the software, conveys no license or rights under any
 * patent, copyright, mask work right, or any other intellectual property rights in
 * or to any products. NXP Semiconductors reserves the right to make changes
 * in the software without notification. NXP Semiconductors also makes no
 * representation or warranty that such application will be suitable for the
 * specified use without further testing or modification.
 *
 * @par
 * Permission to use, copy, modify, and distribute this software and its
 * documentation is hereby granted, under NXP Semiconductors' and its
 * licensor's relevant copyrights in the software, without fee, provided that it
 * is used in conjunction with NXP Semiconductors microcontrollers.  This
 * copyright, permission, and disclaimer notice must appear in all copies of
 * this code.
 */
#ifndef _SL_PROTOCOL_H_
#define _SL_PROTOCOL_H_

#include <stdint.h>
#include "lpc_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/** @defgroup SL_PROTOCOL : Secondary Loader Protocol structures
 * @ingroup SENSOR_HUB
 * @{
 */

#define SL_FLASH_BLOCK_SZ           0x200		/*!< Block size */
#define SL_FLASH_SECT_SZ            0x400		/*!< Size of a flash sector */
#define SL_FLASH_END                0x8000		/*!< Total size of the flash. */
#define SL_FLASH_PAGE_SZ            0x40		/*!< Size of the flash page. */
#define SL_READ_SUBBLOCK_SZ         0x40
#define SL_KEY_BYTES                0x40
#define SL_I2C_SLAVE_ADDR_0         0x18
#define SL_I2C_SLAVE_ADDR_1         0x1C
#define SL_I2C_SLAVE_ADDR_2         0x30
#define SL_I2C_SLAVE_ADDR_3         0x38
#define SL_I2C_SLAVE_ADDR_LENOVO		0x40
/* Address of where the boot-able application is located in FLASH */

#define SL_BOOTAPP_ADDR1             0x00002000
#define SL_BOOTAPP_ADDR2             0x00005000

#define SL_BOOTAPP_START_BLOCK      (SL_BOOTAPP_ADDR1 / SL_FLASH_BLOCK_SZ)
#define SL_BOOTAPP_START_PAGE       (SL_BOOTAPP_ADDR1 / SL_FLASH_PAGE_SZ)

/* Offset in application where the IMG_HEADER_T is stored */
#define SL_BOOTAPP_IMGHDR_OFS       0x100
#define IMG_HEADER_MARKER           0xFEEDA5A5

#define PIN_SPI0_SCK_1      ((0 << 5) | 11)		/*!< Pin PIO0_11 has SPI0_SCK (1) function. */
#define PIN_SPI0_SCK_2      ((1 << 5) | 3)		/*!< Pin PIO1_3 has	SPI0_SCK (5) function. */
#define PIN_SPI0_MOSI_1     ((0 << 5) | 12)		/*!< Pin PIO0_12 has SPI0_MOSI (1) function. */
#define PIN_SPI0_MOSI_2     ((1 << 5) | 9)		/*!< Pin PIO1_9 has	SPI0_MOSI (2) function. */
#define PIN_SPI0_MISO_1     ((0 << 5) | 13)		/*!< Pin PIO0_13 has SPI0_MISO (1) function. */
#define PIN_SPI0_MISO_2     ((1 << 5) | 4)		/*!< Pin PIO1_4 has	SPI0_MISO (5) function. */
#define PIN_SPI0_SEL0_1     ((0 << 5) | 0)		/*!< Pin PIO0_0 has	SPI0_SSEL0 (2) function. */
#define PIN_SPI0_SEL0_2     ((0 << 5) | 9)		/*!< Pin PIO0_9 has	SPI0_SSEL0 (5) function. */
#define PIN_SPI0_SEL0_3     ((0 << 5) | 14)		/*!< Pin PIO0_14 has SPI0_SSEL0 (1) function. */

#define PIN_SPI1_SCK_1      ((1 << 5) | 6)		/*!< Pin PIO1_6 has	SPI1_SCK (2) function. */
#define PIN_SPI1_SCK_2      ((1 << 5) | 12)		/*!< Pin PIO1_12 has SPI1_SCK (4) function. */
#define PIN_SPI1_MOSI_1     ((1 << 5) | 7)		/*!< Pin PIO1_7 has SPI1_MOSI (2) function. */
#define PIN_SPI1_MOSI_2     ((1 << 5) | 13)		/*!< Pin PIO1_13 has SPI1_MOSI (4) function. */
#define PIN_SPI1_MISO_1     ((1 << 5) | 8)		/*!< Pin PIO1_8 has	SPI1_MISO (2) function. */
#define PIN_SPI1_MISO_2     ((1 << 5) | 14)		/*!< Pin PIO1_14 has SPI1_MISO (4) function. */
#define PIN_SPI1_SEL0_1     ((1 << 5) | 5)		/*!< Pin PIO1_5 has	SPI1_SSEL0 (2) function. */
#define PIN_SPI1_SEL0_2     ((1 << 5) | 15)		/*!< Pin PIO1_15 has SPI1_SSEL0 (4) function. */

#define PINCFG_GET_PORT(n)  (((n) >> 5) & 0x7)
#define PINCFG_GET_PIN(n)   ((n) & 0x1F)

/* Bootloader specific commands */
#define SH_CMD_WHO_AM_I             0xA0
#define SH_CMD_GET_VERSION          0xA1
#define SH_CMD_RESET                0xA2
#define SH_CMD_BOOT                 0xA3/*!< Command to boot the flashed image */
#define SH_CMD_CHECK_IMAGE          0xA4/*!< Command to check image integrity. Return 0 if matches else computed CRC32 value (not include CRC field in mage). */
#define SH_CMD_PROBE                0xA5
#define SH_CMD_WRITE_BLOCK          0xA6/*!< Command to write a block. Each block is 512 bytes. Check CmdRWBlockParam_t for message format.*/
#define SH_CMD_READ_BLOCK           0xA7/*!< Command to Read a block. Each block is 512 bytes. Check CmdRWBlockParam_t for message format.*/
#define SH_CMD_SECTOR_ERASE         0xA8
#define SH_CMD_PAGE_ERASE           0xA9
#define SH_CMD_PAGE_WRITE           0xAA
#define SH_CMD_PAGE_READ            0xAB
#define SH_CMD_WRITE_SUBBLOCK       0xAC
#define SH_CMD_READ_SUBBLOCK        0xAD

/* RW command parameter defines */
#define SH_RW_PARAM_SKIP_CRC        1
/* SH_CMD_PROBE command constants */
#define SH_PROBE_LEN                8
#define SH_PROBE_XOR_OFS            5

/* Response field size constants */
#define SH_RESP_HEADER_SIZE         4
#define SH_RESP_ERROR_CODE_SZ       4
#define SH_RESP_CRC32_SZ            4
#define SH_RESP_VERSION_SZ          2

/** Structure describing response packet format. */
typedef struct {
	uint8_t sop;							/*!< Start of packet = 0x55 for boatloader */
	uint8_t cmd;							/*!< Response to the Command ID. For notification use 0xFF. */
	uint16_t length;						/*!< Response data length not including the header. */
} CmdResponse_t;

/** Structure describing Read/Write block command packet format. */
typedef struct {
	uint8_t cmd;							/*!< Command ID */
	uint8_t crc_check;						/*!< specifies if we need to do CRC check before processing */
	uint16_t block_nr;						/*!< Block number.*/
	uint32_t data[SL_FLASH_BLOCK_SZ / 4];		/*!< Data */
	uint32_t crc32;							/*!< CRC32 of command header and data */
} CmdRWBlockParam_t;

/** Structure describing Read/Write page command packet format. */
typedef struct {
	uint8_t cmd;							/*!< Command ID */
	uint8_t crc_check;						/*!< specifies if we need to do CRC check before processing */
	uint16_t page_nr;						/*!< page number.*/
	uint32_t data[SL_FLASH_PAGE_SZ / 4];		/*!< Data */
	uint32_t crc32;							/*!< CRC32 of command header and data */
} CmdRWPageParam_t;

/** Structure describing Read sub-block command packet format. */
typedef struct {
	uint8_t cmd;							/*!< Command ID */
	uint8_t sub_block_nr;					/*!< specifies the sub-block number.
											    0 - Skip crc;
											    5-1: sub block nr;
											    7-6: sub-block size. 0 - 32, 1 - 64, 2 - 128, 3 - 256 */
	uint16_t block_nr;						/*!< block number.*/
	uint32_t data[SL_FLASH_BLOCK_SZ / 4];		/*!< Data */
} CmdReadSubBlockParam_t;

/** Structure describing Sector erase command packet format. */
typedef struct {
	uint8_t cmd;							/*!< Command ID */
	uint8_t reserved;						/*!< Should be zero. */
	uint16_t sec_nr;						/*!< Sector number.*/
} CmdEraseSectorParam_t;

/** Structure describing response packet with data. */
typedef struct {
	CmdResponse_t hdr;						/*!< Response header. */
	uint32_t data[SL_FLASH_BLOCK_SZ / 4];		/*!< Data */
	uint32_t crc32;							/*!< CRC32 of response packet. */
} CmdDataResp_t;

/** Host interface sources */
typedef enum {
	SL_AUTO = 0,		/*!< Auto-detect used for secondary loader host interface */
	SL_I2C0,			/*!< I2C0 used for secondary loader host interface */
	SL_I2C1,			/*!< I2C1 used for secondary loader host interface */
	SL_I2C2,			/*!< I2C1 used for secondary loader host interface */
	SL_SPI0,			/*!< SPI0 used for secondary loader host interface */
	SL_SPI1				/*!< SPI1 used for secondary loader host interface */
} SL_IFSEL_T;

/** Image type enum */
typedef enum {
	IMG_NORMAL = 0,		/*!< Normal image check IRQ line to halt boot. */
	IMG_AP_WAIT,		/*!< Wait for AP to send SH_CMD_BOOT command */
	IMG_NO_WAIT,		/*!< Boot image without checking IRQ line. CRC check is still done. */
	IMG_NO_CRC,			/*!< No CRC or AP IRQ line checks needed. Used during development. */
	IMG_PROBE = 0xA5,	/*!< Image type used with SH_CMD_PROBE command. */
} SL_IMAGE_T;

/** Structure used to setup host interface for the secondary loader. The SPI
   port/pin selections for SSEL, SCK, MOSI, and MISO only need to be configured
   if ifSel is SL_SPI0 or SL_SPI1. */
typedef struct {
	uint8_t img_type;		/*!< Image type (SL_IMAGE_T)  */
	uint8_t ifSel;			/*!< Interface selection for host (SL_IFSEL_T) */
	uint8_t hostIrqPortPin;	/*!< Host IRQ port (bits 7:5) and pins (bits 4:0) */
	uint8_t hostMisoPortPin;	/*!< SPI MISO port (bits 7:5) and pins (bits 4:0) */
	uint8_t hostMosiPortPin;	/*!< SPI MOSI port (bits 7:5) and pins (bits 4:0) */
	uint8_t hostSselPortPin;	/*!< SPI SEL port (bits 7:5) and pins (bits 4:0) */
	uint8_t hostSckPortPin;		/*!< SPI SCK port (bits 7:5) and pins (bits 4:0) */
	uint8_t checksum;		/*!< Checksum. XOR of the remaining 7 bytes of this structure. */
} SL_PINSETUP_T;

/** Image header structure. All application images should define this structure at of offset 0x100.
 *	Adding it to the start-up file is recommended.
 */
typedef struct _IMG_HEADER_T {
	uint32_t header_marker;						/*!< Image header marker should always be set to 0xFEEDA5A5 */
	SL_PINSETUP_T hostifPinCfg;					/*!< Host interface pin configuration */
	const uint32_t crc_len;						/*!< Image length or the length of image CRC check should be done. For faster boot application could set a smaller length than actual image */
	const uint32_t crc_value;					/*!< CRC vale  */
} IMG_HEADER_T;

#ifdef WIN32
typedef unsigned char bool;
#define STATIC static
#define INLINE
#endif

typedef bool (*InBootSecondaryLoader)(const SL_PINSETUP_T *pSetup);

/* Address of indtrect boot table */
#define SL_INDIRECT_FUNC_TABLE      (0x00007F00)

/* Placement addresses for app call flag and app supplied config daa
   for host interface pins. Note these addresses may be used in the
   startup code source and may need values changed there also. */
#define SL_ADDRESS_APPCALLEDFL      (0x10000000)
#define SL_ADDRESS_APPPINDATA       (0x10000004)

/* Function for booting the secondary loader from an application. Returns with
   false if the pSetup strructure is not valid, or doesn't return if the
   loader was started successfully. */
static INLINE bool bootSecondaryLoader(const SL_PINSETUP_T *pSetup)
{
	InBootSecondaryLoader SL, *pSL = (InBootSecondaryLoader *) SL_INDIRECT_FUNC_TABLE;
	SL_PINSETUP_T *pAppPinSetup = (SL_PINSETUP_T *) SL_ADDRESS_APPPINDATA;

	*pAppPinSetup = *pSetup;

	SL = *pSL;
	return SL(pSetup);
}

/**
 * @}
 */

#ifdef __cplusplus
}
#endif

#endif  /* _SL_PROTOCOL_H_ */
