/* SPDX-License-Identifier: LGPL-2.1-only OR BSD-3-Clause */
/******************************************************************************
 *
 * This file is provided under a dual license.  When you use or
 * distribute this software, you may choose to be licensed under
 * version 2.1 of the GNU Lesser General Public License
 * ("LGPLv2.1 License") or BSD License.
 *
 * LGPLv2.1 License
 *
 * Copyright(C) 2019 MediaTek Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2.1 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html for more
 * details.
 *
 * BSD LICENSE
 *
 * Copyright(C) 2019 MediaTek 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:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * 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.
 *  * Neither the name of the copyright holder 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.
 *
 *****************************************************************************/

/*-----------------------------------------------------------------------------
 *
 * $Author: dtvbm11 $
 * $Date: 2015/11/10 $
 * $RCSfile: nand_if.h,v $
 * $Revision: #1 $
 *
 *---------------------------------------------------------------------------*/

/** @file nand_if.h
 *  nand_if.h The NAND driver export function declaration.
 */

#ifndef NAND_IF_H
#define NAND_IF_H

//-----------------------------------------------------------------------------
// Include files
//-----------------------------------------------------------------------------

#include "x_typedef.h"
#include "storage_if.h"

//-----------------------------------------------------------------------------
// Constant definitions
//-----------------------------------------------------------------------------
#if defined(CC_MTK_LOADER) || defined(__cpluscplus)
    #define NAND_ENABLE_ISR             (0)
#else
    #define NAND_ENABLE_ISR             (1)
#endif

#define NAND_MULTIPAGE_ACCESS           (0)

#define NAND_CTRL_FLAGS_ECC             ((UINT32)0x1)
#define NAND_CTRL_FLAGS_DMA             ((UINT32)0x2)
#define NAND_CTRL_FLAGS_ISR             ((UINT32)0x4)
#define NAND_CTRL_FLAGS_ALL             ((UINT32)0xFFFFFFFF)

//-----------------------------------------------------------------------------
// IOCTL flags
//-----------------------------------------------------------------------------
#define NAND_IOCTL_GET_NANDSIZE         (0x00000001)
#define NAND_IOCTL_GET_BLOCKSIZE        (0x00000002)
#define NAND_IOCTL_GET_PARTITION_NUM    (0x00000003)
#define NAND_IOCTL_GET_PARTITION_SIZE   (0x00000004)
#define NAND_IOCTL_LOWLEVEL_FORMAT      (0x00000110)

#if (defined(CC_MT5398) && defined(CC_NAND_60BIT)) || defined(CC_MT5399)
    #define NAND_MAX_PAGE_SIZE              (1024*16)
    #define NAND_MAX_OOB_SIZE               (80*16)
#else 
    #define NAND_MAX_PAGE_SIZE              (1024*8)
    #define NAND_MAX_OOB_SIZE               (64*8)
#endif
#define NAND_NAME_MAX_SIZE              (32)

#define NAND_SDMDUMP_BAD                (0x01)
#define NAND_SDMDUMP_EMPTY              (0x02)
#define NAND_SDMDUMP_USED               (0x04)
#define NAND_SDMDUMP_DIRTY              (0x08)
#define NAND_SDMDUMP_LOGIC              (0x10)
#define NAND_SDMDUMP_ALL                (0x0F)
#ifdef CC_MTD_SUPPORT_64_PARTITION
#define NANDPART_PARTNUM                (64)
#else
#define NANDPART_PARTNUM                (32)
#endif
//-----------------------------------------------------------------------------
// Type definitions
//-----------------------------------------------------------------------------

// Device
typedef struct strucNandDev
{
    UINT32 u4PgSz;
    UINT32 u4BlkSz;
    UINT32 u4OOBSz;
    UINT32 u4TotalBlk;
    UINT32 u4TotalSize;
    UINT32 u4PgPerBlk;
    BOOL   fgMLC;
    UINT32 u4BBMode;
} NANDDEV_T;

typedef enum
{
    NAND_ECC_NONE,
    NAND_ECC_SOFT,
    NAND_ECC_HARD,
} NAND_ECC_TYPE_T;

typedef struct
{
    NAND_ECC_TYPE_T rEccType;
    BOOL fgDMA;
    BOOL fgIsr;
} NAND_CONTROL_T;

//-----------------------------------------------------------------------------
// NAND partition struct
//-----------------------------------------------------------------------------
typedef enum
{
    NANDPART_NONE,
    NANDPART_BDM,
    NANDPART_SDM,
} NANDPART_TYPE;

typedef enum
{
    NANDPART_ATTRB_READONLY,
    NANDPART_ATTRB_READWRITE,
} NANDPART_ATTRB;

