drivers: rkflash: fix rkflash ftl error

1.Modify the incompatibility of FTL in kernel 4.4;
2.Add arm v7 sftl lib and arm v8 sftl lib
3.Unified naming format and variable with code in u-boot

Change-Id: I43ec418bb278fc3590fcb73d50ae6f6c9281ecfa
Signed-off-by: Dingqiang Lin <jon.lin@rock-chips.com>
This commit is contained in:
Dingqiang Lin
2018-06-11 16:15:59 +08:00
committed by Tao Huang
parent 47e4722af1
commit 01faef723d
20 changed files with 83492 additions and 261 deletions

View File

@@ -6,10 +6,10 @@ menuconfig RK_FLASH
tristate "Rockchip Flash Devices Support"
default n
help
Enable rockchip flash devices support.
This enables support for Rockchip Flash Devices including Nandc Slc
Nand, SFC Spi Nand and SFC Spi Nor.
rkflash driver support 3-type flash devices: NANDC NAND, SFC_NOR
and SFC_NAND.
They're block interface.
Say Y when you have a board with one of them.
@@ -18,45 +18,48 @@ if RK_FLASH
comment "Rockchip Flash Devices"
config RK_NANDC_NAND
tristate "RK NANDC NAND Device Support"
tristate "Rockchip NANDC Slc Nand Devices support"
default n
depends on (BLOCK_RKNAND != y && RK_NAND != y)
depends on RK_NAND != y
help
Enable NANDC_NAND device support.
This enables support for NANDC Slc Nand Devices.
It's block interface. only effective for some kinds of slc nand
flash, and it's compatible with spi nand flash drivers.
It's block interface, 512Kb/sector.
Say Y when you have a board with nand flash supported by rockchip.
nandc controller.
config RK_SFC_NOR
tristate "RK SFC NOR Device Support"
default n
help
Enable SFC_NOR device support.
It's block interface.
Say Y when you have a board with nor flash supported by rockchip
sfc controller.
Say Y when you have a board with Slc Nand Flash supported by Rockchip
Nandc controller.
config RK_SFC_NAND
tristate "RK SFC NAND Device Support"
tristate "Rockchip SFC Spi Nand Devices support"
default n
depends on RK_NAND != y
help
This enables support for Rockchip SFC Spi Nand Devices.
It's block interface, 512Kb/sector.
Say Y when you have a board with Spi Nand Flash supported by Rockchip
Serial Flash Controller(SFC).
config RK_SFC_NOR
tristate "Rockchip SFC Spi Nor Devices Support"
default n
help
Enable SFC_NAND device support.
It's block interface
Say Y when you have a board with nand flash supported by rockchip
sfc controller.
This enables support for Rockchip SFC Spi Nor Devices.
It's block interface,512Kb/sector.
Say Y when you have a board with Spi Nor Flash supported by Rockchip
Serial Flash Controller(SFC).
config RK_SFC_NOR_MTD
bool "RK SFC NOR mtd Interface Support"
depends on RK_SFC_NOR
default n
depends on RK_SFC_NOR
help
Enable mtd interface for SFC_NOR device.
It's mtd block interface.
Say Y when you have a board with mtd interface nor flash supported
by rockchip sfc controller.
Say Y when you wanna use mtd interface for SFC_NOR flash.
endif # RK_FLASH

View File

@@ -1,6 +1,16 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_RK_NANDC_NAND) += rkflash_blk.o rkflash_debug.o rknandc_base.o nand_boot.o flash.o nandc.o ftl_flash_plat.o rk_sftl.o
obj-$(CONFIG_RK_SFC_NOR) += rkflash_blk.o rkflash_debug.o rksfc_base.o sfc_nor_boot.o sfc_nor.o sfc.o
obj-$(CONFIG_RK_NANDC_NAND) += rkflash_blk.o rknandc_base.o rkflash_debug.o nand_boot.o flash.o nandc.o ftl_flash_plat.o
obj-$(CONFIG_RK_SFC_NAND) += rkflash_blk.o rksfc_base.o rkflash_debug.o sfc_nand_boot.o sfc_nand.o sfc.o ftl_flash_plat.o
obj-$(CONFIG_RK_SFC_NOR) += rkflash_blk.o rksfc_base.o rkflash_debug.o sfc_nor_boot.o sfc_nor.o sfc.o
obj-$(CONFIG_RK_SFC_NOR_MTD) += sfc_nor_mtd.o
obj-$(CONFIG_RK_SFC_NAND) += rkflash_blk.o rkflash_debug.o rksfc_base.o sfc_nand_boot.o sfc_nand.o sfc.o ftl_flash_plat.o rk_sftl.o
ifneq (, $(CONFIG_RK_NANDC_NAND)$(CONFIG_RK_SFC_NAND))
ifdef CONFIG_ARM64
obj-y += rk_sftl_arm_v8.o
else
obj-y += rk_sftl_arm_v7.o
endif
endif

View File

