U-Boot
Threads by month
- ----- 2025 -----
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2000 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
August 2008
- 172 participants
- 523 discussions
Recently the YAFFS filesystem support has been added to U-boot.
However, just enabling CONFIG_YAFFS2 is not enough to get it working.
ymount will generate an exception (when dereferencing mtd->readoob()), because
the genericDevice is a null pointer. Further, a lot of logging is produced
while using YAFFS fs, so logging should also be disabled.
Both issues are solved by this patch.
With this patch and CONFIG_YAFFS2 enabled, I get a readable filesystem
in U-boot, as well as in Linux.
Tested on a Atmel AT91SAM9261EK board.
Signed-off-by: Remy Bohmer <linux(a)bohmer.net>
---
fs/yaffs2/yaffscfg.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
Index: u-boot-git/fs/yaffs2/yaffscfg.c
===================================================================
--- u-boot-git.orig/fs/yaffs2/yaffscfg.c 2008-08-20 20:40:37.000000000 +0200
+++ u-boot-git/fs/yaffs2/yaffscfg.c 2008-08-20 20:41:42.000000000 +0200
@@ -34,7 +34,7 @@
#include "malloc.h"
#endif
-unsigned yaffs_traceMask = 0xFFFFFFFF;
+unsigned yaffs_traceMask = 0x0; /* Disable logging */
static int yaffs_errno = 0;
void yaffsfs_SetError(int err)
@@ -121,6 +121,9 @@ int yaffs_StartUp(void)
yaffs_Device *flashDev = calloc(1, sizeof(yaffs_Device));
yaffsfs_config[0].dev = flashDev;
+ /* store the mtd device for later use */
+ flashDev->genericDevice = mtd;
+
// Stuff to configure YAFFS
// Stuff to initialise anything special (eg lock semaphore).
yaffsfs_LocalInitialisation();
--
3
3

