summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/freescale/mpc8360erdk/nand.c4
-rw-r--r--board/tqc/tqm85xx/nand.c5
-rw-r--r--common/cmd_nand.c21
-rw-r--r--drivers/mtd/nand/fsl_upm.c82
-rw-r--r--drivers/mtd/nand/nand.c6
-rw-r--r--drivers/mtd/nand/nand_base.c2
-rw-r--r--include/configs/TQM85xx.h32
-rw-r--r--include/linux/mtd/fsl_upm.h11
-rw-r--r--onenand_ipl/onenand_boot.c36
-rw-r--r--onenand_ipl/onenand_ipl.h6
10 files changed, 112 insertions, 93 deletions
diff --git a/board/freescale/mpc8360erdk/nand.c b/board/freescale/mpc8360erdk/nand.c
index 8e22e13..9ffffb4 100644
--- a/board/freescale/mpc8360erdk/nand.c
+++ b/board/freescale/mpc8360erdk/nand.c
@@ -57,7 +57,7 @@ static void upm_setup(struct fsl_upm *upm)
eieio();
}
-static int dev_ready(void)
+static int dev_ready(int chip_nr)
{
if (in_be32(&im->qepio.ioport[4].pdat) & 0x00002000) {
debug("nand ready\n");
@@ -76,7 +76,7 @@ static struct fsl_upm_nand fun = {
.upm_cmd_offset = 8,
.upm_addr_offset = 16,
.dev_ready = dev_ready,
- .wait_pattern = 1,
+ .wait_flags = FSL_UPM_WAIT_RUN_PATTERN,
.chip_delay = 50,
};
diff --git a/board/tqc/tqm85xx/nand.c b/board/tqc/tqm85xx/nand.c
index 8133fdc..3da689a 100644
--- a/board/tqc/tqm85xx/nand.c
+++ b/board/tqc/tqm85xx/nand.c
@@ -385,7 +385,7 @@ static void upmb_write (u_char addr, ulong val)
MxMR_OP_WARR | (addr & MxMR_MAD_MSK));
/* dummy access to perform write */
- out_8 ((void __iomem *)CONFIG_SYS_NAND0_BASE, 0);
+ out_8 ((void __iomem *)CONFIG_SYS_NAND_BASE, 0);
clrbits_be32(&lbc->mbmr, MxMR_OP_WARR);
}
@@ -446,7 +446,10 @@ static struct fsl_upm_nand fun = {
.width = 8,
.upm_cmd_offset = 0x08,
.upm_addr_offset = 0x10,
+ .upm_mar_chip_offset = CONFIG_SYS_NAND_CS_DIST,
+ .chip_offset = CONFIG_SYS_NAND_CS_DIST,
.chip_delay = NAND_BIG_DELAY_US,
+ .wait_flags = FSL_UPM_WAIT_RUN_PATTERN | FSL_UPM_WAIT_WRITE_BUFFER,
};
void board_nand_select_device (struct nand_chip *nand, int chip)
diff --git a/common/cmd_nand.c b/common/cmd_nand.c
index 04b3200..e142d76 100644
--- a/common/cmd_nand.c
+++ b/common/cmd_nand.c
@@ -205,6 +205,17 @@ static void do_nand_status(nand_info_t *nand)
}
#endif
+static void nand_print_info(int idx)
+{
+ nand_info_t *nand = &nand_info[idx];
+ struct nand_chip *chip = nand->priv;
+ printf("Device %d: ", idx);
+ if (chip->numchips > 1)
+ printf("%dx ", chip->numchips);
+ printf("%s, sector size %u KiB\n",
+ nand->name, nand->erasesize >> 10);
+}
+
int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
int i, dev, ret = 0;
@@ -233,9 +244,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
putc('\n');
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
if (nand_info[i].name)
- printf("Device %d: %s, sector size %u KiB\n",
- i, nand_info[i].name,
- nand_info[i].erasesize >> 10);
+ nand_print_info(i);
}
return 0;
}
@@ -243,12 +252,12 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
if (strcmp(cmd, "device") == 0) {
if (argc < 3) {
+ putc('\n');
if ((nand_curr_device < 0) ||
(nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE))
- puts("\nno devices available\n");
+ puts("no devices available\n");
else
- printf("\nDevice %d: %s\n", nand_curr_device,
- nand_info[nand_curr_device].name);
+ nand_print_info(nand_curr_device);
return 0;
}
dev = (int)simple_strtoul(argv[2], NULL, 10);
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 1a1d8c4..7cb99cb 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -31,26 +31,59 @@ static void fsl_upm_end_pattern(struct fsl_upm *upm)
eieio();
}
-static void fsl_upm_run_pattern(struct fsl_upm *upm, int width, u32 cmd)
+static void fsl_upm_run_pattern(struct fsl_upm *upm, int width,
+ void __iomem *io_addr, u32 mar)
{
- out_be32(upm->mar, cmd << (32 - width));
+ out_be32(upm->mar, mar);
switch (width) {
case 8:
- out_8(upm->io_addr, 0x0);
+ out_8(io_addr, 0x0);
break;
case 16:
- out_be16(upm->io_addr, 0x0);
+ out_be16(io_addr, 0x0);
break;
case 32:
- out_be32(upm->io_addr, 0x0);
+ out_be32(io_addr, 0x0);
break;
}
}
+static void fun_wait(struct fsl_upm_nand *fun)
+{
+ if (fun->dev_ready) {
+ while (!fun->dev_ready(fun->chip_nr))
+ debug("unexpected busy state\n");
+ } else {
+ /*
+ * If the R/B pin is not connected, like on the TQM8548,
+ * a short delay is necessary.
+ */
+ udelay(1);
+ }
+}
+
+#if CONFIG_SYS_NAND_MAX_CHIPS > 1
+static void fun_select_chip(struct mtd_info *mtd, int chip_nr)
+{
+ struct nand_chip *chip = mtd->priv;
+ struct fsl_upm_nand *fun = chip->priv;
+
+ if (chip_nr >= 0) {
+ fun->chip_nr = chip_nr;
+ chip->IO_ADDR_R = chip->IO_ADDR_W =
+ fun->upm.io_addr + fun->chip_offset * chip_nr;
+ } else if (chip_nr == -1) {
+ chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
+ }
+}
+#endif
+
static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *chip = mtd->priv;
struct fsl_upm_nand *fun = chip->priv;
+ void __iomem *io_addr;
+ u32 mar;
if (!(ctrl & fun->last_ctrl)) {
fsl_upm_end_pattern(&fun->upm);
@@ -68,18 +101,25 @@ static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
fsl_upm_start_pattern(&fun->upm, fun->upm_cmd_offset);
}
- fsl_upm_run_pattern(&fun->upm, fun->width, cmd);
+ mar = cmd << (32 - fun->width);
+ io_addr = fun->upm.io_addr;
+#if CONFIG_SYS_NAND_MAX_CHIPS > 1
+ if (fun->chip_nr > 0) {
+ io_addr += fun->chip_offset * fun->chip_nr;
+ if (fun->upm_mar_chip_offset)
+ mar |= fun->upm_mar_chip_offset * fun->chip_nr;
+ }
+#endif
+ fsl_upm_run_pattern(&fun->upm, fun->width, io_addr, mar);
/*
- * Some boards/chips needs this. At least on MPC8360E-RDK we
- * need it. Probably weird chip, because I don't see any need
- * for this on MPC8555E + Samsung K9F1G08U0A. Usually here are
- * 0-2 unexpected busy states per block read.
+ * Some boards/chips needs this. At least the MPC8360E-RDK and
+ * TQM8548 need it. Probably weird chip, because I don't see
+ * any need for this on MPC8555E + Samsung K9F1G08U0A. Usually
+ * here are 0-2 unexpected busy states per block read.
*/
- if (fun->wait_pattern) {
- while (!fun->dev_ready())
- debug("unexpected busy state\n");
- }
+ if (fun->wait_flags & FSL_UPM_WAIT_RUN_PATTERN)
+ fun_wait(fun);
}
static u8 nand_read_byte(struct mtd_info *mtd)
@@ -93,9 +133,16 @@ static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
{
int i;
struct nand_chip *chip = mtd->priv;
+ struct fsl_upm_nand *fun = chip->priv;
- for (i = 0; i < len; i++)
+ for (i = 0; i < len; i++) {
out_8(chip->IO_ADDR_W, buf[i]);
+ if (fun->wait_flags & FSL_UPM_WAIT_WRITE_BYTE)
+ fun_wait(fun);
+ }
+
+ if (fun->wait_flags & FSL_UPM_WAIT_WRITE_BUFFER)
+ fun_wait(fun);
}
static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
@@ -125,7 +172,7 @@ static int nand_dev_ready(struct mtd_info *mtd)
struct nand_chip *chip = mtd->priv;
struct fsl_upm_nand *fun = chip->priv;
- return fun->dev_ready();
+ return fun->dev_ready(fun->chip_nr);
}
int fsl_upm_nand_init(struct nand_chip *chip, struct fsl_upm_nand *fun)
@@ -139,6 +186,9 @@ int fsl_upm_nand_init(struct nand_chip *chip, struct fsl_upm_nand *fun)
chip->chip_delay = fun->chip_delay;
chip->ecc.mode = NAND_ECC_SOFT;
chip->cmd_ctrl = fun_cmd_ctrl;
+#if CONFIG_SYS_NAND_MAX_CHIPS > 1
+ chip->select_chip = fun_select_chip;
+#endif
chip->read_byte = nand_read_byte;
chip->read_buf = nand_read_buf;
chip->write_buf = nand_write_buf;
diff --git a/drivers/mtd/nand/nand.c b/drivers/mtd/nand/nand.c
index 70b605f..9d83794 100644
--- a/drivers/mtd/nand/nand.c
+++ b/drivers/mtd/nand/nand.c
@@ -41,11 +41,15 @@ static const char default_nand_name[] = "nand";
static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand,
ulong base_addr)
{
+ int maxchips = CONFIG_SYS_NAND_MAX_CHIPS;
+
+ if (maxchips < 1)
+ maxchips = 1;
mtd->priv = nand;
nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr;
if (board_nand_init(nand) == 0) {
- if (nand_scan(mtd, 1) == 0) {
+ if (nand_scan(mtd, maxchips) == 0) {
if (!mtd->name)
mtd->name = (char *)default_nand_name;
else
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index d33fee2..e6ac859 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2652,8 +2652,10 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips)
type->id != chip->read_byte(mtd))
break;
}
+#ifdef DEBUG
if (i > 1)
printk(KERN_INFO "%d NAND chips detected\n", i);
+#endif
/* Store the number of chips and calc total size for mtd */
chip->numchips = i;
diff --git a/include/configs/TQM85xx.h b/include/configs/TQM85xx.h
index 72db26c..2ef24cd 100644
--- a/include/configs/TQM85xx.h
+++ b/include/configs/TQM85xx.h
@@ -371,35 +371,17 @@
#define CONFIG_SYS_NAND_CS_DIST 0x200
#define CONFIG_SYS_NAND_SIZE 0x8000
-#define CONFIG_SYS_NAND0_BASE (CONFIG_SYS_CCSRBAR + 0x03010000)
-#define CONFIG_SYS_NAND1_BASE (CONFIG_SYS_NAND0_BASE + CONFIG_SYS_NAND_CS_DIST)
-#define CONFIG_SYS_NAND2_BASE (CONFIG_SYS_NAND1_BASE + CONFIG_SYS_NAND_CS_DIST)
-#define CONFIG_SYS_NAND3_BASE (CONFIG_SYS_NAND2_BASE + CONFIG_SYS_NAND_CS_DIST)
-
-#define CONFIG_SYS_MAX_NAND_DEVICE 2 /* Max number of NAND devices */
-
-#if (CONFIG_SYS_MAX_NAND_DEVICE == 1)
-#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND0_BASE }
-#elif (CONFIG_SYS_MAX_NAND_DEVICE == 2)
-#define CONFIG_SYS_NAND_QUIET_TEST 1
-#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND0_BASE, \
- CONFIG_SYS_NAND1_BASE, \
-}
-#elif (CONFIG_SYS_MAX_NAND_DEVICE == 4)
-#define CONFIG_SYS_NAND_QUIET_TEST 1
-#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND0_BASE, \
- CONFIG_SYS_NAND1_BASE, \
- CONFIG_SYS_NAND2_BASE, \
- CONFIG_SYS_NAND3_BASE, \
-}
-#endif
+#define CONFIG_SYS_NAND_BASE (CONFIG_SYS_CCSRBAR + 0x03010000)
+
+#define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND devices */
+#define CONFIG_SYS_NAND_MAX_CHIPS 2 /* Number of chips per device */
/* CS3 for NAND Flash */
-#define CONFIG_SYS_BR3_PRELIM ((CONFIG_SYS_NAND0_BASE & BR_BA) | BR_PS_8 | \
- BR_MS_UPMB | BR_V)
+#define CONFIG_SYS_BR3_PRELIM ((CONFIG_SYS_NAND_BASE & BR_BA) | \
+ BR_PS_8 | BR_MS_UPMB | BR_V)
#define CONFIG_SYS_OR3_PRELIM (P2SZ_TO_AM(CONFIG_SYS_NAND_SIZE) | OR_UPM_BI)
-#define NAND_BIG_DELAY_US 25 /* max tR for Samsung devices */
+#define NAND_BIG_DELAY_US 25 /* max tR for Samsung devices */
#endif /* CONFIG_NAND */
diff --git a/include/linux/mtd/fsl_upm.h b/include/linux/mtd/fsl_upm.h
index 638a4e4..5d7156f 100644
--- a/include/linux/mtd/fsl_upm.h
+++ b/include/linux/mtd/fsl_upm.h
@@ -15,6 +15,10 @@
#include <linux/mtd/nand.h>
+#define FSL_UPM_WAIT_RUN_PATTERN 0x1
+#define FSL_UPM_WAIT_WRITE_BYTE 0x2
+#define FSL_UPM_WAIT_WRITE_BUFFER 0x4
+
struct fsl_upm {
void __iomem *mdr;
void __iomem *mxmr;
@@ -28,9 +32,12 @@ struct fsl_upm_nand {
int width;
int upm_cmd_offset;
int upm_addr_offset;
- int wait_pattern;
- int (*dev_ready)(void);
+ int upm_mar_chip_offset;
+ int wait_flags;
+ int (*dev_ready)(int chip_nr);
int chip_delay;
+ int chip_offset;
+ int chip_nr;
/* no need to fill */
int last_ctrl;
diff --git a/onenand_ipl/onenand_boot.c b/onenand_ipl/onenand_boot.c
index aff62d2..86428cc 100644
--- a/onenand_ipl/onenand_boot.c
+++ b/onenand_ipl/onenand_boot.c
@@ -28,46 +28,16 @@
#include "onenand_ipl.h"
-#ifdef CONFIG_SYS_PRINTF
-int print_info(void)
-{
- printf(XLOADER_VERSION);
-
- return 0;
-}
-#endif
-
typedef int (init_fnc_t)(void);
-init_fnc_t *init_sequence[] = {
- board_init, /* basic board dependent setup */
-#ifdef CONFIG_SYS_PRINTF
- serial_init, /* serial communications setup */
- print_info,
-#endif
- NULL,
-};
-
void start_oneboot(void)
{
- init_fnc_t **init_fnc_ptr;
uchar *buf;
- for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
- if ((*init_fnc_ptr)() != 0)
- hang();
- }
-
buf = (uchar *) CONFIG_SYS_LOAD_ADDR;
- if (!onenand_read_block0(buf))
- buf += ONENAND_BLOCK_SIZE;
-
- if (buf == (uchar *)CONFIG_SYS_LOAD_ADDR)
- hang();
+ onenand_read_block0(buf);
- /* go run U-Boot and never return */
- printf("Starting OS Bootloader...\n");
((init_fnc_t *)CONFIG_SYS_LOAD_ADDR)();
/* should never come here */
@@ -75,7 +45,5 @@ void start_oneboot(void)
void hang(void)
{
- /* if board_hang() returns, hange here */
- printf("X-Loader hangs\n");
- for (;;);
+ for (;;);
}
diff --git a/onenand_ipl/onenand_ipl.h b/onenand_ipl/onenand_ipl.h
index 3387998..57e54f5 100644
--- a/onenand_ipl/onenand_ipl.h
+++ b/onenand_ipl/onenand_ipl.h
@@ -23,12 +23,6 @@
#include <linux/mtd/onenand_regs.h>
-#define ONENAND_BLOCK_SIZE 2048
-
-#ifndef CONFIG_SYS_PRINTF
-#define printf(format, args...)
-#endif
-
#define onenand_readw(a) readw(a)
#define onenand_writew(v, a) writew(v, a)