@@ -8,6 +8,7 @@
#include "flash.h"
#include "flash_com.h"
#include "nandc.h"
#include "rkflash_debug.h"
#define FLASH_STRESS_TEST_EN 0
@@ -69,9 +70,9 @@ static void flash_read_id_raw(u8 cs, u8 *buf)
nandc_flash_de_cs(cs);
if (ptr[0] != 0xFF && ptr[0] && ptr[1] != 0xFF)
PRINT_E("No.%d FLASH ID:%x %x %x %x %x %x\n",
cs + 1, ptr[0], ptr[1], ptr[2],
ptr[3], ptr[4], ptr[5]);
PRINT_NANDC_E("No.%d FLASH ID:%x %x %x %x %x %x\n",
cs + 1, ptr[0], ptr[1], ptr[2],
ptr[3], ptr[4], ptr[5]);
}
static void flash_bch_sel(u8 bits)
@@ -152,12 +153,12 @@ static u32 flash_read_page_raw(u8 cs, u32 page_addr, u32 *p_data, u32 *p_spare)
error_ecc_bits = nandc_xfer_data(cs, NANDC_READ, sec_per_page,
p_data, p_spare);
if (error_ecc_bits > 2) {
PRINT_E("FlashReadRawPage %x %x error_ecc_bits %d\n",
cs, page_addr, error_ecc_bits);
PRINT_NANDC_E("FlashReadRawPage %x %x error_ecc_bits %d\n",
cs, page_addr, error_ecc_bits);
if (p_data)
rknand_print_hex("data:", p_data, 4, 8);
PRINT_NANDC_HEX("data:", p_data, 4, 8);
if (p_spare)
rknand_print_hex("spare:", p_spare, 4, 2);
PRINT_NANDC_HEX("spare:", p_spare, 4, 2);
}
nandc_flash_de_cs(cs);
@@ -196,10 +197,10 @@ static u32 flash_prog_page(u8 cs, u32 page_addr, u32 *p_data, u32 *p_spare)
status = flash_read_status(cs, page_addr);
nandc_flash_de_cs(cs);
status &= 0x01;
if (status)
PRINT_I("%s addr=%x status=%x\n", __func__,
page_addr, status);
if (status) {
PRINT_NANDC_I("%s addr=%x status=%x\n",
__func__, page_addr, status);
}
return status;
}
@@ -214,10 +215,10 @@ static u32 flash_erase_block(u8 cs, u32 page_addr)
status = flash_read_status(cs, page_addr);
nandc_flash_de_cs(cs);
status &= 0x01;
if (status)
PRINT_I("%s addr=%x status=%x\n", __func__,
page_addr, status);
if (status) {
PRINT_NANDC_I("%s pageadd=%x status=%x\n",
__func__, page_addr, status);
}
return status;
}
@@ -266,7 +267,7 @@ static s32 get_bad_blk_list(u16 *table, u32 die)
bad_flag1 != 0xFF ||
bad_flag2 != 0xFF) {
table[bad_cnt++] = blk;
PRINT_E("die[%d], bad_blk[%d]\n", die, blk);
PRINT_NANDC_E("die[%d], bad_blk[%d]\n", die, blk);
}
}
return bad_cnt;
@@ -293,8 +294,7 @@ static void flash_test(void)
u32 blk_addr = 64;
u32 is_bad_blk = 0;
PRINT_E("%s\n", __func__);
PRINT_NANDC_E("%s\n", __func__);
bad_blk_num = 0;
bad_page_num = 0;
bad_cnt = get_bad_blk_list(bad_blk_list, 0);
@@ -307,7 +307,7 @@ static void flash_test(void)
if (i < bad_cnt)
continue;
is_bad_blk = 0;
PRINT_E("Flash prog block: %x\n", blk);
PRINT_NANDC_E("Flash prog block: %x\n", blk);
flash_erase_block(0, blk * blk_addr);
for (page = 0; page < pages_num; page++) {
page_addr = blk * blk_addr + page;
@@ -336,19 +336,21 @@ static void flash_test(void)
}
if (is_bad_blk) {
bad_page_num++;
PRINT_E("ERR:page%x, ret=%x\n", page_addr, ret);
rknand_print_hex("data:", pread, 4, 8);
rknand_print_hex("spare:", pspare_read, 4, 2);
PRINT_NANDC_E("ERR:page %x, ret= %x\n",
page_addr,
ret);
PRINT_NANDC_HEX("data:", pread, 4, 8);
PRINT_NANDC_HEX("spare:", pspare_read, 4, 2);
}
}
flash_erase_block(0, blk * blk_addr);
if (is_bad_blk)
bad_blk_num++;
}
PRINT_E("bad_blk_num = %d, bad_page_num = %d\n",
bad_blk_num, bad_page_num);
PRINT_NANDC_E("bad_blk_num = %d, bad_page_num = %d\n",
bad_blk_num, bad_page_num);
PRINT_E("Flash Test Finish!!!\n");
PRINT_NANDC_E("Flash Test Finish!!!\n");
while (1)
;
}
@@ -369,57 +371,58 @@ static void flash_die_info_init(void)
nand_para.blk_per_plane;
}
static void flash_print_info(void)
static void nandc_flash_print_info(void)
{
PRINT_I("No.0 FLASH ID: %x %x %x %x %x %x\n",
nand_para.nand_id[0],
nand_para.nand_id[1],
nand_para.nand_id[2],
nand_para.nand_id[3],
nand_para.nand_id[4],
nand_para.nand_id[5]);
PRINT_I("die_per_chip: %x\n", nand_para.die_per_chip);
PRINT_I("sec_per_page: %x\n", nand_para.sec_per_page);
PRINT_I("page_per_blk: %x\n", nand_para.page_per_blk);
PRINT_I("cell: %x\n", nand_para.cell);
PRINT_I("plane_per_die: %x\n", nand_para.plane_per_die);
PRINT_I("blk_per_plane: %x\n", nand_para.blk_per_plane);
PRINT_I("TotleBlock: %x\n", g_totle_block);
PRINT_I("die gap: %x\n", nand_para.die_gap);
PRINT_I("lsb_mode: %x\n", nand_para.lsb_mode);
PRINT_I("read_retry_mode: %x\n", nand_para.read_retry_mode);
PRINT_I("ecc_bits: %x\n", nand_para.ecc_bits);
PRINT_I("Use ecc_bits: %x\n", g_nand_flash_ecc_bits);
PRINT_I("access_freq: %x\n", nand_para.access_freq);
PRINT_I("opt_mode: %x\n", nand_para.opt_mode);
PRINT_NANDC_I("No.0 FLASH ID: %x %x %x %x %x %x\n",
nand_para.nand_id[0],
nand_para.nand_id[1],
nand_para.nand_id[2],
nand_para.nand_id[3],
nand_para.nand_id[4],
nand_para.nand_id[5]);
PRINT_NANDC_I("die_per_chip: %x\n", nand_para.die_per_chip);
PRINT_NANDC_I("sec_per_page: %x\n", nand_para.sec_per_page);
PRINT_NANDC_I("page_per_blk: %x\n", nand_para.page_per_blk);
PRINT_NANDC_I("cell: %x\n", nand_para.cell);
PRINT_NANDC_I("plane_per_die: %x\n", nand_para.plane_per_die);
PRINT_NANDC_I("blk_per_plane: %x\n", nand_para.blk_per_plane);
PRINT_NANDC_I("TotleBlock: %x\n", g_totle_block);
PRINT_NANDC_I("die gap: %x\n", nand_para.die_gap);
PRINT_NANDC_I("lsb_mode: %x\n", nand_para.lsb_mode);
PRINT_NANDC_I("read_retry_mode: %x\n", nand_para.read_retry_mode);
PRINT_NANDC_I("ecc_bits: %x\n", nand_para.ecc_bits);
PRINT_NANDC_I("Use ecc_bits: %x\n", g_nand_flash_ecc_bits);
PRINT_NANDC_I("access_freq: %x\n", nand_para.access_freq);
PRINT_NANDC_I("opt_mode: %x\n", nand_para.opt_mode);
PRINT_I("Cache read enable: %x\n",
nand_para.operation_opt & NAND_CACHE_READ_EN ? 1 : 0);
PRINT_I("Cache random read enable: %x\n",
nand_para.operation_opt & NAND_CACHE_RANDOM_READ_EN ? 1 : 0);
PRINT_I("Cache prog enable: %x\n",
nand_para.operation_opt & NAND_CACHE_PROG_EN ? 1 : 0);
PRINT_I("multi read enable: %x\n",
nand_para.operation_opt & NAND_MULTI_READ_EN ? 1 : 0);
PRINT_NANDC_I("Cache read enable: %x\n",
nand_para.operation_opt & NAND_CACHE_READ_EN ? 1 : 0);
PRINT_NANDC_I("Cache random read enable: %x\n",
nand_para.operation_opt &
NAND_CACHE_RANDOM_READ_EN ? 1 : 0);
PRINT_NANDC_I("Cache prog enable: %x\n",
nand_para.operation_opt & NAND_CACHE_PROG_EN ? 1 : 0);
PRINT_NANDC_I("multi read enable: %x\n",
nand_para.operation_opt & NAND_MULTI_READ_EN ? 1 : 0);
PRINT_I("multi prog enable: %x\n",
nand_para.operation_opt & NAND_MULTI_PROG_EN ? 1 : 0);
PRINT_I("interleave enable: %x\n",
nand_para.operation_opt & NAND_INTERLEAVE_EN ? 1 : 0);
PRINT_NANDC_I("multi prog enable: %x\n",
nand_para.operation_opt & NAND_MULTI_PROG_EN ? 1 : 0);
PRINT_NANDC_I("interleave enable: %x\n",
nand_para.operation_opt & NAND_INTERLEAVE_EN ? 1 : 0);
PRINT_I("read retry enable: %x\n",
nand_para.operation_opt & NAND_READ_RETRY_EN ? 1 : 0);
PRINT_I("randomizer enable: %x\n",
nand_para.operation_opt & NAND_RANDOMIZER_EN ? 1 : 0);
PRINT_NANDC_I("read retry enable: %x\n",
nand_para.operation_opt & NAND_READ_RETRY_EN ? 1 : 0);
PRINT_NANDC_I("randomizer enable: %x\n",
nand_para.operation_opt & NAND_RANDOMIZER_EN ? 1 : 0);
PRINT_I("SDR enable: %x\n",
nand_para.operation_opt & NAND_SDR_EN ? 1 : 0);
PRINT_I("ONFI enable: %x\n",
nand_para.operation_opt & NAND_ONFI_EN ? 1 : 0);
PRINT_I("TOGGLE enable: %x\n",
nand_para.operation_opt & NAND_TOGGLE_EN ? 1 : 0);
PRINT_NANDC_I("SDR enable: %x\n",
nand_para.operation_opt & NAND_SDR_EN ? 1 : 0);
PRINT_NANDC_I("ONFI enable: %x\n",
nand_para.operation_opt & NAND_ONFI_EN ? 1 : 0);
PRINT_NANDC_I("TOGGLE enable: %x\n",
nand_para.operation_opt & NAND_TOGGLE_EN ? 1 : 0);
PRINT_I("g_nand_idb_res_blk_num: %x\n", g_nand_idb_res_blk_num);
PRINT_NANDC_I("g_nand_idb_res_blk_num: %x\n", g_nand_idb_res_blk_num);
}
static void ftl_flash_init(void)
@@ -452,7 +455,7 @@ u32 nandc_flash_init(void __iomem *nandc_addr)
{
u32 cs;
/* PRINT_I("...%s enter...\n", __func__); */
PRINT_NANDC_I("...%s enter...\n", __func__);
g_nand_idb_res_blk_num = MAX_IDB_RESERVED_BLOCK;
nandc_init(nandc_addr);
@@ -467,7 +470,9 @@ u32 nandc_flash_init(void __iomem *nandc_addr)
if (id_byte[0][1] != 0xF1 &&
id_byte[0][1] != 0xDA &&
id_byte[0][1] != 0xD1 &&
id_byte[0][1] != 0x95)
id_byte[0][1] != 0x95 &&
id_byte[0][1] != 0xDC)
return FTL_UNSUPPORTED_FLASH;
}
}
@@ -475,10 +480,19 @@ u32 nandc_flash_init(void __iomem *nandc_addr)
if (id_byte[0][1] == 0xDA) {
nand_para.plane_per_die = 2;
nand_para.nand_id[1] = 0xDA;
} else if (id_byte[0][1] == 0xDC) {
nand_para.nand_id[1] = 0xDC;
if (id_byte[0][0] == 0x2C && id_byte[0][3] == 0xA6) {
nand_para.plane_per_die = 2;
nand_para.sec_per_page = 8;
} else {
nand_para.plane_per_die = 2;
nand_para.blk_per_plane = 2048;
}
}
flash_die_info_init();
flash_bch_sel(nand_para.ecc_bits);
flash_print_info();
nandc_flash_print_info();
/* flash_print_info(); */
ftl_flash_init();

