mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 15:41:40 +00:00
Pull request for u-boot-nand-20240115
The first patch is by Heinrich Schuchardt and fixes an integer overflow The following two patches are by Dario Binacchi and add arguments check to the nand_mtd_to_devnum() and nand_register() functions. The remaining patches are by Roger Quadros and include various fixes for the OMAP platform. -----BEGIN PGP SIGNATURE----- iQJYBAABCgBCFiEE6GOTDNYiFygVXvMmQBtB6IWRjvEFAmWlAhUkHGRhcmlvLmJp bmFjY2hpQGFtYXJ1bGFzb2x1dGlvbnMuY29tAAoJEEAbQeiFkY7xp6AP/iSHmzZd GrVbeyjSFPkl1ZEEq1z3UW7jrd/5chGNDrD7OUqKw3L0zrDNQWYaYTyO/IqZMYjm rtSc1hF6cTzkCBYrg8jKlmfS6eRR/7Og+gYxvkD5iqJC/++5eR3N+CYq4nroz9S5 YovWFNkgVQIe2W6PXwhr8Sj7IScWhRJPidaX5MtTN8Xx+uz/2Y/VjKw8m2g+MC6E jrVrmiuFj1YwmS7qx8QZlmPzAnMmANy4YUZywpYNFzN7H5o52FDZRBr5Hn97gmHy asQhuqurMbz+vzV9VPrb1iLUVErnkjzCKvl9Vu75At8L/UcSfxeUG4O9wNhmsADZ kDgGx60ZJdCNK1ym47F/JvB2qgFBByY4FVEHqPfjddCUJhpi8fLwmSNeVh/uaV7C uWG9Gu9rlJV/yQAQCGfuwqf/uQ/PrqaqgPd419JR9GzhM21g8Ytye1lHYgmlnEo6 4dgF4pb/kj1vMwD36kfwqM+zHqzv9I6oNDEHU4keIjUPR+bMnNtwXmS9DtARESK9 RE48iAv/m3OO9Wfcb0XxwAySZiYoJsVCmcwXaoVCiuE+4eSqarqhKvlZdsvXobs/ 0EZYN7lcNcxO5jTTA5S0WcXNeWjc8KyC+w3bPou86TepjrmF6QIm6VUR0Eyks3sA zUoC5M8W/dCt1SRSJiC46jfOqnGgSxWu73P+ =xg/L -----END PGP SIGNATURE----- Merge tag 'u-boot-nand-20240115' of https://source.denx.de/u-boot/custodians/u-boot-nand-flash Pull request for u-boot-nand-20240115 The first patch is by Heinrich Schuchardt and fixes an integer overflow The following two patches are by Dario Binacchi and add arguments check to the nand_mtd_to_devnum() and nand_register() functions. The remaining patches are by Roger Quadros and include various fixes for the OMAP platform.
This commit is contained in:
commit
b9631fe781
8 changed files with 59 additions and 84 deletions
|
@ -348,6 +348,9 @@ static u32 __get_primary_bootmedia(u32 main_devstat)
|
|||
case BOOT_DEVICE_EMMC:
|
||||
return BOOT_DEVICE_MMC1;
|
||||
|
||||
case BOOT_DEVICE_NAND:
|
||||
return BOOT_DEVICE_NAND;
|
||||
|
||||
case BOOT_DEVICE_MMC:
|
||||
if ((bootmode_cfg & MAIN_DEVSTAT_PRIMARY_MMC_PORT_MASK) >>
|
||||
MAIN_DEVSTAT_PRIMARY_MMC_PORT_SHIFT)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#define BOOT_DEVICE_USB 0x2A
|
||||
#define BOOT_DEVICE_DFU 0x0A
|
||||
#define BOOT_DEVICE_NAND 0x0B
|
||||
#define BOOT_DEVICE_GPMC_NOR 0x0C
|
||||
#define BOOT_DEVICE_PCIE 0x0D
|
||||
#define BOOT_DEVICE_XSPI 0x0E
|
||||
|
|
|
@ -77,7 +77,7 @@ static void mtd_dump_device_buf(struct mtd_info *mtd, u64 start_off,
|
|||
|
||||
if (has_pages) {
|
||||
for (page = 0; page < npages; page++) {
|
||||
u64 data_off = page * mtd->writesize;
|
||||
u64 data_off = (u64)page * mtd->writesize;
|
||||
|
||||
printf("\nDump %d data bytes from 0x%08llx:\n",
|
||||
mtd->writesize, start_off + data_off);
|
||||
|
@ -85,7 +85,7 @@ static void mtd_dump_device_buf(struct mtd_info *mtd, u64 start_off,
|
|||
mtd->writesize, start_off + data_off);
|
||||
|
||||
if (woob) {
|
||||
u64 oob_off = page * mtd->oobsize;
|
||||
u64 oob_off = (u64)page * mtd->oobsize;
|
||||
|
||||
printf("Dump %d OOB bytes from page at 0x%08llx:\n",
|
||||
mtd->oobsize, start_off + data_off);
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include <clk.h>
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
|
@ -17,6 +16,7 @@
|
|||
#include <linux/mtd/omap_gpmc.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/sizes.h>
|
||||
#include "ti-gpmc.h"
|
||||
|
||||
enum gpmc_clk_domain {
|
||||
|
|
|
@ -41,8 +41,11 @@ int nand_mtd_to_devnum(struct mtd_info *mtd)
|
|||
{
|
||||
int i;
|
||||
|
||||
if (!mtd)
|
||||
return -ENODEV;
|
||||
|
||||
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
|
||||
if (mtd && get_nand_dev_by_index(i) == mtd)
|
||||
if (get_nand_dev_by_index(i) == mtd)
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -52,7 +55,7 @@ int nand_mtd_to_devnum(struct mtd_info *mtd)
|
|||
/* Register an initialized NAND mtd device with the U-Boot NAND command. */
|
||||
int nand_register(int devnum, struct mtd_info *mtd)
|
||||
{
|
||||
if (devnum >= CONFIG_SYS_MAX_NAND_DEVICE)
|
||||
if (!mtd || devnum >= CONFIG_SYS_MAX_NAND_DEVICE)
|
||||
return -EINVAL;
|
||||
|
||||
nand_info[devnum] = mtd;
|
||||
|
|
|
@ -185,7 +185,6 @@ void elm_reset(void)
|
|||
;
|
||||
}
|
||||
|
||||
#ifdef ELM_BASE
|
||||
/**
|
||||
* elm_init - Initialize ELM module
|
||||
*
|
||||
|
@ -194,10 +193,11 @@ void elm_reset(void)
|
|||
*/
|
||||
void elm_init(void)
|
||||
{
|
||||
#ifdef ELM_BASE
|
||||
elm_cfg = (struct elm *)ELM_BASE;
|
||||
elm_reset();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(SYS_NAND_SELF_INIT)
|
||||
|
||||
|
|
|
@ -74,12 +74,6 @@ int elm_check_error(u8 *syndrome, enum bch_level bch_type, u32 *error_count,
|
|||
u32 *error_locations);
|
||||
int elm_config(enum bch_level level);
|
||||
void elm_reset(void);
|
||||
#ifdef ELM_BASE
|
||||
void elm_init(void);
|
||||
#else
|
||||
static inline void elm_init(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASM_ARCH_ELM_H */
|
||||
|
|
|
@ -8,13 +8,15 @@
|
|||
#include <log.h>
|
||||
#include <system-constants.h>
|
||||
#include <asm/io.h>
|
||||
#include <dm/uclass.h>
|
||||
#include <dm.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP2PLUS
|
||||
#include <asm/arch/mem.h>
|
||||
#endif
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/mtd/omap_gpmc.h>
|
||||
#include <linux/mtd/nand_ecc.h>
|
||||
#include <linux/mtd/rawnand.h>
|
||||
|
@ -294,7 +296,7 @@ static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd,
|
|||
break;
|
||||
case OMAP_ECC_BCH8_CODE_HW:
|
||||
bch_type = 1;
|
||||
nsectors = chip->ecc.steps;
|
||||
nsectors = 1;
|
||||
if (mode == NAND_ECC_READ) {
|
||||
wr_mode = BCH_WRAPMODE_1;
|
||||
ecc_size0 = BCH8R_ECC_SIZE0;
|
||||
|
@ -307,7 +309,7 @@ static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd,
|
|||
break;
|
||||
case OMAP_ECC_BCH16_CODE_HW:
|
||||
bch_type = 0x2;
|
||||
nsectors = chip->ecc.steps;
|
||||
nsectors = 1;
|
||||
if (mode == NAND_ECC_READ) {
|
||||
wr_mode = 0x01;
|
||||
ecc_size0 = 52; /* ECC bits in nibbles per sector */
|
||||
|
@ -346,17 +348,16 @@ static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd,
|
|||
}
|
||||
|
||||
/**
|
||||
* _omap_calculate_ecc_bch - Generate BCH ECC bytes for one sector
|
||||
* omap_calculate_ecc_bch - Generate BCH ECC bytes for one sector
|
||||
* @mtd: MTD device structure
|
||||
* @dat: The pointer to data on which ecc is computed
|
||||
* @ecc_code: The ecc_code buffer
|
||||
* @sector: The sector number (for a multi sector page)
|
||||
*
|
||||
* Support calculating of BCH4/8/16 ECC vectors for one sector
|
||||
* within a page. Sector number is in @sector.
|
||||
*/
|
||||
static int _omap_calculate_ecc_bch(struct mtd_info *mtd, const u8 *dat,
|
||||
u8 *ecc_code, int sector)
|
||||
static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd, const u8 *dat,
|
||||
u8 *ecc_code)
|
||||
{
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct omap_nand_info *info = nand_get_controller_data(chip);
|
||||
|
@ -369,7 +370,7 @@ static int _omap_calculate_ecc_bch(struct mtd_info *mtd, const u8 *dat,
|
|||
case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
|
||||
#endif
|
||||
case OMAP_ECC_BCH8_CODE_HW:
|
||||
ptr = &gpmc_cfg->bch_result_0_3[sector].bch_result_x[3];
|
||||
ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[3];
|
||||
val = readl(ptr);
|
||||
ecc_code[i++] = (val >> 0) & 0xFF;
|
||||
ptr--;
|
||||
|
@ -384,21 +385,21 @@ static int _omap_calculate_ecc_bch(struct mtd_info *mtd, const u8 *dat,
|
|||
|
||||
break;
|
||||
case OMAP_ECC_BCH16_CODE_HW:
|
||||
val = readl(&gpmc_cfg->bch_result_4_6[sector].bch_result_x[2]);
|
||||
val = readl(&gpmc_cfg->bch_result_4_6[0].bch_result_x[2]);
|
||||
ecc_code[i++] = (val >> 8) & 0xFF;
|
||||
ecc_code[i++] = (val >> 0) & 0xFF;
|
||||
val = readl(&gpmc_cfg->bch_result_4_6[sector].bch_result_x[1]);
|
||||
val = readl(&gpmc_cfg->bch_result_4_6[0].bch_result_x[1]);
|
||||
ecc_code[i++] = (val >> 24) & 0xFF;
|
||||
ecc_code[i++] = (val >> 16) & 0xFF;
|
||||
ecc_code[i++] = (val >> 8) & 0xFF;
|
||||
ecc_code[i++] = (val >> 0) & 0xFF;
|
||||
val = readl(&gpmc_cfg->bch_result_4_6[sector].bch_result_x[0]);
|
||||
val = readl(&gpmc_cfg->bch_result_4_6[0].bch_result_x[0]);
|
||||
ecc_code[i++] = (val >> 24) & 0xFF;
|
||||
ecc_code[i++] = (val >> 16) & 0xFF;
|
||||
ecc_code[i++] = (val >> 8) & 0xFF;
|
||||
ecc_code[i++] = (val >> 0) & 0xFF;
|
||||
for (j = 3; j >= 0; j--) {
|
||||
val = readl(&gpmc_cfg->bch_result_0_3[sector].bch_result_x[j]
|
||||
val = readl(&gpmc_cfg->bch_result_0_3[0].bch_result_x[j]
|
||||
);
|
||||
ecc_code[i++] = (val >> 24) & 0xFF;
|
||||
ecc_code[i++] = (val >> 16) & 0xFF;
|
||||
|
@ -432,22 +433,6 @@ static int _omap_calculate_ecc_bch(struct mtd_info *mtd, const u8 *dat,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* omap_calculate_ecc_bch - ECC generator for 1 sector
|
||||
* @mtd: MTD device structure
|
||||
* @dat: The pointer to data on which ecc is computed
|
||||
* @ecc_code: The ecc_code buffer
|
||||
*
|
||||
* Support calculating of BCH4/8/16 ECC vectors for one sector. This is used
|
||||
* when SW based correction is required as ECC is required for one sector
|
||||
* at a time.
|
||||
*/
|
||||
static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
|
||||
const u_char *dat, u_char *ecc_calc)
|
||||
{
|
||||
return _omap_calculate_ecc_bch(mtd, dat, ecc_calc, 0);
|
||||
}
|
||||
|
||||
static inline void omap_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
||||
{
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
@ -573,34 +558,6 @@ static void omap_nand_read_prefetch(struct mtd_info *mtd, uint8_t *buf, int len)
|
|||
|
||||
#ifdef CONFIG_NAND_OMAP_ELM
|
||||
|
||||
/**
|
||||
* omap_calculate_ecc_bch_multi - Generate ECC for multiple sectors
|
||||
* @mtd: MTD device structure
|
||||
* @dat: The pointer to data on which ecc is computed
|
||||
* @ecc_code: The ecc_code buffer
|
||||
*
|
||||
* Support calculating of BCH4/8/16 ecc vectors for the entire page in one go.
|
||||
*/
|
||||
static int omap_calculate_ecc_bch_multi(struct mtd_info *mtd,
|
||||
const u_char *dat, u_char *ecc_calc)
|
||||
{
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
int eccbytes = chip->ecc.bytes;
|
||||
unsigned long nsectors;
|
||||
int i, ret;
|
||||
|
||||
nsectors = ((readl(&gpmc_cfg->ecc_config) >> 4) & 0x7) + 1;
|
||||
for (i = 0; i < nsectors; i++) {
|
||||
ret = _omap_calculate_ecc_bch(mtd, dat, ecc_calc, i);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ecc_calc += eccbytes;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* omap_reverse_list - re-orders list elements in reverse order [internal]
|
||||
* @list: pointer to start of list
|
||||
|
@ -753,7 +710,6 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
{
|
||||
int i, eccsize = chip->ecc.size;
|
||||
int eccbytes = chip->ecc.bytes;
|
||||
int ecctotal = chip->ecc.total;
|
||||
int eccsteps = chip->ecc.steps;
|
||||
uint8_t *p = buf;
|
||||
uint8_t *ecc_calc = chip->buffers->ecccalc;
|
||||
|
@ -761,24 +717,30 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
uint32_t *eccpos = chip->ecc.layout->eccpos;
|
||||
uint8_t *oob = chip->oob_poi;
|
||||
uint32_t oob_pos;
|
||||
u32 data_pos = 0;
|
||||
|
||||
/* oob area start */
|
||||
oob_pos = (eccsize * eccsteps) + chip->ecc.layout->eccpos[0];
|
||||
oob += chip->ecc.layout->eccpos[0];
|
||||
|
||||
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize,
|
||||
oob += eccbytes) {
|
||||
/* Enable ECC engine */
|
||||
chip->ecc.hwctl(mtd, NAND_ECC_READ);
|
||||
|
||||
/* read entire page */
|
||||
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 0, -1);
|
||||
chip->read_buf(mtd, buf, mtd->writesize);
|
||||
/* read data */
|
||||
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_pos, -1);
|
||||
chip->read_buf(mtd, p, eccsize);
|
||||
|
||||
/* read all ecc bytes from oob area */
|
||||
/* read respective ecc from oob area */
|
||||
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, -1);
|
||||
chip->read_buf(mtd, oob, ecctotal);
|
||||
chip->read_buf(mtd, oob, eccbytes);
|
||||
/* read syndrome */
|
||||
chip->ecc.calculate(mtd, p, &ecc_calc[i]);
|
||||
|
||||
/* Calculate ecc bytes */
|
||||
omap_calculate_ecc_bch_multi(mtd, buf, ecc_calc);
|
||||
data_pos += eccsize;
|
||||
oob_pos += eccbytes;
|
||||
}
|
||||
|
||||
for (i = 0; i < chip->ecc.total; i++)
|
||||
ecc_code[i] = chip->oob_poi[eccpos[i]];
|
||||
|
@ -946,6 +908,7 @@ static int omap_select_ecc_scheme(struct nand_chip *nand,
|
|||
nand->ecc.hwctl = omap_enable_hwecc_bch;
|
||||
nand->ecc.correct = omap_correct_data_bch_sw;
|
||||
nand->ecc.calculate = omap_calculate_ecc_bch;
|
||||
nand->ecc.steps = eccsteps;
|
||||
/* define ecc-layout */
|
||||
ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
|
||||
ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH;
|
||||
|
@ -988,6 +951,7 @@ static int omap_select_ecc_scheme(struct nand_chip *nand,
|
|||
nand->ecc.correct = omap_correct_data_bch;
|
||||
nand->ecc.calculate = omap_calculate_ecc_bch;
|
||||
nand->ecc.read_page = omap_read_page_bch;
|
||||
nand->ecc.steps = eccsteps;
|
||||
/* define ecc-layout */
|
||||
ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
|
||||
for (i = 0; i < ecclayout->eccbytes; i++)
|
||||
|
@ -1021,6 +985,7 @@ static int omap_select_ecc_scheme(struct nand_chip *nand,
|
|||
nand->ecc.correct = omap_correct_data_bch;
|
||||
nand->ecc.calculate = omap_calculate_ecc_bch;
|
||||
nand->ecc.read_page = omap_read_page_bch;
|
||||
nand->ecc.steps = eccsteps;
|
||||
/* define ecc-layout */
|
||||
ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
|
||||
for (i = 0; i < ecclayout->eccbytes; i++)
|
||||
|
@ -1124,7 +1089,7 @@ int __maybe_unused omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
|
|||
* nand_scan about special functionality. See the defines for further
|
||||
* explanation
|
||||
*/
|
||||
int gpmc_nand_init(struct nand_chip *nand)
|
||||
int gpmc_nand_init(struct nand_chip *nand, void __iomem *nand_base)
|
||||
{
|
||||
int32_t gpmc_config = 0;
|
||||
int cs = cs_next++;
|
||||
|
@ -1164,7 +1129,7 @@ int gpmc_nand_init(struct nand_chip *nand)
|
|||
info->control = NULL;
|
||||
info->cs = cs;
|
||||
info->ws = wscfg[cs];
|
||||
info->fifo = (void __iomem *)CFG_SYS_NAND_BASE;
|
||||
info->fifo = nand_base;
|
||||
nand_set_controller_data(nand, &omap_nand_info[cs]);
|
||||
nand->cmd_ctrl = omap_nand_hwcontrol;
|
||||
nand->options |= NAND_NO_PADDING | NAND_CACHEPRG;
|
||||
|
@ -1214,9 +1179,18 @@ static int gpmc_nand_probe(struct udevice *dev)
|
|||
{
|
||||
struct nand_chip *nand = dev_get_priv(dev);
|
||||
struct mtd_info *mtd = nand_to_mtd(nand);
|
||||
struct resource res;
|
||||
void __iomem *base;
|
||||
int ret;
|
||||
|
||||
gpmc_nand_init(nand);
|
||||
ret = dev_read_resource(dev, 0, &res);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
base = devm_ioremap(dev, res.start, resource_size(&res));
|
||||
gpmc_nand_init(nand, base);
|
||||
mtd->dev = dev;
|
||||
nand_set_flash_node(nand, dev_ofnode(dev));
|
||||
|
||||
ret = nand_scan(mtd, CONFIG_SYS_NAND_MAX_CHIPS);
|
||||
if (ret)
|
||||
|
@ -1270,7 +1244,7 @@ void board_nand_init(void)
|
|||
|
||||
int board_nand_init(struct nand_chip *nand)
|
||||
{
|
||||
return gpmc_nand_init(nand);
|
||||
return gpmc_nand_init(nand, (void __iomem *)CFG_SYS_NAND_BASE);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SYS_NAND_SELF_INIT */
|
||||
|
|
Loading…
Reference in a new issue