Merge branch 'next-dev' into thunder-boot

This commit is contained in:
Joseph Chen 2020-04-13 19:38:06 +08:00
commit a9017bd54b
8 changed files with 354 additions and 278 deletions

View File

@ -11,6 +11,9 @@
#include "sfc.h" #include "sfc.h"
#define SFC_MAX_IOSIZE_VER3 (1024 * 8)
#define SFC_MAX_IOSIZE_VER4 (0xFFFFFFFF)
static void __iomem *g_sfc_reg; static void __iomem *g_sfc_reg;
static void sfc_reset(void) static void sfc_reset(void)
@ -30,11 +33,21 @@ u16 sfc_get_version(void)
return (u32)(readl(g_sfc_reg + SFC_VER) & 0xffff); return (u32)(readl(g_sfc_reg + SFC_VER) & 0xffff);
} }
u32 sfc_get_max_iosize(void)
{
if (sfc_get_version() >= SFC_VER_4)
return SFC_MAX_IOSIZE_VER4;
else
return SFC_MAX_IOSIZE_VER3;
}
int sfc_init(void __iomem *reg_addr) int sfc_init(void __iomem *reg_addr)
{ {
g_sfc_reg = reg_addr; g_sfc_reg = reg_addr;
sfc_reset(); sfc_reset();
writel(0, g_sfc_reg + SFC_CTRL); writel(0, g_sfc_reg + SFC_CTRL);
if (sfc_get_version() >= SFC_VER_4)
writel(1, g_sfc_reg + SFC_LEN_CTRL);
return SFC_OK; return SFC_OK;
} }
@ -45,7 +58,7 @@ void sfc_clean_irq(void)
writel(0xFFFFFFFF, g_sfc_reg + SFC_IMR); writel(0xFFFFFFFF, g_sfc_reg + SFC_IMR);
} }
int sfc_request(u32 sfcmd, u32 sfctrl, u32 addr, void *data) int sfc_request(struct rk_sfc_op *op, u32 addr, void *data, u32 size)
{ {
int ret = SFC_OK; int ret = SFC_OK;
union SFCCMD_DATA cmd; union SFCCMD_DATA cmd;
@ -57,26 +70,31 @@ int sfc_request(u32 sfcmd, u32 sfctrl, u32 addr, void *data)
(readl(g_sfc_reg + SFC_SR) & SFC_BUSY)) (readl(g_sfc_reg + SFC_SR) & SFC_BUSY))
sfc_reset(); sfc_reset();
cmd.d32 = sfcmd; cmd.d32 = op->sfcmd.d32;
if (cmd.b.addrbits == SFC_ADDR_XBITS) { if (cmd.b.addrbits == SFC_ADDR_XBITS) {
union SFCCTRL_DATA ctrl; union SFCCTRL_DATA ctrl;
ctrl.d32 = sfctrl; ctrl.d32 = op->sfctrl.d32;
if (!ctrl.b.addrbits) if (!ctrl.b.addrbits)
return SFC_PARAM_ERR; return SFC_PARAM_ERR;
/* Controller plus 1 automatically */ /* Controller plus 1 automatically */
writel(ctrl.b.addrbits - 1, g_sfc_reg + SFC_ABIT); writel(ctrl.b.addrbits - 1, g_sfc_reg + SFC_ABIT);
} }
/* shift in the data at negedge sclk_out */ /* shift in the data at negedge sclk_out */
sfctrl |= 0x2; op->sfctrl.d32 |= 0x2;
cmd.b.datasize = size;
if (sfc_get_version() >= SFC_VER_4)
writel(size, g_sfc_reg + SFC_LEN_EXT);
else
cmd.b.datasize = size;
writel(sfctrl, g_sfc_reg + SFC_CTRL); writel(op->sfctrl.d32, g_sfc_reg + SFC_CTRL);
writel(sfcmd, g_sfc_reg + SFC_CMD); writel(cmd.d32, g_sfc_reg + SFC_CMD);
if (cmd.b.addrbits) if (cmd.b.addrbits)
writel(addr, g_sfc_reg + SFC_ADDR); writel(addr, g_sfc_reg + SFC_ADDR);
if (!cmd.b.datasize) if (!size)
goto exit_wait; goto exit_wait;
if (SFC_ENABLE_DMA & sfctrl) { if (op->sfctrl.b.enbledma) {
struct bounce_buffer bb; struct bounce_buffer bb;
unsigned int bb_flags; unsigned int bb_flags;
@ -85,16 +103,16 @@ int sfc_request(u32 sfcmd, u32 sfctrl, u32 addr, void *data)
else else
bb_flags = GEN_BB_WRITE; bb_flags = GEN_BB_WRITE;
ret = bounce_buffer_start(&bb, data, cmd.b.datasize, bb_flags); ret = bounce_buffer_start(&bb, data, size, bb_flags);
if (ret) if (ret)
return ret; return ret;
writel(0xFFFFFFFF, g_sfc_reg + SFC_ICLR); writel(0xFFFFFFFF, g_sfc_reg + SFC_ICLR);
writel(~((u32)FINISH_INT), g_sfc_reg + SFC_IMR); writel(~((u32)DMA_INT), g_sfc_reg + SFC_IMR);
writel((unsigned long)bb.bounce_buffer, g_sfc_reg + SFC_DMA_ADDR); writel((unsigned long)bb.bounce_buffer, g_sfc_reg + SFC_DMA_ADDR);
writel(SFC_DMA_START, g_sfc_reg + SFC_DMA_TRIGGER); writel(SFC_DMA_START, g_sfc_reg + SFC_DMA_TRIGGER);
timeout = cmd.b.datasize * 10; timeout = size * 10;
while ((readl(g_sfc_reg + SFC_SR) & SFC_BUSY) && while ((readl(g_sfc_reg + SFC_SR) & SFC_BUSY) &&
(timeout-- > 0)) (timeout-- > 0))
sfc_delay(1); sfc_delay(1);
@ -108,7 +126,7 @@ int sfc_request(u32 sfcmd, u32 sfctrl, u32 addr, void *data)
u32 *p_data = (u32 *)data; u32 *p_data = (u32 *)data;
if (cmd.b.rw == SFC_WRITE) { if (cmd.b.rw == SFC_WRITE) {
words = (cmd.b.datasize + 3) >> 2; words = (size + 3) >> 2;
while (words) { while (words) {
fifostat.d32 = readl(g_sfc_reg + SFC_FSR); fifostat.d32 = readl(g_sfc_reg + SFC_FSR);
if (fifostat.b.txlevel > 0) { if (fifostat.b.txlevel > 0) {
@ -132,8 +150,8 @@ int sfc_request(u32 sfcmd, u32 sfctrl, u32 addr, void *data)
} }
} else { } else {
/* SFC_READ == cmd.b.rw */ /* SFC_READ == cmd.b.rw */
bytes = cmd.b.datasize & 0x3; bytes = size & 0x3;
words = cmd.b.datasize >> 2; words = size >> 2;
while (words) { while (words) {
fifostat.d32 = readl(g_sfc_reg + SFC_FSR); fifostat.d32 = readl(g_sfc_reg + SFC_FSR);
if (fifostat.b.rxlevel > 0) { if (fifostat.b.rxlevel > 0) {
@ -183,7 +201,7 @@ int sfc_request(u32 sfcmd, u32 sfctrl, u32 addr, void *data)
exit_wait: exit_wait:
timeout = 0; /* wait cmd or data send complete */ timeout = 0; /* wait cmd or data send complete */
while (!(readl(g_sfc_reg + SFC_FSR) & SFC_TXEMPTY)) { while (readl(g_sfc_reg + SFC_SR) & SFC_BUSY) {
sfc_delay(1); sfc_delay(1);
if (timeout++ > 100000) { /* wait 100ms */ if (timeout++ > 100000) { /* wait 100ms */
ret = SFC_TX_TIMEOUT; ret = SFC_TX_TIMEOUT;

View File

@ -7,9 +7,9 @@
#ifndef _SFC_H #ifndef _SFC_H
#define _SFC_H #define _SFC_H
#define SFC_VER_3 0x3 /* ver 3, else ver 1 */ #define SFC_VER_3 0x3
#define SFC_VER_4 0x4
#define SFC_MAX_IOSIZE (1024 * 8) /* 8K byte */
#define SFC_EN_INT (0) /* enable interrupt */ #define SFC_EN_INT (0) /* enable interrupt */
#define SFC_EN_DMA (1) /* enable dma */ #define SFC_EN_DMA (1) /* enable dma */
#define SFC_FIFO_DEPTH (0x10) /* 16 words */ #define SFC_FIFO_DEPTH (0x10) /* 16 words */
@ -90,6 +90,8 @@
#define SFC_QOP 0x30 #define SFC_QOP 0x30
#define SFC_DMA_TRIGGER 0x80 #define SFC_DMA_TRIGGER 0x80
#define SFC_DMA_ADDR 0x84 #define SFC_DMA_ADDR 0x84
#define SFC_LEN_CTRL 0x88
#define SFC_LEN_EXT 0x8C
#define SFC_CMD 0x100 #define SFC_CMD 0x100
#define SFC_ADDR 0x104 #define SFC_ADDR 0x104
#define SFC_DATA 0x108 #define SFC_DATA 0x108
@ -182,10 +184,16 @@ union SFCCMD_DATA {
} b; } b;
}; };
struct rk_sfc_op {
union SFCCMD_DATA sfcmd;
union SFCCTRL_DATA sfctrl;
};
int sfc_init(void __iomem *reg_addr); int sfc_init(void __iomem *reg_addr);
int sfc_request(u32 sfcmd, u32 sfctrl, u32 addr, void *data); int sfc_request(struct rk_sfc_op *op, u32 addr, void *data, u32 size);
u16 sfc_get_version(void); u16 sfc_get_version(void);
void sfc_clean_irq(void); void sfc_clean_irq(void);
u32 sfc_get_max_iosize(void);
int rksfc_get_reg_addr(unsigned long *p_sfc_addr); int rksfc_get_reg_addr(unsigned long *p_sfc_addr);
#endif #endif

View File

@ -16,76 +16,86 @@
static struct nand_info spi_nand_tbl[] = { static struct nand_info spi_nand_tbl[] = {
/* TC58CVG0S0HxAIx */ /* TC58CVG0S0HxAIx */
{0x98C2, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x02, 0xD8, 0x00, 18, 8, 0xFF, 0xFF, 4, 8, NULL}, {0x98C2, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x02, 0xD8, 0x00, 18, 8, 0xFF, 0xFF, {4, 8, 0xff, 0xff}, NULL},
/* TC58CVG1S0HxAIx */ /* TC58CVG1S0HxAIx */
{0x98CB, 4, 64, 2, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x02, 0xD8, 0x00, 19, 8, 0xFF, 0xFF, 4, 8, NULL}, {0x98CB, 4, 64, 2, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x02, 0xD8, 0x00, 19, 8, 0xFF, 0xFF, {4, 8, 0xff, 0xff}, NULL},
/* MX35LF1GE4AB */ /* MX35LF1GE4AB */
{0xC212, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 18, 4, 0xB0, 0, 4, 8, &sfc_nand_ecc_status_sp1}, {0xC212, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 18, 4, 0xB0, 0, {4, 8, 0xff, 0xff}, &sfc_nand_ecc_status_sp1},
/* MX35LF2GE4AB */ /* MX35LF2GE4AB */
{0xC222, 4, 64, 2, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 19, 4, 0xB0, 0, 4, 8, &sfc_nand_ecc_status_sp1}, {0xC222, 4, 64, 2, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 19, 4, 0xB0, 0, {4, 8, 0xff, 0xff}, &sfc_nand_ecc_status_sp1},
/* GD5F1GQ4UAYIG */ /* GD5F1GQ4UAYIG */
{0xC8F1, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 18, 8, 0xB0, 0, 4, 8, NULL}, {0xC8F1, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 18, 8, 0xB0, 0, {4, 8, 0xff, 0xff}, NULL},
/* MT29F1G01ZAC */ /* MT29F1G01ZAC */
{0x2C12, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x00, 18, 1, 0xB0, 0, 4, 8, &sfc_nand_ecc_status_sp1}, {0x2C12, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x00, 18, 1, 0xB0, 0, {4, 8, 0xff, 0xff}, &sfc_nand_ecc_status_sp1},
/* GD5F2GQ40BY2GR */ /* GD5F2GQ40BY2GR */
{0xC8D2, 4, 64, 2, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 19, 8, 0xB0, 0, 4, 8, &sfc_nand_ecc_status_sp3}, {0xC8D2, 4, 64, 2, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 19, 8, 0xB0, 0, {4, 8, 0xff, 0xff}, &sfc_nand_ecc_status_sp3},
/* GD5F1GQ4U */ /* GD5F1GQ4RB9IGR */
{0xC8D1, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 18, 8, 0xB0, 0, 4, 8, &sfc_nand_ecc_status_sp3}, {0xC8D1, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 18, 8, 0xB0, 0, {4, 8, 0xff, 0xff}, &sfc_nand_ecc_status_sp3},
/* IS37SML01G1 */ /* IS37SML01G1 */
{0xC821, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x00, 18, 1, 0xFF, 0xFF, 8, 12, &sfc_nand_ecc_status_sp1}, {0xC821, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x00, 18, 1, 0xFF, 0xFF, {8, 12, 0xff, 0xff}, &sfc_nand_ecc_status_sp1},
/* W25N01GV */ /* W25N01GV */
{0xEFAA, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 18, 1, 0xFF, 0xFF, 4, 20, &sfc_nand_ecc_status_sp1}, {0xEFAA, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 18, 1, 0xFF, 0xFF, {4, 20, 36, 0xff}, &sfc_nand_ecc_status_sp1},
/* HYF2GQ4UAACAE */ /* HYF2GQ4UAACAE */
{0xC952, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 19, 14, 0xB0, 0, 4, 36, NULL}, {0xC952, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 19, 14, 0xB0, 0, {4, 36, 0xff, 0xff}, NULL},
/* HYF2GQ4UDACAE */ /* HYF2GQ4UDACAE */
{0xC922, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 19, 4, 0xB0, 0, 4, 20, NULL}, {0xC922, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 19, 4, 0xB0, 0, {4, 20, 0xff, 0xff}, NULL},
/* HYF2GQ4UHCCAE */ /* HYF2GQ4UHCCAE */
{0xC95A, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 19, 14, 0xB0, 0, 4, 36, NULL}, {0xC95A, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 19, 14, 0xB0, 0, {4, 36, 0xff, 0xff}, NULL},
/* HYF1GQ4UDACAE */ /* HYF1GQ4UDACAE */
{0xC921, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 18, 4, 0xB0, 0, 4, 20, NULL}, {0xC921, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 18, 4, 0xB0, 0, {4, 20, 0xff, 0xff}, NULL},
/* F50L1G41LB */ /* F50L1G41LB */
{0xC801, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 18, 1, 0xFF, 0xFF, 20, 36, &sfc_nand_ecc_status_sp1}, {0xC801, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 18, 1, 0xFF, 0xFF, {20, 36, 0xff, 0xff}, &sfc_nand_ecc_status_sp1},
/* XT26G02A */ /* XT26G02A */
{0x0BE2, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 19, 1, 0xB0, 0x0, 8, 12, &sfc_nand_ecc_status_sp4}, {0x0BE2, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 19, 1, 0xB0, 0x0, {8, 12, 0xff, 0xff}, &sfc_nand_ecc_status_sp4},
/* XT26G01A */ /* XT26G01A */
{0x0BE1, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 18, 1, 0xB0, 0x0, 8, 12, &sfc_nand_ecc_status_sp4}, {0x0BE1, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 18, 1, 0xB0, 0x0, {8, 12, 0xff, 0xff}, &sfc_nand_ecc_status_sp4},
/* FS35ND01G-S1 */ /* FS35ND01G-S1 */
{0xCDB1, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 18, 4, 0xB0, 0x0, 16, 20, &sfc_nand_ecc_status_sp5}, {0xCDB1, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 18, 4, 0xB0, 0x0, {16, 20, 0xff, 0xff}, &sfc_nand_ecc_status_sp5},
/* FS35ND02G-S2 */ /* FS35ND02G-S2 */
{0xCDA2, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x03, 0x02, 0xD8, 0x00, 19, 4, 0xFF, 0xFF, 16, 20, &sfc_nand_ecc_status_sp5}, {0xCDA2, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x03, 0x02, 0xD8, 0x00, 19, 4, 0xFF, 0xFF, {16, 20, 0xff, 0xff}, &sfc_nand_ecc_status_sp5},
/* DS35Q1GA-1B */ /* DS35Q1GA-1B */
{0xE571, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 18, 4, 0xB0, 0x0, 4, 20, &sfc_nand_ecc_status_sp1}, {0xE571, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 18, 4, 0xB0, 0x0, {4, 20, 0xff, 0xff}, &sfc_nand_ecc_status_sp1},
/* DS35Q2GA-1B */ /* DS35Q2GA-1B */
{0xE572, 4, 64, 2, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 19, 4, 0xB0, 0x0, 4, 20, &sfc_nand_ecc_status_sp1}, {0xE572, 4, 64, 2, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 19, 4, 0xB0, 0x0, {4, 20, 0xff, 0xff}, &sfc_nand_ecc_status_sp1},
/* EM73C044SNC-G */ /* EM73C044SNC-G */
{0xD522, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 18, 8, 0xB0, 0x0, 4, 20, NULL}, {0xD522, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 18, 8, 0xB0, 0x0, {4, 20, 0xff, 0xff}, NULL},
/* EM73D044SNB-G */ /* EM73D044SNB-G */
{0xD520, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 19, 8, 0xB0, 0x0, 4, 20, NULL}, {0xD520, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 19, 8, 0xB0, 0x0, {4, 20, 0xff, 0xff}, NULL},
/* ATO25D1GA */ /* ATO25D1GA */
{0x9B12, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x40, 18, 1, 0xB0, 0x0, 20, 36, &sfc_nand_ecc_status_sp1}, {0x9B12, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x40, 18, 1, 0xB0, 0x0, {20, 36, 0xff, 0xff}, &sfc_nand_ecc_status_sp1},
/* XT26G02B */ /* XT26G02B */
{0x0BF2, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 19, 1, 0xB0, 0x0, 8, 12, &sfc_nand_ecc_status_sp4}, {0x0BF2, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 19, 1, 0xB0, 0x0, {8, 12, 0xff, 0xff}, &sfc_nand_ecc_status_sp5},
/* XT26G01B */ /* XT26G01B */
{0x0BF1, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 18, 1, 0xB0, 0x0, 8, 12, &sfc_nand_ecc_status_sp4}, {0x0BF1, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 18, 1, 0xB0, 0x0, {8, 12, 0xff, 0xff}, &sfc_nand_ecc_status_sp4},
/* HYF4GQ4UAACBE */ /* HYF4GQ4UAACBE */
{0xC9D4, 8, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 20, 4, 0xB0, 0, 32, 64, NULL}, {0xC9D4, 8, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 20, 4, 0xB0, 0, {32, 64, 36, 68}, NULL},
/* FM25S01 */ /* FM25S01 */
{0xA1A1, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 18, 1, 0xB0, 0, 0, 4, &sfc_nand_ecc_status_sp1}, {0xA1A1, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 18, 1, 0xB0, 0, {0, 4, 0xff, 0xff}, &sfc_nand_ecc_status_sp1},
/* HYF1GQ4UPACAE */ /* HYF1GQ4UPACAE */
{0xC9A1, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 18, 4, 0xB0, 0, 4, 20, &sfc_nand_ecc_status_sp1}, {0xC9A1, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 18, 4, 0xB0, 0, {4, 20, 0xff, 0xff}, &sfc_nand_ecc_status_sp1},
/* EM73E044SNA-G */ /* EM73E044SNA-G */
{0xD503, 8, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 20, 8, 0xB0, 0, 4, 40, NULL}, {0xD503, 8, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 20, 8, 0xB0, 0, {4, 40, 8, 44}, NULL},
/* GD5F2GQ5UEYIG */ /* GD5F2GQ5UEYIG */
{0xC852, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 19, 4, 0xB0, 0, 4, 20, &sfc_nand_ecc_status_sp2}, {0xC852, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 19, 4, 0xB0, 0, {4, 20, 0xff, 0xff}, &sfc_nand_ecc_status_sp2},
/* GD5F1GQ4R */ /* GD5F1GQ4R */
{0xC8C1, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 18, 8, 0xB0, 0, 4, 8, &sfc_nand_ecc_status_sp3}, {0xC8C1, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 18, 8, 0xB0, 0, {4, 8, 0xff, 0xff}, &sfc_nand_ecc_status_sp3},
/* TC58CVG2S0HRAIJ */
{0x98ED, 8, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 20, 8, 0xFF, 0xFF, {4, 12, 8, 16}, NULL},
/* TC58CVG1S3HRAIJ */
{0x98EB, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 19, 8, 0xFF, 0xFF, {4, 8, 0xff, 0xff}, NULL},
/* TC58CVG0S3HRAIJ */
{0x98E2, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 18, 8, 0xFF, 0xFF, {4, 8, 0xff, 0xff}, NULL},
/* XT26G04A */
{0x0BE3, 4, 128, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 20, 1, 0xB0, 0x0, {8, 12, 0xff, 0xff}, &sfc_nand_ecc_status_sp4},
/* FS35ND01G-S1Y2 */
{0xCDEA, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 18, 4, 0xFF, 0xFF, {4, 8, 12, 16}, &sfc_nand_ecc_status_sp1},
}; };
static struct nand_info *p_nand_info; static struct nand_info *p_nand_info;
static u32 gp_page_buf[SFC_NAND_PAGE_MAX_SIZE / 4]; static u32 gp_page_buf[SFC_NAND_PAGE_MAX_SIZE / 4];
static struct SFNAND_DEV sfc_nand_dev; static struct SFNAND_DEV sfc_nand_dev;
static struct nand_info *spi_nand_get_info(u8 *nand_id) static struct nand_info *sfc_nand_get_info(u8 *nand_id)
{ {
u32 i; u32 i;
u32 id = (nand_id[0] << 8) | (nand_id[1] << 0); u32 id = (nand_id[0] << 8) | (nand_id[1] << 0);
@ -100,43 +110,49 @@ static struct nand_info *spi_nand_get_info(u8 *nand_id)
static int sfc_nand_write_en(void) static int sfc_nand_write_en(void)
{ {
int ret; int ret;
union SFCCMD_DATA sfcmd; struct rk_sfc_op op;
sfcmd.d32 = 0; op.sfcmd.d32 = 0;
sfcmd.b.cmd = CMD_WRITE_EN; op.sfcmd.b.cmd = CMD_WRITE_EN;
ret = sfc_request(sfcmd.d32, 0, 0, NULL);
op.sfctrl.d32 = 0;
ret = sfc_request(&op, 0, NULL, 0);
return ret; return ret;
} }
static int sfc_nand_rw_preset(void) static int sfc_nand_rw_preset(void)
{ {
int ret; int ret;
union SFCCTRL_DATA sfctrl; struct rk_sfc_op op;
union SFCCMD_DATA sfcmd;
u8 status = 0xFF; u8 status = 0xFF;
sfcmd.d32 = 0; op.sfcmd.d32 = 0;
sfcmd.b.cmd = 0; op.sfcmd.b.cmd = 0;
sfcmd.b.datasize = 1; op.sfcmd.b.rw = SFC_WRITE;
sfcmd.b.rw = SFC_WRITE;
sfctrl.b.datalines = 2; op.sfctrl.d32 = 0;
ret = sfc_request(sfcmd.d32, sfctrl.d32, 0, &status); op.sfctrl.b.datalines = 2;
ret = sfc_request(&op, 0, &status, 1);
return ret; return ret;
} }
static int sfc_nand_read_feature(u8 addr, u8 *data) static int sfc_nand_read_feature(u8 addr, u8 *data)
{ {
int ret; int ret;
union SFCCMD_DATA sfcmd; struct rk_sfc_op op;
op.sfcmd.d32 = 0;
op.sfcmd.b.cmd = 0x0F;
op.sfcmd.b.addrbits = SFC_ADDR_XBITS;
op.sfctrl.d32 = 0;
op.sfctrl.b.addrbits = 8;
sfcmd.d32 = 0;
sfcmd.b.cmd = 0x0F;
sfcmd.b.datasize = 1;
sfcmd.b.addrbits = SFC_ADDR_XBITS;
*data = 0; *data = 0;
ret = sfc_request(sfcmd.d32, 0x8 << 16, addr, data); ret = sfc_request(&op, addr, data, 1);
if (ret != SFC_OK) if (ret != SFC_OK)
return ret; return ret;
return SFC_OK; return SFC_OK;
@ -145,17 +161,19 @@ static int sfc_nand_read_feature(u8 addr, u8 *data)
static int sfc_nand_write_feature(u32 addr, u8 status) static int sfc_nand_write_feature(u32 addr, u8 status)
{ {
int ret; int ret;
union SFCCMD_DATA sfcmd; struct rk_sfc_op op;
sfc_nand_write_en(); sfc_nand_write_en();
sfcmd.d32 = 0; op.sfcmd.d32 = 0;
sfcmd.b.cmd = 0x1F; op.sfcmd.b.cmd = 0x1F;
sfcmd.b.datasize = 1; op.sfcmd.b.addrbits = SFC_ADDR_XBITS;
sfcmd.b.addrbits = SFC_ADDR_XBITS; op.sfcmd.b.rw = SFC_WRITE;
sfcmd.b.rw = SFC_WRITE;
ret = sfc_request(sfcmd.d32, 0x8 << 16, addr, &status); op.sfctrl.d32 = 0;
op.sfctrl.b.addrbits = 8;
ret = sfc_request(&op, addr, &status, 1);
if (ret != SFC_OK) if (ret != SFC_OK)
return ret; return ret;
return ret; return ret;
@ -182,6 +200,7 @@ static int sfc_nand_wait_busy(u8 *data, int timeout)
/* /*
* ecc default: * ecc default:
* ecc bits: 0xC0[4,5]
* 0x00, No bit errors were detected * 0x00, No bit errors were detected
* 0x01, Bit errors were detected and corrected. * 0x01, Bit errors were detected and corrected.
* 0x10, Multiple bit errors were detected and not corrected. * 0x10, Multiple bit errors were detected and not corrected.
@ -190,7 +209,7 @@ static int sfc_nand_wait_busy(u8 *data, int timeout)
*/ */
static u32 sfc_nand_ecc_status(void) static u32 sfc_nand_ecc_status(void)
{ {
int ret; u32 ret;
u32 i; u32 i;
u8 ecc; u8 ecc;
u8 status; u8 status;
@ -210,7 +229,7 @@ static u32 sfc_nand_ecc_status(void)
if (ecc <= 1) if (ecc <= 1)
ret = SFC_NAND_ECC_OK; ret = SFC_NAND_ECC_OK;
else if (ecc == 2) else if (ecc == 2)
ret = SFC_NAND_ECC_ERROR; ret = (u32)SFC_NAND_ECC_ERROR;
else else
ret = SFC_NAND_ECC_REFRESH; ret = SFC_NAND_ECC_REFRESH;
@ -219,6 +238,7 @@ static u32 sfc_nand_ecc_status(void)
/* /*
* ecc spectial type1: * ecc spectial type1:
* ecc bits: 0xC0[4,5]
* 0x00, No bit errors were detected; * 0x00, No bit errors were detected;
* 0x01, Bits errors were detected and corrected, bit error count * 0x01, Bits errors were detected and corrected, bit error count
* may reach the bit flip detection threshold; * may reach the bit flip detection threshold;
@ -227,7 +247,7 @@ static u32 sfc_nand_ecc_status(void)
*/ */
u32 sfc_nand_ecc_status_sp1(void) u32 sfc_nand_ecc_status_sp1(void)
{ {
int ret; u32 ret;
u32 i; u32 i;
u8 ecc; u8 ecc;
u8 status; u8 status;
@ -249,13 +269,14 @@ u32 sfc_nand_ecc_status_sp1(void)
else if (ecc == 1) else if (ecc == 1)
ret = SFC_NAND_ECC_REFRESH; ret = SFC_NAND_ECC_REFRESH;
else else
ret = SFC_NAND_ECC_ERROR; ret = (u32)SFC_NAND_ECC_ERROR;
return ret; return ret;
} }
/* /*
* ecc spectial type2: * ecc spectial type2:
* ecc bits: 0xC0[4,5] 0xF0[4,5]
* [0x0000, 0x0011], No bit errors were detected; * [0x0000, 0x0011], No bit errors were detected;
* [0x0100, 0x0111], Bit errors were detected and corrected. Not * [0x0100, 0x0111], Bit errors were detected and corrected. Not
* reach Flipping Bits; * reach Flipping Bits;
@ -265,7 +286,7 @@ u32 sfc_nand_ecc_status_sp1(void)
*/ */
u32 sfc_nand_ecc_status_sp2(void) u32 sfc_nand_ecc_status_sp2(void)
{ {
int ret; u32 ret;
u32 i; u32 i;
u8 ecc; u8 ecc;
u8 status, status1; u8 status, status1;
@ -290,24 +311,25 @@ u32 sfc_nand_ecc_status_sp2(void)
else if (ecc == 7) else if (ecc == 7)
ret = SFC_NAND_ECC_REFRESH; ret = SFC_NAND_ECC_REFRESH;
else else
ret = SFC_NAND_ECC_ERROR; ret = (u32)SFC_NAND_ECC_ERROR;
return ret; return ret;
} }
/* /*
* ecc spectial type3: * ecc spectial type3:
* ecc bits: 0xC0[4,5] 0xF0[4,5]
* [0x0000, 0x0011], No bit errors were detected; * [0x0000, 0x0011], No bit errors were detected;
* [0x0100, 0x0111], Bit errors were detected and corrected. Not * [0x0100, 0x0111], Bit errors were detected and corrected. Not
* reach Flipping Bits; * reach Flipping Bits;
* [0x1000, 0x1011], Multiple bit errors were detected and * [0x1000, 0x1011], Multiple bit errors were detected and
* not corrected. * not corrected.
* [0x1100, 0x1111], Bit error count equals the bit flip * [0x1100, 0x1111], Bit error count equals the bit flip
* detectionthreshold * detectio nthreshold
*/ */
u32 sfc_nand_ecc_status_sp3(void) u32 sfc_nand_ecc_status_sp3(void)
{ {
int ret; u32 ret;
u32 i; u32 i;
u8 ecc; u8 ecc;
u8 status, status1; u8 status, status1;
@ -332,13 +354,14 @@ u32 sfc_nand_ecc_status_sp3(void)
else if (ecc == 7 || ecc >= 12) else if (ecc == 7 || ecc >= 12)
ret = SFC_NAND_ECC_REFRESH; ret = SFC_NAND_ECC_REFRESH;
else else
ret = SFC_NAND_ECC_ERROR; ret = (u32)SFC_NAND_ECC_ERROR;
return ret; return ret;
} }
/* /*
* ecc spectial type4: * ecc spectial type4:
* ecc bits: 0xC0[2,5]
* [0x0000], No bit errors were detected; * [0x0000], No bit errors were detected;
* [0x0001, 0x0111], Bit errors were detected and corrected. Not * [0x0001, 0x0111], Bit errors were detected and corrected. Not
* reach Flipping Bits; * reach Flipping Bits;
@ -350,7 +373,7 @@ u32 sfc_nand_ecc_status_sp3(void)
*/ */
u32 sfc_nand_ecc_status_sp4(void) u32 sfc_nand_ecc_status_sp4(void)
{ {
int ret; u32 ret;
u32 i; u32 i;
u8 ecc; u8 ecc;
u8 status; u8 status;
@ -371,13 +394,14 @@ u32 sfc_nand_ecc_status_sp4(void)
else if (ecc == 7 || ecc == 12) else if (ecc == 7 || ecc == 12)
ret = SFC_NAND_ECC_REFRESH; ret = SFC_NAND_ECC_REFRESH;
else else
ret = SFC_NAND_ECC_ERROR; ret = (u32)SFC_NAND_ECC_ERROR;
return ret; return ret;
} }
/* /*
* ecc spectial type5: * ecc spectial type5:
* ecc bits: 0xC0[4,6]
* [0x0], No bit errors were detected; * [0x0], No bit errors were detected;
* [0x001, 0x011], Bit errors were detected and corrected. Not * [0x001, 0x011], Bit errors were detected and corrected. Not
* reach Flipping Bits; * reach Flipping Bits;
@ -389,7 +413,7 @@ u32 sfc_nand_ecc_status_sp4(void)
*/ */
u32 sfc_nand_ecc_status_sp5(void) u32 sfc_nand_ecc_status_sp5(void)
{ {
int ret; u32 ret;
u32 i; u32 i;
u8 ecc; u8 ecc;
u8 status; u8 status;
@ -410,7 +434,7 @@ u32 sfc_nand_ecc_status_sp5(void)
else if (ecc == 4) else if (ecc == 4)
ret = SFC_NAND_ECC_REFRESH; ret = SFC_NAND_ECC_REFRESH;
else else
ret = SFC_NAND_ECC_ERROR; ret = (u32)SFC_NAND_ECC_ERROR;
return ret; return ret;
} }
@ -418,15 +442,19 @@ u32 sfc_nand_ecc_status_sp5(void)
u32 sfc_nand_erase_block(u8 cs, u32 addr) u32 sfc_nand_erase_block(u8 cs, u32 addr)
{ {
int ret; int ret;
union SFCCMD_DATA sfcmd; struct rk_sfc_op op;
u8 status; u8 status;
rkflash_print_dio("%s %x\n", __func__, addr); rkflash_print_dio("%s %x\n", __func__, addr);
sfcmd.d32 = 0; op.sfcmd.d32 = 0;
sfcmd.b.cmd = p_nand_info->block_erase_cmd; op.sfcmd.b.cmd = p_nand_info->block_erase_cmd;
sfcmd.b.addrbits = SFC_ADDR_24BITS; op.sfcmd.b.addrbits = SFC_ADDR_24BITS;
op.sfcmd.b.rw = SFC_WRITE;
op.sfctrl.d32 = 0;
sfc_nand_write_en(); sfc_nand_write_en();
ret = sfc_request(sfcmd.d32, 0, addr, NULL); ret = sfc_request(&op, addr, NULL, 0);
if (ret != SFC_OK) if (ret != SFC_OK)
return ret; return ret;
ret = sfc_nand_wait_busy(&status, 1000 * 1000); ret = sfc_nand_wait_busy(&status, 1000 * 1000);
@ -440,10 +468,9 @@ static u32 sfc_nand_prog_page_raw(u8 cs, u32 addr, u32 *p_page_buf)
{ {
int ret; int ret;
u32 plane; u32 plane;
union SFCCMD_DATA sfcmd; struct rk_sfc_op op;
union SFCCTRL_DATA sfctrl;
u8 status; u8 status;
u32 sec_per_page = p_nand_info->sec_per_page; u32 page_size = SFC_NAND_SECTOR_FULL_SIZE * p_nand_info->sec_per_page;
rkflash_print_dio("%s %x %x\n", __func__, addr, p_page_buf[0]); rkflash_print_dio("%s %x %x\n", __func__, addr, p_page_buf[0]);
sfc_nand_write_en(); sfc_nand_write_en();
@ -452,24 +479,24 @@ static u32 sfc_nand_prog_page_raw(u8 cs, u32 addr, u32 *p_page_buf)
sfc_get_version() < SFC_VER_3) sfc_get_version() < SFC_VER_3)
sfc_nand_rw_preset(); sfc_nand_rw_preset();
sfcmd.d32 = 0; op.sfcmd.d32 = 0;
sfcmd.b.cmd = sfc_nand_dev.page_prog_cmd; op.sfcmd.b.cmd = sfc_nand_dev.page_prog_cmd;
sfcmd.b.addrbits = SFC_ADDR_XBITS; op.sfcmd.b.addrbits = SFC_ADDR_XBITS;
sfcmd.b.datasize = SFC_NAND_SECTOR_FULL_SIZE * sec_per_page; op.sfcmd.b.rw = SFC_WRITE;
sfcmd.b.rw = SFC_WRITE;
sfctrl.d32 = 0; op.sfctrl.d32 = 0;
sfctrl.b.datalines = sfc_nand_dev.prog_lines; op.sfctrl.b.datalines = sfc_nand_dev.prog_lines;
sfctrl.b.addrbits = 16; op.sfctrl.b.addrbits = 16;
plane = p_nand_info->plane_per_die == 2 ? ((addr >> 6) & 0x1) << 12 : 0; plane = p_nand_info->plane_per_die == 2 ? ((addr >> 6) & 0x1) << 12 : 0;
sfc_request(sfcmd.d32, sfctrl.d32, plane, p_page_buf); sfc_request(&op, plane, p_page_buf, page_size);
sfcmd.d32 = 0; op.sfcmd.d32 = 0;
sfcmd.b.cmd = p_nand_info->page_prog_cmd; op.sfcmd.b.cmd = p_nand_info->page_prog_cmd;
sfcmd.b.addrbits = SFC_ADDR_24BITS; op.sfcmd.b.addrbits = SFC_ADDR_24BITS;
sfcmd.b.datasize = 0; op.sfcmd.b.rw = SFC_WRITE;
sfcmd.b.rw = SFC_WRITE;
ret = sfc_request(sfcmd.d32, 0, addr, p_page_buf); op.sfctrl.d32 = 0;
ret = sfc_request(&op, addr, p_page_buf, 0);
if (ret != SFC_OK) if (ret != SFC_OK)
return ret; return ret;
ret = sfc_nand_wait_busy(&status, 1000 * 1000); ret = sfc_nand_wait_busy(&status, 1000 * 1000);
@ -484,16 +511,15 @@ u32 sfc_nand_prog_page(u8 cs, u32 addr, u32 *p_data, u32 *p_spare)
int ret; int ret;
u32 sec_per_page = p_nand_info->sec_per_page; u32 sec_per_page = p_nand_info->sec_per_page;
u32 data_size = sec_per_page * SFC_NAND_SECTOR_SIZE; u32 data_size = sec_per_page * SFC_NAND_SECTOR_SIZE;
u32 spare_offs_1 = p_nand_info->spare_offs_1; struct nand_mega_area *meta = &p_nand_info->meta;
u32 spare_offs_2 = p_nand_info->spare_offs_2;
memcpy(gp_page_buf, p_data, data_size); memcpy(gp_page_buf, p_data, data_size);
memset(&gp_page_buf[data_size / 4], 0xff, sec_per_page * 16); memset(&gp_page_buf[data_size / 4], 0xff, sec_per_page * 16);
gp_page_buf[(data_size + spare_offs_1) / 4] = p_spare[0]; gp_page_buf[(data_size + meta->off0) / 4] = p_spare[0];
gp_page_buf[(data_size + spare_offs_2) / 4] = p_spare[1]; gp_page_buf[(data_size + meta->off1) / 4] = p_spare[1];
if (sec_per_page == 8) { if (sec_per_page == 8) {
gp_page_buf[(data_size + spare_offs_1) / 4 + 1] = p_spare[2]; gp_page_buf[(data_size + meta->off2) / 4] = p_spare[2];
gp_page_buf[(data_size + spare_offs_2) / 4 + 1] = p_spare[3]; gp_page_buf[(data_size + meta->off3) / 4] = p_spare[3];
} }
ret = sfc_nand_prog_page_raw(cs, addr, gp_page_buf); ret = sfc_nand_prog_page_raw(cs, addr, gp_page_buf);
@ -504,59 +530,61 @@ static u32 sfc_nand_read_page_raw(u8 cs, u32 addr, u32 *p_page_buf)
{ {
int ret; int ret;
u32 plane; u32 plane;
union SFCCMD_DATA sfcmd; struct rk_sfc_op op;
union SFCCTRL_DATA sfctrl;
u32 ecc_result; u32 ecc_result;
u32 sec_per_page = p_nand_info->sec_per_page; u32 page_size = SFC_NAND_SECTOR_FULL_SIZE * p_nand_info->sec_per_page;
u8 status;
sfcmd.d32 = 0; op.sfcmd.d32 = 0;
sfcmd.b.cmd = p_nand_info->page_read_cmd; op.sfcmd.b.cmd = p_nand_info->page_read_cmd;
sfcmd.b.datasize = 0; op.sfcmd.b.rw = SFC_WRITE;
sfcmd.b.addrbits = SFC_ADDR_24BITS; op.sfcmd.b.addrbits = SFC_ADDR_24BITS;
sfc_request(sfcmd.d32, 0, addr, p_page_buf);
if (p_nand_info->ecc_status) op.sfctrl.d32 = 0;
ecc_result = p_nand_info->ecc_status();
else
ecc_result = sfc_nand_ecc_status();
sfc_request(&op, addr, p_page_buf, 0);
if (sfc_nand_dev.read_lines == DATA_LINES_X4 && if (sfc_nand_dev.read_lines == DATA_LINES_X4 &&
p_nand_info->feature & FEA_SOFT_QOP_BIT && p_nand_info->feature & FEA_SOFT_QOP_BIT &&
sfc_get_version() < SFC_VER_3) sfc_get_version() < SFC_VER_3)
sfc_nand_rw_preset(); sfc_nand_rw_preset();
sfcmd.d32 = 0; sfc_nand_wait_busy(&status, 1000 * 1000);
sfcmd.b.cmd = sfc_nand_dev.page_read_cmd; if (p_nand_info->ecc_status)
sfcmd.b.datasize = SFC_NAND_SECTOR_FULL_SIZE * sec_per_page; ecc_result = p_nand_info->ecc_status();
sfcmd.b.addrbits = SFC_ADDR_24BITS; else
sfctrl.d32 = 0; ecc_result = sfc_nand_ecc_status();
sfctrl.b.datalines = sfc_nand_dev.read_lines;
op.sfcmd.d32 = 0;
op.sfcmd.b.cmd = sfc_nand_dev.page_read_cmd;
op.sfcmd.b.addrbits = SFC_ADDR_24BITS;
op.sfctrl.d32 = 0;
op.sfctrl.b.datalines = sfc_nand_dev.read_lines;
plane = p_nand_info->plane_per_die == 2 ? ((addr >> 6) & 0x1) << 12 : 0; plane = p_nand_info->plane_per_die == 2 ? ((addr >> 6) & 0x1) << 12 : 0;
ret = sfc_request(sfcmd.d32, sfctrl.d32, plane << 8, p_page_buf); ret = sfc_request(&op, plane << 8, p_page_buf, page_size);
rkflash_print_dio("%s %x %x\n", __func__, addr, p_page_buf[0]); rkflash_print_dio("%s %x %x\n", __func__, addr, p_page_buf[0]);
if (ret != SFC_OK) if (ret != SFC_OK)
return SFC_NAND_HW_ERROR; return SFC_NAND_ECC_ERROR;
return ecc_result; return ecc_result;
} }
u32 sfc_nand_read_page(u8 cs, u32 addr, u32 *p_data, u32 *p_spare) u32 sfc_nand_read_page(u8 cs, u32 addr, u32 *p_data, u32 *p_spare)
{ {
int ret; u32 ret;
u32 sec_per_page = p_nand_info->sec_per_page; u32 sec_per_page = p_nand_info->sec_per_page;
u32 data_size = sec_per_page * SFC_NAND_SECTOR_SIZE; u32 data_size = sec_per_page * SFC_NAND_SECTOR_SIZE;
u32 spare_offs_1 = p_nand_info->spare_offs_1; struct nand_mega_area *meta = &p_nand_info->meta;
u32 spare_offs_2 = p_nand_info->spare_offs_2;
ret = sfc_nand_read_page_raw(cs, addr, gp_page_buf); ret = sfc_nand_read_page_raw(cs, addr, gp_page_buf);
memcpy(p_data, gp_page_buf, data_size); memcpy(p_data, gp_page_buf, data_size);
p_spare[0] = gp_page_buf[(data_size + spare_offs_1) / 4]; p_spare[0] = gp_page_buf[(data_size + meta->off0) / 4];
p_spare[1] = gp_page_buf[(data_size + spare_offs_2) / 4]; p_spare[1] = gp_page_buf[(data_size + meta->off1) / 4];
if (p_nand_info->sec_per_page == 8) { if (p_nand_info->sec_per_page == 8) {
p_spare[2] = gp_page_buf[(data_size + spare_offs_1) / 4 + 1]; p_spare[2] = gp_page_buf[(data_size + meta->off2) / 4];
p_spare[3] = gp_page_buf[(data_size + spare_offs_2) / 4 + 1]; p_spare[3] = gp_page_buf[(data_size + meta->off3) / 4];
} }
if (ret != SFC_NAND_ECC_OK) { if (ret != SFC_NAND_ECC_OK) {
@ -576,7 +604,7 @@ u32 sfc_nand_check_bad_block(u8 cs, u32 addr)
u32 data_size = p_nand_info->sec_per_page * SFC_NAND_SECTOR_SIZE; u32 data_size = p_nand_info->sec_per_page * SFC_NAND_SECTOR_SIZE;
ret = sfc_nand_read_page_raw(cs, addr, gp_page_buf); ret = sfc_nand_read_page_raw(cs, addr, gp_page_buf);
if (ret) if (ret == SFC_NAND_ECC_ERROR)
return true; return true;
/* Original bad block */ /* Original bad block */
if ((gp_page_buf[data_size / 4] & 0xFF) != 0xFF) if ((gp_page_buf[data_size / 4] & 0xFF) != 0xFF)
@ -604,14 +632,16 @@ u32 sfc_nand_mark_bad_block(u8 cs, u32 addr)
int sfc_nand_read_id(u8 *data) int sfc_nand_read_id(u8 *data)
{ {
int ret; int ret;
union SFCCMD_DATA sfcmd; struct rk_sfc_op op;
sfcmd.d32 = 0; op.sfcmd.d32 = 0;
sfcmd.b.cmd = CMD_READ_JEDECID; op.sfcmd.b.cmd = CMD_READ_JEDECID;
sfcmd.b.datasize = 3; op.sfcmd.b.addrbits = SFC_ADDR_XBITS;
sfcmd.b.addrbits = SFC_ADDR_XBITS;
ret = sfc_request(sfcmd.d32, 0x8 << 16, 0, data); op.sfctrl.d32 = 0;
op.sfctrl.b.addrbits = 8;
ret = sfc_request(&op, 0, data, 3);
return ret; return ret;
} }
@ -683,7 +713,7 @@ void sfc_nand_ftl_ops_init(void)
g_nand_ops.bch_sel = NULL; g_nand_ops.bch_sel = NULL;
} }
static int spi_nand_enable_QE(void) static int sfc_nand_enable_QE(void)
{ {
int ret = SFC_OK; int ret = SFC_OK;
u8 status; u8 status;
@ -713,11 +743,11 @@ u32 sfc_nand_init(void)
rkflash_print_error("sfc_nand id: %x %x %x\n", rkflash_print_error("sfc_nand id: %x %x %x\n",
id_byte[0], id_byte[1], id_byte[2]); id_byte[0], id_byte[1], id_byte[2]);
if (id_byte[0] == 0xFF || id_byte[0] == 0x00) if (id_byte[0] == 0xFF || id_byte[0] == 0x00)
return FTL_NO_FLASH; return (u32)FTL_NO_FLASH;
p_nand_info = spi_nand_get_info(id_byte); p_nand_info = sfc_nand_get_info(id_byte);
if (!p_nand_info) if (!p_nand_info)
return FTL_UNSUPPORTED_FLASH; return (u32)FTL_UNSUPPORTED_FLASH;
sfc_nand_dev.manufacturer = id_byte[0]; sfc_nand_dev.manufacturer = id_byte[0];
sfc_nand_dev.mem_type = id_byte[1]; sfc_nand_dev.mem_type = id_byte[1];
@ -732,7 +762,7 @@ u32 sfc_nand_init(void)
sfc_nand_dev.page_read_cmd = p_nand_info->read_cache_cmd_1; sfc_nand_dev.page_read_cmd = p_nand_info->read_cache_cmd_1;
sfc_nand_dev.page_prog_cmd = p_nand_info->prog_cache_cmd_1; sfc_nand_dev.page_prog_cmd = p_nand_info->prog_cache_cmd_1;
if (p_nand_info->feature & FEA_4BIT_READ) { if (p_nand_info->feature & FEA_4BIT_READ) {
if (spi_nand_enable_QE() == SFC_OK) { if (sfc_nand_enable_QE() == SFC_OK) {
sfc_nand_dev.read_lines = DATA_LINES_X4; sfc_nand_dev.read_lines = DATA_LINES_X4;
sfc_nand_dev.page_read_cmd = sfc_nand_dev.page_read_cmd =
p_nand_info->read_cache_cmd_4; p_nand_info->read_cache_cmd_4;

View File

@ -84,6 +84,13 @@ struct SFNAND_DEV {
u8 page_prog_cmd; u8 page_prog_cmd;
}; };
struct nand_mega_area {
u8 off0;
u8 off1;
u8 off2;
u8 off3;
};
struct nand_info { struct nand_info {
u32 id; u32 id;
@ -107,8 +114,7 @@ struct nand_info {
u8 QE_address; u8 QE_address;
u8 QE_bits; u8 QE_bits;
u8 spare_offs_1; struct nand_mega_area meta;
u8 spare_offs_2;
u32 (*ecc_status)(void); u32 (*ecc_status)(void);
}; };

View File

@ -28,6 +28,8 @@ static struct flash_info spi_flash_tbl[] = {
{ 0xef4018, 128, 8, 0x03, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0C, 15, 9, 0 }, { 0xef4018, 128, 8, 0x03, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0C, 15, 9, 0 },
/* 25Q256F/J */ /* 25Q256F/J */
{ 0xef4019, 128, 8, 0x13, 0x02, 0x6C, 0x32, 0x20, 0xD8, 0x3C, 16, 9, 0 }, { 0xef4019, 128, 8, 0x13, 0x02, 0x6C, 0x32, 0x20, 0xD8, 0x3C, 16, 9, 0 },
/* 25Q256JWEQ*/
{ 0xef6019, 128, 8, 0x13, 0x02, 0x6C, 0x32, 0x20, 0xD8, 0x3C, 16, 9, 0 },
/* 25Q64FWSSIG */ /* 25Q64FWSSIG */
{ 0xef6017, 128, 8, 0x03, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0C, 14, 9, 0 }, { 0xef6017, 128, 8, 0x03, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0C, 14, 9, 0 },
/* MX25L6433F */ /* MX25L6433F */
@ -85,56 +87,64 @@ static struct flash_info spi_flash_tbl[] = {
static int snor_write_en(void) static int snor_write_en(void)
{ {
int ret; int ret;
union SFCCMD_DATA sfcmd; struct rk_sfc_op op;
sfcmd.d32 = 0; op.sfcmd.d32 = 0;
sfcmd.b.cmd = CMD_WRITE_EN; op.sfcmd.b.cmd = CMD_WRITE_EN;
ret = sfc_request(sfcmd.d32, 0, 0, NULL); op.sfctrl.d32 = 0;
ret = sfc_request(&op, 0, NULL, 0);
return ret; return ret;
} }
int snor_reset_device(void) int snor_reset_device(void)
{ {
int ret; struct rk_sfc_op op;
union SFCCMD_DATA sfcmd;
sfcmd.d32 = 0; op.sfcmd.d32 = 0;
sfcmd.b.cmd = CMD_ENABLE_RESER; op.sfcmd.b.cmd = CMD_ENABLE_RESER;
sfc_request(sfcmd.d32, 0, 0, NULL);
sfcmd.d32 = 0; op.sfctrl.d32 = 0;
sfcmd.b.cmd = CMD_RESET_DEVICE; sfc_request(&op, 0, NULL, 0);
ret = sfc_request(sfcmd.d32, 0, 0, NULL);
op.sfcmd.d32 = 0;
op.sfcmd.b.cmd = CMD_RESET_DEVICE;
op.sfctrl.d32 = 0;
sfc_request(&op, 0, NULL, 0);
/* tRST=30us , delay 1ms here */ /* tRST=30us , delay 1ms here */
mdelay(1); sfc_delay(1000);
return ret;
return SFC_OK;
} }
static int snor_enter_4byte_mode(void) static int snor_enter_4byte_mode(void)
{ {
int ret; int ret;
union SFCCMD_DATA sfcmd; struct rk_sfc_op op;
sfcmd.d32 = 0; op.sfcmd.d32 = 0;
sfcmd.b.cmd = CMD_ENTER_4BYTE_MODE; op.sfcmd.b.cmd = CMD_ENTER_4BYTE_MODE;
ret = sfc_request(sfcmd.d32, 0, 0, NULL); op.sfctrl.d32 = 0;
ret = sfc_request(&op, 0, NULL, 0);
return ret; return ret;
} }
static int snor_read_status(u32 reg_index, u8 *status) static int snor_read_status(u32 reg_index, u8 *status)
{ {
int ret; int ret;
union SFCCMD_DATA sfcmd; struct rk_sfc_op op;
u8 read_stat_cmd[] = {CMD_READ_STATUS, u8 read_stat_cmd[] = {CMD_READ_STATUS,
CMD_READ_STATUS2, CMD_READ_STATUS3}; CMD_READ_STATUS2, CMD_READ_STATUS3};
sfcmd.d32 = 0; op.sfcmd.d32 = 0;
sfcmd.b.cmd = read_stat_cmd[reg_index]; op.sfcmd.b.cmd = read_stat_cmd[reg_index];
sfcmd.b.datasize = 1;
ret = sfc_request(sfcmd.d32, 0, 0, status); op.sfctrl.d32 = 0;
ret = sfc_request(&op, 0, status, 1);
return ret; return ret;
} }
@ -142,16 +152,17 @@ static int snor_read_status(u32 reg_index, u8 *status)
static int snor_wait_busy(int timeout) static int snor_wait_busy(int timeout)
{ {
int ret; int ret;
union SFCCMD_DATA sfcmd; struct rk_sfc_op op;
int i; int i;
u32 status; u32 status;
sfcmd.d32 = 0; op.sfcmd.d32 = 0;
sfcmd.b.cmd = CMD_READ_STATUS; op.sfcmd.b.cmd = CMD_READ_STATUS;
sfcmd.b.datasize = 1;
op.sfctrl.d32 = 0;
for (i = 0; i < timeout; i++) { for (i = 0; i < timeout; i++) {
ret = sfc_request(sfcmd.d32, 0, 0, &status); ret = sfc_request(&op, 0, &status, 1);
if (ret != SFC_OK) if (ret != SFC_OK)
return ret; return ret;
@ -168,24 +179,26 @@ static int snor_wait_busy(int timeout)
static int snor_write_status2(u32 reg_index, u8 status) static int snor_write_status2(u32 reg_index, u8 status)
{ {
int ret; int ret;
union SFCCMD_DATA sfcmd; struct rk_sfc_op op;
u8 status2[2]; u8 status2[2];
u8 read_index;
status2[reg_index] = status; status2[reg_index] = status;
read_index = (reg_index == 0) ? 2 : 0; if (reg_index == 0)
ret = snor_read_status(read_index, &status2[read_index]); ret = snor_read_status(2, &status2[1]);
else
ret = snor_read_status(0, &status2[0]);
if (ret != SFC_OK) if (ret != SFC_OK)
return ret; return ret;
snor_write_en(); snor_write_en();
sfcmd.d32 = 0; op.sfcmd.d32 = 0;
sfcmd.b.cmd = CMD_WRITE_STATUS; op.sfcmd.b.cmd = CMD_WRITE_STATUS;
sfcmd.b.datasize = 2; op.sfcmd.b.rw = SFC_WRITE;
sfcmd.b.rw = SFC_WRITE;
ret = sfc_request(sfcmd.d32, 0, 0, &status2[0]); op.sfctrl.d32 = 0;
ret = sfc_request(&op, 0, &status2[0], 2);
if (ret != SFC_OK) if (ret != SFC_OK)
return ret; return ret;
@ -197,7 +210,7 @@ static int snor_write_status2(u32 reg_index, u8 status)
static int snor_write_status1(u32 reg_index, u8 status) static int snor_write_status1(u32 reg_index, u8 status)
{ {
int ret; int ret;
union SFCCMD_DATA sfcmd; struct rk_sfc_op op;
u8 status2[2]; u8 status2[2];
u8 read_index; u8 read_index;
@ -209,12 +222,13 @@ static int snor_write_status1(u32 reg_index, u8 status)
snor_write_en(); snor_write_en();
sfcmd.d32 = 0; op.sfcmd.d32 = 0;
sfcmd.b.cmd = CMD_WRITE_STATUS; op.sfcmd.b.cmd = CMD_WRITE_STATUS;
sfcmd.b.datasize = 2; op.sfcmd.b.rw = SFC_WRITE;
sfcmd.b.rw = SFC_WRITE;
ret = sfc_request(sfcmd.d32, 0, 0, &status2[0]); op.sfctrl.d32 = 0;
ret = sfc_request(&op, 0, &status2[0], 2);
if (ret != SFC_OK) if (ret != SFC_OK)
return ret; return ret;
@ -226,16 +240,17 @@ static int snor_write_status1(u32 reg_index, u8 status)
static int snor_write_status(u32 reg_index, u8 status) static int snor_write_status(u32 reg_index, u8 status)
{ {
int ret; int ret;
union SFCCMD_DATA sfcmd; struct rk_sfc_op op;
u8 write_stat_cmd[] = {CMD_WRITE_STATUS, u8 write_stat_cmd[] = {CMD_WRITE_STATUS,
CMD_WRITE_STATUS2, CMD_WRITE_STATUS3}; CMD_WRITE_STATUS2, CMD_WRITE_STATUS3};
snor_write_en(); snor_write_en();
sfcmd.d32 = 0; op.sfcmd.d32 = 0;
sfcmd.b.cmd = write_stat_cmd[reg_index]; op.sfcmd.b.cmd = write_stat_cmd[reg_index];
sfcmd.b.datasize = 1; op.sfcmd.b.rw = SFC_WRITE;
sfcmd.b.rw = SFC_WRITE;
ret = sfc_request(sfcmd.d32, 0, 0, &status); op.sfctrl.d32 = 0;
ret = sfc_request(&op, 0, &status, 1);
if (ret != SFC_OK) if (ret != SFC_OK)
return ret; return ret;
@ -249,30 +264,32 @@ int snor_erase(struct SFNOR_DEV *p_dev,
enum NOR_ERASE_TYPE erase_type) enum NOR_ERASE_TYPE erase_type)
{ {
int ret; int ret;
union SFCCMD_DATA sfcmd; struct rk_sfc_op op;
int timeout[] = {400, 2000, 40000}; /* ms */ int timeout[] = {400, 2000, 40000}; /* ms */
rkflash_print_dio("%s %x\n", __func__, addr); rkflash_print_dio("%s %x %x\n", __func__, addr, erase_type);
if (erase_type > ERASE_CHIP) if (erase_type > ERASE_CHIP)
return SFC_PARAM_ERR; return SFC_PARAM_ERR;
sfcmd.d32 = 0; op.sfcmd.d32 = 0;
if (erase_type == ERASE_BLOCK64K) if (erase_type == ERASE_BLOCK64K)
sfcmd.b.cmd = p_dev->blk_erase_cmd; op.sfcmd.b.cmd = p_dev->blk_erase_cmd;
else if (erase_type == ERASE_SECTOR) else if (erase_type == ERASE_SECTOR)
sfcmd.b.cmd = p_dev->sec_erase_cmd; op.sfcmd.b.cmd = p_dev->sec_erase_cmd;
else else
sfcmd.b.cmd = CMD_CHIP_ERASE; op.sfcmd.b.cmd = CMD_CHIP_ERASE;
sfcmd.b.addrbits = (erase_type != ERASE_CHIP) ? op.sfcmd.b.addrbits = (erase_type != ERASE_CHIP) ?
SFC_ADDR_24BITS : SFC_ADDR_0BITS; SFC_ADDR_24BITS : SFC_ADDR_0BITS;
if (p_dev->addr_mode == ADDR_MODE_4BYTE && erase_type != ERASE_CHIP) if (p_dev->addr_mode == ADDR_MODE_4BYTE && erase_type != ERASE_CHIP)
sfcmd.b.addrbits = SFC_ADDR_32BITS; op.sfcmd.b.addrbits = SFC_ADDR_32BITS;
op.sfctrl.d32 = 0;
snor_write_en(); snor_write_en();
ret = sfc_request(sfcmd.d32, 0, addr, NULL); ret = sfc_request(&op, addr, NULL, 0);
if (ret != SFC_OK) if (ret != SFC_OK)
return ret; return ret;
@ -286,29 +303,27 @@ int snor_prog_page(struct SFNOR_DEV *p_dev,
u32 size) u32 size)
{ {
int ret; int ret;
union SFCCMD_DATA sfcmd; struct rk_sfc_op op;
union SFCCTRL_DATA sfctrl;
rkflash_print_dio("%s %x %x\n", __func__, addr, *(u32 *)(p_data)); rkflash_print_dio("%s %x %x\n", __func__, addr, *(u32 *)(p_data));
sfcmd.d32 = 0; op.sfcmd.d32 = 0;
sfcmd.b.cmd = p_dev->prog_cmd; op.sfcmd.b.cmd = p_dev->prog_cmd;
sfcmd.b.addrbits = SFC_ADDR_24BITS; op.sfcmd.b.addrbits = SFC_ADDR_24BITS;
sfcmd.b.datasize = size; op.sfcmd.b.rw = SFC_WRITE;
sfcmd.b.rw = SFC_WRITE;
sfctrl.d32 = 0; op.sfctrl.d32 = 0;
sfctrl.b.datalines = p_dev->prog_lines; op.sfctrl.b.datalines = p_dev->prog_lines;
sfctrl.b.enbledma = 0; op.sfctrl.b.enbledma = 1;
if (p_dev->prog_cmd == CMD_PAGE_PROG_A4) if (p_dev->prog_cmd == CMD_PAGE_PROG_A4)
sfctrl.b.addrlines = SFC_4BITS_LINE; op.sfctrl.b.addrlines = SFC_4BITS_LINE;
if (p_dev->addr_mode == ADDR_MODE_4BYTE) if (p_dev->addr_mode == ADDR_MODE_4BYTE)
sfcmd.b.addrbits = SFC_ADDR_32BITS; op.sfcmd.b.addrbits = SFC_ADDR_32BITS;
snor_write_en(); snor_write_en();
ret = sfc_request(sfcmd.d32, sfctrl.d32, addr, p_data); ret = sfc_request(&op, addr, p_data, size);
if (ret != SFC_OK) if (ret != SFC_OK)
return ret; return ret;
@ -386,35 +401,33 @@ int snor_read_data(struct SFNOR_DEV *p_dev,
u32 size) u32 size)
{ {
int ret; int ret;
union SFCCMD_DATA sfcmd; struct rk_sfc_op op;
union SFCCTRL_DATA sfctrl;
sfcmd.d32 = 0; op.sfcmd.d32 = 0;
sfcmd.b.cmd = p_dev->read_cmd; op.sfcmd.b.cmd = p_dev->read_cmd;
sfcmd.b.datasize = size; op.sfcmd.b.addrbits = SFC_ADDR_24BITS;
sfcmd.b.addrbits = SFC_ADDR_24BITS;
sfctrl.d32 = 0; op.sfctrl.d32 = 0;
sfctrl.b.datalines = p_dev->read_lines; op.sfctrl.b.datalines = p_dev->read_lines;
if (!(size & 0x3) && size >= 4) if (!(size & 0x3) && size >= 4)
sfctrl.b.enbledma = 0; op.sfctrl.b.enbledma = 1;
if (p_dev->read_cmd == CMD_FAST_READ_X1 || if (p_dev->read_cmd == CMD_FAST_READ_X1 ||
p_dev->read_cmd == CMD_FAST_READ_X4 || p_dev->read_cmd == CMD_FAST_READ_X4 ||
p_dev->read_cmd == CMD_FAST_READ_X2 || p_dev->read_cmd == CMD_FAST_READ_X2 ||
p_dev->read_cmd == CMD_FAST_4READ_X4) { p_dev->read_cmd == CMD_FAST_4READ_X4) {
sfcmd.b.dummybits = 8; op.sfcmd.b.dummybits = 8;
} else if (p_dev->read_cmd == CMD_FAST_READ_A4) { } else if (p_dev->read_cmd == CMD_FAST_READ_A4) {
sfcmd.b.addrbits = SFC_ADDR_32BITS; op.sfcmd.b.addrbits = SFC_ADDR_32BITS;
addr = (addr << 8) | 0xFF; /* Set M[7:0] = 0xFF */ addr = (addr << 8) | 0xFF; /* Set M[7:0] = 0xFF */
sfcmd.b.dummybits = 4; op.sfcmd.b.dummybits = 4;
sfctrl.b.addrlines = SFC_4BITS_LINE; op.sfctrl.b.addrlines = SFC_4BITS_LINE;
} }
if (p_dev->addr_mode == ADDR_MODE_4BYTE) if (p_dev->addr_mode == ADDR_MODE_4BYTE)
sfcmd.b.addrbits = SFC_ADDR_32BITS; op.sfcmd.b.addrbits = SFC_ADDR_32BITS;
ret = sfc_request(sfcmd.d32, sfctrl.d32, addr, p_data); ret = sfc_request(&op, addr, p_data, size);
rkflash_print_dio("%s %x %x\n", __func__, addr, *(u32 *)(p_data)); rkflash_print_dio("%s %x %x\n", __func__, addr, *(u32 *)(p_data));
return ret; return ret;
@ -434,7 +447,7 @@ int snor_read(struct SFNOR_DEV *p_dev, u32 sec, u32 n_sec, void *p_data)
addr = sec << 9; addr = sec << 9;
size = n_sec << 9; size = n_sec << 9;
while (size) { while (size) {
len = size < SFC_MAX_IOSIZE ? size : SFC_MAX_IOSIZE; len = size < p_dev->max_iosize ? size : p_dev->max_iosize;
ret = snor_read_data(p_dev, addr, p_buf, len); ret = snor_read_data(p_dev, addr, p_buf, len);
if (ret != SFC_OK) { if (ret != SFC_OK) {
rkflash_print_error("snor_read_data %x ret= %x\n", rkflash_print_error("snor_read_data %x ret= %x\n",
@ -502,13 +515,14 @@ out:
int snor_read_id(u8 *data) int snor_read_id(u8 *data)
{ {
int ret; int ret;
union SFCCMD_DATA sfcmd; struct rk_sfc_op op;
sfcmd.d32 = 0; op.sfcmd.d32 = 0;
sfcmd.b.cmd = CMD_READ_JEDECID; op.sfcmd.b.cmd = CMD_READ_JEDECID;
sfcmd.b.datasize = 3;
ret = sfc_request(sfcmd.d32, 0, 0, data); op.sfctrl.d32 = 0;
ret = sfc_request(&op, 0, data, 3);
return ret; return ret;
} }
@ -516,15 +530,16 @@ int snor_read_id(u8 *data)
static int snor_read_parameter(u32 addr, u8 *data) static int snor_read_parameter(u32 addr, u8 *data)
{ {
int ret; int ret;
union SFCCMD_DATA sfcmd; struct rk_sfc_op op;
sfcmd.d32 = 0; op.sfcmd.d32 = 0;
sfcmd.b.cmd = CMD_READ_PARAMETER; op.sfcmd.b.cmd = CMD_READ_PARAMETER;
sfcmd.b.datasize = 1; op.sfcmd.b.addrbits = SFC_ADDR_24BITS;
sfcmd.b.addrbits = SFC_ADDR_24BITS; op.sfcmd.b.dummybits = 8;
sfcmd.b.dummybits = 8;
ret = sfc_request(sfcmd.d32, 0, addr, data); op.sfctrl.d32 = 0;
ret = sfc_request(&op, addr, data, 1);
return ret; return ret;
} }
@ -572,7 +587,8 @@ int snor_init(struct SFNOR_DEV *p_dev)
if (!p_dev) if (!p_dev)
return SFC_PARAM_ERR; return SFC_PARAM_ERR;
memset(p_dev, 0, sizeof(struct SFNOR_DEV)); memset((void *)p_dev, 0, sizeof(struct SFNOR_DEV));
p_dev->max_iosize = sfc_get_max_iosize();
snor_read_id(id_byte); snor_read_id(id_byte);
rkflash_print_error("sfc nor id: %x %x %x\n", rkflash_print_error("sfc nor id: %x %x %x\n",
id_byte[0], id_byte[1], id_byte[2]); id_byte[0], id_byte[1], id_byte[2]);
@ -625,7 +641,7 @@ int snor_init(struct SFNOR_DEV *p_dev)
if ((g_spi_flash_info->feature & FEA_4BYTE_ADDR_MODE)) if ((g_spi_flash_info->feature & FEA_4BYTE_ADDR_MODE))
snor_enter_4byte_mode(); snor_enter_4byte_mode();
} else { } else {
p_dev->capacity = 1 << id_byte[2] >> 3; p_dev->capacity = 1 << (id_byte[2] - 9);
p_dev->QE_bits = 0; p_dev->QE_bits = 0;
p_dev->blk_size = NOR_SECS_BLK; p_dev->blk_size = NOR_SECS_BLK;
p_dev->page_size = NOR_SECS_PAGE; p_dev->page_size = NOR_SECS_PAGE;

View File

@ -112,6 +112,7 @@ struct SFNOR_DEV {
enum SFC_DATA_LINES prog_lines; enum SFC_DATA_LINES prog_lines;
SNOR_WRITE_STATUS write_status; SNOR_WRITE_STATUS write_status;
u32 max_iosize;
}; };
struct flash_info { struct flash_info {

View File

@ -640,7 +640,7 @@ function pack_arm32_trust_image()
else else
./scripts/fit-vboot-uboot.sh --no-vboot --no-rebuild ./scripts/fit-vboot-uboot.sh --no-vboot --no-rebuild
ls uboot.img trust*.img >/dev/null 2>&1 && rm uboot.img trust*.img -rf ls uboot.img trust*.img >/dev/null 2>&1 && rm uboot.img trust*.img -rf
echo "pack uboot.fit (with uboot trust) okay! Input: $ini" echo "pack uboot.img (with uboot trust) okay! Input: $ini"
fi fi
} }

View File

@ -46,14 +46,7 @@ function usage_pack()
echo " $0 [args]" echo " $0 [args]"
echo echo
echo "args:" echo "args:"
if [[ "$0" = *boot.sh ]]; then echo " --rollback-index <decimal integer>"
echo " --rollback-index-boot <decimal integer>"
elif [[ "$0" = *uboot.sh ]]; then
echo " --rollback-index-uboot <decimal integer>"
else
echo " --rollback-index-boot <decimal integer>"
echo " --rollback-index-uboot <decimal integer>"
fi
echo " --no-vboot" echo " --no-vboot"
echo echo
} }
@ -95,13 +88,15 @@ function fit_process_args()
ARG_NO_REBUILD="y" ARG_NO_REBUILD="y"
shift 1 shift 1
;; ;;
--rollback-index-boot) --rollback-index)
ARG_ROLLBACK_IDX_BOOT=$2 if [[ "$0" = *fit-vboot-uboot.sh ]]; then
arg_check_decimal $2 ARG_ROLLBACK_IDX_UBOOT=$2
shift 2 elif [[ "$0" = *fit-vboot-boot.sh ]]; then
;; ARG_ROLLBACK_IDX_BOOT=$2
--rollback-index-uboot) else
ARG_ROLLBACK_IDX_UBOOT=$2 usage_pack
exit 1
fi
arg_check_decimal $2 arg_check_decimal $2
shift 2 shift 2
;; ;;
@ -355,7 +350,9 @@ function fit_boot_make_img()
ITB_FILE=$FIT_ITB_BOOT ITB_FILE=$FIT_ITB_BOOT
fi fi
cp $ITB_FILE $FIT_IMG_BOOT if [ "$ITB_FILE" != "$FIT_IMG_BOOT" ]; then
cp $ITB_FILE $FIT_IMG_BOOT -f
fi
} }
function fit_resign() function fit_resign()