View File

@@ -3,6 +3,8 @@
/* Copyright (c) 2018 Rockchip Electronics Co. Ltd. */
#include <linux/kernel.h>
#include <linux/slab.h>
#include "flash_com.h"
struct nand_phy_info g_nand_phy_info;
@@ -12,6 +14,16 @@ static u32 check_buf[MAX_FLASH_PAGE_SIZE / 4];
static u32 check_spare_buf[MAX_FLASH_PAGE_SIZE / 8 / 4];
static u32 pg_buf0[MAX_FLASH_PAGE_SIZE / 4];
void *ftl_malloc(int size)
{
return kmalloc(size, GFP_KERNEL | GFP_DMA);
}
void ftl_free(void *buf)
{
kfree(buf);
}
static u32 l2p_addr_tran(struct nand_req *req, u32 *addr, u32 *p_die)
{
u16 block_index, page_index;

View File

@@ -6,7 +6,7 @@
#include <linux/mutex.h>
#include "flash.h"
#include "nand_boot.h"
#include "rkflash_api.h"
#include "rk_sftl.h"
#include "typedef.h"

View File

@@ -1,17 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018 Rockchip Electronics Co. Ltd. */
#ifndef _SFC_H
#define _SFC_H
int sftl_flash_init(void __iomem *reg_addr);
void sftl_flash_read_id(u8 chip_sel, void *buf);
int sftl_flash_read(unsigned int sec, unsigned int n_sec, void *p_data);
int sftl_flash_write(unsigned int sec, unsigned int n_sec, void *p_data);
unsigned int sftl_flash_get_capacity(void);
void sftl_flash_deinit(void);
int sftl_flash_resume(void __iomem *reg_addr);
void sftl_flash_clean_irq(void);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -6,15 +6,36 @@
#define __RK_FLASH_API_H
#ifdef CONFIG_RK_NANDC_NAND
#include "nand_boot.h"
int sftl_flash_init(void __iomem *reg_addr);
void sftl_flash_read_id(u8 chip_sel, void *buf);
int sftl_flash_read(unsigned int sec, unsigned int n_sec, void *p_data);
int sftl_flash_write(unsigned int sec, unsigned int n_sec, void *p_data);
unsigned int sftl_flash_get_capacity(void);
void sftl_flash_deinit(void);
int sftl_flash_resume(void __iomem *reg_addr);
void sftl_flash_clean_irq(void);
#endif
#ifdef CONFIG_RK_SFC_NOR
#include "sfc_nor_boot.h"
int spi_flash_init(void __iomem *reg_addr);
void spi_flash_read_id(u8 chip_sel, void *buf);
int snor_read_lba(unsigned int sec, unsigned int n_sec, void *p_data);
int snor_write_lba(unsigned int sec, unsigned int n_sec, void *p_data);
unsigned int snor_capacity(void);
void snor_deinit(void);
int snor_resume(void __iomem *reg_addr);
int snor_vendor_read(unsigned int sec, unsigned int n_sec, void *p_data);
int snor_vendor_write(unsigned int sec, unsigned int n_sec, void *p_data);
#endif
#ifdef CONFIG_RK_SFC_NAND
#include "sfc_nand_boot.h"
int snand_init(void __iomem *reg_addr);
int snand_read(unsigned int sec, unsigned int n_sec, void *p_data);
int snand_write(unsigned int sec, unsigned int n_sec, void *p_data);
unsigned int snand_get_capacity(void);
void snand_deinit(void);
int snand_resume(void __iomem *reg_addr);
void sfc_clean_irq(void);
#endif
#endif

View File

@@ -6,8 +6,9 @@
#include "rkflash_debug.h"
#include "sfc_nor.h"
#include "typedef.h"
void rkflash_print_hex(char *s, void *buf, u32 width, u32 len)
void rknand_print_hex(char *s, void *buf, int width, int len)
{
print_hex_dump(KERN_WARNING, s, DUMP_PREFIX_OFFSET,
16, width, buf, len * width, 0);

View File

@@ -5,6 +5,11 @@
#ifndef _RKFLASH_DEBUG_H
#define _RKFLASH_DEBUG_H
/*
* Test switch
*/
#define BLK_STRESS_TEST_EN 0
/*
* Print switch, set to 1 if needed
* I - info
@@ -16,9 +21,9 @@
#define PRINT_SWI_SFC_E 1
#define PRINT_SWI_SFC_HEX 1
/*
* Test switch
*/
#define PRINT_SWI_NANDC_I 0
#define PRINT_SWI_NANDC_E 1
#define PRINT_SWI_NANDC_HEX 1
#if (PRINT_SWI_SFC_I)
#define PRINT_SFC_I(...) pr_info(__VA_ARGS__)
@@ -27,18 +32,38 @@
#endif
#if (PRINT_SWI_SFC_E)
#define PRINT_SFC_E(...) pr_err(__VA_ARGS__)
#define PRINT_SFC_E(...) pr_info(__VA_ARGS__)
#else
#define PRINT_SFC_E(...)
#endif
#if (PRINT_SWI_SFC_HEX)
#define PRINT_SFC_HEX(s, buf, width, len)\
rkflash_print_hex(s, buf, width, len)
rknand_print_hex(s, buf, width, len)
#else
#define PRINT_SFC_HEX(s, buf, width, len)
#endif
#if (PRINT_SWI_NANDC_I)
#define PRINT_NANDC_I(...) pr_info(__VA_ARGS__)
#else
#define PRINT_NANDC_I(...)
#endif
#if (PRINT_SWI_NANDC_E)
#define PRINT_NANDC_E(...) pr_info(__VA_ARGS__)
#else
#define PRINT_NANDC_E(...)
#endif
#if (PRINT_SWI_NANDC_HEX)
#define PRINT_NANDC_HEX(s, buf, width, len)\
rknand_print_hex(s, buf, width, len)
#else
#define PRINT_NANDC_HEX(s, buf, width, len)
#endif
void rkflash_print_hex(char *s, void *buf, u32 width, u32 len);
#endif

View File

@@ -122,8 +122,10 @@ static int rknandc_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "%s get clk error\n", __func__);
return -1;
}
clk_prepare_enable(g_nandc_info.g_clk);
clk_prepare_enable(g_nandc_info.ahb_clk);
if (!(IS_ERR(g_nandc_info.g_clk)))
clk_prepare_enable(g_nandc_info.g_clk);
clk_set_rate(g_nandc_info.clk, RKNANDC_CLK_SET_RATE);
g_nandc_info.clk_rate = clk_get_rate(g_nandc_info.clk);
clk_prepare_enable(g_nandc_info.clk);
@@ -154,6 +156,7 @@ static void rknandc_shutdown(struct platform_device *pdev)
#ifdef CONFIG_OF
static const struct of_device_id of_rknandc_match[] = {
{.compatible = "rockchip,rk-nandc"},
{.compatible = "rockchip,nandc"},
{}
};