[U-Boot] [PATCH] Fix OneNAND read_oob/write_oob functions compatability (take #2)
by Kyungmin Park 21 Aug '08
by Kyungmin Park 21 Aug '08
21 Aug '08
Also sync with kernel OneNAND codes with adrian contribution credits
Signed-off-by: Kyungmin Park <kyungmin.park(a)samsung.com>
---
diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c
index 5e2062b..8d87b78 100644
--- a/common/cmd_onenand.c
+++ b/common/cmd_onenand.c
@@ -85,15 +85,25 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
ulong addr = simple_strtoul(argv[2], NULL, 16);
ulong ofs = simple_strtoul(argv[3], NULL, 16);
size_t len = simple_strtoul(argv[4], NULL, 16);
- size_t retlen = 0;
int oob = strncmp(argv[1], "read.oob", 8) ? 0 : 1;
+ struct mtd_oob_ops ops;
+
+ ops.mode = MTD_OOB_PLACE;
+
+ if (oob) {
+ ops.len = 0;
+ ops.datbuf = NULL;
+ ops.ooblen = len;
+ ops.oobbuf = (u_char *) addr;
+ } else {
+ ops.len = len;
+ ops.datbuf = (u_char *) addr;
+ ops.ooblen = 0;
+ ops.oobbuf = NULL;
+ }
+ ops.retlen = ops.oobretlen = 0;
- if (oob)
- onenand_read_oob(&onenand_mtd, ofs, len,
- &retlen, (u_char *) addr);
- else
- onenand_read(&onenand_mtd, ofs, len, &retlen,
- (u_char *) addr);
+ onenand_mtd.read_oob(&onenand_mtd, ofs, &ops);
printf("Done\n");
return 0;
@@ -117,9 +127,12 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
ulong block = simple_strtoul(argv[3], NULL, 10);
ulong page = simple_strtoul(argv[4], NULL, 10);
size_t len = simple_strtol(argv[5], NULL, 10);
- size_t retlen = 0;
ulong ofs;
int oob = strncmp(argv[1], "block.oob", 9) ? 0 : 1;
+ struct mtd_oob_ops ops;
+
+ ops.mode = MTD_OOB_PLACE;
+
ofs = block << onenand_chip.erase_shift;
if (page)
@@ -127,17 +140,21 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
if (!len) {
if (oob)
- len = 64;
+ ops.ooblen = 64;
else
- len = 512;
+ ops.len = 512;
+ }
+
+ if (oob) {
+ ops.datbuf = NULL;
+ ops.oobbuf = (u_char *) addr;
+ } else {
+ ops.datbuf = (u_char *) addr;
+ ops.oobbuf = NULL;
}
+ ops.retlen = ops.oobretlen = 0;
- if (oob)
- onenand_read_oob(&onenand_mtd, ofs, len,
- &retlen, (u_char *) addr);
- else
- onenand_read(&onenand_mtd, ofs, len, &retlen,
- (u_char *) addr);
+ onenand_read_oob(&onenand_mtd, ofs, &ops);
return 0;
}
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 9ce68e1..67901bb 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -4,6 +4,11 @@
* Copyright (C) 2005-2007 Samsung Electronics
* Kyungmin Park <kyungmin.park(a)samsung.com>
*
+ * Credits:
+ * Adrian Hunter <ext-adrian.hunter(a)nokia.com>:
+ * auto-placement support, read-while load support, various fixes
+ * Copyright (C) Nokia Corporation, 2007
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
@@ -526,83 +531,269 @@ static void onenand_release_device(struct mtd_info *mtd)
}
/**
- * onenand_read_ecc - [MTD Interface] Read data with ECC
+ * onenand_transfer_auto_oob - [Internal] oob auto-placement transfer
+ * @param mtd MTD device structure
+ * @param buf destination address
+ * @param column oob offset to read from
+ * @param thislen oob length to read
+ */
+static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf,
+ int column, int thislen)
+{
+ struct onenand_chip *this = mtd->priv;
+ struct nand_oobfree *free;
+ int readcol = column;
+ int readend = column + thislen;
+ int lastgap = 0;
+ unsigned int i;
+ uint8_t *oob_buf = this->oob_buf;
+
+ free = this->ecclayout->oobfree;
+ for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
+ if (readcol >= lastgap)
+ readcol += free->offset - lastgap;
+ if (readend >= lastgap)
+ readend += free->offset - lastgap;
+ lastgap = free->offset + free->length;
+ }
+ this->read_bufferram(mtd, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize);
+ free = this->ecclayout->oobfree;
+ for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
+ int free_end = free->offset + free->length;
+ if (free->offset < readend && free_end > readcol) {
+ int st = max_t(int,free->offset,readcol);
+ int ed = min_t(int,free_end,readend);
+ int n = ed - st;
+ memcpy(buf, oob_buf + st, n);
+ buf += n;
+ } else if (column == 0)
+ break;
+ }
+ return 0;
+}
+
+/**
+ * onenand_read_ops_nolock - [OneNAND Interface] OneNAND read main and/or out-of-band
* @param mtd MTD device structure
* @param from offset to read from
- * @param len number of bytes to read
- * @param retlen pointer to variable to store the number of read bytes
- * @param buf the databuffer to put data
- * @param oob_buf filesystem supplied oob data buffer
- * @param oobsel oob selection structure
+ * @param ops oob operation description structure
*
- * OneNAND read with ECC
+ * OneNAND read main and/or out-of-band data
*/
-static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
- size_t * retlen, u_char * buf,
- u_char * oob_buf, struct nand_oobinfo *oobsel)
+static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
+ struct mtd_oob_ops *ops)
{
struct onenand_chip *this = mtd->priv;
- int read = 0, column;
- int thislen;
- int ret = 0;
+ struct mtd_ecc_stats stats;
+ size_t len = ops->len;
+ size_t ooblen = ops->ooblen;
+ u_char *buf = ops->datbuf;
+ u_char *oobbuf = ops->oobbuf;
+ int read = 0, column, thislen;
+ int oobread = 0, oobcolumn, thisooblen, oobsize;
+ int ret = 0, boundary = 0;
+ int writesize = this->writesize;
+
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_read_ops_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
+
+ if (ops->mode == MTD_OOB_AUTO)
+ oobsize = this->ecclayout->oobavail;
+ else
+ oobsize = mtd->oobsize;
- MTDDEBUG (MTD_DEBUG_LEVEL3, "onenand_read_ecc: "
- "from = 0x%08x, len = %i\n",
- (unsigned int)from, (int)len);
+ oobcolumn = from & (mtd->oobsize - 1);
/* Do not allow reads past end of device */
if ((from + len) > mtd->size) {
- MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_read_ecc: "
- "Attempt read beyond end of device\n");
- *retlen = 0;
+ printk(KERN_ERR "onenand_read_ops_nolock: Attempt read beyond end of device\n");
+ ops->retlen = 0;
+ ops->oobretlen = 0;
return -EINVAL;
}
- /* Grab the lock and see if the device is available */
- onenand_get_device(mtd, FL_READING);
+ stats = mtd->ecc_stats;
- while (read < len) {
- thislen = min_t(int, mtd->writesize, len - read);
-
- column = from & (mtd->writesize - 1);
- if (column + thislen > mtd->writesize)
- thislen = mtd->writesize - column;
+ /* Read-while-load method */
+ /* Do first load to bufferRAM */
+ if (read < len) {
if (!onenand_check_bufferram(mtd, from)) {
- this->command(mtd, ONENAND_CMD_READ, from,
- mtd->writesize);
+ this->command(mtd, ONENAND_CMD_READ, from, writesize);
ret = this->wait(mtd, FL_READING);
- /* First copy data and check return value for ECC handling */
- onenand_update_bufferram(mtd, from, 1);
+ onenand_update_bufferram(mtd, from, !ret);
+ if (ret == -EBADMSG)
+ ret = 0;
}
+ }
- this->read_bufferram(mtd, ONENAND_DATARAM, buf, column,
- thislen);
+ thislen = min_t(int, writesize, len - read);
+ column = from & (writesize - 1);
+ if (column + thislen > writesize)
+ thislen = writesize - column;
- read += thislen;
- if (read == len)
- break;
+ while (!ret) {
+ /* If there is more to load then start next load */
+ from += thislen;
+ if (read + thislen < len) {
+ this->command(mtd, ONENAND_CMD_READ, from, writesize);
+ /*
+ * Chip boundary handling in DDP
+ * Now we issued chip 1 read and pointed chip 1
+ * bufferam so we have to point chip 0 bufferam.
+ */
+ if (ONENAND_IS_DDP(this) &&
+ unlikely(from == (this->chipsize >> 1))) {
+ this->write_word(ONENAND_DDP_CHIP0, this->base + ONENAND_REG_START_ADDRESS2);
+ boundary = 1;
+ } else
+ boundary = 0;
+ ONENAND_SET_PREV_BUFFERRAM(this);
+ }
- if (ret) {
- MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_read_ecc: read failed = %d\n", ret);
- break;
+ /* While load is going, read from last bufferRAM */
+ this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen);
+
+ /* Read oob area if needed */
+ if (oobbuf) {
+ thisooblen = oobsize - oobcolumn;
+ thisooblen = min_t(int, thisooblen, ooblen - oobread);
+
+ if (ops->mode == MTD_OOB_AUTO)
+ onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen);
+ else
+ this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen);
+ oobread += thisooblen;
+ oobbuf += thisooblen;
+ oobcolumn = 0;
}
- from += thislen;
+ /* See if we are done */
+ read += thislen;
+ if (read == len)
+ break;
+ /* Set up for next read from bufferRAM */
+ if (unlikely(boundary))
+ this->write_word(ONENAND_DDP_CHIP1, this->base + ONENAND_REG_START_ADDRESS2);
+ ONENAND_SET_NEXT_BUFFERRAM(this);
buf += thislen;
- }
+ thislen = min_t(int, writesize, len - read);
+ column = 0;
- /* Deselect and wake up anyone waiting on the device */
- onenand_release_device(mtd);
+ /* Now wait for load */
+ ret = this->wait(mtd, FL_READING);
+ onenand_update_bufferram(mtd, from, !ret);
+ if (ret == -EBADMSG)
+ ret = 0;
+ }
/*
* Return success, if no ECC failures, else -EBADMSG
* fs driver will take care of that, because
* retlen == desired len and result == -EBADMSG
*/
- *retlen = read;
- return ret;
+ ops->retlen = read;
+ ops->oobretlen = oobread;
+
+ if (ret)
+ return ret;
+
+ if (mtd->ecc_stats.failed - stats.failed)
+ return -EBADMSG;
+
+ return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
+}
+
+/**
+ * onenand_read_oob_nolock - [MTD Interface] OneNAND read out-of-band
+ * @param mtd MTD device structure
+ * @param from offset to read from
+ * @param ops oob operation description structure
+ *
+ * OneNAND read out-of-band data from the spare area
+ */
+static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
+ struct mtd_oob_ops *ops)
+{
+ struct onenand_chip *this = mtd->priv;
+ struct mtd_ecc_stats stats;
+ int read = 0, thislen, column, oobsize;
+ size_t len = ops->ooblen;
+ mtd_oob_mode_t mode = ops->mode;
+ u_char *buf = ops->oobbuf;
+ int ret = 0;
+
+ from += ops->ooboffs;
+
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_read_oob_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
+
+ /* Initialize return length value */
+ ops->oobretlen = 0;
+
+ if (mode == MTD_OOB_AUTO)
+ oobsize = this->ecclayout->oobavail;
+ else
+ oobsize = mtd->oobsize;
+
+ column = from & (mtd->oobsize - 1);
+
+ if (unlikely(column >= oobsize)) {
+ printk(KERN_ERR "onenand_read_oob_nolock: Attempted to start read outside oob\n");
+ return -EINVAL;
+ }
+
+ /* Do not allow reads past end of device */
+ if (unlikely(from >= mtd->size ||
+ column + len > ((mtd->size >> this->page_shift) -
+ (from >> this->page_shift)) * oobsize)) {
+ printk(KERN_ERR "onenand_read_oob_nolock: Attempted to read beyond end of device\n");
+ return -EINVAL;
+ }
+
+ stats = mtd->ecc_stats;
+
+ while (read < len) {
+ thislen = oobsize - column;
+ thislen = min_t(int, thislen, len);
+
+ this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize);
+
+ onenand_update_bufferram(mtd, from, 0);
+
+ ret = this->wait(mtd, FL_READING);
+ if (ret && ret != -EBADMSG) {
+ printk(KERN_ERR "onenand_read_oob_nolock: read failed = 0x%x\n", ret);
+ break;
+ }
+
+ if (mode == MTD_OOB_AUTO)
+ onenand_transfer_auto_oob(mtd, buf, column, thislen);
+ else
+ this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
+
+ read += thislen;
+
+ if (read == len)
+ break;
+
+ buf += thislen;
+
+ /* Read more? */
+ if (read < len) {
+ /* Page size */
+ from += mtd->writesize;
+ column = 0;
+ }
+ }
+
+ ops->oobretlen = read;
+
+ if (ret)
+ return ret;
+
+ if (mtd->ecc_stats.failed - stats.failed)
+ return -EBADMSG;
+
+ return 0;
}
/**
@@ -618,38 +809,124 @@ static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t * retlen, u_char * buf)
{
- return onenand_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);
+ struct mtd_oob_ops ops = {
+ .len = len,
+ .ooblen = 0,
+ .datbuf = buf,
+ .oobbuf = NULL,
+ };
+ int ret;
+
+ onenand_get_device(mtd, FL_READING);
+ ret = onenand_read_ops_nolock(mtd, from, &ops);
+ onenand_release_device(mtd);
+
+ *retlen = ops.retlen;
+ return ret;
}
/**
* onenand_read_oob - [MTD Interface] OneNAND read out-of-band
* @param mtd MTD device structure
* @param from offset to read from
- * @param len number of bytes to read
- * @param retlen pointer to variable to store the number of read bytes
- * @param buf the databuffer to put data
+ * @param ops oob operations description structure
*
- * OneNAND read out-of-band data from the spare area
+ * OneNAND main and/or out-of-band
*/
-int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
- size_t * retlen, u_char * buf)
+int onenand_read_oob(struct mtd_info *mtd, loff_t from,
+ struct mtd_oob_ops *ops)
+{
+ int ret;
+
+ switch (ops->mode) {
+ case MTD_OOB_PLACE:
+ case MTD_OOB_AUTO:
+ break;
+ case MTD_OOB_RAW:
+ /* Not implemented yet */
+ default:
+ return -EINVAL;
+ }
+
+ onenand_get_device(mtd, FL_READING);
+ if (ops->datbuf)
+ ret = onenand_read_ops_nolock(mtd, from, ops);
+ else
+ ret = onenand_read_oob_nolock(mtd, from, ops);
+ onenand_release_device(mtd);
+
+ return ret;
+}
+
+/**
+ * onenand_bbt_wait - [DEFAULT] wait until the command is done
+ * @param mtd MTD device structure
+ * @param state state to select the max. timeout value
+ *
+ * Wait for command done.
+ */
+static int onenand_bbt_wait(struct mtd_info *mtd, int state)
+{
+ struct onenand_chip *this = mtd->priv;
+ unsigned int flags = ONENAND_INT_MASTER;
+ unsigned int interrupt;
+ unsigned int ctrl;
+
+ while (1) {
+ interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
+ if (interrupt & flags)
+ break;
+ }
+
+ /* To get correct interrupt status in timeout case */
+ interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
+ ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
+
+ /* Initial bad block case: 0x2400 or 0x0400 */
+ if (ctrl & ONENAND_CTRL_ERROR) {
+ printk(KERN_DEBUG "onenand_bbt_wait: controller error = 0x%04x\n", ctrl);
+ return ONENAND_BBT_READ_ERROR;
+ }
+
+ if (interrupt & ONENAND_INT_READ) {
+ int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
+ if (ecc & ONENAND_ECC_2BIT_ALL)
+ return ONENAND_BBT_READ_ERROR;
+ } else {
+ printk(KERN_ERR "onenand_bbt_wait: read timeout!"
+ "ctrl=0x%04x intr=0x%04x\n", ctrl, interrupt);
+ return ONENAND_BBT_READ_FATAL_ERROR;
+ }
+
+ return 0;
+}
+
+/**
+ * onenand_bbt_read_oob - [MTD Interface] OneNAND read out-of-band for bbt scan
+ * @param mtd MTD device structure
+ * @param from offset to read from
+ * @param ops oob operation description structure
+ *
+ * OneNAND read out-of-band data from the spare area for bbt scan
+ */
+int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
+ struct mtd_oob_ops *ops)
{
struct onenand_chip *this = mtd->priv;
int read = 0, thislen, column;
int ret = 0;
+ size_t len = ops->ooblen;
+ u_char *buf = ops->oobbuf;
- MTDDEBUG (MTD_DEBUG_LEVEL3, "onenand_read_oob: "
- "from = 0x%08x, len = %i\n",
- (unsigned int)from, (int)len);
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_bbt_read_oob: from = 0x%08x, len = %zi\n", (unsigned int) from, len);
- /* Initialize return length value */
- *retlen = 0;
+ /* Initialize return value */
+ ops->oobretlen = 0;
/* Do not allow reads past end of device */
if (unlikely((from + len) > mtd->size)) {
- MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_read_oob: "
- "Attempt read beyond end of device\n");
- return -EINVAL;
+ printk(KERN_ERR "onenand_bbt_read_oob: Attempt read beyond end of device\n");
+ return ONENAND_BBT_READ_FATAL_ERROR;
}
/* Grab the lock and see if the device is available */
@@ -658,6 +935,7 @@ int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
column = from & (mtd->oobsize - 1);
while (read < len) {
+
thislen = mtd->oobsize - column;
thislen = min_t(int, thislen, len);
@@ -665,27 +943,21 @@ int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
onenand_update_bufferram(mtd, from, 0);
- ret = this->wait(mtd, FL_READING);
- /* First copy data and check return value for ECC handling */
-
- this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column,
- thislen);
+ ret = onenand_bbt_wait(mtd, FL_READING);
+ if (ret)
+ break;
+ this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
read += thislen;
if (read == len)
break;
- if (ret) {
- MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_read_oob: read failed = %d\n", ret);
- break;
- }
-
buf += thislen;
+
/* Read more? */
if (read < len) {
- /* Page size */
- from += mtd->writesize;
+ /* Update Page size */
+ from += this->writesize;
column = 0;
}
}
@@ -693,224 +965,421 @@ int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
/* Deselect and wake up anyone waiting on the device */
onenand_release_device(mtd);
- *retlen = read;
+ ops->oobretlen = read;
return ret;
}
+
#ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE
/**
- * onenand_verify_page - [GENERIC] verify the chip contents after a write
- * @param mtd MTD device structure
- * @param buf the databuffer to verify
- *
- * Check DataRAM area directly
+ * onenand_verify_oob - [GENERIC] verify the oob contents after a write
+ * @param mtd MTD device structure
+ * @param buf the databuffer to verify
+ * @param to offset to read from
*/
-static int onenand_verify_page(struct mtd_info *mtd, u_char * buf,
- loff_t addr)
+static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to)
{
struct onenand_chip *this = mtd->priv;
- void __iomem *dataram0, *dataram1;
+ u_char *oob_buf = this->oob_buf;
+ int status, i;
+
+ this->command(mtd, ONENAND_CMD_READOOB, to, mtd->oobsize);
+ onenand_update_bufferram(mtd, to, 0);
+ status = this->wait(mtd, FL_READING);
+ if (status)
+ return status;
+
+ this->read_bufferram(mtd, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize);
+ for (i = 0; i < mtd->oobsize; i++)
+ if (buf[i] != 0xFF && buf[i] != oob_buf[i])
+ return -EBADMSG;
+
+ return 0;
+}
+
+/**
+ * onenand_verify - [GENERIC] verify the chip contents after a write
+ * @param mtd MTD device structure
+ * @param buf the databuffer to verify
+ * @param addr offset to read from
+ * @param len number of bytes to read and compare
+ */
+static int onenand_verify(struct mtd_info *mtd, const u_char *buf, loff_t addr, size_t len)
+{
+ struct onenand_chip *this = mtd->priv;
+ void __iomem *dataram;
int ret = 0;
+ int thislen, column;
- this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize);
+ while (len != 0) {
+ thislen = min_t(int, this->writesize, len);
+ column = addr & (this->writesize - 1);
+ if (column + thislen > this->writesize)
+ thislen = this->writesize - column;
- ret = this->wait(mtd, FL_READING);
- if (ret)
- return ret;
+ this->command(mtd, ONENAND_CMD_READ, addr, this->writesize);
- onenand_update_bufferram(mtd, addr, 1);
+ onenand_update_bufferram(mtd, addr, 0);
- /* Check, if the two dataram areas are same */
- dataram0 = this->base + ONENAND_DATARAM;
- dataram1 = dataram0 + mtd->writesize;
+ ret = this->wait(mtd, FL_READING);
+ if (ret)
+ return ret;
- if (memcmp(dataram0, dataram1, mtd->writesize))
- return -EBADMSG;
+ onenand_update_bufferram(mtd, addr, 1);
+
+ dataram = this->base + ONENAND_DATARAM;
+ dataram += onenand_bufferram_offset(mtd, ONENAND_DATARAM);
+
+ if (memcmp(buf, dataram + column, thislen))
+ return -EBADMSG;
+
+ len -= thislen;
+ buf += thislen;
+ addr += thislen;
+ }
return 0;
}
#else
-#define onenand_verify_page(...) (0)
+#define onenand_verify(...) (0)
+#define onenand_verify_oob(...) (0)
#endif
#define NOTALIGNED(x) ((x & (mtd->writesize - 1)) != 0)
/**
- * onenand_write_ecc - [MTD Interface] OneNAND write with ECC
- * @param mtd MTD device structure
- * @param to offset to write to
- * @param len number of bytes to write
- * @param retlen pointer to variable to store the number of written bytes
- * @param buf the data to write
- * @param eccbuf filesystem supplied oob data buffer
- * @param oobsel oob selection structure
+ * onenand_fill_auto_oob - [Internal] oob auto-placement transfer
+ * @param mtd MTD device structure
+ * @param oob_buf oob buffer
+ * @param buf source address
+ * @param column oob offset to write to
+ * @param thislen oob length to write
+ */
+static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf,
+ const u_char *buf, int column, int thislen)
+{
+ struct onenand_chip *this = mtd->priv;
+ struct nand_oobfree *free;
+ int writecol = column;
+ int writeend = column + thislen;
+ int lastgap = 0;
+ unsigned int i;
+
+ free = this->ecclayout->oobfree;
+ for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
+ if (writecol >= lastgap)
+ writecol += free->offset - lastgap;
+ if (writeend >= lastgap)
+ writeend += free->offset - lastgap;
+ lastgap = free->offset + free->length;
+ }
+ free = this->ecclayout->oobfree;
+ for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
+ int free_end = free->offset + free->length;
+ if (free->offset < writeend && free_end > writecol) {
+ int st = max_t(int,free->offset,writecol);
+ int ed = min_t(int,free_end,writeend);
+ int n = ed - st;
+ memcpy(oob_buf + st, buf, n);
+ buf += n;
+ } else if (column == 0)
+ break;
+ }
+ return 0;
+}
+
+/**
+ * onenand_write_ops_nolock - [OneNAND Interface] write main and/or out-of-band
+ * @param mtd MTD device structure
+ * @param to offset to write to
+ * @param ops oob operation description structure
*
- * OneNAND write with ECC
+ * Write main and/or oob with ECC
*/
-static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
- size_t * retlen, const u_char * buf,
- u_char * eccbuf, struct nand_oobinfo *oobsel)
+static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
+ struct mtd_oob_ops *ops)
{
struct onenand_chip *this = mtd->priv;
- int written = 0;
+ int written = 0, column, thislen, subpage;
+ int oobwritten = 0, oobcolumn, thisooblen, oobsize;
+ size_t len = ops->len;
+ size_t ooblen = ops->ooblen;
+ const u_char *buf = ops->datbuf;
+ const u_char *oob = ops->oobbuf;
+ u_char *oobbuf;
int ret = 0;
- MTDDEBUG (MTD_DEBUG_LEVEL3, "onenand_write_ecc: "
- "to = 0x%08x, len = %i\n",
- (unsigned int)to, (int)len);
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_write_ops_nolock: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
/* Initialize retlen, in case of early exit */
- *retlen = 0;
+ ops->retlen = 0;
+ ops->oobretlen = 0;
/* Do not allow writes past end of device */
if (unlikely((to + len) > mtd->size)) {
- MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_write_ecc: "
- "Attempt write to past end of device\n");
+ printk(KERN_ERR "onenand_write_ops_nolock: Attempt write to past end of device\n");
return -EINVAL;
}
/* Reject writes, which are not page aligned */
- if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) {
- MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_write_ecc: "
- "Attempt to write not page aligned data\n");
+ if (unlikely(NOTALIGNED(to) || NOTALIGNED(len))) {
+ printk(KERN_ERR "onenand_write_ops_nolock: Attempt to write not page aligned data\n");
return -EINVAL;
}
- /* Grab the lock and see if the device is available */
- onenand_get_device(mtd, FL_WRITING);
+ if (ops->mode == MTD_OOB_AUTO)
+ oobsize = this->ecclayout->oobavail;
+ else
+ oobsize = mtd->oobsize;
+
+ oobcolumn = to & (mtd->oobsize - 1);
+
+ column = to & (mtd->writesize - 1);
/* Loop until all data write */
while (written < len) {
- int thislen = min_t(int, mtd->writesize, len - written);
+ u_char *wbuf = (u_char *) buf;
- this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->writesize);
+ thislen = min_t(int, mtd->writesize - column, len - written);
+ thisooblen = min_t(int, oobsize - oobcolumn, ooblen - oobwritten);
- this->write_bufferram(mtd, ONENAND_DATARAM, buf, 0, thislen);
- this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0,
- mtd->oobsize);
+ this->command(mtd, ONENAND_CMD_BUFFERRAM, to, thislen);
- this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);
+ /* Partial page write */
+ subpage = thislen < mtd->writesize;
+ if (subpage) {
+ memset(this->page_buf, 0xff, mtd->writesize);
+ memcpy(this->page_buf + column, buf, thislen);
+ wbuf = this->page_buf;
+ }
+
+ this->write_bufferram(mtd, ONENAND_DATARAM, wbuf, 0, mtd->writesize);
+
+ if (oob) {
+ oobbuf = this->oob_buf;
- onenand_update_bufferram(mtd, to, 1);
+ /* We send data to spare ram with oobsize
+ * * to prevent byte access */
+ memset(oobbuf, 0xff, mtd->oobsize);
+ if (ops->mode == MTD_OOB_AUTO)
+ onenand_fill_auto_oob(mtd, oobbuf, oob, oobcolumn, thisooblen);
+ else
+ memcpy(oobbuf + oobcolumn, oob, thisooblen);
+
+ oobwritten += thisooblen;
+ oob += thisooblen;
+ oobcolumn = 0;
+ } else
+ oobbuf = (u_char *) ffchars;
+
+ this->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize);
+
+ this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);
ret = this->wait(mtd, FL_WRITING);
+
+ /* In partial page write we don't update bufferram */
+ onenand_update_bufferram(mtd, to, !ret && !subpage);
+ if (ONENAND_IS_2PLANE(this)) {
+ ONENAND_SET_BUFFERRAM1(this);
+ onenand_update_bufferram(mtd, to + this->writesize, !ret && !subpage);
+ }
+
if (ret) {
- MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_write_ecc: write filaed %d\n", ret);
+ printk(KERN_ERR "onenand_write_ops_nolock: write filaed %d\n", ret);
break;
}
- written += thislen;
-
/* Only check verify write turn on */
- ret = onenand_verify_page(mtd, (u_char *) buf, to);
+ ret = onenand_verify(mtd, buf, to, thislen);
if (ret) {
- MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_write_ecc: verify failed %d\n", ret);
+ printk(KERN_ERR "onenand_write_ops_nolock: verify failed %d\n", ret);
break;
}
+ written += thislen;
+
if (written == len)
break;
+ column = 0;
to += thislen;
buf += thislen;
}
- /* Deselect and wake up anyone waiting on the device */
- onenand_release_device(mtd);
-
- *retlen = written;
+ ops->retlen = written;
return ret;
}
/**
- * onenand_write - [MTD Interface] compability function for onenand_write_ecc
- * @param mtd MTD device structure
- * @param to offset to write to
- * @param len number of bytes to write
- * @param retlen pointer to variable to store the number of written bytes
- * @param buf the data to write
- *
- * This function simply calls onenand_write_ecc
- * with oob buffer and oobsel = NULL
- */
-int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
- size_t * retlen, const u_char * buf)
-{
- return onenand_write_ecc(mtd, to, len, retlen, buf, NULL, NULL);
-}
-
-/**
- * onenand_write_oob - [MTD Interface] OneNAND write out-of-band
- * @param mtd MTD device structure
- * @param to offset to write to
- * @param len number of bytes to write
- * @param retlen pointer to variable to store the number of written bytes
- * @param buf the data to write
+ * onenand_write_oob_nolock - [Internal] OneNAND write out-of-band
+ * @param mtd MTD device structure
+ * @param to offset to write to
+ * @param len number of bytes to write
+ * @param retlen pointer to variable to store the number of written bytes
+ * @param buf the data to write
+ * @param mode operation mode
*
* OneNAND write out-of-band
*/
-int onenand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
- size_t * retlen, const u_char * buf)
+static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to,
+ struct mtd_oob_ops *ops)
{
struct onenand_chip *this = mtd->priv;
- int column, status;
+ int column, ret = 0, oobsize;
int written = 0;
+ u_char *oobbuf;
+ size_t len = ops->ooblen;
+ const u_char *buf = ops->oobbuf;
+ mtd_oob_mode_t mode = ops->mode;
- MTDDEBUG (MTD_DEBUG_LEVEL3, "onenand_write_oob: "
- "to = 0x%08x, len = %i\n",
- (unsigned int)to, (int)len);
+ to += ops->ooboffs;
+
+ MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob_nolock: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
/* Initialize retlen, in case of early exit */
- *retlen = 0;
+ ops->oobretlen = 0;
- /* Do not allow writes past end of device */
- if (unlikely((to + len) > mtd->size)) {
- MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_write_oob: "
- "Attempt write to past end of device\n");
+ if (mode == MTD_OOB_AUTO)
+ oobsize = this->ecclayout->oobavail;
+ else
+ oobsize = mtd->oobsize;
+
+ column = to & (mtd->oobsize - 1);
+
+ if (unlikely(column >= oobsize)) {
+ printk(KERN_ERR "onenand_write_oob_nolock: Attempted to start write outside oob\n");
return -EINVAL;
}
- /* Grab the lock and see if the device is available */
- onenand_get_device(mtd, FL_WRITING);
+ /* For compatibility with NAND: Do not allow write past end of page */
+ if (unlikely(column + len > oobsize)) {
+ printk(KERN_ERR "onenand_write_oob_nolock: "
+ "Attempt to write past end of page\n");
+ return -EINVAL;
+ }
+
+ /* Do not allow reads past end of device */
+ if (unlikely(to >= mtd->size ||
+ column + len > ((mtd->size >> this->page_shift) -
+ (to >> this->page_shift)) * oobsize)) {
+ printk(KERN_ERR "onenand_write_oob_nolock: Attempted to write past end of device\n");
+ return -EINVAL;
+ }
+
+ oobbuf = this->oob_buf;
/* Loop until all data write */
while (written < len) {
- int thislen = min_t(int, mtd->oobsize, len - written);
-
- column = to & (mtd->oobsize - 1);
+ int thislen = min_t(int, oobsize, len - written);
this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobsize);
- this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0,
- mtd->oobsize);
- this->write_bufferram(mtd, ONENAND_SPARERAM, buf, column,
- thislen);
+ /* We send data to spare ram with oobsize
+ * to prevent byte access */
+ memset(oobbuf, 0xff, mtd->oobsize);
+ if (mode == MTD_OOB_AUTO)
+ onenand_fill_auto_oob(mtd, oobbuf, buf, column, thislen);
+ else
+ memcpy(oobbuf + column, buf, thislen);
+ this->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize);
this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize);
onenand_update_bufferram(mtd, to, 0);
+ if (ONENAND_IS_2PLANE(this)) {
+ ONENAND_SET_BUFFERRAM1(this);
+ onenand_update_bufferram(mtd, to + this->writesize, 0);
+ }
- status = this->wait(mtd, FL_WRITING);
- if (status)
+ ret = this->wait(mtd, FL_WRITING);
+ if (ret) {
+ printk(KERN_ERR "onenand_write_oob_nolock: write failed %d\n", ret);
break;
+ }
+
+ ret = onenand_verify_oob(mtd, oobbuf, to);
+ if (ret) {
+ printk(KERN_ERR "onenand_write_oob_nolock: verify failed %d\n", ret);
+ break;
+ }
written += thislen;
if (written == len)
break;
- to += thislen;
+ to += mtd->writesize;
buf += thislen;
+ column = 0;
}
- /* Deselect and wake up anyone waiting on the device */
+ ops->oobretlen = written;
+
+ return ret;
+}
+
+/**
+ * onenand_write - [MTD Interface] compability function for onenand_write_ecc
+ * @param mtd MTD device structure
+ * @param to offset to write to
+ * @param len number of bytes to write
+ * @param retlen pointer to variable to store the number of written bytes
+ * @param buf the data to write
+ *
+ * Write with ECC
+ */
+int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t * retlen, const u_char * buf)
+{
+ struct mtd_oob_ops ops = {
+ .len = len,
+ .ooblen = 0,
+ .datbuf = (u_char *) buf,
+ .oobbuf = NULL,
+ };
+ int ret;
+
+ onenand_get_device(mtd, FL_WRITING);
+ ret = onenand_write_ops_nolock(mtd, to, &ops);
onenand_release_device(mtd);
- *retlen = written;
+ *retlen = ops.retlen;
+ return ret;
+}
+
+/**
+ * onenand_write_oob - [MTD Interface] OneNAND write out-of-band
+ * @param mtd MTD device structure
+ * @param to offset to write to
+ * @param ops oob operation description structure
+ *
+ * OneNAND write main and/or out-of-band
+ */
+int onenand_write_oob(struct mtd_info *mtd, loff_t to,
+ struct mtd_oob_ops *ops)
+{
+ int ret;
+
+ switch (ops->mode) {
+ case MTD_OOB_PLACE:
+ case MTD_OOB_AUTO:
+ break;
+ case MTD_OOB_RAW:
+ /* Not implemented yet */
+ default:
+ return -EINVAL;
+ }
+
+ onenand_get_device(mtd, FL_WRITING);
+ if (ops->datbuf)
+ ret = onenand_write_ops_nolock(mtd, to, ops);
+ else
+ ret = onenand_write_oob_nolock(mtd, to, ops);
+ onenand_release_device(mtd);
+
+ return ret;
- return 0;
}
/**
@@ -1277,6 +1746,8 @@ static int onenand_probe(struct mtd_info *mtd)
this->page_shift = ffs(mtd->writesize) - 1;
this->ppb_shift = (this->erase_shift - this->page_shift);
this->page_mask = (mtd->erasesize / mtd->writesize) - 1;
+ /* It's real page size */
+ this->writesize = mtd->writesize;
/* REVIST: Multichip handling */
@@ -1346,6 +1817,28 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
this->read_bufferram = onenand_sync_read_bufferram;
}
+ /* Allocate buffers, if necessary */
+ if (!this->page_buf) {
+ this->page_buf = kzalloc(mtd->writesize, GFP_KERNEL);
+ if (!this->page_buf) {
+ printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n");
+ return -ENOMEM;
+ }
+ this->options |= ONENAND_PAGEBUF_ALLOC;
+ }
+ if (!this->oob_buf) {
+ this->oob_buf = kzalloc(mtd->oobsize, GFP_KERNEL);
+ if (!this->oob_buf) {
+ printk(KERN_ERR "onenand_scan: Can't allocate oob_buf\n");
+ if (this->options & ONENAND_PAGEBUF_ALLOC) {
+ this->options &= ~ONENAND_PAGEBUF_ALLOC;
+ kfree(this->page_buf);
+ }
+ return -ENOMEM;
+ }
+ this->options |= ONENAND_OOBBUF_ALLOC;
+ }
+
onenand_unlock(mtd, 0, mtd->size);
return onenand_default_bbt(mtd);
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c
index d13d277..dde11ae 100644
--- a/drivers/mtd/onenand/onenand_bbt.c
+++ b/drivers/mtd/onenand/onenand_bbt.c
@@ -68,6 +68,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t * buf,
int startblock;
loff_t from;
size_t readlen, ooblen;
+ struct mtd_oob_ops ops;
printk(KERN_INFO "Scanning device for bad blocks\n");
@@ -85,25 +86,26 @@ static int create_bbt(struct mtd_info *mtd, uint8_t * buf,
startblock = 0;
from = 0;
+ ops.mode = MTD_OOB_PLACE;
+ ops.ooblen = readlen;
+ ops.oobbuf = buf;
+ ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
+
for (i = startblock; i < numblocks;) {
int ret;
for (j = 0; j < len; j++) {
- size_t retlen;
-
/* No need to read pages fully,
* just read required OOB bytes */
- ret = onenand_read_oob(mtd,
+ ret = onenand_bbt_read_oob(mtd,
from + j * mtd->writesize +
- bd->offs, readlen, &retlen,
- &buf[0]);
+ bd->offs, &ops);
- if (ret && ret != -EAGAIN) {
- printk("ret = %d\n", ret);
- return ret;
- }
+ /* If it is a initial bad block, just ignore it */
+ if (ret == ONENAND_BBT_READ_FATAL_ERROR)
+ return -EIO;
- if (check_short_pattern
+ if (ret || check_short_pattern
(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
printk(KERN_WARNING
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h
index bffb25b..abf8f1a 100644
--- a/include/linux/mtd/bbm.h
+++ b/include/linux/mtd/bbm.h
@@ -97,6 +97,13 @@ struct nand_bbt_descr {
*/
#define ONENAND_BADBLOCK_POS 0
+/*
+ * Bad block scanning errors
+ */
+#define ONENAND_BBT_READ_ERROR 1
+#define ONENAND_BBT_READ_ECC_ERROR 2
+#define ONENAND_BBT_READ_FATAL_ERROR 4
+
/**
* struct bbt_info - [GENERIC] Bad Block Table data structure
* @param bbt_erase_shift [INTERN] number of address bits in a bbt entry
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index 8a0fd0d..540d02d 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -75,6 +75,7 @@ struct onenand_chip {
unsigned int page_shift;
unsigned int ppb_shift; /* Pages per block shift */
unsigned int page_mask;
+ unsigned int writesize;
unsigned int bufferram_index;
struct onenand_bufferram bufferram[MAX_BUFFERRAM];
@@ -93,25 +94,43 @@ struct onenand_chip {
int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
int (*scan_bbt)(struct mtd_info *mtd);
+#if 0
spinlock_t chip_lock;
wait_queue_head_t wq;
+#endif
int state;
+ unsigned char *page_buf;
+ unsigned char *oob_buf;
struct nand_oobinfo *autooob;
+ struct nand_ecclayout *ecclayout;
void *bbm;
void *priv;
};
+/*
+ * Helper macros
+ */
#define ONENAND_CURRENT_BUFFERRAM(this) (this->bufferram_index)
#define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1)
#define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1)
+#define ONENAND_SET_PREV_BUFFERRAM(this) (this->bufferram_index ^= 1)
+#define ONENAND_SET_BUFFERRAM0(this) (this->bufferram_index = 0)
+#define ONENAND_SET_BUFFERRAM1(this) (this->bufferram_index = 1)
+
+#define ONENAND_IS_DDP(this) \
+ (this->device_id & ONENAND_DEVICE_IS_DDP)
+
+#define ONENAND_IS_2PLANE(this) (0)
/*
* Options bits
*/
#define ONENAND_CONT_LOCK (0x0001)
+#define ONENAND_PAGEBUF_ALLOC (0x1000)
+#define ONENAND_OOBBUF_ALLOC (0x2000)
/*
* OneNAND Flash Manufacturer ID Codes
@@ -129,4 +148,7 @@ struct onenand_manufacturers {
char *name;
};
+int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
+ struct mtd_oob_ops *ops);
+
#endif /* __LINUX_MTD_ONENAND_H */
diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h
index c8a9f3e..6a8aa28 100644
--- a/include/linux/mtd/onenand_regs.h
+++ b/include/linux/mtd/onenand_regs.h
@@ -83,6 +83,8 @@
* Start Address 1 F100h (R/W)
*/
#define ONENAND_DDP_SHIFT (15)
+#define ONENAND_DDP_CHIP0 (0)
+#define ONENAND_DDP_CHIP1 (1 << ONENAND_DDP_SHIFT)
/*
* Start Address 8 F107h (R/W)
diff --git a/include/onenand_uboot.h b/include/onenand_uboot.h
index 4260ee7..098b827 100644
--- a/include/onenand_uboot.h
+++ b/include/onenand_uboot.h
@@ -16,23 +16,16 @@
#include <linux/types.h>
-struct kvec {
- void *iov_base;
- size_t iov_len;
-};
-
-typedef int spinlock_t;
-typedef int wait_queue_head_t;
-
struct mtd_info;
struct erase_info;
+extern struct mtd_info onenand_mtd;
+
/* Functions */
extern void onenand_init(void);
extern int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t * retlen, u_char * buf);
-extern int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
- size_t * retlen, u_char * buf);
+extern int onenand_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops);
extern int onenand_write(struct mtd_info *mtd, loff_t from, size_t len,
size_t * retlen, const u_char * buf);
extern int onenand_erase(struct mtd_info *mtd, struct erase_info *instr);
2
1

[U-Boot] [PATCH v2] mpc52xx: added support for the MPC5200 based MUC.MC52 board from MAN.
by Heiko Schocher 21 Aug '08
by Heiko Schocher 21 Aug '08
21 Aug '08
Hello,
changes since last Patch:
- fixed Codingstyle issues
[PATCH] mpc52xx: added support for the MPC5200 based MUC.MC52
board from MAN.
Signed-off-by: Heiko Schocher <hs(a)denx.de>
---
MAINTAINERS | 1 +
Makefile | 3 +
board/mucmc52/Makefile | 53 ++++++
board/mucmc52/config.mk | 45 +++++
board/mucmc52/mucmc52.c | 400 +++++++++++++++++++++++++++++++++++++++++++++
cpu/mpc5xxx/fec.c | 6 +-
include/configs/mucmc52.h | 376 ++++++++++++++++++++++++++++++++++++++++++
7 files changed, 882 insertions(+), 2 deletions(-)
create mode 100644 board/mucmc52/Makefile
create mode 100644 board/mucmc52/config.mk
create mode 100644 board/mucmc52/mucmc52.c
create mode 100644 include/configs/mucmc52.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 323a3a6..892f2de 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -369,6 +369,7 @@ Heiko Schocher <hs(a)denx.de>
jupiter MPC5200
mgcoge MPC8247
mgsuvd MPC852
+ mucmc52 MPC5200
municse MPC5200
sc3 PPC405GP
uc101 MPC5200
diff --git a/Makefile b/Makefile
index 00ae9ca..091f53b 100644
--- a/Makefile
+++ b/Makefile
@@ -620,6 +620,9 @@ mecp5200_config: unconfig
motionpro_config: unconfig
@$(MKCONFIG) motionpro ppc mpc5xxx motionpro
+mucmc52_config: unconfig
+ @$(MKCONFIG) mucmc52 ppc mpc5xxx mucmc52
+
munices_config: unconfig
@$(MKCONFIG) munices ppc mpc5xxx munices
diff --git a/board/mucmc52/Makefile b/board/mucmc52/Makefile
new file mode 100644
index 0000000..721c016
--- /dev/null
+++ b/board/mucmc52/Makefile
@@ -0,0 +1,53 @@
+#
+# (C) Copyright 2008
+# Heiko Schocher, DENX Software Engineering, hs(a)denx.de.
+#
+# (C) Copyright 2003-2006
+# Wolfgang Denk, DENX Software Engineering, wd(a)denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(BOARD).a
+
+COBJS := $(BOARD).o
+
+SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+SOBJS := $(addprefix $(obj),$(SOBJS))
+
+$(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+clean:
+ rm -f $(SOBJS) $(OBJS)
+
+distclean: clean
+ rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/mucmc52/config.mk b/board/mucmc52/config.mk
new file mode 100644
index 0000000..90d9ce2
--- /dev/null
+++ b/board/mucmc52/config.mk
@@ -0,0 +1,45 @@
+#
+# (C) Copyright 2008
+# Heiko Schocher, DENX Software Engineering, hs(a)denx.de.
+#
+# (C) Copyright 2004
+# Wolfgang Denk, DENX Software Engineering, wd(a)denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+#
+# MUCMC52 board:
+#
+# Valid values for TEXT_BASE are:
+#
+# 0xFFE00000 boot high
+#
+# 0x00100000 boot from RAM (for testing only)
+#
+
+ifndef TEXT_BASE
+## Standard: boot high
+TEXT_BASE = 0xFFF00000
+## For testing: boot from RAM
+#TEXT_BASE = 0x00100000
+endif
+
+PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) -I$(TOPDIR)/board
+LDSCRIPT := $(SRCTREE)/cpu/mpc5xxx/u-boot.lds
diff --git a/board/mucmc52/mucmc52.c b/board/mucmc52/mucmc52.c
new file mode 100644
index 0000000..45f5f70
--- /dev/null
+++ b/board/mucmc52/mucmc52.c
@@ -0,0 +1,400 @@
+/*
+ * (C) Copyright 2003-2004
+ * Wolfgang Denk, DENX Software Engineering, wd(a)denx.de.
+ *
+ * (C) Copyright 2004
+ * Mark Jonas, Freescale Semiconductor, mark.jonas(a)motorola.com.
+ *
+ * (C) Copyright 2004
+ * Martin Krause, TQ-Systems GmbH, martin.krause(a)tqs.de
+ *
+ * (C) Copyright 2008
+ * Heiko Schocher, DENX Software Engineering, hs(a)denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc5xxx.h>
+#include <pci.h>
+#include <malloc.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+
+#ifndef CFG_RAMBOOT
+static void sdram_start (int hi_addr)
+{
+ long hi_addr_bit = hi_addr ? 0x01000000 : 0;
+
+ /* unlock mode register */
+ out_be32 ((unsigned __iomem *)MPC5XXX_SDRAM_CTRL,
+ (SDRAM_CONTROL | 0x80000000 | hi_addr_bit));
+ __asm__ volatile ("sync");
+
+ /* precharge all banks */
+ out_be32 ((unsigned __iomem *)MPC5XXX_SDRAM_CTRL,
+ (SDRAM_CONTROL | 0x80000002 | hi_addr_bit));
+ __asm__ volatile ("sync");
+
+#if SDRAM_DDR
+ /* set mode register: extended mode */
+ out_be32 ((unsigned __iomem *)MPC5XXX_SDRAM_MODE, (SDRAM_EMODE));
+ __asm__ volatile ("sync");
+
+ /* set mode register: reset DLL */
+ out_be32 ((unsigned __iomem *)MPC5XXX_SDRAM_MODE,
+ (SDRAM_MODE | 0x04000000));
+ __asm__ volatile ("sync");
+#endif
+
+ /* precharge all banks */
+ out_be32 ((unsigned __iomem *)MPC5XXX_SDRAM_CTRL,
+ (SDRAM_CONTROL | 0x80000002 | hi_addr_bit));
+ __asm__ volatile ("sync");
+
+ /* auto refresh */
+ out_be32 ((unsigned __iomem *)MPC5XXX_SDRAM_CTRL,
+ (SDRAM_CONTROL | 0x80000004 | hi_addr_bit));
+ __asm__ volatile ("sync");
+
+ /* set mode register */
+ out_be32 ((unsigned __iomem *)MPC5XXX_SDRAM_MODE, (SDRAM_MODE));
+ __asm__ volatile ("sync");
+
+ /* normal operation */
+ out_be32 ((unsigned __iomem *)MPC5XXX_SDRAM_CTRL,
+ (SDRAM_CONTROL | hi_addr_bit));
+ __asm__ volatile ("sync");
+}
+#endif
+
+/*
+ * ATTENTION: Although partially referenced initdram does NOT make real use
+ * use of CFG_SDRAM_BASE. The code does not work if CFG_SDRAM_BASE
+ * is something else than 0x00000000.
+ */
+
+phys_size_t initdram (int board_type)
+{
+ ulong dramsize = 0;
+ ulong dramsize2 = 0;
+ uint svr, pvr;
+
+#ifndef CFG_RAMBOOT
+ ulong test1, test2;
+
+ /* setup SDRAM chip selects */
+ out_be32 ((unsigned __iomem *)MPC5XXX_SDRAM_CS0CFG, 0x0000001c); /* 512MB at 0x0 */
+ out_be32 ((unsigned __iomem *)MPC5XXX_SDRAM_CS1CFG, 0x80000000);/* disabled */
+ __asm__ volatile ("sync");
+
+ /* setup config registers */
+ out_be32 ((unsigned __iomem *)MPC5XXX_SDRAM_CONFIG1, SDRAM_CONFIG1);
+ out_be32 ((unsigned __iomem *)MPC5XXX_SDRAM_CONFIG2, SDRAM_CONFIG2);
+ __asm__ volatile ("sync");
+
+#if SDRAM_DDR
+ /* set tap delay */
+ out_be32 ((unsigned __iomem *)MPC5XXX_CDM_PORCFG, SDRAM_TAPDELAY);
+ __asm__ volatile ("sync");
+#endif
+
+ /* find RAM size using SDRAM CS0 only */
+ sdram_start (0);
+ test1 = get_ram_size ((long *)CFG_SDRAM_BASE, 0x20000000);
+ sdram_start(1);
+ test2 = get_ram_size ((long *)CFG_SDRAM_BASE, 0x20000000);
+ if (test1 > test2) {
+ sdram_start (0);
+ dramsize = test1;
+ } else {
+ dramsize = test2;
+ }
+
+ /* memory smaller than 1MB is impossible */
+ if (dramsize < (1 << 20)) {
+ dramsize = 0;
+ }
+
+ /* set SDRAM CS0 size according to the amount of RAM found */
+ if (dramsize > 0) {
+ out_be32 ((unsigned __iomem *)MPC5XXX_SDRAM_CS0CFG,
+ (0x13 + __builtin_ffs(dramsize >> 20) - 1));
+ } else {
+ out_be32 ((unsigned __iomem *)MPC5XXX_SDRAM_CS0CFG, 0); /* disabled */
+ }
+
+ /* let SDRAM CS1 start right after CS0 */
+ out_be32 ((unsigned __iomem *)MPC5XXX_SDRAM_CS1CFG, (dramsize + 0x0000001c));/*512MB*/
+
+ /* find RAM size using SDRAM CS1 only */
+ if (!dramsize)
+ sdram_start (0);
+ test2 = test1 = get_ram_size ((long *)(CFG_SDRAM_BASE + dramsize), 0x20000000);
+ if (!dramsize) {
+ sdram_start (1);
+ test2 = get_ram_size ((long *)(CFG_SDRAM_BASE + dramsize), 0x20000000);
+ }
+ if (test1 > test2) {
+ sdram_start (0);
+ dramsize2 = test1;
+ } else {
+ dramsize2 = test2;
+ }
+
+ /* memory smaller than 1MB is impossible */
+ if (dramsize2 < (1 << 20)) {
+ dramsize2 = 0;
+ }
+
+ /* set SDRAM CS1 size according to the amount of RAM found */
+ if (dramsize2 > 0) {
+ out_be32 ((unsigned __iomem *)MPC5XXX_SDRAM_CS1CFG,
+ (dramsize | (0x13 + __builtin_ffs(dramsize2 >> 20) - 1)));
+ } else {
+ out_be32 ((unsigned __iomem *)MPC5XXX_SDRAM_CS1CFG, dramsize); /* disabled */
+ }
+
+#else /* CFG_RAMBOOT */
+
+ /* retrieve size of memory connected to SDRAM CS0 */
+ dramsize = in_be32 ((unsigned __iomem *)MPC5XXX_SDRAM_CS0CFG) & 0xFF;
+ if (dramsize >= 0x13) {
+ dramsize = (1 << (dramsize - 0x13)) << 20;
+ } else {
+ dramsize = 0;
+ }
+
+ /* retrieve size of memory connected to SDRAM CS1 */
+ dramsize2 = in_be32 ((unsigned __iomem *)MPC5XXX_SDRAM_CS1CFG) & 0xFF;
+ if (dramsize2 >= 0x13) {
+ dramsize2 = (1 << (dramsize2 - 0x13)) << 20;
+ } else {
+ dramsize2 = 0;
+ }
+
+#endif /* CFG_RAMBOOT */
+
+ /*
+ * On MPC5200B we need to set the special configuration delay in the
+ * DDR controller. Please refer to Freescale's AN3221 "MPC5200B SDRAM
+ * Initialization and Configuration", 3.3.1 SDelay--MBAR + 0x0190:
+ *
+ * "The SDelay should be written to a value of 0x00000004. It is
+ * required to account for changes caused by normal wafer processing
+ * parameters."
+ */
+ svr = get_svr();
+ pvr = get_pvr();
+ if ((SVR_MJREV(svr) >= 2) &&
+ (PVR_MAJ(pvr) == 1) && (PVR_MIN(pvr) == 4)) {
+
+ out_be32 ((unsigned __iomem *)MPC5XXX_SDRAM_SDELAY, 0x04);
+ __asm__ volatile ("sync");
+ }
+
+ return dramsize + dramsize2;
+}
+
+int checkboard (void)
+{
+ puts ("Board: MUC.MC-52 HW WDT ");
+#if defined(CONFIG_HW_WATCHDOG)
+ puts ("enabled\n");
+#else
+ puts ("disabled\n");
+#endif
+ return 0;
+}
+
+#ifdef CONFIG_PREBOOT
+
+static uchar kbd_magic_prefix[] = "key_magic";
+static uchar kbd_command_prefix[] = "key_cmd";
+
+#define S1_ROT 0xf0
+#define S2_Q 0x40
+#define S2_M 0x20
+
+struct kbd_data_t {
+ char s1;
+ char s2;
+};
+
+struct kbd_data_t* get_keys (struct kbd_data_t *kbd_data)
+{
+ kbd_data->s1 = in_8 ((volatile uchar*)CFG_STATUS1_BASE);
+ kbd_data->s2 = in_8 ((volatile uchar*)CFG_STATUS2_BASE);
+
+ return kbd_data;
+}
+
+static int compare_magic (const struct kbd_data_t *kbd_data, char *str)
+{
+ char s1 = str[0];
+ char s2;
+
+ if (s1 >= '0' && s1 <= '9')
+ s1 -= '0';
+ else if (s1 >= 'a' && s1 <= 'f')
+ s1 = s1 - 'a' + 10;
+ else if (s1 >= 'A' && s1 <= 'F')
+ s1 = s1 - 'A' + 10;
+ else
+ return -1;
+
+ if (((S1_ROT & kbd_data->s1) >> 4) != s1)
+ return -1;
+
+ s2 = (S2_Q | S2_M) & kbd_data->s2;
+
+ switch (str[1]) {
+ case 'q':
+ case 'Q':
+ if (s2 == S2_Q)
+ return -1;
+ break;
+ case 'm':
+ case 'M':
+ if (s2 == S2_M)
+ return -1;
+ break;
+ case '\0':
+ if (s2 == (S2_Q | S2_M))
+ return 0;
+ default:
+ return -1;
+ }
+
+ if (str[2])
+ return -1;
+
+ return 0;
+}
+
+static char *key_match (const struct kbd_data_t *kbd_data)
+{
+ char magic[sizeof (kbd_magic_prefix) + 1];
+ char *suffix;
+ char *kbd_magic_keys;
+
+ /*
+ * The following string defines the characters that can be appended
+ * to "key_magic" to form the names of environment variables that
+ * hold "magic" key codes, i. e. such key codes that can cause
+ * pre-boot actions. If the string is empty (""), then only
+ * "key_magic" is checked (old behaviour); the string "125" causes
+ * checks for "key_magic1", "key_magic2" and "key_magic5", etc.
+ */
+ if ((kbd_magic_keys = getenv ("magic_keys")) == NULL)
+ kbd_magic_keys = "";
+
+ /* loop over all magic keys;
+ * use '\0' suffix in case of empty string
+ */
+ for (suffix = kbd_magic_keys; *suffix ||
+ suffix == kbd_magic_keys; ++suffix) {
+ sprintf (magic, "%s%c", kbd_magic_prefix, *suffix);
+
+ if (compare_magic(kbd_data, getenv(magic)) == 0) {
+ char cmd_name[sizeof (kbd_command_prefix) + 1];
+ char *cmd;
+
+ sprintf (cmd_name, "%s%c", kbd_command_prefix, *suffix);
+ cmd = getenv (cmd_name);
+
+ return (cmd);
+ }
+ }
+
+ return (NULL);
+}
+
+#endif /* CONFIG_PREBOOT */
+
+int misc_init_r (void)
+{
+#ifdef CONFIG_PREBOOT
+ struct kbd_data_t kbd_data;
+ /* Decode keys */
+ char *str = strdup (key_match (get_keys (&kbd_data)));
+ /* Set or delete definition */
+ setenv ("preboot", str);
+ free (str);
+#endif /* CONFIG_PREBOOT */
+
+ out_8 ((volatile uchar *)(CFG_DISPLAY_BASE + 0x38), ' ');
+ out_8 ((volatile uchar *)(CFG_DISPLAY_BASE + 0x39), ' ');
+ out_8 ((volatile uchar *)(CFG_DISPLAY_BASE + 0x3A), ' ');
+ out_8 ((volatile uchar *)(CFG_DISPLAY_BASE + 0x3B), ' ');
+ out_8 ((volatile uchar *)(CFG_DISPLAY_BASE + 0x3C), ' ');
+ out_8 ((volatile uchar *)(CFG_DISPLAY_BASE + 0x3D), ' ');
+ out_8 ((volatile uchar *)(CFG_DISPLAY_BASE + 0x3E), ' ');
+ out_8 ((volatile uchar *)(CFG_DISPLAY_BASE + 0x3F), ' ');
+
+ return 0;
+}
+
+int board_early_init_r (void)
+{
+ out_be32 ((unsigned __iomem *)MPC5XXX_BOOTCS_CFG, in_be32 ((unsigned __iomem *)MPC5XXX_BOOTCS_CFG) & ~0x1);
+ out_be32 ((unsigned __iomem *)MPC5XXX_BOOTCS_START, START_REG(CFG_FLASH_BASE));
+ out_be32 ((unsigned __iomem *)MPC5XXX_CS0_START, START_REG(CFG_FLASH_BASE));
+ out_be32 ((unsigned __iomem *)MPC5XXX_BOOTCS_STOP,
+ STOP_REG(CFG_FLASH_BASE, CFG_FLASH_SIZE));
+ out_be32 ((unsigned __iomem *)MPC5XXX_CS0_STOP,
+ STOP_REG(CFG_FLASH_BASE, CFG_FLASH_SIZE));
+ return 0;
+}
+
+int last_stage_init (void)
+{
+ out_8 ((volatile uchar *)(CFG_DISPLAY_BASE + 0x38), 'M');
+ out_8 ((volatile uchar *)(CFG_DISPLAY_BASE + 0x39), 'U');
+ out_8 ((volatile uchar *)(CFG_DISPLAY_BASE + 0x3A), 'C');
+ out_8 ((volatile uchar *)(CFG_DISPLAY_BASE + 0x3B), '.');
+ out_8 ((volatile uchar *)(CFG_DISPLAY_BASE + 0x3C), 'M');
+ out_8 ((volatile uchar *)(CFG_DISPLAY_BASE + 0x3D), 'C');
+ out_8 ((volatile uchar *)(CFG_DISPLAY_BASE + 0x3E), '5');
+ out_8 ((volatile uchar *)(CFG_DISPLAY_BASE + 0x3F), '2');
+
+ return 0;
+}
+
+#if defined(CONFIG_HW_WATCHDOG)
+#define GPT_OUT_0 0x00000027
+#define GPT_OUT_1 0x00000037
+void hw_watchdog_reset (void)
+{
+ /* Trigger HW Watchdog with TIMER_0 */
+ out_be32 ((unsigned __iomem *)MPC5XXX_GPT0_ENABLE, GPT_OUT_1);
+ out_be32 ((unsigned __iomem *)MPC5XXX_GPT0_ENABLE, GPT_OUT_0);
+}
+#endif
+
+#ifdef CONFIG_PCI
+static struct pci_controller hose;
+
+extern void pci_mpc5xxx_init (struct pci_controller *);
+
+void pci_init_board (void)
+{
+ pci_mpc5xxx_init (&hose);
+}
+#endif
diff --git a/cpu/mpc5xxx/fec.c b/cpu/mpc5xxx/fec.c
index 82640ab..bf804ee 100644
--- a/cpu/mpc5xxx/fec.c
+++ b/cpu/mpc5xxx/fec.c
@@ -474,8 +474,9 @@ static int mpc5xxx_fec_init_phy(struct eth_device *dev, bd_t * bis)
miiphy_write(dev->name, phyAddr, 0x0, 0x8000);
udelay(1000);
-#if defined(CONFIG_UC101)
- /* Set the LED configuration Register for the UC101 Board */
+#if defined(CONFIG_UC101) || defined(CONFIG_MUCMC52)
+ /* Set the LED configuration Register for the UC101
+ and MUCMC52 Board */
miiphy_write(dev->name, phyAddr, 0x14, 0x4122);
#endif
if (fec->xcv_type == MII10) {
@@ -897,6 +898,7 @@ int mpc5xxx_fec_initialize(bd_t * bis)
defined(CONFIG_JUPITER) || \
defined(CONFIG_MCC200) || \
defined(CONFIG_MOTIONPRO) || \
+ defined(CONFIG_MUCMC52) || \
defined(CONFIG_O2DNT) || \
defined(CONFIG_PM520) || \
defined(CONFIG_TOP5200) || \
diff --git a/include/configs/mucmc52.h b/include/configs/mucmc52.h
new file mode 100644
index 0000000..c8c78c7
--- /dev/null
+++ b/include/configs/mucmc52.h
@@ -0,0 +1,376 @@
+/*
+ * (C) Copyright 2008
+ * Heiko Schocher, DENX Software Engineering, hs(a)denx.de.
+ *
+ * (C) Copyright 2003-2005
+ * Wolfgang Denk, DENX Software Engineering, wd(a)denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_MPC5xxx 1 /* This is an MPC5xxx CPU */
+#define CONFIG_MPC5200 1 /* (more precisely an MPC5200 CPU) */
+#define CONFIG_MUCMC52 1 /* MUCMC52 board */
+
+#define CFG_MPC5XXX_CLKIN 33000000 /* ... running at 33.000000MHz */
+
+#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */
+#define BOOTFLAG_WARM 0x02 /* Software reboot */
+
+#define CFG_CACHELINE_SIZE 32 /* For MPC5xxx CPUs */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+# define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */
+#endif
+
+#define CONFIG_BOARD_EARLY_INIT_R
+
+#define CONFIG_LAST_STAGE_INIT
+
+#define CONFIG_HIGH_BATS 1 /* High BATs supported */
+/*
+ * Serial console configuration
+ */
+#define CONFIG_PSC_CONSOLE 1 /* console is on PSC1 */
+#define CONFIG_BAUDRATE 38400 /* ... at 38400 bps */
+#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, 230400 }
+
+/* Partitions */
+#define CONFIG_DOS_PARTITION
+
+/*
+ * Command line configuration.
+ */
+#include <config_cmd_default.h>
+
+#define CONFIG_CMD_DATE
+#define CONFIG_CMD_DISPLAY
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_EEPROM
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_I2C
+#define CONFIG_CMD_DTT
+#define CONFIG_CMD_IDE
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_NFS
+#define CONFIG_CMD_PCI
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_SNTP
+
+#define CONFIG_TIMESTAMP 1 /* Print image info with timestamp */
+
+#if (TEXT_BASE == 0xFFF00000) /* Boot low */
+# define CFG_LOWBOOT 1
+#endif
+
+/*
+ * Autobooting
+ */
+#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */
+
+#define CONFIG_PREBOOT "echo;" \
+ "echo Type \"run flash_nfs\" to mount root filesystem over NFS;" \
+ "echo"
+
+#undef CONFIG_BOOTARGS
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "netdev=eth0\0" \
+ "nfsargs=setenv bootargs root=/dev/nfs rw " \
+ "nfsroot=${serverip}:${rootpath}\0" \
+ "ramargs=setenv bootargs root=/dev/ram rw\0" \
+ "addip=setenv bootargs ${bootargs} " \
+ "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}" \
+ ":${hostname}:${netdev}:off panic=1\0" \
+ "flash_nfs=run nfsargs addip;" \
+ "bootm ${kernel_addr}\0" \
+ "net_nfs=tftp 200000 ${bootfile};run nfsargs addip;bootm\0" \
+ "rootpath=/opt/eldk/ppc_82xx\0" \
+ ""
+
+#define CONFIG_BOOTCOMMAND "run net_nfs"
+
+#define CONFIG_MISC_INIT_R 1
+
+/*
+ * IPB Bus clocking configuration.
+ */
+#undef CFG_IPBCLK_EQUALS_XLBCLK /* define for 133MHz speed */
+
+/*
+ * I2C configuration
+ */
+#define CONFIG_HARD_I2C 1 /* I2C with hardware support */
+#define CFG_I2C_MODULE 2 /* Select I2C module #1 or #2 */
+
+#define CFG_I2C_SPEED 100000 /* 100 kHz */
+#define CFG_I2C_SLAVE 0x7F
+
+/*
+ * EEPROM configuration
+ */
+#define CFG_I2C_EEPROM_ADDR 0x58
+#define CFG_I2C_EEPROM_ADDR_LEN 1
+#define CFG_EEPROM_PAGE_WRITE_BITS 4
+#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10
+/* for LM81 */
+#define CFG_EEPROM_PAGE_WRITE_ENABLE
+
+/*
+ * RTC configuration
+ */
+#define CONFIG_RTC_PCF8563
+#define CFG_I2C_RTC_ADDR 0x51
+
+/* I2C SYSMON (LM75) */
+#define CONFIG_DTT_LM81 1 /* ON Semi's LM75 */
+#define CONFIG_DTT_SENSORS {0} /* Sensor addresses */
+#define CFG_DTT_MAX_TEMP 70
+#define CFG_DTT_LOW_TEMP -30
+#define CFG_DTT_HYSTERESIS 3
+
+/*
+ * Flash configuration
+ */
+#define CFG_FLASH_BASE 0xFF800000
+
+#define CFG_FLASH_SIZE 0x00800000 /* 8 MByte */
+#define CFG_MAX_FLASH_SECT 67 /* max num of sects on one chip */
+
+#define CFG_ENV_ADDR (TEXT_BASE+0x40000) /* second sector */
+#define CFG_MAX_FLASH_BANKS 1 /* max num of flash banks
+ (= chip selects) */
+#define CFG_FLASH_ERASE_TOUT 240000 /* Flash Erase Timeout (in ms) */
+#define CFG_FLASH_WRITE_TOUT 500 /* Flash Write Timeout (in ms) */
+
+#define CONFIG_FLASH_CFI_DRIVER
+#define CFG_FLASH_CFI
+#define CFG_FLASH_EMPTY_INFO
+#define CFG_FLASH_CFI_AMD_RESET
+
+/*
+ * Environment settings
+ */
+#define CFG_ENV_IS_IN_FLASH 1
+#define CFG_ENV_SIZE 0x4000
+#define CFG_ENV_SECT_SIZE 0x20000
+#define CFG_ENV_OFFSET_REDUND (CFG_ENV_OFFSET+CFG_ENV_SECT_SIZE)
+#define CFG_ENV_SIZE_REDUND (CFG_ENV_SIZE)
+
+/*
+ * Memory map
+ */
+#define CFG_MBAR 0xF0000000
+#define CFG_SDRAM_BASE 0x00000000
+#define CFG_DEFAULT_MBAR 0x80000000
+#define CFG_DISPLAY_BASE 0x80600000
+#define CFG_STATUS1_BASE 0x80600200
+#define CFG_STATUS2_BASE 0x80600300
+#define CFG_PMI_UNI_BASE 0x80800000
+#define CFG_PMI_BROAD_BASE 0x80810000
+
+/* Settings for XLB = 132 MHz */
+#define SDRAM_DDR 1
+#define SDRAM_MODE 0x018D0000
+#define SDRAM_EMODE 0x40090000
+#define SDRAM_CONTROL 0x714f0f00
+#define SDRAM_CONFIG1 0x73722930
+#define SDRAM_CONFIG2 0x47770000
+#define SDRAM_TAPDELAY 0x10000000
+
+/* Use ON-Chip SRAM until RAM will be available */
+#define CFG_INIT_RAM_ADDR MPC5XXX_SRAM
+#ifdef CONFIG_POST
+/* preserve space for the post_word at end of on-chip SRAM */
+#define CFG_INIT_RAM_END MPC5XXX_SRAM_POST_SIZE
+#else
+#define CFG_INIT_RAM_END MPC5XXX_SRAM_SIZE
+#endif
+
+#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET
+
+#define CFG_MONITOR_BASE TEXT_BASE
+#if (CFG_MONITOR_BASE < CFG_FLASH_BASE)
+# define CFG_RAMBOOT 1
+#endif
+
+#define CFG_MONITOR_LEN (192 << 10) /* Reserve 192 kB for Monitor */
+#define CFG_MALLOC_LEN (512 << 10) /* Reserve 128 kB for malloc() */
+#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */
+
+/*
+ * Ethernet configuration
+ */
+#define CONFIG_MPC5xxx_FEC 1
+#define CONFIG_PHY_ADDR 0x00
+#define CONFIG_MII 1 /* MII PHY management */
+
+/*
+ * GPIO configuration
+ */
+#define CFG_GPS_PORT_CONFIG 0x8D550644
+
+/*use Hardware WDT */
+#define CONFIG_HW_WATCHDOG
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP /* undef to save memory */
+#define CFG_PROMPT "=> " /* Monitor Command Prompt */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */
+#else
+#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
+#endif
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define CFG_MAXARGS 16 /* max number of command args */
+#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */
+
+/* Enable an alternate, more extensive memory test */
+#define CFG_ALT_MEMTEST
+
+#define CFG_MEMTEST_START 0x00100000 /* memtest works on */
+#define CFG_MEMTEST_END 0x00f00000 /* 1 ... 15 MB in DRAM */
+
+#define CFG_LOAD_ADDR 0x100000 /* default load address */
+
+#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */
+
+/*
+ * Enable loopw commando. This has only affect, if CFG_CMD_MEM is defined,
+ * which is normally part of the default commands (CFV_CMD_DFL)
+ */
+#define CONFIG_LOOPW
+
+/*
+ * Various low-level settings
+ */
+#if defined(CONFIG_MPC5200)
+#define CFG_HID0_INIT HID0_ICE | HID0_ICFI
+#define CFG_HID0_FINAL HID0_ICE
+#else
+#define CFG_HID0_INIT 0
+#define CFG_HID0_FINAL 0
+#endif
+
+#define CFG_BOOTCS_START CFG_FLASH_BASE
+#define CFG_BOOTCS_SIZE CFG_FLASH_SIZE
+#define CFG_BOOTCS_CFG 0x0004FB00
+#define CFG_CS0_START CFG_FLASH_BASE
+#define CFG_CS0_SIZE CFG_FLASH_SIZE
+
+/* 8Mbit SRAM @0x80100000 */
+#define CFG_CS1_START 0x80100000
+#define CFG_CS1_SIZE 0x00100000
+#define CFG_CS1_CFG 0x00019B00
+
+/* FRAM 32Kbyte @0x80700000 */
+#define CFG_CS2_START 0x80700000
+#define CFG_CS2_SIZE 0x00008000
+#define CFG_CS2_CFG 0x00019800
+
+/* Display H1, Status Inputs, EPLD @0x80600000 */
+#define CFG_CS3_START 0x80600000
+#define CFG_CS3_SIZE 0x00100000
+#define CFG_CS3_CFG 0x00019800
+
+/* PMI Unicast 32Kbyte @0x80800000 */
+#define CFG_CS6_START CFG_PMI_UNI_BASE
+#define CFG_CS6_SIZE 0x00008000
+#define CFG_CS6_CFG 0xFFFFF930
+
+/* PMI Broadcast 32Kbyte @0x80810000 */
+#define CFG_CS7_START CFG_PMI_BROAD_BASE
+#define CFG_CS7_SIZE 0x00008000
+#define CFG_CS7_CFG 0xFF00F930
+
+#define CFG_CS_BURST 0x00000000
+#define CFG_CS_DEADCYCLE 0x33333333
+
+/*-----------------------------------------------------------------------
+ * IDE/ATA stuff Supports IDE harddisk
+ *-----------------------------------------------------------------------
+ */
+
+#undef CONFIG_IDE_8xx_PCCARD /* Use IDE with PC Card Adapter */
+
+#undef CONFIG_IDE_8xx_DIRECT /* Direct IDE not supported */
+#undef CONFIG_IDE_LED /* LED for ide not supported */
+
+#define CFG_IDE_MAXBUS 1 /* max. 1 IDE bus */
+#define CFG_IDE_MAXDEVICE 1 /* max. 2 drives per IDE bus */
+
+#define CONFIG_IDE_PREINIT 1
+
+#define CFG_ATA_IDE0_OFFSET 0x0000
+
+#define CFG_ATA_BASE_ADDR MPC5XXX_ATA
+
+/* Offset for data I/O */
+#define CFG_ATA_DATA_OFFSET (0x0060)
+
+/* Offset for normal register accesses */
+#define CFG_ATA_REG_OFFSET (CFG_ATA_DATA_OFFSET)
+
+/* Offset for alternate registers */
+#define CFG_ATA_ALT_OFFSET (0x005C)
+
+/* Interval between registers */
+#define CFG_ATA_STRIDE 4
+
+#define CONFIG_ATAPI 1
+
+/*
+ * PCI Mapping:
+ * 0x40000000 - 0x4fffffff - PCI Memory
+ * 0x50000000 - 0x50ffffff - PCI IO Space
+ */
+#define CONFIG_PCI 1
+#define CONFIG_PCI_PNP 1
+#define CONFIG_PCI_SCAN_SHOW 1
+#define CONFIG_PCIAUTO_SKIP_HOST_BRIDGE 1
+
+#define CONFIG_PCI_MEM_BUS 0x40000000
+#define CONFIG_PCI_MEM_PHYS CONFIG_PCI_MEM_BUS
+#define CONFIG_PCI_MEM_SIZE 0x10000000
+
+#define CONFIG_PCI_IO_BUS 0x50000000
+#define CONFIG_PCI_IO_PHYS CONFIG_PCI_IO_BUS
+#define CONFIG_PCI_IO_SIZE 0x01000000
+
+#define CFG_ISA_IO CONFIG_PCI_IO_BUS
+
+/*---------------------------------------------------------------------*/
+/* Display addresses */
+/*---------------------------------------------------------------------*/
+
+#define CFG_DISP_CHR_RAM (CFG_DISPLAY_BASE + 0x38)
+#define CFG_DISP_CWORD (CFG_DISPLAY_BASE + 0x30)
+
+#endif /* __CONFIG_H */
--
1.5.6.1
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
1
0

[U-Boot] [PATCH] ppc4xx: Optimize PLB4 Arbiter and Memory Queue settings for PPC 440SP/SPe, PPC405EX and PPC 460EX/GT
by Prodyut Hazarika 21 Aug '08
by Prodyut Hazarika 21 Aug '08
21 Aug '08
Resending the patch since it was not copied to Stefan. Stefan, please ignore the previous post.
Read pipeline depth set to 4 for PPC440SP/SPE, PPC405EX, PPC460EX/GT/SX processors
Moved PLB4 Arbiter register definitions to ppc4xx.h since it is shared across processors
Optimize Memory Queue settings for PPC440SP/SPE and PPC460EX/GT/SX processors
Add register bit definitions for Memory Queue Configuration registers
Signed-off-by: Prodyut Hazarika <phazarika(a)amcc.com>
---
cpu/ppc4xx/44x_spd_ddr2.c | 27 ++++++++++++++++---
cpu/ppc4xx/cpu_init.c | 16 ++++++++++-
include/asm-ppc/ppc4xx-sdram.h | 48 ++++++++++++++++++++++-----------
include/ppc440.h | 47 ---------------------------------
include/ppc4xx.h | 56 ++++++++++++++++++++++++++++++++++++++++
5 files changed, 126 insertions(+), 68 deletions(-)
diff --git a/cpu/ppc4xx/44x_spd_ddr2.c b/cpu/ppc4xx/44x_spd_ddr2.c
index 1c36324..0431754 100644
--- a/cpu/ppc4xx/44x_spd_ddr2.c
+++ b/cpu/ppc4xx/44x_spd_ddr2.c
@@ -2172,6 +2172,11 @@ static void program_memory_queue(unsigned long *dimm_populated,
unsigned long i;
unsigned long bank_0_populated = 0;
phys_size_t total_size = 0;
+#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_460SX)
+ unsigned long val;
+#endif
/*------------------------------------------------------------------
* Reset the rank_base_address.
@@ -2249,17 +2254,31 @@ static void program_memory_queue(unsigned long *dimm_populated,
}
}
-#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_460SX)
+
/*
- * Enable high bandwidth access on 460EX/GT.
- * This should/could probably be done on other
- * PPC's too, like 440SPe.
+ * Enable high bandwidth access
* This is currently not used, but with this setup
* it is possible to use it later on in e.g. the Linux
* EMAC driver for performance gain.
*/
mtdcr(SDRAM_PLBADDULL, 0x00000000); /* MQ0_BAUL */
mtdcr(SDRAM_PLBADDUHB, 0x00000008); /* MQ0_BAUH */
+
+ /*
+ * Set optimal value for Memory Queue HB/LL Configuration registers
+ */
+
+ val = (mfdcr(SDRAM_CONF1HB) | SDRAM_CONF1HB_AAFR | SDRAM_CONF1HB_RPEN | SDRAM_CONF1HB_RFTE);
+ mtdcr(SDRAM_CONF1HB, val);
+
+ val = (mfdcr(SDRAM_CONF1LL) | SDRAM_CONF1LL_AAFR | SDRAM_CONF1LL_RPEN | SDRAM_CONF1LL_RFTE);
+ mtdcr(SDRAM_CONF1LL, val);
+
+ val = (mfdcr(SDRAM_CONFPATHB) | SDRAM_CONFPATHB_TPEN);
+ mtdcr(SDRAM_CONFPATHB, val);
#endif
}
diff --git a/cpu/ppc4xx/cpu_init.c b/cpu/ppc4xx/cpu_init.c
index e2d0402..c7c429e 100644
--- a/cpu/ppc4xx/cpu_init.c
+++ b/cpu/ppc4xx/cpu_init.c
@@ -138,7 +138,9 @@ void reconfigure_pll(u32 new_cpu_freq)
void
cpu_init_f (void)
{
-#if defined(CONFIG_WATCHDOG) || defined(CONFIG_440GX) || defined(CONFIG_460EX)
+#if defined(CONFIG_WATCHDOG) || defined(CONFIG_440GX) || defined(CONFIG_460EX) || \
+ defined(CONFIG_440SP) || defined(CONFIG_440SPE) || defined(CONFIG_405EX) || \
+ defined(CONFIG_460GT) || defined(CONFIG_460SX)
u32 val;
#endif
@@ -301,6 +303,18 @@ cpu_init_f (void)
val |= 0x400;
mtsdr(SDR0_USB2HOST_CFG, val);
#endif /* CONFIG_460EX */
+
+#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_405EX) || defined(CONFIG_460SX)
+ /*
+ * Set PLB4 arbiter (Segment 0 and 1) to 4 deep pipeline read
+ */
+ val = (mfdcr(plb0_acr) & ~plb0_acr_rdp_mask) | plb0_acr_rdp_4deep;
+ mtdcr(plb0_acr, val);
+ val = (mfdcr(plb1_acr) & ~plb1_acr_rdp_mask) | plb1_acr_rdp_4deep;
+ mtdcr(plb1_acr, val);
+#endif /* CONFIG_440SP/SPE || CONFIG_460EX/GT || CONFIG_405EX */
}
/*
diff --git a/include/asm-ppc/ppc4xx-sdram.h b/include/asm-ppc/ppc4xx-sdram.h
index df787b3..0174d62 100644
--- a/include/asm-ppc/ppc4xx-sdram.h
+++ b/include/asm-ppc/ppc4xx-sdram.h
@@ -259,23 +259,39 @@
/*
* Memory queue defines
*/
-#define SDRAMQ_DCR_BASE 0x040
-
-#define SDRAM_R0BAS (SDRAMQ_DCR_BASE+0x0) /* rank 0 base address & size */
-#define SDRAM_R1BAS (SDRAMQ_DCR_BASE+0x1) /* rank 1 base address & size */
-#define SDRAM_R2BAS (SDRAMQ_DCR_BASE+0x2) /* rank 2 base address & size */
-#define SDRAM_R3BAS (SDRAMQ_DCR_BASE+0x3) /* rank 3 base address & size */
-#define SDRAM_CONF1HB (SDRAMQ_DCR_BASE+0x5) /* configuration 1 HB */
-#define SDRAM_ERRSTATHB (SDRAMQ_DCR_BASE+0x7) /* error status HB */
-#define SDRAM_ERRADDUHB (SDRAMQ_DCR_BASE+0x8) /* error address upper 32 HB */
-#define SDRAM_ERRADDLHB (SDRAMQ_DCR_BASE+0x9) /* error address lower 32 HB */
-#define SDRAM_PLBADDULL (SDRAMQ_DCR_BASE+0xA) /* PLB base address upper 32 LL */
-#define SDRAM_CONF1LL (SDRAMQ_DCR_BASE+0xB) /* configuration 1 LL */
-#define SDRAM_ERRSTATLL (SDRAMQ_DCR_BASE+0xC) /* error status LL */
-#define SDRAM_ERRADDULL (SDRAMQ_DCR_BASE+0xD) /* error address upper 32 LL */
-#define SDRAM_ERRADDLLL (SDRAMQ_DCR_BASE+0xE) /* error address lower 32 LL */
-#define SDRAM_CONFPATHB (SDRAMQ_DCR_BASE+0xF) /* configuration between paths */
-#define SDRAM_PLBADDUHB (SDRAMQ_DCR_BASE+0x10) /* PLB base address upper 32 LL */
+#define SDRAMQ_DCR_BASE 0x040
+
+#define SDRAM_R0BAS (SDRAMQ_DCR_BASE+0x0) /* rank 0 base address & size */
+#define SDRAM_R1BAS (SDRAMQ_DCR_BASE+0x1) /* rank 1 base address & size */
+#define SDRAM_R2BAS (SDRAMQ_DCR_BASE+0x2) /* rank 2 base address & size */
+#define SDRAM_R3BAS (SDRAMQ_DCR_BASE+0x3) /* rank 3 base address & size */
+#define SDRAM_CONF1HB (SDRAMQ_DCR_BASE+0x5) /* configuration 1 HB */
+#define SDRAM_CONF1HB_AAFR 0x80000000 /* Address Ack on First Request - Bit 0 */
+#define SDRAM_CONF1HB_PRPD 0x00080000 /* PLB Read pipeline Disable - Bit 12 */
+#define SDRAM_CONF1HB_PWPD 0x00040000 /* PLB Write pipeline Disable - Bit 13 */
+#define SDRAM_CONF1HB_PRW 0x00020000 /* PLB Read Wait - Bit 14 */
+#define SDRAM_CONF1HB_RPEN 0x00000800 /* Read Passing Enable - Bit 20 */
+#define SDRAM_CONF1HB_RFTE 0x00000400 /* Read Flow Through Enable - Bit 21 */
+
+#define SDRAM_ERRSTATHB (SDRAMQ_DCR_BASE+0x7) /* error status HB */
+#define SDRAM_ERRADDUHB (SDRAMQ_DCR_BASE+0x8) /* error address upper 32 HB */
+#define SDRAM_ERRADDLHB (SDRAMQ_DCR_BASE+0x9) /* error address lower 32 HB */
+#define SDRAM_PLBADDULL (SDRAMQ_DCR_BASE+0xA) /* PLB base address upper 32 LL */
+#define SDRAM_CONF1LL (SDRAMQ_DCR_BASE+0xB) /* configuration 1 LL */
+#define SDRAM_CONF1LL_AAFR 0x80000000 /* Address Ack on First Request - Bit 0 */
+#define SDRAM_CONF1LL_PRPD 0x00080000 /* PLB Read pipeline Disable - Bit 12 */
+#define SDRAM_CONF1LL_PWPD 0x00040000 /* PLB Write pipeline Disable - Bit 13 */
+#define SDRAM_CONF1LL_PRW 0x00020000 /* PLB Read Wait - Bit 14 */
+#define SDRAM_CONF1LL_RPEN 0x00000800 /* Read Passing Enable - Bit 20 */
+#define SDRAM_CONF1LL_RFTE 0x00000400 /* Read Flow Through Enable - Bit 21 */
+
+#define SDRAM_ERRSTATLL (SDRAMQ_DCR_BASE+0xC) /* error status LL */
+#define SDRAM_ERRADDULL (SDRAMQ_DCR_BASE+0xD) /* error address upper 32 LL */
+#define SDRAM_ERRADDLLL (SDRAMQ_DCR_BASE+0xE) /* error address lower 32 LL */
+#define SDRAM_CONFPATHB (SDRAMQ_DCR_BASE+0xF) /* configuration between paths */
+#define SDRAM_CONFPATHB_TPEN 0x08000000 /* Transaction Passing Enable - Bit 4 */
+
+#define SDRAM_PLBADDUHB (SDRAMQ_DCR_BASE+0x10) /* PLB base address upper 32 LL */
#if !defined(CONFIG_405EX)
/*
diff --git a/include/ppc440.h b/include/ppc440.h
index 92db15f..3584fd2 100644
--- a/include/ppc440.h
+++ b/include/ppc440.h
@@ -341,53 +341,6 @@
#define PLB4_ACR_WRP (0x80000000 >> 7)
-/* Nebula PLB4 Arbiter - PowerPC440EP */
-#define PLB_ARBITER_BASE 0x80
-
-#define plb0_revid (PLB_ARBITER_BASE+ 0x00)
-#define plb0_acr (PLB_ARBITER_BASE+ 0x01)
-#define plb0_acr_ppm_mask 0xF0000000
-#define plb0_acr_ppm_fixed 0x00000000
-#define plb0_acr_ppm_fair 0xD0000000
-#define plb0_acr_hbu_mask 0x08000000
-#define plb0_acr_hbu_disabled 0x00000000
-#define plb0_acr_hbu_enabled 0x08000000
-#define plb0_acr_rdp_mask 0x06000000
-#define plb0_acr_rdp_disabled 0x00000000
-#define plb0_acr_rdp_2deep 0x02000000
-#define plb0_acr_rdp_3deep 0x04000000
-#define plb0_acr_rdp_4deep 0x06000000
-#define plb0_acr_wrp_mask 0x01000000
-#define plb0_acr_wrp_disabled 0x00000000
-#define plb0_acr_wrp_2deep 0x01000000
-
-#define plb0_besrl (PLB_ARBITER_BASE+ 0x02)
-#define plb0_besrh (PLB_ARBITER_BASE+ 0x03)
-#define plb0_bearl (PLB_ARBITER_BASE+ 0x04)
-#define plb0_bearh (PLB_ARBITER_BASE+ 0x05)
-#define plb0_ccr (PLB_ARBITER_BASE+ 0x08)
-
-#define plb1_acr (PLB_ARBITER_BASE+ 0x09)
-#define plb1_acr_ppm_mask 0xF0000000
-#define plb1_acr_ppm_fixed 0x00000000
-#define plb1_acr_ppm_fair 0xD0000000
-#define plb1_acr_hbu_mask 0x08000000
-#define plb1_acr_hbu_disabled 0x00000000
-#define plb1_acr_hbu_enabled 0x08000000
-#define plb1_acr_rdp_mask 0x06000000
-#define plb1_acr_rdp_disabled 0x00000000
-#define plb1_acr_rdp_2deep 0x02000000
-#define plb1_acr_rdp_3deep 0x04000000
-#define plb1_acr_rdp_4deep 0x06000000
-#define plb1_acr_wrp_mask 0x01000000
-#define plb1_acr_wrp_disabled 0x00000000
-#define plb1_acr_wrp_2deep 0x01000000
-
-#define plb1_besrl (PLB_ARBITER_BASE+ 0x0A)
-#define plb1_besrh (PLB_ARBITER_BASE+ 0x0B)
-#define plb1_bearl (PLB_ARBITER_BASE+ 0x0C)
-#define plb1_bearh (PLB_ARBITER_BASE+ 0x0D)
-
/* Pin Function Control Register 1 */
#define SDR0_PFC1 0x4101
#define SDR0_PFC1_U1ME_MASK 0x02000000 /* UART1 Mode Enable */
diff --git a/include/ppc4xx.h b/include/ppc4xx.h
index c71da60..e1613dd 100644
--- a/include/ppc4xx.h
+++ b/include/ppc4xx.h
@@ -46,6 +46,62 @@
#define CONFIG_SDRAM_PPC4xx_IBM_DDR2 /* IBM DDR(2) controller */
#endif
+/* PLB4 CrossBar Arbiter Core supported across PPC4xx families */
+#if defined(CONFIG_405EX) || \
+ defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \
+ defined(CONFIG_440GR) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_460SX)
+
+#define PLB_ARBITER_BASE 0x80
+
+#define plb0_revid (PLB_ARBITER_BASE+ 0x00)
+#define plb0_acr (PLB_ARBITER_BASE+ 0x01)
+#define plb0_acr_ppm_mask 0xF0000000
+#define plb0_acr_ppm_fixed 0x00000000
+#define plb0_acr_ppm_fair 0xD0000000
+#define plb0_acr_hbu_mask 0x08000000
+#define plb0_acr_hbu_disabled 0x00000000
+#define plb0_acr_hbu_enabled 0x08000000
+#define plb0_acr_rdp_mask 0x06000000
+#define plb0_acr_rdp_disabled 0x00000000
+#define plb0_acr_rdp_2deep 0x02000000
+#define plb0_acr_rdp_3deep 0x04000000
+#define plb0_acr_rdp_4deep 0x06000000
+#define plb0_acr_wrp_mask 0x01000000
+#define plb0_acr_wrp_disabled 0x00000000
+#define plb0_acr_wrp_2deep 0x01000000
+
+#define plb0_besrl (PLB_ARBITER_BASE+ 0x02)
+#define plb0_besrh (PLB_ARBITER_BASE+ 0x03)
+#define plb0_bearl (PLB_ARBITER_BASE+ 0x04)
+#define plb0_bearh (PLB_ARBITER_BASE+ 0x05)
+#define plb0_ccr (PLB_ARBITER_BASE+ 0x08)
+
+#define plb1_acr (PLB_ARBITER_BASE+ 0x09)
+#define plb1_acr_ppm_mask 0xF0000000
+#define plb1_acr_ppm_fixed 0x00000000
+#define plb1_acr_ppm_fair 0xD0000000
+#define plb1_acr_hbu_mask 0x08000000
+#define plb1_acr_hbu_disabled 0x00000000
+#define plb1_acr_hbu_enabled 0x08000000
+#define plb1_acr_rdp_mask 0x06000000
+#define plb1_acr_rdp_disabled 0x00000000
+#define plb1_acr_rdp_2deep 0x02000000
+#define plb1_acr_rdp_3deep 0x04000000
+#define plb1_acr_rdp_4deep 0x06000000
+#define plb1_acr_wrp_mask 0x01000000
+#define plb1_acr_wrp_disabled 0x00000000
+#define plb1_acr_wrp_2deep 0x01000000
+
+#define plb1_besrl (PLB_ARBITER_BASE+ 0x0A)
+#define plb1_besrh (PLB_ARBITER_BASE+ 0x0B)
+#define plb1_bearl (PLB_ARBITER_BASE+ 0x0C)
+#define plb1_bearh (PLB_ARBITER_BASE+ 0x0D)
+
+#endif /* 440EP/EPX 440GR/GRX 440SP/SPE 460EX/GT/SX 405EX*/
+
#if defined(CONFIG_440)
/*
* Enable long long (%ll ...) printf format on 440 PPC's since most of
--
1.5.5
2
3
Hello,
I have one system with USB connector only, no RS232 port. How can I do
the interaction with Uboot?
Thanks for your help,
Mike
5
7
Hi,
I would like to know if u-boot source code is there for ARM Cortex A8.
Thanks,
Alwin
Please do not print this email unless it is absolutely necessary.
The information contained in this electronic message and any attachments to this message are intended for the exclusive use of the addressee(s) and may contain proprietary, confidential or privileged information. If you are not the intended recipient, you should not disseminate, distribute or copy this e-mail. Please notify the sender immediately and destroy all copies of this message and any attachments.
WARNING: Computer viruses can be transmitted via email. The recipient should check this email and any attachments for the presence of viruses. The company accepts no liability for any damage caused by any virus transmitted by this email.
www.wipro.com
4
3
I use U-Boot 1.2.0 on MPC5200B. Console over serial works fine. I have a
Grafic controller (LIME) at LPB Bus and U-Boot shows his console output at
VGa too.
But I would need a keyboard. I compiled U-Boot with USB and if i type "usb
reset" the ohci controller scans the USB devices and finds a keyboard. But
nothing happens if i push the buttons on the keyboard!
There would be another way, that I use a serial-keyboard controller. This
would work, i Think?
But I would prefer a USB keyboard, because I think PS/2 will not be the
future.
Can anyone help me (eg. say or give me anather usb-keyboard driver or where
I find any template how to make such a driver?)
I am very new in Linux and am happy that my Grafics driver works. But I have
never programmed USB.
Thanks
Alexander Schmid
Dipl. Ing. (FH)
-Entwicklung-
Systeme & Steuerungen GmbH
Josef-Buchinger-Strasse 8
DE-94481 Grafenau
Amtsgericht Passau; HRB-Nr.: 1248
Geschäftsführer: Wolfgang Biewald
Tel.: +49 85 52 96 39 37
Fax.: +49 85 52 96 39 40
Email: a.schmid(a)systeme-steuerungen.de
Der Inhalt dieser E-Mail ist vertraulich. Wenn Sie nicht der berechtigte
Empfänger sind, bitten wir Sie, uns umgehend zu informieren und den Inhalt
weder für eigene Zwecke zu nutzen noch an Dritte weiterzugeben.
This e-mail is confidential. If you are not the intended recipient, please
notify us immediately. You should not disclose its contents to any other
person nor use it for any purposes.
1
0
Hi Wolfgang,
Please pull
git://git.denx.de/u-boot-avr32.git master
to receive the below changes. This adds support for three new
avr32-based boards.
There are a couple of commits that were never posted to the list. They
are trivial fixes for compile breakage that turned up after I merged
everything together (things like CFG_FLASH_CFI_DRIVER recently being
renamed CONFIG_FLASH_CFI_DRIVER and a couple of format warnings.)
Ben Warren (1):
Moved initialization of AVR32 Ethernet controllers to board_eth_init()
Haavard Skinnemoen (9):
Merge branch 'eth-cleanup' of git://git.denx.de/u-boot-avr32
Merge branch 'hammerhead' of git://git.denx.de/u-boot-avr32
Merge branch 'favr-32' of git://git.denx.de/u-boot-avr32
Merge branch 'mimc200' of git://git.denx.de/u-boot-avr32
MAINTAINERS: Sort avr32 section alphabetically
favr-32-ezkit: Fix printf format warnings
hammerhead: Add missing printf parameter to CONFIG_AUTOBOOT_PROMPT
Merge branch 'next' of git://git.denx.de/u-boot-avr32
hammerhead/mimc200: Use CONFIG_FLASH_CFI_DRIVER
Hans-Christian Egtvedt (1):
avr32: add support for EarthLCD Favr-32 board
Julien May (1):
Add support for the hammerhead (AVR32) board
Mark Jackson (1):
avr32: Add MIMC200 board
CREDITS | 4 +
MAINTAINERS | 15 ++-
MAKEALL | 3 +
Makefile | 9 +
board/atmel/atngw100/Makefile | 2 +-
board/atmel/atngw100/atngw100.c | 11 +
board/atmel/atstk1000/Makefile | 2 +-
board/atmel/atstk1000/atstk1000.c | 11 +
board/earthlcd/favr-32-ezkit/Makefile | 42 ++++
board/earthlcd/favr-32-ezkit/config.mk | 4 +
board/earthlcd/favr-32-ezkit/favr-32-ezkit.c | 96 ++++++++
board/earthlcd/favr-32-ezkit/flash.c | 230 ++++++++++++++++++++
board/earthlcd/favr-32-ezkit/u-boot.lds | 71 ++++++
board/mimc/mimc200/Makefile | 40 ++++
board/mimc/mimc200/config.mk | 3 +
board/mimc/mimc200/mimc200.c | 207 ++++++++++++++++++
.../atstk1000/eth.c => mimc/mimc200/u-boot.lds} | 61 ++++-
board/miromico/hammerhead/Makefile | 40 ++++
board/miromico/hammerhead/config.mk | 3 +
board/miromico/hammerhead/hammerhead.c | 114 ++++++++++
.../eth.c => miromico/hammerhead/u-boot.lds} | 61 ++++-
cpu/at32ap/at32ap700x/sm.h | 2 +-
cpu/at32ap/cpu.c | 3 +
include/asm-avr32/arch-at32ap700x/clk.h | 1 +
include/configs/favr-32-ezkit.h | 201 +++++++++++++++++
include/configs/hammerhead.h | 172 +++++++++++++++
include/configs/mimc200.h | 177 +++++++++++++++
net/eth.c | 8 -
28 files changed, 1556 insertions(+), 37 deletions(-)
create mode 100644 board/earthlcd/favr-32-ezkit/Makefile
create mode 100644 board/earthlcd/favr-32-ezkit/config.mk
create mode 100644 board/earthlcd/favr-32-ezkit/favr-32-ezkit.c
create mode 100644 board/earthlcd/favr-32-ezkit/flash.c
create mode 100644 board/earthlcd/favr-32-ezkit/u-boot.lds
create mode 100644 board/mimc/mimc200/Makefile
create mode 100644 board/mimc/mimc200/config.mk
create mode 100644 board/mimc/mimc200/mimc200.c
rename board/{atmel/atstk1000/eth.c => mimc/mimc200/u-boot.lds} (59%)
create mode 100644 board/miromico/hammerhead/Makefile
create mode 100644 board/miromico/hammerhead/config.mk
create mode 100644 board/miromico/hammerhead/hammerhead.c
rename board/{atmel/atngw100/eth.c => miromico/hammerhead/u-boot.lds} (56%)
create mode 100644 include/configs/favr-32-ezkit.h
create mode 100644 include/configs/hammerhead.h
create mode 100644 include/configs/mimc200.h
2
5

[U-Boot] [PATCH] ppc4xx: Cleanup of "ppc4xx: Optimize PLB4 Arbiter..." patch
by Stefan Roese 21 Aug '08
by Stefan Roese 21 Aug '08
21 Aug '08
This patch fixes some minor issues introduced with the patch:
ppc4xx: Optimize PLB4 Arbiter... from Prodyut Hazarika:
- Rework memory-queue and PLB arbiter optimization code, that the
local variable is not needed anymore. This removes one #ifdef.
- Use consistant spacing in ppc4xx.h header (XXX + 0x01 instead
of XXX+ 0x01). This was not introduced by Prodyut, just a
copy-paste problem.
Signed-off-by: Stefan Roese <sr(a)denx.de>
---
cpu/ppc4xx/44x_spd_ddr2.c | 20 +++++---------------
cpu/ppc4xx/cpu_init.c | 17 ++++++++---------
include/ppc4xx.h | 24 ++++++++++++------------
3 files changed, 25 insertions(+), 36 deletions(-)
diff --git a/cpu/ppc4xx/44x_spd_ddr2.c b/cpu/ppc4xx/44x_spd_ddr2.c
index c7ed161..001f2c1 100644
--- a/cpu/ppc4xx/44x_spd_ddr2.c
+++ b/cpu/ppc4xx/44x_spd_ddr2.c
@@ -2172,11 +2172,6 @@ static void program_memory_queue(unsigned long *dimm_populated,
unsigned long i;
unsigned long bank_0_populated = 0;
phys_size_t total_size = 0;
-#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
- defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
- defined(CONFIG_460SX)
- unsigned long val;
-#endif
/*------------------------------------------------------------------
* Reset the rank_base_address.
@@ -2257,7 +2252,6 @@ static void program_memory_queue(unsigned long *dimm_populated,
#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_460SX)
-
/*
* Enable high bandwidth access
* This is currently not used, but with this setup
@@ -2270,15 +2264,11 @@ static void program_memory_queue(unsigned long *dimm_populated,
/*
* Set optimal value for Memory Queue HB/LL Configuration registers
*/
-
- val = (mfdcr(SDRAM_CONF1HB) | SDRAM_CONF1HB_AAFR | SDRAM_CONF1HB_RPEN | SDRAM_CONF1HB_RFTE);
- mtdcr(SDRAM_CONF1HB, val);
-
- val = (mfdcr(SDRAM_CONF1LL) | SDRAM_CONF1LL_AAFR | SDRAM_CONF1LL_RPEN | SDRAM_CONF1LL_RFTE);
- mtdcr(SDRAM_CONF1LL, val);
-
- val = (mfdcr(SDRAM_CONFPATHB) | SDRAM_CONFPATHB_TPEN);
- mtdcr(SDRAM_CONFPATHB, val);
+ mtdcr(SDRAM_CONF1HB, mfdcr(SDRAM_CONF1HB) | SDRAM_CONF1HB_AAFR |
+ SDRAM_CONF1HB_RPEN | SDRAM_CONF1HB_RFTE);
+ mtdcr(SDRAM_CONF1LL, mfdcr(SDRAM_CONF1LL) | SDRAM_CONF1LL_AAFR |
+ SDRAM_CONF1LL_RPEN | SDRAM_CONF1LL_RFTE);
+ mtdcr(SDRAM_CONFPATHB, mfdcr(SDRAM_CONFPATHB) | SDRAM_CONFPATHB_TPEN);
#endif
}
diff --git a/cpu/ppc4xx/cpu_init.c b/cpu/ppc4xx/cpu_init.c
index 281819a..dee9807 100644
--- a/cpu/ppc4xx/cpu_init.c
+++ b/cpu/ppc4xx/cpu_init.c
@@ -138,9 +138,7 @@ void reconfigure_pll(u32 new_cpu_freq)
void
cpu_init_f (void)
{
-#if defined(CONFIG_WATCHDOG) || defined(CONFIG_440GX) || defined(CONFIG_460EX) || \
- defined(CONFIG_440SP) || defined(CONFIG_440SPE) || defined(CONFIG_405EX) || \
- defined(CONFIG_460GT) || defined(CONFIG_460SX)
+#if defined(CONFIG_WATCHDOG) || defined(CONFIG_440GX) || defined(CONFIG_460EX)
u32 val;
#endif
@@ -304,16 +302,17 @@ cpu_init_f (void)
mtsdr(SDR0_USB2HOST_CFG, val);
#endif /* CONFIG_460EX */
-#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+#if defined(CONFIG_405EX) || \
+ defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
- defined(CONFIG_405EX) || defined(CONFIG_460SX)
+ defined(CONFIG_460SX)
/*
* Set PLB4 arbiter (Segment 0 and 1) to 4 deep pipeline read
*/
- val = (mfdcr(plb0_acr) & ~plb0_acr_rdp_mask) | plb0_acr_rdp_4deep;
- mtdcr(plb0_acr, val);
- val = (mfdcr(plb1_acr) & ~plb1_acr_rdp_mask) | plb1_acr_rdp_4deep;
- mtdcr(plb1_acr, val);
+ mtdcr(plb0_acr, (mfdcr(plb0_acr) & ~plb0_acr_rdp_mask) |
+ plb0_acr_rdp_4deep);
+ mtdcr(plb1_acr, (mfdcr(plb1_acr) & ~plb1_acr_rdp_mask) |
+ plb1_acr_rdp_4deep);
#endif /* CONFIG_440SP/SPE || CONFIG_460EX/GT || CONFIG_405EX */
}
diff --git a/include/ppc4xx.h b/include/ppc4xx.h
index e1613dd..59a3b06 100644
--- a/include/ppc4xx.h
+++ b/include/ppc4xx.h
@@ -56,8 +56,8 @@
#define PLB_ARBITER_BASE 0x80
-#define plb0_revid (PLB_ARBITER_BASE+ 0x00)
-#define plb0_acr (PLB_ARBITER_BASE+ 0x01)
+#define plb0_revid (PLB_ARBITER_BASE + 0x00)
+#define plb0_acr (PLB_ARBITER_BASE + 0x01)
#define plb0_acr_ppm_mask 0xF0000000
#define plb0_acr_ppm_fixed 0x00000000
#define plb0_acr_ppm_fair 0xD0000000
@@ -73,13 +73,13 @@
#define plb0_acr_wrp_disabled 0x00000000
#define plb0_acr_wrp_2deep 0x01000000
-#define plb0_besrl (PLB_ARBITER_BASE+ 0x02)
-#define plb0_besrh (PLB_ARBITER_BASE+ 0x03)
-#define plb0_bearl (PLB_ARBITER_BASE+ 0x04)
-#define plb0_bearh (PLB_ARBITER_BASE+ 0x05)
-#define plb0_ccr (PLB_ARBITER_BASE+ 0x08)
+#define plb0_besrl (PLB_ARBITER_BASE + 0x02)
+#define plb0_besrh (PLB_ARBITER_BASE + 0x03)
+#define plb0_bearl (PLB_ARBITER_BASE + 0x04)
+#define plb0_bearh (PLB_ARBITER_BASE + 0x05)
+#define plb0_ccr (PLB_ARBITER_BASE + 0x08)
-#define plb1_acr (PLB_ARBITER_BASE+ 0x09)
+#define plb1_acr (PLB_ARBITER_BASE + 0x09)
#define plb1_acr_ppm_mask 0xF0000000
#define plb1_acr_ppm_fixed 0x00000000
#define plb1_acr_ppm_fair 0xD0000000
@@ -95,10 +95,10 @@
#define plb1_acr_wrp_disabled 0x00000000
#define plb1_acr_wrp_2deep 0x01000000
-#define plb1_besrl (PLB_ARBITER_BASE+ 0x0A)
-#define plb1_besrh (PLB_ARBITER_BASE+ 0x0B)
-#define plb1_bearl (PLB_ARBITER_BASE+ 0x0C)
-#define plb1_bearh (PLB_ARBITER_BASE+ 0x0D)
+#define plb1_besrl (PLB_ARBITER_BASE + 0x0A)
+#define plb1_besrh (PLB_ARBITER_BASE + 0x0B)
+#define plb1_bearl (PLB_ARBITER_BASE + 0x0C)
+#define plb1_bearh (PLB_ARBITER_BASE + 0x0D)
#endif /* 440EP/EPX 440GR/GRX 440SP/SPE 460EX/GT/SX 405EX*/
--
1.5.6.5
1
0

[U-Boot-Users] [PATCH] SPI Flash: Support the ST Microelectronics M25P80 and M25P40 SPI Flash
by Jason McMullan 21 Aug '08
by Jason McMullan 21 Aug '08
21 Aug '08
This commit adds MTD support for the M25P80 (1Mx8) and the M25P40 (512kx8)
SPI Flash components from ST Microelectronics.
Tested with the M25P40, but should work for the M25P80 according
to the spec sheet.
Signed-off-by: Jason McMullan <mcmullan(a)netapp.com>
---
drivers/mtd/spi/Makefile | 1 +
drivers/mtd/spi/spi_flash.c | 5 +
drivers/mtd/spi/spi_flash_internal.h | 1 +
drivers/mtd/spi/stmicro.c | 326 ++++++++++++++++++++++++++++++++++
4 files changed, 333 insertions(+), 0 deletions(-)
create mode 100644 drivers/mtd/spi/stmicro.c
diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile
index af6af97..01b288a 100644
--- a/drivers/mtd/spi/Makefile
+++ b/drivers/mtd/spi/Makefile
@@ -27,6 +27,7 @@ LIB := $(obj)libspi_flash.a
COBJS-$(CONFIG_SPI_FLASH) += spi_flash.o
COBJS-$(CONFIG_SPI_FLASH_ATMEL) += atmel.o
+COBJS-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index d581cb3..dd4d130 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -134,6 +134,11 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
flash = spi_flash_probe_atmel(spi, idcode);
break;
#endif
+#ifdef CONFIG_SPI_FLASH_STMICRO
+ case 0xff:
+ flash = spi_flash_probe_stmicro(spi, idcode);
+ break;
+#endif
default:
debug("SF: Unsupported manufacturer %02X\n", idcode[0]);
flash = NULL;
diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h
index 1438050..e5f758e 100644
--- a/drivers/mtd/spi/spi_flash_internal.h
+++ b/drivers/mtd/spi/spi_flash_internal.h
@@ -43,3 +43,4 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
/* Manufacturer-specific probe functions */
struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode);
struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode);
+struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 *idcode);
diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c
new file mode 100644
index 0000000..cb5a971
--- /dev/null
+++ b/drivers/mtd/spi/stmicro.c
@@ -0,0 +1,326 @@
+/*
+ * $Id$
+ *
+ * Copyright 2008, Network Appliance Inc.
+ * Author: Jason McMullan <mcmullan(a)netapp.com>
+ *
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi_flash.h>
+
+#include "spi_flash_internal.h"
+
+/* M25Pxx-specific commands */
+#define CMD_M25PXX_WREN 0x06 /* Write Enable */
+#define CMD_M25PXX_WRDI 0x04 /* Write Disable */
+#define CMD_M25PXX_RDSR 0x05 /* Read Status Register */
+#define CMD_M25PXX_WRSR 0x01 /* Write Status Register */
+#define CMD_M25PXX_READ 0x03 /* Read Data Bytes */
+#define CMD_M25PXX_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */
+#define CMD_M25PXX_PP 0x02 /* Page Program */
+#define CMD_M25PXX_SE 0xd8 /* Sector Erase */
+#define CMD_M25PXX_BE 0xc7 /* Bulk Erase */
+#define CMD_M25PXX_DP 0xb9 /* Deep Power-down */
+#define CMD_M25PXX_RES 0xab /* Release from DP, and Read Signature */
+
+#define STM_ID_M25P40 0x12
+#define STM_ID_M25P80 0x13
+
+#define STMICRO_SR_WIP (1 << 0) /* Write-in-Progress */
+
+struct stmicro_spi_flash_params {
+ uint8_t idcode1;
+ uint8_t esig;
+ /* Log2 of page size in power-of-two mode */
+ uint8_t l2_page_size;
+ uint16_t pages_per_sector;
+ uint8_t nr_sectors;
+ const char *name;
+};
+
+struct stmicro_spi_flash {
+ const struct stmicro_spi_flash_params *params;
+ struct spi_flash flash;
+};
+
+static inline struct stmicro_spi_flash *
+to_stmicro_spi_flash(struct spi_flash *flash)
+{
+ return container_of(flash, struct stmicro_spi_flash, flash);
+}
+
+static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = {
+ {
+ .idcode1 = 0xff,
+ .esig = STM_ID_M25P40,
+ .l2_page_size = 8,
+ .pages_per_sector = 256,
+ .nr_sectors = 8,
+ .name = "M25P40",
+ },
+ {
+ .idcode1 = 0xff,
+ .esig = STM_ID_M25P80,
+ .l2_page_size = 8,
+ .pages_per_sector = 256,
+ .nr_sectors = 16,
+ .name = "M25P80",
+ },
+};
+
+static int stmicro_wait_ready(struct spi_flash *flash, unsigned long timeout)
+{
+ struct spi_slave *spi = flash->spi;
+ unsigned long timebase;
+ int ret;
+ u8 status;
+ u8 cmd[4] = { CMD_M25PXX_RDSR, 0xff, 0xff, 0xff };
+
+ ret = spi_xfer(spi, 32, &cmd[0], NULL, SPI_XFER_BEGIN);
+ if (ret) {
+ debug("SF: Failed to send command %02x: %d\n", cmd, ret);
+ return ret;
+ }
+
+ timebase = get_timer(0);
+ do {
+ ret = spi_xfer(spi, 8, NULL, &status, 0);
+ if (ret)
+ return -1;
+
+ if ((status & STMICRO_SR_WIP) == 0)
+ break;
+
+ } while (1 || get_timer(timebase) < timeout);
+
+ spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
+
+ if ((status & STMICRO_SR_WIP) == 0)
+ return 0;
+
+ /* Timed out */
+ return -1;
+}
+
+/*
+ * Assemble the address part of a command for STMicro devices in
+ * non-power-of-two page size mode.
+ */
+static void stmicro_build_address(struct stmicro_spi_flash *stm, u8 *cmd, u32 offset)
+{
+ unsigned long page_addr;
+ unsigned long byte_addr;
+ unsigned long page_size;
+ unsigned int page_shift;
+
+ /*
+ * The "extra" space per page is the power-of-two page size
+ * divided by 32.
+ */
+ page_shift = stm->params->l2_page_size;
+ page_size = (1 << page_shift);
+ page_addr = offset / page_size;
+ byte_addr = offset % page_size;
+
+ cmd[0] = page_addr >> (16 - page_shift);
+ cmd[1] = page_addr << (page_shift - 8) | (byte_addr >> 8);
+ cmd[2] = byte_addr;
+}
+
+static int stmicro_read_fast(struct spi_flash *flash,
+ u32 offset, size_t len, void *buf)
+{
+ struct stmicro_spi_flash *stm = to_stmicro_spi_flash(flash);
+ u8 cmd[5];
+
+ cmd[0] = CMD_READ_ARRAY_FAST;
+ stmicro_build_address(stm, cmd + 1, offset);
+ cmd[4] = 0x00;
+
+ return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len);
+}
+
+static int stmicro_write(struct spi_flash *flash,
+ u32 offset, size_t len, const void *buf)
+{
+ struct stmicro_spi_flash *stm = to_stmicro_spi_flash(flash);
+ unsigned long page_addr;
+ unsigned long byte_addr;
+ unsigned long page_size;
+ unsigned int page_shift;
+ size_t chunk_len;
+ size_t actual;
+ int ret;
+ u8 cmd[4];
+
+ page_shift = stm->params->l2_page_size;
+ page_size = (1 << page_shift);
+ page_addr = offset / page_size;
+ byte_addr = offset % page_size;
+
+ ret = spi_claim_bus(flash->spi);
+ if (ret) {
+ debug("SF: Unable to claim SPI bus\n");
+ return ret;
+ }
+
+ for (actual = 0; actual < len; actual += chunk_len) {
+ chunk_len = min(len - actual, page_size - byte_addr);
+
+ cmd[0] = CMD_M25PXX_PP;
+ cmd[1] = page_addr >> (16 - page_shift);
+ cmd[2] = page_addr << (page_shift - 8) | (byte_addr >> 8);
+ cmd[3] = byte_addr;
+ debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %d\n",
+ buf + actual,
+ cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
+
+ ret = spi_flash_cmd(flash->spi, CMD_M25PXX_WREN, NULL, 0);
+ if (ret < 0) {
+ debug("SF: Enabling Write failed\n");
+ goto out;
+ }
+
+ ret = spi_flash_cmd_write(flash->spi, cmd, 4,
+ buf + actual, chunk_len);
+ if (ret < 0) {
+ debug("SF: STMicro Page Program failed\n");
+ goto out;
+ }
+
+ ret = stmicro_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
+ if (ret < 0) {
+ debug("SF: STMicro page programming timed out\n");
+ goto out;
+ }
+
+ page_addr++;
+ byte_addr = 0;
+ }
+
+ debug("SF: STMicro: Successfully programmed %u bytes @ 0x%x\n",
+ len, offset);
+ ret = 0;
+
+out:
+ spi_release_bus(flash->spi);
+ return ret;
+}
+
+int stmicro_erase(struct spi_flash *flash, u32 offset, size_t len)
+{
+ struct stmicro_spi_flash *stm = to_stmicro_spi_flash(flash);
+ unsigned long sector_size;
+ unsigned int page_shift;
+ size_t actual;
+ int ret;
+ u8 cmd[4];
+
+ /*
+ * This function currently uses sector erase only.
+ * probably speed things up by using bulk erase
+ * when possible.
+ */
+
+ page_shift = stm->params->l2_page_size;
+ sector_size = (1 << page_shift) * stm->params->pages_per_sector;
+
+ if (offset % sector_size || len % sector_size) {
+ debug("SF: Erase offset/length not multiple of sector size\n");
+ return -1;
+ }
+
+ len /= sector_size;
+ cmd[0] = CMD_M25PXX_SE;
+ cmd[2] = 0x00;
+ cmd[3] = 0x00;
+
+ ret = spi_claim_bus(flash->spi);
+ if (ret) {
+ debug("SF: Unable to claim SPI bus\n");
+ return ret;
+ }
+
+ for (actual = 0; actual < len; actual++) {
+ cmd[1] = (offset / sector_size) + actual;
+
+ ret = spi_flash_cmd(flash->spi, CMD_M25PXX_WREN, NULL, 0);
+ if (ret < 0) {
+ debug("SF: Enabling Write failed\n");
+ goto out;
+ }
+
+ ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
+ if (ret < 0) {
+ debug("SF: STMicro page erase failed\n");
+ goto out;
+ }
+
+ ret = stmicro_wait_ready(flash, 2 * CFG_HZ); /* Up to 2 seconds */
+ if (ret < 0) {
+ debug("SF: STMicro page erase timed out\n");
+ goto out;
+ }
+ }
+
+ debug("SF: STMicro: Successfully erased %u bytes @ 0x%x\n",
+ len * sector_size, offset);
+ ret = 0;
+
+out:
+ spi_release_bus(flash->spi);
+ return ret;
+}
+
+struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 *idcode)
+{
+ const struct stmicro_spi_flash_params *params;
+ unsigned long page_size;
+ struct stmicro_spi_flash *stm;
+ unsigned int i;
+ int ret;
+ u8 id[4];
+
+ ret = spi_flash_cmd(spi, CMD_M25PXX_RES, id, 4);
+ if (ret)
+ return NULL;
+
+ for (i = 0; i < ARRAY_SIZE(stmicro_spi_flash_table); i++) {
+ params = &stmicro_spi_flash_table[i];
+ if (params->idcode1 == idcode[1] &&
+ params->esig == id[3])
+ break;
+ }
+
+ if (i == ARRAY_SIZE(stmicro_spi_flash_table)) {
+ debug("SF: Unsupported STMicro ID %02x\n",
+ id[3]);
+ return NULL;
+ }
+
+ stm = malloc(sizeof(struct stmicro_spi_flash));
+ if (!stm) {
+ debug("SF: Failed to allocate memory\n");
+ return NULL;
+ }
+
+ stm->params = params;
+ stm->flash.spi = spi;
+ stm->flash.name = params->name;
+
+ /* Assuming power-of-two page size initially. */
+ page_size = 1 << params->l2_page_size;
+
+ stm->flash.write = stmicro_write;
+ stm->flash.erase = stmicro_erase;
+ stm->flash.read = stmicro_read_fast;
+ stm->flash.size = page_size * params->pages_per_sector
+ * params->nr_sectors;
+
+ debug("SF: Detected %s with page size %u, total %u bytes\n",
+ params->name, page_size, stm->flash.size);
+
+ return &stm->flash;
+}
--
1.5.4.3
4
3