| #ifndef __AML_NFTL_BLOCK_H |
| #define __AML_NFTL_BLOCK_H |
| |
| #include "amlnf_type.h" |
| #include "hw_ctrl.h" |
| #include "amlnf_ctrl.h" |
| #include "amlnf_cfg.h" |
| |
| #include "partition_table.h" |
| #include <asm/arch/secure_apb.h> |
| #include <asm/arch/cpu_sdio.h> |
| #include <asm/io.h> |
| |
| #ifndef AML_NAND_UBOOT |
| #include <linux/types.h> |
| #include <linux/init.h> |
| #include <linux/of.h> |
| #include <linux/pinctrl/consumer.h> |
| #endif /*AML_NAND_UBOOT*/ |
| |
| |
| #define aml_nftl_dbg aml_nand_dbg |
| |
| #define aml_nftl_malloc aml_nand_malloc |
| #define aml_nftl_free aml_nand_free |
| |
| //#define NAND_LINE do {aml_nand_msg("%s() l-%d", __FUNCTION__, __LINE__);} while(0); |
| #define NAND_LINE do {;} while(0); |
| //#define BOOT_LINE do {aml_nand_msg("%s() l-%d", __FUNCTION__, __LINE__);} while(0); |
| #define BOOT_LINE do {;} while(0); |
| //#define PHY_NAND_LINE do {aml_nand_msg("%s() l-%d", __FUNCTION__, __LINE__);} while(0); |
| #define PHY_NAND_LINE do {;} while(0); |
| //#define ENV_NAND_LINE do {aml_nand_msg("%s() l-%d", __FUNCTION__, __LINE__);} while(0); |
| #define ENV_NAND_LINE do {;} while(0); |
| //#define CMD_LINE do {aml_nand_msg("%s() l-%d", __FUNCTION__, __LINE__);} while(0); |
| #define CMD_LINE do {;} while(0); |
| //#define PHYDEV_LINE do {aml_nand_msg("%s() l-%d", __FUNCTION__, __LINE__);} while(0); |
| #define PHYDEV_LINE do {;} while(0); |
| |
| |
| #define DISPROTECT_DBG 1<<4 |
| #if (AML_CFG_INSIDE_PARTTBL) |
| /* |
| * fixme, moved from <partition_table.h> |
| */ |
| #define DISPROTECT_KEY 1 |
| #define DISPROTECT_SECURE 1<<1 |
| #define DISPROTECT_FBBT 1<<2 |
| #define DISPROTECT_HYNIX 1<<3 |
| |
| /* |
| * fixme, moved from <storage.h> |
| */ |
| #define STORE_CODE (1<<0) |
| #define STORE_CACHE (1<<1) |
| #define STORE_DATA (1<<2) |
| #endif //0 |
| /* |
| * cpu version |
| **/ |
| |
| #define MAX_DEVICE_NUM 4 |
| #define MAX_DEVICE_NAME_LEN 16 |
| |
| |
| #define AMLNF_DEV_MAJOR 250 |
| #define TIMESTAMP_LENGTH 15 |
| #define MAX_TIMESTAMP_NUM ((1<<(TIMESTAMP_LENGTH-1))-1) |
| #define AML_NFTL_BOUNCE_SIZE 0x40000 |
| |
| #define NFTL_MAX_SCHEDULE_TIMEOUT 1000 |
| #define NFTL_FLUSH_DATA_TIME 1 |
| #define NFTL_CACHE_FORCE_WRITE_LEN 16 |
| |
| |
| #define FACTORY_BAD_BLOCK_ERROR 2 |
| #define BYTES_PER_SECTOR 512 |
| #define SHIFT_PER_SECTOR 9 |
| #define BYTES_OF_USER_PER_PAGE 16 |
| #define MIN_BYTES_OF_USER_PER_PAGE 16 |
| |
| #define AMLNF_DEV_RO_MODE (1<<0) |
| |
| #define RET_YES 1 |
| #define RET_NO 0 |
| |
| #define PRINT aml_nftl_dbg |
| |
| #define NAND_BLOCK_GOOD 0 |
| #define NAND_BLOCK_USED_BAD 1 |
| #define NAND_BLOCK_FACTORY_BAD 2 |
| |
| |
| #define MAX_NAND_PART_NUM 16 |
| #define MAX_NAND_PART_NAME_LEN 16 |
| |
| #define NAND_PART_SIZE_FULL -1 |
| |
| #define NAND_BLOCK_GOOD 0 |
| #define NAND_BLOCK_USED_BAD 1 |
| #define NAND_BLOCK_FACTORY_BAD 2 |
| |
| /***nand device name***/ |
| #define NAND_BOOT_NAME "nfboot" |
| #define NAND_CACHE_NAME "nfcache" |
| #define NAND_CODE_NAME "nfcode" |
| #define NAND_DATA_NAME "nfdata" |
| #define NAND_RESERVED_NAME "nfrevd" |
| |
| #define PHY_DEV_NUM 3 |
| |
| |
| /***boot device flag***/ |
| #define SPI_BOOT_FLAG 0 |
| #define NAND_BOOT_FLAG 1 |
| #define EMMC_BOOT_FLAG 2 |
| #define CARD_BOOT_FLAG 3 |
| #define SPI_NAND_FLAG 4 |
| #define SPI_EMMC_FLAG 5 |
| |
| #define STORAGE_DEV_NOSET (0) |
| #define STORAGE_DEV_EMMC (1) |
| #define STORAGE_DEV_NAND (2) |
| #define STORAGE_DEV_SPI (3) |
| #define STORAGE_DEV_SDCARD (4) |
| #define STORAGE_DEV_USB (5) |
| |
| |
| /***nand BOOT flags***/ |
| #define NAND_BOOT_NORMAL 0 |
| #define NAND_BOOT_UPGRATE 1 |
| #define NAND_BOOT_ERASE_PROTECT_CACHE 2 |
| #define NAND_BOOT_ERASE_ALL 3 |
| #define NAND_BOOT_SCRUB_ALL 4 |
| #define NAND_SCAN_ID_INIT 5 |
| |
| /****nand debug flag info******/ |
| #define NAND_WRITE_VERIFY 1 |
| |
| #define DRV_AMLNFDEV_NAME "amlnfdev" |
| #define DRV_AMLNFDEV_AUTHOR "AMLOGIC SZ NAND TEAM" |
| #define DRV_AMLNFDEV_DESC "Amlogic Nand Flash driver" |
| |
| /* |
| * dummy structure for uboot. fixme, |
| */ |
| #ifdef AML_NAND_UBOOT |
| struct platform_device { |
| |
| }; |
| #endif // |
| |
| struct amlnf_partition { |
| /* identifier string */ |
| char name[MAX_NAND_PART_NAME_LEN]; |
| /* partition size */ |
| u64 size; |
| /* offset within the master space */ |
| u64 offset; |
| /* master flags to mask out for this partition */ |
| u32 mask_flags; |
| void *priv; |
| }; |
| |
| enum amlnf_error_t { |
| NAND_SUCCESS = 0, |
| NAND_CMD_FAILURE = 1, |
| NAND_BUSY_FAILURE = 2, |
| NAND_ID_FAILURE = 3, |
| NAND_DMA_FAILURE = 4, |
| NAND_ECC_FAILURE = 5, |
| NAND_BITFLIP_FAILURE = 6, |
| NAND_MALLOC_FAILURE = 7, |
| NAND_ARGUMENT_FAILURE = 8, |
| NAND_STATUS_FAILURE = 9, |
| NAND_WP_FAILURE = 10, |
| NAND_SELECT_CHIP_FAILURE = 12, |
| NAND_ERASE_FAILED = 13, |
| NAND_WRITE_FAILED = 14, |
| NAND_FAILED = 15, |
| NAND_READ_FAILED = 16, |
| NAND_BAD_BLCOK_FAILURE = 17, |
| NAND_SHIPPED_BAD_FAILURE = 18, |
| NAND_CONFIGS_FAILED = 19, |
| NAND_SHIPPED_BADBLOCK_FAILED = 20, |
| NAND_DETECT_DTB_FAILED = 21, |
| }; |
| |
| struct _nftl_cfg { |
| u16 nftl_use_cache; |
| u16 nftl_support_gc_read_reclaim; |
| u16 nftl_support_wear_leveling; |
| u16 nftl_need_erase; |
| u16 nftl_part_reserved_block_ratio; |
| u16 nftl_part_adjust_block_num; |
| u16 nftl_min_free_block_num; |
| u16 nftl_gc_threshold_free_block_num; |
| u16 nftl_min_free_block; |
| u16 nftl_gc_threshold_ratio_numerator; |
| u16 nftl_gc_threshold_ratio_denominator; |
| u16 nftl_max_cache_write_num; |
| }; |
| |
| /* |
| * Constants for ECC_MODES |
| */ |
| enum oob_modes_t { |
| NAND_HW_ECC, |
| NAND_SOFT_ECC, |
| }; |
| |
| /** |
| * struct phydev_ops - oob operation operands |
| * @mode: operation mode, for ecc none or hw mode |
| * @len: number of data bytes to write/read |
| * @retlen: number of data bytes written/read |
| * @ooblen: number of oob bytes to write/read |
| * @oobretlen: number of oob bytes written/read |
| * @datbuf: data buffer - if NULL only oob data are read/written |
| * @oobbuf: oob data buffer- if NULL only data are read/written |
| * |
| * Note, it is not allowed to read/write more than one OOB area |
| * at one go when oob operation. |
| * That is, the interface assumes that the OOB write requests |
| * program/read within only one page's |
| * OOB area. |
| */ |
| struct phydev_ops { |
| enum oob_modes_t mode; |
| u64 addr; |
| /* one operation less than 2GB data len */ |
| u64 len; |
| u32 retlen; |
| u32 ooblen; |
| u8 *datbuf; |
| u8 *oobbuf; |
| }; |
| |
| /* #include "../phy/phynand.h" */ |
| /* |
| * API for NFTL driver. |
| * Provide nand basic information and common operation function. |
| * Must meet all the requirement of NFTL driver, |
| * and also consider the fulture extensions |
| */ |
| |
| /** |
| * struct amlnand_phydev - nand phy device |
| * @name: |
| * @type: used for fulture, differ from SLC, MLC and TLC |
| * @retlen: number of data bytes written/read |
| * @ooblen: number of oob bytes to write/read |
| * @oobretlen: number of oob bytes written/read |
| * @datbuf: data buffer - if NULL only oob data are read/written |
| * @oobbuf: oob data buffer- if NULL only data are read/written |
| * |
| * Note, it is not allowed to read/write more than one OOB area |
| * at one go when oob operation. |
| * That is, the interface assumes that the OOB write requests |
| * program/read within only one page's |
| * OOB area. |
| */ |
| struct amlnand_phydev { |
| const char name[MAX_DEVICE_NAME_LEN]; |
| |
| /*****nand flash chip type, maybe SLC/MLC/TLC ******/ |
| u8 type; |
| |
| u8 ecc_failed; |
| u8 bit_flip; |
| |
| /*** used for Read-Only, or other feature ***/ |
| u32 flags; |
| |
| /*** used for other feature setting***/ |
| u32 option; |
| |
| /*** struct for whole nand chip***/ |
| /* struct amlnand_chip *aml_chip; */ |
| void *priv; |
| |
| struct list_head list; |
| |
| #ifndef AML_NAND_UBOOT |
| struct device dev; |
| struct class cls; |
| |
| struct cdev uboot_cdev; |
| #endif /* AML_NAND_UBOOT */ |
| |
| /*** offset value of the whole nand device***/ |
| u64 offset; |
| |
| /*** Total size of the cunrrent nand device***/ |
| u64 size; |
| |
| u8 chipnr; |
| |
| /*** "Major" erase size for the device. ***/ |
| u32 erasesize; |
| |
| /* Minimal writable flash unit size. In case of NOR flash it is 1 (even |
| * though individual bits can be cleared), in case of NAND flash it is |
| * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR |
| * it is of ECC block size, etc. It is illegal to have writesize = 0. |
| * Any driver registering a struct mtd_info must ensure a writesize of |
| * 1 or larger. |
| */ |
| u32 writesize; |
| |
| /**** Available OOB bytes per page ***/ |
| u32 oobavail; |
| |
| /* |
| * If erasesize is a power of 2 then the shift is stored in |
| * erasesize_shift otherwise erasesize_shift is zero. Ditto writesize. |
| */ |
| u32 erasesize_shift; |
| u32 writesize_shift; |
| |
| /*** Masks based on writesize_shift ***/ |
| u32 writesize_mask; |
| |
| /***partitions info***/ |
| u8 nr_partitions; |
| struct amlnf_partition *partitions; |
| |
| struct phydev_ops ops; |
| /* |
| * Erase is an asynchronous operation. Device drivers are supposed |
| * to call instr->callback() whenever the operation completes, even |
| * if it completes with a failure. |
| * Callers are supposed to pass a callback function and wait for it |
| * to be called before writing to the block. |
| */ |
| int (*erase)(struct amlnand_phydev *phydev); |
| |
| /***basic data operation and included oob data****/ |
| int (*read)(struct amlnand_phydev *phydev); |
| int (*write)(struct amlnand_phydev *phydev); |
| |
| /* In blackbox flight recorder like scenarios we want to make successful |
| * writes in interrupt context. panic_write() is only intended to be |
| * called when its known the kernel is about to panic and we need the |
| * write to succeed. Since the kernel is not going to be running for |
| * much longer, this function can break locks and delay to ensure the |
| * write succeeds (but not sleep). |
| */ |
| int (*panic_write)(struct amlnand_phydev *phydev); |
| |
| int (*read_oob)(struct amlnand_phydev *phydev); |
| |
| /********not support yet**********/ |
| int (*write_oob)(struct amlnand_phydev *phydev); |
| |
| /* |
| * support read data for sect_uint(512bytes in genreal), |
| * not just writesize unit, to improve read data speed. |
| * Not spport yet. |
| */ |
| int (*read_sect)(struct amlnand_phydev *phydev); |
| |
| /* |
| Sync to nand device, used for TLC nand to finish the current write ops |
| */ |
| void (*sync)(struct amlnand_phydev *phydev); |
| |
| /* Chip-supported device locking */ |
| int (*lock)(struct amlnand_phydev *phydev); |
| int (*unlock)(struct amlnand_phydev *phydev); |
| int (*is_locked)(struct amlnand_phydev *phydev); |
| |
| #ifndef AML_NAND_UBOOT |
| /* Power Management functions */ |
| int (*suspend)(struct amlnand_phydev *phydev); |
| void (*resume)(struct amlnand_phydev *phydev); |
| #endif /* AML_NAND_UBOOT */ |
| |
| /* Bad block management functions, maybe managed by NFTL layer*/ |
| int (*block_isbad)(struct amlnand_phydev *phydev); |
| int (*block_markbad)(struct amlnand_phydev *phydev); |
| |
| int (*block_modifybbt)(struct amlnand_phydev *phydev, int value); |
| int (*update_bbt)(struct amlnand_phydev *phydev); |
| int (*phydev_test_block)(struct amlnand_phydev *phydev); |
| /* default mode before reboot */ |
| /* struct notifier_block reboot_notifier; */ |
| }; |
| |
| struct amlnf_logicdev_t { |
| |
| #ifndef AML_NAND_UBOOT |
| struct mutex lock; |
| struct timespec ts_write_start; |
| spinlock_t thread_lock; |
| struct notifier_block nb; |
| struct task_struct *thread; |
| struct class cls; |
| #endif /* AML_NAND_UBOOT */ |
| |
| /* struct aml_nftl_part_t* aml_nftl_part; */ |
| void *priv; |
| |
| struct amlnand_phydev *nand_dev; |
| /* amlnf_dev list, since several dev can share one logicdev. */ |
| /* struct list_head nfdev_list; */ |
| struct list_head list; |
| /* fixme, u32 may not enough! */ |
| int (*read_data)(struct amlnf_logicdev_t *amlnf_logicdev, |
| u32 start_sector, |
| u32 len, |
| u8 *buf); |
| int (*write_data)(struct amlnf_logicdev_t *amlnf_logicdev, |
| u32 start_sector, |
| u32 len, |
| u8 *buf); |
| int (*flush)(struct amlnf_logicdev_t *amlnf_logicdev); |
| int (*shutdown)(struct amlnf_logicdev_t *amlnf_logicdev); |
| |
| struct _nftl_cfg nftl_cfg; |
| }; |
| |
| struct amlnf_dev { |
| /* identifier string */ |
| char name[MAX_NAND_PART_NAME_LEN]; |
| struct amlnf_logicdev_t *logicdev; |
| struct amlnand_phydev *nand_dev; |
| u64 size_sector; |
| u64 offset_sector; |
| u32 mask_flags; |
| |
| #ifndef AML_NAND_UBOOT |
| struct kref ref; |
| struct request *req; |
| struct request_queue *queue; |
| spinlock_t queue_lock; |
| struct mutex mutex_lock_req; |
| struct mutex mutex_lock; |
| struct scatterlist *bounce_sg; |
| u32 bounce_sg_len; |
| bool bg_stop; |
| struct task_struct *thread; |
| struct gendisk *disk; |
| struct attribute_group *disk_attributes; |
| struct class cls; |
| #endif /* AML_NAND_UBOOT */ |
| |
| struct list_head list; |
| /* fixme, u32 may not enough! */ |
| u32(*read_sector)(struct amlnf_dev *dev, |
| u32 start_sector, |
| u32 len, |
| u8 *buf); |
| u32(*write_sector)(struct amlnf_dev *dev, |
| u32 start_sector, |
| u32 len, |
| u8 *buf); |
| u32(*flush)(struct amlnf_dev *dev); |
| }; |
| |
| extern struct amlnand_phydev *phydev; |
| extern struct list_head nphy_dev_list; |
| extern struct list_head nf_dev_list; |
| |
| struct amlnf_platform_data { |
| volatile uint32_t *poc_reg; |
| volatile uint32_t *nf_reg_base; |
| volatile uint32_t *ext_clk_reg; |
| u32 irq; |
| }; |
| |
| struct aml_nand_device { |
| struct amlnf_platform_data *platform_data; |
| int nandboot; |
| }; |
| |
| extern unsigned char device_model[20]; |
| |
| extern struct list_head nphy_dev_list; |
| //extern struct partitions *part_table; |
| extern struct aml_nand_device *aml_nand_dev; |
| extern int boot_device_flag; |
| #ifndef AML_NAND_UBOOT |
| #define amlnf_notifier_to_blk(l) container_of(l, struct amlnf_logicdev_t, nb) |
| extern void nand_get_chip(void *aml_chip); |
| extern void nand_release_chip(void *aml_chip); |
| extern int check_storage_device(void); |
| |
| |
| |
| extern ssize_t verify_nand_page(struct class *class, |
| struct class_attribute *attr, |
| const char *buf, |
| size_t count); |
| extern ssize_t dump_nand_page(struct class *class, |
| struct class_attribute *attr, |
| const char *buf, |
| size_t count); |
| extern ssize_t show_nand_info(struct class *class, |
| struct class_attribute *attr, |
| char *buf); |
| extern ssize_t show_bbt_table(struct class *class, |
| struct class_attribute *attr, |
| const char *buf, |
| size_t count); |
| extern ssize_t change_test_sync_flag(struct class *class, |
| struct class_attribute *attr, |
| const char *buf, |
| size_t count); |
| extern ssize_t show_amlnf_version_info(struct class *class, |
| struct class_attribute *attr, |
| char *buf); |
| extern ssize_t nand_page_read(struct class *class, |
| struct class_attribute *attr, |
| const char *buf, |
| size_t count); |
| extern ssize_t nand_page_write(struct class *class, |
| struct class_attribute *attr, |
| const char *buf, |
| size_t count); |
| extern ssize_t show_nand_info(struct class *class, struct class_attribute *attr, char *buf); |
| extern ssize_t show_bbt_table(struct class *class, struct class_attribute *attr, char *buf); |
| /* */ |
| extern u16 aml_nftl_get_part_write_cache_nums(void *_part); |
| extern int logicdev_bg_handle(void *priv); |
| /* */ |
| extern ssize_t show_part_struct(struct class *class, |
| struct class_attribute *attr, |
| char *buf); |
| extern ssize_t show_list(struct class *class, |
| struct class_attribute *attr, |
| const char *buf); |
| extern ssize_t discard_page(struct class *class, |
| struct class_attribute *attr, |
| const char *buf); |
| extern ssize_t do_gc_all(struct class *class, |
| struct class_attribute *attr, |
| const char *buf); |
| extern ssize_t do_gc_one(struct class *class, |
| struct class_attribute *attr, |
| const char *buf); |
| extern ssize_t do_test(struct class *class, |
| struct class_attribute *attr, |
| const char *buf, |
| size_t count); |
| |
| extern int amlnf_pdev_register(struct amlnand_phydev *phydev); |
| extern int amlnf_ldev_register(void); |
| extern void amlchip_resume(struct amlnand_phydev *phydev); |
| extern int phydev_suspend(struct amlnand_phydev *phydev); |
| extern void phydev_resume(struct amlnand_phydev *phydev); |
| extern int amlphy_prepare(u32 flag); |
| |
| extern int add_ntd_partitions(struct amlnand_phydev *master); |
| extern int boot_device_register(struct amlnand_phydev *phydev); |
| #endif /* AML_NAND_UBOOT */ |
| extern void *aml_nand_malloc(u32 size); |
| extern void aml_nand_free(void *ptr); |
| |
| #ifndef AML_NAND_UBOOT |
| extern void *amlnf_dma_malloc(u32 size, u8 flag); |
| extern void amlnf_dma_free(const void *ptr, u32 size, u8 flag); |
| #endif /* AML_NAND_UBOOT */ |
| |
| extern int amlnf_get_logicdev(struct amlnf_logicdev_t *amlnf_logicdev); |
| extern int amlnf_free_logicdev(struct amlnf_logicdev_t *amlnf_logicdev); |
| extern int amlnf_logicdev_mis_init(struct amlnf_logicdev_t *amlnf_logicdev); |
| |
| |
| extern void pinmux_select_chip(u32 ce_enable, |
| u32 rb_enable, |
| u32 flag); |
| |
| extern int amlnf_phy_init(u8 flag, struct platform_device *pdev); |
| |
| extern int amlnf_logic_init(u32 flag); |
| extern int amlnf_dev_init(u32 flag); |
| |
| extern int is_phydev_off_adjust(void); |
| extern int get_adjust_block_num(void); |
| |
| extern void amldev_dumpinfo(struct amlnand_phydev *phydev); |
| |
| #endif |