typedef INT32 (*PFN_NANDREAD)(UINT8 u1Part, UINT32 u4Offset, UINT32 u4MemPtr, UINT32 u4Memlen);
typedef INT32 (*PFN_NANDWRITE)(UINT8 u1Part, UINT32 u4Offset, UINT32 u4MemPtr, UINT32 u4Memlen);

typedef struct
{
    UINT8           u1PartId;
    CHAR            cName[NAND_NAME_MAX_SIZE];
    UINT32          u4Offset;
    UINT32          u4Size;
    NANDPART_TYPE   rType;
    NANDPART_ATTRB  rAttrb;

    PFN_NANDREAD    pfnNandRead;
    PFN_NANDWRITE   pfnNandWrite;
} NANDPART_STRUCT_T;

//-----------------------------------------------------------------------------
// mtk partition information 
//-----------------------------------------------------------------------------
typedef struct
{
    UINT32  u4PgStart;
    UINT32  u4PgEnd;
    UINT32  u4Encryped;
} mtk_part_info_t;

//-----------------------------------------------------------------------------
// Public functions
//-----------------------------------------------------------------------------
extern void NAND_SetControl(UINT32 u4Flag, NAND_CONTROL_T *prCtrl);
EXTERN void NAND_GetControl(UINT32 u4Flag, NAND_CONTROL_T *prCtrl);

#ifdef CC_FCI_ENABLE
// fix me
EXTERN BOOL NAND_QuerySetSwEcc(const BOOL *pfgSet);     // Compatible to XD
#endif

EXTERN VOID NAND_ApiLock(HANDLE_T *hhSema);
EXTERN VOID NAND_ApiUnLock(HANDLE_T *hhSema);

EXTERN void NAND_Init(void);
EXTERN void NAND_Stop(void);
EXTERN void NAND_Reset(void);
EXTERN INT32 NAND_Diag(void);
EXTERN INT32 NAND_GetInfo(NANDDEV_T *prNand);
EXTERN char* NAND_GetName(void);
EXTERN INT32 NAND_ReadID(UINT32 *pID);

// Storage device interface function
EXTERN INT32 NAND_Read(UINT64 u4Offset, UINT32 u4MemPtr, UINT32 u4MemLen);
EXTERN INT32 NAND_Write(UINT64 u4Offset, UINT32 u4MemPtr, UINT32 u4MemLen);
EXTERN INT32 NAND_ReadAttr(UINT64 u4Offset, UINT32 u4MemPtr, UINT32 u4SparePtr, UINT32 u4MemLen);
#if defined(CC_NAND_WRITE_VERIFY)
EXTERN INT32 NAND_VerifyAttr(UINT64 u8Offset, UINT32 u4MemLen);
#endif
EXTERN INT32 NAND_WriteAttr(UINT64 u4Offset, UINT32 u4MemPtr, UINT32 u4SparePtr, UINT32 u4MemLen);
EXTERN INT32 NAND_Erase(UINT32 u4PageIdx, UINT32 u4PageNum);
EXTERN INT32 NAND_EraseForce(UINT32 u4PageIdx, UINT32 u4PageNum);
EXTERN INT32 NAND_RdAttr(UINT64 u8Offset, UINT32 u4DataMemPtr, UINT32 u4ByteCount);
EXTERN INT32 NAND_WrAttr(UINT64 u8Offset, UINT32 u4DataMemPtr, UINT32 u4ByteCount);
EXTERN INT64 NAND_GetSize(void);

EXTERN INT32 NAND_ReadBlock(UINT64 u8Offset, UINT32 u4MemPtr, UINT32 u4MemLen);
EXTERN INT32 NAND_BlankCheck(UINT64 u8Offset, UINT32 u4PageCount);
EXTERN INT32 NAND_BlankCheckAttr(UINT64 u8Offset, UINT32 u4PageCount);

EXTERN BOOL NAND_IsBadBlk(UINT32 u4BlkNum);
EXTERN BOOL NAND_MarkBadBlk(UINT32 u4BlkNum);

EXTERN void NAND_ShowDevList(void);

// nand_part.c
EXTERN INT32 NANDPART_Init(void);
EXTERN NANDPART_STRUCT_T* NANDPART_GetPartStruct(void);
EXTERN void NANDPART_ShowPartition(void);

#ifndef NDEBUG  /*only valid in debug version*/
EXTERN UINT32 NANDPART_Writer_NandStructure(void);
EXTERN UINT32 NANDPART_Writer_NandLayout(void);
#endif

