--- linux-4.9.37/drivers/mtd/nand/gkfmc100/fmc100.h 1970-01-01 03:00:00.000000000 +0300 +++ linux-4.9.y/drivers/mtd/nand/gkfmc100/fmc100.h 2021-06-07 13:01:33.000000000 +0300 @@ -0,0 +1,375 @@ +/* + * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved. + */ + +#ifndef __FMC100_H__ +#define __FMC100_H__ + +/*****************************************************************************/ +#include +#include + +/*****************************************************************************/ +#define INFINITE (0xFFFFFFFF) + +/*****************************************************************************/ +#define SPI_IF_READ_STD (0x01) +#define SPI_IF_READ_FAST (0x02) +#define SPI_IF_READ_DUAL (0x04) +#define SPI_IF_READ_DUAL_ADDR (0x08) +#define SPI_IF_READ_QUAD (0x10) +#define SPI_IF_READ_QUAD_ADDR (0x20) + +#define SPI_IF_WRITE_STD (0x01) +#define SPI_IF_WRITE_DUAL (0x02) +#define SPI_IF_WRITE_DUAL_ADDR (0x04) +#define SPI_IF_WRITE_QUAD (0x08) +#define SPI_IF_WRITE_QUAD_ADDR (0x10) + +#define SPI_IF_ERASE_SECTOR_4K (0x01) +#define SPI_IF_ERASE_SECTOR_32K (0x02) +#define SPI_IF_ERASE_SECTOR_64K (0x04) +#define SPI_IF_ERASE_SECTOR_128K (0x08) +#define SPI_IF_ERASE_SECTOR_256K (0x10) + +/******************************************************************************/ +#define FMC_SPI_NAND_SUPPORT_READ (SPI_IF_READ_STD \ + | SPI_IF_READ_FAST \ + | SPI_IF_READ_DUAL \ + | SPI_IF_READ_DUAL_ADDR \ + | SPI_IF_READ_QUAD \ + | SPI_IF_READ_QUAD_ADDR) + +#define FMC_SPI_NAND_SUPPORT_WRITE (SPI_IF_WRITE_STD | SPI_IF_WRITE_QUAD) + +#define FMC_SPI_NAND_SUPPORT_MAX_DUMMY 8 + +/*****************************************************************************/ +#define SPI_CMD_READ_STD 0x03 /* Standard read cache */ +#define SPI_CMD_READ_FAST 0x0B /* Higher speed read cache */ +#define SPI_CMD_READ_DUAL 0x3B /* 2 IO read cache only date */ +#define SPI_CMD_READ_DUAL_ADDR 0xBB /* 2 IO read cache date&addr */ +#define SPI_CMD_READ_QUAD 0x6B /* 4 IO read cache only date */ +#define SPI_CMD_READ_QUAD_ADDR 0xEB /* 4 IO read cache date&addr */ + +#define SPI_CMD_WRITE_STD 0x02 /* Standard page program */ +#define SPI_CMD_WRITE_DUAL 0xA2 /* 2 IO program only date */ +#define SPI_CMD_WRITE_DUAL_ADDR 0xD2 /* 2 IO program date&addr */ +#define SPI_CMD_WRITE_QUAD 0x32 /* 4 IO program only date */ +#define SPI_CMD_WRITE_QUAD_ADDR 0x12 /* 4 IO program date&addr */ + +#define SPI_CMD_SE_4K 0x20 /* 4KB sector Erase */ +#define SPI_CMD_SE_32K 0x52 /* 32KB sector Erase */ +#define SPI_CMD_SE_64K 0xD8 /* 64KB sector Erase */ +#define SPI_CMD_SE_128K 0xD8 /* 128KB sector Erase */ +#define SPI_CMD_SE_256K 0xD8 /* 256KB sector Erase */ + +/*****************************************************************************/ +#define SET_READ_STD(_dummy_, _size_, _clk_) \ + static struct spi_op read_std_##_dummy_##_size_##_clk_ = { \ + SPI_IF_READ_STD, SPI_CMD_READ_STD, _dummy_, _size_, _clk_ } + +#define SET_READ_FAST(_dummy_, _size_, _clk_) \ + static struct spi_op read_fast_##_dummy_##_size_##_clk_ = { \ + SPI_IF_READ_FAST, SPI_CMD_READ_FAST, _dummy_, _size_, _clk_ } + +#define SET_READ_DUAL(_dummy_, _size_, _clk_) \ + static struct spi_op read_dual_##_dummy_##_size_##_clk_ = { \ + SPI_IF_READ_DUAL, SPI_CMD_READ_DUAL, _dummy_, _size_, _clk_ } + +#define SET_READ_DUAL_ADDR(_dummy_, _size_, _clk_) \ + static struct spi_op read_dual_addr_##_dummy_##_size_##_clk_ = { \ + SPI_IF_READ_DUAL_ADDR, SPI_CMD_READ_DUAL_ADDR, _dummy_, _size_, _clk_ } + +#define SET_READ_QUAD(_dummy_, _size_, _clk_) \ + static struct spi_op read_quad_##_dummy_##_size_##_clk_ = { \ + SPI_IF_READ_QUAD, SPI_CMD_READ_QUAD, _dummy_, _size_, _clk_ } + +#define SET_READ_QUAD_ADDR(_dummy_, _size_, _clk_) \ + static struct spi_op read_quad_addr_##_dummy_##_size_##_clk_ = { \ + SPI_IF_READ_QUAD_ADDR, SPI_CMD_READ_QUAD_ADDR, _dummy_, _size_, _clk_ } + +/*****************************************************************************/ +#define SET_WRITE_STD(_dummy_, _size_, _clk_) \ + static struct spi_op write_std_##_dummy_##_size_##_clk_ = { \ + SPI_IF_WRITE_STD, SPI_CMD_WRITE_STD, _dummy_, _size_, _clk_ } + +#define SET_WRITE_DUAL(_dummy_, _size_, _clk_) \ + static struct spi_op write_dual_##_dummy_##_size_##_clk_ = { \ + SPI_IF_WRITE_DUAL, SPI_CMD_WRITE_DUAL, _dummy_, _size_, _clk_ } + +#define SET_WRITE_DUAL_ADDR(_dummy_, _size_, _clk_) \ + static struct spi_op write_dual_addr_##_dummy_##_size_##_clk_ = { \ +SPI_IF_WRITE_DUAL_ADDR, SPI_CMD_WRITE_DUAL_ADDR, _dummy_, _size_, _clk_ } + +#define SET_WRITE_QUAD(_dummy_, _size_, _clk_) \ + static struct spi_op write_quad_##_dummy_##_size_##_clk_ = { \ + SPI_IF_WRITE_QUAD, SPI_CMD_WRITE_QUAD, _dummy_, _size_, _clk_ } + +#define SET_WRITE_QUAD_ADDR(_dummy_, _size_, _clk_) \ + static struct spi_op write_quad_addr_##_dummy_##_size_##_clk_ = { \ +SPI_IF_WRITE_QUAD_ADDR, SPI_CMD_WRITE_QUAD_ADDR, _dummy_, _size_, _clk_ } + +/*****************************************************************************/ +#define SET_ERASE_SECTOR_4K(_dummy_, _size_, _clk_) \ + static struct spi_op erase_sector_4k_##_dummy_##_size_##_clk_ = { \ + SPI_IF_ERASE_SECTOR_4K, SPI_CMD_SE_4K, _dummy_, _size_, _clk_ } + +#define SET_ERASE_SECTOR_32K(_dummy_, _size_, _clk_) \ + static struct spi_op erase_sector_32k_##_dummy_##_size_##_clk_ = { \ + SPI_IF_ERASE_SECTOR_32K, SPI_CMD_SE_32K, _dummy_, _size_, _clk_ } + +#define SET_ERASE_SECTOR_64K(_dummy_, _size_, _clk_) \ + static struct spi_op erase_sector_64k_##_dummy_##_size_##_clk_ = { \ + SPI_IF_ERASE_SECTOR_64K, SPI_CMD_SE_64K, _dummy_, _size_, _clk_ } + +#define SET_ERASE_SECTOR_128K(_dummy_, _size_, _clk_) \ + static struct spi_op erase_sector_128k_##_dummy_##_size_##_clk_ = { \ + SPI_IF_ERASE_SECTOR_128K, SPI_CMD_SE_128K, _dummy_, _size_, _clk_ } + +#define SET_ERASE_SECTOR_256K(_dummy_, _size_, _clk_) \ + static struct spi_op erase_sector_256k_##_dummy_##_size_##_clk_ = { \ + SPI_IF_ERASE_SECTOR_256K, SPI_CMD_SE_256K, _dummy_, _size_, _clk_ } + +/*****************************************************************************/ +#define READ_STD(_dummy_, _size_, _clk_) read_std_##_dummy_##_size_##_clk_ +#define READ_FAST(_dummy_, _size_, _clk_) read_fast_##_dummy_##_size_##_clk_ +#define READ_DUAL(_dummy_, _size_, _clk_) read_dual_##_dummy_##_size_##_clk_ +#define READ_DUAL_ADDR(_dummy_, _size_, _clk_) \ + read_dual_addr_##_dummy_##_size_##_clk_ +#define READ_QUAD(_dummy_, _size_, _clk_) read_quad_##_dummy_##_size_##_clk_ +#define READ_QUAD_ADDR(_dummy_, _size_, _clk_) \ + read_quad_addr_##_dummy_##_size_##_clk_ + +/*****************************************************************************/ +#define WRITE_STD(_dummy_, _size_, _clk_) write_std_##_dummy_##_size_##_clk_ +#define WRITE_DUAL(_dummy_, _size_, _clk_) write_dual_##_dummy_##_size_##_clk_ +#define WRITE_DUAL_ADDR(_dummy_, _size_, _clk_) \ + write_dual_addr_##_dummy_##_size_##_clk_ +#define WRITE_QUAD(_dummy_, _size_, _clk_) write_quad_##_dummy_##_size_##_clk_ +#define WRITE_QUAD_ADDR(_dummy_, _size_, _clk_) \ + write_quad_addr_##_dummy_##_size_##_clk_ + +/*****************************************************************************/ +#define ERASE_SECTOR_4K(_dummy_, _size_, _clk_) \ + erase_sector_4k_##_dummy_##_size_##_clk_ +#define ERASE_SECTOR_32K(_dummy_, _size_, _clk_) \ + erase_sector_32k_##_dummy_##_size_##_clk_ +#define ERASE_SECTOR_64K(_dummy_, _size_, _clk_) \ + erase_sector_64k_##_dummy_##_size_##_clk_ +#define ERASE_SECTOR_128K(_dummy_, _size_, _clk_) \ + erase_sector_128k_##_dummy_##_size_##_clk_ +#define ERASE_SECTOR_256K(_dummy_, _size_, _clk_) \ + erase_sector_256k_##_dummy_##_size_##_clk_ + +/*****************************************************************************/ +#define SPI_CMD_WREN 0x06 /* Write Enable */ +#define SPI_CMD_WRDI 0x04 /* Write Disable */ + +#define SPI_CMD_RDID 0x9F /* Read Identification */ + +/*****************************************************************************/ +#define SPI_CMD_GET_FEATURES 0x0F /* Get Features */ +#define SPI_CMD_SET_FEATURE 0x1F /* Set Feature */ + +#define SPI_CMD_PAGE_READ 0x13 /* Page Read to Cache */ + +#define SPI_CMD_RESET 0xff /* Reset the device */ + +/*****************************************************************************/ +/* These macroes are for debug only, reg option is slower then dma option */ +#undef FMC100_SPI_NAND_SUPPORT_REG_READ +/* #define FMC100_SPI_NAND_SUPPORT_REG_READ */ + +#undef FMC100_SPI_NAND_SUPPORT_REG_WRITE +/* #define FMC100_SPI_NAND_SUPPORT_REG_WRITE */ + +#ifdef CONFIG_GOKE_NAND_ECC_STATUS_REPORT +/*****************************************************************************/ +#define FMC100_ECC_ERR_NUM0_BUF0 0xc0 + +#define GET_ECC_ERR_NUM(_i, _reg) (((_reg) >> ((_i) * 8)) & 0xff) +#endif +/*****************************************************************************/ +#define REG_CNT_HIGH_BLOCK_NUM_SHIFT 10 + +#define REG_CNT_BLOCK_NUM_MASK 0x3ff +#define REG_CNT_BLOCK_NUM_SHIFT 22 + +#define REG_CNT_PAGE_NUM_MASK 0x3f +#define REG_CNT_PAGE_NUM_SHIFT 16 + +#define REG_CNT_WRAP_MASK 0xf +#define REG_CNT_WRAP_SHIFT 12 + +#define REG_CNT_ECC_OFFSET_MASK 0xfff +#define REG_CNT_ECC_8BIT_OFFSET 1054 +#define REG_CNT_ECC_16BIT_OFFSET 1056 +#define REG_CNT_ECC_24BIT_OFFSET 1082 + +#define ERR_STR_DRIVER "Driver does not support this configure " +#define ERR_STR_CHECK "Please make sure the hardware configuration is correct" + +/*****************************************************************************/ +#define FMC100_ADDR_CYCLE_MASK 0x2 + +/*****************************************************************************/ +#define OP_STYPE_NONE 0x0 +#define OP_STYPE_READ 0x01 +#define OP_STYPE_WRITE 0x02 +#define OP_STYPE_ERASE 0x04 +#define CLK_FMC_TO_CRG_MHZ(_clk) ((_clk) * 2000000) + +/*****************************************************************************/ +#define MAX_SPI_OP 8 + +/*****************************************************************************/ +/* SPI general operation parameter */ +struct spi_op { + unsigned char iftype; + unsigned char cmd; + unsigned char dummy; + unsigned int size; + unsigned int clock; +}; + +struct spi_drv; + +/* SPI interface all operation */ +struct fmc_spi { + char *name; + int chipselect; + unsigned long long chipsize; + unsigned int erasesize; +#define SPI_NOR_3BYTE_ADDR_LEN 3 /* address len 3Bytes */ +#define SPI_NOR_4BYTE_ADDR_LEN 4 /* address len 4Bytes for 32MB */ + unsigned int addrcycle; + + struct spi_op read[1]; + struct spi_op write[1]; + struct spi_op erase[MAX_SPI_OP]; + + void *host; + + struct spi_drv *driver; +}; + +/* SPI interface special operation function hook */ +struct spi_drv { + int (*wait_ready)(struct fmc_spi *spi); + int (*write_enable)(struct fmc_spi *spi); + int (*qe_enable)(struct fmc_spi *spi); + int (*bus_prepare)(struct fmc_spi *spi, int op); + int (*entry_4addr)(struct fmc_spi *spi, int en); +}; + +struct spi_nand_info { + char *name; + unsigned char id[MAX_SPI_NAND_ID_LEN]; + unsigned char id_len; + unsigned long long chipsize; + unsigned int erasesize; + unsigned int pagesize; + unsigned int oobsize; +#define BBP_LAST_PAGE 0x01 +#define BBP_FIRST_PAGE 0x02 + unsigned int badblock_pos; + struct spi_op *read[MAX_SPI_OP]; + struct spi_op *write[MAX_SPI_OP]; + struct spi_op *erase[MAX_SPI_OP]; + struct spi_drv *driver; +}; + +/*****************************************************************************/ +extern u_char spi_nand_feature_op(struct fmc_spi *spi, u_char op, u_char addr, + u_char val); + +/*****************************************************************************/ +struct fmc_host { + struct mtd_info *mtd; + struct nand_chip *chip; + struct fmc_spi spi[CONFIG_SPI_NAND_MAX_CHIP_NUM]; + struct fmc_cmd_op cmd_op; + + void __iomem *iobase; + void __iomem *regbase; + struct clk *clk; + u32 clkrate; + + unsigned int fmc_cfg; + unsigned int fmc_cfg_ecc0; + + unsigned int offset; + + struct device *dev; + struct mutex *lock; + + /* This is maybe an un-aligment address, only for malloc or free */ + char *buforg; + char *buffer; + +#ifdef CONFIG_64BIT + unsigned long long dma_buffer; + unsigned long long dma_oob; +#else + unsigned int dma_buffer; + unsigned int dma_oob; +#endif + + unsigned int addr_cycle; + unsigned int addr_value[2]; + unsigned int cache_addr_value[2]; + + unsigned int column; + unsigned int block_page_mask; + + unsigned int ecctype; + unsigned int pagesize; + unsigned int oobsize; + + int add_partition; + + int need_rr_data; +#define FMC100_READ_RETRY_DATA_LEN 128 + char rr_data[FMC100_READ_RETRY_DATA_LEN]; + struct read_retry_t *read_retry; + + int version; + + /* BOOTROM read two bytes to detect the bad block flag */ +#define FMC_BAD_BLOCK_POS 0 + unsigned char *bbm; /* nand bad block mark */ + unsigned short *epm; /* nand empty page mark */ + + unsigned int uc_er; + + void (*send_cmd_write)(struct fmc_host *host); + void (*send_cmd_status)(struct fmc_host *host); + void (*send_cmd_read)(struct fmc_host *host); + void (*send_cmd_erase)(struct fmc_host *host); + void (*send_cmd_readid)(struct fmc_host *host); + void (*send_cmd_reset)(struct fmc_host *host); +#ifdef CONFIG_PM + int (*suspend)(struct platform_device *pltdev, pm_message_t state); + int (*resume)(struct platform_device *pltdev); +#endif +}; + +/*****************************************************************************/ +void fmc100_ecc0_switch(struct fmc_host *host, unsigned char op); + +int fmc100_spi_nand_init(struct nand_chip *chip); + +/*****************************************************************************/ +extern void fmc_spi_nand_ids_register(void); + +extern void fmc_set_nand_system_clock(struct spi_op *op, int clk_en); + +/*****************************************************************************/ +#ifdef CONFIG_PM +int fmc100_suspend(struct platform_device *pltdev, pm_message_t state); +int fmc100_resume(struct platform_device *pltdev); +void fmc100_spi_nand_config(struct fmc_host *host); +#endif + +#endif /* End of __FMC100_H__ */