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:
Tom Rini 2024-01-15 09:29:57 -05:00
commit b9631fe781
8 changed files with 59 additions and 84 deletions

View file

@ -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)

View file

@ -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

View file

@ -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);

View file

@ -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 {

View file

@ -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;

View file

@ -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)

View file

@ -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 */

View file

@ -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];
/* Enable ECC engine */
chip->ecc.hwctl(mtd, NAND_ECC_READ);
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 */
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, -1);
chip->read_buf(mtd, oob, ecctotal);
/* read respective ecc from oob area */
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, -1);
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 */