EXTERN INT32 NANDPART_IORequest(UINT8 u1PartId, UINT32 u4Offset, UINT32 u4MemPtr, UINT32 u4MemLen, BOOL fgRead);
EXTERN INT32 NANDPART_Mount(UINT8 u1PartId, NANDPART_TYPE rType, UINT32 u4Offset, UINT32 u4Size);
EXTERN INT32 NANDPART_UnMount(UINT8 u1PartId);
EXTERN INT32 NANDPART_Read(UINT64 u8Offset, UINT32 u4MemPtr, UINT32 u4MemLen);
EXTERN INT32 NANDPART_Write(UINT64 u8Offset, UINT32 u4MemPtr, UINT32 u4MemLen);
EXTERN INT32 NANDPART_BulkWrite(UINT64 u8Offset, UINT8 u1Val, UINT32 u4MemLen);
EXTERN INT32 NANDPART_GetSectorTbl(SECTTBL_T *pt_sector_tbl, UINT32 u4Pid);
EXTERN INT32 NANDPART_GetMWPartNum(void);
EXTERN UINT32 NANDPART_GetMaxPartId(void);
EXTERN UINT32 NANDPART_GetPartSize(UINT32 u4Pid);
EXTERN INT32 NANDPART_Erase(UINT8 u1PartId);
EXTERN UINT32 NANDPART_GetPageSize(UINT32 u4Pid);

// nand_bdm.c
EXTERN INT32 NAND_BDM_Mount(UINT8 u1PartId);
EXTERN INT32 NAND_BDM_UnMount(UINT8 u1PartId);
EXTERN INT32 NAND_BDM_Format(UINT8 u1PartId);

//EXTERN INT32 NAND_BDM_ReadBlocks(UINT8 u1Part, UINT32 u4Offset, UINT32 u4MemPtr, UINT32 u4MemLen);
EXTERN INT32 NAND_BDM_WriteBlocks(UINT8 u1Part, UINT32 u4Offset, UINT32 u4MemPtr, UINT32 u4MemLen);
EXTERN INT32 NAND_BDM_ReadSectors(UINT8 u1Part, UINT32 u4Offset, UINT32 u4MemPtr, UINT32 u4MemLen);
EXTERN INT32 NAND_BDM_WriteSectors(UINT8 u1Part, UINT32 u4Offset, UINT32 u4MemPtr, UINT32 u4MemLen);
EXTERN INT32 NAND_BDM_ReadPages(UINT8 u1Part, UINT32 u4Offset, UINT32 u4MemPtr, UINT32 u4MemLen);

// nand_sdm.c
EXTERN INT32 NAND_SDM_Mount(UINT8 u1PartId);
EXTERN INT32 NAND_SDM_UnMount(UINT8 u1PartId);

//EXTERN INT32 NAND_SDM_ReadBlocks(UINT8 u1Part, UINT32 u4Offset, UINT32 u4MemPtr, UINT32 u4MemLen);
EXTERN INT32 NAND_SDM_WriteBlocks(UINT8 u1Part, UINT32 u4Offset, UINT32 u4MemPtr, UINT32 u4MemLen);
EXTERN INT32 NAND_SDM_ReadPagesEx(UINT8 u1PartId, UINT32 u4Offset, UINT32 u4MemPtr, UINT32 u4MemLen);

EXTERN INT32 NAND_SDM_ReadPages(UINT8 u1PartId, UINT32 u4Offset, UINT32 u4PageIdx, UINT32 u4MemPtr, UINT32 u4MemLen);
EXTERN INT32 NAND_SDM_WritePages(UINT8 u1PartId, UINT32 u4Offset, UINT32 *pu4PageIdx, UINT32 u4MemPtr, UINT32 u4MemLen);

EXTERN INT32 NAND_SDM_DumpStatus(UINT8 u1PartId, UINT32 u4Flags);
//EXTERN INT32 NAND_SDM_SyncCheck(UINT8 u1PartId);
//EXTERN INT32 NAND_SDM_SyncStatus(UINT8 u1PartId);
//EXTERN INT32 NAND_SDM_RWTest(UINT32 u4Count);
EXTERN INT32 NAND_SDM_MountTest(UINT32 u4Count);

// for loader use
EXTERN INT32 Loader_GetNandFlashBlockSize(void);
EXTERN INT32 Loader_ReadNandFlash(UINT32 u4PartId, UINT32 u4Offset, void *pvMemPtr, UINT32 u4MemLen);
EXTERN INT32 Loader_WriteNandFlash(UINT32 u4PartId, UINT32 u4Offset, void *pvMemPtr, UINT32 u4MemLen);

// for eeprom replacement
EXTERN INT32 NAND_EEPROM_Read(UINT32 u4Offset, UINT32 u4MemPtr, UINT32 u4MemLen);
EXTERN INT32 NAND_EEPROM_Write(UINT32 u4Offset, UINT32 u4MemPtr, UINT32 u4MemLen);

EXTERN INT32 NAND_CheckEcc(UINT32 *pu4EccError,UINT32 *pu4BadBlock);
EXTERN INT32 NAND_SDM_DumpData(UINT8 u1PartId,UINT32 u4Offset);
#endif /* NAND_IF_H */


