diff options
-rw-r--r-- | arch/arm/mach-k3/am642_init.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-k3/include/mach/am64_spl.h | 1 | ||||
-rw-r--r-- | cmd/mtd.c | 4 | ||||
-rw-r--r-- | drivers/memory/ti-gpmc.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/nand.c | 7 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/omap_elm.c | 4 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/omap_elm.h | 6 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/omap_gpmc.c | 116 |
8 files changed, 59 insertions, 84 deletions
diff --git a/arch/arm/mach-k3/am642_init.c b/arch/arm/mach-k3/am642_init.c index 6085379f1db..ddf47ef0a9b 100644 --- a/arch/arm/mach-k3/am642_init.c +++ b/arch/arm/mach-k3/am642_init.c @@ -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) diff --git a/arch/arm/mach-k3/include/mach/am64_spl.h b/arch/arm/mach-k3/include/mach/am64_spl.h index b4f396b2c0a..a0a517019cb 100644 --- a/arch/arm/mach-k3/include/mach/am64_spl.h +++ b/arch/arm/mach-k3/include/mach/am64_spl.h @@ -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 diff --git a/cmd/mtd.c b/cmd/mtd.c index e63c011e791..9083a6840ac 100644 --- a/cmd/mtd.c +++ b/cmd/mtd.c @@ -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); diff --git a/drivers/memory/ti-gpmc.c b/drivers/memory/ti-gpmc.c index 775e78c9a5b..0b8674339ec 100644 --- a/drivers/memory/ti-gpmc.c +++ b/drivers/memory/ti-gpmc.c @@ -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 { diff --git a/drivers/mtd/nand/raw/nand.c b/drivers/mtd/nand/raw/nand.c index 4c18861aa25..b591170346d 100644 --- a/drivers/mtd/nand/raw/nand.c +++ b/drivers/mtd/nand/raw/nand.c @@ -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; diff --git a/drivers/mtd/nand/raw/omap_elm.c b/drivers/mtd/nand/raw/omap_elm.c index 56a2c39e4f6..015ec9bc2de 100644 --- a/drivers/mtd/nand/raw/omap_elm.c +++ b/drivers/mtd/nand/raw/omap_elm.c @@ -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) diff --git a/drivers/mtd/nand/raw/omap_elm.h b/drivers/mtd/nand/raw/omap_elm.h index a7f7bacb154..f3db00d55de 100644 --- a/drivers/mtd/nand/raw/omap_elm.h +++ b/drivers/mtd/nand/raw/omap_elm.h @@ -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 */ diff --git a/drivers/mtd/nand/raw/omap_gpmc.c b/drivers/mtd/nand/raw/omap_gpmc.c index 0e25bd5dc28..2f8fa7d73d2 100644 --- a/drivers/mtd/nand/raw/omap_gpmc.c +++ b/drivers/mtd/nand/raw/omap_gpmc.c @@ -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 */ |