View File

@@ -8,66 +8,10 @@
#include "flash.h"
#include "flash_com.h"
#include "rkflash_debug.h"
#include "sfc.h"
#include "sfc_nand.h"
#define SFC_NAND_STRESS_TEST_EN 0
#define SFC_NAND_PROG_ERASE_ERROR -2
#define SFC_NAND_HW_ERROR -1
#define SFC_NAND_ECC_ERROR NAND_ERROR
#define SFC_NAND_ECC_REFRESH NAND_STS_REFRESH
#define SFC_NAND_ECC_OK NAND_STS_OK
#define SFC_NAND_PAGE_MAX_SIZE 2112
#define FEA_READ_STATUE_MASK (0x3 << 0)
#define FEA_STATUE_MODE1 0
#define FEA_STATUE_MODE2 1
#define FEA_4BIT_READ BIT(2)
#define FEA_4BIT_PROG BIT(3)
#define FEA_4BYTE_ADDR BIT(4)
#define FEA_4BYTE_ADDR_MODE BIT(5)
struct SFC_NAND_DEV_T {
u32 capacity;
u32 block_size;
u16 page_size;
u8 manufacturer;
u8 mem_type;
u8 read_lines;
u8 prog_lines;
u8 page_read_cmd;
u8 page_prog_cmd;
};
struct nand_info {
u32 id;
u16 sec_per_page;
u16 page_per_blk;
u16 plane_per_die;
u16 blk_per_plane;
u8 page_read_cmd;
u8 page_prog_cmd;
u8 read_cache_cmd_1;
u8 prog_cache_cmd_1;
u8 read_cache_cmd_4;
u8 prog_cache_cmd_4;
u8 block_erase_cmd;
u8 feature;
u8 density; /* (1 << density) sectors*/
u8 max_ecc_bits;
u8 QE_address;
u8 QE_bits;
u8 spare_offs_1;
u8 spare_offs_2;
};
static struct nand_info spi_nand_tbl[] = {
/* TC58CVG0S0HxAIx */
{0x98C2, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x02, 0xD8, 0x00, 18, 8, 0xB0, 0XFF, 4, 8},
@@ -98,7 +42,7 @@ static struct nand_info spi_nand_tbl[] = {
static u8 id_byte[8];
static struct nand_info *p_nand_info;
static u32 gp_page_buf[SFC_NAND_PAGE_MAX_SIZE / 4];
static struct SFC_NAND_DEV_T sfc_nand_dev;
static struct SFNAND_DEV sfc_nand_dev;
static struct nand_info *spi_nand_get_info(u8 *nand_id)
{
@@ -243,7 +187,7 @@ static u32 sfc_nand_prog_page(u8 cs, u32 addr, u32 *p_data, u32 *p_spare)
sfctrl.d32 = 0;
sfctrl.b.datalines = sfc_nand_dev.prog_lines;
sfctrl.b.addrbits = 16;
ret = sfc_request(sfcmd.d32, sfctrl.d32, 0, gp_page_buf);
sfc_request(sfcmd.d32, sfctrl.d32, 0, gp_page_buf);
sfcmd.d32 = 0;
sfcmd.b.cmd = p_nand_info->page_prog_cmd;
@@ -274,9 +218,9 @@ static u32 sfc_nand_read_page(u8 cs, u32 addr, u32 *p_data, u32 *p_spare)
sfcmd.b.cmd = p_nand_info->page_read_cmd;
sfcmd.b.datasize = 0;
sfcmd.b.addrbits = SFC_ADDR_24BITS;
ret = sfc_request(sfcmd.d32, 0, addr, p_data);
sfc_request(sfcmd.d32, 0, addr, p_data);
ret = sfc_nand_wait_busy(&status, 1000 * 1000);
sfc_nand_wait_busy(&status, 1000 * 1000);
ecc = (status >> 4) & 0x03;
if (sfc_nand_dev.read_lines == DATA_LINES_X4 &&
p_nand_info->QE_address == 0xFF &&
@@ -327,11 +271,11 @@ static u32 sfc_nand_read_page(u8 cs, u32 addr, u32 *p_data, u32 *p_spare)
}
if (ret != SFC_NAND_ECC_OK) {
PRINT_E("%s[0x%x], ret=0x%x\n", __func__, addr, ret);
PRINT_SFC_E("%s[0x%x], ret=0x%x\n", __func__, addr, ret);
if (p_data)
rknand_print_hex("data:", p_data, 4, 8);
PRINT_SFC_HEX("data:", p_data, 4, 8);
if (p_spare)
rknand_print_hex("spare:", p_spare, 4, 2);
PRINT_SFC_HEX("spare:", p_spare, 4, 2);
}
return ret;
}
@@ -363,7 +307,7 @@ static int sfc_nand_get_bad_block_list(u16 *table, u32 die)
u32 *pread;
u32 *pspare_read;
PRINT_E("%s\n", __func__);
PRINT_SFC_E("%s\n", __func__);
pread = ftl_malloc(2048);
pspare_read = ftl_malloc(8);
bad_cnt = 0;
@@ -377,7 +321,7 @@ static int sfc_nand_get_bad_block_list(u16 *table, u32 die)
if (pread[0] != 0xFFFFFFFF ||
pspare_read[0] != 0xFFFFFFFF) {
table[bad_cnt++] = blk;
PRINT_E("die[%d], bad_blk[%d]\n", die, blk);
PRINT_SFC_E("die[%d], bad_blk[%d]\n", die, blk);
}
}
ftl_free(pread);
@@ -406,7 +350,7 @@ static void sfc_nand_test(void)
u32 blk_addr = 64;
u32 is_bad_blk = 0;
PRINT_E("%s\n", __func__);
PRINT_SFC_E("%s\n", __func__);
bad_blk_num = 0;
bad_page_num = 0;
@@ -420,7 +364,7 @@ static void sfc_nand_test(void)
if (i < bad_cnt)
continue;
is_bad_blk = 0;
PRINT_E("Flash prog block: %x\n", blk);
PRINT_SFC_E("Flash prog block: %x\n", blk);
sfc_nand_erase_block(0, blk * blk_addr);
for (page = 0; page < pages_num; page++) {
page_addr = blk * blk_addr + page;
@@ -449,19 +393,20 @@ static void sfc_nand_test(void)
}
if (is_bad_blk) {
bad_page_num++;
PRINT_E("ERR:page%x, ret=%x\n", page_addr, ret);
rknand_print_hex("data:", pread, 4, 8);
rknand_print_hex("spare:", pspare_read, 4, 2);
PRINT_SFC_E("ERR:page%x, ret=%x\n",
page_addr, ret);
PRINT_SFC_HEX("data:", pread, 4, 8);
PRINT_SFC_HEX("spare:", pspare_read, 4, 2);
}
}
sfc_nand_erase_block(0, blk * blk_addr);
if (is_bad_blk)
bad_blk_num++;
}
PRINT_E("bad_blk_num = %d, bad_page_num = %d\n",
bad_blk_num, bad_page_num);
PRINT_SFC_E("bad_blk_num = %d, bad_page_num = %d\n",
bad_blk_num, bad_page_num);
PRINT_E("Flash Test Finish!!!\n");
PRINT_SFC_E("Flash Test Finish!!!\n");
while (1)
;
}
@@ -514,12 +459,13 @@ static int spi_nand_enable_QE(void)
return ret;
}
u32 sfc_nand_init(void __iomem *sfc_addr)
u32 sfc_nand_init(void)
{
PRINT_E("%s\n", __func__);
sfc_init(sfc_addr);
PRINT_SFC_I("...%s enter...\n", __func__);
sfc_nand_read_id_raw(id_byte);
PRINT_E("sfc_nand id: %x %x %x\n", id_byte[0], id_byte[1], id_byte[2]);
PRINT_SFC_E("sfc_nand id: %x %x %x\n",
id_byte[0], id_byte[1], id_byte[2]);
if (id_byte[0] == 0xFF || id_byte[0] == 0x00)
return FTL_NO_FLASH;
@@ -554,15 +500,15 @@ u32 sfc_nand_init(void __iomem *sfc_addr)
u8 status;
sfc_nand_read_feature(0xA0, &status);
PRINT_E("sfc_nand A0 = 0x%x\n", status);
PRINT_SFC_I("sfc_nand A0 = 0x%x\n", status);
sfc_nand_read_feature(0xB0, &status);
PRINT_E("sfc_nand B0 = 0x%x\n", status);
PRINT_SFC_I("sfc_nand B0 = 0x%x\n", status);
sfc_nand_read_feature(0xC0, &status);
PRINT_E("sfc_nand C0 = 0x%x\n", status);
PRINT_E("read_lines = %x\n", sfc_nand_dev.read_lines);
PRINT_E("prog_lines = %x\n", sfc_nand_dev.prog_lines);
PRINT_E("page_read_cmd = %x\n", sfc_nand_dev.page_read_cmd);
PRINT_E("page_prog_cmd = %x\n", sfc_nand_dev.page_prog_cmd);
PRINT_SFC_I("sfc_nand C0 = 0x%x\n", status);
PRINT_SFC_I("read_lines = %x\n", sfc_nand_dev.read_lines);
PRINT_SFC_I("prog_lines = %x\n", sfc_nand_dev.prog_lines);
PRINT_SFC_I("page_read_cmd = %x\n", sfc_nand_dev.page_read_cmd);
PRINT_SFC_I("page_prog_cmd = %x\n", sfc_nand_dev.page_prog_cmd);
}
ftl_flash_init();

