summaryrefslogtreecommitdiff
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2022-12-19 17:29:55 +0300
committerTom Rini <trini@konsulko.com>2022-12-21 21:09:01 +0300
commit14f43797d0a696248c09d298e2f2809dded345ba (patch)
tree23fc5bc462689f07f389cc0b8e7f7bedd35253ff /drivers/mtd/nand
parent9c955393f7a27ded250fef7688e0065b44a3343f (diff)
parent2243922edca9f56a9d5519b9d6e36f5d7a18434d (diff)
downloadu-boot-14f43797d0a696248c09d298e2f2809dded345ba.tar.xz
Merge tag 'v2023.01-rc4' into next
Prepare v2023.01-rc4 Signed-off-by: Tom Rini <trini@konsulko.com>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/core.c3
-rw-r--r--drivers/mtd/nand/raw/Kconfig2
-rw-r--r--drivers/mtd/nand/raw/mxs_nand_spl.c2
-rw-r--r--drivers/mtd/nand/raw/nand_base.c7
-rw-r--r--drivers/mtd/nand/raw/nand_spl_loaders.c2
-rw-r--r--drivers/mtd/nand/raw/omap_gpmc.c68
6 files changed, 51 insertions, 33 deletions
diff --git a/drivers/mtd/nand/core.c b/drivers/mtd/nand/core.c
index 99c29670c7..4b9dd6a926 100644
--- a/drivers/mtd/nand/core.c
+++ b/drivers/mtd/nand/core.c
@@ -129,7 +129,7 @@ EXPORT_SYMBOL_GPL(nanddev_isreserved);
*
* Return: 0 in case of success, a negative error code otherwise.
*/
-int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos)
+static int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos)
{
unsigned int entry;
@@ -147,7 +147,6 @@ int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos)
return nand->ops->erase(nand, pos);
}
-EXPORT_SYMBOL_GPL(nanddev_erase);
/**
* nanddev_mtd_erase() - Generic mtd->_erase() implementation for NAND devices
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 338a3562a4..25b829f11c 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -251,7 +251,7 @@ config NAND_LPC32XX_SLC
config NAND_OMAP_GPMC
bool "Support OMAP GPMC NAND controller"
- depends on ARCH_OMAP2PLUS
+ depends on ARCH_OMAP2PLUS || ARCH_KEYSTONE || ARCH_K3
help
Enables omap_gpmc.c driver for OMAPx and AMxxxx platforms.
GPMC controller is used for parallel NAND flash devices, and can
diff --git a/drivers/mtd/nand/raw/mxs_nand_spl.c b/drivers/mtd/nand/raw/mxs_nand_spl.c
index ef03b7789d..300662994c 100644
--- a/drivers/mtd/nand/raw/mxs_nand_spl.c
+++ b/drivers/mtd/nand/raw/mxs_nand_spl.c
@@ -257,7 +257,7 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
while (block <= lastblock && size > 0) {
if (!is_badblock(mtd, mtd->erasesize * block, 1)) {
/* Skip bad blocks */
- while (page < nand_page_per_block) {
+ while (page < nand_page_per_block && size) {
int curr_page = nand_page_per_block * block + page;
if (mxs_read_page_ecc(mtd, page_buf, curr_page) < 0) {
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 215b9ba84f..bc61ad03eb 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4171,10 +4171,13 @@ static void nand_manufacturer_detect(struct nand_chip *chip)
* nand_decode_ext_id() otherwise.
*/
if (chip->manufacturer.desc && chip->manufacturer.desc->ops &&
- chip->manufacturer.desc->ops->detect)
+ chip->manufacturer.desc->ops->detect) {
+ /* The 3rd id byte holds MLC / multichip data */
+ chip->bits_per_cell = nand_get_bits_per_cell(chip->id.data[2]);
chip->manufacturer.desc->ops->detect(chip);
- else
+ } else {
nand_decode_ext_id(chip);
+ }
}
/*
diff --git a/drivers/mtd/nand/raw/nand_spl_loaders.c b/drivers/mtd/nand/raw/nand_spl_loaders.c
index 4befc75c04..156b44d835 100644
--- a/drivers/mtd/nand/raw/nand_spl_loaders.c
+++ b/drivers/mtd/nand/raw/nand_spl_loaders.c
@@ -23,7 +23,7 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
if (unlikely(page_offset)) {
memmove(dst, dst + page_offset,
CONFIG_SYS_NAND_PAGE_SIZE);
- dst = (void *)((int)dst - page_offset);
+ dst = (void *)(dst - page_offset);
page_offset = 0;
}
dst += CONFIG_SYS_NAND_PAGE_SIZE;
diff --git a/drivers/mtd/nand/raw/omap_gpmc.c b/drivers/mtd/nand/raw/omap_gpmc.c
index b7d261d8ce..be3cb3c601 100644
--- a/drivers/mtd/nand/raw/omap_gpmc.c
+++ b/drivers/mtd/nand/raw/omap_gpmc.c
@@ -8,7 +8,11 @@
#include <log.h>
#include <asm/io.h>
#include <linux/errno.h>
+
+#ifdef CONFIG_ARCH_OMAP2PLUS
#include <asm/arch/mem.h>
+#endif
+
#include <linux/mtd/omap_gpmc.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/rawnand.h>
@@ -17,6 +21,10 @@
#include <nand.h>
#include <linux/mtd/omap_elm.h>
+#ifndef GPMC_MAX_CS
+#define GPMC_MAX_CS 4
+#endif
+
#define BADBLOCK_MARKER_LENGTH 2
#define SECTOR_BYTES 512
#define ECCCLEAR (0x1 << 8)
@@ -29,7 +37,6 @@ static u8 bch8_polynomial[] = {0xef, 0x51, 0x2e, 0x09, 0xed, 0x93, 0x9a, 0xc2,
0x97, 0x79, 0xe5, 0x24, 0xb5};
#endif
static uint8_t cs_next;
-static __maybe_unused struct nand_ecclayout omap_ecclayout;
#if defined(CONFIG_NAND_OMAP_GPMC_WSCFG)
static const int8_t wscfg[CONFIG_SYS_MAX_NAND_DEVICE] =
@@ -47,6 +54,7 @@ struct omap_nand_info {
enum omap_ecc ecc_scheme;
uint8_t cs;
uint8_t ws; /* wait status pin (0,1) */
+ void __iomem *fifo;
};
/* We are wasting a bit of memory but al least we are safe */
@@ -342,6 +350,20 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
return 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);
+ struct omap_nand_info *info = nand_get_controller_data(chip);
+ u32 alignment = ((uintptr_t)buf | len) & 3;
+
+ if (alignment & 1)
+ readsb(info->fifo, buf, len);
+ else if (alignment & 3)
+ readsw(info->fifo, buf, len >> 1);
+ else
+ readsl(info->fifo, buf, len >> 2);
+}
+
#ifdef CONFIG_NAND_OMAP_GPMC_PREFETCH
#define PREFETCH_CONFIG1_CS_SHIFT 24
@@ -407,7 +429,7 @@ static int __read_prefetch_aligned(struct nand_chip *chip, uint32_t *buf, int le
cnt = PREFETCH_STATUS_FIFO_CNT(cnt);
for (i = 0; i < cnt / 4; i++) {
- *buf++ = readl(CFG_SYS_NAND_BASE);
+ *buf++ = readl(info->fifo);
len -= 4;
}
} while (len);
@@ -417,29 +439,19 @@ static int __read_prefetch_aligned(struct nand_chip *chip, uint32_t *buf, int le
return 0;
}
-static inline void omap_nand_read(struct mtd_info *mtd, uint8_t *buf, int len)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
-
- if (chip->options & NAND_BUSWIDTH_16)
- nand_read_buf16(mtd, buf, len);
- else
- nand_read_buf(mtd, buf, len);
-}
-
static void omap_nand_read_prefetch(struct mtd_info *mtd, uint8_t *buf, int len)
{
int ret;
- uint32_t head, tail;
+ uintptr_t head, tail;
struct nand_chip *chip = mtd_to_nand(mtd);
/*
* If the destination buffer is unaligned, start with reading
* the overlap byte-wise.
*/
- head = ((uint32_t) buf) % 4;
+ head = ((uintptr_t)buf) % 4;
if (head) {
- omap_nand_read(mtd, buf, head);
+ omap_nand_read_buf(mtd, buf, head);
buf += head;
len -= head;
}
@@ -453,10 +465,10 @@ static void omap_nand_read_prefetch(struct mtd_info *mtd, uint8_t *buf, int len)
ret = __read_prefetch_aligned(chip, (uint32_t *)buf, len - tail);
if (ret < 0) {
/* fallback in case the prefetch engine is busy */
- omap_nand_read(mtd, buf, len);
+ omap_nand_read_buf(mtd, buf, len);
} else if (tail) {
buf += len - tail;
- omap_nand_read(mtd, buf, tail);
+ omap_nand_read_buf(mtd, buf, tail);
}
}
#endif /* CONFIG_NAND_OMAP_GPMC_PREFETCH */
@@ -740,7 +752,7 @@ static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
static int omap_select_ecc_scheme(struct nand_chip *nand,
enum omap_ecc ecc_scheme, unsigned int pagesize, unsigned int oobsize) {
struct omap_nand_info *info = nand_get_controller_data(nand);
- struct nand_ecclayout *ecclayout = &omap_ecclayout;
+ struct nand_ecclayout *ecclayout = nand->ecc.layout;
int eccsteps = pagesize / SECTOR_BYTES;
int i;
@@ -993,6 +1005,8 @@ int board_nand_init(struct nand_chip *nand)
int32_t gpmc_config = 0;
int cs = cs_next++;
int err = 0;
+ struct omap_nand_info *info;
+
/*
* xloader/Uboot's gpmc configuration would have configured GPMC for
* nand type of memory. The following logic scans and latches on to the
@@ -1021,14 +1035,19 @@ int board_nand_init(struct nand_chip *nand)
nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
- omap_nand_info[cs].control = NULL;
- omap_nand_info[cs].cs = cs;
- omap_nand_info[cs].ws = wscfg[cs];
+
+ info = &omap_nand_info[cs];
+ info->control = NULL;
+ info->cs = cs;
+ info->ws = wscfg[cs];
+ info->fifo = (void __iomem *)CFG_SYS_NAND_BASE;
nand_set_controller_data(nand, &omap_nand_info[cs]);
nand->cmd_ctrl = omap_nand_hwcontrol;
nand->options |= NAND_NO_PADDING | NAND_CACHEPRG;
nand->chip_delay = 100;
- nand->ecc.layout = &omap_ecclayout;
+ nand->ecc.layout = kzalloc(sizeof(*nand->ecc.layout), GFP_KERNEL);
+ if (!nand->ecc.layout)
+ return -ENOMEM;
/* configure driver and controller based on NAND device bus-width */
gpmc_config = readl(&gpmc_cfg->cs[cs].config1);
@@ -1054,10 +1073,7 @@ int board_nand_init(struct nand_chip *nand)
#ifdef CONFIG_NAND_OMAP_GPMC_PREFETCH
nand->read_buf = omap_nand_read_prefetch;
#else
- if (nand->options & NAND_BUSWIDTH_16)
- nand->read_buf = nand_read_buf16;
- else
- nand->read_buf = nand_read_buf;
+ nand->read_buf = omap_nand_read_buf;
#endif
nand->dev_ready = omap_dev_ready;