mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
drivers: rkflash: Change to use the api which the oob area available
Fixes: 69f3c341d9 ("drivers: rkflash: Support spinand non aligned read")
Change-Id: I3146cd574ac77c2d1a0b5b6563440d86766a0a9a
Signed-off-by: Jon Lin <jon.lin@rock-chips.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
obj-$(CONFIG_RK_NANDC_NAND) += rkflash_blk.o rkflash_debug.o rksftl.o rknandc_base.o nand_boot.o flash.o nandc.o
|
obj-$(CONFIG_RK_NANDC_NAND) += rkflash_blk.o rkflash_debug.o rksftl.o rknandc_base.o nand_boot.o flash.o nandc.o
|
||||||
obj-$(CONFIG_RK_SFC_NAND) += rkflash_blk.o rkflash_debug.o rksftl.o rksfc_base.o sfc_nand_boot.o sfc_nand.o sfc.o
|
obj-$(CONFIG_RK_SFC_NAND) += rkflash_blk.o rkflash_debug.o rksftl.o rksfc_base.o sfc_nand_boot.o sfc_nand.o sfc.o
|
||||||
obj-$(CONFIG_RK_SFC_NAND_MTD) += sfc_nand_mtd.o
|
obj-$(CONFIG_RK_SFC_NAND_MTD) += sfc_nand_mtd.o sfc_nand_mtd_bbt.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_SFC_NOR) += rkflash_blk.o rkflash_debug.o rksfc_base.o sfc_nor_boot.o sfc_nor.o sfc.o
|
||||||
obj-$(CONFIG_RK_SFC_NOR_MTD) += sfc_nor_mtd.o
|
obj-$(CONFIG_RK_SFC_NOR_MTD) += sfc_nor_mtd.o
|
||||||
|
|
||||||
|
|||||||
@@ -697,7 +697,7 @@ u32 sfc_nand_read_page_raw(u8 cs, u32 addr, u32 *p_page_buf)
|
|||||||
{
|
{
|
||||||
u32 page_size = SFC_NAND_SECTOR_FULL_SIZE * p_nand_info->sec_per_page;
|
u32 page_size = SFC_NAND_SECTOR_FULL_SIZE * p_nand_info->sec_per_page;
|
||||||
|
|
||||||
return sfc_nand_read(addr, gp_page_buf, 0, page_size);
|
return sfc_nand_read(addr, p_page_buf, 0, page_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
@@ -11,8 +11,11 @@
|
|||||||
|
|
||||||
#include "rkflash_blk.h"
|
#include "rkflash_blk.h"
|
||||||
#include "rkflash_debug.h"
|
#include "rkflash_debug.h"
|
||||||
|
#include "sfc_nand.h"
|
||||||
#include "sfc_nand_mtd.h"
|
#include "sfc_nand_mtd.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_RK_SFC_NAND_MTD
|
||||||
|
|
||||||
static struct mtd_partition nand_parts[MAX_PART_COUNT];
|
static struct mtd_partition nand_parts[MAX_PART_COUNT];
|
||||||
|
|
||||||
static inline struct snand_mtd_dev *mtd_to_priv(struct mtd_info *ptr_mtd)
|
static inline struct snand_mtd_dev *mtd_to_priv(struct mtd_info *ptr_mtd)
|
||||||
@@ -21,7 +24,7 @@ static inline struct snand_mtd_dev *mtd_to_priv(struct mtd_info *ptr_mtd)
|
|||||||
offsetof(struct snand_mtd_dev, mtd));
|
offsetof(struct snand_mtd_dev, mtd));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sfc_nand_erase_mtd(struct mtd_info *mtd, u32 addr)
|
int sfc_nand_erase_mtd(struct mtd_info *mtd, u32 addr)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -127,7 +130,7 @@ static int sfc_nand_read_mtd(struct mtd_info *mtd, loff_t from,
|
|||||||
return ret ? ret : max_bitflips;
|
return ret ? ret : max_bitflips;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sfc_nand_isbad_mtd(struct mtd_info *mtd, loff_t ofs)
|
int sfc_nand_isbad_mtd(struct mtd_info *mtd, loff_t ofs)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct snand_mtd_dev *p_dev = mtd_to_priv(mtd);
|
struct snand_mtd_dev *p_dev = mtd_to_priv(mtd);
|
||||||
@@ -220,8 +223,6 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "sfc_nand_mtd_bbt.c"
|
|
||||||
|
|
||||||
static int sfc_erase_mtd(struct mtd_info *mtd, struct erase_info *instr)
|
static int sfc_erase_mtd(struct mtd_info *mtd, struct erase_info *instr)
|
||||||
{
|
{
|
||||||
struct snand_mtd_dev *p_dev = mtd_to_priv(mtd);
|
struct snand_mtd_dev *p_dev = mtd_to_priv(mtd);
|
||||||
@@ -418,3 +419,5 @@ error_out:
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -68,9 +68,15 @@ static inline struct snand_mtd_dev *mtd_to_snanddev(struct mtd_info *mtd)
|
|||||||
return mtd->priv;
|
return mtd->priv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int snanddev_bbt_init(struct snand_mtd_dev *nand);
|
||||||
|
void snanddev_bbt_cleanup(struct snand_mtd_dev *nand);
|
||||||
int snanddev_bbt_update(struct snand_mtd_dev *nand);
|
int snanddev_bbt_update(struct snand_mtd_dev *nand);
|
||||||
int snanddev_bbt_get_block_status(const struct snand_mtd_dev *nand,
|
int snanddev_bbt_get_block_status(const struct snand_mtd_dev *nand,
|
||||||
unsigned int entry);
|
unsigned int entry);
|
||||||
int snanddev_bbt_set_block_status(struct snand_mtd_dev *nand, unsigned int entry,
|
int snanddev_bbt_set_block_status(struct snand_mtd_dev *nand, unsigned int entry,
|
||||||
enum nand_bbt_block_status status);
|
enum nand_bbt_block_status status);
|
||||||
|
|
||||||
|
int sfc_nand_isbad_mtd(struct mtd_info *mtd, loff_t ofs);
|
||||||
|
int sfc_nand_erase_mtd(struct mtd_info *mtd, u32 addr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -7,8 +7,10 @@
|
|||||||
* Peter Pan <peterpandong@micron.com>
|
* Peter Pan <peterpandong@micron.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/mtd/mtd.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
#include "sfc_nand.h"
|
||||||
#include "sfc_nand_mtd.h"
|
#include "sfc_nand_mtd.h"
|
||||||
|
|
||||||
#ifdef CONFIG_MTD_NAND_BBT_USING_FLASH
|
#ifdef CONFIG_MTD_NAND_BBT_USING_FLASH
|
||||||
@@ -44,12 +46,13 @@ static int nanddev_read_bbt(struct snand_mtd_dev *nand, u32 block, bool update)
|
|||||||
unsigned int nbytes = DIV_ROUND_UP(nblocks * bits_per_block,
|
unsigned int nbytes = DIV_ROUND_UP(nblocks * bits_per_block,
|
||||||
BITS_PER_LONG) * sizeof(*nand->bbt.cache);
|
BITS_PER_LONG) * sizeof(*nand->bbt.cache);
|
||||||
struct mtd_info *mtd = snanddev_to_mtd(nand);
|
struct mtd_info *mtd = snanddev_to_mtd(nand);
|
||||||
u8 *data_buf, *oob_buf;
|
u8 *data_buf, *oob_buf, *temp_buf;
|
||||||
struct nanddev_bbt_info *bbt_info;
|
struct nanddev_bbt_info *bbt_info;
|
||||||
struct mtd_oob_ops ops;
|
struct mtd_oob_ops ops;
|
||||||
int bbt_page_num;
|
u32 bbt_page_num;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
unsigned int version = 0;
|
unsigned int version = 0;
|
||||||
|
u32 page_addr, i;
|
||||||
|
|
||||||
if (!nand->bbt.cache)
|
if (!nand->bbt.cache)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@@ -74,7 +77,7 @@ static int nanddev_read_bbt(struct snand_mtd_dev *nand, u32 block, bool update)
|
|||||||
bbt_info = (struct nanddev_bbt_info *)(data_buf + nbytes);
|
bbt_info = (struct nanddev_bbt_info *)(data_buf + nbytes);
|
||||||
|
|
||||||
memset(&ops, 0, sizeof(struct mtd_oob_ops));
|
memset(&ops, 0, sizeof(struct mtd_oob_ops));
|
||||||
ops.mode = MTD_OPS_RAW;
|
ops.mode = MTD_OPS_PLACE_OOB;
|
||||||
ops.datbuf = data_buf;
|
ops.datbuf = data_buf;
|
||||||
ops.len = bbt_page_num * mtd->writesize;
|
ops.len = bbt_page_num * mtd->writesize;
|
||||||
ops.oobbuf = oob_buf;
|
ops.oobbuf = oob_buf;
|
||||||
@@ -82,14 +85,27 @@ static int nanddev_read_bbt(struct snand_mtd_dev *nand, u32 block, bool update)
|
|||||||
ops.ooboffs = 0;
|
ops.ooboffs = 0;
|
||||||
|
|
||||||
/* Store one entry for each block */
|
/* Store one entry for each block */
|
||||||
ret = sfc_nand_read_mtd(mtd, block * mtd->erasesize, &ops);
|
temp_buf = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
|
||||||
if (ret < 0) {
|
if (!temp_buf) {
|
||||||
pr_err("%s fail %d\n", __func__, ret);
|
kfree(data_buf);
|
||||||
ret = -EIO;
|
kfree(oob_buf);
|
||||||
goto out;
|
|
||||||
} else {
|
return -ENOMEM;
|
||||||
ret = 0;
|
|
||||||
}
|
}
|
||||||
|
page_addr = (u32)(block << (mtd->erasesize_shift - mtd->writesize_shift));
|
||||||
|
for (i = 0; i < bbt_page_num; i++) {
|
||||||
|
ret = sfc_nand_read_page_raw(0, page_addr + i, (u32 *)temp_buf);
|
||||||
|
if (ret < 0) {
|
||||||
|
pr_err("%s fail %d\n", __func__, ret);
|
||||||
|
ret = -EIO;
|
||||||
|
kfree(temp_buf);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ops.datbuf + i * mtd->writesize, temp_buf, mtd->writesize);
|
||||||
|
memcpy(ops.oobbuf + i * mtd->oobsize, temp_buf + mtd->writesize, mtd->oobsize);
|
||||||
|
}
|
||||||
|
kfree(temp_buf);
|
||||||
|
|
||||||
if (oob_buf[0] != 0xff && !memcmp(bbt_pattern, bbt_info->pattern, 4))
|
if (oob_buf[0] != 0xff && !memcmp(bbt_pattern, bbt_info->pattern, 4))
|
||||||
version = bbt_info->version;
|
version = bbt_info->version;
|
||||||
@@ -114,11 +130,12 @@ static int nanddev_write_bbt(struct snand_mtd_dev *nand, u32 block)
|
|||||||
unsigned int nbytes = DIV_ROUND_UP(nblocks * bits_per_block,
|
unsigned int nbytes = DIV_ROUND_UP(nblocks * bits_per_block,
|
||||||
BITS_PER_LONG) * sizeof(*nand->bbt.cache);
|
BITS_PER_LONG) * sizeof(*nand->bbt.cache);
|
||||||
struct mtd_info *mtd = snanddev_to_mtd(nand);
|
struct mtd_info *mtd = snanddev_to_mtd(nand);
|
||||||
u8 *data_buf, *oob_buf;
|
u8 *data_buf, *oob_buf, *temp_buf;
|
||||||
struct nanddev_bbt_info *bbt_info;
|
struct nanddev_bbt_info *bbt_info;
|
||||||
struct mtd_oob_ops ops;
|
struct mtd_oob_ops ops;
|
||||||
int bbt_page_num;
|
u32 bbt_page_num;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
u32 page_addr, i;
|
||||||
|
|
||||||
BBT_DBG("write_bbt to blk=%d ver=%d\n", block, nand->bbt.version);
|
BBT_DBG("write_bbt to blk=%d ver=%d\n", block, nand->bbt.version);
|
||||||
if (!nand->bbt.cache)
|
if (!nand->bbt.cache)
|
||||||
@@ -149,7 +166,7 @@ static int nanddev_write_bbt(struct snand_mtd_dev *nand, u32 block)
|
|||||||
bbt_info->version = nand->bbt.version;
|
bbt_info->version = nand->bbt.version;
|
||||||
|
|
||||||
/* Store one entry for each block */
|
/* Store one entry for each block */
|
||||||
ret = sfc_nand_erase_mtd(mtd, block << mtd->erasesize_shift);
|
ret = sfc_nand_erase_mtd(mtd, block / mtd->erasesize);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@@ -159,7 +176,28 @@ static int nanddev_write_bbt(struct snand_mtd_dev *nand, u32 block)
|
|||||||
ops.oobbuf = oob_buf;
|
ops.oobbuf = oob_buf;
|
||||||
ops.ooblen = bbt_page_num * mtd->oobsize;
|
ops.ooblen = bbt_page_num * mtd->oobsize;
|
||||||
ops.ooboffs = 0;
|
ops.ooboffs = 0;
|
||||||
ret = sfc_nand_write_mtd(mtd, block * mtd->erasesize, &ops);
|
|
||||||
|
temp_buf = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
|
||||||
|
if (!temp_buf) {
|
||||||
|
kfree(data_buf);
|
||||||
|
kfree(oob_buf);
|
||||||
|
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
page_addr = (u32)(block << (mtd->erasesize_shift - mtd->writesize_shift));
|
||||||
|
for (i = 0; i < bbt_page_num; i++) {
|
||||||
|
memcpy(temp_buf, ops.datbuf + i * mtd->writesize, mtd->writesize);
|
||||||
|
memcpy(temp_buf + mtd->writesize, ops.oobbuf + i * mtd->oobsize, mtd->oobsize);
|
||||||
|
|
||||||
|
ret = sfc_nand_prog_page_raw(0, page_addr + i, (u32 *)temp_buf);
|
||||||
|
if (ret < 0) {
|
||||||
|
pr_err("%s fail %d\n", __func__, ret);
|
||||||
|
ret = -EIO;
|
||||||
|
kfree(temp_buf);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kfree(temp_buf);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
kfree(data_buf);
|
kfree(data_buf);
|
||||||
@@ -196,7 +234,7 @@ static int nanddev_scan_bbt(struct snand_mtd_dev *nand)
|
|||||||
{
|
{
|
||||||
unsigned int nblocks = snanddev_neraseblocks(nand);
|
unsigned int nblocks = snanddev_neraseblocks(nand);
|
||||||
u32 start_block, block;
|
u32 start_block, block;
|
||||||
int ret;
|
int ret = 0;
|
||||||
|
|
||||||
nand->bbt.version = 0;
|
nand->bbt.version = 0;
|
||||||
start_block = nblocks - NANDDEV_BBT_SCAN_MAXBLOCKS;
|
start_block = nblocks - NANDDEV_BBT_SCAN_MAXBLOCKS;
|
||||||
@@ -213,7 +251,7 @@ static int nanddev_scan_bbt(struct snand_mtd_dev *nand)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user