summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/nand/diskonchip.c43
-rw-r--r--drivers/mtd/nand/fsl_elbc_nand.c36
-rw-r--r--drivers/mtd/nand/nand_base.c135
-rw-r--r--drivers/mtd/nand/nand_bbt.c2
-rw-r--r--drivers/mtd/nand/nand_ecc.c7
-rw-r--r--drivers/mtd/nand/nand_ids.c3
-rw-r--r--drivers/mtd/nand/nand_util.c30
-rw-r--r--drivers/mtd/onenand/onenand_base.c2
-rw-r--r--drivers/pci/fsl_pci_init.c143
-rw-r--r--drivers/pci/pci.c37
-rw-r--r--drivers/pci/pci_auto.c88
-rw-r--r--drivers/video/atmel_lcdfb.c6
12 files changed, 393 insertions, 139 deletions
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 4cba810..e9dc4d1 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -15,8 +15,6 @@
* converted to the generic Reed-Solomon library by Thomas Gleixner <tglx@linutronix.de>
*
* Interface to generic NAND code for M-Systems DiskOnChip devices
- *
- * $Id: diskonchip.c,v 1.55 2005/11/07 11:14:30 gleixner Exp $
*/
#include <common.h>
@@ -58,13 +56,6 @@ static unsigned long __initdata doc_locations[] = {
0xe0000, 0xe2000, 0xe4000, 0xe6000,
0xe8000, 0xea000, 0xec000, 0xee000,
#endif /* CONFIG_MTD_DOCPROBE_HIGH */
-#elif defined(__PPC__)
- 0xe4000000,
-#elif defined(CONFIG_MOMENCO_OCELOT)
- 0x2f000000,
- 0xff000000,
-#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
- 0xff000000,
#else
#warning Unknown architecture for DiskOnChip. No default probe locations defined
#endif
@@ -229,7 +220,7 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
}
}
/* If the parity is wrong, no rescue possible */
- return parity ? -1 : nerr;
+ return parity ? -EBADMSG : nerr;
}
static void DoC_Delay(struct doc_priv *doc, unsigned short cycles)
@@ -1044,7 +1035,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat,
WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);
else
WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
- if (no_ecc_failures && (ret == -1)) {
+ if (no_ecc_failures && (ret == -EBADMSG)) {
printk(KERN_ERR "suppressing ECC failure\n");
ret = 0;
}
@@ -1139,9 +1130,9 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio
goto out;
mh = (struct NFTLMediaHeader *)buf;
- mh->NumEraseUnits = le16_to_cpu(mh->NumEraseUnits);
- mh->FirstPhysicalEUN = le16_to_cpu(mh->FirstPhysicalEUN);
- mh->FormattedSize = le32_to_cpu(mh->FormattedSize);
+ le16_to_cpus(&mh->NumEraseUnits);
+ le16_to_cpus(&mh->FirstPhysicalEUN);
+ le32_to_cpus(&mh->FormattedSize);
printk(KERN_INFO " DataOrgID = %s\n"
" NumEraseUnits = %d\n"
@@ -1249,12 +1240,12 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partiti
doc->mh1_page = doc->mh0_page + (4096 >> this->page_shift);
mh = (struct INFTLMediaHeader *)buf;
- mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks);
- mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions);
- mh->NoOfBDTLPartitions = le32_to_cpu(mh->NoOfBDTLPartitions);
- mh->BlockMultiplierBits = le32_to_cpu(mh->BlockMultiplierBits);
- mh->FormatFlags = le32_to_cpu(mh->FormatFlags);
- mh->PercentUsed = le32_to_cpu(mh->PercentUsed);
+ le32_to_cpus(&mh->NoOfBootImageBlocks);
+ le32_to_cpus(&mh->NoOfBinaryPartitions);
+ le32_to_cpus(&mh->NoOfBDTLPartitions);
+ le32_to_cpus(&mh->BlockMultiplierBits);
+ le32_to_cpus(&mh->FormatFlags);
+ le32_to_cpus(&mh->PercentUsed);
printk(KERN_INFO " bootRecordID = %s\n"
" NoOfBootImageBlocks = %d\n"
@@ -1291,12 +1282,12 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partiti
/* Scan the partitions */
for (i = 0; (i < 4); i++) {
ip = &(mh->Partitions[i]);
- ip->virtualUnits = le32_to_cpu(ip->virtualUnits);
- ip->firstUnit = le32_to_cpu(ip->firstUnit);
- ip->lastUnit = le32_to_cpu(ip->lastUnit);
- ip->flags = le32_to_cpu(ip->flags);
- ip->spareUnits = le32_to_cpu(ip->spareUnits);
- ip->Reserved0 = le32_to_cpu(ip->Reserved0);
+ le32_to_cpus(&ip->virtualUnits);
+ le32_to_cpus(&ip->firstUnit);
+ le32_to_cpus(&ip->lastUnit);
+ le32_to_cpus(&ip->flags);
+ le32_to_cpus(&ip->spareUnits);
+ le32_to_cpus(&ip->Reserved0);
printk(KERN_INFO " PARTITION[%d] ->\n"
" virtualUnits = %d\n"
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 7dda6c4..367c7d7 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -75,7 +75,7 @@ struct fsl_elbc_ctrl {
struct fsl_elbc_mtd *chips[MAX_BANKS];
/* device info */
- lbus83xx_t *regs;
+ fsl_lbus_t *regs;
u8 __iomem *addr; /* Address of assigned FCM buffer */
unsigned int page; /* Last page written to / read from */
unsigned int read_bytes; /* Number of bytes read during command */
@@ -171,7 +171,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- lbus83xx_t *lbc = ctrl->regs;
+ fsl_lbus_t *lbc = ctrl->regs;
int buf_num;
ctrl->page = page_addr;
@@ -211,7 +211,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- lbus83xx_t *lbc = ctrl->regs;
+ fsl_lbus_t *lbc = ctrl->regs;
long long end_tick;
u32 ltesr;
@@ -261,7 +261,7 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
{
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- lbus83xx_t *lbc = ctrl->regs;
+ fsl_lbus_t *lbc = ctrl->regs;
if (priv->page_size) {
out_be32(&lbc->fir,
@@ -295,7 +295,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- lbus83xx_t *lbc = ctrl->regs;
+ fsl_lbus_t *lbc = ctrl->regs;
ctrl->use_mdr = 0;
@@ -633,7 +633,7 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
{
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- lbus83xx_t *lbc = ctrl->regs;
+ fsl_lbus_t *lbc = ctrl->regs;
if (ctrl->status != LTESR_CC)
return NAND_STATUS_FAIL;
@@ -693,13 +693,15 @@ static struct fsl_elbc_ctrl *elbc_ctrl;
static void fsl_elbc_ctrl_init(void)
{
- immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
-
elbc_ctrl = kzalloc(sizeof(*elbc_ctrl), GFP_KERNEL);
if (!elbc_ctrl)
return;
- elbc_ctrl->regs = &im->lbus;
+#ifdef CONFIG_MPC85xx
+ elbc_ctrl->regs = (void *)CONFIG_SYS_MPC85xx_LBC_ADDR;
+#else
+ elbc_ctrl->regs = &((immap_t *)CONFIG_SYS_IMMR)->lbus;
+#endif
/* clear event registers */
out_be32(&elbc_ctrl->regs->ltesr, LTESR_NAND_MASK);
@@ -775,6 +777,20 @@ int board_nand_init(struct nand_chip *nand)
nand->ecc.read_page = fsl_elbc_read_page;
nand->ecc.write_page = fsl_elbc_write_page;
+#ifdef CONFIG_FSL_ELBC_FMR
+ priv->fmr = CONFIG_FSL_ELBC_FMR;
+#else
+ priv->fmr = (15 << FMR_CWTO_SHIFT) | (2 << FMR_AL_SHIFT);
+
+ /*
+ * Hardware expects small page has ECCM0, large page has ECCM1
+ * when booting from NAND. Board config can override if not
+ * booting from NAND.
+ */
+ if (or & OR_FCM_PGS)
+ priv->fmr |= FMR_ECCM;
+#endif
+
/* If CS Base Register selects full hardware ECC then use it */
if ((br & BR_DECC) == BR_DECC_CHK_GEN) {
nand->ecc.mode = NAND_ECC_HW;
@@ -791,8 +807,6 @@ int board_nand_init(struct nand_chip *nand)
nand->ecc.mode = NAND_ECC_SOFT;
}
- priv->fmr = (15 << FMR_CWTO_SHIFT) | (2 << FMR_AL_SHIFT);
-
/* Large-page-specific setup */
if (or & OR_FCM_PGS) {
priv->page_size = 1;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index fe34a48..ba05b76 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -7,7 +7,7 @@
* Basic support for AG-AND chips is provided.
*
* Additional technical information is available on
- * http://www.linux-mtd.infradead.org/tech/nand.html
+ * http://www.linux-mtd.infradead.org/doc/nand.html
*
* Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
* 2002-2006 Thomas Gleixner (tglx@linutronix.de)
@@ -24,6 +24,7 @@
* if we have HW ecc support.
* The AG-AND chips have nice features for speed improvement,
* which are not supported yet. Read / program 4 pages in one go.
+ * BBT table is not serialized, has to be fixed
*
* 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
@@ -128,7 +129,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
static int nand_wait(struct mtd_info *mtd, struct nand_chip *this);
/*
- * For devices which display every fart in the system on a seperate LED. Is
+ * For devices which display every fart in the system on a separate LED. Is
* compiled away when LED support is disabled.
*/
/* XXX U-BOOT XXX */
@@ -412,6 +413,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
/* We write two bytes, so we dont have to mess with 16 bit
* access
*/
+ nand_get_device(chip, mtd, FL_WRITING);
ofs += mtd->oobsize;
chip->ops.len = chip->ops.ooblen = 2;
chip->ops.datbuf = NULL;
@@ -419,9 +421,11 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
chip->ops.ooboffs = chip->badblockpos & ~0x01;
ret = nand_do_write_oob(mtd, ofs, &chip->ops);
+ nand_release_device(mtd);
}
if (!ret)
mtd->ecc_stats.badblocks++;
+
return ret;
}
@@ -911,7 +915,88 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
int stat;
stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
- if (stat == -1)
+ if (stat < 0)
+ mtd->ecc_stats.failed++;
+ else
+ mtd->ecc_stats.corrected += stat;
+ }
+ return 0;
+}
+
+/**
+ * nand_read_subpage - [REPLACABLE] software ecc based sub-page read function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @dataofs offset of requested data within the page
+ * @readlen data length
+ * @buf: buffer to store read data
+ */
+static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi)
+{
+ int start_step, end_step, num_steps;
+ uint32_t *eccpos = chip->ecc.layout->eccpos;
+ uint8_t *p;
+ int data_col_addr, i, gaps = 0;
+ int datafrag_len, eccfrag_len, aligned_len, aligned_pos;
+ int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1;
+
+ /* Column address wihin the page aligned to ECC size (256bytes). */
+ start_step = data_offs / chip->ecc.size;
+ end_step = (data_offs + readlen - 1) / chip->ecc.size;
+ num_steps = end_step - start_step + 1;
+
+ /* Data size aligned to ECC ecc.size*/
+ datafrag_len = num_steps * chip->ecc.size;
+ eccfrag_len = num_steps * chip->ecc.bytes;
+
+ data_col_addr = start_step * chip->ecc.size;
+ /* If we read not a page aligned data */
+ if (data_col_addr != 0)
+ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_col_addr, -1);
+
+ p = bufpoi + data_col_addr;
+ chip->read_buf(mtd, p, datafrag_len);
+
+ /* Calculate ECC */
+ for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size)
+ chip->ecc.calculate(mtd, p, &chip->buffers->ecccalc[i]);
+
+ /* The performance is faster if to position offsets
+ according to ecc.pos. Let make sure here that
+ there are no gaps in ecc positions */
+ for (i = 0; i < eccfrag_len - 1; i++) {
+ if (eccpos[i + start_step * chip->ecc.bytes] + 1 !=
+ eccpos[i + start_step * chip->ecc.bytes + 1]) {
+ gaps = 1;
+ break;
+ }
+ }
+ if (gaps) {
+ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
+ chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+ } else {
+ /* send the command to read the particular ecc bytes */
+ /* take care about buswidth alignment in read_buf */
+ aligned_pos = eccpos[start_step * chip->ecc.bytes] & ~(busw - 1);
+ aligned_len = eccfrag_len;
+ if (eccpos[start_step * chip->ecc.bytes] & (busw - 1))
+ aligned_len++;
+ if (eccpos[(start_step + num_steps) * chip->ecc.bytes] & (busw - 1))
+ aligned_len++;
+
+ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize + aligned_pos, -1);
+ chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len);
+ }
+
+ for (i = 0; i < eccfrag_len; i++)
+ chip->buffers->ecccode[i] = chip->oob_poi[eccpos[i + start_step * chip->ecc.bytes]];
+
+ p = bufpoi + data_col_addr;
+ for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) {
+ int stat;
+
+ stat = chip->ecc.correct(mtd, p, &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]);
+ if (stat < 0)
mtd->ecc_stats.failed++;
else
mtd->ecc_stats.corrected += stat;
@@ -996,7 +1081,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
chip->read_buf(mtd, oob, eccbytes);
stat = chip->ecc.correct(mtd, p, oob, NULL);
- if (stat == -1)
+ if (stat < 0)
mtd->ecc_stats.failed++;
else
mtd->ecc_stats.corrected += stat;
@@ -1116,6 +1201,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
/* Now read the page into the buffer */
if (unlikely(ops->mode == MTD_OOB_RAW))
ret = chip->ecc.read_page_raw(mtd, chip, bufpoi);
+ else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob)
+ ret = chip->ecc.read_subpage(mtd, chip, col, bytes, bufpoi);
else
ret = chip->ecc.read_page(mtd, chip, bufpoi);
if (ret < 0)
@@ -1123,7 +1210,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
/* Transfer not aligned data */
if (!aligned) {
- chip->pagebuf = realpage;
+ if (!NAND_SUBPAGE_READ(chip) && !oob)
+ chip->pagebuf = realpage;
memcpy(buf, chip->buffers->databuf + col, bytes);
}
@@ -2193,13 +2281,14 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
erase_exit:
ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
- /* Do call back function */
- if (!ret)
- mtd_erase_callback(instr);
/* Deselect and wake up anyone waiting on the device */
nand_release_device(mtd);
+ /* Do call back function */
+ if (!ret)
+ mtd_erase_callback(instr);
+
/*
* If BBT requires refresh and erase was successful, rewrite any
* selected bad block tables
@@ -2356,10 +2445,17 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
{
struct nand_flash_dev *type = NULL;
int i, dev_id, maf_idx;
+ int tmp_id, tmp_manf;
/* Select the device */
chip->select_chip(mtd, 0);
+ /*
+ * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
+ * after power-up
+ */
+ chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+
/* Send the command for reading device ID */
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
@@ -2367,6 +2463,26 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
*maf_id = chip->read_byte(mtd);
dev_id = chip->read_byte(mtd);
+ /* Try again to make sure, as some systems the bus-hold or other
+ * interface concerns can cause random data which looks like a
+ * possibly credible NAND flash to appear. If the two results do
+ * not match, ignore the device completely.
+ */
+
+ chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
+
+ /* Read manufacturer and device IDs */
+
+ tmp_manf = chip->read_byte(mtd);
+ tmp_id = chip->read_byte(mtd);
+
+ if (tmp_manf != *maf_id || tmp_id != dev_id) {
+ printk(KERN_INFO "%s: second ID read did not match "
+ "%02x,%02x against %02x,%02x\n", __func__,
+ *maf_id, dev_id, tmp_manf, tmp_id);
+ return ERR_PTR(-ENODEV);
+ }
+
/* Lookup the flash id */
for (i = 0; nand_flash_ids[i].name != NULL; i++) {
if (dev_id == nand_flash_ids[i].id) {
@@ -2510,6 +2626,8 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips)
/* Check for a chip array */
for (i = 1; i < maxchips; i++) {
chip->select_chip(mtd, i);
+ /* See comment in nand_get_flash_type for reset */
+ chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
/* Send the command for reading device ID */
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
/* Read manufacturer and device IDs */
@@ -2630,6 +2748,7 @@ int nand_scan_tail(struct mtd_info *mtd)
chip->ecc.calculate = nand_calculate_ecc;
chip->ecc.correct = nand_correct_data;
chip->ecc.read_page = nand_read_page_swecc;
+ chip->ecc.read_subpage = nand_read_subpage;
chip->ecc.write_page = nand_write_page_swecc;
chip->ecc.read_oob = nand_read_oob_std;
chip->ecc.write_oob = nand_write_oob_std;
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index b3b740d..d68a315f 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -6,8 +6,6 @@
*
* Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
*
- * $Id: nand_bbt.c,v 1.36 2005/11/07 11:14:30 gleixner Exp $
- *
* 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.
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c
index ee1f6cc..94923b9 100644
--- a/drivers/mtd/nand/nand_ecc.c
+++ b/drivers/mtd/nand/nand_ecc.c
@@ -9,8 +9,6 @@
*
* Copyright (C) 2006 Thomas Gleixner <tglx@linutronix.de>
*
- * $Id: nand_ecc.c,v 1.15 2005/11/07 11:14:30 gleixner Exp $
- *
* This file 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 or (at your option) any
@@ -47,7 +45,8 @@
#include <linux/mtd/nand_ecc.h>
#endif
-#include<linux/mtd/mtd.h>
+#include <asm/errno.h>
+#include <linux/mtd/mtd.h>
/*
* NAND-SPL has no sofware ECC for now, so don't include nand_calculate_ecc(),
@@ -206,7 +205,7 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat,
if(countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 <<16)) == 1)
return 1;
- return -1;
+ return -EBADMSG;
}
/* XXX U-BOOT XXX */
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index 2ff75c9..077c305 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -3,8 +3,6 @@
*
* Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de)
*
- * $Id: nand_ids.c,v 1.16 2005/11/07 11:14:31 gleixner Exp $
- *
* 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.
@@ -142,5 +140,6 @@ struct nand_manufacturers nand_manuf_ids[] = {
{NAND_MFR_STMICRO, "ST Micro"},
{NAND_MFR_HYNIX, "Hynix"},
{NAND_MFR_MICRON, "Micron"},
+ {NAND_MFR_AMD, "AMD"},
{0x0, "Unknown"}
};
diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c
index 52b3d21..149af83 100644
--- a/drivers/mtd/nand/nand_util.c
+++ b/drivers/mtd/nand/nand_util.c
@@ -78,9 +78,7 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
const char *mtd_device = meminfo->name;
struct mtd_oob_ops oob_opts;
struct nand_chip *chip = meminfo->priv;
- uint8_t buf[64];
- memset(buf, 0, sizeof(buf));
memset(&erase, 0, sizeof(erase));
memset(&oob_opts, 0, sizeof(oob_opts));
@@ -89,13 +87,9 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
erase.addr = opts->offset;
erase_length = opts->length;
-
cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
cleanmarker.totlen = cpu_to_je32(8);
- cleanmarker.hdr_crc = cpu_to_je32(
- crc32_no_comp(0, (unsigned char *) &cleanmarker,
- sizeof(struct jffs2_unknown_node) - 4));
/* scrub option allows to erase badblock. To prevent internal
* check from erase() method, set block check method to dummy
@@ -154,23 +148,21 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
}
/* format for JFFS2 ? */
- if (opts->jffs2) {
-
- chip->ops.len = chip->ops.ooblen = 64;
+ if (opts->jffs2 && chip->ecc.layout->oobavail >= 8) {
+ chip->ops.ooblen = 8;
chip->ops.datbuf = NULL;
- chip->ops.oobbuf = buf;
- chip->ops.ooboffs = chip->badblockpos & ~0x01;
+ chip->ops.oobbuf = (uint8_t *)&cleanmarker;
+ chip->ops.ooboffs = 0;
+ chip->ops.mode = MTD_OOB_AUTO;
result = meminfo->write_oob(meminfo,
- erase.addr + meminfo->oobsize,
- &chip->ops);
+ erase.addr,
+ &chip->ops);
if (result != 0) {
printf("\n%s: MTD writeoob failure: %d\n",
- mtd_device, result);
+ mtd_device, result);
continue;
}
- else
- printf("%s: MTD writeoob at 0x%08x\n",mtd_device, erase.addr + meminfo->oobsize );
}
if (!opts->quiet) {
@@ -190,11 +182,11 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
percent_complete = percent;
printf("\rErasing at 0x%x -- %3d%% complete.",
- erase.addr, percent);
+ erase.addr, percent);
if (opts->jffs2 && result == 0)
- printf(" Cleanmarker written at 0x%x.",
- erase.addr);
+ printf(" Cleanmarker written at 0x%x.",
+ erase.addr);
}
}
}
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index c22a8a8..9b7bf3a 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -1428,7 +1428,7 @@ int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
MTDDEBUG (MTD_DEBUG_LEVEL3,
"onenand_erase: start = 0x%08x, len = %i\n",
- (unsigned int)instr->addr, (unsigned int)ins tr->len);
+ (unsigned int)instr->addr, (unsigned int)instr->len);
block_size = (1 << this->erase_shift);
diff --git a/drivers/pci/fsl_pci_init.c b/drivers/pci/fsl_pci_init.c
index 38a16e5..7625ccc 100644
--- a/drivers/pci/fsl_pci_init.c
+++ b/drivers/pci/fsl_pci_init.c
@@ -18,6 +18,8 @@
#include <common.h>
+DECLARE_GLOBAL_DATA_PTR;
+
/*
* PCI/PCIE Controller initialization for mpc85xx/mpc86xx soc's
*
@@ -39,10 +41,92 @@ void pciauto_prescan_setup_bridge(struct pci_controller *hose,
pci_dev_t dev, int sub_bus);
void pciauto_postscan_setup_bridge(struct pci_controller *hose,
pci_dev_t dev, int sub_bus);
-
void pciauto_config_init(struct pci_controller *hose);
-void
-fsl_pci_init(struct pci_controller *hose)
+
+#ifndef CONFIG_SYS_PCI_MEMORY_BUS
+#define CONFIG_SYS_PCI_MEMORY_BUS 0
+#endif
+
+#ifndef CONFIG_SYS_PCI_MEMORY_PHYS
+#define CONFIG_SYS_PCI_MEMORY_PHYS 0
+#endif
+
+#if defined(CONFIG_SYS_PCI_64BIT) && !defined(CONFIG_SYS_PCI64_MEMORY_BUS)
+#define CONFIG_SYS_PCI64_MEMORY_BUS (64ull*1024*1024*1024)
+#endif
+
+int fsl_pci_setup_inbound_windows(struct pci_region *r)
+{
+ struct pci_region *rgn_base = r;
+ u64 sz = min((u64)gd->ram_size, 1ull << 32);
+
+ phys_addr_t phys_start = CONFIG_SYS_PCI_MEMORY_PHYS;
+ pci_addr_t bus_start = CONFIG_SYS_PCI_MEMORY_BUS;
+ pci_size_t pci_sz = 1ull << __ilog2_u64(sz);
+
+ debug ("R0 bus_start: %llx phys_start: %llx size: %llx\n",
+ (u64)bus_start, (u64)phys_start, (u64)pci_sz);
+ pci_set_region(r++, bus_start, phys_start, pci_sz,
+ PCI_REGION_MEM | PCI_REGION_MEMORY |
+ PCI_REGION_PREFETCH);
+
+ sz -= pci_sz;
+ bus_start += pci_sz;
+ phys_start += pci_sz;
+
+ pci_sz = 1ull << __ilog2_u64(sz);
+ if (sz) {
+ debug ("R1 bus_start: %llx phys_start: %llx size: %llx\n",
+ (u64)bus_start, (u64)phys_start, (u64)pci_sz);
+ pci_set_region(r++, bus_start, phys_start, pci_sz,
+ PCI_REGION_MEM | PCI_REGION_MEMORY |
+ PCI_REGION_PREFETCH);
+ sz -= pci_sz;
+ bus_start += pci_sz;
+ phys_start += pci_sz;
+ }
+
+#if defined(CONFIG_PHYS_64BIT) && defined(CONFIG_SYS_PCI_64BIT)
+ /*
+ * On 64-bit capable systems, set up a mapping for all of DRAM
+ * in high pci address space.
+ */
+ pci_sz = 1ull << __ilog2_u64(gd->ram_size);
+ /* round up to the next largest power of two */
+ if (gd->ram_size > pci_sz)
+ pci_sz = 1ull << (__ilog2_u64(gd->ram_size) + 1);
+ debug ("R64 bus_start: %llx phys_start: %llx size: %llx\n",
+ (u64)CONFIG_SYS_PCI64_MEMORY_BUS,
+ (u64)CONFIG_SYS_PCI_MEMORY_PHYS,
+ (u64)pci_sz);
+ pci_set_region(r++,
+ CONFIG_SYS_PCI64_MEMORY_BUS,
+ CONFIG_SYS_PCI_MEMORY_PHYS,
+ pci_sz,
+ PCI_REGION_MEM | PCI_REGION_MEMORY |
+ PCI_REGION_PREFETCH);
+#else
+ pci_sz = 1ull << __ilog2_u64(sz);
+ if (sz) {
+ debug ("R2 bus_start: %llx phys_start: %llx size: %llx\n",
+ (u64)bus_start, (u64)phys_start, (u64)pci_sz);
+ pci_set_region(r++, bus_start, phys_start, pci_sz,
+ PCI_REGION_MEM | PCI_REGION_MEMORY |
+ PCI_REGION_PREFETCH);
+ sz -= pci_sz;
+ bus_start += pci_sz;
+ phys_start += pci_sz;
+ }
+#endif
+
+ if (sz && (((u64)gd->ram_size) < (1ull << 32)))
+ printf("Was not able to map all of memory via "
+ "inbound windows -- %lld remaining\n", sz);
+
+ return r - rgn_base;
+}
+
+void fsl_pci_init(struct pci_controller *hose)
{
u16 temp16;
u32 temp32;
@@ -65,25 +149,36 @@ fsl_pci_init(struct pci_controller *hose)
#endif
for (r=0; r<hose->region_count; r++) {
+ u32 sz = (__ilog2_u64((u64)hose->regions[r].size) - 1);
if (hose->regions[r].flags & PCI_REGION_MEMORY) { /* inbound */
- pi->pitar = (hose->regions[r].bus_start >> 12) & 0x000fffff;
- pi->piwbar = (hose->regions[r].phys_start >> 12) & 0x000fffff;
+ u32 flag = PIWAR_EN | PIWAR_LOCAL |
+ PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP;
+ pi->pitar = (hose->regions[r].phys_start >> 12);
+ pi->piwbar = (hose->regions[r].bus_start >> 12);
+#ifdef CONFIG_SYS_PCI_64BIT
+ pi->piwbear = (hose->regions[r].bus_start >> 44);
+#else
pi->piwbear = 0;
- pi->piwar = PIWAR_EN | PIWAR_PF | PIWAR_LOCAL |
- PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP |
- (__ilog2(hose->regions[r].size) - 1);
+#endif
+ if (hose->regions[r].flags & PCI_REGION_PREFETCH)
+ flag |= PIWAR_PF;
+ pi->piwar = flag | sz;
pi++;
inbound = hose->regions[r].size > 0;
} else { /* Outbound */
- po->powbar = (hose->regions[r].phys_start >> 12) & 0x000fffff;
- po->potar = (hose->regions[r].bus_start >> 12) & 0x000fffff;
+ po->powbar = (hose->regions[r].phys_start >> 12);
+ po->potar = (hose->regions[r].bus_start >> 12);
+#ifdef CONFIG_SYS_PCI_64BIT
+ po->potear = (hose->regions[r].bus_start >> 44);
+#else
po->potear = 0;
+#endif
if (hose->regions[r].flags & PCI_REGION_IO)
- po->powar = POWAR_EN | POWAR_IO_READ | POWAR_IO_WRITE |
- (__ilog2(hose->regions[r].size) - 1);
+ po->powar = POWAR_EN | sz |
+ POWAR_IO_READ | POWAR_IO_WRITE;
else
- po->powar = POWAR_EN | POWAR_MEM_READ | POWAR_MEM_WRITE |
- (__ilog2(hose->regions[r].size) - 1);
+ po->powar = POWAR_EN | sz |
+ POWAR_MEM_READ | POWAR_MEM_WRITE;
po++;
}
}
@@ -208,3 +303,23 @@ fsl_pci_init(struct pci_controller *hose)
pci_hose_write_config_word(hose, dev, PCI_SEC_STATUS, 0xffff);
}
}
+
+#ifdef CONFIG_OF_BOARD_SETUP
+#include <libfdt.h>
+#include <fdt_support.h>
+
+void ft_fsl_pci_setup(void *blob, const char *pci_alias,
+ struct pci_controller *hose)
+{
+ int off = fdt_path_offset(blob, pci_alias);
+
+ if (off >= 0) {
+ u32 bus_range[2];
+
+ bus_range[0] = 0;
+ bus_range[1] = hose->last_busno - hose->first_busno;
+ fdt_setprop(blob, off, "bus-range", &bus_range[0], 2*4);
+ fdt_pci_dma_ranges(blob, off, hose);
+ }
+}
+#endif
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 41780db..e2b05d8 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -218,12 +218,12 @@ pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index)
*
*/
-unsigned long pci_hose_phys_to_bus (struct pci_controller *hose,
+pci_addr_t pci_hose_phys_to_bus (struct pci_controller *hose,
phys_addr_t phys_addr,
unsigned long flags)
{
struct pci_region *res;
- unsigned long bus_addr;
+ pci_addr_t bus_addr;
int i;
if (!hose) {
@@ -252,7 +252,7 @@ Done:
}
phys_addr_t pci_hose_bus_to_phys(struct pci_controller* hose,
- unsigned long bus_addr,
+ pci_addr_t bus_addr,
unsigned long flags)
{
struct pci_region *res;
@@ -288,15 +288,17 @@ Done:
int pci_hose_config_device(struct pci_controller *hose,
pci_dev_t dev,
unsigned long io,
- unsigned long mem,
+ pci_addr_t mem,
unsigned long command)
{
- unsigned int bar_response, bar_size, bar_value, old_command;
+ unsigned int bar_response, old_command;
+ pci_addr_t bar_value;
+ pci_size_t bar_size;
unsigned char pin;
int bar, found_mem64;
- debug ("PCI Config: I/O=0x%lx, Memory=0x%lx, Command=0x%lx\n",
- io, mem, command);
+ debug ("PCI Config: I/O=0x%lx, Memory=0x%llx, Command=0x%lx\n",
+ io, (u64)mem, command);
pci_hose_write_config_dword (hose, dev, PCI_COMMAND, 0);
@@ -319,10 +321,19 @@ int pci_hose_config_device(struct pci_controller *hose,
io = io + bar_size;
} else {
if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
- PCI_BASE_ADDRESS_MEM_TYPE_64)
- found_mem64 = 1;
+ PCI_BASE_ADDRESS_MEM_TYPE_64) {
+ u32 bar_response_upper;
+ u64 bar64;
+ pci_hose_write_config_dword(hose, dev, bar+4, 0xffffffff);
+ pci_hose_read_config_dword(hose, dev, bar+4, &bar_response_upper);
- bar_size = ~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1;
+ bar64 = ((u64)bar_response_upper << 32) | bar_response;
+
+ bar_size = ~(bar64 & PCI_BASE_ADDRESS_MEM_MASK) + 1;
+ found_mem64 = 1;
+ } else {
+ bar_size = (u32)(~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1);
+ }
/* round up region base address to multiple of size */
mem = ((mem - 1) | (bar_size - 1)) + 1;
@@ -332,11 +343,15 @@ int pci_hose_config_device(struct pci_controller *hose,
}
/* Write it out and update our limit */
- pci_hose_write_config_dword (hose, dev, bar, bar_value);
+ pci_hose_write_config_dword (hose, dev, bar, (u32)bar_value);
if (found_mem64) {
bar += 4;
+#ifdef CONFIG_SYS_PCI_64BIT
+ pci_hose_write_config_dword(hose, dev, bar, (u32)(bar_value>>32));
+#else
pci_hose_write_config_dword (hose, dev, bar, 0x00000000);
+#endif
}
}
diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c
index 3844359..c20b981 100644
--- a/drivers/pci/pci_auto.c
+++ b/drivers/pci/pci_auto.c
@@ -45,14 +45,14 @@ void pciauto_region_init(struct pci_region* res)
res->bus_lower = res->bus_start ? res->bus_start : 0x1000;
}
-void pciauto_region_align(struct pci_region *res, unsigned long size)
+void pciauto_region_align(struct pci_region *res, pci_size_t size)
{
res->bus_lower = ((res->bus_lower - 1) | (size - 1)) + 1;
}
-int pciauto_region_allocate(struct pci_region* res, unsigned int size, unsigned int *bar)
+int pciauto_region_allocate(struct pci_region* res, pci_size_t size, pci_addr_t *bar)
{
- unsigned long addr;
+ pci_addr_t addr;
if (!res) {
DEBUGF("No resource");
@@ -68,13 +68,13 @@ int pciauto_region_allocate(struct pci_region* res, unsigned int size, unsigned
res->bus_lower = addr + size;
- DEBUGF("address=0x%lx bus_lower=%x", addr, res->bus_lower);
+ DEBUGF("address=0x%llx bus_lower=0x%llx", (u64)addr, (u64)res->bus_lower);
*bar = addr;
return 0;
error:
- *bar = 0xffffffff;
+ *bar = (pci_addr_t)-1;
return -1;
}
@@ -88,7 +88,9 @@ void pciauto_setup_device(struct pci_controller *hose,
struct pci_region *prefetch,
struct pci_region *io)
{
- unsigned int bar_value, bar_response, bar_size;
+ unsigned int bar_response;
+ pci_addr_t bar_value;
+ pci_size_t bar_size;
unsigned int cmdstat = 0;
struct pci_region *bar_res;
int bar, bar_nr = 0;
@@ -114,33 +116,46 @@ void pciauto_setup_device(struct pci_controller *hose,
& 0xffff) + 1;
bar_res = io;
- DEBUGF("PCI Autoconfig: BAR %d, I/O, size=0x%x, ", bar_nr, bar_size);
+ DEBUGF("PCI Autoconfig: BAR %d, I/O, size=0x%llx, ", bar_nr, (u64)bar_size);
} else {
if ( (bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
- PCI_BASE_ADDRESS_MEM_TYPE_64)
- found_mem64 = 1;
+ PCI_BASE_ADDRESS_MEM_TYPE_64) {
+ u32 bar_response_upper;
+ u64 bar64;
+ pci_hose_write_config_dword(hose, dev, bar+4, 0xffffffff);
+ pci_hose_read_config_dword(hose, dev, bar+4, &bar_response_upper);
+
+ bar64 = ((u64)bar_response_upper << 32) | bar_response;
- bar_size = ~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1;
+ bar_size = ~(bar64 & PCI_BASE_ADDRESS_MEM_MASK) + 1;
+ found_mem64 = 1;
+ } else {
+ bar_size = (u32)(~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1);
+ }
if (prefetch && (bar_response & PCI_BASE_ADDRESS_MEM_PREFETCH))
bar_res = prefetch;
else
bar_res = mem;
- DEBUGF("PCI Autoconfig: BAR %d, Mem, size=0x%x, ", bar_nr, bar_size);
+ DEBUGF("PCI Autoconfig: BAR %d, Mem, size=0x%llx, ", bar_nr, (u64)bar_size);
}
if (pciauto_region_allocate(bar_res, bar_size, &bar_value) == 0) {
/* Write it out and update our limit */
- pci_hose_write_config_dword(hose, dev, bar, bar_value);
+ pci_hose_write_config_dword(hose, dev, bar, (u32)bar_value);
- /*
- * If we are a 64-bit decoder then increment to the
- * upper 32 bits of the bar and force it to locate
- * in the lower 4GB of memory.
- */
if (found_mem64) {
bar += 4;
+#ifdef CONFIG_SYS_PCI_64BIT
+ pci_hose_write_config_dword(hose, dev, bar, (u32)(bar_value>>32));
+#else
+ /*
+ * If we are a 64-bit decoder then increment to the
+ * upper 32 bits of the bar and force it to locate
+ * in the lower 4GB of memory.
+ */
pci_hose_write_config_dword(hose, dev, bar, 0x00000000);
+#endif
}
cmdstat |= (bar_response & PCI_BASE_ADDRESS_SPACE) ?
@@ -289,35 +304,36 @@ void pciauto_config_init(struct pci_controller *hose)
if (hose->pci_mem) {
pciauto_region_init(hose->pci_mem);
- DEBUGF("PCI Autoconfig: Bus Memory region: [%lx-%lx],\n"
- "\t\tPhysical Memory [%x-%x]\n",
- hose->pci_mem->bus_start,
- hose->pci_mem->bus_start + hose->pci_mem->size - 1,
- hose->pci_mem->phys_start,
- hose->pci_mem->phys_start + hose->pci_mem->size - 1);
+ DEBUGF("PCI Autoconfig: Bus Memory region: [0x%llx-0x%llx],\n"
+ "\t\tPhysical Memory [%llx-%llxx]\n",
+ (u64)hose->pci_mem->bus_start,
+ (u64)(hose->pci_mem->bus_start + hose->pci_mem->size - 1),
+ (u64)hose->pci_mem->phys_start,
+ (u64)(hose->pci_mem->phys_start + hose->pci_mem->size - 1));
}
if (hose->pci_prefetch) {
pciauto_region_init(hose->pci_prefetch);
- DEBUGF("PCI Autoconfig: Bus Prefetchable Mem: [%lx-%lx],\n"
- "\t\tPhysical Memory [%x-%x]\n",
- hose->pci_prefetch->bus_start,
- hose->pci_prefetch->bus_start + hose->pci_prefetch->size - 1,
- hose->pci_prefetch->phys_start,
- hose->pci_prefetch->phys_start +
- hose->pci_prefetch->size - 1);
+ DEBUGF("PCI Autoconfig: Bus Prefetchable Mem: [0x%llx-0x%llx],\n"
+ "\t\tPhysical Memory [%llx-%llx]\n",
+ (u64)hose->pci_prefetch->bus_start,
+ (u64)(hose->pci_prefetch->bus_start +
+ hose->pci_prefetch->size - 1),
+ (u64)hose->pci_prefetch->phys_start,
+ (u64)(hose->pci_prefetch->phys_start +
+ hose->pci_prefetch->size - 1));
}
if (hose->pci_io) {
pciauto_region_init(hose->pci_io);
- DEBUGF("PCI Autoconfig: Bus I/O region: [%lx-%lx],\n"
- "\t\tPhysical Memory: [%x-%x]\n",
- hose->pci_io->bus_start,
- hose->pci_io->bus_start + hose->pci_io->size - 1,
- hose->pci_io->phys_start,
- hose->pci_io->phys_start + hose->pci_io->size - 1);
+ DEBUGF("PCI Autoconfig: Bus I/O region: [0x%llx-0x%llx],\n"
+ "\t\tPhysical Memory: [%llx-%llx]\n",
+ (u64)hose->pci_io->bus_start,
+ (u64)(hose->pci_io->bus_start + hose->pci_io->size - 1),
+ (u64)hose->pci_io->phys_start,
+ (u64)(hose->pci_io->phys_start + hose->pci_io->size - 1));
}
}
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index b332a82..3a51cc7 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -24,7 +24,6 @@
#include <common.h>
#include <asm/io.h>
-#include <asm/arch/hardware.h>
#include <asm/arch/gpio.h>
#include <asm/arch/clk.h>
#include <lcd.h>
@@ -108,10 +107,7 @@ void lcd_ctrl_init(void *lcdbase)
if (panel_info.vl_tft)
value |= ATMEL_LCDC_DISTYPE_TFT;
- if (!(panel_info.vl_sync & ATMEL_LCDC_INVLINE_INVERTED))
- value |= ATMEL_LCDC_INVLINE_INVERTED;
- if (!(panel_info.vl_sync & ATMEL_LCDC_INVFRAME_INVERTED))
- value |= ATMEL_LCDC_INVFRAME_INVERTED;
+ value |= panel_info.vl_sync;
value |= (panel_info.vl_bpix << 5);
lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDCON2, value);