mirror of https://github.com/OpenIPC/firmware.git
				
				
				
			
		
			
				
	
	
		
			379 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Diff
		
	
	
			
		
		
	
	
			379 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Diff
		
	
	
| --- 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 <linux/platform_device.h>
 | |
| +#include <linux/mfd/goke_fmc.h>
 | |
| +
 | |
| +/*****************************************************************************/
 | |
| +#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__ */
 |