View File

@@ -5,7 +5,24 @@
#ifndef __SFC_NAND_H
#define __SFC_NAND_H
/* Manufactory ID */
#define SFC_NAND_STRESS_TEST_EN 0
#define SFC_NAND_PROG_ERASE_ERROR -2
#define SFC_NAND_HW_ERROR -1
#define SFC_NAND_ECC_ERROR NAND_ERROR
#define SFC_NAND_ECC_REFRESH NAND_STS_REFRESH
#define SFC_NAND_ECC_OK NAND_STS_OK
#define SFC_NAND_PAGE_MAX_SIZE 2112
#define FEA_READ_STATUE_MASK (0x3 << 0)
#define FEA_STATUE_MODE1 0
#define FEA_STATUE_MODE2 1
#define FEA_4BIT_READ BIT(2)
#define FEA_4BIT_PROG BIT(3)
#define FEA_4BYTE_ADDR BIT(4)
#define FEA_4BYTE_ADDR_MODE BIT(5)
#define MID_WINBOND 0xEF
#define MID_GIGADEV 0xC8
#define MID_MICRON 0x2C
@@ -58,7 +75,46 @@
#define CMD_ENABLE_RESER (0x66)
#define CMD_RESET_DEVICE (0x99)
u32 sfc_nand_init(void __iomem *sfc_addr);
struct SFNAND_DEV {
u32 capacity;
u32 block_size;
u16 page_size;
u8 manufacturer;
u8 mem_type;
u8 read_lines;
u8 prog_lines;
u8 page_read_cmd;
u8 page_prog_cmd;
};
struct nand_info {
u32 id;
u16 sec_per_page;
u16 page_per_blk;
u16 plane_per_die;
u16 blk_per_plane;
u8 page_read_cmd;
u8 page_prog_cmd;
u8 read_cache_cmd_1;
u8 prog_cache_cmd_1;
u8 read_cache_cmd_4;
u8 prog_cache_cmd_4;
u8 block_erase_cmd;
u8 feature;
u8 density; /* (1 << density) sectors*/
u8 max_ecc_bits;
u8 QE_address;
u8 QE_bits;
u8 spare_offs_1;
u8 spare_offs_2;
};
u32 sfc_nand_init(void);
void sfc_nand_deinit(void);
int sfc_nand_read_id(u8 *buf);

