Merge branch 'next'
This commit is contained in:
@@ -385,34 +385,38 @@ static int Spartan3_ss_load (Xilinx_desc * desc, void *buf, size_t bsize)
|
||||
} while ((*fn->init) (cookie));
|
||||
|
||||
/* Load the data */
|
||||
while (bytecount < bsize) {
|
||||
if(*fn->bwr)
|
||||
(*fn->bwr) (data, bsize, TRUE, cookie);
|
||||
else {
|
||||
while (bytecount < bsize) {
|
||||
|
||||
/* Xilinx detects an error if INIT goes low (active)
|
||||
while DONE is low (inactive) */
|
||||
if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
|
||||
puts ("** CRC error during FPGA load.\n");
|
||||
return (FPGA_FAIL);
|
||||
}
|
||||
val = data [bytecount ++];
|
||||
i = 8;
|
||||
do {
|
||||
/* Deassert the clock */
|
||||
(*fn->clk) (FALSE, TRUE, cookie);
|
||||
CONFIG_FPGA_DELAY ();
|
||||
/* Write data */
|
||||
(*fn->wr) ((val & 0x80), TRUE, cookie);
|
||||
CONFIG_FPGA_DELAY ();
|
||||
/* Assert the clock */
|
||||
(*fn->clk) (TRUE, TRUE, cookie);
|
||||
CONFIG_FPGA_DELAY ();
|
||||
val <<= 1;
|
||||
i --;
|
||||
} while (i > 0);
|
||||
/* Xilinx detects an error if INIT goes low (active)
|
||||
while DONE is low (inactive) */
|
||||
if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
|
||||
puts ("** CRC error during FPGA load.\n");
|
||||
return (FPGA_FAIL);
|
||||
}
|
||||
val = data [bytecount ++];
|
||||
i = 8;
|
||||
do {
|
||||
/* Deassert the clock */
|
||||
(*fn->clk) (FALSE, TRUE, cookie);
|
||||
CONFIG_FPGA_DELAY ();
|
||||
/* Write data */
|
||||
(*fn->wr) ((val & 0x80), TRUE, cookie);
|
||||
CONFIG_FPGA_DELAY ();
|
||||
/* Assert the clock */
|
||||
(*fn->clk) (TRUE, TRUE, cookie);
|
||||
CONFIG_FPGA_DELAY ();
|
||||
val <<= 1;
|
||||
i --;
|
||||
} while (i > 0);
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
if (bytecount % (bsize / 40) == 0)
|
||||
putc ('.'); /* let them know we are alive */
|
||||
if (bytecount % (bsize / 40) == 0)
|
||||
putc ('.'); /* let them know we are alive */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
CONFIG_FPGA_DELAY ();
|
||||
|
||||
@@ -36,8 +36,6 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||
#define PSC_BASE MPC5XXX_PSC2
|
||||
#elif CONFIG_PS2SERIAL == 3
|
||||
#define PSC_BASE MPC5XXX_PSC3
|
||||
#elif defined(CONFIG_MGT5100)
|
||||
#error CONFIG_PS2SERIAL must be in 1, 2 or 3
|
||||
#elif CONFIG_PS2SERIAL == 4
|
||||
#define PSC_BASE MPC5XXX_PSC4
|
||||
#elif CONFIG_PS2SERIAL == 5
|
||||
@@ -87,23 +85,14 @@ int ps2ser_init(void)
|
||||
psc->command = PSC_SEL_MODE_REG_1;
|
||||
|
||||
/* select clock sources */
|
||||
#if defined(CONFIG_MGT5100)
|
||||
psc->psc_clock_select = 0xdd00;
|
||||
baseclk = (CONFIG_SYS_MPC5XXX_CLKIN + 16) / 32;
|
||||
#elif defined(CONFIG_MPC5200)
|
||||
psc->psc_clock_select = 0;
|
||||
baseclk = (gd->ipb_clk + 16) / 32;
|
||||
#endif
|
||||
|
||||
/* switch to UART mode */
|
||||
psc->sicr = 0;
|
||||
|
||||
/* configure parity, bit length and so on */
|
||||
#if defined(CONFIG_MGT5100)
|
||||
psc->mode = PSC_MODE_ERR | PSC_MODE_8_BITS | PSC_MODE_PARNONE;
|
||||
#elif defined(CONFIG_MPC5200)
|
||||
psc->mode = PSC_MODE_8_BITS | PSC_MODE_PARNONE;
|
||||
#endif
|
||||
psc->mode = PSC_MODE_ONE_STOP;
|
||||
|
||||
/* set up UART divisor */
|
||||
|
||||
@@ -605,6 +605,63 @@ static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int use_flash_status_poll(flash_info_t *info)
|
||||
{
|
||||
#ifdef CONFIG_SYS_CFI_FLASH_STATUS_POLL
|
||||
if (info->vendor == CFI_CMDSET_AMD_EXTENDED ||
|
||||
info->vendor == CFI_CMDSET_AMD_STANDARD)
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flash_status_poll(flash_info_t *info, void *src, void *dst,
|
||||
ulong tout, char *prompt)
|
||||
{
|
||||
#ifdef CONFIG_SYS_CFI_FLASH_STATUS_POLL
|
||||
ulong start;
|
||||
int ready;
|
||||
|
||||
#if CONFIG_SYS_HZ != 1000
|
||||
if ((ulong)CONFIG_SYS_HZ > 100000)
|
||||
tout *= (ulong)CONFIG_SYS_HZ / 1000; /* for a big HZ, avoid overflow */
|
||||
else
|
||||
tout = DIV_ROUND_UP(tout * (ulong)CONFIG_SYS_HZ, 1000);
|
||||
#endif
|
||||
|
||||
/* Wait for command completion */
|
||||
start = get_timer(0);
|
||||
while (1) {
|
||||
switch (info->portwidth) {
|
||||
case FLASH_CFI_8BIT:
|
||||
ready = flash_read8(dst) == flash_read8(src);
|
||||
break;
|
||||
case FLASH_CFI_16BIT:
|
||||
ready = flash_read16(dst) == flash_read16(src);
|
||||
break;
|
||||
case FLASH_CFI_32BIT:
|
||||
ready = flash_read32(dst) == flash_read32(src);
|
||||
break;
|
||||
case FLASH_CFI_64BIT:
|
||||
ready = flash_read64(dst) == flash_read64(src);
|
||||
break;
|
||||
default:
|
||||
ready = 0;
|
||||
break;
|
||||
}
|
||||
if (ready)
|
||||
break;
|
||||
if (get_timer(start) > tout) {
|
||||
printf("Flash %s timeout at address %lx data %lx\n",
|
||||
prompt, (ulong)dst, (ulong)flash_read8(dst));
|
||||
return ERR_TIMOUT;
|
||||
}
|
||||
udelay(1); /* also triggers watchdog */
|
||||
}
|
||||
#endif /* CONFIG_SYS_CFI_FLASH_STATUS_POLL */
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
||||
static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c)
|
||||
@@ -752,7 +809,12 @@ static int flash_write_cfiword (flash_info_t * info, ulong dest,
|
||||
if (!sect_found)
|
||||
sect = find_sector (info, dest);
|
||||
|
||||
return flash_full_status_check (info, sect, info->write_tout, "write");
|
||||
if (use_flash_status_poll(info))
|
||||
return flash_status_poll(info, &cword, dstaddr,
|
||||
info->write_tout, "write");
|
||||
else
|
||||
return flash_full_status_check(info, sect,
|
||||
info->write_tout, "write");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE
|
||||
@@ -914,9 +976,15 @@ static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
|
||||
}
|
||||
|
||||
flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM);
|
||||
retcode = flash_full_status_check (info, sector,
|
||||
info->buffer_write_tout,
|
||||
"buffer write");
|
||||
if (use_flash_status_poll(info))
|
||||
retcode = flash_status_poll(info, src - (1 << shift),
|
||||
dst - (1 << shift),
|
||||
info->buffer_write_tout,
|
||||
"buffer write");
|
||||
else
|
||||
retcode = flash_full_status_check(info, sector,
|
||||
info->buffer_write_tout,
|
||||
"buffer write");
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -938,6 +1006,7 @@ int flash_erase (flash_info_t * info, int s_first, int s_last)
|
||||
int rcode = 0;
|
||||
int prot;
|
||||
flash_sect_t sect;
|
||||
int st;
|
||||
|
||||
if (info->flash_id != FLASH_MAN_CFI) {
|
||||
puts ("Can't erase unknown flash type - aborted\n");
|
||||
@@ -1001,10 +1070,20 @@ int flash_erase (flash_info_t * info, int s_first, int s_last)
|
||||
break;
|
||||
}
|
||||
|
||||
if (flash_full_status_check
|
||||
(info, sect, info->erase_blk_tout, "erase")) {
|
||||
if (use_flash_status_poll(info)) {
|
||||
cfiword_t cword = (cfiword_t)0xffffffffffffffffULL;
|
||||
void *dest;
|
||||
dest = flash_map(info, sect, 0);
|
||||
st = flash_status_poll(info, &cword, dest,
|
||||
info->erase_blk_tout, "erase");
|
||||
flash_unmap(info, sect, 0, dest);
|
||||
} else
|
||||
st = flash_full_status_check(info, sect,
|
||||
info->erase_blk_tout,
|
||||
"erase");
|
||||
if (st)
|
||||
rcode = 1;
|
||||
} else if (flash_verbose)
|
||||
else if (flash_verbose)
|
||||
putc ('.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,209 @@
|
||||
|
||||
#include <nand.h>
|
||||
|
||||
#ifdef CONFIG_ATMEL_NAND_HWECC
|
||||
|
||||
/* Register access macros */
|
||||
#define ecc_readl(add, reg) \
|
||||
readl(AT91_BASE_SYS + add + ATMEL_ECC_##reg)
|
||||
#define ecc_writel(add, reg, value) \
|
||||
writel((value), AT91_BASE_SYS + add + ATMEL_ECC_##reg)
|
||||
|
||||
#include "atmel_nand_ecc.h" /* Hardware ECC registers */
|
||||
|
||||
/* oob layout for large page size
|
||||
* bad block info is on bytes 0 and 1
|
||||
* the bytes have to be consecutives to avoid
|
||||
* several NAND_CMD_RNDOUT during read
|
||||
*/
|
||||
static struct nand_ecclayout atmel_oobinfo_large = {
|
||||
.eccbytes = 4,
|
||||
.eccpos = {60, 61, 62, 63},
|
||||
.oobfree = {
|
||||
{2, 58}
|
||||
},
|
||||
};
|
||||
|
||||
/* oob layout for small page size
|
||||
* bad block info is on bytes 4 and 5
|
||||
* the bytes have to be consecutives to avoid
|
||||
* several NAND_CMD_RNDOUT during read
|
||||
*/
|
||||
static struct nand_ecclayout atmel_oobinfo_small = {
|
||||
.eccbytes = 4,
|
||||
.eccpos = {0, 1, 2, 3},
|
||||
.oobfree = {
|
||||
{6, 10}
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Calculate HW ECC
|
||||
*
|
||||
* function called after a write
|
||||
*
|
||||
* mtd: MTD block structure
|
||||
* dat: raw data (unused)
|
||||
* ecc_code: buffer for ECC
|
||||
*/
|
||||
static int atmel_nand_calculate(struct mtd_info *mtd,
|
||||
const u_char *dat, unsigned char *ecc_code)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
unsigned int ecc_value;
|
||||
|
||||
/* get the first 2 ECC bytes */
|
||||
ecc_value = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, PR);
|
||||
|
||||
ecc_code[0] = ecc_value & 0xFF;
|
||||
ecc_code[1] = (ecc_value >> 8) & 0xFF;
|
||||
|
||||
/* get the last 2 ECC bytes */
|
||||
ecc_value = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, NPR) & ATMEL_ECC_NPARITY;
|
||||
|
||||
ecc_code[2] = ecc_value & 0xFF;
|
||||
ecc_code[3] = (ecc_value >> 8) & 0xFF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* HW ECC read page function
|
||||
*
|
||||
* mtd: mtd info structure
|
||||
* chip: nand chip info structure
|
||||
* buf: buffer to store read data
|
||||
*/
|
||||
static int atmel_nand_read_page(struct mtd_info *mtd,
|
||||
struct nand_chip *chip, uint8_t *buf, int page)
|
||||
{
|
||||
int eccsize = chip->ecc.size;
|
||||
int eccbytes = chip->ecc.bytes;
|
||||
uint32_t *eccpos = chip->ecc.layout->eccpos;
|
||||
uint8_t *p = buf;
|
||||
uint8_t *oob = chip->oob_poi;
|
||||
uint8_t *ecc_pos;
|
||||
int stat;
|
||||
|
||||
/* read the page */
|
||||
chip->read_buf(mtd, p, eccsize);
|
||||
|
||||
/* move to ECC position if needed */
|
||||
if (eccpos[0] != 0) {
|
||||
/* This only works on large pages
|
||||
* because the ECC controller waits for
|
||||
* NAND_CMD_RNDOUTSTART after the
|
||||
* NAND_CMD_RNDOUT.
|
||||
* anyway, for small pages, the eccpos[0] == 0
|
||||
*/
|
||||
chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
|
||||
mtd->writesize + eccpos[0], -1);
|
||||
}
|
||||
|
||||
/* the ECC controller needs to read the ECC just after the data */
|
||||
ecc_pos = oob + eccpos[0];
|
||||
chip->read_buf(mtd, ecc_pos, eccbytes);
|
||||
|
||||
/* check if there's an error */
|
||||
stat = chip->ecc.correct(mtd, p, oob, NULL);
|
||||
|
||||
if (stat < 0)
|
||||
mtd->ecc_stats.failed++;
|
||||
else
|
||||
mtd->ecc_stats.corrected += stat;
|
||||
|
||||
/* get back to oob start (end of page) */
|
||||
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
|
||||
|
||||
/* read the oob */
|
||||
chip->read_buf(mtd, oob, mtd->oobsize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* HW ECC Correction
|
||||
*
|
||||
* function called after a read
|
||||
*
|
||||
* mtd: MTD block structure
|
||||
* dat: raw data read from the chip
|
||||
* read_ecc: ECC from the chip (unused)
|
||||
* isnull: unused
|
||||
*
|
||||
* Detect and correct a 1 bit error for a page
|
||||
*/
|
||||
static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
|
||||
u_char *read_ecc, u_char *isnull)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
unsigned int ecc_status, ecc_parity, ecc_mode;
|
||||
unsigned int ecc_word, ecc_bit;
|
||||
|
||||
/* get the status from the Status Register */
|
||||
ecc_status = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, SR);
|
||||
|
||||
/* if there's no error */
|
||||
if (likely(!(ecc_status & ATMEL_ECC_RECERR)))
|
||||
return 0;
|
||||
|
||||
/* get error bit offset (4 bits) */
|
||||
ecc_bit = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, PR) & ATMEL_ECC_BITADDR;
|
||||
/* get word address (12 bits) */
|
||||
ecc_word = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, PR) & ATMEL_ECC_WORDADDR;
|
||||
ecc_word >>= 4;
|
||||
|
||||
/* if there are multiple errors */
|
||||
if (ecc_status & ATMEL_ECC_MULERR) {
|
||||
/* check if it is a freshly erased block
|
||||
* (filled with 0xff) */
|
||||
if ((ecc_bit == ATMEL_ECC_BITADDR)
|
||||
&& (ecc_word == (ATMEL_ECC_WORDADDR >> 4))) {
|
||||
/* the block has just been erased, return OK */
|
||||
return 0;
|
||||
}
|
||||
/* it doesn't seems to be a freshly
|
||||
* erased block.
|
||||
* We can't correct so many errors */
|
||||
printk(KERN_WARNING "atmel_nand : multiple errors detected."
|
||||
" Unable to correct.\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* if there's a single bit error : we can correct it */
|
||||
if (ecc_status & ATMEL_ECC_ECCERR) {
|
||||
/* there's nothing much to do here.
|
||||
* the bit error is on the ECC itself.
|
||||
*/
|
||||
printk(KERN_WARNING "atmel_nand : one bit error on ECC code."
|
||||
" Nothing to correct\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
printk(KERN_WARNING "atmel_nand : one bit error on data."
|
||||
" (word offset in the page :"
|
||||
" 0x%x bit offset : 0x%x)\n",
|
||||
ecc_word, ecc_bit);
|
||||
/* correct the error */
|
||||
if (nand_chip->options & NAND_BUSWIDTH_16) {
|
||||
/* 16 bits words */
|
||||
((unsigned short *) dat)[ecc_word] ^= (1 << ecc_bit);
|
||||
} else {
|
||||
/* 8 bits words */
|
||||
dat[ecc_word] ^= (1 << ecc_bit);
|
||||
}
|
||||
printk(KERN_WARNING "atmel_nand : error corrected\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable HW ECC : unused on most chips
|
||||
*/
|
||||
static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static void at91_nand_hwcontrol(struct mtd_info *mtd,
|
||||
int cmd, unsigned int ctrl)
|
||||
{
|
||||
@@ -64,6 +267,11 @@ static int at91_nand_ready(struct mtd_info *mtd)
|
||||
|
||||
int board_nand_init(struct nand_chip *nand)
|
||||
{
|
||||
#ifdef CONFIG_ATMEL_NAND_HWECC
|
||||
static int chip_nr = 0;
|
||||
struct mtd_info *mtd;
|
||||
#endif
|
||||
|
||||
nand->ecc.mode = NAND_ECC_SOFT;
|
||||
#ifdef CONFIG_SYS_NAND_DBW_16
|
||||
nand->options = NAND_BUSWIDTH_16;
|
||||
@@ -74,5 +282,62 @@ int board_nand_init(struct nand_chip *nand)
|
||||
#endif
|
||||
nand->chip_delay = 20;
|
||||
|
||||
#ifdef CONFIG_ATMEL_NAND_HWECC
|
||||
nand->ecc.mode = NAND_ECC_HW;
|
||||
nand->ecc.calculate = atmel_nand_calculate;
|
||||
nand->ecc.correct = atmel_nand_correct;
|
||||
nand->ecc.hwctl = atmel_nand_hwctl;
|
||||
nand->ecc.read_page = atmel_nand_read_page;
|
||||
nand->ecc.bytes = 4;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ATMEL_NAND_HWECC
|
||||
mtd = &nand_info[chip_nr++];
|
||||
mtd->priv = nand;
|
||||
|
||||
/* Detect NAND chips */
|
||||
if (nand_scan_ident(mtd, 1)) {
|
||||
printk(KERN_WARNING "NAND Flash not found !\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
if (nand->ecc.mode == NAND_ECC_HW) {
|
||||
/* ECC is calculated for the whole page (1 step) */
|
||||
nand->ecc.size = mtd->writesize;
|
||||
|
||||
/* set ECC page size and oob layout */
|
||||
switch (mtd->writesize) {
|
||||
case 512:
|
||||
nand->ecc.layout = &atmel_oobinfo_small;
|
||||
ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR, ATMEL_ECC_PAGESIZE_528);
|
||||
break;
|
||||
case 1024:
|
||||
nand->ecc.layout = &atmel_oobinfo_large;
|
||||
ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR, ATMEL_ECC_PAGESIZE_1056);
|
||||
break;
|
||||
case 2048:
|
||||
nand->ecc.layout = &atmel_oobinfo_large;
|
||||
ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR, ATMEL_ECC_PAGESIZE_2112);
|
||||
break;
|
||||
case 4096:
|
||||
nand->ecc.layout = &atmel_oobinfo_large;
|
||||
ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR, ATMEL_ECC_PAGESIZE_4224);
|
||||
break;
|
||||
default:
|
||||
/* page size not handled by HW ECC */
|
||||
/* switching back to soft ECC */
|
||||
nand->ecc.mode = NAND_ECC_SOFT;
|
||||
nand->ecc.calculate = NULL;
|
||||
nand->ecc.correct = NULL;
|
||||
nand->ecc.hwctl = NULL;
|
||||
nand->ecc.read_page = NULL;
|
||||
nand->ecc.postpad = 0;
|
||||
nand->ecc.prepad = 0;
|
||||
nand->ecc.bytes = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
36
drivers/mtd/nand/atmel_nand_ecc.h
Normal file
36
drivers/mtd/nand/atmel_nand_ecc.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Error Corrected Code Controller (ECC) - System peripherals regsters.
|
||||
* Based on AT91SAM9260 datasheet revision B.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ATMEL_NAND_ECC_H
|
||||
#define ATMEL_NAND_ECC_H
|
||||
|
||||
#define ATMEL_ECC_CR 0x00 /* Control register */
|
||||
#define ATMEL_ECC_RST (1 << 0) /* Reset parity */
|
||||
|
||||
#define ATMEL_ECC_MR 0x04 /* Mode register */
|
||||
#define ATMEL_ECC_PAGESIZE (3 << 0) /* Page Size */
|
||||
#define ATMEL_ECC_PAGESIZE_528 (0)
|
||||
#define ATMEL_ECC_PAGESIZE_1056 (1)
|
||||
#define ATMEL_ECC_PAGESIZE_2112 (2)
|
||||
#define ATMEL_ECC_PAGESIZE_4224 (3)
|
||||
|
||||
#define ATMEL_ECC_SR 0x08 /* Status register */
|
||||
#define ATMEL_ECC_RECERR (1 << 0) /* Recoverable Error */
|
||||
#define ATMEL_ECC_ECCERR (1 << 1) /* ECC Single Bit Error */
|
||||
#define ATMEL_ECC_MULERR (1 << 2) /* Multiple Errors */
|
||||
|
||||
#define ATMEL_ECC_PR 0x0c /* Parity register */
|
||||
#define ATMEL_ECC_BITADDR (0xf << 0) /* Bit Error Address */
|
||||
#define ATMEL_ECC_WORDADDR (0xfff << 4) /* Word Error Address */
|
||||
|
||||
#define ATMEL_ECC_NPR 0x10 /* NParity register */
|
||||
#define ATMEL_ECC_NPARITY (0xffff << 0) /* NParity */
|
||||
|
||||
#endif
|
||||
@@ -57,8 +57,6 @@
|
||||
#define ECC_STATE_ERR_CORR_COMP_P 0x2
|
||||
#define ECC_STATE_ERR_CORR_COMP_N 0x3
|
||||
|
||||
static emif_registers *const emif_regs = (void *) DAVINCI_ASYNC_EMIF_CNTRL_BASE;
|
||||
|
||||
/*
|
||||
* Exploit the little endianness of the ARM to do multi-byte transfers
|
||||
* per device read. This can perform over twice as quickly as individual
|
||||
@@ -93,7 +91,7 @@ static void nand_davinci_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
||||
|
||||
/* copy aligned data */
|
||||
while (len >= 4) {
|
||||
*(u32 *)buf = readl(nand);
|
||||
*(u32 *)buf = __raw_readl(nand);
|
||||
buf += 4;
|
||||
len -= 4;
|
||||
}
|
||||
@@ -138,7 +136,7 @@ static void nand_davinci_write_buf(struct mtd_info *mtd, const uint8_t *buf,
|
||||
|
||||
/* copy aligned data */
|
||||
while (len >= 4) {
|
||||
writel(*(u32 *)buf, nand);
|
||||
__raw_writel(*(u32 *)buf, nand);
|
||||
buf += 4;
|
||||
len -= 4;
|
||||
}
|
||||
@@ -156,7 +154,8 @@ static void nand_davinci_write_buf(struct mtd_info *mtd, const uint8_t *buf,
|
||||
}
|
||||
}
|
||||
|
||||
static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
||||
static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
u_int32_t IO_ADDR_W = (u_int32_t)this->IO_ADDR_W;
|
||||
@@ -164,9 +163,9 @@ static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int c
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
IO_ADDR_W &= ~(MASK_ALE|MASK_CLE);
|
||||
|
||||
if ( ctrl & NAND_CLE )
|
||||
if (ctrl & NAND_CLE)
|
||||
IO_ADDR_W |= MASK_CLE;
|
||||
if ( ctrl & NAND_ALE )
|
||||
if (ctrl & NAND_ALE)
|
||||
IO_ADDR_W |= MASK_ALE;
|
||||
this->IO_ADDR_W = (void __iomem *) IO_ADDR_W;
|
||||
}
|
||||
@@ -181,24 +180,26 @@ static void nand_davinci_enable_hwecc(struct mtd_info *mtd, int mode)
|
||||
{
|
||||
u_int32_t val;
|
||||
|
||||
(void)readl(&(emif_regs->NANDFECC[CONFIG_SYS_NAND_CS - 2]));
|
||||
(void)__raw_readl(&(davinci_emif_regs->nandfecc[
|
||||
CONFIG_SYS_NAND_CS - 2]));
|
||||
|
||||
val = readl(&emif_regs->NANDFCR);
|
||||
val = __raw_readl(&davinci_emif_regs->nandfcr);
|
||||
val |= DAVINCI_NANDFCR_NAND_ENABLE(CONFIG_SYS_NAND_CS);
|
||||
val |= DAVINCI_NANDFCR_1BIT_ECC_START(CONFIG_SYS_NAND_CS);
|
||||
writel(val, &emif_regs->NANDFCR);
|
||||
__raw_writel(val, &davinci_emif_regs->nandfcr);
|
||||
}
|
||||
|
||||
static u_int32_t nand_davinci_readecc(struct mtd_info *mtd, u_int32_t region)
|
||||
{
|
||||
u_int32_t ecc = 0;
|
||||
|
||||
ecc = readl(&(emif_regs->NANDFECC[region - 1]));
|
||||
ecc = __raw_readl(&(davinci_emif_regs->nandfecc[region - 1]));
|
||||
|
||||
return(ecc);
|
||||
return ecc;
|
||||
}
|
||||
|
||||
static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
|
||||
static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
|
||||
u_char *ecc_code)
|
||||
{
|
||||
u_int32_t tmp;
|
||||
const int region = 1;
|
||||
@@ -232,7 +233,8 @@ static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
|
||||
static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat,
|
||||
u_char *read_ecc, u_char *calc_ecc)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
u_int32_t ecc_nand = read_ecc[0] | (read_ecc[1] << 8) |
|
||||
@@ -268,7 +270,7 @@ static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_SYS_NAND_HW_ECC */
|
||||
|
||||
@@ -315,15 +317,15 @@ static void nand_davinci_4bit_enable_hwecc(struct mtd_info *mtd, int mode)
|
||||
* Start a new ECC calculation for reading or writing 512 bytes
|
||||
* of data.
|
||||
*/
|
||||
val = readl(&emif_regs->NANDFCR);
|
||||
val = __raw_readl(&davinci_emif_regs->nandfcr);
|
||||
val &= ~DAVINCI_NANDFCR_4BIT_ECC_SEL_MASK;
|
||||
val |= DAVINCI_NANDFCR_NAND_ENABLE(CONFIG_SYS_NAND_CS);
|
||||
val |= DAVINCI_NANDFCR_4BIT_ECC_SEL(CONFIG_SYS_NAND_CS);
|
||||
val |= DAVINCI_NANDFCR_4BIT_ECC_START;
|
||||
writel(val, &emif_regs->NANDFCR);
|
||||
__raw_writel(val, &davinci_emif_regs->nandfcr);
|
||||
break;
|
||||
case NAND_ECC_READSYN:
|
||||
val = emif_regs->NAND4BITECC1;
|
||||
val = __raw_readl(&davinci_emif_regs->nand4bitecc[0]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -332,10 +334,12 @@ static void nand_davinci_4bit_enable_hwecc(struct mtd_info *mtd, int mode)
|
||||
|
||||
static u32 nand_davinci_4bit_readecc(struct mtd_info *mtd, unsigned int ecc[4])
|
||||
{
|
||||
ecc[0] = emif_regs->NAND4BITECC1 & NAND_4BITECC_MASK;
|
||||
ecc[1] = emif_regs->NAND4BITECC2 & NAND_4BITECC_MASK;
|
||||
ecc[2] = emif_regs->NAND4BITECC3 & NAND_4BITECC_MASK;
|
||||
ecc[3] = emif_regs->NAND4BITECC4 & NAND_4BITECC_MASK;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
ecc[i] = __raw_readl(&davinci_emif_regs->nand4bitecc[i]) &
|
||||
NAND_4BITECC_MASK;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -418,32 +422,36 @@ static int nand_davinci_4bit_correct_data(struct mtd_info *mtd, uint8_t *dat,
|
||||
*/
|
||||
|
||||
/*Take 2 bits from 8th byte and 8 bits from 9th byte */
|
||||
writel(((ecc16[4]) >> 6) & 0x3FF, &emif_regs->NAND4BITECCLOAD);
|
||||
__raw_writel(((ecc16[4]) >> 6) & 0x3FF,
|
||||
&davinci_emif_regs->nand4biteccload);
|
||||
|
||||
/* Take 4 bits from 7th byte and 6 bits from 8th byte */
|
||||
writel((((ecc16[3]) >> 12) & 0xF) | ((((ecc16[4])) << 4) & 0x3F0),
|
||||
&emif_regs->NAND4BITECCLOAD);
|
||||
__raw_writel((((ecc16[3]) >> 12) & 0xF) | ((((ecc16[4])) << 4) & 0x3F0),
|
||||
&davinci_emif_regs->nand4biteccload);
|
||||
|
||||
/* Take 6 bits from 6th byte and 4 bits from 7th byte */
|
||||
writel((ecc16[3] >> 2) & 0x3FF, &emif_regs->NAND4BITECCLOAD);
|
||||
__raw_writel((ecc16[3] >> 2) & 0x3FF,
|
||||
&davinci_emif_regs->nand4biteccload);
|
||||
|
||||
/* Take 8 bits from 5th byte and 2 bits from 6th byte */
|
||||
writel(((ecc16[2]) >> 8) | ((((ecc16[3])) << 8) & 0x300),
|
||||
&emif_regs->NAND4BITECCLOAD);
|
||||
__raw_writel(((ecc16[2]) >> 8) | ((((ecc16[3])) << 8) & 0x300),
|
||||
&davinci_emif_regs->nand4biteccload);
|
||||
|
||||
/*Take 2 bits from 3rd byte and 8 bits from 4th byte */
|
||||
writel((((ecc16[1]) >> 14) & 0x3) | ((((ecc16[2])) << 2) & 0x3FC),
|
||||
&emif_regs->NAND4BITECCLOAD);
|
||||
__raw_writel((((ecc16[1]) >> 14) & 0x3) | ((((ecc16[2])) << 2) & 0x3FC),
|
||||
&davinci_emif_regs->nand4biteccload);
|
||||
|
||||
/* Take 4 bits form 2nd bytes and 6 bits from 3rd bytes */
|
||||
writel(((ecc16[1]) >> 4) & 0x3FF, &emif_regs->NAND4BITECCLOAD);
|
||||
__raw_writel(((ecc16[1]) >> 4) & 0x3FF,
|
||||
&davinci_emif_regs->nand4biteccload);
|
||||
|
||||
/* Take 6 bits from 1st byte and 4 bits from 2nd byte */
|
||||
writel((((ecc16[0]) >> 10) & 0x3F) | (((ecc16[1]) << 6) & 0x3C0),
|
||||
&emif_regs->NAND4BITECCLOAD);
|
||||
__raw_writel((((ecc16[0]) >> 10) & 0x3F) | (((ecc16[1]) << 6) & 0x3C0),
|
||||
&davinci_emif_regs->nand4biteccload);
|
||||
|
||||
/* Take 10 bits from 0th and 1st bytes */
|
||||
writel((ecc16[0]) & 0x3FF, &emif_regs->NAND4BITECCLOAD);
|
||||
__raw_writel((ecc16[0]) & 0x3FF,
|
||||
&davinci_emif_regs->nand4biteccload);
|
||||
|
||||
/*
|
||||
* Perform a dummy read to the EMIF Revision Code and Status register.
|
||||
@@ -451,7 +459,7 @@ static int nand_davinci_4bit_correct_data(struct mtd_info *mtd, uint8_t *dat,
|
||||
* writing the ECC values in previous step.
|
||||
*/
|
||||
|
||||
val = emif_regs->NANDFSR;
|
||||
val = __raw_readl(&davinci_emif_regs->nandfsr);
|
||||
|
||||
/*
|
||||
* Read the syndrome from the NAND Flash 4-Bit ECC 1-4 registers.
|
||||
@@ -467,13 +475,13 @@ static int nand_davinci_4bit_correct_data(struct mtd_info *mtd, uint8_t *dat,
|
||||
* Clear any previous address calculation by doing a dummy read of an
|
||||
* error address register.
|
||||
*/
|
||||
val = emif_regs->NANDERRADD1;
|
||||
val = __raw_readl(&davinci_emif_regs->nanderradd1);
|
||||
|
||||
/*
|
||||
* Set the addr_calc_st bit(bit no 13) in the NAND Flash Control
|
||||
* register to 1.
|
||||
*/
|
||||
emif_regs->NANDFCR |= 1 << 13;
|
||||
__raw_writel(1 << 13, &davinci_emif_regs->nandfcr);
|
||||
|
||||
/*
|
||||
* Wait for the corr_state field (bits 8 to 11)in the
|
||||
@@ -481,12 +489,12 @@ static int nand_davinci_4bit_correct_data(struct mtd_info *mtd, uint8_t *dat,
|
||||
*/
|
||||
i = NAND_TIMEOUT;
|
||||
do {
|
||||
val = emif_regs->NANDFSR;
|
||||
val = __raw_readl(&davinci_emif_regs->nandfsr);
|
||||
val &= 0xc00;
|
||||
i--;
|
||||
} while ((i > 0) && val);
|
||||
|
||||
iserror = emif_regs->NANDFSR;
|
||||
iserror = __raw_readl(&davinci_emif_regs->nandfsr);
|
||||
iserror &= EMIF_NANDFSR_ECC_STATE_MASK;
|
||||
iserror = iserror >> 8;
|
||||
|
||||
@@ -501,32 +509,33 @@ static int nand_davinci_4bit_correct_data(struct mtd_info *mtd, uint8_t *dat,
|
||||
*/
|
||||
|
||||
if (iserror == ECC_STATE_NO_ERR) {
|
||||
val = emif_regs->NANDERRVAL1;
|
||||
val = __raw_readl(&davinci_emif_regs->nanderrval1);
|
||||
return 0;
|
||||
} else if (iserror == ECC_STATE_TOO_MANY_ERRS) {
|
||||
val = emif_regs->NANDERRVAL1;
|
||||
val = __raw_readl(&davinci_emif_regs->nanderrval1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
numerrors = ((emif_regs->NANDFSR >> 16) & 0x3) + 1;
|
||||
numerrors = ((__raw_readl(&davinci_emif_regs->nandfsr) >> 16)
|
||||
& 0x3) + 1;
|
||||
|
||||
/* Read the error address, error value and correct */
|
||||
for (i = 0; i < numerrors; i++) {
|
||||
if (i > 1) {
|
||||
erroraddress =
|
||||
((emif_regs->NANDERRADD2 >>
|
||||
((__raw_readl(&davinci_emif_regs->nanderradd2) >>
|
||||
(16 * (i & 1))) & 0x3FF);
|
||||
erroraddress = ((512 + 7) - erroraddress);
|
||||
errorvalue =
|
||||
((emif_regs->NANDERRVAL2 >>
|
||||
((__raw_readl(&davinci_emif_regs->nanderrval2) >>
|
||||
(16 * (i & 1))) & 0xFF);
|
||||
} else {
|
||||
erroraddress =
|
||||
((emif_regs->NANDERRADD1 >>
|
||||
((__raw_readl(&davinci_emif_regs->nanderradd1) >>
|
||||
(16 * (i & 1))) & 0x3FF);
|
||||
erroraddress = ((512 + 7) - erroraddress);
|
||||
errorvalue =
|
||||
((emif_regs->NANDERRVAL1 >>
|
||||
((__raw_readl(&davinci_emif_regs->nanderrval1) >>
|
||||
(16 * (i & 1))) & 0xFF);
|
||||
}
|
||||
/* xor the corrupt data with error value */
|
||||
@@ -540,7 +549,7 @@ static int nand_davinci_4bit_correct_data(struct mtd_info *mtd, uint8_t *dat,
|
||||
|
||||
static int nand_davinci_dev_ready(struct mtd_info *mtd)
|
||||
{
|
||||
return emif_regs->NANDFSR & 0x1;
|
||||
return __raw_readl(&davinci_emif_regs->nandfsr) & 0x1;
|
||||
}
|
||||
|
||||
static void nand_flash_init(void)
|
||||
@@ -561,21 +570,22 @@ static void nand_flash_init(void)
|
||||
* *
|
||||
*------------------------------------------------------------------*/
|
||||
acfg1 = 0
|
||||
| (0 << 31 ) /* selectStrobe */
|
||||
| (0 << 30 ) /* extWait */
|
||||
| (1 << 26 ) /* writeSetup 10 ns */
|
||||
| (3 << 20 ) /* writeStrobe 40 ns */
|
||||
| (1 << 17 ) /* writeHold 10 ns */
|
||||
| (1 << 13 ) /* readSetup 10 ns */
|
||||
| (5 << 7 ) /* readStrobe 60 ns */
|
||||
| (1 << 4 ) /* readHold 10 ns */
|
||||
| (3 << 2 ) /* turnAround ?? ns */
|
||||
| (0 << 0 ) /* asyncSize 8-bit bus */
|
||||
| (0 << 31) /* selectStrobe */
|
||||
| (0 << 30) /* extWait */
|
||||
| (1 << 26) /* writeSetup 10 ns */
|
||||
| (3 << 20) /* writeStrobe 40 ns */
|
||||
| (1 << 17) /* writeHold 10 ns */
|
||||
| (1 << 13) /* readSetup 10 ns */
|
||||
| (5 << 7) /* readStrobe 60 ns */
|
||||
| (1 << 4) /* readHold 10 ns */
|
||||
| (3 << 2) /* turnAround ?? ns */
|
||||
| (0 << 0) /* asyncSize 8-bit bus */
|
||||
;
|
||||
|
||||
emif_regs->AB1CR = acfg1; /* CS2 */
|
||||
__raw_writel(acfg1, &davinci_emif_regs->ab1cr); /* CS2 */
|
||||
|
||||
emif_regs->NANDFCR = 0x00000101; /* NAND flash on CS2 */
|
||||
/* NAND flash on CS2 */
|
||||
__raw_writel(0x00000101, &davinci_emif_regs->nandfcr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -336,13 +336,11 @@ static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis)
|
||||
*/
|
||||
fec->eth->xmit_fsm = 0x03000000;
|
||||
|
||||
#if defined(CONFIG_MPC5200)
|
||||
/*
|
||||
* Turn off COMM bus prefetch in the MGT5200 BestComm. It doesn't
|
||||
* Turn off COMM bus prefetch in the MPC5200 BestComm. It doesn't
|
||||
* work w/ the current receive task.
|
||||
*/
|
||||
sdma->PtdCntrl |= 0x00000001;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set priority of different initiators
|
||||
@@ -579,9 +577,7 @@ static int mpc5xxx_fec_init_phy(struct eth_device *dev, bd_t * bis)
|
||||
/********************************************************************/
|
||||
static void mpc5xxx_fec_halt(struct eth_device *dev)
|
||||
{
|
||||
#if defined(CONFIG_MPC5200)
|
||||
struct mpc5xxx_sdma *sdma = (struct mpc5xxx_sdma *)MPC5XXX_SDMA;
|
||||
#endif
|
||||
mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
|
||||
int counter = 0xffff;
|
||||
|
||||
@@ -611,13 +607,11 @@ static void mpc5xxx_fec_halt(struct eth_device *dev)
|
||||
SDMA_TASK_DISABLE (FEC_XMIT_TASK_NO);
|
||||
SDMA_TASK_DISABLE (FEC_RECV_TASK_NO);
|
||||
|
||||
#if defined(CONFIG_MPC5200)
|
||||
/*
|
||||
* Turn on COMM bus prefetch in the MGT5200 BestComm after we're
|
||||
* Turn on COMM bus prefetch in the MPC5200 BestComm after we're
|
||||
* done. It doesn't work w/ the current receive task.
|
||||
*/
|
||||
sdma->PtdCntrl &= ~0x00000001;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Disable the Ethernet Controller
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
extern void uart_port_conf(void);
|
||||
extern void uart_port_conf(int port);
|
||||
|
||||
int serial_init(void)
|
||||
{
|
||||
@@ -43,7 +43,7 @@ int serial_init(void)
|
||||
|
||||
uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE);
|
||||
|
||||
uart_port_conf();
|
||||
uart_port_conf(CONFIG_SYS_UART_PORT);
|
||||
|
||||
/* write to SICR: SIM2 = uart mode,dcd does not affect rx */
|
||||
uart->ucr = UART_UCR_RESET_RX;
|
||||
|
||||
Reference in New Issue
Block a user