494 lines
15 KiB
C
494 lines
15 KiB
C
/*
|
|
* (C) 2010 by Tieto <www.tieto.com>
|
|
* Marcin Mielczarczyk <marcin.mielczarczyk@tieto.com>
|
|
*
|
|
* All Rights Reserved
|
|
*
|
|
* 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.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <nand.h>
|
|
#include <asm/io.h>
|
|
#include <asm/arch-mtk/nfi.h>
|
|
#include <asm/arch-mtk/system.h>
|
|
#include <linux/err.h>
|
|
|
|
/*
|
|
* MT62XX NAND controller (NFI) can suppport small page (512B) and
|
|
* large page (2048B) NAND devices. It also supports hardware ECC control.
|
|
* ECC is calculated by hardware for given block of bytes (128, 256, 512, 1024).
|
|
* NFI controller can acutomatically detect if read page has no errors -
|
|
* comparing calculated ECC with ECC bytes written in spare area.
|
|
* Problem with hardware ECC is that ECC calculation is available after
|
|
* addtional cycle of read/write (after reading of whole page).
|
|
* I.e. page size is 512, so after reading whole page addtional read/write cycle
|
|
* has to be issued to get ECC calculation (NFI_ADDRCNTR has to show more than
|
|
* 512).
|
|
*
|
|
* In case of reading it's not a problem as NFI controller has 16 bytes FIFO and
|
|
* in burst mode it'll issue 16 reads in advance, so after reading whole page
|
|
* from FIFO, ECC calculation will be already available (as 16 addtional bytes
|
|
* are already placed in FIFO). To have ECC calculations working, SPARE_EN bit
|
|
* has to be enabled, otherwise there will be no additional read cycle. In this
|
|
* case AUTO_ECC_DEC_EN mode works (automatic ECC errors detection).
|
|
*
|
|
* Problem is with writing mode, as additional byte has to be written to spare
|
|
* area and only after that ECC calculation will be available. It means that
|
|
* when using HW ECC it's not possible to place calculation at first byte of
|
|
* spare area. There is AUTO_ECC_ENC_EN mode which doesn't seem to work.
|
|
* In this mode NFI controller should automatically write calculated ECC bytes
|
|
* in spare area. To have it working SPARE_EN bit should be disabled, which
|
|
* indicates that NFI controller has control over spare area, not the user.
|
|
* Unfortunatelly even after disabling SPARE_EN bit, NFI controller doesn't
|
|
* write ECC calculations in spare automatically.
|
|
* Because of these NFI controller issues, driver has to have some hacks.
|
|
*
|
|
* Sciphone G2 specific informations:
|
|
*
|
|
* Sciphone G2 comes with small page and large page NAND devices.
|
|
* For both configurations ecc block size is the same:
|
|
*
|
|
* ecc_block_size = 256
|
|
*
|
|
* Placement of ecc bytes in spare area is as follows:
|
|
*
|
|
* --------------------------------------------------------------
|
|
* | SPARE |
|
|
* --------------------------------------------------------------
|
|
* | | ECC0 | | ECC1 | | ECC2 | | ECC3 |
|
|
* --------------------------------------------------------------
|
|
* 0 8 16 24 32 40 48 56 64
|
|
*
|
|
* ECC0 = 12 bits (from 1st ECC block) + 12 bits (from 2nd ECC block)
|
|
* ECC1 = 12 bits (from 3rd ECC block) + 12 bits (from 4th ECC block)
|
|
* ECC2 = 12 bits (from 5th ECC block) + 12 bits (from 6th ECC block)
|
|
* ECC2 = 12 bits (from 7th ECC block) + 12 bits (from 8th ECC block)
|
|
*
|
|
* This information is pretty important as built-in bootloader in MT62xx chips
|
|
* has hardware ECC enabled and it won't load code from NAND if ECC layout will
|
|
* not match.
|
|
*/
|
|
|
|
/* MT62XX NFI controller has 2 chipselects */
|
|
#define NAND_CHIPS_MAX 2
|
|
|
|
/*
|
|
* Configure which byte in spare area will store ECC calculations.
|
|
* This value should be dword (4 bytes) aligned.
|
|
*/
|
|
#define ECC_SPARE_BYTE_POS 8
|
|
|
|
/*
|
|
* Below tables describe layout of BBT (Bad Block Table) in OOB area.
|
|
* U-Boot's default layout overlaps with MTK's HW ECC position, that's
|
|
* why redefinition is placed here.
|
|
*/
|
|
#ifdef MT62XX_NAND_BBT_IN_NAND
|
|
|
|
static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
|
|
static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
|
|
|
|
static struct nand_bbt_descr bbt_main_descr = {
|
|
.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
|
|
| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
|
|
.offs = 0, /* offset changed as default one overlaps with HW ECC */
|
|
.len = 4,
|
|
.veroffs = 14, /* offset changed as default one overlaps with HW ECC */
|
|
.maxblocks = 4,
|
|
.pattern = bbt_pattern
|
|
};
|
|
|
|
static struct nand_bbt_descr bbt_mirror_descr = {
|
|
.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
|
|
| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
|
|
.offs = 0, /* offset changed as default one overlaps with HW ECC */
|
|
.len = 4,
|
|
.veroffs = 14, /* offset changed as default one overlaps with HW ECC */
|
|
.maxblocks = 4,
|
|
.pattern = mirror_pattern
|
|
};
|
|
|
|
#endif
|
|
|
|
/*
|
|
* Macro which counts zeroes until first set bit.
|
|
* This is used to avoid dividing, so no additional library is needed.
|
|
* It's important as this file is compiled also in SPL and there is no need
|
|
* to link additional library.
|
|
*/
|
|
#ifdef CONFIG_ARM926EJS
|
|
#define COUNT_ZEROES(x) __builtin_ctz(x)
|
|
#else
|
|
#define COUNT_ZEROES(x) (ffs(x) - 1)
|
|
#endif
|
|
|
|
#ifdef CONFIG_PRELOADER
|
|
#define nand_print(x)
|
|
#else
|
|
#define nand_print(x) printk(KERN_ERR (x))
|
|
#endif
|
|
|
|
static void nand_ctrl_change(int cmd, int address, int *addr_cycle,
|
|
int write_size)
|
|
{
|
|
int burst_read = 0;
|
|
|
|
if (write_size > 512) {
|
|
/* Large page device - set burst read on READSTART command */
|
|
if (cmd == NAND_CMD_READSTART)
|
|
burst_read = 1;
|
|
} else {
|
|
/* Small page device - set burst read on all read commands */
|
|
if ((cmd == NAND_CMD_READ0) |
|
|
(cmd == NAND_CMD_READ1) |
|
|
(cmd == NAND_CMD_READOOB))
|
|
burst_read = 1;
|
|
}
|
|
|
|
/* Any address to write? */
|
|
if (*addr_cycle) {
|
|
writel(address, MTK_NFI_ADDRL);
|
|
|
|
if (cmd == NAND_CMD_READID) {
|
|
/* For READID command just one address byte is used */
|
|
writel(1, MTK_NFI_ADDRNOB);
|
|
while(readl(MTK_NFI_PSTA) & NFI_PSTA_ADDR)
|
|
;
|
|
/* Set single read mode */
|
|
writel(NFI_OPCON_SRD, MTK_NFI_OPCON);
|
|
while(readl(MTK_NFI_PSTA) & NFI_PSTA_DATAR)
|
|
;
|
|
} else {
|
|
/* Write calculated number of address bytes */
|
|
writel(*addr_cycle, MTK_NFI_ADDRNOB);
|
|
while(readl(MTK_NFI_PSTA) & NFI_PSTA_ADDR)
|
|
;
|
|
}
|
|
|
|
*addr_cycle = 0;
|
|
}
|
|
|
|
if (burst_read) {
|
|
/* Set burst read mode */
|
|
writel(NFI_OPCON_BRD, MTK_NFI_OPCON);
|
|
while(readl(MTK_NFI_PSTA) & NFI_PSTA_DATAR)
|
|
;
|
|
} else if (cmd == NAND_CMD_STATUS) {
|
|
/* Set single read mode */
|
|
writel(NFI_OPCON_SRD, MTK_NFI_OPCON);
|
|
while(readl(MTK_NFI_PSTA) & NFI_PSTA_DATAR)
|
|
;
|
|
}
|
|
}
|
|
|
|
static void nand_write_command(int cmd)
|
|
{
|
|
/*
|
|
* Clear BRD and SRD bits before issuing command,
|
|
* otherwise there can be some zeroes at the beggining of read.
|
|
*/
|
|
writew(readl(MTK_NFI_OPCON) & ~(NFI_OPCON_BRD | NFI_OPCON_SRD),
|
|
MTK_NFI_OPCON);
|
|
writel(cmd, MTK_NFI_CMD);
|
|
while(readl(MTK_NFI_PSTA) & NFI_PSTA_CMD)
|
|
;
|
|
}
|
|
|
|
static void mt62xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
|
|
unsigned int ctrl)
|
|
{
|
|
static int addr_cycle = 0;
|
|
static int address = 0;
|
|
static int command = 0;
|
|
|
|
if (ctrl == (NAND_CTRL_CHANGE | NAND_NCE))
|
|
nand_ctrl_change(command, address, &addr_cycle, mtd->writesize);
|
|
else if ((ctrl & NAND_CLE) && (cmd != NAND_CMD_NONE)) {
|
|
command = cmd;
|
|
nand_write_command(cmd);
|
|
} else if (ctrl & NAND_ALE) {
|
|
/*
|
|
* Calculate address and address bytes which will be written
|
|
* in nand_ctrl_change() function.
|
|
*/
|
|
if (!addr_cycle)
|
|
address = cmd;
|
|
else
|
|
address |= cmd << (addr_cycle*8);
|
|
|
|
addr_cycle++;
|
|
}
|
|
}
|
|
|
|
static int mt62xx_nand_dev_ready(struct mtd_info *mtd)
|
|
{
|
|
return !(readl(MTK_NFI_PSTA) & NFI_PSTA_NAND_BUSY);
|
|
}
|
|
|
|
static void mt62xx_nand_select_chip(struct mtd_info *mtd, int chip)
|
|
{
|
|
if (chip > NAND_CHIPS_MAX) {
|
|
nand_print("Wrong NAND chip number!\n");
|
|
return;
|
|
}
|
|
|
|
if (chip != -1)
|
|
writel(chip, MTK_NFI_CSEL);
|
|
}
|
|
|
|
static void mt62xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|
{
|
|
uint32_t *buf_32 = (uint32_t *)buf;
|
|
struct nand_chip *chip = mtd->priv;
|
|
int i;
|
|
|
|
if (len % 4)
|
|
nand_print("Length parameter is not aligned\n");
|
|
|
|
for (i = 0; i < len/4; ++i) {
|
|
while(readl(MTK_NFI_FIFOSTA) & NFI_FIFOSTA_RD_EMPTY)
|
|
;
|
|
buf_32[i] = readl(chip->IO_ADDR_R);
|
|
}
|
|
}
|
|
|
|
static uint8_t mt62xx_nand_read_byte(struct mtd_info *mtd)
|
|
{
|
|
struct nand_chip *chip = mtd->priv;
|
|
uint16_t nfi_con = readl(MTK_NFI_CON);
|
|
uint8_t byte;
|
|
|
|
/* Enable byte mode reading */
|
|
writel(nfi_con | NFI_CON_BYTE_RW, MTK_NFI_CON);
|
|
while(readl(MTK_NFI_FIFOSTA) & NFI_FIFOSTA_RD_EMPTY)
|
|
;
|
|
byte = readb(chip->IO_ADDR_R);
|
|
/* Disable byte mode reading */
|
|
writel(nfi_con & ~NFI_CON_BYTE_RW, MTK_NFI_CON);
|
|
return byte;
|
|
}
|
|
|
|
static void mt62xx_nand_write_buf_ecc(struct mtd_info *mtd, const uint8_t *buffer)
|
|
{
|
|
int i, ecc_nr, ecc_blocks;
|
|
struct nand_chip *chip = mtd->priv;
|
|
uint8_t *buf = (uint8_t *)buffer;
|
|
|
|
while(readl(MTK_NFI_FIFOSTA) & NFI_FIFOSTA_WR_FULL)
|
|
;
|
|
/*
|
|
* After this write ECC calculations will
|
|
* be available in NFI_PAR_P and NFI_PAR_C registers.
|
|
*/
|
|
writel(*((uint32_t *)buf), chip->IO_ADDR_W);
|
|
|
|
/*
|
|
* Two ECC blocks are combined on MT62xx platform,
|
|
* that's why there is division by 2.
|
|
*/
|
|
ecc_blocks = (mtd->writesize >> COUNT_ZEROES(chip->ecc.size))/2;
|
|
buf += ECC_SPARE_BYTE_POS;
|
|
|
|
for (ecc_nr = 0; ecc_nr < ecc_blocks; ++ecc_nr) {
|
|
int ecc_p, ecc_c;
|
|
|
|
/*
|
|
* Read calculated ECC bytes and write them
|
|
* to buffer in proper format (as Sciphone G2 expects).
|
|
*/
|
|
for (i = 0; i < 2; ++i) {
|
|
ecc_p = readw((uint32_t *)MTK_NFI_PAR_0P + ecc_nr*2 + i*2);
|
|
ecc_c = readw((uint32_t *)MTK_NFI_PAR_0C + ecc_nr*2 + i*2);
|
|
*(buf++) = ecc_p >> 4;
|
|
*(buf++) = ((ecc_p & 0x0F) << 4) | (ecc_c >> 8);
|
|
*(buf++) = ecc_c & 0xFF;
|
|
}
|
|
buf += 16;
|
|
}
|
|
}
|
|
|
|
static void mt62xx_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf,
|
|
int len)
|
|
{
|
|
uint32_t *buf_32 = (uint32_t *)buf;
|
|
struct nand_chip *chip = mtd->priv;
|
|
int i = 0;
|
|
|
|
/* Writing in spare area? */
|
|
if (readw(MTK_NFI_ADDRCNTR) >= mtd->writesize) {
|
|
/*
|
|
* Due to issue that ECC calculations are available after
|
|
* additional read/write cycle, ECC calculations
|
|
* are handled here.
|
|
*/
|
|
mt62xx_nand_write_buf_ecc(mtd, buf);
|
|
|
|
/* Increment index as above function already written 32 bytes */
|
|
i++;
|
|
}
|
|
|
|
for (; i < len/4; ++i) {
|
|
while(readl(MTK_NFI_FIFOSTA) & NFI_FIFOSTA_WR_FULL)
|
|
;
|
|
writel(buf_32[i], chip->IO_ADDR_W);
|
|
}
|
|
}
|
|
|
|
static int mt62xx_nand_ecc_calculate(struct mtd_info *mtd, const uint8_t *dat,
|
|
uint8_t *ecc_code)
|
|
{
|
|
struct nand_chip *chip = mtd->priv;
|
|
|
|
/*
|
|
* Calculations are done automatically and there is no need for
|
|
* additional operations.
|
|
* This function is used to pass ECC block number to ecc_correct()
|
|
* function to be able to correct proper ECC block.
|
|
* MT62XX chips have address counter which points to address in page
|
|
* which is currently read. We can use it to calculate which ECC block
|
|
* has been already read.
|
|
*/
|
|
*ecc_code = readw(MTK_NFI_ADDRCNTR) >> COUNT_ZEROES(chip->ecc.size);
|
|
return 0;
|
|
}
|
|
|
|
static int mt62xx_nand_ecc_correct(struct mtd_info *mtd, uint8_t *dat,
|
|
uint8_t *read_ecc, uint8_t *ecc_block_nr)
|
|
{
|
|
int ecc_block_mask, ecc_status, ret;
|
|
|
|
/* ECC block number is calculated in ecc_calculate() function */
|
|
if (*ecc_block_nr == 0)
|
|
/* Should neve happen */
|
|
return -1;
|
|
|
|
/* Decrease value to get proper index */
|
|
(*ecc_block_nr)--;
|
|
ecc_block_mask = 1 << *ecc_block_nr;
|
|
ecc_block_mask |= ecc_block_mask << 16;
|
|
|
|
ecc_status = readl(MTK_NFI_ERRDET) & ecc_block_mask;
|
|
if (ecc_status & 0xFF)
|
|
/* Uncorrectable error detected */
|
|
ret = -1;
|
|
else if(ecc_status >> 16) {
|
|
/* Correctable error detected */
|
|
int address;
|
|
uint32_t *buffer = (uint32_t *)dat;
|
|
|
|
/* Read address (for given block) where error occured */
|
|
address = readw((uint32_t *)MTK_NFI_SYM0_ADDR + *ecc_block_nr);
|
|
/* Correct error using syndrome word for given block */
|
|
buffer[address >> 2] ^=
|
|
readw((uint32_t *)MTK_NFI_SYM0_DATA + *ecc_block_nr);
|
|
ret = 1;
|
|
} else
|
|
/* Data read without errors */
|
|
ret = 0;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void mt62xx_nand_ecc_hwctl(struct mtd_info *mtd, int mode)
|
|
{
|
|
/* HW ECC doesn't need to be controlled, it's turned on during init */
|
|
}
|
|
|
|
int board_nand_init(struct nand_chip *chip)
|
|
{
|
|
static int chip_nr = 0;
|
|
struct mtd_info *mtd;
|
|
|
|
/* Power on NFI controller */
|
|
writel(PDN_CON1_NFI, MTK_CONFG_PDN_CLR1);
|
|
|
|
/* Configure for max wait times */
|
|
writel(3 << NFI_ACCCON_RLT_SHIFT |
|
|
3 << NFI_ACCCON_WST_SHIFT |
|
|
3 << NFI_ACCCON_WH_SHIFT |
|
|
3 << NFI_ACCCON_W2R_SHIFT |
|
|
3 << NFI_ACCCON_C2R_SHIFT |
|
|
7 << NFI_ACCCON_LCD2NAND_SHIFT,
|
|
MTK_NFI_ACCCON);
|
|
|
|
/*
|
|
* Reset NFI page format control register.
|
|
* After processor reset it's not always zero what renders problems.
|
|
*/
|
|
writel(0, MTK_NFI_PAGEFMT);
|
|
|
|
/* Flush and reset NFI FIFO */
|
|
writel(NFI_OPCON_FIFO_FLUSH | NFI_OPCON_FIFO_RST, MTK_NFI_OPCON);
|
|
while(readl(MTK_NFI_OPCON))
|
|
;
|
|
|
|
/* Enable spare area and ECC decoding for main */
|
|
writel(NFI_CON_AUTOECC_DEC_EN |
|
|
NFI_CON_MAIN_ECC_EN |
|
|
NFI_CON_SPARE_EN,
|
|
MTK_NFI_CON);
|
|
/* Setup byte number in spare for ECC */
|
|
writel(ECC_SPARE_BYTE_POS, MTK_NFI_SCON);
|
|
|
|
chip->IO_ADDR_R = (uint32_t *)MTK_NFI_DATAR;
|
|
chip->IO_ADDR_W = (uint32_t *)MTK_NFI_DATAW;
|
|
chip->cmd_ctrl = mt62xx_nand_cmd_ctrl;
|
|
chip->dev_ready = mt62xx_nand_dev_ready;
|
|
chip->read_buf = mt62xx_nand_read_buf;
|
|
chip->read_byte = mt62xx_nand_read_byte;
|
|
chip->write_buf = mt62xx_nand_write_buf;
|
|
chip->select_chip = mt62xx_nand_select_chip;
|
|
|
|
/*
|
|
* Below option allows U-Boot to save BBT table in NAND.
|
|
* Without this option BBT table is created everytime when first nand
|
|
* command is executed (except "nand dump"). Full scanning of NAND
|
|
* takes long time and unnecessarily delays start of platform.
|
|
*/
|
|
#ifdef MT62XX_NAND_BBT_IN_NAND
|
|
chip->options |= NAND_USE_FLASH_BBT;
|
|
chip->bbt_td = &bbt_main_descr;
|
|
chip->bbt_md = &bbt_mirror_descr;
|
|
#endif
|
|
|
|
/* ECC settings */
|
|
chip->ecc.mode = NAND_ECC_HW;
|
|
chip->ecc.calculate = mt62xx_nand_ecc_calculate;
|
|
chip->ecc.correct = mt62xx_nand_ecc_correct;
|
|
chip->ecc.hwctl = mt62xx_nand_ecc_hwctl;
|
|
chip->ecc.size = 256;
|
|
|
|
mtd = &nand_info[chip_nr++];
|
|
|
|
/* Detect NAND chip */
|
|
if (nand_scan_ident(mtd, 1, NULL))
|
|
return -ENXIO;
|
|
|
|
if (mtd->writesize > 512)
|
|
/* Large page NAND detected */
|
|
writel(NFI_PAGEFMT_PSIZE_2048 |
|
|
NFI_PAGEFMT_ADRMODE_LARGE_8IO |
|
|
NFI_PAGEFMT_ECCBLKSIZE_256,
|
|
MTK_NFI_PAGEFMT);
|
|
else
|
|
/* Small page NAND detected */
|
|
writel(NFI_PAGEFMT_ECCBLKSIZE_256,
|
|
MTK_NFI_PAGEFMT);
|
|
|
|
return 0;
|
|
}
|