View File

@@ -6,15 +6,17 @@
#include <linux/mutex.h>
#include "rk_sftl.h"
#include "rkflash_api.h"
#include "sfc.h"
#include "sfc_nand.h"
#include "sfc_nand_boot.h"
#include "typedef.h"
int snand_init(void __iomem *reg_addr)
{
int ret;
ret = sfc_nand_init(reg_addr);
sfc_init(reg_addr);
ret = sfc_nand_init();
if (ret == 0)
ret = sftl_init();
@@ -45,5 +47,6 @@ void snand_deinit(void)
int snand_resume(void __iomem *reg_addr)
{
return sfc_nand_init(reg_addr);
sfc_init(reg_addr);
return sfc_nand_init();
}

View File

@@ -1,16 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018 Rockchip Electronics Co. Ltd. */
#ifndef _SFC_NOR_BOOT_H
#define _SFC_NOR_BOOT_H
int snand_init(void __iomem *reg_addr);
int snand_read(unsigned int sec, unsigned int n_sec, void *p_data);
int snand_write(unsigned int sec, unsigned int n_sec, void *p_data);
unsigned int snand_get_capacity(void);
void snand_deinit(void);
int snand_resume(void __iomem *reg_addr);
void sfc_clean_irq(void);
#endif

View File

@@ -54,7 +54,6 @@ static const u32 sfnor_capacity[] = {
0x2000000 /* 32M-byte */
};
struct SFNOR_DEV sfnor_dev;
struct flash_info *g_spi_flash_info;
static int snor_write_en(void)
@@ -442,6 +441,7 @@ int snor_write(struct SFNOR_DEV *p_dev, u32 sec, u32 n_sec, void *p_data)
int ret = SFC_OK;
u32 len, blk_size, offset;
u8 *p_buf = (u8 *)p_data;
u32 total_sec = n_sec;
if ((sec + n_sec) > p_dev->capacity)
return SFC_PARAM_ERR;
@@ -477,7 +477,7 @@ int snor_write(struct SFNOR_DEV *p_dev, u32 sec, u32 n_sec, void *p_data)
out:
mutex_unlock(&p_dev->lock);
if (!ret)
ret = n_sec;
ret = total_sec;
return ret;
}

