393 lines
14 KiB
C
393 lines
14 KiB
C
/*
|
|
* spinand.c for SUNXI NAND .
|
|
*
|
|
* Copyright (C) 2016 Allwinner.
|
|
*
|
|
*
|
|
* This file is licensed under the terms of the GNU General Public
|
|
* License version 2. This program is licensed "as is" without any
|
|
* warranty of any kind, whether express or implied.
|
|
*/
|
|
|
|
#ifndef _SUNXI_NAND_H
|
|
#define _SUNXI_NAND_H
|
|
#include <asm/types.h>
|
|
|
|
#ifndef __s8
|
|
typedef signed char __s8;
|
|
#endif
|
|
|
|
#ifndef __u8
|
|
typedef unsigned char __u8;
|
|
#endif
|
|
|
|
#ifndef __s16
|
|
typedef signed short __s16;
|
|
#endif
|
|
|
|
#ifndef __u16
|
|
typedef unsigned short __u16;
|
|
#endif
|
|
|
|
#ifndef __s32
|
|
typedef signed int __s32;
|
|
#endif
|
|
|
|
#ifndef __u32
|
|
typedef unsigned int __u32;
|
|
#endif
|
|
|
|
#ifndef __s64
|
|
typedef signed long long __s64;
|
|
#endif
|
|
|
|
#ifndef __u64
|
|
typedef unsigned long long __u64;
|
|
#endif
|
|
|
|
#ifndef uchar
|
|
typedef unsigned char uchar;
|
|
#endif
|
|
|
|
#ifndef uint16
|
|
typedef unsigned short uint16;
|
|
#endif
|
|
|
|
#ifndef uint32
|
|
typedef unsigned int uint32;
|
|
#endif
|
|
|
|
#ifndef uint
|
|
typedef unsigned int uint;
|
|
#endif
|
|
|
|
|
|
#ifndef sint32
|
|
typedef int sint32;
|
|
#endif
|
|
|
|
#ifndef uint64
|
|
typedef unsigned long long uint64;
|
|
#endif
|
|
|
|
#ifndef sint16
|
|
typedef short sint16;
|
|
#endif
|
|
|
|
#ifndef UINT8
|
|
typedef unsigned char UINT8;
|
|
#endif
|
|
|
|
#ifndef UINT32
|
|
typedef unsigned int UINT32;
|
|
#endif
|
|
|
|
#ifndef SINT32
|
|
typedef signed int SINT32;
|
|
#endif
|
|
|
|
#define NULL ((void *)0)
|
|
|
|
//extern __u32 SPIC_IO_BASE;
|
|
/* run time control */
|
|
#define TEST_SPI_NO (0)
|
|
#define SPI_DEFAULT_CLK (40000000)
|
|
#define SPI_TX_WL (32)
|
|
#define SPI_RX_WL (32)
|
|
#define SPI_FIFO_SIZE (64)
|
|
#define SPI_CLK_SRC (1) //0-24M, 1-PLL6
|
|
#define SPI_MCLK (40000000)
|
|
|
|
//#define SPIC_BASE_OS (0x1000)
|
|
extern void *NAND_GetIOBaseAddr(u32 no);
|
|
#define SPI_BASE (u8 *)(NAND_GetIOBaseAddr(0))
|
|
//#define SPI_BASE (0xe086f000)
|
|
//#define SPI_IRQNO(_n) (INTC_SRC_SPI0 + (_n))
|
|
|
|
#define SPI_VAR (SPI_BASE + 0x00)
|
|
#define SPI_GCR (SPI_BASE + 0x04)
|
|
#define SPI_TCR (SPI_BASE + 0x08)
|
|
#define SPI_IER (SPI_BASE + 0x10)
|
|
#define SPI_ISR (SPI_BASE + 0x14)
|
|
#define SPI_FCR (SPI_BASE + 0x18)
|
|
#define SPI_FSR (SPI_BASE + 0x1c)
|
|
#define SPI_WCR (SPI_BASE + 0x20)
|
|
#define SPI_CCR (SPI_BASE + 0x24)
|
|
#define SPI_MBC (SPI_BASE + 0x30)
|
|
#define SPI_MTC (SPI_BASE + 0x34)
|
|
#define SPI_BCC (SPI_BASE + 0x38)
|
|
#define SPI_TXD (SPI_BASE + 0x200)
|
|
#define SPI_RXD (SPI_BASE + 0x300)
|
|
|
|
/* bit field of registers */
|
|
#define SPI_SOFT_RST (1U << 31)
|
|
#define SPI_TXPAUSE_EN (1U << 7)
|
|
#define SPI_MASTER (1U << 1)
|
|
#define SPI_ENABLE (1U << 0)
|
|
|
|
#define SPI_EXCHANGE (1U << 31)
|
|
#define SPI_SAMPLE_MODE (1U << 13)
|
|
#define SPI_LSB_MODE (1U << 12)
|
|
#define SPI_SAMPLE_CTRL (1U << 11)
|
|
#define SPI_RAPIDS_MODE (1U << 10)
|
|
#define SPI_DUMMY_1 (1U << 9)
|
|
#define SPI_DHB (1U << 8)
|
|
#define SPI_SET_SS_1 (1U << 7)
|
|
#define SPI_SS_MANUAL (1U << 6)
|
|
#define SPI_SEL_SS0 (0U << 4)
|
|
#define SPI_SEL_SS1 (1U << 4)
|
|
#define SPI_SEL_SS2 (2U << 4)
|
|
#define SPI_SEL_SS3 (3U << 4)
|
|
#define SPI_SS_N_INBST (1U << 3)
|
|
#define SPI_SS_ACTIVE0 (1U << 2)
|
|
#define SPI_MODE0 (0U << 0)
|
|
#define SPI_MODE1 (1U << 0)
|
|
#define SPI_MODE2 (2U << 0)
|
|
#define SPI_MODE3 (3U << 0)
|
|
|
|
#define SPI_CPHA (1U << 0)
|
|
|
|
#define SPI_SS_INT (1U << 13)
|
|
#define SPI_TC_INT (1U << 12)
|
|
#define SPI_TXUR_INT (1U << 11)
|
|
#define SPI_TXOF_INT (1U << 10)
|
|
#define SPI_RXUR_INT (1U << 9)
|
|
#define SPI_RXOF_INT (1U << 8)
|
|
#define SPI_TXFULL_INT (1U << 6)
|
|
#define SPI_TXEMPT_INT (1U << 5)
|
|
#define SPI_TXREQ_INT (1U << 4)
|
|
#define SPI_RXFULL_INT (1U << 2)
|
|
#define SPI_RXEMPT_INT (1U << 1)
|
|
#define SPI_RXREQ_INT (1U << 0)
|
|
#define SPI_ERROR_INT (SPI_TXUR_INT|SPI_TXOF_INT|SPI_RXUR_INT|SPI_RXOF_INT)
|
|
|
|
#define SPI_TXFIFO_RST (1U << 31)
|
|
#define SPI_TXFIFO_TST (1U << 30)
|
|
#define SPI_TXDMAREQ_EN (1U << 24)
|
|
#define SPI_RXFIFO_RST (1U << 15)
|
|
#define SPI_RXFIFO_TST (1U << 14)
|
|
#define SPI_RXDMAREQ_EN (1U << 8)
|
|
|
|
#define SPI_MASTER_DUAL (1U << 28)
|
|
|
|
#define SPI_NAND_READY (1U << 0)
|
|
#define SPI_NAND_ERASE_FAIL (1U << 2)
|
|
#define SPI_NAND_WRITE_FAIL (1U << 3)
|
|
#define SPI_NAND_ECC_FIRST_BIT (4)
|
|
#define SPI_NAND_ECC_BITMAP (0x3)
|
|
#define SPI_NAND_INT_ECCSR_BITMAP (0xf)
|
|
|
|
#define SPI_NAND_WREN 0x06
|
|
#define SPI_NAND_WRDI 0x04
|
|
#define SPI_NAND_GETSR 0x0f //get status/features
|
|
#define SPI_NAND_SETSR 0x1f //set status/features
|
|
#define SPI_NAND_PAGE_READ 0x13
|
|
#define SPI_NAND_FAST_READ_X1 0x0b
|
|
#define SPI_NAND_READ_X1 0x03
|
|
#define SPI_NAND_READ_X2 0x3b
|
|
#define SPI_NAND_READ_X4 0x6b
|
|
#define SPI_NAND_READ_DUAL_IO 0xbb
|
|
#define SPI_NAND_READ_QUAD_IO 0xeb
|
|
#define SPI_NAND_RDID 0x9f
|
|
#define SPI_NAND_PP 0x02
|
|
#define SPI_NAND_PP_X4 0x32
|
|
#define SPI_NAND_RANDOM_PP 0x84
|
|
#define SPI_NAND_RANDOM_PP_X4 0x34
|
|
#define SPI_NAND_PE 0x10 //program execute
|
|
#define SPI_NAND_BE 0xd8 //block erase
|
|
#define SPI_NAND_RESET 0xff
|
|
#define SPI_NAND_READ_INT_ECCSTATUS 0x7c
|
|
|
|
#undef readb
|
|
#undef readw
|
|
#undef writeb
|
|
#undef writew
|
|
#define readb(addr) (*((volatile unsigned char *)(addr)))
|
|
#define readw(addr) (*((volatile unsigned int *)(addr)))
|
|
#define writeb(v, addr) (*((volatile unsigned char *)(addr)) = (unsigned char)(v))
|
|
#define writew(v, addr) (*((volatile unsigned int *)(addr)) = (unsigned int)(v))
|
|
|
|
#define NAND_OP_TRUE (0) //define the successful return value
|
|
#define NAND_OP_FALSE (-1) //define the failed return value
|
|
|
|
|
|
//define the return value
|
|
//#define ECC_CORRECT 9 //error can be corrected
|
|
#define ECC_LIMIT 10 //reach the limit of the ability of ECC
|
|
|
|
#define ERR_ECC 12 //too much ecc error
|
|
|
|
#define ERR_NANDFAIL 13 //nand flash program or erase fail
|
|
//#define ERR_TIMEOUT 14 //hardware timeout
|
|
|
|
|
|
#define SECTOR_SIZE 512 //the size of a sector, based on byte
|
|
|
|
|
|
/* define the mask for the nand flash optional operation */
|
|
|
|
/* nand flash support dual read operation */
|
|
#define NAND_DUAL_READ (1 << 0)
|
|
/* nand flash support page dual program operation */
|
|
#define NAND_DUAL_PROGRAM (1 << 1)
|
|
/* nand flash support multi-plane page read operation */
|
|
#define NAND_MULTI_READ (1 << 2)
|
|
/* nand flash support multi-plane page program operation */
|
|
#define NAND_MULTI_PROGRAM (1 << 3)
|
|
/* nand flash support external inter-leave operation, it based multi-chip */
|
|
#define NAND_EXT_INTERLEAVE (1 << 4)
|
|
/* nand flash support the maximum block erase cnt */
|
|
#define NAND_MAX_BLK_ERASE_CNT (1 << 5)
|
|
/* nand flash support to read reclaim Operation */
|
|
#define NAND_READ_RECLAIM (1 << 6)
|
|
/* nand flash need plane select for addr */
|
|
#define NAND_TWO_PLANE_SELECT (1 << 7)
|
|
#define SPINAND_TWO_PLANE_SELECT NAND_TWO_PLANE_SELECT
|
|
/* nand flash need a dummy Byte after random fast read */
|
|
#define NAND_ONEDUMMY_AFTER_RANDOMREAD (1 << 8)
|
|
/* nand flash only support 8B user meta data under ecc protected */
|
|
#define NAND_8B_METADATA_ECC_PROTECTED (1 << 9)
|
|
/* nand flash support quad read operation */
|
|
#define NAND_QUAD_READ (1<<10)
|
|
/* nand flash support page quad program operation */
|
|
#define NAND_QUAD_PROGRAM (1<<11)
|
|
|
|
/* nand flash should not enable QE register bit manually */
|
|
#define SPINAND_QUAD_NO_NEED_ENABLE (1 << 12)
|
|
|
|
enum ecc_status_shift {
|
|
ECC_STATUS_SHIFT_0 = 0,
|
|
ECC_STATUS_SHIFT_1,
|
|
ECC_STATUS_SHIFT_2,
|
|
ECC_STATUS_SHIFT_3,
|
|
ECC_STATUS_SHIFT_4,
|
|
ECC_STATUS_SHIFT_5,
|
|
ECC_STATUS_SHIFT_6,
|
|
ECC_STATUS_SHIFT_7,
|
|
};
|
|
|
|
//define the nand flash physical information parameter type, for id table
|
|
struct __NandPhyInfoPar_t {
|
|
__u8 NandID[8]; //the ID number of the nand flash chip
|
|
__u8 DieCntPerChip; //the count of the Die in one nand flash chip
|
|
__u8 SectCntPerPage; //the count of the sectors in one single physical page
|
|
__u16 PageCntPerBlk; //the count of the pages in one single physical block
|
|
__u16 BlkCntPerDie; //the count fo the physical blocks in one nand flash Die
|
|
__u32 OperationOpt; //the bitmap that marks which optional operation that the nand flash can support
|
|
__u16 AccessFreq; //the highest access frequence of the nand flash chip, based on MHz
|
|
__u32 SpiMode; //spi nand mode, 0:mode 0, 3:mode 3
|
|
__u32 pagewithbadflag; //bad block flag was written at the first byte of spare area of this page
|
|
struct spi_nand_function *spi_nand_function; //erase,write,read function for spi nand
|
|
__u32 MultiPlaneBlockOffset; //the value of the block number offset between the two plane block
|
|
__u32 MaxEraseTimes; //the max erase times of a physic block
|
|
__u32 MaxEccBits; //the max ecc bits that nand support
|
|
__u32 EccLimitBits; //the ecc limit flag for tne nand
|
|
__u32 Idnumber;
|
|
__u32 EccType; // Just use in spinand2, select different ecc status type.
|
|
__u32 EccProtectedType; // just use in spinand2, select different ecc protected type.
|
|
enum ecc_status_shift ecc_status_shift;
|
|
__u8 reserved[4]; //reserved for 32bit align
|
|
};
|
|
|
|
//define the nand flash storage system information
|
|
struct __NandStorageInfo_t {
|
|
__u8 ChipCnt; //the count of the total nand flash chips are currently connecting on the CE pin
|
|
__u16 ChipConnectInfo; //chip connect information, bit == 1 means there is a chip connecting on the CE pin
|
|
__u8 ConnectMode; //the rb connect mode
|
|
__u8 BankCntPerChip; //the count of the banks in one nand chip, multiple banks can support Inter-Leave
|
|
__u8 DieCntPerChip; //the count of the dies in one nand chip, block management is based on Die
|
|
__u8 PlaneCntPerDie; //the count of planes in one die, multiple planes can support multi-plane operation
|
|
__u8 SectorCntPerPage; //the count of sectors in one single physic page, one sector is 0.5k
|
|
__u16 PageCntPerPhyBlk; //the count of physic pages in one physic block
|
|
__u32 BlkCntPerDie; //the count of the physic blocks in one die, include valid block and invalid block
|
|
__u32 OperationOpt; //the mask of the operation types which current nand flash can support support
|
|
__u16 FrequencePar; //the parameter of the hardware access clock, based on 'MHz'
|
|
__u32 SpiMode; //spi nand mode, 0:mode 0, 3:mode 3
|
|
__u8 NandChipId[8]; //the nand chip id of current connecting nand chip
|
|
__u32 pagewithbadflag; //bad block flag was written at the first byte of spare area of this page
|
|
__u32 MultiPlaneBlockOffset; //the value of the block number offset between the two plane block
|
|
__u32 MaxEraseTimes; //the max erase times of a physic block
|
|
__u32 MaxEccBits; //the max ecc bits that nand support
|
|
__u32 EccLimitBits; //the ecc limit flag for tne nand
|
|
__u32 Idnumber;
|
|
__u32 EccType; // Just use in spinand2, select different ecc status type.
|
|
__u32 EccProtectedType; // just use in spinand2, select different ecc protected type.
|
|
struct spi_nand_function *spi_nand_function; //erase,write,read function for spi nand
|
|
enum ecc_status_shift ecc_status_shift;
|
|
};
|
|
|
|
//define the page buffer pool for nand flash driver
|
|
struct __NandPageCachePool_t {
|
|
__u8 *PageCache0; //the pointer to the first page size ram buffer
|
|
// __u8 *PageCache1; //the pointer to the second page size ram buffer
|
|
// __u8 *PageCache2; //the pointer to the third page size ram buffer
|
|
__u8 *SpareCache;
|
|
__u8 *TmpPageCache;
|
|
__u8 *SpiPageCache;
|
|
__u8 *SpareCache1;
|
|
};
|
|
|
|
struct boot_physical_param {
|
|
__u32 chip; //chip no
|
|
__u32 block; // block no within chip
|
|
__u32 page; // apge no within block
|
|
__u32 sectorbitmap;
|
|
void *mainbuf; //data buf
|
|
void *oobbuf; //oob buf
|
|
};
|
|
struct spi_nand_function {
|
|
__s32 (*spi_nand_reset)(__u32 spi_no, __u32 chip);
|
|
__s32 (*spi_nand_read_status)(__u32 spi_no, __u32 chip, __u8 status, __u32 mode);
|
|
__s32 (*spi_nand_setstatus)(__u32 spi_no, __u32 chip, __u8 reg);
|
|
__s32 (*spi_nand_getblocklock)(__u32 spi_no, __u32 chip, __u8 *reg);
|
|
__s32 (*spi_nand_setblocklock)(__u32 spi_no, __u32 chip, __u8 reg);
|
|
__s32 (*spi_nand_getotp)(__u32 spi_no, __u32 chip, __u8 *reg);
|
|
__s32 (*spi_nand_setotp)(__u32 spi_no, __u32 chip, __u8 reg);
|
|
__s32 (*spi_nand_getoutdriver)(__u32 spi_no, __u32 chip, __u8 *reg);
|
|
__s32 (*spi_nand_setoutdriver)(__u32 spi_no, __u32 chip, __u8 reg);
|
|
__s32 (*erase_single_block)(struct boot_physical_param *eraseop);
|
|
__s32 (*write_single_page)(struct boot_physical_param *writeop);
|
|
__s32 (*read_single_page)(struct boot_physical_param *readop, __u32 spare_only_flag);
|
|
};
|
|
|
|
extern struct spi_nand_function spinand_function;
|
|
|
|
extern int nand_dma_config_start(__u32 tx_mode, __u32 addr, __u32 length);
|
|
extern int NAND_WaitDmaFinish(__u32 tx_flag, __u32 rx_flag);
|
|
extern int Nand_Dma_End(__u32 rw, __u32 addr, __u32 length);
|
|
|
|
extern int spinand_get_mbr(char *buffer, uint len);
|
|
|
|
extern int spinand_uboot_init(int boot_mode);
|
|
extern int spinand_uboot_exit(int force);
|
|
|
|
extern int spinand_uboot_probe(void);
|
|
|
|
extern uint spinand_uboot_read(uint start, uint sectors, void *buffer);
|
|
|
|
extern uint spinand_uboot_write(uint start, uint sectors, void *buffer);
|
|
|
|
|
|
extern int spinand_download_boot0(uint length, void *buffer);
|
|
extern int spinand_download_uboot(uint length, void *buffer);
|
|
|
|
extern int spinand_force_download_uboot(uint length, void *buffer);
|
|
extern int spinand_uboot_erase(int user_erase);
|
|
|
|
extern uint spinand_uboot_get_flash_info(void *buffer, uint length);
|
|
|
|
extern uint spinand_uboot_set_flash_info(void *buffer, uint length);
|
|
|
|
extern uint spinand_uboot_get_flash_size(void);
|
|
|
|
extern int spinand_uboot_flush(void);
|
|
|
|
extern int SPINAND_Uboot_Force_Erase(void);
|
|
|
|
uint spinand_upload_boot0(uint length, void *buf);
|
|
|
|
int spinand_download_boot0_simple(uint length, void *buffer);
|
|
|
|
#endif
|
|
|