View File

@@ -7,7 +7,7 @@
#include "sfc.h"
#include "sfc_nor.h"
#include "sfc_nor_boot.h"
#include "rkflash_api.h"
#include "typedef.h"
#define VENDOR_PART_NUM 4
@@ -19,6 +19,8 @@
(FLASH_VENDOR_PART_START +\
FLASH_VENDOR_PART_SIZE * VENDOR_PART_NUM - 1)
struct SFNOR_DEV sfnor_dev;
/* SFNOR_DEV sfnor_dev is in the sfc_nor.h */
int spi_flash_init(void __iomem *reg_addr)
{

View File

@@ -1,19 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018 Rockchip Electronics Co. Ltd. */
#ifndef _SFC_NOR_BOOT_H
#define _SFC_NOR_BOOT_H
int spi_flash_init(void __iomem *reg_addr);
void spi_flash_read_id(u8 chip_sel, void *buf);
int snor_read_lba(unsigned int sec, unsigned int n_sec, void *p_data);
int snor_write_lba(unsigned int sec, unsigned int n_sec, void *p_data);
unsigned int snor_capacity(void);
void snor_deinit(void);
int snor_resume(void __iomem *reg_addr);
int snor_vendor_read(unsigned int sec, unsigned int n_sec, void *p_data);
int snor_vendor_write(unsigned int sec, unsigned int n_sec, void *p_data);
#endif

View File

@@ -35,7 +35,7 @@ void *ftl_memset(void *s, int c, unsigned int n);
void *ftl_memcpy(void *pv_to,
const void *pv_from,
unsigned int size);
void ftl_free(void *p, int size);
void ftl_free(void *p);
void rknand_print_hex(char *s, void *buf, int width, int len);
#endif /*__TYPEDEF_H */