mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-03 21:48:15 +00:00 
			
		
		
		
	Update MTD to that of Linux 2.6.22.1
A lot changed in the Linux MTD code, since it was last ported from Linux to U-Boot. This patch takes U-Boot NAND support to the level of Linux 2.6.22.1 and will enable support for very large NAND devices (4KB pages) and ease the compatibility between U-Boot and Linux filesystems. This patch is tested on two custom boards with PPC and ARM processors running YAFFS in U-Boot and Linux using gcc-4.1.2 cross compilers. MAKEALL ppc/arm has some issues: * DOC/OneNand/nand_spl is not building (I have not tried porting these parts, and since I do not have any HW and I am not familiar with this code/HW I think its best left to someone else.) Except for the issues mentioned above, I have ported all drivers necessary to run MAKEALL ppc/arm without errors and warnings. Many drivers were trivial to port, but some were not so trivial. The following drivers must be examined carefully and maybe rewritten to some degree: cpu/ppc4xx/ndfc.c cpu/arm926ejs/davinci/nand.c board/delta/nand.c board/zylonite/nand.c Signed-off-by: William Juul <william.juul@tandberg.com> Signed-off-by: Stig Olsen <stig.olsen@tandberg.com> Signed-off-by: Scott Wood <scottwood@freescale.com>
This commit is contained in:
		
							parent
							
								
									cd82919e6c
								
							
						
					
					
						commit
						cfa460adfd
					
				@ -37,34 +37,29 @@
 | 
			
		||||
/*
 | 
			
		||||
 * hardware specific access to control-lines
 | 
			
		||||
 */
 | 
			
		||||
static void bfin_hwcontrol(struct mtd_info *mtd, int cmd)
 | 
			
		||||
static void bfin_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 | 
			
		||||
{
 | 
			
		||||
	register struct nand_chip *this = mtd->priv;
 | 
			
		||||
    u32 IO_ADDR_W = (u32) this->IO_ADDR_W;
 | 
			
		||||
 | 
			
		||||
	switch (cmd) {
 | 
			
		||||
 | 
			
		||||
	case NAND_CTL_SETCLE:
 | 
			
		||||
		this->IO_ADDR_W = CFG_NAND_BASE + BFIN_NAND_CLE;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRCLE:
 | 
			
		||||
		this->IO_ADDR_W = CFG_NAND_BASE;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case NAND_CTL_SETALE:
 | 
			
		||||
		this->IO_ADDR_W = CFG_NAND_BASE + BFIN_NAND_ALE;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRALE:
 | 
			
		||||
		this->IO_ADDR_W = CFG_NAND_BASE;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_SETNCE:
 | 
			
		||||
	case NAND_CTL_CLRNCE:
 | 
			
		||||
		break;
 | 
			
		||||
	if (ctrl & NAND_CTRL_CHANGE) {
 | 
			
		||||
		if( ctrl & NAND_CLE )
 | 
			
		||||
			IO_ADDR_W = CFG_NAND_BASE + BFIN_NAND_CLE;
 | 
			
		||||
		else
 | 
			
		||||
			IO_ADDR_W = CFG_NAND_BASE;
 | 
			
		||||
		if( ctrl & NAND_ALE )
 | 
			
		||||
			IO_ADDR_W = CFG_NAND_BASE + BFIN_NAND_ALE;
 | 
			
		||||
		else
 | 
			
		||||
			IO_ADDR_W = CFG_NAND_BASE;			
 | 
			
		||||
		this->IO_ADDR_W = (void __iomem *) IO_ADDR_W;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this->IO_ADDR_R = this->IO_ADDR_W;
 | 
			
		||||
 | 
			
		||||
	/* Drain the writebuffer */
 | 
			
		||||
	SSYNC();
 | 
			
		||||
 | 
			
		||||
	if (cmd != NAND_CMD_NONE)
 | 
			
		||||
		writeb(cmd, this->IO_ADDR_W);	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int bfin_device_ready(struct mtd_info *mtd)
 | 
			
		||||
@ -79,11 +74,11 @@ int bfin_device_ready(struct mtd_info *mtd)
 | 
			
		||||
 * argument are board-specific (per include/linux/mtd/nand.h):
 | 
			
		||||
 * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device
 | 
			
		||||
 * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device
 | 
			
		||||
 * - hwcontrol: hardwarespecific function for accesing control-lines
 | 
			
		||||
 * - cmd_ctrl: hardwarespecific function for accesing control-lines
 | 
			
		||||
 * - dev_ready: hardwarespecific function for  accesing device ready/busy line
 | 
			
		||||
 * - enable_hwecc?: function to enable (reset)  hardware ecc generator. Must
 | 
			
		||||
 *   only be provided if a hardware ECC is available
 | 
			
		||||
 * - eccmode: mode of ecc, see defines
 | 
			
		||||
 * - ecc.mode: mode of ecc, see defines
 | 
			
		||||
 * - chip_delay: chip dependent delay for transfering data from array to
 | 
			
		||||
 *   read regs (tR)
 | 
			
		||||
 * - options: various chip options. They can partly be set to inform
 | 
			
		||||
@ -98,8 +93,8 @@ void board_nand_init(struct nand_chip *nand)
 | 
			
		||||
	*PORT(CONFIG_NAND_GPIO_PORT, IO_DIR) &= ~BFIN_NAND_READY;
 | 
			
		||||
	*PORT(CONFIG_NAND_GPIO_PORT, IO_INEN) |= BFIN_NAND_READY;
 | 
			
		||||
 | 
			
		||||
	nand->hwcontrol = bfin_hwcontrol;
 | 
			
		||||
	nand->eccmode = NAND_ECC_SOFT;
 | 
			
		||||
	nand->cmd_ctrl = bfin_hwcontrol;
 | 
			
		||||
	nand->ecc.mode = NAND_ECC_SOFT;
 | 
			
		||||
	nand->dev_ready = bfin_device_ready;
 | 
			
		||||
	nand->chip_delay = 30;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -21,7 +21,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <common.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_CMD_NAND)
 | 
			
		||||
 | 
			
		||||
@ -31,31 +31,28 @@
 | 
			
		||||
 * hardware specific access to control-lines
 | 
			
		||||
 * function borrowed from Linux 2.6 (drivers/mtd/nand/ppchameleonevb.c)
 | 
			
		||||
 */
 | 
			
		||||
static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd)
 | 
			
		||||
static void ppchameleonevb_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 | 
			
		||||
{
 | 
			
		||||
	struct nand_chip *this = mtdinfo->priv;
 | 
			
		||||
	struct nand_chip *this = mtd->priv;
 | 
			
		||||
	ulong base = (ulong) this->IO_ADDR_W;
 | 
			
		||||
 | 
			
		||||
	switch(cmd) {
 | 
			
		||||
	case NAND_CTL_SETCLE:
 | 
			
		||||
		MACRO_NAND_CTL_SETCLE((unsigned long)base);
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRCLE:
 | 
			
		||||
		MACRO_NAND_CTL_CLRCLE((unsigned long)base);
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_SETALE:
 | 
			
		||||
		MACRO_NAND_CTL_SETALE((unsigned long)base);
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRALE:
 | 
			
		||||
		MACRO_NAND_CTL_CLRALE((unsigned long)base);
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_SETNCE:
 | 
			
		||||
		MACRO_NAND_ENABLE_CE((unsigned long)base);
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRNCE:
 | 
			
		||||
		MACRO_NAND_DISABLE_CE((unsigned long)base);
 | 
			
		||||
		break;
 | 
			
		||||
    if (ctrl & NAND_CTRL_CHANGE) {
 | 
			
		||||
		if ( ctrl & NAND_CLE )
 | 
			
		||||
			MACRO_NAND_CTL_SETCLE((unsigned long)base);
 | 
			
		||||
		else
 | 
			
		||||
			MACRO_NAND_CTL_CLRCLE((unsigned long)base);
 | 
			
		||||
		if ( ctrl & NAND_ALE )
 | 
			
		||||
			MACRO_NAND_CTL_CLRCLE((unsigned long)base);
 | 
			
		||||
		else
 | 
			
		||||
			MACRO_NAND_CTL_CLRALE((unsigned long)base);
 | 
			
		||||
		if ( ctrl & NAND_NCE )
 | 
			
		||||
			MACRO_NAND_ENABLE_CE((unsigned long)base);
 | 
			
		||||
		else
 | 
			
		||||
			MACRO_NAND_DISABLE_CE((unsigned long)base);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    if (cmd != NAND_CMD_NONE)
 | 
			
		||||
		writeb(cmd, this->IO_ADDR_W);	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -92,11 +89,11 @@ static int ppchameleonevb_device_ready(struct mtd_info *mtdinfo)
 | 
			
		||||
 * argument are board-specific (per include/linux/mtd/nand.h):
 | 
			
		||||
 * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device
 | 
			
		||||
 * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device
 | 
			
		||||
 * - hwcontrol: hardwarespecific function for accesing control-lines
 | 
			
		||||
 * - cmd_ctrl: hardwarespecific function for accesing control-lines
 | 
			
		||||
 * - dev_ready: hardwarespecific function for  accesing device ready/busy line
 | 
			
		||||
 * - enable_hwecc?: function to enable (reset)  hardware ecc generator. Must
 | 
			
		||||
 *   only be provided if a hardware ECC is available
 | 
			
		||||
 * - eccmode: mode of ecc, see defines
 | 
			
		||||
 * - ecc.mode: mode of ecc, see defines
 | 
			
		||||
 * - chip_delay: chip dependent delay for transfering data from array to
 | 
			
		||||
 *   read regs (tR)
 | 
			
		||||
 * - options: various chip options. They can partly be set to inform
 | 
			
		||||
@ -108,9 +105,9 @@ static int ppchameleonevb_device_ready(struct mtd_info *mtdinfo)
 | 
			
		||||
int board_nand_init(struct nand_chip *nand)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	nand->hwcontrol = ppchameleonevb_hwcontrol;
 | 
			
		||||
	nand->cmd_ctrl = ppchameleonevb_hwcontrol;
 | 
			
		||||
	nand->dev_ready = ppchameleonevb_device_ready;
 | 
			
		||||
	nand->eccmode = NAND_ECC_SOFT;
 | 
			
		||||
	nand->ecc.mode = NAND_ECC_SOFT;
 | 
			
		||||
	nand->chip_delay = NAND_BIG_DELAY_US;
 | 
			
		||||
	nand->options = NAND_SAMSUNG_LP_OPTIONS;
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
@ -69,7 +69,7 @@ static struct nand_oobinfo delta_oob = {
 | 
			
		||||
/*
 | 
			
		||||
 * not required for Monahans DFC
 | 
			
		||||
 */
 | 
			
		||||
static void dfc_hwcontrol(struct mtd_info *mtdinfo, int cmd)
 | 
			
		||||
static void dfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
@ -110,30 +110,6 @@ static void dfc_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * These functions are quite problematic for the DFC. Luckily they are
 | 
			
		||||
 * not used in the current nand code, except for nand_command, which
 | 
			
		||||
 * we've defined our own anyway. The problem is, that we always need
 | 
			
		||||
 * to write 4 bytes to the DFC Data Buffer, but in these functions we
 | 
			
		||||
 * don't know if to buffer the bytes/half words until we've gathered 4
 | 
			
		||||
 * bytes or if to send them straight away.
 | 
			
		||||
 *
 | 
			
		||||
 * Solution: Don't use these with Mona's DFC and complain loudly.
 | 
			
		||||
 */
 | 
			
		||||
static void dfc_write_word(struct mtd_info *mtd, u16 word)
 | 
			
		||||
{
 | 
			
		||||
	printf("dfc_write_word: WARNING, this function does not work with the Monahans DFC!\n");
 | 
			
		||||
}
 | 
			
		||||
static void dfc_write_byte(struct mtd_info *mtd, u_char byte)
 | 
			
		||||
{
 | 
			
		||||
	printf("dfc_write_byte: WARNING, this function does not work with the Monahans DFC!\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* The original:
 | 
			
		||||
 * static void dfc_read_buf(struct mtd_info *mtd, const u_char *buf, int len)
 | 
			
		||||
 *
 | 
			
		||||
 * Shouldn't this be "u_char * const buf" ?
 | 
			
		||||
 */
 | 
			
		||||
static void dfc_read_buf(struct mtd_info *mtd, u_char* const buf, int len)
 | 
			
		||||
{
 | 
			
		||||
	int i=0, j;
 | 
			
		||||
@ -168,7 +144,7 @@ static void dfc_read_buf(struct mtd_info *mtd, u_char* const buf, int len)
 | 
			
		||||
 */
 | 
			
		||||
static u16 dfc_read_word(struct mtd_info *mtd)
 | 
			
		||||
{
 | 
			
		||||
	printf("dfc_write_byte: UNIMPLEMENTED.\n");
 | 
			
		||||
	printf("dfc_read_word: UNIMPLEMENTED.\n");
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -289,9 +265,10 @@ static void dfc_new_cmd(void)
 | 
			
		||||
 | 
			
		||||
/* this function is called after Programm and Erase Operations to
 | 
			
		||||
 * check for success or failure */
 | 
			
		||||
static int dfc_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
 | 
			
		||||
static int dfc_wait(struct mtd_info *mtd, struct nand_chip *this)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long ndsr=0, event=0;
 | 
			
		||||
	int state = this->state;
 | 
			
		||||
 | 
			
		||||
	if(state == FL_WRITING) {
 | 
			
		||||
		event = NDSR_CS0_CMDD | NDSR_CS0_BBD;
 | 
			
		||||
@ -439,7 +416,7 @@ static void dfc_gpio_init(void)
 | 
			
		||||
 * - dev_ready: hardwarespecific function for  accesing device ready/busy line
 | 
			
		||||
 * - enable_hwecc?: function to enable (reset)  hardware ecc generator. Must
 | 
			
		||||
 *   only be provided if a hardware ECC is available
 | 
			
		||||
 * - eccmode: mode of ecc, see defines
 | 
			
		||||
 * - ecc.mode: mode of ecc, see defines
 | 
			
		||||
 * - chip_delay: chip dependent delay for transfering data from array to
 | 
			
		||||
 *   read regs (tR)
 | 
			
		||||
 * - options: various chip options. They can partly be set to inform
 | 
			
		||||
@ -561,20 +538,18 @@ int board_nand_init(struct nand_chip *nand)
 | 
			
		||||
	/*	wait(10); */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	nand->hwcontrol = dfc_hwcontrol;
 | 
			
		||||
	nand->cmd_ctrl = dfc_hwcontrol;
 | 
			
		||||
/*	nand->dev_ready = dfc_device_ready; */
 | 
			
		||||
	nand->eccmode = NAND_ECC_SOFT;
 | 
			
		||||
	nand->ecc.mode = NAND_ECC_SOFT;
 | 
			
		||||
	nand->options = NAND_BUSWIDTH_16;
 | 
			
		||||
	nand->waitfunc = dfc_wait;
 | 
			
		||||
	nand->read_byte = dfc_read_byte;
 | 
			
		||||
	nand->write_byte = dfc_write_byte;
 | 
			
		||||
	nand->read_word = dfc_read_word;
 | 
			
		||||
	nand->write_word = dfc_write_word;
 | 
			
		||||
	nand->read_buf = dfc_read_buf;
 | 
			
		||||
	nand->write_buf = dfc_write_buf;
 | 
			
		||||
 | 
			
		||||
	nand->cmdfunc = dfc_cmdfunc;
 | 
			
		||||
	nand->autooob = &delta_oob;
 | 
			
		||||
//	nand->autooob = &delta_oob;
 | 
			
		||||
	nand->badblock_pattern = &delta_bbt_descr;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -30,28 +30,26 @@
 | 
			
		||||
/*
 | 
			
		||||
 * hardware specific access to control-lines
 | 
			
		||||
 */
 | 
			
		||||
static void esd405ep_nand_hwcontrol(struct mtd_info *mtdinfo, int cmd)
 | 
			
		||||
static void esd405ep_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 | 
			
		||||
{
 | 
			
		||||
	switch(cmd) {
 | 
			
		||||
	case NAND_CTL_SETCLE:
 | 
			
		||||
		out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) | CFG_NAND_CLE);
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRCLE:
 | 
			
		||||
		out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) & ~CFG_NAND_CLE);
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_SETALE:
 | 
			
		||||
		out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) | CFG_NAND_ALE);
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRALE:
 | 
			
		||||
		out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) & ~CFG_NAND_ALE);
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_SETNCE:
 | 
			
		||||
		out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) & ~CFG_NAND_CE);
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRNCE:
 | 
			
		||||
		out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) | CFG_NAND_CE);
 | 
			
		||||
		break;
 | 
			
		||||
    struct nand_chip *this = mtd->priv;
 | 
			
		||||
    if (ctrl & NAND_CTRL_CHANGE) {
 | 
			
		||||
		if ( ctrl & NAND_CLE )
 | 
			
		||||
			out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) | CFG_NAND_CLE);
 | 
			
		||||
		else
 | 
			
		||||
			out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) & ~CFG_NAND_CLE);
 | 
			
		||||
		if ( ctrl & NAND_ALE )
 | 
			
		||||
			out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) | CFG_NAND_ALE);
 | 
			
		||||
		else
 | 
			
		||||
			out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) & ~CFG_NAND_ALE);
 | 
			
		||||
		if ( ctrl & NAND_NCE )
 | 
			
		||||
			out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) & ~CFG_NAND_CE);
 | 
			
		||||
		else
 | 
			
		||||
			out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) | CFG_NAND_CE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    if (cmd != NAND_CMD_NONE)
 | 
			
		||||
		writeb(cmd, this->IO_ADDR_W);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -77,9 +75,9 @@ int board_nand_init(struct nand_chip *nand)
 | 
			
		||||
	/*
 | 
			
		||||
	 * Initialize nand_chip structure
 | 
			
		||||
	 */
 | 
			
		||||
	nand->hwcontrol = esd405ep_nand_hwcontrol;
 | 
			
		||||
	nand->cmd_ctrl = esd405ep_nand_hwcontrol;
 | 
			
		||||
	nand->dev_ready = esd405ep_nand_device_ready;
 | 
			
		||||
	nand->eccmode = NAND_ECC_SOFT;
 | 
			
		||||
	nand->ecc.mode = NAND_ECC_SOFT;
 | 
			
		||||
	nand->chip_delay = NAND_BIG_DELAY_US;
 | 
			
		||||
	nand->options = NAND_SAMSUNG_LP_OPTIONS;
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
@ -40,36 +40,26 @@ DECLARE_GLOBAL_DATA_PTR;
 | 
			
		||||
#define SET_ALE		0x08
 | 
			
		||||
#define CLR_ALE		~SET_ALE
 | 
			
		||||
 | 
			
		||||
static void nand_hwcontrol(struct mtd_info *mtdinfo, int cmd)
 | 
			
		||||
static void nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 | 
			
		||||
{
 | 
			
		||||
	struct nand_chip *this = mtdinfo->priv;
 | 
			
		||||
	volatile fbcs_t *fbcs = (fbcs_t *) MMAP_FBCS;
 | 
			
		||||
/*	volatile fbcs_t *fbcs = (fbcs_t *) MMAP_FBCS; TODO: handle wp */
 | 
			
		||||
	u32 nand_baseaddr = (u32) this->IO_ADDR_W;
 | 
			
		||||
 | 
			
		||||
	switch (cmd) {
 | 
			
		||||
	case NAND_CTL_SETNCE:
 | 
			
		||||
	case NAND_CTL_CLRNCE:
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_SETCLE:
 | 
			
		||||
		nand_baseaddr |= SET_CLE;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRCLE:
 | 
			
		||||
		nand_baseaddr &= CLR_CLE;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_SETALE:
 | 
			
		||||
		nand_baseaddr |= SET_ALE;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRALE:
 | 
			
		||||
		nand_baseaddr |= CLR_ALE;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_SETWP:
 | 
			
		||||
		fbcs->csmr2 |= FBCS_CSMR_WP;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRWP:
 | 
			
		||||
		fbcs->csmr2 &= ~FBCS_CSMR_WP;
 | 
			
		||||
		break;
 | 
			
		||||
	if (ctrl & NAND_CTRL_CHANGE) {
 | 
			
		||||
		if ( ctrl & NAND_CLE )
 | 
			
		||||
			nand_baseaddr |= SET_CLE;
 | 
			
		||||
		else
 | 
			
		||||
			nand_baseaddr &= CLR_CLE;
 | 
			
		||||
		if ( ctrl & NAND_ALE )
 | 
			
		||||
			nand_baseaddr |= SET_ALE;
 | 
			
		||||
		else
 | 
			
		||||
			nand_baseaddr &= CLR_ALE;
 | 
			
		||||
	}
 | 
			
		||||
	this->IO_ADDR_W = (void __iomem *)(nand_baseaddr);
 | 
			
		||||
 | 
			
		||||
	if (cmd != NAND_CMD_NONE)
 | 
			
		||||
		writeb(cmd, this->IO_ADDR_W);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void nand_write_byte(struct mtd_info *mtdinfo, u_char byte)
 | 
			
		||||
@ -103,8 +93,8 @@ int board_nand_init(struct nand_chip *nand)
 | 
			
		||||
	gpio->podr_timer = 0;
 | 
			
		||||
 | 
			
		||||
	nand->chip_delay = 50;
 | 
			
		||||
	nand->eccmode = NAND_ECC_SOFT;
 | 
			
		||||
	nand->hwcontrol = nand_hwcontrol;
 | 
			
		||||
	nand->ecc.mode = NAND_ECC_SOFT;
 | 
			
		||||
	nand->cmd_ctrl = nand_hwcontrol;
 | 
			
		||||
	nand->read_byte = nand_read_byte;
 | 
			
		||||
	nand->write_byte = nand_write_byte;
 | 
			
		||||
	nand->dev_ready = nand_dev_ready;
 | 
			
		||||
 | 
			
		||||
@ -22,7 +22,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <common.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_CMD_NAND)
 | 
			
		||||
 | 
			
		||||
@ -32,57 +32,49 @@
 | 
			
		||||
/*
 | 
			
		||||
 *	hardware specific access to control-lines
 | 
			
		||||
 */
 | 
			
		||||
static void nc650_hwcontrol(struct mtd_info *mtd, int cmd)
 | 
			
		||||
static void nc650_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 | 
			
		||||
{
 | 
			
		||||
	struct nand_chip *this = mtd->priv;
 | 
			
		||||
 | 
			
		||||
	switch(cmd) {
 | 
			
		||||
	case NAND_CTL_SETCLE:
 | 
			
		||||
		this->IO_ADDR_W += 2;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRCLE:
 | 
			
		||||
		this->IO_ADDR_W -= 2;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_SETALE:
 | 
			
		||||
		this->IO_ADDR_W += 1;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRALE:
 | 
			
		||||
		this->IO_ADDR_W -= 1;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_SETNCE:
 | 
			
		||||
	case NAND_CTL_CLRNCE:
 | 
			
		||||
		/* nop */
 | 
			
		||||
		break;
 | 
			
		||||
    if (ctrl & NAND_CTRL_CHANGE) {
 | 
			
		||||
		if ( ctrl & NAND_CLE )
 | 
			
		||||
			this->IO_ADDR_W += 2;
 | 
			
		||||
		else
 | 
			
		||||
			this->IO_ADDR_W -= 2;
 | 
			
		||||
		if ( ctrl & NAND_ALE )
 | 
			
		||||
			this->IO_ADDR_W += 1;
 | 
			
		||||
		else
 | 
			
		||||
			this->IO_ADDR_W -= 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    if (cmd != NAND_CMD_NONE)
 | 
			
		||||
		writeb(cmd, this->IO_ADDR_W);	
 | 
			
		||||
}
 | 
			
		||||
#elif defined(CONFIG_IDS852_REV2)
 | 
			
		||||
/*
 | 
			
		||||
 *	hardware specific access to control-lines
 | 
			
		||||
 */
 | 
			
		||||
static void nc650_hwcontrol(struct mtd_info *mtd, int cmd)
 | 
			
		||||
static void nc650_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 | 
			
		||||
{
 | 
			
		||||
	struct nand_chip *this = mtd->priv;
 | 
			
		||||
 | 
			
		||||
	switch(cmd) {
 | 
			
		||||
	case NAND_CTL_SETCLE:
 | 
			
		||||
		*(((volatile __u8 *) this->IO_ADDR_W) + 0xa) = 0;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRCLE:
 | 
			
		||||
		*(((volatile __u8 *) this->IO_ADDR_W) + 0x8) = 0;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_SETALE:
 | 
			
		||||
		*(((volatile __u8 *) this->IO_ADDR_W) + 0x9) = 0;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRALE:
 | 
			
		||||
		*(((volatile __u8 *) this->IO_ADDR_W) + 0x8) = 0;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_SETNCE:
 | 
			
		||||
		*(((volatile __u8 *) this->IO_ADDR_W) + 0x8) = 0;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRNCE:
 | 
			
		||||
		*(((volatile __u8 *) this->IO_ADDR_W) + 0xc) = 0;
 | 
			
		||||
		break;
 | 
			
		||||
    if (ctrl & NAND_CTRL_CHANGE) {
 | 
			
		||||
		if ( ctrl & NAND_CLE )
 | 
			
		||||
			writeb(0, (volatile __u8 *) this->IO_ADDR_W + 0xa);
 | 
			
		||||
		else
 | 
			
		||||
			writeb(0, (volatile __u8 *) this->IO_ADDR_W) + 0x8);
 | 
			
		||||
		if ( ctrl & NAND_ALE )
 | 
			
		||||
			writeb(0, (volatile __u8 *) this->IO_ADDR_W) + 0x9);
 | 
			
		||||
		else
 | 
			
		||||
			writeb(0, (volatile __u8 *) this->IO_ADDR_W) + 0x8);
 | 
			
		||||
		if ( ctrl & NAND_NCE )
 | 
			
		||||
			writeb(0, (volatile __u8 *) this->IO_ADDR_W) + 0x8);
 | 
			
		||||
		else
 | 
			
		||||
			writeb(0, (volatile __u8 *) this->IO_ADDR_W) + 0xc);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    if (cmd != NAND_CMD_NONE)
 | 
			
		||||
		writeb(cmd, this->IO_ADDR_W);
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
#error Unknown IDS852 module revision
 | 
			
		||||
@ -93,11 +85,11 @@ static void nc650_hwcontrol(struct mtd_info *mtd, int cmd)
 | 
			
		||||
 * argument are board-specific (per include/linux/mtd/nand.h):
 | 
			
		||||
 * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device
 | 
			
		||||
 * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device
 | 
			
		||||
 * - hwcontrol: hardwarespecific function for accesing control-lines
 | 
			
		||||
 * - cmd_ctrl: hardwarespecific function for accesing control-lines
 | 
			
		||||
 * - dev_ready: hardwarespecific function for  accesing device ready/busy line
 | 
			
		||||
 * - enable_hwecc?: function to enable (reset)  hardware ecc generator. Must
 | 
			
		||||
 *   only be provided if a hardware ECC is available
 | 
			
		||||
 * - eccmode: mode of ecc, see defines
 | 
			
		||||
 * - eccm.ode: mode of ecc, see defines
 | 
			
		||||
 * - chip_delay: chip dependent delay for transfering data from array to
 | 
			
		||||
 *   read regs (tR)
 | 
			
		||||
 * - options: various chip options. They can partly be set to inform
 | 
			
		||||
@ -109,8 +101,8 @@ static void nc650_hwcontrol(struct mtd_info *mtd, int cmd)
 | 
			
		||||
int board_nand_init(struct nand_chip *nand)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	nand->hwcontrol = nc650_hwcontrol;
 | 
			
		||||
	nand->eccmode = NAND_ECC_SOFT;
 | 
			
		||||
	nand->cmd_ctrl = nc650_hwcontrol;
 | 
			
		||||
	nand->ecc.mode = NAND_ECC_SOFT;
 | 
			
		||||
	nand->chip_delay = 12;
 | 
			
		||||
/*	nand->options = NAND_SAMSUNG_LP_OPTIONS;*/
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
@ -21,6 +21,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <common.h>
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_CMD_NAND)
 | 
			
		||||
 | 
			
		||||
@ -32,24 +33,29 @@
 | 
			
		||||
#define	MASK_CLE	0x02
 | 
			
		||||
#define	MASK_ALE	0x04
 | 
			
		||||
 | 
			
		||||
static void netstar_nand_hwcontrol(struct mtd_info *mtd, int cmd)
 | 
			
		||||
static void netstar_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 | 
			
		||||
{
 | 
			
		||||
	struct nand_chip *this = mtd->priv;
 | 
			
		||||
	ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
 | 
			
		||||
 | 
			
		||||
	IO_ADDR_W &= ~(MASK_ALE|MASK_CLE);
 | 
			
		||||
	switch (cmd) {
 | 
			
		||||
		case NAND_CTL_SETCLE: IO_ADDR_W |= MASK_CLE; break;
 | 
			
		||||
		case NAND_CTL_SETALE: IO_ADDR_W |= MASK_ALE; break;
 | 
			
		||||
	if (ctrl & NAND_CTRL_CHANGE) {
 | 
			
		||||
		if ( ctrl & NAND_CLE )
 | 
			
		||||
			IO_ADDR_W |= MASK_CLE;
 | 
			
		||||
		if ( ctrl & NAND_ALE )
 | 
			
		||||
			IO_ADDR_W |= MASK_ALE;
 | 
			
		||||
	}
 | 
			
		||||
	this->IO_ADDR_W = (void *) IO_ADDR_W;
 | 
			
		||||
	this->IO_ADDR_W = (void __iomem *) IO_ADDR_W;
 | 
			
		||||
	
 | 
			
		||||
    if (cmd != NAND_CMD_NONE)
 | 
			
		||||
		writeb(cmd, this->IO_ADDR_W);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int board_nand_init(struct nand_chip *nand)
 | 
			
		||||
{
 | 
			
		||||
	nand->options = NAND_SAMSUNG_LP_OPTIONS;
 | 
			
		||||
	nand->eccmode = NAND_ECC_SOFT;
 | 
			
		||||
	nand->hwcontrol = netstar_nand_hwcontrol;
 | 
			
		||||
	nand->ecc.mode = NAND_ECC_SOFT;
 | 
			
		||||
	nand->cmd_ctrl = netstar_nand_hwcontrol;
 | 
			
		||||
	nand->chip_delay = 400;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -56,43 +56,24 @@ static struct alpr_ndfc_regs *alpr_ndfc = NULL;
 | 
			
		||||
 *
 | 
			
		||||
 * There are 2 NAND devices on the board, a Hynix HY27US08561A (1 GByte).
 | 
			
		||||
 */
 | 
			
		||||
static void alpr_nand_hwcontrol(struct mtd_info *mtd, int cmd)
 | 
			
		||||
{
 | 
			
		||||
	switch (cmd) {
 | 
			
		||||
	case NAND_CTL_SETCLE:
 | 
			
		||||
		hwctl |= 0x1;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRCLE:
 | 
			
		||||
		hwctl &= ~0x1;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_SETALE:
 | 
			
		||||
		hwctl |= 0x2;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRALE:
 | 
			
		||||
		hwctl &= ~0x2;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_SETNCE:
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRNCE:
 | 
			
		||||
		writeb(0x00, &(alpr_ndfc->term));
 | 
			
		||||
		break;
 | 
			
		||||
static void alpr_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 | 
			
		||||
{	
 | 
			
		||||
    struct nand_chip *this = mtd->priv;
 | 
			
		||||
 | 
			
		||||
	if (ctrl & NAND_CTRL_CHANGE) {
 | 
			
		||||
		if ( ctrl & NAND_CLE )
 | 
			
		||||
			hwctl |= 0x1;
 | 
			
		||||
		else
 | 
			
		||||
			hwctl &= ~0x1;
 | 
			
		||||
		if ( ctrl & NAND_ALE )
 | 
			
		||||
			hwctl |= 0x2;
 | 
			
		||||
		else
 | 
			
		||||
			hwctl &= ~0x2;
 | 
			
		||||
		if ( (ctrl & NAND_NCE) != NAND_NCE)
 | 
			
		||||
			writeb(0x00, &(alpr_ndfc->term));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void alpr_nand_write_byte(struct mtd_info *mtd, u_char byte)
 | 
			
		||||
{
 | 
			
		||||
	struct nand_chip *nand = mtd->priv;
 | 
			
		||||
 | 
			
		||||
	if (hwctl & 0x1)
 | 
			
		||||
		/*
 | 
			
		||||
		 * IO_ADDR_W used as CMD[i] reg to support multiple NAND
 | 
			
		||||
		 * chips.
 | 
			
		||||
		 */
 | 
			
		||||
		writeb(byte, nand->IO_ADDR_W);
 | 
			
		||||
	else if (hwctl & 0x2) {
 | 
			
		||||
		writeb(byte, &(alpr_ndfc->addr_wait));
 | 
			
		||||
	} else
 | 
			
		||||
		writeb(byte, &(alpr_ndfc->data));
 | 
			
		||||
	if (cmd != NAND_CMD_NONE)
 | 
			
		||||
		writeb(cmd, this->IO_ADDR_W);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static u_char alpr_nand_read_byte(struct mtd_info *mtd)
 | 
			
		||||
@ -158,12 +139,10 @@ int board_nand_init(struct nand_chip *nand)
 | 
			
		||||
{
 | 
			
		||||
	alpr_ndfc = (struct alpr_ndfc_regs *)CFG_NAND_BASE;
 | 
			
		||||
 | 
			
		||||
	nand->eccmode = NAND_ECC_SOFT;
 | 
			
		||||
	nand->ecc.mode = NAND_ECC_SOFT;
 | 
			
		||||
 | 
			
		||||
	/* Reference hardware control function */
 | 
			
		||||
	nand->hwcontrol  = alpr_nand_hwcontrol;
 | 
			
		||||
	/* Set command delay time */
 | 
			
		||||
	nand->write_byte = alpr_nand_write_byte;
 | 
			
		||||
	nand->cmd_ctrl  = alpr_nand_hwcontrol;
 | 
			
		||||
	nand->read_byte  = alpr_nand_read_byte;
 | 
			
		||||
	nand->write_buf  = alpr_nand_write_buf;
 | 
			
		||||
	nand->read_buf   = alpr_nand_read_buf;
 | 
			
		||||
 | 
			
		||||
@ -52,40 +52,26 @@ static struct pdnb3_ndfc_regs *pdnb3_ndfc;
 | 
			
		||||
 *
 | 
			
		||||
 * There is one NAND devices on the board, a Hynix HY27US08561A (32 MByte).
 | 
			
		||||
 */
 | 
			
		||||
static void pdnb3_nand_hwcontrol(struct mtd_info *mtd, int cmd)
 | 
			
		||||
static void pdnb3_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 | 
			
		||||
{
 | 
			
		||||
	switch (cmd) {
 | 
			
		||||
	case NAND_CTL_SETCLE:
 | 
			
		||||
		hwctl |= 0x1;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRCLE:
 | 
			
		||||
		hwctl &= ~0x1;
 | 
			
		||||
		break;
 | 
			
		||||
    struct nand_chip *this = mtd->priv;
 | 
			
		||||
 | 
			
		||||
	case NAND_CTL_SETALE:
 | 
			
		||||
		hwctl |= 0x2;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRALE:
 | 
			
		||||
		hwctl &= ~0x2;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case NAND_CTL_SETNCE:
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRNCE:
 | 
			
		||||
		writeb(0x00, &(pdnb3_ndfc->term));
 | 
			
		||||
		break;
 | 
			
		||||
	if (ctrl & NAND_CTRL_CHANGE) {
 | 
			
		||||
		if ( ctrl & NAND_CLE )
 | 
			
		||||
			hwctl |= 0x1;
 | 
			
		||||
		else
 | 
			
		||||
			hwctl &= ~0x1;
 | 
			
		||||
		if ( ctrl & NAND_ALE )
 | 
			
		||||
			hwctl |= 0x2;
 | 
			
		||||
		else
 | 
			
		||||
			hwctl &= ~0x2;
 | 
			
		||||
		if ( (ctrl & NAND_NCE) != NAND_NCE)
 | 
			
		||||
			writeb(0x00, &(pdnb3_ndfc->term));
 | 
			
		||||
	}
 | 
			
		||||
	if (cmd != NAND_CMD_NONE)
 | 
			
		||||
		writeb(cmd, this->IO_ADDR_W);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pdnb3_nand_write_byte(struct mtd_info *mtd, u_char byte)
 | 
			
		||||
{
 | 
			
		||||
	if (hwctl & 0x1)
 | 
			
		||||
		writeb(byte, &(pdnb3_ndfc->cmd));
 | 
			
		||||
	else if (hwctl & 0x2)
 | 
			
		||||
		writeb(byte, &(pdnb3_ndfc->addr));
 | 
			
		||||
	else
 | 
			
		||||
		writeb(byte, &(pdnb3_ndfc->data));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static u_char pdnb3_nand_read_byte(struct mtd_info *mtd)
 | 
			
		||||
{
 | 
			
		||||
@ -152,16 +138,13 @@ int board_nand_init(struct nand_chip *nand)
 | 
			
		||||
{
 | 
			
		||||
	pdnb3_ndfc = (struct pdnb3_ndfc_regs *)CFG_NAND_BASE;
 | 
			
		||||
 | 
			
		||||
	nand->eccmode = NAND_ECC_SOFT;
 | 
			
		||||
	nand->ecc.mode = NAND_ECC_SOFT;
 | 
			
		||||
 | 
			
		||||
	/* Set address of NAND IO lines (Using Linear Data Access Region) */
 | 
			
		||||
	nand->IO_ADDR_R = (void __iomem *) ((ulong) pdnb3_ndfc + 0x4);
 | 
			
		||||
	nand->IO_ADDR_W = (void __iomem *) ((ulong) pdnb3_ndfc + 0x4);
 | 
			
		||||
	/* Reference hardware control function */
 | 
			
		||||
	nand->hwcontrol  = pdnb3_nand_hwcontrol;
 | 
			
		||||
	/* Set command delay time */
 | 
			
		||||
	nand->hwcontrol  = pdnb3_nand_hwcontrol;
 | 
			
		||||
	nand->write_byte = pdnb3_nand_write_byte;
 | 
			
		||||
	nand->cmd_ctrl   = pdnb3_nand_hwcontrol;
 | 
			
		||||
	nand->read_byte  = pdnb3_nand_read_byte;
 | 
			
		||||
	nand->write_buf  = pdnb3_nand_write_buf;
 | 
			
		||||
	nand->read_buf   = pdnb3_nand_read_buf;
 | 
			
		||||
 | 
			
		||||
@ -39,30 +39,26 @@
 | 
			
		||||
static void *sc3_io_base;
 | 
			
		||||
static void *sc3_control_base = (void *)0xEF600700;
 | 
			
		||||
 | 
			
		||||
static void sc3_nand_hwcontrol(struct mtd_info *mtd, int cmd)
 | 
			
		||||
static void sc3_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 | 
			
		||||
{
 | 
			
		||||
	switch (cmd) {
 | 
			
		||||
	case NAND_CTL_SETCLE:
 | 
			
		||||
		set_bit (SC3_NAND_CLE, sc3_control_base);
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRCLE:
 | 
			
		||||
		clear_bit (SC3_NAND_CLE, sc3_control_base);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case NAND_CTL_SETALE:
 | 
			
		||||
		set_bit (SC3_NAND_ALE, sc3_control_base);
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRALE:
 | 
			
		||||
		clear_bit (SC3_NAND_ALE, sc3_control_base);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case NAND_CTL_SETNCE:
 | 
			
		||||
		set_bit (SC3_NAND_CE, sc3_control_base);
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRNCE:
 | 
			
		||||
		clear_bit (SC3_NAND_CE, sc3_control_base);
 | 
			
		||||
		break;
 | 
			
		||||
    struct nand_chip *this = mtd->priv;
 | 
			
		||||
    if (ctrl & NAND_CTRL_CHANGE) {
 | 
			
		||||
		if ( ctrl & NAND_CLE )
 | 
			
		||||
			set_bit (SC3_NAND_CLE, sc3_control_base);
 | 
			
		||||
		else
 | 
			
		||||
			clear_bit (SC3_NAND_CLE, sc3_control_base);			
 | 
			
		||||
		if ( ctrl & NAND_ALE )
 | 
			
		||||
			set_bit (SC3_NAND_ALE, sc3_control_base);
 | 
			
		||||
		else
 | 
			
		||||
			clear_bit (SC3_NAND_ALE, sc3_control_base);
 | 
			
		||||
		if ( ctrl & NAND_NCE )
 | 
			
		||||
			set_bit (SC3_NAND_CE, sc3_control_base);
 | 
			
		||||
		else
 | 
			
		||||
			clear_bit (SC3_NAND_CE, sc3_control_base);		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    if (cmd != NAND_CMD_NONE)
 | 
			
		||||
		writeb(cmd, this->IO_ADDR_W);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int sc3_nand_dev_ready(struct mtd_info *mtd)
 | 
			
		||||
@ -79,14 +75,14 @@ static void sc3_select_chip(struct mtd_info *mtd, int chip)
 | 
			
		||||
 | 
			
		||||
int board_nand_init(struct nand_chip *nand)
 | 
			
		||||
{
 | 
			
		||||
	nand->eccmode = NAND_ECC_SOFT;
 | 
			
		||||
	nand->ecc.mode = NAND_ECC_SOFT;
 | 
			
		||||
 | 
			
		||||
	sc3_io_base = (void *) CFG_NAND_BASE;
 | 
			
		||||
	/* Set address of NAND IO lines (Using Linear Data Access Region) */
 | 
			
		||||
	nand->IO_ADDR_R = (void __iomem *) sc3_io_base;
 | 
			
		||||
	nand->IO_ADDR_W = (void __iomem *) sc3_io_base;
 | 
			
		||||
	/* Reference hardware control function */
 | 
			
		||||
	nand->hwcontrol  = sc3_nand_hwcontrol;
 | 
			
		||||
	nand->cmd_ctrl  = sc3_nand_hwcontrol;
 | 
			
		||||
	nand->dev_ready  = sc3_nand_dev_ready;
 | 
			
		||||
	nand->select_chip = sc3_select_chip;
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
@ -1068,24 +1068,22 @@ int update_flash_size (int flash_size)
 | 
			
		||||
 | 
			
		||||
static u8 hwctl = 0;
 | 
			
		||||
 | 
			
		||||
static void upmnand_hwcontrol(struct mtd_info *mtdinfo, int cmd)
 | 
			
		||||
static void upmnand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 | 
			
		||||
{
 | 
			
		||||
	switch (cmd) {
 | 
			
		||||
	case NAND_CTL_SETCLE:
 | 
			
		||||
		hwctl |= 0x1;
 | 
			
		||||
		break;
 | 
			
		||||
	case NAND_CTL_CLRCLE:
 | 
			
		||||
		hwctl &= ~0x1;
 | 
			
		||||
		break;
 | 
			
		||||
    struct nand_chip *this = mtd->priv;
 | 
			
		||||
 | 
			
		||||
	case NAND_CTL_SETALE:
 | 
			
		||||
		hwctl |= 0x2;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case NAND_CTL_CLRALE:
 | 
			
		||||
		hwctl &= ~0x2;
 | 
			
		||||
		break;
 | 
			
		||||
	if (ctrl & NAND_CTRL_CHANGE) {
 | 
			
		||||
		if ( ctrl & NAND_CLE )
 | 
			
		||||
			hwctl |= 0x1;
 | 
			
		||||
		else
 | 
			
		||||
			hwctl &= ~0x1;
 | 
			
		||||
		if ( ctrl & NAND_ALE )
 | 
			
		||||
			hwctl |= 0x2;
 | 
			
		||||
		else
 | 
			
		||||
			hwctl &= ~0x2;
 | 
			
		||||
	}
 | 
			
		||||
	if (cmd != NAND_CMD_NONE)
 | 
			
		||||
		writeb(cmd, this->IO_ADDR_W);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void upmnand_write_byte(struct mtd_info *mtdinfo, u_char byte)
 | 
			
		||||
@ -1188,9 +1186,9 @@ int board_nand_init(struct nand_chip *nand)
 | 
			
		||||
	memctl->memc_br3 = CFG_NAND_BR;
 | 
			
		||||
	memctl->memc_mbmr = (MxMR_OP_NORM);
 | 
			
		||||
 | 
			
		||||
	nand->eccmode = NAND_ECC_SOFT;
 | 
			
		||||
	nand->ecc.mode = NAND_ECC_SOFT;
 | 
			
		||||
 | 
			
		||||
	nand->hwcontrol	 = upmnand_hwcontrol;
 | 
			
		||||
	nand->cmd_ctrl	 = upmnand_hwcontrol;
 | 
			
		||||
	nand->read_byte	 = upmnand_read_byte;
 | 
			
		||||
	nand->write_byte = upmnand_write_byte;
 | 
			
		||||
	nand->dev_ready	 = tqm8272_dev_ready;
 | 
			
		||||
 | 
			
		||||
@ -69,7 +69,7 @@ static struct nand_oobinfo delta_oob = {
 | 
			
		||||
/*
 | 
			
		||||
 * not required for Monahans DFC
 | 
			
		||||
 */
 | 
			
		||||
static void dfc_hwcontrol(struct mtd_info *mtdinfo, int cmd)
 | 
			
		||||
static void dfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
@ -110,25 +110,6 @@ static void dfc_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * These functions are quite problematic for the DFC. Luckily they are
 | 
			
		||||
 * not used in the current nand code, except for nand_command, which
 | 
			
		||||
 * we've defined our own anyway. The problem is, that we always need
 | 
			
		||||
 * to write 4 bytes to the DFC Data Buffer, but in these functions we
 | 
			
		||||
 * don't know if to buffer the bytes/half words until we've gathered 4
 | 
			
		||||
 * bytes or if to send them straight away.
 | 
			
		||||
 *
 | 
			
		||||
 * Solution: Don't use these with Mona's DFC and complain loudly.
 | 
			
		||||
 */
 | 
			
		||||
static void dfc_write_word(struct mtd_info *mtd, u16 word)
 | 
			
		||||
{
 | 
			
		||||
	printf("dfc_write_word: WARNING, this function does not work with the Monahans DFC!\n");
 | 
			
		||||
}
 | 
			
		||||
static void dfc_write_byte(struct mtd_info *mtd, u_char byte)
 | 
			
		||||
{
 | 
			
		||||
	printf("dfc_write_byte: WARNING, this function does not work with the Monahans DFC!\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* The original:
 | 
			
		||||
 * static void dfc_read_buf(struct mtd_info *mtd, const u_char *buf, int len)
 | 
			
		||||
 *
 | 
			
		||||
@ -168,7 +149,7 @@ static void dfc_read_buf(struct mtd_info *mtd, u_char* const buf, int len)
 | 
			
		||||
 */
 | 
			
		||||
static u16 dfc_read_word(struct mtd_info *mtd)
 | 
			
		||||
{
 | 
			
		||||
	printf("dfc_write_byte: UNIMPLEMENTED.\n");
 | 
			
		||||
	printf("dfc_read_word: UNIMPLEMENTED.\n");
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -289,9 +270,10 @@ static void dfc_new_cmd(void)
 | 
			
		||||
 | 
			
		||||
/* this function is called after Programm and Erase Operations to
 | 
			
		||||
 * check for success or failure */
 | 
			
		||||
static int dfc_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
 | 
			
		||||
static int dfc_wait(struct mtd_info *mtd, struct nand_chip *this)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long ndsr=0, event=0;
 | 
			
		||||
	int state = this->state;
 | 
			
		||||
 | 
			
		||||
	if(state == FL_WRITING) {
 | 
			
		||||
		event = NDSR_CS0_CMDD | NDSR_CS0_BBD;
 | 
			
		||||
@ -435,11 +417,11 @@ static void dfc_gpio_init(void)
 | 
			
		||||
 * argument are board-specific (per include/linux/mtd/nand_new.h):
 | 
			
		||||
 * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device
 | 
			
		||||
 * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device
 | 
			
		||||
 * - hwcontrol: hardwarespecific function for accesing control-lines
 | 
			
		||||
 * - cmd_ctrl: hardwarespecific function for accesing control-lines
 | 
			
		||||
 * - dev_ready: hardwarespecific function for  accesing device ready/busy line
 | 
			
		||||
 * - enable_hwecc?: function to enable (reset)  hardware ecc generator. Must
 | 
			
		||||
 *   only be provided if a hardware ECC is available
 | 
			
		||||
 * - eccmode: mode of ecc, see defines
 | 
			
		||||
 * - ecc.mode: mode of ecc, see defines
 | 
			
		||||
 * - chip_delay: chip dependent delay for transfering data from array to
 | 
			
		||||
 *   read regs (tR)
 | 
			
		||||
 * - options: various chip options. They can partly be set to inform
 | 
			
		||||
@ -560,21 +542,18 @@ int board_nand_init(struct nand_chip *nand)
 | 
			
		||||
	/* wait 10 us due to cmd buffer clear reset */
 | 
			
		||||
	/*	wait(10); */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	nand->hwcontrol = dfc_hwcontrol;
 | 
			
		||||
	nand->cmd_ctrl = dfc_hwcontrol;
 | 
			
		||||
/*	nand->dev_ready = dfc_device_ready; */
 | 
			
		||||
	nand->eccmode = NAND_ECC_SOFT;
 | 
			
		||||
	nand->ecc.mode = NAND_ECC_SOFT;
 | 
			
		||||
	nand->options = NAND_BUSWIDTH_16;
 | 
			
		||||
	nand->waitfunc = dfc_wait;
 | 
			
		||||
	nand->read_byte = dfc_read_byte;
 | 
			
		||||
	nand->write_byte = dfc_write_byte;
 | 
			
		||||
	nand->read_word = dfc_read_word;
 | 
			
		||||
	nand->write_word = dfc_write_word;
 | 
			
		||||
	nand->read_buf = dfc_read_buf;
 | 
			
		||||
	nand->write_buf = dfc_write_buf;
 | 
			
		||||
 | 
			
		||||
	nand->cmdfunc = dfc_cmdfunc;
 | 
			
		||||
	nand->autooob = &delta_oob;
 | 
			
		||||
//	nand->autooob = &delta_oob;
 | 
			
		||||
	nand->badblock_pattern = &delta_bbt_descr;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -14,6 +14,7 @@
 | 
			
		||||
#include <linux/mtd/nftl.h>
 | 
			
		||||
#include <linux/mtd/doc2000.h>
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
#ifdef CFG_DOC_SUPPORT_2000
 | 
			
		||||
#define DoC_is_2000(doc) (doc->ChipID == DOC_ChipID_Doc2k)
 | 
			
		||||
#else
 | 
			
		||||
@ -1629,3 +1630,6 @@ void doc_probe(unsigned long physadr)
 | 
			
		||||
		puts ("No DiskOnChip found\n");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void doc_probe(unsigned long physadr) {}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -18,6 +18,7 @@
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#include <common.h>
 | 
			
		||||
#include <linux/mtd/mtd.h>
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_CMD_NAND)
 | 
			
		||||
 | 
			
		||||
@ -34,7 +35,7 @@
 | 
			
		||||
int mtdparts_init(void);
 | 
			
		||||
int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num);
 | 
			
		||||
int find_dev_and_part(const char *id, struct mtd_device **dev,
 | 
			
		||||
		u8 *part_num, struct part_info **part);
 | 
			
		||||
        u8 *part_num, struct part_info **part);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int nand_dump_oob(nand_info_t *nand, ulong off)
 | 
			
		||||
@ -47,32 +48,38 @@ static int nand_dump(nand_info_t *nand, ulong off)
 | 
			
		||||
	int i;
 | 
			
		||||
	u_char *buf, *p;
 | 
			
		||||
 | 
			
		||||
	buf = malloc(nand->oobblock + nand->oobsize);
 | 
			
		||||
	buf = malloc(nand->writesize + nand->oobsize);
 | 
			
		||||
	if (!buf) {
 | 
			
		||||
		puts("No memory for page buffer\n");
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
	off &= ~(nand->oobblock - 1);
 | 
			
		||||
	i = nand_read_raw(nand, buf, off, nand->oobblock, nand->oobsize);
 | 
			
		||||
	off &= ~(nand->writesize - 1);
 | 
			
		||||
#if 0
 | 
			
		||||
	i = nand_read_raw(nand, buf, off, nand->writesize, nand->oobsize);
 | 
			
		||||
#else
 | 
			
		||||
	size_t dummy;
 | 
			
		||||
	loff_t addr = (loff_t) off;
 | 
			
		||||
	i = nand->read(nand, addr, nand->writesize, &dummy, buf);
 | 
			
		||||
#endif
 | 
			
		||||
	if (i < 0) {
 | 
			
		||||
		printf("Error (%d) reading page %08lx\n", i, off);
 | 
			
		||||
		free(buf);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
	printf("Page %08lx dump:\n", off);
 | 
			
		||||
	i = nand->oobblock >> 4; p = buf;
 | 
			
		||||
	i = nand->writesize >> 4; p = buf;
 | 
			
		||||
	while (i--) {
 | 
			
		||||
		printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x"
 | 
			
		||||
			"  %02x %02x %02x %02x %02x %02x %02x %02x\n",
 | 
			
		||||
			p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
 | 
			
		||||
			p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
 | 
			
		||||
		printf("\t%02x %02x %02x %02x %02x %02x %02x %02x"
 | 
			
		||||
		       "  %02x %02x %02x %02x %02x %02x %02x %02x\n",
 | 
			
		||||
		       p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
 | 
			
		||||
		       p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
 | 
			
		||||
		p += 16;
 | 
			
		||||
	}
 | 
			
		||||
	puts("OOB:\n");
 | 
			
		||||
	i = nand->oobsize >> 3;
 | 
			
		||||
	while (i--) {
 | 
			
		||||
		printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
 | 
			
		||||
			p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
 | 
			
		||||
		printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
 | 
			
		||||
		       p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
 | 
			
		||||
		p += 8;
 | 
			
		||||
	}
 | 
			
		||||
	free(buf);
 | 
			
		||||
@ -155,7 +162,7 @@ out:
 | 
			
		||||
 | 
			
		||||
int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
	int i, dev, ret;
 | 
			
		||||
	int i, dev, ret = 0;
 | 
			
		||||
	ulong addr, off;
 | 
			
		||||
	size_t size;
 | 
			
		||||
	char *cmd, *s;
 | 
			
		||||
@ -182,8 +189,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 | 
			
		||||
		for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) {
 | 
			
		||||
			if (nand_info[i].name)
 | 
			
		||||
				printf("Device %d: %s, sector size %u KiB\n",
 | 
			
		||||
					i, nand_info[i].name,
 | 
			
		||||
					nand_info[i].erasesize >> 10);
 | 
			
		||||
 				       i, nand_info[i].name,
 | 
			
		||||
				       nand_info[i].erasesize >> 10);
 | 
			
		||||
		}
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@ -192,11 +199,11 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 | 
			
		||||
 | 
			
		||||
		if (argc < 3) {
 | 
			
		||||
			if ((nand_curr_device < 0) ||
 | 
			
		||||
			    (nand_curr_device >= CFG_MAX_NAND_DEVICE))
 | 
			
		||||
				(nand_curr_device >= CFG_MAX_NAND_DEVICE))
 | 
			
		||||
				puts("\nno devices available\n");
 | 
			
		||||
			else
 | 
			
		||||
				printf("\nDevice %d: %s\n", nand_curr_device,
 | 
			
		||||
					nand_info[nand_curr_device].name);
 | 
			
		||||
				       nand_info[nand_curr_device].name);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		dev = (int)simple_strtoul(argv[2], NULL, 10);
 | 
			
		||||
@ -219,11 +226,11 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&
 | 
			
		||||
	    strncmp(cmd, "dump", 4) != 0 &&
 | 
			
		||||
	    strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 &&
 | 
			
		||||
	    strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 &&
 | 
			
		||||
	    strcmp(cmd, "biterr") != 0 &&
 | 
			
		||||
	    strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 )
 | 
			
		||||
		strncmp(cmd, "dump", 4) != 0 &&
 | 
			
		||||
		strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 &&
 | 
			
		||||
		strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 &&
 | 
			
		||||
		strcmp(cmd, "biterr") != 0 &&
 | 
			
		||||
		strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 )
 | 
			
		||||
		goto usage;
 | 
			
		||||
 | 
			
		||||
	/* the following commands operate on the current device */
 | 
			
		||||
@ -250,7 +257,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 | 
			
		||||
	if (strcmp(cmd, "erase") == 0 || strcmp(cmd, "scrub") == 0) {
 | 
			
		||||
		nand_erase_options_t opts;
 | 
			
		||||
		/* "clean" at index 2 means request to write cleanmarker */
 | 
			
		||||
		int clean = argc > 2 && !strcmp("clean", argv[2]);
 | 
			
		||||
		int clean = !strcmp("clean", argv[2]);
 | 
			
		||||
		int o = clean ? 3 : 2;
 | 
			
		||||
		int scrub = !strcmp(cmd, "scrub");
 | 
			
		||||
 | 
			
		||||
@ -260,6 +267,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 | 
			
		||||
			return 1;
 | 
			
		||||
 | 
			
		||||
		memset(&opts, 0, sizeof(opts));
 | 
			
		||||
 | 
			
		||||
		opts.offset = off;
 | 
			
		||||
		opts.length = size;
 | 
			
		||||
		opts.jffs2  = clean;
 | 
			
		||||
@ -320,40 +328,41 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 | 
			
		||||
		printf("\nNAND %s: ", read ? "read" : "write");
 | 
			
		||||
		if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0)
 | 
			
		||||
			return 1;
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
		s = strchr(cmd, '.');
 | 
			
		||||
		if (s != NULL &&
 | 
			
		||||
		    (!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) {
 | 
			
		||||
			(!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) {
 | 
			
		||||
			if (read) {
 | 
			
		||||
				/* read */
 | 
			
		||||
				nand_read_options_t opts;
 | 
			
		||||
				memset(&opts, 0, sizeof(opts));
 | 
			
		||||
				opts.buffer	= (u_char*) addr;
 | 
			
		||||
				opts.length	= size;
 | 
			
		||||
				opts.offset	= off;
 | 
			
		||||
				opts.quiet      = quiet;
 | 
			
		||||
				ret = nand_read_opts(nand, &opts);
 | 
			
		||||
				opts.buffer = (u_char*) addr;
 | 
			
		||||
				opts.length = size;
 | 
			
		||||
				opts.offset = off;
 | 
			
		||||
				opts.quiet = quiet;
 | 
			
		||||
//				ret = nand_read_opts(nand, &opts);
 | 
			
		||||
			} else {
 | 
			
		||||
				/* write */
 | 
			
		||||
				nand_write_options_t opts;
 | 
			
		||||
				mtd_oob_ops_t opts;
 | 
			
		||||
				memset(&opts, 0, sizeof(opts));
 | 
			
		||||
				opts.buffer	= (u_char*) addr;
 | 
			
		||||
				opts.length	= size;
 | 
			
		||||
				opts.offset	= off;
 | 
			
		||||
				/* opts.forcejffs2 = 1; */
 | 
			
		||||
				opts.pad	= 1;
 | 
			
		||||
				opts.blockalign = 1;
 | 
			
		||||
				opts.quiet      = quiet;
 | 
			
		||||
				ret = nand_write_opts(nand, &opts);
 | 
			
		||||
				opts.datbuf = (u_char*) addr;
 | 
			
		||||
				opts.len = size;
 | 
			
		||||
				opts.ooblen = 64;
 | 
			
		||||
				opts.mode = MTD_OOB_AUTO;
 | 
			
		||||
				ret = nand_write_opts(nand, off, &opts);
 | 
			
		||||
			}
 | 
			
		||||
		} else if (s != NULL && !strcmp(s, ".oob")) {
 | 
			
		||||
			/* read out-of-band data */
 | 
			
		||||
			/* out-of-band data */
 | 
			
		||||
			mtd_oob_ops_t ops = {
 | 
			
		||||
				.oobbuf = (u8 *)addr,
 | 
			
		||||
				.ooblen = size,
 | 
			
		||||
				.mode = MTD_OOB_RAW
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			if (read)
 | 
			
		||||
				ret = nand->read_oob(nand, off, size, &size,
 | 
			
		||||
						     (u_char *) addr);
 | 
			
		||||
				ret = nand->read_oob(nand, off, &ops);
 | 
			
		||||
			else
 | 
			
		||||
				ret = nand->write_oob(nand, off, size, &size,
 | 
			
		||||
						      (u_char *) addr);
 | 
			
		||||
				ret = nand->write_oob(nand, off, &ops);
 | 
			
		||||
		} else {
 | 
			
		||||
			if (read)
 | 
			
		||||
				ret = nand_read(nand, off, &size, (u_char *)addr);
 | 
			
		||||
@ -397,44 +406,44 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (status) {
 | 
			
		||||
			ulong block_start = 0;
 | 
			
		||||
//			ulong block_start = 0;
 | 
			
		||||
			ulong off;
 | 
			
		||||
			int last_status = -1;
 | 
			
		||||
//			int last_status = -1;
 | 
			
		||||
 | 
			
		||||
			struct nand_chip *nand_chip = nand->priv;
 | 
			
		||||
			/* check the WP bit */
 | 
			
		||||
			nand_chip->cmdfunc (nand, NAND_CMD_STATUS, -1, -1);
 | 
			
		||||
			printf("device is %swrite protected\n",
 | 
			
		||||
			       (nand_chip->read_byte(nand) & 0x80 ?
 | 
			
		||||
				"NOT " : "" ) );
 | 
			
		||||
			       "NOT " : "" ) );
 | 
			
		||||
 | 
			
		||||
			for (off = 0; off < nand->size; off += nand->oobblock) {
 | 
			
		||||
				int s = nand_get_lock_status(nand, off);
 | 
			
		||||
 | 
			
		||||
				/* print message only if status has changed
 | 
			
		||||
				 * or at end of chip
 | 
			
		||||
				 */
 | 
			
		||||
				if (off == nand->size - nand->oobblock
 | 
			
		||||
				    || (s != last_status && off != 0))	{
 | 
			
		||||
 | 
			
		||||
					printf("%08lx - %08lx: %8lu pages %s%s%s\n",
 | 
			
		||||
					       block_start,
 | 
			
		||||
					       off-1,
 | 
			
		||||
					       (off-block_start)/nand->oobblock,
 | 
			
		||||
					       ((last_status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""),
 | 
			
		||||
					       ((last_status & NAND_LOCK_STATUS_LOCK) ? "LOCK " : ""),
 | 
			
		||||
					       ((last_status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : ""));
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				last_status = s;
 | 
			
		||||
		       }
 | 
			
		||||
		} else {
 | 
			
		||||
			if (!nand_lock(nand, tight)) {
 | 
			
		||||
				puts("NAND flash successfully locked\n");
 | 
			
		||||
			} else {
 | 
			
		||||
				puts("Error locking NAND flash\n");
 | 
			
		||||
				return 1;
 | 
			
		||||
			for (off = 0; off < nand->size; off += nand->writesize) {
 | 
			
		||||
//				int s = nand_get_lock_status(nand, off);
 | 
			
		||||
//
 | 
			
		||||
//				/* print message only if status has changed
 | 
			
		||||
//				 * or at end of chip
 | 
			
		||||
//				 */
 | 
			
		||||
//				if (off == nand->size - nand->writesize
 | 
			
		||||
//				    || (s != last_status && off != 0))	{
 | 
			
		||||
//
 | 
			
		||||
//					printf("%08lx - %08lx: %8d pages %s%s%s\n",
 | 
			
		||||
//					       block_start,
 | 
			
		||||
//					       off-1,
 | 
			
		||||
//					       (off-block_start)/nand->writesize,
 | 
			
		||||
//					       ((last_status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""),
 | 
			
		||||
//					       ((last_status & NAND_LOCK_STATUS_LOCK) ? "LOCK " : ""),
 | 
			
		||||
//					       ((last_status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : ""));
 | 
			
		||||
//				}
 | 
			
		||||
//
 | 
			
		||||
//				last_status = s;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
//			if (!nand_lock(nand, tight)) {
 | 
			
		||||
//				puts("NAND flash successfully locked\n");
 | 
			
		||||
//			} else {
 | 
			
		||||
//				puts("Error locking NAND flash\n");
 | 
			
		||||
//				return 1;
 | 
			
		||||
//			}
 | 
			
		||||
		}
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@ -443,13 +452,13 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 | 
			
		||||
		if (arg_off_size(argc - 2, argv + 2, nand, &off, &size) < 0)
 | 
			
		||||
			return 1;
 | 
			
		||||
 | 
			
		||||
		if (!nand_unlock(nand, off, size)) {
 | 
			
		||||
			puts("NAND flash successfully unlocked\n");
 | 
			
		||||
		} else {
 | 
			
		||||
			puts("Error unlocking NAND flash, "
 | 
			
		||||
			     "write and erase will probably fail\n");
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
//		if (!nand_unlock(nand, off, size)) {
 | 
			
		||||
//			puts("NAND flash successfully unlocked\n");
 | 
			
		||||
//		} else {
 | 
			
		||||
//			puts("Error unlocking NAND flash, "
 | 
			
		||||
//			     "write and erase will probably fail\n");
 | 
			
		||||
//			return 1;
 | 
			
		||||
//		}
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -459,24 +468,26 @@ usage:
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
U_BOOT_CMD(nand, 5, 1, do_nand,
 | 
			
		||||
	"nand    - NAND sub-system\n",
 | 
			
		||||
	"info                  - show available NAND devices\n"
 | 
			
		||||
	"nand device [dev]     - show or set current device\n"
 | 
			
		||||
	"nand read[.jffs2]     - addr off|partition size\n"
 | 
			
		||||
	"nand write[.jffs2]    - addr off|partition size - read/write `size' bytes starting\n"
 | 
			
		||||
	"    at offset `off' to/from memory address `addr'\n"
 | 
			
		||||
	"nand erase [clean] [off size] - erase `size' bytes from\n"
 | 
			
		||||
	"    offset `off' (entire device if not specified)\n"
 | 
			
		||||
	"nand bad - show bad blocks\n"
 | 
			
		||||
	"nand dump[.oob] off - dump page\n"
 | 
			
		||||
	"nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
 | 
			
		||||
	"nand markbad off - mark bad block at offset (UNSAFE)\n"
 | 
			
		||||
	"nand biterr off - make a bit error at offset (UNSAFE)\n"
 | 
			
		||||
	"nand lock [tight] [status] - bring nand to lock state or display locked pages\n"
 | 
			
		||||
	"nand unlock [offset] [size] - unlock section\n");
 | 
			
		||||
           "nand - NAND sub-system\n",
 | 
			
		||||
           "info - show available NAND devices\n"
 | 
			
		||||
           "nand device [dev] - show or set current device\n"
 | 
			
		||||
           "nand read[.jffs2] - addr off|partition size\n"
 | 
			
		||||
           "nand write[.jffs2] - addr off|partition size\n"
 | 
			
		||||
           "    read/write 'size' bytes starting at offset 'off'\n"
 | 
			
		||||
           "    to/from memory address 'addr'\n"
 | 
			
		||||
           "nand erase [clean] [off size] - erase 'size' bytes from\n"
 | 
			
		||||
           "    offset 'off' (entire device if not specified)\n"
 | 
			
		||||
           "nand bad - show bad blocks\n"
 | 
			
		||||
           "nand dump[.oob] off - dump page\n"
 | 
			
		||||
           "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
 | 
			
		||||
           "nand markbad off - mark bad block at offset (UNSAFE)\n"
 | 
			
		||||
           "nand biterr off - make a bit error at offset (UNSAFE)\n"
 | 
			
		||||
           "nand lock [tight] [status]\n"
 | 
			
		||||
           "    bring nand to lock state or display locked pages\n"
 | 
			
		||||
           "nand unlock [offset] [size] - unlock section\n");
 | 
			
		||||
 | 
			
		||||
static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,
 | 
			
		||||
			   ulong offset, ulong addr, char *cmd)
 | 
			
		||||
                           ulong offset, ulong addr, char *cmd)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	char *ep, *s;
 | 
			
		||||
@ -494,19 +505,8 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,
 | 
			
		||||
 | 
			
		||||
	printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset);
 | 
			
		||||
 | 
			
		||||
	cnt = nand->oobblock;
 | 
			
		||||
	if (jffs2) {
 | 
			
		||||
		nand_read_options_t opts;
 | 
			
		||||
		memset(&opts, 0, sizeof(opts));
 | 
			
		||||
		opts.buffer	= (u_char*) addr;
 | 
			
		||||
		opts.length	= cnt;
 | 
			
		||||
		opts.offset	= offset;
 | 
			
		||||
		opts.quiet      = 1;
 | 
			
		||||
		r = nand_read_opts(nand, &opts);
 | 
			
		||||
	} else {
 | 
			
		||||
		r = nand_read(nand, offset, &cnt, (u_char *) addr);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cnt = nand->writesize;
 | 
			
		||||
	r = nand_read(nand, offset, &cnt, (u_char *) addr);
 | 
			
		||||
	if (r) {
 | 
			
		||||
		puts("** Read error\n");
 | 
			
		||||
		show_boot_progress (-56);
 | 
			
		||||
@ -537,18 +537,7 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (jffs2) {
 | 
			
		||||
		nand_read_options_t opts;
 | 
			
		||||
		memset(&opts, 0, sizeof(opts));
 | 
			
		||||
		opts.buffer	= (u_char*) addr;
 | 
			
		||||
		opts.length	= cnt;
 | 
			
		||||
		opts.offset	= offset;
 | 
			
		||||
		opts.quiet      = 1;
 | 
			
		||||
		r = nand_read_opts(nand, &opts);
 | 
			
		||||
	} else {
 | 
			
		||||
		r = nand_read(nand, offset, &cnt, (u_char *) addr);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = nand_read(nand, offset, &cnt, (u_char *) addr);
 | 
			
		||||
	if (r) {
 | 
			
		||||
		puts("** Read error\n");
 | 
			
		||||
		show_boot_progress (-58);
 | 
			
		||||
@ -614,7 +603,7 @@ int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 | 
			
		||||
			else
 | 
			
		||||
				addr = CFG_LOAD_ADDR;
 | 
			
		||||
			return nand_load_image(cmdtp, &nand_info[dev->id->num],
 | 
			
		||||
					       part->offset, addr, argv[0]);
 | 
			
		||||
			                       part->offset, addr, argv[0]);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
@ -704,8 +693,8 @@ void archflashwp(void *archdata, int wp);
 | 
			
		||||
 | 
			
		||||
#define ROUND_DOWN(value,boundary)      ((value) & (~((boundary)-1)))
 | 
			
		||||
 | 
			
		||||
#undef	NAND_DEBUG
 | 
			
		||||
#undef	PSYCHO_DEBUG
 | 
			
		||||
#undef  NAND_DEBUG
 | 
			
		||||
#undef  PSYCHO_DEBUG
 | 
			
		||||
 | 
			
		||||
/* ****************** WARNING *********************
 | 
			
		||||
 * When ALLOW_ERASE_BAD_DEBUG is non-zero the erase command will
 | 
			
		||||
@ -720,16 +709,16 @@ void archflashwp(void *archdata, int wp);
 | 
			
		||||
 * and attempting to program or erase bad blocks can affect
 | 
			
		||||
 * the data in _other_ (good) blocks.
 | 
			
		||||
 */
 | 
			
		||||
#define	 ALLOW_ERASE_BAD_DEBUG 0
 | 
			
		||||
#define  ALLOW_ERASE_BAD_DEBUG 0
 | 
			
		||||
 | 
			
		||||
#define CONFIG_MTD_NAND_ECC  /* enable ECC */
 | 
			
		||||
#define CONFIG_MTD_NAND_ECC_JFFS2
 | 
			
		||||
 | 
			
		||||
/* bits for nand_legacy_rw() `cmd'; or together as needed */
 | 
			
		||||
#define NANDRW_READ	0x01
 | 
			
		||||
#define NANDRW_WRITE	0x00
 | 
			
		||||
#define NANDRW_JFFS2	0x02
 | 
			
		||||
#define NANDRW_JFFS2_SKIP	0x04
 | 
			
		||||
#define NANDRW_READ 0x01
 | 
			
		||||
#define NANDRW_WRITE    0x00
 | 
			
		||||
#define NANDRW_JFFS2    0x02
 | 
			
		||||
#define NANDRW_JFFS2_SKIP   0x04
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Imports from nand_legacy.c
 | 
			
		||||
@ -737,15 +726,15 @@ void archflashwp(void *archdata, int wp);
 | 
			
		||||
extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
 | 
			
		||||
extern int curr_device;
 | 
			
		||||
extern int nand_legacy_erase(struct nand_chip *nand, size_t ofs,
 | 
			
		||||
			    size_t len, int clean);
 | 
			
		||||
                size_t len, int clean);
 | 
			
		||||
extern int nand_legacy_rw(struct nand_chip *nand, int cmd, size_t start,
 | 
			
		||||
			 size_t len, size_t *retlen, u_char *buf);
 | 
			
		||||
             size_t len, size_t *retlen, u_char *buf);
 | 
			
		||||
extern void nand_print(struct nand_chip *nand);
 | 
			
		||||
extern void nand_print_bad(struct nand_chip *nand);
 | 
			
		||||
extern int nand_read_oob(struct nand_chip *nand, size_t ofs,
 | 
			
		||||
			       size_t len, size_t *retlen, u_char *buf);
 | 
			
		||||
                   size_t len, size_t *retlen, u_char *buf);
 | 
			
		||||
extern int nand_write_oob(struct nand_chip *nand, size_t ofs,
 | 
			
		||||
				size_t len, size_t *retlen, const u_char *buf);
 | 
			
		||||
                size_t len, size_t *retlen, const u_char *buf);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int do_nand (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 | 
			
		||||
@ -878,7 +867,7 @@ int do_nand (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 | 
			
		||||
			else if (cmdtail && !strcmp (cmdtail, ".i")) {
 | 
			
		||||
				cmd |= NANDRW_JFFS2;	/* skip bad blocks (on read too) */
 | 
			
		||||
				if (cmd & NANDRW_READ)
 | 
			
		||||
					cmd |= NANDRW_JFFS2_SKIP;	/* skip bad blocks (on read too) */
 | 
			
		||||
					cmd |= NANDRW_JFFS2_SKIP;   /* skip bad blocks (on read too) */
 | 
			
		||||
			}
 | 
			
		||||
#endif /* CFG_NAND_SKIP_BAD_DOT_I */
 | 
			
		||||
			else if (cmdtail) {
 | 
			
		||||
@ -928,7 +917,7 @@ int do_nand (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
U_BOOT_CMD(
 | 
			
		||||
	nand,	5,	1,	do_nand,
 | 
			
		||||
	nand,   5,  1,  do_nand,
 | 
			
		||||
	"nand    - legacy NAND sub-system\n",
 | 
			
		||||
	"info  - show available NAND devices\n"
 | 
			
		||||
	"nand device [dev] - show or set current device\n"
 | 
			
		||||
@ -992,7 +981,7 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 | 
			
		||||
	dev = simple_strtoul(boot_device, &ep, 16);
 | 
			
		||||
 | 
			
		||||
	if ((dev >= CFG_MAX_NAND_DEVICE) ||
 | 
			
		||||
	    (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN)) {
 | 
			
		||||
		(nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN)) {
 | 
			
		||||
		printf ("\n** Device %d not available\n", dev);
 | 
			
		||||
		show_boot_progress (-55);
 | 
			
		||||
		return 1;
 | 
			
		||||
@ -1000,11 +989,11 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 | 
			
		||||
	show_boot_progress (55);
 | 
			
		||||
 | 
			
		||||
	printf ("\nLoading from device %d: %s at 0x%lx (offset 0x%lx)\n",
 | 
			
		||||
		dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR,
 | 
			
		||||
		offset);
 | 
			
		||||
	    dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR,
 | 
			
		||||
	    offset);
 | 
			
		||||
 | 
			
		||||
	if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ, offset,
 | 
			
		||||
			SECTORSIZE, NULL, (u_char *)addr)) {
 | 
			
		||||
	                    SECTORSIZE, NULL, (u_char *)addr)) {
 | 
			
		||||
		printf ("** Read error on %d\n", dev);
 | 
			
		||||
		show_boot_progress (-56);
 | 
			
		||||
		return 1;
 | 
			
		||||
@ -1035,8 +1024,8 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 | 
			
		||||
	show_boot_progress (57);
 | 
			
		||||
 | 
			
		||||
	if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ,
 | 
			
		||||
			offset + SECTORSIZE, cnt, NULL,
 | 
			
		||||
			(u_char *)(addr+SECTORSIZE))) {
 | 
			
		||||
	                    offset + SECTORSIZE, cnt, NULL,
 | 
			
		||||
	                    (u_char *)(addr+SECTORSIZE))) {
 | 
			
		||||
		printf ("** Read error on %d\n", dev);
 | 
			
		||||
		show_boot_progress (-58);
 | 
			
		||||
		return 1;
 | 
			
		||||
@ -1077,7 +1066,7 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
U_BOOT_CMD(
 | 
			
		||||
	nboot,	4,	1,	do_nandboot,
 | 
			
		||||
	nboot,  4,  1,  do_nandboot,
 | 
			
		||||
	"nboot   - boot from NAND device\n",
 | 
			
		||||
	"loadAddr dev\n"
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
@ -42,6 +42,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <common.h>
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
 | 
			
		||||
#ifdef CFG_USE_NAND
 | 
			
		||||
#if !defined(CFG_NAND_LEGACY)
 | 
			
		||||
@ -52,23 +53,23 @@
 | 
			
		||||
 | 
			
		||||
extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
 | 
			
		||||
 | 
			
		||||
static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd)
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
	IO_ADDR_W &= ~(MASK_ALE|MASK_CLE);
 | 
			
		||||
 | 
			
		||||
	switch (cmd) {
 | 
			
		||||
		case NAND_CTL_SETCLE:
 | 
			
		||||
	if (ctrl & NAND_CTRL_CHANGE) {
 | 
			
		||||
		if ( ctrl & NAND_CLE )
 | 
			
		||||
			IO_ADDR_W |= MASK_CLE;
 | 
			
		||||
			break;
 | 
			
		||||
		case NAND_CTL_SETALE:
 | 
			
		||||
		if ( ctrl & NAND_ALE )
 | 
			
		||||
			IO_ADDR_W |= MASK_ALE;
 | 
			
		||||
			break;
 | 
			
		||||
		this->IO_ADDR_W = (void __iomem *) IO_ADDR_W;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this->IO_ADDR_W = (void *)IO_ADDR_W;
 | 
			
		||||
    if (cmd != NAND_CMD_NONE)
 | 
			
		||||
		writeb(cmd, this->IO_ADDR_W);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Set WP on deselect, write enable on select */
 | 
			
		||||
@ -145,7 +146,7 @@ static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u
 | 
			
		||||
	int			region, n;
 | 
			
		||||
	struct nand_chip	*this = mtd->priv;
 | 
			
		||||
 | 
			
		||||
	n = (this->eccmode == NAND_ECC_HW12_2048) ? 4 : 1;
 | 
			
		||||
	n = (this->ecc.size/512);
 | 
			
		||||
 | 
			
		||||
	region = 1;
 | 
			
		||||
	while (n--) {
 | 
			
		||||
@ -281,7 +282,7 @@ static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *
 | 
			
		||||
	int			block_count = 0, i, rc;
 | 
			
		||||
 | 
			
		||||
	this = mtd->priv;
 | 
			
		||||
	block_count = (this->eccmode == NAND_ECC_HW12_2048) ? 4 : 1;
 | 
			
		||||
	block_count = (this->ecc.size/512);
 | 
			
		||||
	for (i = 0; i < block_count; i++) {
 | 
			
		||||
		if (memcmp(read_ecc, calc_ecc, 3) != 0) {
 | 
			
		||||
			rc = nand_davinci_compare_ecc(read_ecc, calc_ecc, dat);
 | 
			
		||||
@ -306,7 +307,7 @@ static int nand_davinci_dev_ready(struct mtd_info *mtd)
 | 
			
		||||
	return(emif_addr->NANDFSR & 0x1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int nand_davinci_waitfunc(struct mtd_info *mtd, struct nand_chip *this, int state)
 | 
			
		||||
static int nand_davinci_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
 | 
			
		||||
{
 | 
			
		||||
	while(!nand_davinci_dev_ready(mtd)) {;}
 | 
			
		||||
	*NAND_CE0CLE = NAND_STATUS;
 | 
			
		||||
@ -362,22 +363,26 @@ int board_nand_init(struct nand_chip *nand)
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef CFG_NAND_HW_ECC
 | 
			
		||||
#ifdef CFG_NAND_LARGEPAGE
 | 
			
		||||
	nand->eccmode     = NAND_ECC_HW12_2048;
 | 
			
		||||
	nand->ecc.mode     = NAND_ECC_HW;
 | 
			
		||||
    nand->ecc.size = 2048;
 | 
			
		||||
    nand->ecc.bytes = 12;
 | 
			
		||||
#elif defined(CFG_NAND_SMALLPAGE)
 | 
			
		||||
	nand->eccmode     = NAND_ECC_HW3_512;
 | 
			
		||||
	nand->ecc.mode     = NAND_ECC_HW;
 | 
			
		||||
    nand->ecc.size = 512;
 | 
			
		||||
    nand->ecc.bytes = 3;
 | 
			
		||||
#else
 | 
			
		||||
#error "Either CFG_NAND_LARGEPAGE or CFG_NAND_SMALLPAGE must be defined!"
 | 
			
		||||
#endif
 | 
			
		||||
	nand->autooob	  = &davinci_nand_oobinfo;
 | 
			
		||||
	nand->calculate_ecc = nand_davinci_calculate_ecc;
 | 
			
		||||
	nand->correct_data  = nand_davinci_correct_data;
 | 
			
		||||
	nand->enable_hwecc  = nand_davinci_enable_hwecc;
 | 
			
		||||
//	nand->autooob	  = &davinci_nand_oobinfo;
 | 
			
		||||
	nand->ecc.calculate = nand_davinci_calculate_ecc;
 | 
			
		||||
	nand->ecc.correct  = nand_davinci_correct_data;
 | 
			
		||||
	nand->ecc.hwctl  = nand_davinci_enable_hwecc;	
 | 
			
		||||
#else
 | 
			
		||||
	nand->eccmode     = NAND_ECC_SOFT;
 | 
			
		||||
	nand->ecc.mode     = NAND_ECC_SOFT;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/* Set address of hardware control function */
 | 
			
		||||
	nand->hwcontrol = nand_davinci_hwcontrol;
 | 
			
		||||
	nand->cmd_ctrl = nand_davinci_hwcontrol;
 | 
			
		||||
 | 
			
		||||
	nand->dev_ready = nand_davinci_dev_ready;
 | 
			
		||||
	nand->waitfunc = nand_davinci_waitfunc;
 | 
			
		||||
 | 
			
		||||
@ -46,38 +46,22 @@
 | 
			
		||||
 | 
			
		||||
static u8 hwctl = 0;
 | 
			
		||||
 | 
			
		||||
static void ndfc_hwcontrol(struct mtd_info *mtdinfo, int cmd)
 | 
			
		||||
static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 | 
			
		||||
{
 | 
			
		||||
	switch (cmd) {
 | 
			
		||||
	case NAND_CTL_SETCLE:
 | 
			
		||||
		hwctl |= 0x1;
 | 
			
		||||
		break;
 | 
			
		||||
    struct nand_chip *this = mtd->priv;
 | 
			
		||||
 | 
			
		||||
	case NAND_CTL_CLRCLE:
 | 
			
		||||
		hwctl &= ~0x1;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case NAND_CTL_SETALE:
 | 
			
		||||
		hwctl |= 0x2;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case NAND_CTL_CLRALE:
 | 
			
		||||
		hwctl &= ~0x2;
 | 
			
		||||
		break;
 | 
			
		||||
	if (ctrl & NAND_CTRL_CHANGE) {
 | 
			
		||||
		if ( ctrl & NAND_CLE )
 | 
			
		||||
			hwctl |= 0x1;
 | 
			
		||||
		else
 | 
			
		||||
			hwctl &= ~0x1;
 | 
			
		||||
		if ( ctrl & NAND_ALE )
 | 
			
		||||
			hwctl |= 0x2;
 | 
			
		||||
		else
 | 
			
		||||
			hwctl &= ~0x2;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ndfc_write_byte(struct mtd_info *mtdinfo, u_char byte)
 | 
			
		||||
{
 | 
			
		||||
	struct nand_chip *this = mtdinfo->priv;
 | 
			
		||||
	ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc;
 | 
			
		||||
 | 
			
		||||
	if (hwctl & 0x1)
 | 
			
		||||
		out_8((u8 *)(base + NDFC_CMD), byte);
 | 
			
		||||
	else if (hwctl & 0x2)
 | 
			
		||||
		out_8((u8 *)(base + NDFC_ALE), byte);
 | 
			
		||||
	else
 | 
			
		||||
		out_8((u8 *)(base + NDFC_DATA), byte);
 | 
			
		||||
	if (cmd != NAND_CMD_NONE)
 | 
			
		||||
		writeb(cmd, this->IO_ADDR_W);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static u_char ndfc_read_byte(struct mtd_info *mtdinfo)
 | 
			
		||||
@ -194,16 +178,17 @@ int board_nand_init(struct nand_chip *nand)
 | 
			
		||||
	int cs = (ulong)nand->IO_ADDR_W & 0x00000003;
 | 
			
		||||
	ulong base = (ulong)nand->IO_ADDR_W & 0xfffffffc;
 | 
			
		||||
 | 
			
		||||
	nand->hwcontrol  = ndfc_hwcontrol;
 | 
			
		||||
	nand->cmd_ctrl  = ndfc_hwcontrol;
 | 
			
		||||
	nand->read_byte  = ndfc_read_byte;
 | 
			
		||||
	nand->read_buf   = ndfc_read_buf;
 | 
			
		||||
	nand->write_byte = ndfc_write_byte;
 | 
			
		||||
	nand->dev_ready  = ndfc_dev_ready;
 | 
			
		||||
 | 
			
		||||
	nand->eccmode = NAND_ECC_HW3_256;
 | 
			
		||||
	nand->enable_hwecc = ndfc_enable_hwecc;
 | 
			
		||||
	nand->calculate_ecc = ndfc_calculate_ecc;
 | 
			
		||||
	nand->correct_data = nand_correct_data;
 | 
			
		||||
    nand->ecc.correct = nand_correct_data;
 | 
			
		||||
    nand->ecc.hwctl = ndfc_enable_hwecc;
 | 
			
		||||
    nand->ecc.calculate = ndfc_calculate_ecc;
 | 
			
		||||
    nand->ecc.mode = NAND_ECC_HW;
 | 
			
		||||
    nand->ecc.size = 256;
 | 
			
		||||
    nand->ecc.bytes = 3;
 | 
			
		||||
 | 
			
		||||
#ifndef CONFIG_NAND_SPL
 | 
			
		||||
	nand->write_buf  = ndfc_write_buf;
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -7,7 +7,9 @@
 | 
			
		||||
 * Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com)
 | 
			
		||||
 *                         Toshiba America Electronics Components, Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: nand_ecc.c,v 1.14 2004/06/16 15:34:37 gleixner Exp $
 | 
			
		||||
 * 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
 | 
			
		||||
@ -39,6 +41,14 @@
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
 | 
			
		||||
 | 
			
		||||
/* XXX U-BOOT XXX */
 | 
			
		||||
#if 0
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/mtd/nand_ecc.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include<linux/mtd/mtd.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@ -128,6 +138,10 @@ int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
/* XXX U-BOOT XXX */
 | 
			
		||||
#if 0
 | 
			
		||||
EXPORT_SYMBOL(nand_calculate_ecc);
 | 
			
		||||
#endif
 | 
			
		||||
#endif /* CONFIG_NAND_SPL */
 | 
			
		||||
 | 
			
		||||
static inline int countbits(uint32_t byte)
 | 
			
		||||
@ -197,4 +211,9 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat,
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* XXX U-BOOT XXX */
 | 
			
		||||
#if 0
 | 
			
		||||
EXPORT_SYMBOL(nand_correct_data);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -2,8 +2,8 @@
 | 
			
		||||
 *  drivers/mtd/nandids.c
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de)
 | 
			
		||||
  *
 | 
			
		||||
 * $Id: nand_ids.c,v 1.10 2004/05/26 13:40:12 gleixner Exp $
 | 
			
		||||
 *
 | 
			
		||||
 * $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
 | 
			
		||||
@ -16,7 +16,6 @@
 | 
			
		||||
#if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
 | 
			
		||||
 | 
			
		||||
#include <linux/mtd/nand.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
*	Chip ID list
 | 
			
		||||
*
 | 
			
		||||
@ -29,13 +28,15 @@
 | 
			
		||||
*	512	512 Byte page size
 | 
			
		||||
*/
 | 
			
		||||
struct nand_flash_dev nand_flash_ids[] = {
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_MTD_NAND_MUSEUM_IDS
 | 
			
		||||
	{"NAND 1MiB 5V 8-bit",		0x6e, 256, 1, 0x1000, 0},
 | 
			
		||||
	{"NAND 2MiB 5V 8-bit",		0x64, 256, 2, 0x1000, 0},
 | 
			
		||||
	{"NAND 4MiB 5V 8-bit",		0x6b, 512, 4, 0x2000, 0},
 | 
			
		||||
	{"NAND 1MiB 3,3V 8-bit",	0xe8, 256, 1, 0x1000, 0},
 | 
			
		||||
	{"NAND 1MiB 3,3V 8-bit",	0xec, 256, 1, 0x1000, 0},
 | 
			
		||||
	{"NAND 2MiB 3,3V 8-bit",	0xea, 256, 2, 0x1000, 0},
 | 
			
		||||
	{"NAND 4MiB 3,3V 8-bit",	0xd5, 512, 4, 0x2000, 0},
 | 
			
		||||
	{"NAND 4MiB 3,3V 8-bit", 	0xd5, 512, 4, 0x2000, 0},
 | 
			
		||||
	{"NAND 4MiB 3,3V 8-bit",	0xe3, 512, 4, 0x2000, 0},
 | 
			
		||||
	{"NAND 4MiB 3,3V 8-bit",	0xe5, 512, 4, 0x2000, 0},
 | 
			
		||||
	{"NAND 8MiB 3,3V 8-bit",	0xd6, 512, 8, 0x2000, 0},
 | 
			
		||||
@ -44,6 +45,7 @@ struct nand_flash_dev nand_flash_ids[] = {
 | 
			
		||||
	{"NAND 8MiB 3,3V 8-bit",	0xe6, 512, 8, 0x2000, 0},
 | 
			
		||||
	{"NAND 8MiB 1,8V 16-bit",	0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16},
 | 
			
		||||
	{"NAND 8MiB 3,3V 16-bit",	0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16},
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	{"NAND 16MiB 1,8V 8-bit",	0x33, 512, 16, 0x4000, 0},
 | 
			
		||||
	{"NAND 16MiB 3,3V 8-bit",	0x73, 512, 16, 0x4000, 0},
 | 
			
		||||
@ -61,52 +63,72 @@ struct nand_flash_dev nand_flash_ids[] = {
 | 
			
		||||
	{"NAND 64MiB 3,3V 16-bit",	0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16},
 | 
			
		||||
 | 
			
		||||
	{"NAND 128MiB 1,8V 8-bit",	0x78, 512, 128, 0x4000, 0},
 | 
			
		||||
	{"NAND 128MiB 1,8V 8-bit",	0x39, 512, 128, 0x4000, 0},
 | 
			
		||||
	{"NAND 128MiB 3,3V 8-bit",	0x79, 512, 128, 0x4000, 0},
 | 
			
		||||
	{"NAND 128MiB 1,8V 16-bit",	0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16},
 | 
			
		||||
	{"NAND 128MiB 1,8V 16-bit",	0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16},
 | 
			
		||||
	{"NAND 128MiB 3,3V 16-bit",	0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16},
 | 
			
		||||
	{"NAND 128MiB 3,3V 16-bit",	0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16},
 | 
			
		||||
 | 
			
		||||
	{"NAND 256MiB 3,3V 8-bit",	0x71, 512, 256, 0x4000, 0},
 | 
			
		||||
 | 
			
		||||
	/* These are the new chips with large page size. The pagesize
 | 
			
		||||
	* and the erasesize is determined from the extended id bytes
 | 
			
		||||
	*/
 | 
			
		||||
	/*
 | 
			
		||||
	 * These are the new chips with large page size. The pagesize and the
 | 
			
		||||
	 * erasesize is determined from the extended id bytes
 | 
			
		||||
	 */
 | 
			
		||||
#define LP_OPTIONS (NAND_SAMSUNG_LP_OPTIONS | NAND_NO_READRDY | NAND_NO_AUTOINCR)
 | 
			
		||||
#define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16)
 | 
			
		||||
 | 
			
		||||
	/*512 Megabit */
 | 
			
		||||
	{"NAND 64MiB 1,8V 8-bit",	0xA2, 0,  64, 0, LP_OPTIONS},
 | 
			
		||||
	{"NAND 64MiB 3,3V 8-bit",	0xF2, 0,  64, 0, LP_OPTIONS},
 | 
			
		||||
	{"NAND 64MiB 1,8V 16-bit",	0xB2, 0,  64, 0, LP_OPTIONS16},
 | 
			
		||||
	{"NAND 64MiB 3,3V 16-bit",	0xC2, 0,  64, 0, LP_OPTIONS16},
 | 
			
		||||
 | 
			
		||||
	/* 1 Gigabit */
 | 
			
		||||
	{"NAND 128MiB 1,8V 8-bit",	0xA1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
 | 
			
		||||
	{"NAND 128MiB 3,3V 8-bit",	0xF1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
 | 
			
		||||
	{"NAND 128MiB 1,8V 16-bit",	0xB1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
 | 
			
		||||
	{"NAND 128MiB 3,3V 16-bit",	0xC1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
 | 
			
		||||
	{"NAND 128MiB 1,8V 8-bit",	0xA1, 0, 128, 0, LP_OPTIONS},
 | 
			
		||||
	{"NAND 128MiB 3,3V 8-bit",	0xF1, 0, 128, 0, LP_OPTIONS},
 | 
			
		||||
	{"NAND 128MiB 1,8V 16-bit",	0xB1, 0, 128, 0, LP_OPTIONS16},
 | 
			
		||||
	{"NAND 128MiB 3,3V 16-bit",	0xC1, 0, 128, 0, LP_OPTIONS16},
 | 
			
		||||
 | 
			
		||||
	/* 2 Gigabit */
 | 
			
		||||
	{"NAND 256MiB 1,8V 8-bit",	0xAA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
 | 
			
		||||
	{"NAND 256MiB 3,3V 8-bit",	0xDA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
 | 
			
		||||
	{"NAND 256MiB 1,8V 16-bit",	0xBA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
 | 
			
		||||
	{"NAND 256MiB 3,3V 16-bit",	0xCA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
 | 
			
		||||
	{"NAND 256MiB 1,8V 8-bit",	0xAA, 0, 256, 0, LP_OPTIONS},
 | 
			
		||||
	{"NAND 256MiB 3,3V 8-bit",	0xDA, 0, 256, 0, LP_OPTIONS},
 | 
			
		||||
	{"NAND 256MiB 1,8V 16-bit",	0xBA, 0, 256, 0, LP_OPTIONS16},
 | 
			
		||||
	{"NAND 256MiB 3,3V 16-bit",	0xCA, 0, 256, 0, LP_OPTIONS16},
 | 
			
		||||
 | 
			
		||||
	/* 4 Gigabit */
 | 
			
		||||
	{"NAND 512MiB 1,8V 8-bit",	0xAC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
 | 
			
		||||
	{"NAND 512MiB 3,3V 8-bit",	0xDC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
 | 
			
		||||
	{"NAND 512MiB 1,8V 16-bit",	0xBC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
 | 
			
		||||
	{"NAND 512MiB 3,3V 16-bit",	0xCC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
 | 
			
		||||
	{"NAND 512MiB 1,8V 8-bit",	0xAC, 0, 512, 0, LP_OPTIONS},
 | 
			
		||||
	{"NAND 512MiB 3,3V 8-bit",	0xDC, 0, 512, 0, LP_OPTIONS},
 | 
			
		||||
	{"NAND 512MiB 1,8V 16-bit",	0xBC, 0, 512, 0, LP_OPTIONS16},
 | 
			
		||||
	{"NAND 512MiB 3,3V 16-bit",	0xCC, 0, 512, 0, LP_OPTIONS16},
 | 
			
		||||
 | 
			
		||||
	/* 8 Gigabit */
 | 
			
		||||
	{"NAND 1GiB 1,8V 8-bit",	0xA3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
 | 
			
		||||
	{"NAND 1GiB 3,3V 8-bit",	0xD3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
 | 
			
		||||
	{"NAND 1GiB 1,8V 16-bit",	0xB3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
 | 
			
		||||
	{"NAND 1GiB 3,3V 16-bit",	0xC3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
 | 
			
		||||
	{"NAND 1GiB 1,8V 8-bit",	0xA3, 0, 1024, 0, LP_OPTIONS},
 | 
			
		||||
	{"NAND 1GiB 3,3V 8-bit",	0xD3, 0, 1024, 0, LP_OPTIONS},
 | 
			
		||||
	{"NAND 1GiB 1,8V 16-bit",	0xB3, 0, 1024, 0, LP_OPTIONS16},
 | 
			
		||||
	{"NAND 1GiB 3,3V 16-bit",	0xC3, 0, 1024, 0, LP_OPTIONS16},
 | 
			
		||||
 | 
			
		||||
	/* 16 Gigabit */
 | 
			
		||||
	{"NAND 2GiB 1,8V 8-bit",	0xA5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
 | 
			
		||||
	{"NAND 2GiB 3,3V 8-bit",	0xD5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
 | 
			
		||||
	{"NAND 2GiB 1,8V 16-bit",	0xB5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
 | 
			
		||||
	{"NAND 2GiB 3,3V 16-bit",	0xC5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
 | 
			
		||||
	{"NAND 2GiB 1,8V 8-bit",	0xA5, 0, 2048, 0, LP_OPTIONS},
 | 
			
		||||
	{"NAND 2GiB 3,3V 8-bit",	0xD5, 0, 2048, 0, LP_OPTIONS},
 | 
			
		||||
	{"NAND 2GiB 1,8V 16-bit",	0xB5, 0, 2048, 0, LP_OPTIONS16},
 | 
			
		||||
	{"NAND 2GiB 3,3V 16-bit",	0xC5, 0, 2048, 0, LP_OPTIONS16},
 | 
			
		||||
 | 
			
		||||
	/* Renesas AND 1 Gigabit. Those chips do not support extended id and have a strange page/block layout !
 | 
			
		||||
	 * The chosen minimum erasesize is 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page planes
 | 
			
		||||
	 * 1 block = 2 pages, but due to plane arrangement the blocks 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7
 | 
			
		||||
	 * Anyway JFFS2 would increase the eraseblock size so we chose a combined one which can be erased in one go
 | 
			
		||||
	 * There are more speed improvements for reads and writes possible, but not implemented now
 | 
			
		||||
	/*
 | 
			
		||||
	 * Renesas AND 1 Gigabit. Those chips do not support extended id and
 | 
			
		||||
	 * have a strange page/block layout !  The chosen minimum erasesize is
 | 
			
		||||
	 * 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page
 | 
			
		||||
	 * planes 1 block = 2 pages, but due to plane arrangement the blocks
 | 
			
		||||
	 * 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7 Anyway JFFS2 would
 | 
			
		||||
	 * increase the eraseblock size so we chose a combined one which can be
 | 
			
		||||
	 * erased in one go There are more speed improvements for reads and
 | 
			
		||||
	 * writes possible, but not implemented now
 | 
			
		||||
	 */
 | 
			
		||||
	{"AND 128MiB 3,3V 8-bit",	0x01, 2048, 128, 0x4000, NAND_IS_AND | NAND_NO_AUTOINCR | NAND_4PAGE_ARRAY},
 | 
			
		||||
	{"AND 128MiB 3,3V 8-bit",	0x01, 2048, 128, 0x4000,
 | 
			
		||||
	 NAND_IS_AND | NAND_NO_AUTOINCR |NAND_NO_READRDY | NAND_4PAGE_ARRAY |
 | 
			
		||||
	 BBT_AUTO_REFRESH
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	{NULL,}
 | 
			
		||||
};
 | 
			
		||||
@ -121,6 +143,7 @@ struct nand_manufacturers nand_manuf_ids[] = {
 | 
			
		||||
	{NAND_MFR_NATIONAL, "National"},
 | 
			
		||||
	{NAND_MFR_RENESAS, "Renesas"},
 | 
			
		||||
	{NAND_MFR_STMICRO, "ST Micro"},
 | 
			
		||||
	{NAND_MFR_HYNIX, "Hynix"},
 | 
			
		||||
	{NAND_MFR_MICRON, "Micron"},
 | 
			
		||||
	{0x0, "Unknown"}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -39,6 +39,9 @@
 | 
			
		||||
#include <malloc.h>
 | 
			
		||||
#include <div64.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <asm/errno.h>
 | 
			
		||||
#include <linux/mtd/mtd.h>
 | 
			
		||||
#include <nand.h>
 | 
			
		||||
#include <jffs2/jffs2.h>
 | 
			
		||||
 | 
			
		||||
@ -69,71 +72,33 @@ static int nand_block_bad_scrub(struct mtd_info *mtd, loff_t ofs, int getchip)
 | 
			
		||||
int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
 | 
			
		||||
{
 | 
			
		||||
	struct jffs2_unknown_node cleanmarker;
 | 
			
		||||
	int clmpos = 0;
 | 
			
		||||
	int clmlen = 8;
 | 
			
		||||
	erase_info_t erase;
 | 
			
		||||
	ulong erase_length;
 | 
			
		||||
	int isNAND;
 | 
			
		||||
	int bbtest = 1;
 | 
			
		||||
	int result;
 | 
			
		||||
	int percent_complete = -1;
 | 
			
		||||
	int (*nand_block_bad_old)(struct mtd_info *, loff_t, int) = NULL;
 | 
			
		||||
	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));
 | 
			
		||||
 | 
			
		||||
	erase.mtd = meminfo;
 | 
			
		||||
	erase.len  = meminfo->erasesize;
 | 
			
		||||
	erase.addr = opts->offset;
 | 
			
		||||
	erase_length = opts->length;
 | 
			
		||||
 | 
			
		||||
	isNAND = meminfo->type == MTD_NANDFLASH ? 1 : 0;
 | 
			
		||||
 | 
			
		||||
	if (opts->jffs2) {
 | 
			
		||||
		cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
 | 
			
		||||
		cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
 | 
			
		||||
		if (isNAND) {
 | 
			
		||||
			struct nand_oobinfo *oobinfo = &meminfo->oobinfo;
 | 
			
		||||
 | 
			
		||||
			/* check for autoplacement */
 | 
			
		||||
			if (oobinfo->useecc == MTD_NANDECC_AUTOPLACE) {
 | 
			
		||||
				/* get the position of the free bytes */
 | 
			
		||||
				if (!oobinfo->oobfree[0][1]) {
 | 
			
		||||
					printf(" Eeep. Autoplacement selected "
 | 
			
		||||
					       "and no empty space in oob\n");
 | 
			
		||||
					return -1;
 | 
			
		||||
				}
 | 
			
		||||
				clmpos = oobinfo->oobfree[0][0];
 | 
			
		||||
				clmlen = oobinfo->oobfree[0][1];
 | 
			
		||||
				if (clmlen > 8)
 | 
			
		||||
					clmlen = 8;
 | 
			
		||||
			} else {
 | 
			
		||||
				/* legacy mode */
 | 
			
		||||
				switch (meminfo->oobsize) {
 | 
			
		||||
				case 8:
 | 
			
		||||
					clmpos = 6;
 | 
			
		||||
					clmlen = 2;
 | 
			
		||||
					break;
 | 
			
		||||
				case 16:
 | 
			
		||||
					clmpos = 8;
 | 
			
		||||
					clmlen = 8;
 | 
			
		||||
					break;
 | 
			
		||||
				case 64:
 | 
			
		||||
					clmpos = 16;
 | 
			
		||||
					clmlen = 8;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			cleanmarker.totlen = cpu_to_je32(8);
 | 
			
		||||
		} else {
 | 
			
		||||
			cleanmarker.totlen =
 | 
			
		||||
				cpu_to_je32(sizeof(struct jffs2_unknown_node));
 | 
			
		||||
		}
 | 
			
		||||
		cleanmarker.hdr_crc =  cpu_to_je32(
 | 
			
		||||
			crc32_no_comp(0, (unsigned char *) &cleanmarker,
 | 
			
		||||
				      sizeof(struct jffs2_unknown_node) - 4));
 | 
			
		||||
	}
 | 
			
		||||
	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
 | 
			
		||||
@ -163,7 +128,7 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
 | 
			
		||||
	for (;
 | 
			
		||||
	     erase.addr < opts->offset + erase_length;
 | 
			
		||||
	     erase.addr += meminfo->erasesize) {
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
		WATCHDOG_RESET ();
 | 
			
		||||
 | 
			
		||||
		if (!opts->scrub && bbtest) {
 | 
			
		||||
@ -194,25 +159,21 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
 | 
			
		||||
		/* format for JFFS2 ? */
 | 
			
		||||
		if (opts->jffs2) {
 | 
			
		||||
 | 
			
		||||
			/* write cleanmarker */
 | 
			
		||||
			if (isNAND) {
 | 
			
		||||
				size_t written;
 | 
			
		||||
				result = meminfo->write_oob(meminfo,
 | 
			
		||||
							    erase.addr + clmpos,
 | 
			
		||||
							    clmlen,
 | 
			
		||||
							    &written,
 | 
			
		||||
							    (unsigned char *)
 | 
			
		||||
							    &cleanmarker);
 | 
			
		||||
				if (result != 0) {
 | 
			
		||||
					printf("\n%s: MTD writeoob failure: %d\n",
 | 
			
		||||
					       mtd_device, result);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				printf("\n%s: this erase routine only supports"
 | 
			
		||||
				       " NAND devices!\n",
 | 
			
		||||
				       mtd_device);
 | 
			
		||||
			chip->ops.len = chip->ops.ooblen = 64;
 | 
			
		||||
			chip->ops.datbuf = NULL;
 | 
			
		||||
			chip->ops.oobbuf = buf;
 | 
			
		||||
			chip->ops.ooboffs = chip->badblockpos & ~0x01;
 | 
			
		||||
			
 | 
			
		||||
			result = meminfo->write_oob(meminfo,
 | 
			
		||||
							erase.addr + meminfo->oobsize,
 | 
			
		||||
							&chip->ops);
 | 
			
		||||
			if (result != 0) {
 | 
			
		||||
				printf("\n%s: MTD writeoob failure: %d\n",
 | 
			
		||||
				mtd_device, result);
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
				printf("%s: MTD writeoob at 0x%08x\n",mtd_device, erase.addr + meminfo->oobsize );
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!opts->quiet) {
 | 
			
		||||
@ -232,11 +193,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);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -253,6 +214,9 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* XXX U-BOOT XXX */
 | 
			
		||||
#if 0
 | 
			
		||||
 | 
			
		||||
#define MAX_PAGE_SIZE	2048
 | 
			
		||||
#define MAX_OOB_SIZE	64
 | 
			
		||||
 | 
			
		||||
@ -263,26 +227,189 @@ static unsigned char data_buf[MAX_PAGE_SIZE];
 | 
			
		||||
static unsigned char oob_buf[MAX_OOB_SIZE];
 | 
			
		||||
 | 
			
		||||
/* OOB layouts to pass into the kernel as default */
 | 
			
		||||
static struct nand_oobinfo none_oobinfo = {
 | 
			
		||||
static struct nand_ecclayout none_ecclayout = {
 | 
			
		||||
	.useecc = MTD_NANDECC_OFF,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct nand_oobinfo jffs2_oobinfo = {
 | 
			
		||||
static struct nand_ecclayout jffs2_ecclayout = {
 | 
			
		||||
	.useecc = MTD_NANDECC_PLACE,
 | 
			
		||||
	.eccbytes = 6,
 | 
			
		||||
	.eccpos = { 0, 1, 2, 3, 6, 7 }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct nand_oobinfo yaffs_oobinfo = {
 | 
			
		||||
static struct nand_ecclayout yaffs_ecclayout = {
 | 
			
		||||
	.useecc = MTD_NANDECC_PLACE,
 | 
			
		||||
	.eccbytes = 6,
 | 
			
		||||
	.eccpos = { 8, 9, 10, 13, 14, 15}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct nand_oobinfo autoplace_oobinfo = {
 | 
			
		||||
static struct nand_ecclayout autoplace_ecclayout = {
 | 
			
		||||
	.useecc = MTD_NANDECC_AUTOPLACE
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * nand_fill_oob - [Internal] Transfer client buffer to oob
 | 
			
		||||
 * @chip:	nand chip structure
 | 
			
		||||
 * @oob:	oob data buffer
 | 
			
		||||
 * @ops:	oob ops structure
 | 
			
		||||
 * 
 | 
			
		||||
 * Copied from nand_base.c
 | 
			
		||||
 */
 | 
			
		||||
static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob,
 | 
			
		||||
				  struct mtd_oob_ops *ops)
 | 
			
		||||
{
 | 
			
		||||
	size_t len = ops->ooblen;
 | 
			
		||||
 | 
			
		||||
	switch(ops->mode) {
 | 
			
		||||
 | 
			
		||||
	case MTD_OOB_PLACE:
 | 
			
		||||
	case MTD_OOB_RAW:
 | 
			
		||||
		memcpy(chip->oob_poi + ops->ooboffs, oob, len);
 | 
			
		||||
		return oob + len;
 | 
			
		||||
 | 
			
		||||
	case MTD_OOB_AUTO: {
 | 
			
		||||
		struct nand_oobfree *free = chip->ecc.layout->oobfree;
 | 
			
		||||
		uint32_t boffs = 0, woffs = ops->ooboffs;
 | 
			
		||||
		size_t bytes = 0;
 | 
			
		||||
 | 
			
		||||
		for(; free->length && len; free++, len -= bytes) {
 | 
			
		||||
			/* Write request not from offset 0 ? */
 | 
			
		||||
			if (unlikely(woffs)) {
 | 
			
		||||
				if (woffs >= free->length) {
 | 
			
		||||
					woffs -= free->length;
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				boffs = free->offset + woffs;
 | 
			
		||||
				bytes = min_t(size_t, len,
 | 
			
		||||
					      (free->length - woffs));
 | 
			
		||||
				woffs = 0;
 | 
			
		||||
			} else {
 | 
			
		||||
				bytes = min_t(size_t, len, free->length);
 | 
			
		||||
				boffs = free->offset;
 | 
			
		||||
			}
 | 
			
		||||
			memcpy(chip->oob_poi + boffs, oob, bytes);
 | 
			
		||||
			oob += bytes;
 | 
			
		||||
		}
 | 
			
		||||
		return oob;
 | 
			
		||||
	}
 | 
			
		||||
	default:
 | 
			
		||||
		BUG();
 | 
			
		||||
	}
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define NOTALIGNED(x)	(x & (chip->subpagesize - 1)) != 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* copied from nand_base.c: nand_do_write_ops()
 | 
			
		||||
 * Only very small changes
 | 
			
		||||
 */
 | 
			
		||||
int nand_write_opts(nand_info_t *mtd, loff_t to, mtd_oob_ops_t *ops)
 | 
			
		||||
{
 | 
			
		||||
	int chipnr, realpage, page, blockmask, column;
 | 
			
		||||
	struct nand_chip *chip = mtd->priv;
 | 
			
		||||
	uint32_t writelen = ops->len;
 | 
			
		||||
	uint8_t *oob = ops->oobbuf;
 | 
			
		||||
	uint8_t *buf = ops->datbuf;
 | 
			
		||||
	int ret, subpage;
 | 
			
		||||
	
 | 
			
		||||
	ops->retlen = 0;
 | 
			
		||||
	if (!writelen)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	printk("nand_write_opts: to: 0x%08x, ops->len: 0x%08x\n", to, ops->len);
 | 
			
		||||
	
 | 
			
		||||
	/* reject writes, which are not page aligned */
 | 
			
		||||
	if (NOTALIGNED(to) || NOTALIGNED(ops->len)) {
 | 
			
		||||
		printk(KERN_NOTICE "nand_write: "
 | 
			
		||||
		       "Attempt to write not page aligned data\n");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	column = to & (mtd->writesize - 1);
 | 
			
		||||
	subpage = column || (writelen & (mtd->writesize - 1));
 | 
			
		||||
 | 
			
		||||
	if (subpage && oob) {
 | 
			
		||||
		printk(KERN_NOTICE "nand_write: "
 | 
			
		||||
		       "Attempt to write oob to subpage\n");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	chipnr = (int)(to >> chip->chip_shift);
 | 
			
		||||
	chip->select_chip(mtd, chipnr);
 | 
			
		||||
 | 
			
		||||
	/* XXX U-BOOT XXX */
 | 
			
		||||
#if 0
 | 
			
		||||
	/* Check, if it is write protected */
 | 
			
		||||
	if (nand_check_wp(mtd))
 | 
			
		||||
		return -EIO;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	realpage = (int)(to >> chip->page_shift);
 | 
			
		||||
	page = realpage & chip->pagemask;
 | 
			
		||||
	blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
 | 
			
		||||
 | 
			
		||||
	/* Invalidate the page cache, when we write to the cached page */
 | 
			
		||||
	if (to <= (chip->pagebuf << chip->page_shift) &&
 | 
			
		||||
	    (chip->pagebuf << chip->page_shift) < (to + ops->len))
 | 
			
		||||
		chip->pagebuf = -1;
 | 
			
		||||
 | 
			
		||||
	/* If we're not given explicit OOB data, let it be 0xFF */
 | 
			
		||||
	if (likely(!oob)) {
 | 
			
		||||
		printf("!oob, writing %d bytes with 0xff to chip->oob_poi (0x%08x)\n", mtd->oobsize, chip->oob_poi);
 | 
			
		||||
		memset(chip->oob_poi, 0xff, mtd->oobsize);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while(1) {
 | 
			
		||||
		int bytes = mtd->writesize;
 | 
			
		||||
		int cached = writelen > bytes && page != blockmask;
 | 
			
		||||
		uint8_t *wbuf = buf;
 | 
			
		||||
 | 
			
		||||
		/* Partial page write ? */
 | 
			
		||||
		if (unlikely(column || writelen < (mtd->writesize - 1))) {
 | 
			
		||||
			cached = 0;
 | 
			
		||||
			bytes = min_t(int, bytes - column, (int) writelen);
 | 
			
		||||
			chip->pagebuf = -1;
 | 
			
		||||
			memset(chip->buffers->databuf, 0xff, mtd->writesize);
 | 
			
		||||
			memcpy(&chip->buffers->databuf[column], buf, bytes);
 | 
			
		||||
			wbuf = chip->buffers->databuf;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (unlikely(oob))
 | 
			
		||||
			oob = nand_fill_oob(chip, oob, ops);
 | 
			
		||||
 | 
			
		||||
		ret = chip->write_page(mtd, chip, wbuf, page, cached,
 | 
			
		||||
				       (ops->mode == MTD_OOB_RAW));
 | 
			
		||||
		if (ret)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		writelen -= bytes;
 | 
			
		||||
		if (!writelen)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		column = 0;
 | 
			
		||||
		buf += bytes;
 | 
			
		||||
		realpage++;
 | 
			
		||||
 | 
			
		||||
		page = realpage & chip->pagemask;
 | 
			
		||||
		/* Check, if we cross a chip boundary */
 | 
			
		||||
		if (!page) {
 | 
			
		||||
			chipnr++;
 | 
			
		||||
			chip->select_chip(mtd, -1);
 | 
			
		||||
			chip->select_chip(mtd, chipnr);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ops->retlen = ops->len - writelen;
 | 
			
		||||
	if (unlikely(oob))
 | 
			
		||||
		ops->oobretlen = ops->ooblen;
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* XXX U-BOOT XXX */
 | 
			
		||||
#if 0
 | 
			
		||||
/**
 | 
			
		||||
 * nand_write_opts: - write image to NAND flash with support for various options
 | 
			
		||||
 *
 | 
			
		||||
@ -301,9 +428,9 @@ int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts)
 | 
			
		||||
	int blockstart = -1;
 | 
			
		||||
	loff_t offs;
 | 
			
		||||
	int readlen;
 | 
			
		||||
	int oobinfochanged = 0;
 | 
			
		||||
	int ecclayoutchanged = 0;
 | 
			
		||||
	int percent_complete = -1;
 | 
			
		||||
	struct nand_oobinfo old_oobinfo;
 | 
			
		||||
	struct nand_ecclayout old_ecclayout;
 | 
			
		||||
	ulong mtdoffset = opts->offset;
 | 
			
		||||
	ulong erasesize_blockalign;
 | 
			
		||||
	u_char *buffer = opts->buffer;
 | 
			
		||||
@ -324,35 +451,35 @@ int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* make sure device page sizes are valid */
 | 
			
		||||
	if (!(meminfo->oobsize == 16 && meminfo->oobblock == 512)
 | 
			
		||||
	    && !(meminfo->oobsize == 8 && meminfo->oobblock == 256)
 | 
			
		||||
	    && !(meminfo->oobsize == 64 && meminfo->oobblock == 2048)) {
 | 
			
		||||
	if (!(meminfo->oobsize == 16 && meminfo->writesize == 512)
 | 
			
		||||
	    && !(meminfo->oobsize == 8 && meminfo->writesize == 256)
 | 
			
		||||
	    && !(meminfo->oobsize == 64 && meminfo->writesize == 2048)) {
 | 
			
		||||
		printf("Unknown flash (not normal NAND)\n");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* read the current oob info */
 | 
			
		||||
	memcpy(&old_oobinfo, &meminfo->oobinfo, sizeof(old_oobinfo));
 | 
			
		||||
	memcpy(&old_ecclayout, &meminfo->ecclayout, sizeof(old_ecclayout));
 | 
			
		||||
 | 
			
		||||
	/* write without ecc? */
 | 
			
		||||
	if (opts->noecc) {
 | 
			
		||||
		memcpy(&meminfo->oobinfo, &none_oobinfo,
 | 
			
		||||
		       sizeof(meminfo->oobinfo));
 | 
			
		||||
		oobinfochanged = 1;
 | 
			
		||||
		memcpy(&meminfo->ecclayout, &none_ecclayout,
 | 
			
		||||
		       sizeof(meminfo->ecclayout));
 | 
			
		||||
		ecclayoutchanged = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* autoplace ECC? */
 | 
			
		||||
	if (opts->autoplace && (old_oobinfo.useecc != MTD_NANDECC_AUTOPLACE)) {
 | 
			
		||||
	if (opts->autoplace && (old_ecclayout.useecc != MTD_NANDECC_AUTOPLACE)) {
 | 
			
		||||
 | 
			
		||||
		memcpy(&meminfo->oobinfo, &autoplace_oobinfo,
 | 
			
		||||
		       sizeof(meminfo->oobinfo));
 | 
			
		||||
		oobinfochanged = 1;
 | 
			
		||||
		memcpy(&meminfo->ecclayout, &autoplace_ecclayout,
 | 
			
		||||
		       sizeof(meminfo->ecclayout));
 | 
			
		||||
		ecclayoutchanged = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* force OOB layout for jffs2 or yaffs? */
 | 
			
		||||
	if (opts->forcejffs2 || opts->forceyaffs) {
 | 
			
		||||
		struct nand_oobinfo *oobsel =
 | 
			
		||||
			opts->forcejffs2 ? &jffs2_oobinfo : &yaffs_oobinfo;
 | 
			
		||||
		struct nand_ecclayout *oobsel =
 | 
			
		||||
			opts->forcejffs2 ? &jffs2_ecclayout : &yaffs_ecclayout;
 | 
			
		||||
 | 
			
		||||
		if (meminfo->oobsize == 8) {
 | 
			
		||||
			if (opts->forceyaffs) {
 | 
			
		||||
@ -361,15 +488,15 @@ int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts)
 | 
			
		||||
				goto restoreoob;
 | 
			
		||||
			}
 | 
			
		||||
			/* Adjust number of ecc bytes */
 | 
			
		||||
			jffs2_oobinfo.eccbytes = 3;
 | 
			
		||||
			jffs2_ecclayout.eccbytes = 3;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		memcpy(&meminfo->oobinfo, oobsel, sizeof(meminfo->oobinfo));
 | 
			
		||||
		memcpy(&meminfo->ecclayout, oobsel, sizeof(meminfo->ecclayout));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* get image length */
 | 
			
		||||
	imglen = opts->length;
 | 
			
		||||
	pagelen = meminfo->oobblock
 | 
			
		||||
	pagelen = meminfo->writesize
 | 
			
		||||
		+ ((opts->writeoob != 0) ? meminfo->oobsize : 0);
 | 
			
		||||
 | 
			
		||||
	/* check, if file is pagealigned */
 | 
			
		||||
@ -379,11 +506,11 @@ int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* check, if length fits into device */
 | 
			
		||||
	if (((imglen / pagelen) * meminfo->oobblock)
 | 
			
		||||
	if (((imglen / pagelen) * meminfo->writesize)
 | 
			
		||||
	     > (meminfo->size - opts->offset)) {
 | 
			
		||||
		printf("Image %d bytes, NAND page %d bytes, "
 | 
			
		||||
		       "OOB area %u bytes, device size %u bytes\n",
 | 
			
		||||
		       imglen, pagelen, meminfo->oobblock, meminfo->size);
 | 
			
		||||
		       imglen, pagelen, meminfo->writesize, meminfo->size);
 | 
			
		||||
		printf("Input block does not fit into device\n");
 | 
			
		||||
		goto restoreoob;
 | 
			
		||||
	}
 | 
			
		||||
@ -437,11 +564,11 @@ int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts)
 | 
			
		||||
			} while (offs < blockstart + erasesize_blockalign);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		readlen = meminfo->oobblock;
 | 
			
		||||
		readlen = meminfo->writesize;
 | 
			
		||||
		if (opts->pad && (imglen < readlen)) {
 | 
			
		||||
			readlen = imglen;
 | 
			
		||||
			memset(data_buf + readlen, 0xff,
 | 
			
		||||
			       meminfo->oobblock - readlen);
 | 
			
		||||
			       meminfo->writesize - readlen);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* read page data from input memory buffer */
 | 
			
		||||
@ -474,7 +601,7 @@ int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts)
 | 
			
		||||
		/* write out the page data */
 | 
			
		||||
		result = meminfo->write(meminfo,
 | 
			
		||||
					mtdoffset,
 | 
			
		||||
					meminfo->oobblock,
 | 
			
		||||
					meminfo->writesize,
 | 
			
		||||
					&written,
 | 
			
		||||
					(unsigned char *) &data_buf);
 | 
			
		||||
 | 
			
		||||
@ -505,16 +632,16 @@ int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		mtdoffset += meminfo->oobblock;
 | 
			
		||||
		mtdoffset += meminfo->writesize;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!opts->quiet)
 | 
			
		||||
		printf("\n");
 | 
			
		||||
 | 
			
		||||
restoreoob:
 | 
			
		||||
	if (oobinfochanged) {
 | 
			
		||||
		memcpy(&meminfo->oobinfo, &old_oobinfo,
 | 
			
		||||
		       sizeof(meminfo->oobinfo));
 | 
			
		||||
	if (ecclayoutchanged) {
 | 
			
		||||
		memcpy(&meminfo->ecclayout, &old_ecclayout,
 | 
			
		||||
		       sizeof(meminfo->ecclayout));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (imglen > 0) {
 | 
			
		||||
@ -548,22 +675,22 @@ int nand_read_opts(nand_info_t *meminfo, const nand_read_options_t *opts)
 | 
			
		||||
	int result;
 | 
			
		||||
 | 
			
		||||
	/* make sure device page sizes are valid */
 | 
			
		||||
	if (!(meminfo->oobsize == 16 && meminfo->oobblock == 512)
 | 
			
		||||
	    && !(meminfo->oobsize == 8 && meminfo->oobblock == 256)
 | 
			
		||||
	    && !(meminfo->oobsize == 64 && meminfo->oobblock == 2048)) {
 | 
			
		||||
	if (!(meminfo->oobsize == 16 && meminfo->writesize == 512)
 | 
			
		||||
	    && !(meminfo->oobsize == 8 && meminfo->writesize == 256)
 | 
			
		||||
	    && !(meminfo->oobsize == 64 && meminfo->writesize == 2048)) {
 | 
			
		||||
		printf("Unknown flash (not normal NAND)\n");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pagelen = meminfo->oobblock
 | 
			
		||||
	pagelen = meminfo->writesize
 | 
			
		||||
		+ ((opts->readoob != 0) ? meminfo->oobsize : 0);
 | 
			
		||||
 | 
			
		||||
	/* check, if length is not larger than device */
 | 
			
		||||
	if (((imglen / pagelen) * meminfo->oobblock)
 | 
			
		||||
	if (((imglen / pagelen) * meminfo->writesize)
 | 
			
		||||
	     > (meminfo->size - opts->offset)) {
 | 
			
		||||
		printf("Image %d bytes, NAND page %d bytes, "
 | 
			
		||||
		       "OOB area %u bytes, device size %u bytes\n",
 | 
			
		||||
		       imglen, pagelen, meminfo->oobblock, meminfo->size);
 | 
			
		||||
		       imglen, pagelen, meminfo->writesize, meminfo->size);
 | 
			
		||||
		printf("Input block is larger than device\n");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
@ -621,7 +748,7 @@ int nand_read_opts(nand_info_t *meminfo, const nand_read_options_t *opts)
 | 
			
		||||
		/* read page data to memory buffer */
 | 
			
		||||
		result = meminfo->read(meminfo,
 | 
			
		||||
				       mtdoffset,
 | 
			
		||||
				       meminfo->oobblock,
 | 
			
		||||
				       meminfo->writesize,
 | 
			
		||||
				       &readlen,
 | 
			
		||||
				       (unsigned char *) &data_buf);
 | 
			
		||||
 | 
			
		||||
@ -685,7 +812,7 @@ int nand_read_opts(nand_info_t *meminfo, const nand_read_options_t *opts)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		mtdoffset += meminfo->oobblock;
 | 
			
		||||
		mtdoffset += meminfo->writesize;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!opts->quiet)
 | 
			
		||||
@ -699,7 +826,10 @@ int nand_read_opts(nand_info_t *meminfo, const nand_read_options_t *opts)
 | 
			
		||||
	/* return happy */
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* XXX U-BOOT XXX */
 | 
			
		||||
#if 0
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 * Support for locking / unlocking operations of some NAND devices
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
@ -784,7 +914,7 @@ int nand_get_lock_status(nand_info_t *meminfo, ulong offset)
 | 
			
		||||
	this->select_chip(meminfo, chipnr);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	if ((offset & (meminfo->oobblock - 1)) != 0) {
 | 
			
		||||
	if ((offset & (meminfo->writesize - 1)) != 0) {
 | 
			
		||||
		printf ("nand_get_lock_status: "
 | 
			
		||||
			"Start address must be beginning of "
 | 
			
		||||
			"nand page!\n");
 | 
			
		||||
@ -813,7 +943,7 @@ int nand_get_lock_status(nand_info_t *meminfo, ulong offset)
 | 
			
		||||
 * @param meminfo	nand mtd instance
 | 
			
		||||
 * @param start		start byte address
 | 
			
		||||
 * @param length	number of bytes to unlock (must be a multiple of
 | 
			
		||||
 *			page size nand->oobblock)
 | 
			
		||||
 *			page size nand->writesize)
 | 
			
		||||
 *
 | 
			
		||||
 * @return		0 on success, -1 in case of error
 | 
			
		||||
 */
 | 
			
		||||
@ -839,14 +969,14 @@ int nand_unlock(nand_info_t *meminfo, ulong start, ulong length)
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((start & (meminfo->oobblock - 1)) != 0) {
 | 
			
		||||
	if ((start & (meminfo->writesize - 1)) != 0) {
 | 
			
		||||
		printf ("nand_unlock: Start address must be beginning of "
 | 
			
		||||
			"nand page!\n");
 | 
			
		||||
		ret = -1;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (length == 0 || (length & (meminfo->oobblock - 1)) != 0) {
 | 
			
		||||
	if (length == 0 || (length & (meminfo->writesize - 1)) != 0) {
 | 
			
		||||
		printf ("nand_unlock: Length must be a multiple of nand page "
 | 
			
		||||
			"size!\n");
 | 
			
		||||
		ret = -1;
 | 
			
		||||
@ -875,5 +1005,6 @@ int nand_unlock(nand_info_t *meminfo, ulong start, ulong length)
 | 
			
		||||
	this->select_chip(meminfo, -1);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -119,11 +119,13 @@ typedef volatile unsigned char	vu_char;
 | 
			
		||||
#define debugX(level,fmt,args...)
 | 
			
		||||
#endif	/* DEBUG */
 | 
			
		||||
 | 
			
		||||
#ifndef BUG
 | 
			
		||||
#define BUG() do { \
 | 
			
		||||
	printf("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __FUNCTION__); \
 | 
			
		||||
	panic("BUG!"); \
 | 
			
		||||
} while (0)
 | 
			
		||||
#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
 | 
			
		||||
#endif /* BUG */
 | 
			
		||||
 | 
			
		||||
typedef void (interrupt_handler_t)(void *);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										45
									
								
								include/linux/err.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								include/linux/err.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
			
		||||
#ifndef _LINUX_ERR_H
 | 
			
		||||
#define _LINUX_ERR_H
 | 
			
		||||
 | 
			
		||||
/* XXX U-BOOT XXX */
 | 
			
		||||
#if 0
 | 
			
		||||
#include <linux/compiler.h>
 | 
			
		||||
#else
 | 
			
		||||
#include <linux/mtd/compat.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <asm/errno.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Kernel pointers have redundant information, so we can use a
 | 
			
		||||
 * scheme where we can return either an error code or a dentry
 | 
			
		||||
 * pointer with the same return value.
 | 
			
		||||
 *
 | 
			
		||||
 * This should be a per-architecture thing, to allow different
 | 
			
		||||
 * error and pointer decisions.
 | 
			
		||||
 */
 | 
			
		||||
#define MAX_ERRNO	4095
 | 
			
		||||
 | 
			
		||||
#ifndef __ASSEMBLY__
 | 
			
		||||
 | 
			
		||||
#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)
 | 
			
		||||
 | 
			
		||||
static inline void *ERR_PTR(long error)
 | 
			
		||||
{
 | 
			
		||||
	return (void *) error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline long PTR_ERR(const void *ptr)
 | 
			
		||||
{
 | 
			
		||||
	return (long) ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline long IS_ERR(const void *ptr)
 | 
			
		||||
{
 | 
			
		||||
	return IS_ERR_VALUE((unsigned long)ptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* _LINUX_ERR_H */
 | 
			
		||||
							
								
								
									
										81
									
								
								include/linux/mtd/blktrans.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								include/linux/mtd/blktrans.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,81 @@
 | 
			
		||||
/*
 | 
			
		||||
 * $Id: blktrans.h,v 1.6 2005/11/07 11:14:54 gleixner Exp $
 | 
			
		||||
 *
 | 
			
		||||
 * (C) 2003 David Woodhouse <dwmw2@infradead.org>
 | 
			
		||||
 *
 | 
			
		||||
 * Interface to Linux block layer for MTD 'translation layers'.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __MTD_TRANS_H__
 | 
			
		||||
#define __MTD_TRANS_H__
 | 
			
		||||
 | 
			
		||||
/* XXX U-BOOT XXX */
 | 
			
		||||
#if 0
 | 
			
		||||
#include <linux/mutex.h>
 | 
			
		||||
#else
 | 
			
		||||
#include <linux/list.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct hd_geometry;
 | 
			
		||||
struct mtd_info;
 | 
			
		||||
struct mtd_blktrans_ops;
 | 
			
		||||
struct file;
 | 
			
		||||
struct inode;
 | 
			
		||||
 | 
			
		||||
struct mtd_blktrans_dev {
 | 
			
		||||
	struct mtd_blktrans_ops *tr;
 | 
			
		||||
	struct list_head list;
 | 
			
		||||
	struct mtd_info *mtd;
 | 
			
		||||
/* XXX U-BOOT XXX */
 | 
			
		||||
#if 0
 | 
			
		||||
	struct mutex lock;
 | 
			
		||||
#endif
 | 
			
		||||
	int devnum;
 | 
			
		||||
	unsigned long size;
 | 
			
		||||
	int readonly;
 | 
			
		||||
	void *blkcore_priv; /* gendisk in 2.5, devfs_handle in 2.4 */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct blkcore_priv; /* Differs for 2.4 and 2.5 kernels; private */
 | 
			
		||||
 | 
			
		||||
struct mtd_blktrans_ops {
 | 
			
		||||
	char *name;
 | 
			
		||||
	int major;
 | 
			
		||||
	int part_bits;
 | 
			
		||||
	int blksize;
 | 
			
		||||
	int blkshift;
 | 
			
		||||
 | 
			
		||||
	/* Access functions */
 | 
			
		||||
	int (*readsect)(struct mtd_blktrans_dev *dev,
 | 
			
		||||
		    unsigned long block, char *buffer);
 | 
			
		||||
	int (*writesect)(struct mtd_blktrans_dev *dev,
 | 
			
		||||
		     unsigned long block, char *buffer);
 | 
			
		||||
 | 
			
		||||
	/* Block layer ioctls */
 | 
			
		||||
	int (*getgeo)(struct mtd_blktrans_dev *dev, struct hd_geometry *geo);
 | 
			
		||||
	int (*flush)(struct mtd_blktrans_dev *dev);
 | 
			
		||||
 | 
			
		||||
	/* Called with mtd_table_mutex held; no race with add/remove */
 | 
			
		||||
	int (*open)(struct mtd_blktrans_dev *dev);
 | 
			
		||||
	int (*release)(struct mtd_blktrans_dev *dev);
 | 
			
		||||
 | 
			
		||||
	/* Called on {de,}registration and on subsequent addition/removal
 | 
			
		||||
	   of devices, with mtd_table_mutex held. */
 | 
			
		||||
	void (*add_mtd)(struct mtd_blktrans_ops *tr, struct mtd_info *mtd);
 | 
			
		||||
	void (*remove_dev)(struct mtd_blktrans_dev *dev);
 | 
			
		||||
 | 
			
		||||
	struct list_head devs;
 | 
			
		||||
	struct list_head list;
 | 
			
		||||
	struct module *owner;
 | 
			
		||||
 | 
			
		||||
	struct mtd_blkcore_priv *blkcore_priv;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern int register_mtd_blktrans(struct mtd_blktrans_ops *tr);
 | 
			
		||||
extern int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr);
 | 
			
		||||
extern int add_mtd_blktrans_dev(struct mtd_blktrans_dev *dev);
 | 
			
		||||
extern int del_mtd_blktrans_dev(struct mtd_blktrans_dev *dev);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* __MTD_TRANS_H__ */
 | 
			
		||||
@ -18,7 +18,12 @@
 | 
			
		||||
#define KERN_DEBUG
 | 
			
		||||
 | 
			
		||||
#define kmalloc(size, flags)	malloc(size)
 | 
			
		||||
#define kfree(ptr)		free(ptr)
 | 
			
		||||
#define kzalloc(size, flags)    calloc(size, 1)
 | 
			
		||||
#define vmalloc(size)			malloc(size)
 | 
			
		||||
#define kfree(ptr)		        free(ptr)
 | 
			
		||||
#define vfree(ptr)              free(ptr)
 | 
			
		||||
 | 
			
		||||
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * ..and if you can't take the strict
 | 
			
		||||
 | 
			
		||||
@ -1,15 +1,23 @@
 | 
			
		||||
 | 
			
		||||
/* Linux driver for Disk-On-Chip 2000       */
 | 
			
		||||
/* (c) 1999 Machine Vision Holdings, Inc.   */
 | 
			
		||||
/* Author: David Woodhouse <dwmw2@mvhi.com> */
 | 
			
		||||
/* $Id: doc2000.h,v 1.15 2001/09/19 00:22:15 dwmw2 Exp $ */
 | 
			
		||||
/*
 | 
			
		||||
 * Linux driver for Disk-On-Chip devices
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 1999 Machine Vision Holdings, Inc.
 | 
			
		||||
 * Copyright (C) 2001-2003 David Woodhouse <dwmw2@infradead.org>
 | 
			
		||||
 * Copyright (C) 2002-2003 Greg Ungerer <gerg@snapgear.com>
 | 
			
		||||
 * Copyright (C) 2002-2003 SnapGear Inc
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: doc2000.h,v 1.25 2005/11/07 11:14:54 gleixner Exp $
 | 
			
		||||
 *
 | 
			
		||||
 * Released under GPL
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __MTD_DOC2000_H__
 | 
			
		||||
#define __MTD_DOC2000_H__
 | 
			
		||||
 | 
			
		||||
struct DiskOnChip;
 | 
			
		||||
 | 
			
		||||
#include <linux/mtd/nftl.h>
 | 
			
		||||
#include <linux/mtd/mtd.h>
 | 
			
		||||
#if 0
 | 
			
		||||
#include <linux/mutex.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define DoC_Sig1 0
 | 
			
		||||
#define DoC_Sig2 1
 | 
			
		||||
@ -40,10 +48,58 @@ struct DiskOnChip;
 | 
			
		||||
#define DoC_Mil_CDSN_IO		0x0800
 | 
			
		||||
#define DoC_2k_CDSN_IO		0x1800
 | 
			
		||||
 | 
			
		||||
#define ReadDOC_(adr, reg)      ((volatile unsigned char)(*(volatile __u8 *)(((unsigned long)adr)+((reg)))))
 | 
			
		||||
#define WriteDOC_(d, adr, reg)  do{ *(volatile __u8 *)(((unsigned long)adr)+((reg))) = (__u8)d; eieio();} while(0)
 | 
			
		||||
#define DoC_Mplus_NOP			0x1002
 | 
			
		||||
#define DoC_Mplus_AliasResolution	0x1004
 | 
			
		||||
#define DoC_Mplus_DOCControl		0x1006
 | 
			
		||||
#define DoC_Mplus_AccessStatus		0x1008
 | 
			
		||||
#define DoC_Mplus_DeviceSelect		0x1008
 | 
			
		||||
#define DoC_Mplus_Configuration		0x100a
 | 
			
		||||
#define DoC_Mplus_OutputControl		0x100c
 | 
			
		||||
#define DoC_Mplus_FlashControl		0x1020
 | 
			
		||||
#define DoC_Mplus_FlashSelect 		0x1022
 | 
			
		||||
#define DoC_Mplus_FlashCmd		0x1024
 | 
			
		||||
#define DoC_Mplus_FlashAddress		0x1026
 | 
			
		||||
#define DoC_Mplus_FlashData0		0x1028
 | 
			
		||||
#define DoC_Mplus_FlashData1		0x1029
 | 
			
		||||
#define DoC_Mplus_ReadPipeInit		0x102a
 | 
			
		||||
#define DoC_Mplus_LastDataRead		0x102c
 | 
			
		||||
#define DoC_Mplus_LastDataRead1		0x102d
 | 
			
		||||
#define DoC_Mplus_WritePipeTerm 	0x102e
 | 
			
		||||
#define DoC_Mplus_ECCSyndrome0		0x1040
 | 
			
		||||
#define DoC_Mplus_ECCSyndrome1		0x1041
 | 
			
		||||
#define DoC_Mplus_ECCSyndrome2		0x1042
 | 
			
		||||
#define DoC_Mplus_ECCSyndrome3		0x1043
 | 
			
		||||
#define DoC_Mplus_ECCSyndrome4		0x1044
 | 
			
		||||
#define DoC_Mplus_ECCSyndrome5		0x1045
 | 
			
		||||
#define DoC_Mplus_ECCConf 		0x1046
 | 
			
		||||
#define DoC_Mplus_Toggle		0x1046
 | 
			
		||||
#define DoC_Mplus_DownloadStatus	0x1074
 | 
			
		||||
#define DoC_Mplus_CtrlConfirm		0x1076
 | 
			
		||||
#define DoC_Mplus_Power			0x1fff
 | 
			
		||||
 | 
			
		||||
#define DOC_IOREMAP_LEN		0x4000
 | 
			
		||||
/* How to access the device?
 | 
			
		||||
 * On ARM, it'll be mmap'd directly with 32-bit wide accesses.
 | 
			
		||||
 * On PPC, it's mmap'd and 16-bit wide.
 | 
			
		||||
 * Others use readb/writeb
 | 
			
		||||
 */
 | 
			
		||||
#if defined(__arm__)
 | 
			
		||||
#define ReadDOC_(adr, reg)      ((unsigned char)(*(volatile __u32 *)(((unsigned long)adr)+((reg)<<2))))
 | 
			
		||||
#define WriteDOC_(d, adr, reg)  do{ *(volatile __u32 *)(((unsigned long)adr)+((reg)<<2)) = (__u32)d; wmb();} while(0)
 | 
			
		||||
#define DOC_IOREMAP_LEN 0x8000
 | 
			
		||||
#elif defined(__ppc__)
 | 
			
		||||
#define ReadDOC_(adr, reg)      ((unsigned char)(*(volatile __u16 *)(((unsigned long)adr)+((reg)<<1))))
 | 
			
		||||
#define WriteDOC_(d, adr, reg)  do{ *(volatile __u16 *)(((unsigned long)adr)+((reg)<<1)) = (__u16)d; wmb();} while(0)
 | 
			
		||||
#define DOC_IOREMAP_LEN 0x4000
 | 
			
		||||
#else
 | 
			
		||||
#define ReadDOC_(adr, reg)      readb((void __iomem *)(adr) + (reg))
 | 
			
		||||
#define WriteDOC_(d, adr, reg)  writeb(d, (void __iomem *)(adr) + (reg))
 | 
			
		||||
#define DOC_IOREMAP_LEN 0x2000
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__i386__) || defined(__x86_64__)
 | 
			
		||||
#define USE_MEMCPY
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* These are provided to directly use the DoC_xxx defines */
 | 
			
		||||
#define ReadDOC(adr, reg)      ReadDOC_(adr,DoC_##reg)
 | 
			
		||||
@ -54,14 +110,21 @@ struct DiskOnChip;
 | 
			
		||||
#define DOC_MODE_RESERVED1	2
 | 
			
		||||
#define DOC_MODE_RESERVED2	3
 | 
			
		||||
 | 
			
		||||
#define DOC_MODE_MDWREN		4
 | 
			
		||||
#define DOC_MODE_CLR_ERR	0x80
 | 
			
		||||
#define	DOC_MODE_RST_LAT	0x10
 | 
			
		||||
#define	DOC_MODE_BDECT		0x08
 | 
			
		||||
#define DOC_MODE_MDWREN	0x04
 | 
			
		||||
 | 
			
		||||
#define DOC_ChipID_UNKNOWN	0x00
 | 
			
		||||
#define DOC_ChipID_Doc2k	0x20
 | 
			
		||||
#define DOC_ChipID_Doc2kTSOP	0x21	/* internal number for MTD */
 | 
			
		||||
#define DOC_ChipID_DocMil	0x30
 | 
			
		||||
#define DOC_ChipID_DocMilPlus32	0x40
 | 
			
		||||
#define DOC_ChipID_DocMilPlus16	0x41
 | 
			
		||||
 | 
			
		||||
#define CDSN_CTRL_FR_B		0x80
 | 
			
		||||
#define CDSN_CTRL_FR_B0		0x40
 | 
			
		||||
#define CDSN_CTRL_FR_B1		0x80
 | 
			
		||||
 | 
			
		||||
#define CDSN_CTRL_ECC_IO	0x20
 | 
			
		||||
#define CDSN_CTRL_FLASH_IO	0x10
 | 
			
		||||
#define CDSN_CTRL_WP		0x08
 | 
			
		||||
@ -77,20 +140,14 @@ struct DiskOnChip;
 | 
			
		||||
#define DOC_ECC_RESV		0x02
 | 
			
		||||
#define DOC_ECC_IGNORE		0x01
 | 
			
		||||
 | 
			
		||||
#define DOC_FLASH_CE		0x80
 | 
			
		||||
#define DOC_FLASH_WP		0x40
 | 
			
		||||
#define DOC_FLASH_BANK		0x02
 | 
			
		||||
 | 
			
		||||
/* We have to also set the reserved bit 1 for enable */
 | 
			
		||||
#define DOC_ECC_EN (DOC_ECC__EN | DOC_ECC_RESV)
 | 
			
		||||
#define DOC_ECC_DIS (DOC_ECC_RESV)
 | 
			
		||||
 | 
			
		||||
#define MAX_FLOORS 4
 | 
			
		||||
#define MAX_CHIPS 4
 | 
			
		||||
 | 
			
		||||
#define MAX_FLOORS_MIL 4
 | 
			
		||||
#define MAX_CHIPS_MIL 1
 | 
			
		||||
 | 
			
		||||
#define ADDR_COLUMN 1
 | 
			
		||||
#define ADDR_PAGE 2
 | 
			
		||||
#define ADDR_COLUMN_PAGE 3
 | 
			
		||||
 | 
			
		||||
struct Nand {
 | 
			
		||||
	char floor, chip;
 | 
			
		||||
	unsigned long curadr;
 | 
			
		||||
@ -98,20 +155,32 @@ struct Nand {
 | 
			
		||||
	/* Also some erase/write/pipeline info when we get that far */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define MAX_FLOORS 4
 | 
			
		||||
#define MAX_CHIPS 4
 | 
			
		||||
 | 
			
		||||
#define MAX_FLOORS_MIL 1
 | 
			
		||||
#define MAX_CHIPS_MIL 1
 | 
			
		||||
 | 
			
		||||
#define MAX_FLOORS_MPLUS 2
 | 
			
		||||
#define MAX_CHIPS_MPLUS 1
 | 
			
		||||
 | 
			
		||||
#define ADDR_COLUMN 1
 | 
			
		||||
#define ADDR_PAGE 2
 | 
			
		||||
#define ADDR_COLUMN_PAGE 3
 | 
			
		||||
 | 
			
		||||
struct DiskOnChip {
 | 
			
		||||
	unsigned long physadr;
 | 
			
		||||
	unsigned long virtadr;
 | 
			
		||||
	void __iomem *virtadr;
 | 
			
		||||
	unsigned long totlen;
 | 
			
		||||
	char* name;
 | 
			
		||||
	char ChipID; /* Type of DiskOnChip */
 | 
			
		||||
	unsigned char ChipID; /* Type of DiskOnChip */
 | 
			
		||||
	int ioreg;
 | 
			
		||||
 | 
			
		||||
	char* chips_name;
 | 
			
		||||
	unsigned long mfr; /* Flash IDs - only one type of flash per device */
 | 
			
		||||
	unsigned long id;
 | 
			
		||||
	int chipshift;
 | 
			
		||||
	char page256;
 | 
			
		||||
	char pageadrlen;
 | 
			
		||||
	char interleave; /* Internal interleaving - Millennium Plus style */
 | 
			
		||||
	unsigned long erasesize;
 | 
			
		||||
 | 
			
		||||
	int curfloor;
 | 
			
		||||
@ -119,98 +188,22 @@ struct DiskOnChip {
 | 
			
		||||
 | 
			
		||||
	int numchips;
 | 
			
		||||
	struct Nand *chips;
 | 
			
		||||
 | 
			
		||||
	int nftl_found;
 | 
			
		||||
	struct NFTLrecord nftl;
 | 
			
		||||
	struct mtd_info *nextdoc;
 | 
			
		||||
/* XXX U-BOOT XXX */
 | 
			
		||||
#if 0
 | 
			
		||||
	struct mutex lock;
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define SECTORSIZE 512
 | 
			
		||||
 | 
			
		||||
/* Return codes from doc_write(), doc_read(), and doc_erase().
 | 
			
		||||
 */
 | 
			
		||||
#define DOC_OK		0
 | 
			
		||||
#define DOC_EIO		1
 | 
			
		||||
#define DOC_EINVAL	2
 | 
			
		||||
#define DOC_EECC	3
 | 
			
		||||
#define DOC_ETIMEOUT	4
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Function Prototypes
 | 
			
		||||
 */
 | 
			
		||||
int doc_decode_ecc(unsigned char sector[512], unsigned char ecc1[6]);
 | 
			
		||||
 | 
			
		||||
int doc_rw(struct DiskOnChip* this, int cmd, loff_t from, size_t len,
 | 
			
		||||
	   size_t *retlen, u_char *buf);
 | 
			
		||||
int doc_read_ecc(struct DiskOnChip* this, loff_t from, size_t len,
 | 
			
		||||
		 size_t *retlen, u_char *buf, u_char *eccbuf);
 | 
			
		||||
int doc_write_ecc(struct DiskOnChip* this, loff_t to, size_t len,
 | 
			
		||||
		  size_t *retlen, const u_char *buf, u_char *eccbuf);
 | 
			
		||||
int doc_read_oob(struct DiskOnChip* this, loff_t ofs, size_t len,
 | 
			
		||||
		 size_t *retlen, u_char *buf);
 | 
			
		||||
int doc_write_oob(struct DiskOnChip* this, loff_t ofs, size_t len,
 | 
			
		||||
		  size_t *retlen, const u_char *buf);
 | 
			
		||||
int doc_erase (struct DiskOnChip* this, loff_t ofs, size_t len);
 | 
			
		||||
 | 
			
		||||
void doc_probe(unsigned long physadr);
 | 
			
		||||
 | 
			
		||||
void doc_print(struct DiskOnChip*);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Standard NAND flash commands
 | 
			
		||||
 */
 | 
			
		||||
#define NAND_CMD_READ0		0
 | 
			
		||||
#define NAND_CMD_READ1		1
 | 
			
		||||
#define NAND_CMD_PAGEPROG	0x10
 | 
			
		||||
#define NAND_CMD_READOOB	0x50
 | 
			
		||||
#define NAND_CMD_ERASE1		0x60
 | 
			
		||||
#define NAND_CMD_STATUS		0x70
 | 
			
		||||
#define NAND_CMD_SEQIN		0x80
 | 
			
		||||
#define NAND_CMD_READID		0x90
 | 
			
		||||
#define NAND_CMD_ERASE2		0xd0
 | 
			
		||||
#define NAND_CMD_RESET		0xff
 | 
			
		||||
 | 
			
		||||
/* XXX U-BOOT XXX */
 | 
			
		||||
#if 1
 | 
			
		||||
/*
 | 
			
		||||
 * NAND Flash Manufacturer ID Codes
 | 
			
		||||
 */
 | 
			
		||||
#define NAND_MFR_TOSHIBA	0x98
 | 
			
		||||
#define NAND_MFR_SAMSUNG	0xec
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * NAND Flash Device ID Structure
 | 
			
		||||
 *
 | 
			
		||||
 * Structure overview:
 | 
			
		||||
 *
 | 
			
		||||
 *  name - Complete name of device
 | 
			
		||||
 *
 | 
			
		||||
 *  manufacture_id - manufacturer ID code of device.
 | 
			
		||||
 *
 | 
			
		||||
 *  model_id - model ID code of device.
 | 
			
		||||
 *
 | 
			
		||||
 *  chipshift - total number of address bits for the device which
 | 
			
		||||
 *              is used to calculate address offsets and the total
 | 
			
		||||
 *              number of bytes the device is capable of.
 | 
			
		||||
 *
 | 
			
		||||
 *  page256 - denotes if flash device has 256 byte pages or not.
 | 
			
		||||
 *
 | 
			
		||||
 *  pageadrlen - number of bytes minus one needed to hold the
 | 
			
		||||
 *               complete address into the flash array. Keep in
 | 
			
		||||
 *               mind that when a read or write is done to a
 | 
			
		||||
 *               specific address, the address is input serially
 | 
			
		||||
 *               8 bits at a time. This structure member is used
 | 
			
		||||
 *               by the read/write routines as a loop index for
 | 
			
		||||
 *               shifting the address out 8 bits at a time.
 | 
			
		||||
 *
 | 
			
		||||
 *  erasesize - size of an erase block in the flash device.
 | 
			
		||||
 */
 | 
			
		||||
struct nand_flash_dev {
 | 
			
		||||
	char * name;
 | 
			
		||||
	int manufacture_id;
 | 
			
		||||
	int model_id;
 | 
			
		||||
	int chipshift;
 | 
			
		||||
	char page256;
 | 
			
		||||
	char pageadrlen;
 | 
			
		||||
	unsigned long erasesize;
 | 
			
		||||
	int bus16;
 | 
			
		||||
};
 | 
			
		||||
#define NAND_MFR_TOSHIBA   0x98
 | 
			
		||||
#define NAND_MFR_SAMSUNG   0xec
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* __MTD_DOC2000_H__ */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										91
									
								
								include/linux/mtd/inftl-user.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								include/linux/mtd/inftl-user.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,91 @@
 | 
			
		||||
/*
 | 
			
		||||
 * $Id: inftl-user.h,v 1.2 2005/11/07 11:14:56 gleixner Exp $
 | 
			
		||||
 *
 | 
			
		||||
 * Parts of INFTL headers shared with userspace
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __MTD_INFTL_USER_H__
 | 
			
		||||
#define __MTD_INFTL_USER_H__
 | 
			
		||||
 | 
			
		||||
#define	OSAK_VERSION	0x5120
 | 
			
		||||
#define	PERCENTUSED	98
 | 
			
		||||
 | 
			
		||||
#define	SECTORSIZE	512
 | 
			
		||||
 | 
			
		||||
/* Block Control Information */
 | 
			
		||||
 | 
			
		||||
struct inftl_bci {
 | 
			
		||||
	uint8_t ECCsig[6];
 | 
			
		||||
	uint8_t Status;
 | 
			
		||||
	uint8_t Status1;
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
struct inftl_unithead1 {
 | 
			
		||||
	uint16_t virtualUnitNo;
 | 
			
		||||
	uint16_t prevUnitNo;
 | 
			
		||||
	uint8_t ANAC;
 | 
			
		||||
	uint8_t NACs;
 | 
			
		||||
	uint8_t parityPerField;
 | 
			
		||||
	uint8_t discarded;
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
struct inftl_unithead2 {
 | 
			
		||||
	uint8_t parityPerField;
 | 
			
		||||
	uint8_t ANAC;
 | 
			
		||||
	uint16_t prevUnitNo;
 | 
			
		||||
	uint16_t virtualUnitNo;
 | 
			
		||||
	uint8_t NACs;
 | 
			
		||||
	uint8_t discarded;
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
struct inftl_unittail {
 | 
			
		||||
	uint8_t Reserved[4];
 | 
			
		||||
	uint16_t EraseMark;
 | 
			
		||||
	uint16_t EraseMark1;
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
union inftl_uci {
 | 
			
		||||
	struct inftl_unithead1 a;
 | 
			
		||||
	struct inftl_unithead2 b;
 | 
			
		||||
	struct inftl_unittail c;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct inftl_oob {
 | 
			
		||||
	struct inftl_bci b;
 | 
			
		||||
	union inftl_uci u;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* INFTL Media Header */
 | 
			
		||||
 | 
			
		||||
struct INFTLPartition {
 | 
			
		||||
	__u32 virtualUnits;
 | 
			
		||||
	__u32 firstUnit;
 | 
			
		||||
	__u32 lastUnit;
 | 
			
		||||
	__u32 flags;
 | 
			
		||||
	__u32 spareUnits;
 | 
			
		||||
	__u32 Reserved0;
 | 
			
		||||
	__u32 Reserved1;
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
struct INFTLMediaHeader {
 | 
			
		||||
	char bootRecordID[8];
 | 
			
		||||
	__u32 NoOfBootImageBlocks;
 | 
			
		||||
	__u32 NoOfBinaryPartitions;
 | 
			
		||||
	__u32 NoOfBDTLPartitions;
 | 
			
		||||
	__u32 BlockMultiplierBits;
 | 
			
		||||
	__u32 FormatFlags;
 | 
			
		||||
	__u32 OsakVersion;
 | 
			
		||||
	__u32 PercentUsed;
 | 
			
		||||
	struct INFTLPartition Partitions[4];
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
/* Partition flag types */
 | 
			
		||||
#define	INFTL_BINARY	0x20000000
 | 
			
		||||
#define	INFTL_BDTL	0x40000000
 | 
			
		||||
#define	INFTL_LAST	0x80000000
 | 
			
		||||
 | 
			
		||||
#endif /* __MTD_INFTL_USER_H__ */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										35
									
								
								include/linux/mtd/jffs2-user.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								include/linux/mtd/jffs2-user.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
			
		||||
/*
 | 
			
		||||
 * $Id: jffs2-user.h,v 1.1 2004/05/05 11:57:54 dwmw2 Exp $
 | 
			
		||||
 *
 | 
			
		||||
 * JFFS2 definitions for use in user space only
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __JFFS2_USER_H__
 | 
			
		||||
#define __JFFS2_USER_H__
 | 
			
		||||
 | 
			
		||||
/* This file is blessed for inclusion by userspace */
 | 
			
		||||
#include <linux/jffs2.h>
 | 
			
		||||
#include <endian.h>
 | 
			
		||||
#include <byteswap.h>
 | 
			
		||||
 | 
			
		||||
#undef cpu_to_je16
 | 
			
		||||
#undef cpu_to_je32
 | 
			
		||||
#undef cpu_to_jemode
 | 
			
		||||
#undef je16_to_cpu
 | 
			
		||||
#undef je32_to_cpu
 | 
			
		||||
#undef jemode_to_cpu
 | 
			
		||||
 | 
			
		||||
extern int target_endian;
 | 
			
		||||
 | 
			
		||||
#define t16(x) ({ uint16_t __b = (x); (target_endian==__BYTE_ORDER)?__b:bswap_16(__b); })
 | 
			
		||||
#define t32(x) ({ uint32_t __b = (x); (target_endian==__BYTE_ORDER)?__b:bswap_32(__b); })
 | 
			
		||||
 | 
			
		||||
#define cpu_to_je16(x) ((jint16_t){t16(x)})
 | 
			
		||||
#define cpu_to_je32(x) ((jint32_t){t32(x)})
 | 
			
		||||
#define cpu_to_jemode(x) ((jmode_t){t32(x)})
 | 
			
		||||
 | 
			
		||||
#define je16_to_cpu(x) (t16((x).v16))
 | 
			
		||||
#define je32_to_cpu(x) (t32((x).v32))
 | 
			
		||||
#define jemode_to_cpu(x) (t32((x).m))
 | 
			
		||||
 | 
			
		||||
#endif /* __JFFS2_USER_H__ */
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * $Id: mtd-abi.h,v 1.7 2004/11/23 15:37:32 gleixner Exp $
 | 
			
		||||
 * $Id: mtd-abi.h,v 1.13 2005/11/07 11:14:56 gleixner Exp $
 | 
			
		||||
 *
 | 
			
		||||
 * Portions of MTD ABI definition which are shared by kernel and user space
 | 
			
		||||
 */
 | 
			
		||||
@ -7,6 +7,10 @@
 | 
			
		||||
#ifndef __MTD_ABI_H__
 | 
			
		||||
#define __MTD_ABI_H__
 | 
			
		||||
 | 
			
		||||
#if 1
 | 
			
		||||
#include <linux/mtd/compat.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct erase_info_user {
 | 
			
		||||
	uint32_t start;
 | 
			
		||||
	uint32_t length;
 | 
			
		||||
@ -15,7 +19,7 @@ struct erase_info_user {
 | 
			
		||||
struct mtd_oob_buf {
 | 
			
		||||
	uint32_t start;
 | 
			
		||||
	uint32_t length;
 | 
			
		||||
	unsigned char *ptr;
 | 
			
		||||
	unsigned char __user *ptr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define MTD_ABSENT		0
 | 
			
		||||
@ -23,47 +27,41 @@ struct mtd_oob_buf {
 | 
			
		||||
#define MTD_ROM			2
 | 
			
		||||
#define MTD_NORFLASH		3
 | 
			
		||||
#define MTD_NANDFLASH		4
 | 
			
		||||
#define MTD_PEROM		5
 | 
			
		||||
#define MTD_OTHER		14
 | 
			
		||||
#define MTD_UNKNOWN		15
 | 
			
		||||
#define MTD_DATAFLASH		6
 | 
			
		||||
#define MTD_UBIVOLUME		7
 | 
			
		||||
 | 
			
		||||
#define MTD_CLEAR_BITS		1       /* Bits can be cleared (flash) */
 | 
			
		||||
#define MTD_SET_BITS		2       /* Bits can be set */
 | 
			
		||||
#define MTD_ERASEABLE		4       /* Has an erase function */
 | 
			
		||||
#define MTD_WRITEB_WRITEABLE	8       /* Direct IO is possible */
 | 
			
		||||
#define MTD_VOLATILE		16      /* Set for RAMs */
 | 
			
		||||
#define MTD_XIP			32	/* eXecute-In-Place possible */
 | 
			
		||||
#define MTD_OOB			64	/* Out-of-band data (NAND flash) */
 | 
			
		||||
#define MTD_ECC			128	/* Device capable of automatic ECC */
 | 
			
		||||
#define MTD_NO_VIRTBLOCKS	256	/* Virtual blocks not allowed */
 | 
			
		||||
#define MTD_WRITEABLE		0x400	/* Device is writeable */
 | 
			
		||||
#define MTD_BIT_WRITEABLE	0x800	/* Single bits can be flipped */
 | 
			
		||||
#define MTD_NO_ERASE		0x1000	/* No erase necessary */
 | 
			
		||||
#define MTD_STUPID_LOCK		0x2000	/* Always locked after reset */
 | 
			
		||||
 | 
			
		||||
/* Some common devices / combinations of capabilities */
 | 
			
		||||
// Some common devices / combinations of capabilities
 | 
			
		||||
#define MTD_CAP_ROM		0
 | 
			
		||||
#define MTD_CAP_RAM		(MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEB_WRITEABLE)
 | 
			
		||||
#define MTD_CAP_NORFLASH        (MTD_CLEAR_BITS|MTD_ERASEABLE)
 | 
			
		||||
#define MTD_CAP_NANDFLASH       (MTD_CLEAR_BITS|MTD_ERASEABLE|MTD_OOB)
 | 
			
		||||
#define MTD_WRITEABLE		(MTD_CLEAR_BITS|MTD_SET_BITS)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Types of automatic ECC/Checksum available */
 | 
			
		||||
#define MTD_ECC_NONE		0	/* No automatic ECC available */
 | 
			
		||||
#define MTD_ECC_RS_DiskOnChip	1	/* Automatic ECC on DiskOnChip */
 | 
			
		||||
#define MTD_ECC_SW		2	/* SW ECC for Toshiba & Samsung devices */
 | 
			
		||||
#define MTD_CAP_RAM		(MTD_WRITEABLE | MTD_BIT_WRITEABLE | MTD_NO_ERASE)
 | 
			
		||||
#define MTD_CAP_NORFLASH	(MTD_WRITEABLE | MTD_BIT_WRITEABLE)
 | 
			
		||||
#define MTD_CAP_NANDFLASH	(MTD_WRITEABLE)
 | 
			
		||||
 | 
			
		||||
/* ECC byte placement */
 | 
			
		||||
#define MTD_NANDECC_OFF		0	/* Switch off ECC (Not recommended) */
 | 
			
		||||
#define MTD_NANDECC_PLACE	1	/* Use the given placement in the structure (YAFFS1 legacy mode) */
 | 
			
		||||
#define MTD_NANDECC_AUTOPLACE	2	/* Use the default placement scheme */
 | 
			
		||||
#define MTD_NANDECC_PLACEONLY	3	/* Use the given placement in the structure (Do not store ecc result on read) */
 | 
			
		||||
#define MTD_NANDECC_AUTOPL_USR	4	/* Use the given autoplacement scheme rather than using the default */
 | 
			
		||||
#define MTD_NANDECC_OFF		0	// Switch off ECC (Not recommended)
 | 
			
		||||
#define MTD_NANDECC_PLACE	1	// Use the given placement in the structure (YAFFS1 legacy mode)
 | 
			
		||||
#define MTD_NANDECC_AUTOPLACE	2	// Use the default placement scheme
 | 
			
		||||
#define MTD_NANDECC_PLACEONLY	3	// Use the given placement in the structure (Do not store ecc result on read)
 | 
			
		||||
#define MTD_NANDECC_AUTOPL_USR	4	// Use the given autoplacement scheme rather than using the default
 | 
			
		||||
 | 
			
		||||
/* OTP mode selection */
 | 
			
		||||
#define MTD_OTP_OFF		0
 | 
			
		||||
#define MTD_OTP_FACTORY		1
 | 
			
		||||
#define MTD_OTP_USER		2
 | 
			
		||||
 | 
			
		||||
struct mtd_info_user {
 | 
			
		||||
	uint8_t type;
 | 
			
		||||
	uint32_t flags;
 | 
			
		||||
	uint32_t size;	 /* Total size of the MTD */
 | 
			
		||||
	uint32_t size;	 // Total size of the MTD
 | 
			
		||||
	uint32_t erasesize;
 | 
			
		||||
	uint32_t oobblock;  /* Size of OOB blocks (e.g. 512) */
 | 
			
		||||
	uint32_t oobsize;   /* Amount of OOB data per block (e.g. 16) */
 | 
			
		||||
	uint32_t writesize;
 | 
			
		||||
	uint32_t oobsize;   // Amount of OOB data per block (e.g. 16)
 | 
			
		||||
	/* The below two fields are obsolete and broken, do not use them
 | 
			
		||||
	 * (TODO: remove at some point) */
 | 
			
		||||
	uint32_t ecctype;
 | 
			
		||||
	uint32_t eccsize;
 | 
			
		||||
};
 | 
			
		||||
@ -76,19 +74,36 @@ struct region_info_user {
 | 
			
		||||
	uint32_t regionindex;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define MEMGETINFO              _IOR('M', 1, struct mtd_info_user)
 | 
			
		||||
#define MEMERASE                _IOW('M', 2, struct erase_info_user)
 | 
			
		||||
#define MEMWRITEOOB             _IOWR('M', 3, struct mtd_oob_buf)
 | 
			
		||||
#define MEMREADOOB              _IOWR('M', 4, struct mtd_oob_buf)
 | 
			
		||||
#define MEMLOCK                 _IOW('M', 5, struct erase_info_user)
 | 
			
		||||
#define MEMUNLOCK               _IOW('M', 6, struct erase_info_user)
 | 
			
		||||
struct otp_info {
 | 
			
		||||
	uint32_t start;
 | 
			
		||||
	uint32_t length;
 | 
			
		||||
	uint32_t locked;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define MEMGETINFO		_IOR('M', 1, struct mtd_info_user)
 | 
			
		||||
#define MEMERASE		_IOW('M', 2, struct erase_info_user)
 | 
			
		||||
#define MEMWRITEOOB		_IOWR('M', 3, struct mtd_oob_buf)
 | 
			
		||||
#define MEMREADOOB		_IOWR('M', 4, struct mtd_oob_buf)
 | 
			
		||||
#define MEMLOCK			_IOW('M', 5, struct erase_info_user)
 | 
			
		||||
#define MEMUNLOCK		_IOW('M', 6, struct erase_info_user)
 | 
			
		||||
#define MEMGETREGIONCOUNT	_IOR('M', 7, int)
 | 
			
		||||
#define MEMGETREGIONINFO	_IOWR('M', 8, struct region_info_user)
 | 
			
		||||
#define MEMSETOOBSEL		_IOW('M', 9, struct nand_oobinfo)
 | 
			
		||||
#define MEMGETOOBSEL		_IOR('M', 10, struct nand_oobinfo)
 | 
			
		||||
#define MEMGETBADBLOCK		_IOW('M', 11, loff_t)
 | 
			
		||||
#define MEMSETBADBLOCK		_IOW('M', 12, loff_t)
 | 
			
		||||
#define OTPSELECT		_IOR('M', 13, int)
 | 
			
		||||
#define OTPGETREGIONCOUNT	_IOW('M', 14, int)
 | 
			
		||||
#define OTPGETREGIONINFO	_IOW('M', 15, struct otp_info)
 | 
			
		||||
#define OTPLOCK			_IOR('M', 16, struct otp_info)
 | 
			
		||||
#define ECCGETLAYOUT		_IOR('M', 17, struct nand_ecclayout)
 | 
			
		||||
#define ECCGETSTATS		_IOR('M', 18, struct mtd_ecc_stats)
 | 
			
		||||
#define MTDFILEMODE		_IO('M', 19)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Obsolete legacy interface. Keep it in order not to break userspace
 | 
			
		||||
 * interfaces
 | 
			
		||||
 */
 | 
			
		||||
struct nand_oobinfo {
 | 
			
		||||
	uint32_t useecc;
 | 
			
		||||
	uint32_t eccbytes;
 | 
			
		||||
@ -96,4 +111,46 @@ struct nand_oobinfo {
 | 
			
		||||
	uint32_t eccpos[48];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct nand_oobfree {
 | 
			
		||||
	uint32_t offset;
 | 
			
		||||
	uint32_t length;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define MTD_MAX_OOBFREE_ENTRIES	8
 | 
			
		||||
/*
 | 
			
		||||
 * ECC layout control structure. Exported to userspace for
 | 
			
		||||
 * diagnosis and to allow creation of raw images
 | 
			
		||||
 */
 | 
			
		||||
struct nand_ecclayout {
 | 
			
		||||
	uint32_t eccbytes;
 | 
			
		||||
	uint32_t eccpos[64];
 | 
			
		||||
	uint32_t oobavail;
 | 
			
		||||
	struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct mtd_ecc_stats - error correction stats
 | 
			
		||||
 *
 | 
			
		||||
 * @corrected:	number of corrected bits
 | 
			
		||||
 * @failed:	number of uncorrectable errors
 | 
			
		||||
 * @badblocks:	number of bad blocks in this partition
 | 
			
		||||
 * @bbtblocks:	number of blocks reserved for bad block tables
 | 
			
		||||
 */
 | 
			
		||||
struct mtd_ecc_stats {
 | 
			
		||||
	uint32_t corrected;
 | 
			
		||||
	uint32_t failed;
 | 
			
		||||
	uint32_t badblocks;
 | 
			
		||||
	uint32_t bbtblocks;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Read/write file modes for access to MTD
 | 
			
		||||
 */
 | 
			
		||||
enum mtd_file_modes {
 | 
			
		||||
	MTD_MODE_NORMAL = MTD_OTP_OFF,
 | 
			
		||||
	MTD_MODE_OTP_FACTORY = MTD_OTP_FACTORY,
 | 
			
		||||
	MTD_MODE_OTP_USER = MTD_OTP_USER,
 | 
			
		||||
	MTD_MODE_RAW,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif /* __MTD_ABI_H__ */
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * $Id: mtd.h,v 1.56 2004/08/09 18:46:04 dmarlin Exp $
 | 
			
		||||
 * $Id: mtd.h,v 1.61 2005/11/07 11:14:54 gleixner Exp $
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al.
 | 
			
		||||
 *
 | 
			
		||||
@ -8,10 +8,13 @@
 | 
			
		||||
 | 
			
		||||
#ifndef __MTD_MTD_H__
 | 
			
		||||
#define __MTD_MTD_H__
 | 
			
		||||
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/mtd/mtd-abi.h>
 | 
			
		||||
 | 
			
		||||
#define MAX_MTD_DEVICES 16
 | 
			
		||||
#define MTD_CHAR_MAJOR 90
 | 
			
		||||
#define MTD_BLOCK_MAJOR 31
 | 
			
		||||
#define MAX_MTD_DEVICES 32
 | 
			
		||||
 | 
			
		||||
#define MTD_ERASE_PENDING	0x01
 | 
			
		||||
#define MTD_ERASING		0x02
 | 
			
		||||
@ -41,32 +44,83 @@ struct mtd_erase_region_info {
 | 
			
		||||
	u_int32_t offset;			/* At which this region starts, from the beginning of the MTD */
 | 
			
		||||
	u_int32_t erasesize;		/* For this region */
 | 
			
		||||
	u_int32_t numblocks;		/* Number of blocks of erasesize in this region */
 | 
			
		||||
	unsigned long *lockmap;		/* If keeping bitmap of locks */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * oob operation modes
 | 
			
		||||
 *
 | 
			
		||||
 * MTD_OOB_PLACE:	oob data are placed at the given offset
 | 
			
		||||
 * MTD_OOB_AUTO:	oob data are automatically placed at the free areas
 | 
			
		||||
 *			which are defined by the ecclayout
 | 
			
		||||
 * MTD_OOB_RAW:		mode to read raw data+oob in one chunk. The oob data
 | 
			
		||||
 *			is inserted into the data. Thats a raw image of the
 | 
			
		||||
 *			flash contents.
 | 
			
		||||
 */
 | 
			
		||||
typedef enum {
 | 
			
		||||
	MTD_OOB_PLACE,
 | 
			
		||||
	MTD_OOB_AUTO,
 | 
			
		||||
	MTD_OOB_RAW,
 | 
			
		||||
} mtd_oob_mode_t;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct mtd_oob_ops - oob operation operands
 | 
			
		||||
 * @mode:	operation mode
 | 
			
		||||
 *
 | 
			
		||||
 * @len:	number of data bytes to write/read
 | 
			
		||||
 *
 | 
			
		||||
 * @retlen:	number of data bytes written/read
 | 
			
		||||
 *
 | 
			
		||||
 * @ooblen:	number of oob bytes to write/read
 | 
			
		||||
 * @oobretlen:	number of oob bytes written/read
 | 
			
		||||
 * @ooboffs:	offset of oob data in the oob area (only relevant when
 | 
			
		||||
 *		mode = MTD_OOB_PLACE)
 | 
			
		||||
 * @datbuf:	data buffer - if NULL only oob data are read/written
 | 
			
		||||
 * @oobbuf:	oob data buffer
 | 
			
		||||
 *
 | 
			
		||||
 * Note, it is allowed to read more then one OOB area at one go, but not write.
 | 
			
		||||
 * The interface assumes that the OOB write requests program only one page's
 | 
			
		||||
 * OOB area.
 | 
			
		||||
 */
 | 
			
		||||
struct mtd_oob_ops {
 | 
			
		||||
	mtd_oob_mode_t	mode;
 | 
			
		||||
	size_t		len;
 | 
			
		||||
	size_t		retlen;
 | 
			
		||||
	size_t		ooblen;
 | 
			
		||||
	size_t		oobretlen;
 | 
			
		||||
	uint32_t	ooboffs;
 | 
			
		||||
	uint8_t		*datbuf;
 | 
			
		||||
	uint8_t		*oobbuf;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mtd_info {
 | 
			
		||||
	u_char type;
 | 
			
		||||
	u_int32_t flags;
 | 
			
		||||
	u_int32_t size;	 /* Total size of the MTD */
 | 
			
		||||
	u_int32_t size;	 // Total size of the MTD
 | 
			
		||||
 | 
			
		||||
	/* "Major" erase size for the device. Naïve users may take this
 | 
			
		||||
	/* "Major" erase size for the device. Naïve users may take this
 | 
			
		||||
	 * to be the only erase size available, or may use the more detailed
 | 
			
		||||
	 * information below if they desire
 | 
			
		||||
	 */
 | 
			
		||||
	u_int32_t erasesize;
 | 
			
		||||
	/* Minimal writable flash unit size. In case of NOR flash it is 1 (even
 | 
			
		||||
	 * though individual bits can be cleared), in case of NAND flash it is
 | 
			
		||||
	 * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR
 | 
			
		||||
	 * it is of ECC block size, etc. It is illegal to have writesize = 0.
 | 
			
		||||
	 * Any driver registering a struct mtd_info must ensure a writesize of
 | 
			
		||||
	 * 1 or larger.
 | 
			
		||||
	 */
 | 
			
		||||
	u_int32_t writesize;
 | 
			
		||||
 | 
			
		||||
	u_int32_t oobblock;  /* Size of OOB blocks (e.g. 512) */
 | 
			
		||||
	u_int32_t oobsize;   /* Amount of OOB data per block (e.g. 16) */
 | 
			
		||||
	u_int32_t oobavail;  /* Number of bytes in OOB area available for fs  */
 | 
			
		||||
	u_int32_t ecctype;
 | 
			
		||||
	u_int32_t eccsize;
 | 
			
		||||
	u_int32_t oobsize;   // Amount of OOB data per block (e.g. 16)
 | 
			
		||||
	u_int32_t oobavail;  // Available OOB bytes per block
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	/* Kernel-only stuff starts here. */
 | 
			
		||||
	// Kernel-only stuff starts here.
 | 
			
		||||
	char *name;
 | 
			
		||||
	int index;
 | 
			
		||||
 | 
			
		||||
	/* oobinfo is a nand_oobinfo structure, which can be set by iotcl (MEMSETOOBINFO) */
 | 
			
		||||
	struct nand_oobinfo oobinfo;
 | 
			
		||||
	/* ecc layout structure pointer - read only ! */
 | 
			
		||||
	struct nand_ecclayout *ecclayout;
 | 
			
		||||
 | 
			
		||||
	/* Data for variable erase regions. If numeraseregions is zero,
 | 
			
		||||
	 * it means that the whole device has erasesize as given above.
 | 
			
		||||
@ -74,9 +128,6 @@ struct mtd_info {
 | 
			
		||||
	int numeraseregions;
 | 
			
		||||
	struct mtd_erase_region_info *eraseregions;
 | 
			
		||||
 | 
			
		||||
	/* This really shouldn't be here. It can go away in 2.5 */
 | 
			
		||||
	u_int32_t bank_size;
 | 
			
		||||
 | 
			
		||||
	int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
 | 
			
		||||
 | 
			
		||||
	/* This stuff for eXecute-In-Place */
 | 
			
		||||
@ -89,39 +140,35 @@ struct mtd_info {
 | 
			
		||||
	int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
 | 
			
		||||
	int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
 | 
			
		||||
 | 
			
		||||
	int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
 | 
			
		||||
	int (*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);
 | 
			
		||||
 | 
			
		||||
	int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
 | 
			
		||||
	int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
 | 
			
		||||
	int (*read_oob) (struct mtd_info *mtd, loff_t from,
 | 
			
		||||
			 struct mtd_oob_ops *ops);
 | 
			
		||||
	int (*write_oob) (struct mtd_info *mtd, loff_t to,
 | 
			
		||||
			 struct mtd_oob_ops *ops);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Methods to access the protection register area, present in some
 | 
			
		||||
	 * flash devices. The user data is one time programmable but the
 | 
			
		||||
	 * factory data is read only.
 | 
			
		||||
	 */
 | 
			
		||||
	int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
 | 
			
		||||
 | 
			
		||||
	int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
 | 
			
		||||
	int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
 | 
			
		||||
 | 
			
		||||
	/* This function is not yet implemented */
 | 
			
		||||
	int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
 | 
			
		||||
	int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
 | 
			
		||||
	int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
 | 
			
		||||
	int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len);
 | 
			
		||||
 | 
			
		||||
/* XXX U-BOOT XXX */
 | 
			
		||||
#if 0
 | 
			
		||||
	/* kvec-based read/write methods. We need these especially for NAND flash,
 | 
			
		||||
	   with its limited number of write cycles per erase.
 | 
			
		||||
	/* kvec-based read/write methods.
 | 
			
		||||
	   NB: The 'count' parameter is the number of _vectors_, each of
 | 
			
		||||
	   which contains an (ofs, len) tuple.
 | 
			
		||||
	*/
 | 
			
		||||
	int (*readv) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen);
 | 
			
		||||
	int (*readv_ecc) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from,
 | 
			
		||||
		size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
 | 
			
		||||
	int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen);
 | 
			
		||||
	int (*writev_ecc) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to,
 | 
			
		||||
		size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/* Sync */
 | 
			
		||||
	void (*sync) (struct mtd_info *mtd);
 | 
			
		||||
#if 0
 | 
			
		||||
 | 
			
		||||
	/* Chip-supported device locking */
 | 
			
		||||
	int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len);
 | 
			
		||||
	int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len);
 | 
			
		||||
@ -129,15 +176,32 @@ struct mtd_info {
 | 
			
		||||
	/* Power Management functions */
 | 
			
		||||
	int (*suspend) (struct mtd_info *mtd);
 | 
			
		||||
	void (*resume) (struct mtd_info *mtd);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/* Bad block management functions */
 | 
			
		||||
	int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
 | 
			
		||||
	int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
 | 
			
		||||
 | 
			
		||||
/* XXX U-BOOT XXX */
 | 
			
		||||
#if 0
 | 
			
		||||
	struct notifier_block reboot_notifier;  /* default mode before reboot */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/* ECC status information */
 | 
			
		||||
	struct mtd_ecc_stats ecc_stats;
 | 
			
		||||
	/* Subpage shift (NAND) */
 | 
			
		||||
	int subpage_sft;
 | 
			
		||||
 | 
			
		||||
	void *priv;
 | 
			
		||||
 | 
			
		||||
	struct module *owner;
 | 
			
		||||
	int usecount;
 | 
			
		||||
 | 
			
		||||
	/* If the driver is something smart, like UBI, it may need to maintain
 | 
			
		||||
	 * its own reference counting. The below functions are only for driver.
 | 
			
		||||
	 * The driver may register its callbacks. These callbacks are not
 | 
			
		||||
	 * supposed to be called by MTD users */
 | 
			
		||||
	int (*get_device) (struct mtd_info *mtd);
 | 
			
		||||
	void (*put_device) (struct mtd_info *mtd);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -147,9 +211,11 @@ extern int add_mtd_device(struct mtd_info *mtd);
 | 
			
		||||
extern int del_mtd_device (struct mtd_info *mtd);
 | 
			
		||||
 | 
			
		||||
extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
 | 
			
		||||
extern struct mtd_info *get_mtd_device_nm(const char *name);
 | 
			
		||||
 | 
			
		||||
extern void put_mtd_device(struct mtd_info *mtd);
 | 
			
		||||
 | 
			
		||||
/* XXX U-BOOT XXX */
 | 
			
		||||
#if 0
 | 
			
		||||
struct mtd_notifier {
 | 
			
		||||
	void (*add)(struct mtd_info *mtd);
 | 
			
		||||
@ -157,7 +223,6 @@ struct mtd_notifier {
 | 
			
		||||
	struct list_head list;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
extern void register_mtd_user (struct mtd_notifier *new);
 | 
			
		||||
extern int unregister_mtd_user (struct mtd_notifier *old);
 | 
			
		||||
 | 
			
		||||
@ -168,20 +233,6 @@ int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs,
 | 
			
		||||
		      unsigned long count, loff_t from, size_t *retlen);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define MTD_ERASE(mtd, args...) (*(mtd->erase))(mtd, args)
 | 
			
		||||
#define MTD_POINT(mtd, a,b,c,d) (*(mtd->point))(mtd, a,b,c, (u_char **)(d))
 | 
			
		||||
#define MTD_UNPOINT(mtd, arg) (*(mtd->unpoint))(mtd, (u_char *)arg)
 | 
			
		||||
#define MTD_READ(mtd, args...) (*(mtd->read))(mtd, args)
 | 
			
		||||
#define MTD_WRITE(mtd, args...) (*(mtd->write))(mtd, args)
 | 
			
		||||
#define MTD_READV(mtd, args...) (*(mtd->readv))(mtd, args)
 | 
			
		||||
#define MTD_WRITEV(mtd, args...) (*(mtd->writev))(mtd, args)
 | 
			
		||||
#define MTD_READECC(mtd, args...) (*(mtd->read_ecc))(mtd, args)
 | 
			
		||||
#define MTD_WRITEECC(mtd, args...) (*(mtd->write_ecc))(mtd, args)
 | 
			
		||||
#define MTD_READOOB(mtd, args...) (*(mtd->read_oob))(mtd, args)
 | 
			
		||||
#define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args)
 | 
			
		||||
#define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd);  } while (0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_MTD_PARTITIONS
 | 
			
		||||
void mtd_erase_callback(struct erase_info *instr);
 | 
			
		||||
#else
 | 
			
		||||
@ -208,7 +259,6 @@ static inline void mtd_erase_callback(struct erase_info *instr)
 | 
			
		||||
	} while(0)
 | 
			
		||||
#else /* CONFIG_MTD_DEBUG */
 | 
			
		||||
#define MTDDEBUG(n, args...) do { } while(0)
 | 
			
		||||
 | 
			
		||||
#endif /* CONFIG_MTD_DEBUG */
 | 
			
		||||
 | 
			
		||||
#endif /* __MTD_MTD_H__ */
 | 
			
		||||
 | 
			
		||||
@ -2,114 +2,123 @@
 | 
			
		||||
 *  linux/include/linux/mtd/nand.h
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright (c) 2000 David Woodhouse <dwmw2@mvhi.com>
 | 
			
		||||
 *		       Steven J. Hill <sjhill@realitydiluted.com>
 | 
			
		||||
 *                     Steven J. Hill <sjhill@realitydiluted.com>
 | 
			
		||||
 *		       Thomas Gleixner <tglx@linutronix.de>
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: nand.h,v 1.68 2004/11/12 10:40:37 gleixner Exp $
 | 
			
		||||
 * $Id: nand.h,v 1.74 2005/09/15 13:58:50 vwool 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.
 | 
			
		||||
 *
 | 
			
		||||
 *  Info:
 | 
			
		||||
 *   Contains standard defines and IDs for NAND flash devices
 | 
			
		||||
 * Info:
 | 
			
		||||
 *	Contains standard defines and IDs for NAND flash devices
 | 
			
		||||
 *
 | 
			
		||||
 *  Changelog:
 | 
			
		||||
 *   01-31-2000 DMW	Created
 | 
			
		||||
 *   09-18-2000 SJH	Moved structure out of the Disk-On-Chip drivers
 | 
			
		||||
 *			so it can be used by other NAND flash device
 | 
			
		||||
 *			drivers. I also changed the copyright since none
 | 
			
		||||
 *			of the original contents of this file are specific
 | 
			
		||||
 *			to DoC devices. David can whack me with a baseball
 | 
			
		||||
 *			bat later if I did something naughty.
 | 
			
		||||
 *   10-11-2000 SJH	Added private NAND flash structure for driver
 | 
			
		||||
 *   10-24-2000 SJH	Added prototype for 'nand_scan' function
 | 
			
		||||
 *   10-29-2001 TG	changed nand_chip structure to support
 | 
			
		||||
 *			hardwarespecific function for accessing control lines
 | 
			
		||||
 *   02-21-2002 TG	added support for different read/write adress and
 | 
			
		||||
 *			ready/busy line access function
 | 
			
		||||
 *   02-26-2002 TG	added chip_delay to nand_chip structure to optimize
 | 
			
		||||
 *			command delay times for different chips
 | 
			
		||||
 *   04-28-2002 TG	OOB config defines moved from nand.c to avoid duplicate
 | 
			
		||||
 *			defines in jffs2/wbuf.c
 | 
			
		||||
 *   08-07-2002 TG	forced bad block location to byte 5 of OOB, even if
 | 
			
		||||
 *			CONFIG_MTD_NAND_ECC_JFFS2 is not set
 | 
			
		||||
 *   08-10-2002 TG	extensions to nand_chip structure to support HW-ECC
 | 
			
		||||
 *
 | 
			
		||||
 *   08-29-2002 tglx	nand_chip structure: data_poi for selecting
 | 
			
		||||
 *			internal / fs-driver buffer
 | 
			
		||||
 *			support for 6byte/512byte hardware ECC
 | 
			
		||||
 *			read_ecc, write_ecc extended for different oob-layout
 | 
			
		||||
 *			oob layout selections: NAND_NONE_OOB, NAND_JFFS2_OOB,
 | 
			
		||||
 *			NAND_YAFFS_OOB
 | 
			
		||||
 *  11-25-2002 tglx	Added Manufacturer code FUJITSU, NATIONAL
 | 
			
		||||
 *			Split manufacturer and device ID structures
 | 
			
		||||
 *
 | 
			
		||||
 *  02-08-2004 tglx	added option field to nand structure for chip anomalities
 | 
			
		||||
 *  05-25-2004 tglx	added bad block table support, ST-MICRO manufacturer id
 | 
			
		||||
 *			update of nand_chip structure description
 | 
			
		||||
 * Changelog:
 | 
			
		||||
 *	See git changelog.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef __LINUX_MTD_NAND_H
 | 
			
		||||
#define __LINUX_MTD_NAND_H
 | 
			
		||||
 | 
			
		||||
#include <linux/mtd/compat.h>
 | 
			
		||||
/* XXX U-BOOT XXX */
 | 
			
		||||
#if 0
 | 
			
		||||
#include <linux/wait.h>
 | 
			
		||||
#include <linux/spinlock.h>
 | 
			
		||||
#include <linux/mtd/mtd.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "linux/mtd/compat.h"
 | 
			
		||||
#include "linux/mtd/mtd.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct mtd_info;
 | 
			
		||||
/* Scan and identify a NAND device */
 | 
			
		||||
extern int nand_scan (struct mtd_info *mtd, int max_chips);
 | 
			
		||||
/* Separate phases of nand_scan(), allowing board driver to intervene
 | 
			
		||||
 * and override command or ECC setup according to flash type */
 | 
			
		||||
extern int nand_scan_ident(struct mtd_info *mtd, int max_chips);
 | 
			
		||||
extern int nand_scan_tail(struct mtd_info *mtd);
 | 
			
		||||
 | 
			
		||||
/* Free resources held by the NAND device */
 | 
			
		||||
extern void nand_release (struct mtd_info *mtd);
 | 
			
		||||
 | 
			
		||||
/* Read raw data from the device without ECC */
 | 
			
		||||
extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, size_t ooblen);
 | 
			
		||||
/* Internal helper for board drivers which need to override command function */
 | 
			
		||||
extern void nand_wait_ready(struct mtd_info *mtd);
 | 
			
		||||
 | 
			
		||||
/* The maximum number of NAND chips in an array */
 | 
			
		||||
#ifndef NAND_MAX_CHIPS
 | 
			
		||||
#define NAND_MAX_CHIPS		8
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* This constant declares the max. oobsize / page, which
 | 
			
		||||
 * is supported now. If you add a chip with bigger oobsize/page
 | 
			
		||||
 * adjust this accordingly.
 | 
			
		||||
 */
 | 
			
		||||
#define NAND_MAX_OOBSIZE	64
 | 
			
		||||
#define NAND_MAX_OOBSIZE	128
 | 
			
		||||
#define NAND_MAX_PAGESIZE	4096
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Constants for hardware specific CLE/ALE/NCE function
 | 
			
		||||
*/
 | 
			
		||||
 *
 | 
			
		||||
 * These are bits which can be or'ed to set/clear multiple
 | 
			
		||||
 * bits in one go.
 | 
			
		||||
 */
 | 
			
		||||
/* Select the chip by setting nCE to low */
 | 
			
		||||
#define NAND_CTL_SETNCE		1
 | 
			
		||||
/* Deselect the chip by setting nCE to high */
 | 
			
		||||
#define NAND_CTL_CLRNCE		2
 | 
			
		||||
#define NAND_NCE		0x01
 | 
			
		||||
/* Select the command latch by setting CLE to high */
 | 
			
		||||
#define NAND_CTL_SETCLE		3
 | 
			
		||||
/* Deselect the command latch by setting CLE to low */
 | 
			
		||||
#define NAND_CTL_CLRCLE		4
 | 
			
		||||
#define NAND_CLE		0x02
 | 
			
		||||
/* Select the address latch by setting ALE to high */
 | 
			
		||||
#define NAND_CTL_SETALE		5
 | 
			
		||||
/* Deselect the address latch by setting ALE to low */
 | 
			
		||||
#define NAND_CTL_CLRALE		6
 | 
			
		||||
/* Set write protection by setting WP to high. Not used! */
 | 
			
		||||
#define NAND_CTL_SETWP		7
 | 
			
		||||
/* Clear write protection by setting WP to low. Not used! */
 | 
			
		||||
#define NAND_CTL_CLRWP		8
 | 
			
		||||
#define NAND_ALE		0x04
 | 
			
		||||
 | 
			
		||||
#define NAND_CTRL_CLE		(NAND_NCE | NAND_CLE)
 | 
			
		||||
#define NAND_CTRL_ALE		(NAND_NCE | NAND_ALE)
 | 
			
		||||
#define NAND_CTRL_CHANGE	0x80
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Standard NAND flash commands
 | 
			
		||||
 */
 | 
			
		||||
#define NAND_CMD_READ0		0
 | 
			
		||||
#define NAND_CMD_READ1		1
 | 
			
		||||
#define NAND_CMD_RNDOUT		5
 | 
			
		||||
#define NAND_CMD_PAGEPROG	0x10
 | 
			
		||||
#define NAND_CMD_READOOB	0x50
 | 
			
		||||
#define NAND_CMD_ERASE1		0x60
 | 
			
		||||
#define NAND_CMD_STATUS		0x70
 | 
			
		||||
#define NAND_CMD_STATUS_MULTI	0x71
 | 
			
		||||
#define NAND_CMD_SEQIN		0x80
 | 
			
		||||
#define NAND_CMD_RNDIN		0x85
 | 
			
		||||
#define NAND_CMD_READID		0x90
 | 
			
		||||
#define NAND_CMD_ERASE2		0xd0
 | 
			
		||||
#define NAND_CMD_RESET		0xff
 | 
			
		||||
 | 
			
		||||
/* Extended commands for large page devices */
 | 
			
		||||
#define NAND_CMD_READSTART	0x30
 | 
			
		||||
#define NAND_CMD_RNDOUTSTART	0xE0
 | 
			
		||||
#define NAND_CMD_CACHEDPROG	0x15
 | 
			
		||||
 | 
			
		||||
/* Extended commands for AG-AND device */
 | 
			
		||||
/*
 | 
			
		||||
 * Note: the command for NAND_CMD_DEPLETE1 is really 0x00 but
 | 
			
		||||
 *       there is no way to distinguish that from NAND_CMD_READ0
 | 
			
		||||
 *       until the remaining sequence of commands has been completed
 | 
			
		||||
 *       so add a high order bit and mask it off in the command.
 | 
			
		||||
 */
 | 
			
		||||
#define NAND_CMD_DEPLETE1	0x100
 | 
			
		||||
#define NAND_CMD_DEPLETE2	0x38
 | 
			
		||||
#define NAND_CMD_STATUS_MULTI	0x71
 | 
			
		||||
#define NAND_CMD_STATUS_ERROR	0x72
 | 
			
		||||
/* multi-bank error status (banks 0-3) */
 | 
			
		||||
#define NAND_CMD_STATUS_ERROR0	0x73
 | 
			
		||||
#define NAND_CMD_STATUS_ERROR1	0x74
 | 
			
		||||
#define NAND_CMD_STATUS_ERROR2	0x75
 | 
			
		||||
#define NAND_CMD_STATUS_ERROR3	0x76
 | 
			
		||||
#define NAND_CMD_STATUS_RESET	0x7f
 | 
			
		||||
#define NAND_CMD_STATUS_CLEAR	0xff
 | 
			
		||||
 | 
			
		||||
#define NAND_CMD_NONE		-1
 | 
			
		||||
 | 
			
		||||
/* Status bits */
 | 
			
		||||
#define NAND_STATUS_FAIL	0x01
 | 
			
		||||
#define NAND_STATUS_FAIL_N1	0x02
 | 
			
		||||
@ -120,25 +129,16 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_
 | 
			
		||||
/*
 | 
			
		||||
 * Constants for ECC_MODES
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* No ECC. Usage is not recommended ! */
 | 
			
		||||
#define NAND_ECC_NONE		0
 | 
			
		||||
/* Software ECC 3 byte ECC per 256 Byte data */
 | 
			
		||||
#define NAND_ECC_SOFT		1
 | 
			
		||||
/* Hardware ECC 3 byte ECC per 256 Byte data */
 | 
			
		||||
#define NAND_ECC_HW3_256	2
 | 
			
		||||
/* Hardware ECC 3 byte ECC per 512 Byte data */
 | 
			
		||||
#define NAND_ECC_HW3_512	3
 | 
			
		||||
/* Hardware ECC 6 byte ECC per 512 Byte data */
 | 
			
		||||
#define NAND_ECC_HW6_512	4
 | 
			
		||||
/* Hardware ECC 8 byte ECC per 512 Byte data */
 | 
			
		||||
#define NAND_ECC_HW8_512	6
 | 
			
		||||
/* Hardware ECC 12 byte ECC per 2048 Byte data */
 | 
			
		||||
#define NAND_ECC_HW12_2048	7
 | 
			
		||||
typedef enum {
 | 
			
		||||
	NAND_ECC_NONE,
 | 
			
		||||
	NAND_ECC_SOFT,
 | 
			
		||||
	NAND_ECC_HW,
 | 
			
		||||
	NAND_ECC_HW_SYNDROME,
 | 
			
		||||
} nand_ecc_modes_t;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Constants for Hardware ECC
 | 
			
		||||
*/
 | 
			
		||||
 */
 | 
			
		||||
/* Reset Hardware ECC for read */
 | 
			
		||||
#define NAND_ECC_READ		0
 | 
			
		||||
/* Reset Hardware ECC for write */
 | 
			
		||||
@ -146,6 +146,10 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_
 | 
			
		||||
/* Enable Hardware ECC before syndrom is read back from flash */
 | 
			
		||||
#define NAND_ECC_READSYN	2
 | 
			
		||||
 | 
			
		||||
/* Bit mask for flags passed to do_nand_read_ecc */
 | 
			
		||||
#define NAND_GET_DEVICE		0x80
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Option constants for bizarre disfunctionality and real
 | 
			
		||||
*  features
 | 
			
		||||
*/
 | 
			
		||||
@ -165,6 +169,17 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_
 | 
			
		||||
/* Chip has a array of 4 pages which can be read without
 | 
			
		||||
 * additional ready /busy waits */
 | 
			
		||||
#define NAND_4PAGE_ARRAY	0x00000040
 | 
			
		||||
/* Chip requires that BBT is periodically rewritten to prevent
 | 
			
		||||
 * bits from adjacent blocks from 'leaking' in altering data.
 | 
			
		||||
 * This happens with the Renesas AG-AND chips, possibly others.  */
 | 
			
		||||
#define BBT_AUTO_REFRESH	0x00000080
 | 
			
		||||
/* Chip does not require ready check on read. True
 | 
			
		||||
 * for all large page devices, as they do not support
 | 
			
		||||
 * autoincrement.*/
 | 
			
		||||
#define NAND_NO_READRDY		0x00000100
 | 
			
		||||
/* Chip does not allow subpage writes */
 | 
			
		||||
#define NAND_NO_SUBPAGE_WRITE	0x00000200
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Options valid for Samsung large page devices */
 | 
			
		||||
#define NAND_SAMSUNG_LP_OPTIONS \
 | 
			
		||||
@ -183,18 +198,18 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_
 | 
			
		||||
/* Use a flash based bad block table. This option is passed to the
 | 
			
		||||
 * default bad block table function. */
 | 
			
		||||
#define NAND_USE_FLASH_BBT	0x00010000
 | 
			
		||||
/* The hw ecc generator provides a syndrome instead a ecc value on read
 | 
			
		||||
 * This can only work if we have the ecc bytes directly behind the
 | 
			
		||||
 * data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */
 | 
			
		||||
#define NAND_HWECC_SYNDROME	0x00020000
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* This option skips the bbt scan during initialization. */
 | 
			
		||||
#define NAND_SKIP_BBTSCAN	0x00020000
 | 
			
		||||
/* This option is defined if the board driver allocates its own buffers
 | 
			
		||||
   (e.g. because it needs them DMA-coherent */
 | 
			
		||||
#define NAND_OWN_BUFFERS	0x00040000
 | 
			
		||||
/* Options set by nand scan */
 | 
			
		||||
/* Nand scan has allocated oob_buf */
 | 
			
		||||
#define NAND_OOBBUF_ALLOC	0x40000000
 | 
			
		||||
/* Nand scan has allocated data_buf */
 | 
			
		||||
#define NAND_DATABUF_ALLOC	0x80000000
 | 
			
		||||
/* Nand scan has allocated controller struct */
 | 
			
		||||
#define NAND_CONTROLLER_ALLOC	0x80000000
 | 
			
		||||
 | 
			
		||||
/* Cell info constants */
 | 
			
		||||
#define NAND_CI_CHIPNR_MSK	0x03
 | 
			
		||||
#define NAND_CI_CELLTYPE_MSK	0x0C
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * nand_state_t - chip states
 | 
			
		||||
@ -207,135 +222,216 @@ typedef enum {
 | 
			
		||||
	FL_ERASING,
 | 
			
		||||
	FL_SYNCING,
 | 
			
		||||
	FL_CACHEDPRG,
 | 
			
		||||
	FL_PM_SUSPENDED,
 | 
			
		||||
} nand_state_t;
 | 
			
		||||
 | 
			
		||||
/* Keep gcc happy */
 | 
			
		||||
struct nand_chip;
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
/**
 | 
			
		||||
 * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independend devices
 | 
			
		||||
 * @lock:		protection lock
 | 
			
		||||
 * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices
 | 
			
		||||
 * @lock:               protection lock
 | 
			
		||||
 * @active:		the mtd device which holds the controller currently
 | 
			
		||||
 * @wq:			wait queue to sleep on if a NAND operation is in progress
 | 
			
		||||
 *                      used instead of the per chip wait queue when a hw controller is available
 | 
			
		||||
 */
 | 
			
		||||
struct nand_hw_control {
 | 
			
		||||
	spinlock_t	 lock;
 | 
			
		||||
	struct nand_chip *active;
 | 
			
		||||
};
 | 
			
		||||
#if 0
 | 
			
		||||
    spinlock_t	 lock;
 | 
			
		||||
    wait_queue_head_t wq;
 | 
			
		||||
#endif
 | 
			
		||||
    struct nand_chip *active;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct nand_ecc_ctrl - Control structure for ecc
 | 
			
		||||
 * @mode:	ecc mode
 | 
			
		||||
 * @steps:	number of ecc steps per page
 | 
			
		||||
 * @size:	data bytes per ecc step
 | 
			
		||||
 * @bytes:	ecc bytes per step
 | 
			
		||||
 * @total:	total number of ecc bytes per page
 | 
			
		||||
 * @prepad:	padding information for syndrome based ecc generators
 | 
			
		||||
 * @postpad:	padding information for syndrome based ecc generators
 | 
			
		||||
 * @layout:	ECC layout control struct pointer
 | 
			
		||||
 * @hwctl:	function to control hardware ecc generator. Must only
 | 
			
		||||
 *		be provided if an hardware ECC is available
 | 
			
		||||
 * @calculate:	function for ecc calculation or readback from ecc hardware
 | 
			
		||||
 * @correct:	function for ecc correction, matching to ecc generator (sw/hw)
 | 
			
		||||
 * @read_page_raw:	function to read a raw page without ECC
 | 
			
		||||
 * @write_page_raw:	function to write a raw page without ECC
 | 
			
		||||
 * @read_page:	function to read a page according to the ecc generator requirements
 | 
			
		||||
 * @write_page:	function to write a page according to the ecc generator requirements
 | 
			
		||||
 * @read_oob:	function to read chip OOB data
 | 
			
		||||
 * @write_oob:	function to write chip OOB data
 | 
			
		||||
 */
 | 
			
		||||
struct nand_ecc_ctrl {
 | 
			
		||||
	nand_ecc_modes_t	mode;
 | 
			
		||||
	int			steps;
 | 
			
		||||
	int			size;
 | 
			
		||||
	int			bytes;
 | 
			
		||||
	int			total;
 | 
			
		||||
	int			prepad;
 | 
			
		||||
	int			postpad;
 | 
			
		||||
	struct nand_ecclayout	*layout;
 | 
			
		||||
	void			(*hwctl)(struct mtd_info *mtd, int mode);
 | 
			
		||||
	int			(*calculate)(struct mtd_info *mtd,
 | 
			
		||||
					     const uint8_t *dat,
 | 
			
		||||
					     uint8_t *ecc_code);
 | 
			
		||||
	int			(*correct)(struct mtd_info *mtd, uint8_t *dat,
 | 
			
		||||
					   uint8_t *read_ecc,
 | 
			
		||||
					   uint8_t *calc_ecc);
 | 
			
		||||
	int			(*read_page_raw)(struct mtd_info *mtd,
 | 
			
		||||
						 struct nand_chip *chip,
 | 
			
		||||
						 uint8_t *buf);
 | 
			
		||||
	void			(*write_page_raw)(struct mtd_info *mtd,
 | 
			
		||||
						  struct nand_chip *chip,
 | 
			
		||||
						  const uint8_t *buf);
 | 
			
		||||
	int			(*read_page)(struct mtd_info *mtd,
 | 
			
		||||
					     struct nand_chip *chip,
 | 
			
		||||
					     uint8_t *buf);
 | 
			
		||||
	void			(*write_page)(struct mtd_info *mtd,
 | 
			
		||||
					      struct nand_chip *chip,
 | 
			
		||||
					      const uint8_t *buf);
 | 
			
		||||
	int			(*read_oob)(struct mtd_info *mtd,
 | 
			
		||||
					    struct nand_chip *chip,
 | 
			
		||||
					    int page,
 | 
			
		||||
					    int sndcmd);
 | 
			
		||||
	int			(*write_oob)(struct mtd_info *mtd,
 | 
			
		||||
					     struct nand_chip *chip,
 | 
			
		||||
					     int page);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct nand_buffers - buffer structure for read/write
 | 
			
		||||
 * @ecccalc:	buffer for calculated ecc
 | 
			
		||||
 * @ecccode:	buffer for ecc read from flash
 | 
			
		||||
 * @databuf:	buffer for data - dynamically sized
 | 
			
		||||
 *
 | 
			
		||||
 * Do not change the order of buffers. databuf and oobrbuf must be in
 | 
			
		||||
 * consecutive order.
 | 
			
		||||
 */
 | 
			
		||||
struct nand_buffers {
 | 
			
		||||
	uint8_t	ecccalc[NAND_MAX_OOBSIZE];
 | 
			
		||||
	uint8_t	ecccode[NAND_MAX_OOBSIZE];
 | 
			
		||||
	uint8_t databuf[NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct nand_chip - NAND Private Flash Chip Data
 | 
			
		||||
 * @IO_ADDR_R:		[BOARDSPECIFIC] address to read the 8 I/O lines of the flash device
 | 
			
		||||
 * @IO_ADDR_W:		[BOARDSPECIFIC] address to write the 8 I/O lines of the flash device
 | 
			
		||||
 * @read_byte:		[REPLACEABLE] read one byte from the chip
 | 
			
		||||
 * @write_byte:		[REPLACEABLE] write one byte to the chip
 | 
			
		||||
 * @read_word:		[REPLACEABLE] read one word from the chip
 | 
			
		||||
 * @write_word:		[REPLACEABLE] write one word to the chip
 | 
			
		||||
 * @write_buf:		[REPLACEABLE] write data from the buffer to the chip
 | 
			
		||||
 * @read_buf:		[REPLACEABLE] read data from the chip into the buffer
 | 
			
		||||
 * @verify_buf:		[REPLACEABLE] verify buffer contents against the chip data
 | 
			
		||||
 * @select_chip:	[REPLACEABLE] select chip nr
 | 
			
		||||
 * @block_bad:		[REPLACEABLE] check, if the block is bad
 | 
			
		||||
 * @block_markbad:	[REPLACEABLE] mark the block bad
 | 
			
		||||
 * @hwcontrol:		[BOARDSPECIFIC] hardwarespecific function for accesing control-lines
 | 
			
		||||
 * @cmd_ctrl:		[BOARDSPECIFIC] hardwarespecific funtion for controlling
 | 
			
		||||
 *			ALE/CLE/nCE. Also used to write command and address
 | 
			
		||||
 * @dev_ready:		[BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line
 | 
			
		||||
 *			If set to NULL no access to ready/busy is available and the ready/busy information
 | 
			
		||||
 *			is read from the chip status register
 | 
			
		||||
 * @cmdfunc:		[REPLACEABLE] hardwarespecific function for writing commands to the chip
 | 
			
		||||
 * @waitfunc:		[REPLACEABLE] hardwarespecific function for wait on ready
 | 
			
		||||
 * @calculate_ecc:	[REPLACEABLE] function for ecc calculation or readback from ecc hardware
 | 
			
		||||
 * @correct_data:	[REPLACEABLE] function for ecc correction, matching to ecc generator (sw/hw)
 | 
			
		||||
 * @enable_hwecc:	[BOARDSPECIFIC] function to enable (reset) hardware ecc generator. Must only
 | 
			
		||||
 *			be provided if a hardware ECC is available
 | 
			
		||||
 * @ecc:		[BOARDSPECIFIC] ecc control ctructure
 | 
			
		||||
 * @buffers:		buffer structure for read/write
 | 
			
		||||
 * @hwcontrol:		platform-specific hardware control structure
 | 
			
		||||
 * @ops:		oob operation operands
 | 
			
		||||
 * @erase_cmd:		[INTERN] erase command write function, selectable due to AND support
 | 
			
		||||
 * @scan_bbt:		[REPLACEABLE] function to scan bad block table
 | 
			
		||||
 * @eccmode:		[BOARDSPECIFIC] mode of ecc, see defines
 | 
			
		||||
 * @eccsize:		[INTERN] databytes used per ecc-calculation
 | 
			
		||||
 * @eccbytes:		[INTERN] number of ecc bytes per ecc-calculation step
 | 
			
		||||
 * @eccsteps:		[INTERN] number of ecc calculation steps per page
 | 
			
		||||
 * @chip_delay:		[BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR)
 | 
			
		||||
 * @chip_lock:		[INTERN] spinlock used to protect access to this structure and the chip
 | 
			
		||||
 * @wq:			[INTERN] wait queue to sleep on if a NAND operation is in progress
 | 
			
		||||
 * @state:		[INTERN] the current state of the NAND device
 | 
			
		||||
 * @oob_poi:		poison value buffer
 | 
			
		||||
 * @page_shift:		[INTERN] number of address bits in a page (column address bits)
 | 
			
		||||
 * @phys_erase_shift:	[INTERN] number of address bits in a physical eraseblock
 | 
			
		||||
 * @bbt_erase_shift:	[INTERN] number of address bits in a bbt entry
 | 
			
		||||
 * @chip_shift:		[INTERN] number of address bits in one chip
 | 
			
		||||
 * @data_buf:		[INTERN] internal buffer for one page + oob
 | 
			
		||||
 * @oob_buf:		[INTERN] oob buffer for one eraseblock
 | 
			
		||||
 * @datbuf:		[INTERN] internal buffer for one page + oob
 | 
			
		||||
 * @oobbuf:		[INTERN] oob buffer for one eraseblock
 | 
			
		||||
 * @oobdirty:		[INTERN] indicates that oob_buf must be reinitialized
 | 
			
		||||
 * @data_poi:		[INTERN] pointer to a data buffer
 | 
			
		||||
 * @options:		[BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about
 | 
			
		||||
 *			special functionality. See the defines for further explanation
 | 
			
		||||
 * @badblockpos:	[INTERN] position of the bad block marker in the oob area
 | 
			
		||||
 * @cellinfo:		[INTERN] MLC/multichip data from chip ident
 | 
			
		||||
 * @numchips:		[INTERN] number of physical chips
 | 
			
		||||
 * @chipsize:		[INTERN] the size of one chip for multichip arrays
 | 
			
		||||
 * @pagemask:		[INTERN] page number mask = number of (pages / chip) - 1
 | 
			
		||||
 * @pagebuf:		[INTERN] holds the pagenumber which is currently in data_buf
 | 
			
		||||
 * @autooob:		[REPLACEABLE] the default (auto)placement scheme
 | 
			
		||||
 * @subpagesize:	[INTERN] holds the subpagesize
 | 
			
		||||
 * @ecclayout:		[REPLACEABLE] the default ecc placement scheme
 | 
			
		||||
 * @bbt:		[INTERN] bad block table pointer
 | 
			
		||||
 * @bbt_td:		[REPLACEABLE] bad block table descriptor for flash lookup
 | 
			
		||||
 * @bbt_md:		[REPLACEABLE] bad block table mirror descriptor
 | 
			
		||||
 * @badblock_pattern:	[REPLACEABLE] bad block scan pattern used for initial bad block scan
 | 
			
		||||
 * @controller:		[OPTIONAL] a pointer to a hardware controller structure which is shared among multiple independend devices
 | 
			
		||||
 * @controller:		[REPLACEABLE] a pointer to a hardware controller structure
 | 
			
		||||
 *			which is shared among multiple independend devices
 | 
			
		||||
 * @priv:		[OPTIONAL] pointer to private chip date
 | 
			
		||||
 * @errstat:		[OPTIONAL] hardware specific function to perform additional error status checks
 | 
			
		||||
 *			(determine if errors are correctable)
 | 
			
		||||
 * @write_page:		[REPLACEABLE] High-level page write function
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
struct nand_chip {
 | 
			
		||||
	void  __iomem	*IO_ADDR_R;
 | 
			
		||||
	void  __iomem	*IO_ADDR_W;
 | 
			
		||||
 | 
			
		||||
	u_char		(*read_byte)(struct mtd_info *mtd);
 | 
			
		||||
	void		(*write_byte)(struct mtd_info *mtd, u_char byte);
 | 
			
		||||
	uint8_t		(*read_byte)(struct mtd_info *mtd);
 | 
			
		||||
	u16		(*read_word)(struct mtd_info *mtd);
 | 
			
		||||
	void		(*write_word)(struct mtd_info *mtd, u16 word);
 | 
			
		||||
 | 
			
		||||
	void		(*write_buf)(struct mtd_info *mtd, const u_char *buf, int len);
 | 
			
		||||
	void		(*read_buf)(struct mtd_info *mtd, u_char *buf, int len);
 | 
			
		||||
	int		(*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len);
 | 
			
		||||
	void		(*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
 | 
			
		||||
	void		(*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
 | 
			
		||||
	int		(*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
 | 
			
		||||
	void		(*select_chip)(struct mtd_info *mtd, int chip);
 | 
			
		||||
	int		(*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
 | 
			
		||||
	int		(*block_markbad)(struct mtd_info *mtd, loff_t ofs);
 | 
			
		||||
	void		(*hwcontrol)(struct mtd_info *mtd, int cmd);
 | 
			
		||||
	void		(*cmd_ctrl)(struct mtd_info *mtd, int dat,
 | 
			
		||||
				    unsigned int ctrl);
 | 
			
		||||
	int		(*dev_ready)(struct mtd_info *mtd);
 | 
			
		||||
	void		(*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
 | 
			
		||||
	int		(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state);
 | 
			
		||||
	int		(*calculate_ecc)(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code);
 | 
			
		||||
	int		(*correct_data)(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
 | 
			
		||||
	void		(*enable_hwecc)(struct mtd_info *mtd, int mode);
 | 
			
		||||
	int		(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this);
 | 
			
		||||
	void		(*erase_cmd)(struct mtd_info *mtd, int page);
 | 
			
		||||
	int		(*scan_bbt)(struct mtd_info *mtd);
 | 
			
		||||
	int		eccmode;
 | 
			
		||||
	int		eccsize;
 | 
			
		||||
	int		eccbytes;
 | 
			
		||||
	int		eccsteps;
 | 
			
		||||
	int		(*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page);
 | 
			
		||||
	int		(*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
 | 
			
		||||
				      const uint8_t *buf, int page, int cached, int raw);
 | 
			
		||||
 | 
			
		||||
	int		chip_delay;
 | 
			
		||||
#if 0
 | 
			
		||||
	spinlock_t	chip_lock;
 | 
			
		||||
	wait_queue_head_t wq;
 | 
			
		||||
	nand_state_t	state;
 | 
			
		||||
#endif
 | 
			
		||||
	unsigned int	options;
 | 
			
		||||
 | 
			
		||||
	int		page_shift;
 | 
			
		||||
	int		phys_erase_shift;
 | 
			
		||||
	int		bbt_erase_shift;
 | 
			
		||||
	int		chip_shift;
 | 
			
		||||
	u_char		*data_buf;
 | 
			
		||||
	u_char		*oob_buf;
 | 
			
		||||
	int		oobdirty;
 | 
			
		||||
	u_char		*data_poi;
 | 
			
		||||
	unsigned int	options;
 | 
			
		||||
	int		badblockpos;
 | 
			
		||||
	int		numchips;
 | 
			
		||||
	unsigned long	chipsize;
 | 
			
		||||
	int		pagemask;
 | 
			
		||||
	int		pagebuf;
 | 
			
		||||
	struct nand_oobinfo	*autooob;
 | 
			
		||||
	int		subpagesize;
 | 
			
		||||
	uint8_t		cellinfo;
 | 
			
		||||
	int		badblockpos;
 | 
			
		||||
 | 
			
		||||
	nand_state_t	state;
 | 
			
		||||
 | 
			
		||||
	uint8_t		*oob_poi;
 | 
			
		||||
	struct nand_hw_control  *controller;
 | 
			
		||||
	struct nand_ecclayout	*ecclayout;
 | 
			
		||||
 | 
			
		||||
	struct nand_ecc_ctrl ecc;
 | 
			
		||||
	struct nand_buffers *buffers;
 | 
			
		||||
	
 | 
			
		||||
	struct nand_hw_control hwcontrol;
 | 
			
		||||
 | 
			
		||||
	struct mtd_oob_ops ops;
 | 
			
		||||
 | 
			
		||||
	uint8_t		*bbt;
 | 
			
		||||
	struct nand_bbt_descr	*bbt_td;
 | 
			
		||||
	struct nand_bbt_descr	*bbt_md;
 | 
			
		||||
 | 
			
		||||
	struct nand_bbt_descr	*badblock_pattern;
 | 
			
		||||
	struct nand_hw_control	*controller;
 | 
			
		||||
 | 
			
		||||
	void		*priv;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -348,11 +444,11 @@ struct nand_chip {
 | 
			
		||||
#define NAND_MFR_NATIONAL	0x8f
 | 
			
		||||
#define NAND_MFR_RENESAS	0x07
 | 
			
		||||
#define NAND_MFR_STMICRO	0x20
 | 
			
		||||
#define NAND_MFR_HYNIX		0xad
 | 
			
		||||
#define NAND_MFR_MICRON		0x2c
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct nand_flash_dev - NAND Flash Device ID Structure
 | 
			
		||||
 *
 | 
			
		||||
 * @name:	Identify the device type
 | 
			
		||||
 * @id:		device ID code
 | 
			
		||||
 * @pagesize:	Pagesize in bytes. Either 256 or 512 or 0
 | 
			
		||||
@ -403,7 +499,7 @@ extern struct nand_manufacturers nand_manuf_ids[];
 | 
			
		||||
 *		blocks is reserved at the end of the device where the tables are
 | 
			
		||||
 *		written.
 | 
			
		||||
 * @reserved_block_code: if non-0, this pattern denotes a reserved (rather than
 | 
			
		||||
 *		bad) block in the stored bbt
 | 
			
		||||
 *              bad) block in the stored bbt
 | 
			
		||||
 * @pattern:	pattern to identify bad block table or factory marked good /
 | 
			
		||||
 *		bad blocks, can be NULL, if len = 0
 | 
			
		||||
 *
 | 
			
		||||
@ -417,11 +513,11 @@ struct nand_bbt_descr {
 | 
			
		||||
	int	pages[NAND_MAX_CHIPS];
 | 
			
		||||
	int	offs;
 | 
			
		||||
	int	veroffs;
 | 
			
		||||
	uint8_t version[NAND_MAX_CHIPS];
 | 
			
		||||
	uint8_t	version[NAND_MAX_CHIPS];
 | 
			
		||||
	int	len;
 | 
			
		||||
	int	maxblocks;
 | 
			
		||||
	int	reserved_block_code;
 | 
			
		||||
	uint8_t *pattern;
 | 
			
		||||
	uint8_t	*pattern;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Options for the bad block table descriptors */
 | 
			
		||||
@ -433,7 +529,7 @@ struct nand_bbt_descr {
 | 
			
		||||
#define NAND_BBT_4BIT		0x00000004
 | 
			
		||||
#define NAND_BBT_8BIT		0x00000008
 | 
			
		||||
/* The bad block table is in the last good block of the device */
 | 
			
		||||
#define NAND_BBT_LASTBLOCK	0x00000010
 | 
			
		||||
#define	NAND_BBT_LASTBLOCK	0x00000010
 | 
			
		||||
/* The bbt is at the given page, else we must scan for the bbt */
 | 
			
		||||
#define NAND_BBT_ABSPAGE	0x00000020
 | 
			
		||||
/* The bbt is at the given page, else we must scan for the bbt */
 | 
			
		||||
@ -456,13 +552,16 @@ struct nand_bbt_descr {
 | 
			
		||||
#define NAND_BBT_SCAN2NDPAGE	0x00004000
 | 
			
		||||
 | 
			
		||||
/* The maximum number of blocks to scan for a bbt */
 | 
			
		||||
#define NAND_BBT_SCAN_MAXBLOCKS 4
 | 
			
		||||
#define NAND_BBT_SCAN_MAXBLOCKS	4
 | 
			
		||||
 | 
			
		||||
extern int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd);
 | 
			
		||||
extern int nand_update_bbt (struct mtd_info *mtd, loff_t offs);
 | 
			
		||||
extern int nand_default_bbt (struct mtd_info *mtd);
 | 
			
		||||
extern int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt);
 | 
			
		||||
extern int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbbt);
 | 
			
		||||
extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd);
 | 
			
		||||
extern int nand_update_bbt(struct mtd_info *mtd, loff_t offs);
 | 
			
		||||
extern int nand_default_bbt(struct mtd_info *mtd);
 | 
			
		||||
extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt);
 | 
			
		||||
extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 | 
			
		||||
			   int allowbbt);
 | 
			
		||||
extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
 | 
			
		||||
			size_t * retlen, uint8_t * buf);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
* Constants for oob configuration
 | 
			
		||||
@ -470,4 +569,67 @@ extern int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int
 | 
			
		||||
#define NAND_SMALL_BADBLOCK_POS		5
 | 
			
		||||
#define NAND_LARGE_BADBLOCK_POS		0
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct platform_nand_chip - chip level device structure
 | 
			
		||||
 * @nr_chips:		max. number of chips to scan for
 | 
			
		||||
 * @chip_offset:	chip number offset
 | 
			
		||||
 * @nr_partitions:	number of partitions pointed to by partitions (or zero)
 | 
			
		||||
 * @partitions:		mtd partition list
 | 
			
		||||
 * @chip_delay:		R/B delay value in us
 | 
			
		||||
 * @options:		Option flags, e.g. 16bit buswidth
 | 
			
		||||
 * @ecclayout:		ecc layout info structure
 | 
			
		||||
 * @part_probe_types:	NULL-terminated array of probe types
 | 
			
		||||
 * @priv:		hardware controller specific settings
 | 
			
		||||
 */
 | 
			
		||||
struct platform_nand_chip {
 | 
			
		||||
	int			nr_chips;
 | 
			
		||||
	int			chip_offset;
 | 
			
		||||
	int			nr_partitions;
 | 
			
		||||
	struct mtd_partition	*partitions;
 | 
			
		||||
	struct nand_ecclayout	*ecclayout;
 | 
			
		||||
	int			chip_delay;
 | 
			
		||||
	unsigned int		options;
 | 
			
		||||
	const char		**part_probe_types;
 | 
			
		||||
	void			*priv;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct platform_nand_ctrl - controller level device structure
 | 
			
		||||
 * @hwcontrol:		platform specific hardware control structure
 | 
			
		||||
 * @dev_ready:		platform specific function to read ready/busy pin
 | 
			
		||||
 * @select_chip:	platform specific chip select function
 | 
			
		||||
 * @cmd_ctrl:		platform specific function for controlling
 | 
			
		||||
 *			ALE/CLE/nCE. Also used to write command and address
 | 
			
		||||
 * @priv:		private data to transport driver specific settings
 | 
			
		||||
 *
 | 
			
		||||
 * All fields are optional and depend on the hardware driver requirements
 | 
			
		||||
 */
 | 
			
		||||
struct platform_nand_ctrl {
 | 
			
		||||
	void		(*hwcontrol)(struct mtd_info *mtd, int cmd);
 | 
			
		||||
	int		(*dev_ready)(struct mtd_info *mtd);
 | 
			
		||||
	void		(*select_chip)(struct mtd_info *mtd, int chip);
 | 
			
		||||
	void		(*cmd_ctrl)(struct mtd_info *mtd, int dat,
 | 
			
		||||
				    unsigned int ctrl);
 | 
			
		||||
	void		*priv;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct platform_nand_data - container structure for platform-specific data
 | 
			
		||||
 * @chip:		chip level chip structure
 | 
			
		||||
 * @ctrl:		controller level device structure
 | 
			
		||||
 */
 | 
			
		||||
struct platform_nand_data {
 | 
			
		||||
	struct platform_nand_chip	chip;
 | 
			
		||||
	struct platform_nand_ctrl	ctrl;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Some helpers to access the data structures */
 | 
			
		||||
static inline
 | 
			
		||||
struct platform_nand_chip *get_platform_nandchip(struct mtd_info *mtd)
 | 
			
		||||
{
 | 
			
		||||
	struct nand_chip *chip = mtd->priv;
 | 
			
		||||
 | 
			
		||||
	return chip->priv;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* __LINUX_MTD_NAND_H */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										76
									
								
								include/linux/mtd/nftl-user.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								include/linux/mtd/nftl-user.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,76 @@
 | 
			
		||||
/*
 | 
			
		||||
 * $Id: nftl-user.h,v 1.2 2005/11/07 11:14:56 gleixner Exp $
 | 
			
		||||
 *
 | 
			
		||||
 * Parts of NFTL headers shared with userspace
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __MTD_NFTL_USER_H__
 | 
			
		||||
#define __MTD_NFTL_USER_H__
 | 
			
		||||
 | 
			
		||||
/* Block Control Information */
 | 
			
		||||
 | 
			
		||||
struct nftl_bci {
 | 
			
		||||
	unsigned char ECCSig[6];
 | 
			
		||||
	uint8_t Status;
 | 
			
		||||
	uint8_t Status1;
 | 
			
		||||
}__attribute__((packed));
 | 
			
		||||
 | 
			
		||||
/* Unit Control Information */
 | 
			
		||||
 | 
			
		||||
struct nftl_uci0 {
 | 
			
		||||
	uint16_t VirtUnitNum;
 | 
			
		||||
	uint16_t ReplUnitNum;
 | 
			
		||||
	uint16_t SpareVirtUnitNum;
 | 
			
		||||
	uint16_t SpareReplUnitNum;
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
struct nftl_uci1 {
 | 
			
		||||
	uint32_t WearInfo;
 | 
			
		||||
	uint16_t EraseMark;
 | 
			
		||||
	uint16_t EraseMark1;
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
struct nftl_uci2 {
 | 
			
		||||
        uint16_t FoldMark;
 | 
			
		||||
        uint16_t FoldMark1;
 | 
			
		||||
	uint32_t unused;
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
union nftl_uci {
 | 
			
		||||
	struct nftl_uci0 a;
 | 
			
		||||
	struct nftl_uci1 b;
 | 
			
		||||
	struct nftl_uci2 c;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct nftl_oob {
 | 
			
		||||
	struct nftl_bci b;
 | 
			
		||||
	union nftl_uci u;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* NFTL Media Header */
 | 
			
		||||
 | 
			
		||||
struct NFTLMediaHeader {
 | 
			
		||||
	char DataOrgID[6];
 | 
			
		||||
	uint16_t NumEraseUnits;
 | 
			
		||||
	uint16_t FirstPhysicalEUN;
 | 
			
		||||
	uint32_t FormattedSize;
 | 
			
		||||
	unsigned char UnitSizeFactor;
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
#define MAX_ERASE_ZONES (8192 - 512)
 | 
			
		||||
 | 
			
		||||
#define ERASE_MARK 0x3c69
 | 
			
		||||
#define SECTOR_FREE 0xff
 | 
			
		||||
#define SECTOR_USED 0x55
 | 
			
		||||
#define SECTOR_IGNORE 0x11
 | 
			
		||||
#define SECTOR_DELETED 0x00
 | 
			
		||||
 | 
			
		||||
#define FOLD_MARK_IN_PROGRESS 0x5555
 | 
			
		||||
 | 
			
		||||
#define ZONE_GOOD 0xff
 | 
			
		||||
#define ZONE_BAD_ORIGINAL 0
 | 
			
		||||
#define ZONE_BAD_MARKED 7
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* __MTD_NFTL_USER_H__ */
 | 
			
		||||
@ -1,75 +1,16 @@
 | 
			
		||||
 | 
			
		||||
/* Defines for NAND Flash Translation Layer  */
 | 
			
		||||
/* (c) 1999 Machine Vision Holdings, Inc.    */
 | 
			
		||||
/* Author: David Woodhouse <dwmw2@mvhi.com>  */
 | 
			
		||||
/* $Id: nftl.h,v 1.10 2000/12/29 00:25:38 dwmw2 Exp $ */
 | 
			
		||||
/*
 | 
			
		||||
 * $Id: nftl.h,v 1.16 2004/06/30 14:49:00 dbrown Exp $
 | 
			
		||||
 *
 | 
			
		||||
 * (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __MTD_NFTL_H__
 | 
			
		||||
#define __MTD_NFTL_H__
 | 
			
		||||
 | 
			
		||||
/* Block Control Information */
 | 
			
		||||
#include <linux/mtd/mtd.h>
 | 
			
		||||
#include <linux/mtd/blktrans.h>
 | 
			
		||||
 | 
			
		||||
struct nftl_bci {
 | 
			
		||||
	unsigned char ECCSig[6];
 | 
			
		||||
	__u8 Status;
 | 
			
		||||
	__u8 Status1;
 | 
			
		||||
}__attribute__((packed));
 | 
			
		||||
 | 
			
		||||
/* Unit Control Information */
 | 
			
		||||
 | 
			
		||||
struct nftl_uci0 {
 | 
			
		||||
	__u16 VirtUnitNum;
 | 
			
		||||
	__u16 ReplUnitNum;
 | 
			
		||||
	__u16 SpareVirtUnitNum;
 | 
			
		||||
	__u16 SpareReplUnitNum;
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
struct nftl_uci1 {
 | 
			
		||||
	__u32 WearInfo;
 | 
			
		||||
	__u16 EraseMark;
 | 
			
		||||
	__u16 EraseMark1;
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
struct nftl_uci2 {
 | 
			
		||||
	__u16 FoldMark;
 | 
			
		||||
	__u16 FoldMark1;
 | 
			
		||||
	__u32 unused;
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
union nftl_uci {
 | 
			
		||||
	struct nftl_uci0 a;
 | 
			
		||||
	struct nftl_uci1 b;
 | 
			
		||||
	struct nftl_uci2 c;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct nftl_oob {
 | 
			
		||||
	struct nftl_bci b;
 | 
			
		||||
	union nftl_uci u;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* NFTL Media Header */
 | 
			
		||||
 | 
			
		||||
struct NFTLMediaHeader {
 | 
			
		||||
	char DataOrgID[6];
 | 
			
		||||
	__u16 NumEraseUnits;
 | 
			
		||||
	__u16 FirstPhysicalEUN;
 | 
			
		||||
	__u32 FormattedSize;
 | 
			
		||||
	unsigned char UnitSizeFactor;
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
#define MAX_ERASE_ZONES (8192 - 512)
 | 
			
		||||
 | 
			
		||||
#define ERASE_MARK 0x3c69
 | 
			
		||||
#define SECTOR_FREE 0xff
 | 
			
		||||
#define SECTOR_USED 0x55
 | 
			
		||||
#define SECTOR_IGNORE 0x11
 | 
			
		||||
#define SECTOR_DELETED 0x00
 | 
			
		||||
 | 
			
		||||
#define FOLD_MARK_IN_PROGRESS 0x5555
 | 
			
		||||
 | 
			
		||||
#define ZONE_GOOD 0xff
 | 
			
		||||
#define ZONE_BAD_ORIGINAL 0
 | 
			
		||||
#define ZONE_BAD_MARKED 7
 | 
			
		||||
#include <linux/mtd/nftl-user.h>
 | 
			
		||||
 | 
			
		||||
/* these info are used in ReplUnitTable */
 | 
			
		||||
#define BLOCK_NIL          0xffff /* last block of a chain */
 | 
			
		||||
@ -78,7 +19,7 @@ struct NFTLMediaHeader {
 | 
			
		||||
#define BLOCK_RESERVED     0xfffc /* bios block or bad block */
 | 
			
		||||
 | 
			
		||||
struct NFTLrecord {
 | 
			
		||||
	struct DiskOnChip *mtd;
 | 
			
		||||
	struct mtd_blktrans_dev mbd;
 | 
			
		||||
	__u16 MediaUnit, SpareMediaUnit;
 | 
			
		||||
	__u32 EraseSize;
 | 
			
		||||
	struct NFTLMediaHeader MediaHdr;
 | 
			
		||||
@ -90,16 +31,24 @@ struct NFTLrecord {
 | 
			
		||||
	__u16 lastEUN;                  /* should be suppressed */
 | 
			
		||||
	__u16 numfreeEUNs;
 | 
			
		||||
	__u16 LastFreeEUN;		/* To speed up finding a free EUN */
 | 
			
		||||
	__u32 nr_sects;
 | 
			
		||||
	int head,sect,cyl;
 | 
			
		||||
	__u16 *EUNtable;		/* [numvunits]: First EUN for each virtual unit  */
 | 
			
		||||
	__u16 *ReplUnitTable;		/* [numEUNs]: ReplUnitNumber for each */
 | 
			
		||||
	unsigned int nb_blocks;		/* number of physical blocks */
 | 
			
		||||
	unsigned int nb_boot_blocks;	/* number of blocks used by the bios */
 | 
			
		||||
        unsigned int nb_blocks;		/* number of physical blocks */
 | 
			
		||||
        unsigned int nb_boot_blocks;	/* number of blocks used by the bios */
 | 
			
		||||
        struct erase_info instr;
 | 
			
		||||
	struct nand_ecclayout oobinfo;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int NFTL_mount(struct NFTLrecord *s);
 | 
			
		||||
int NFTL_formatblock(struct NFTLrecord *s, int block);
 | 
			
		||||
 | 
			
		||||
#ifndef NFTL_MAJOR
 | 
			
		||||
#define NFTL_MAJOR 93
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define MAX_NFTLS 16
 | 
			
		||||
#define MAX_SECTORS_PER_UNIT 32
 | 
			
		||||
#define MAX_SECTORS_PER_UNIT 64
 | 
			
		||||
#define NFTL_PARTN_BITS 4
 | 
			
		||||
 | 
			
		||||
#endif /* __MTD_NFTL_H__ */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										360
									
								
								include/linux/mtd/ubi-header.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										360
									
								
								include/linux/mtd/ubi-header.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,360 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) International Business Machines Corp., 2006
 | 
			
		||||
 *
 | 
			
		||||
 * 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
 | 
			
		||||
 *
 | 
			
		||||
 * Authors: Artem Bityutskiy (Битюцкий Артём)
 | 
			
		||||
 *          Thomas Gleixner
 | 
			
		||||
 *          Frank Haverkamp
 | 
			
		||||
 *          Oliver Lohmann
 | 
			
		||||
 *          Andreas Arnez
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This file defines the layout of UBI headers and all the other UBI on-flash
 | 
			
		||||
 * data structures. May be included by user-space.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __UBI_HEADER_H__
 | 
			
		||||
#define __UBI_HEADER_H__
 | 
			
		||||
 | 
			
		||||
#include <asm/byteorder.h>
 | 
			
		||||
 | 
			
		||||
/* The version of UBI images supported by this implementation */
 | 
			
		||||
#define UBI_VERSION 1
 | 
			
		||||
 | 
			
		||||
/* The highest erase counter value supported by this implementation */
 | 
			
		||||
#define UBI_MAX_ERASECOUNTER 0x7FFFFFFF
 | 
			
		||||
 | 
			
		||||
/* The initial CRC32 value used when calculating CRC checksums */
 | 
			
		||||
#define UBI_CRC32_INIT 0xFFFFFFFFU
 | 
			
		||||
 | 
			
		||||
/* Erase counter header magic number (ASCII "UBI#") */
 | 
			
		||||
#define UBI_EC_HDR_MAGIC  0x55424923
 | 
			
		||||
/* Volume identifier header magic number (ASCII "UBI!") */
 | 
			
		||||
#define UBI_VID_HDR_MAGIC 0x55424921
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Volume type constants used in the volume identifier header.
 | 
			
		||||
 *
 | 
			
		||||
 * @UBI_VID_DYNAMIC: dynamic volume
 | 
			
		||||
 * @UBI_VID_STATIC: static volume
 | 
			
		||||
 */
 | 
			
		||||
enum {
 | 
			
		||||
	UBI_VID_DYNAMIC = 1,
 | 
			
		||||
	UBI_VID_STATIC  = 2
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Compatibility constants used by internal volumes.
 | 
			
		||||
 *
 | 
			
		||||
 * @UBI_COMPAT_DELETE: delete this internal volume before anything is written
 | 
			
		||||
 * to the flash
 | 
			
		||||
 * @UBI_COMPAT_RO: attach this device in read-only mode
 | 
			
		||||
 * @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its
 | 
			
		||||
 * physical eraseblocks, don't allow the wear-leveling unit to move them
 | 
			
		||||
 * @UBI_COMPAT_REJECT: reject this UBI image
 | 
			
		||||
 */
 | 
			
		||||
enum {
 | 
			
		||||
	UBI_COMPAT_DELETE   = 1,
 | 
			
		||||
	UBI_COMPAT_RO       = 2,
 | 
			
		||||
	UBI_COMPAT_PRESERVE = 4,
 | 
			
		||||
	UBI_COMPAT_REJECT   = 5
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * ubi16_t/ubi32_t/ubi64_t - 16, 32, and 64-bit integers used in UBI on-flash
 | 
			
		||||
 * data structures.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct {
 | 
			
		||||
	uint16_t int16;
 | 
			
		||||
} __attribute__ ((packed)) ubi16_t;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
	uint32_t int32;
 | 
			
		||||
} __attribute__ ((packed)) ubi32_t;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
	uint64_t int64;
 | 
			
		||||
} __attribute__ ((packed)) ubi64_t;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * In this implementation of UBI uses the big-endian format for on-flash
 | 
			
		||||
 * integers. The below are the corresponding conversion macros.
 | 
			
		||||
 */
 | 
			
		||||
#define cpu_to_ubi16(x) ((ubi16_t){__cpu_to_be16(x)})
 | 
			
		||||
#define ubi16_to_cpu(x) ((uint16_t)__be16_to_cpu((x).int16))
 | 
			
		||||
 | 
			
		||||
#define cpu_to_ubi32(x) ((ubi32_t){__cpu_to_be32(x)})
 | 
			
		||||
#define ubi32_to_cpu(x) ((uint32_t)__be32_to_cpu((x).int32))
 | 
			
		||||
 | 
			
		||||
#define cpu_to_ubi64(x) ((ubi64_t){__cpu_to_be64(x)})
 | 
			
		||||
#define ubi64_to_cpu(x) ((uint64_t)__be64_to_cpu((x).int64))
 | 
			
		||||
 | 
			
		||||
/* Sizes of UBI headers */
 | 
			
		||||
#define UBI_EC_HDR_SIZE  sizeof(struct ubi_ec_hdr)
 | 
			
		||||
#define UBI_VID_HDR_SIZE sizeof(struct ubi_vid_hdr)
 | 
			
		||||
 | 
			
		||||
/* Sizes of UBI headers without the ending CRC */
 | 
			
		||||
#define UBI_EC_HDR_SIZE_CRC  (UBI_EC_HDR_SIZE  - sizeof(ubi32_t))
 | 
			
		||||
#define UBI_VID_HDR_SIZE_CRC (UBI_VID_HDR_SIZE - sizeof(ubi32_t))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct ubi_ec_hdr - UBI erase counter header.
 | 
			
		||||
 * @magic: erase counter header magic number (%UBI_EC_HDR_MAGIC)
 | 
			
		||||
 * @version: version of UBI implementation which is supposed to accept this
 | 
			
		||||
 * UBI image
 | 
			
		||||
 * @padding1: reserved for future, zeroes
 | 
			
		||||
 * @ec: the erase counter
 | 
			
		||||
 * @vid_hdr_offset: where the VID header starts
 | 
			
		||||
 * @data_offset: where the user data start
 | 
			
		||||
 * @padding2: reserved for future, zeroes
 | 
			
		||||
 * @hdr_crc: erase counter header CRC checksum
 | 
			
		||||
 *
 | 
			
		||||
 * The erase counter header takes 64 bytes and has a plenty of unused space for
 | 
			
		||||
 * future usage. The unused fields are zeroed. The @version field is used to
 | 
			
		||||
 * indicate the version of UBI implementation which is supposed to be able to
 | 
			
		||||
 * work with this UBI image. If @version is greater then the current UBI
 | 
			
		||||
 * version, the image is rejected. This may be useful in future if something
 | 
			
		||||
 * is changed radically. This field is duplicated in the volume identifier
 | 
			
		||||
 * header.
 | 
			
		||||
 *
 | 
			
		||||
 * The @vid_hdr_offset and @data_offset fields contain the offset of the the
 | 
			
		||||
 * volume identifier header and user data, relative to the beginning of the
 | 
			
		||||
 * physical eraseblock. These values have to be the same for all physical
 | 
			
		||||
 * eraseblocks.
 | 
			
		||||
 */
 | 
			
		||||
struct ubi_ec_hdr {
 | 
			
		||||
	ubi32_t magic;
 | 
			
		||||
	uint8_t version;
 | 
			
		||||
	uint8_t padding1[3];
 | 
			
		||||
	ubi64_t ec; /* Warning: the current limit is 31-bit anyway! */
 | 
			
		||||
	ubi32_t vid_hdr_offset;
 | 
			
		||||
	ubi32_t data_offset;
 | 
			
		||||
	uint8_t padding2[36];
 | 
			
		||||
	ubi32_t hdr_crc;
 | 
			
		||||
} __attribute__ ((packed));
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct ubi_vid_hdr - on-flash UBI volume identifier header.
 | 
			
		||||
 * @magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC)
 | 
			
		||||
 * @version: UBI implementation version which is supposed to accept this UBI
 | 
			
		||||
 * image (%UBI_VERSION)
 | 
			
		||||
 * @vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC)
 | 
			
		||||
 * @copy_flag: if this logical eraseblock was copied from another physical
 | 
			
		||||
 * eraseblock (for wear-leveling reasons)
 | 
			
		||||
 * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE,
 | 
			
		||||
 * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
 | 
			
		||||
 * @vol_id: ID of this volume
 | 
			
		||||
 * @lnum: logical eraseblock number
 | 
			
		||||
 * @leb_ver: version of this logical eraseblock (IMPORTANT: obsolete, to be
 | 
			
		||||
 * removed, kept only for not breaking older UBI users)
 | 
			
		||||
 * @data_size: how many bytes of data this logical eraseblock contains
 | 
			
		||||
 * @used_ebs: total number of used logical eraseblocks in this volume
 | 
			
		||||
 * @data_pad: how many bytes at the end of this physical eraseblock are not
 | 
			
		||||
 * used
 | 
			
		||||
 * @data_crc: CRC checksum of the data stored in this logical eraseblock
 | 
			
		||||
 * @padding1: reserved for future, zeroes
 | 
			
		||||
 * @sqnum: sequence number
 | 
			
		||||
 * @padding2: reserved for future, zeroes
 | 
			
		||||
 * @hdr_crc: volume identifier header CRC checksum
 | 
			
		||||
 *
 | 
			
		||||
 * The @sqnum is the value of the global sequence counter at the time when this
 | 
			
		||||
 * VID header was created. The global sequence counter is incremented each time
 | 
			
		||||
 * UBI writes a new VID header to the flash, i.e. when it maps a logical
 | 
			
		||||
 * eraseblock to a new physical eraseblock. The global sequence counter is an
 | 
			
		||||
 * unsigned 64-bit integer and we assume it never overflows. The @sqnum
 | 
			
		||||
 * (sequence number) is used to distinguish between older and newer versions of
 | 
			
		||||
 * logical eraseblocks.
 | 
			
		||||
 *
 | 
			
		||||
 * There are 2 situations when there may be more then one physical eraseblock
 | 
			
		||||
 * corresponding to the same logical eraseblock, i.e., having the same @vol_id
 | 
			
		||||
 * and @lnum values in the volume identifier header. Suppose we have a logical
 | 
			
		||||
 * eraseblock L and it is mapped to the physical eraseblock P.
 | 
			
		||||
 *
 | 
			
		||||
 * 1. Because UBI may erase physical eraseblocks asynchronously, the following
 | 
			
		||||
 * situation is possible: L is asynchronously erased, so P is scheduled for
 | 
			
		||||
 * erasure, then L is written to,i.e. mapped to another physical eraseblock P1,
 | 
			
		||||
 * so P1 is written to, then an unclean reboot happens. Result - there are 2
 | 
			
		||||
 * physical eraseblocks P and P1 corresponding to the same logical eraseblock
 | 
			
		||||
 * L. But P1 has greater sequence number, so UBI picks P1 when it attaches the
 | 
			
		||||
 * flash.
 | 
			
		||||
 *
 | 
			
		||||
 * 2. From time to time UBI moves logical eraseblocks to other physical
 | 
			
		||||
 * eraseblocks for wear-leveling reasons. If, for example, UBI moves L from P
 | 
			
		||||
 * to P1, and an unclean reboot happens before P is physically erased, there
 | 
			
		||||
 * are two physical eraseblocks P and P1 corresponding to L and UBI has to
 | 
			
		||||
 * select one of them when the flash is attached. The @sqnum field says which
 | 
			
		||||
 * PEB is the original (obviously P will have lower @sqnum) and the copy. But
 | 
			
		||||
 * it is not enough to select the physical eraseblock with the higher sequence
 | 
			
		||||
 * number, because the unclean reboot could have happen in the middle of the
 | 
			
		||||
 * copying process, so the data in P is corrupted. It is also not enough to
 | 
			
		||||
 * just select the physical eraseblock with lower sequence number, because the
 | 
			
		||||
 * data there may be old (consider a case if more data was added to P1 after
 | 
			
		||||
 * the copying). Moreover, the unclean reboot may happen when the erasure of P
 | 
			
		||||
 * was just started, so it result in unstable P, which is "mostly" OK, but
 | 
			
		||||
 * still has unstable bits.
 | 
			
		||||
 *
 | 
			
		||||
 * UBI uses the @copy_flag field to indicate that this logical eraseblock is a
 | 
			
		||||
 * copy. UBI also calculates data CRC when the data is moved and stores it at
 | 
			
		||||
 * the @data_crc field of the copy (P1). So when UBI needs to pick one physical
 | 
			
		||||
 * eraseblock of two (P or P1), the @copy_flag of the newer one (P1) is
 | 
			
		||||
 * examined. If it is cleared, the situation* is simple and the newer one is
 | 
			
		||||
 * picked. If it is set, the data CRC of the copy (P1) is examined. If the CRC
 | 
			
		||||
 * checksum is correct, this physical eraseblock is selected (P1). Otherwise
 | 
			
		||||
 * the older one (P) is selected.
 | 
			
		||||
 *
 | 
			
		||||
 * Note, there is an obsolete @leb_ver field which was used instead of @sqnum
 | 
			
		||||
 * in the past. But it is not used anymore and we keep it in order to be able
 | 
			
		||||
 * to deal with old UBI images. It will be removed at some point.
 | 
			
		||||
 *
 | 
			
		||||
 * There are 2 sorts of volumes in UBI: user volumes and internal volumes.
 | 
			
		||||
 * Internal volumes are not seen from outside and are used for various internal
 | 
			
		||||
 * UBI purposes. In this implementation there is only one internal volume - the
 | 
			
		||||
 * layout volume. Internal volumes are the main mechanism of UBI extensions.
 | 
			
		||||
 * For example, in future one may introduce a journal internal volume. Internal
 | 
			
		||||
 * volumes have their own reserved range of IDs.
 | 
			
		||||
 *
 | 
			
		||||
 * The @compat field is only used for internal volumes and contains the "degree
 | 
			
		||||
 * of their compatibility". It is always zero for user volumes. This field
 | 
			
		||||
 * provides a mechanism to introduce UBI extensions and to be still compatible
 | 
			
		||||
 * with older UBI binaries. For example, if someone introduced a journal in
 | 
			
		||||
 * future, he would probably use %UBI_COMPAT_DELETE compatibility for the
 | 
			
		||||
 * journal volume.  And in this case, older UBI binaries, which know nothing
 | 
			
		||||
 * about the journal volume, would just delete this volume and work perfectly
 | 
			
		||||
 * fine. This is similar to what Ext2fs does when it is fed by an Ext3fs image
 | 
			
		||||
 * - it just ignores the Ext3fs journal.
 | 
			
		||||
 *
 | 
			
		||||
 * The @data_crc field contains the CRC checksum of the contents of the logical
 | 
			
		||||
 * eraseblock if this is a static volume. In case of dynamic volumes, it does
 | 
			
		||||
 * not contain the CRC checksum as a rule. The only exception is when the
 | 
			
		||||
 * data of the physical eraseblock was moved by the wear-leveling unit, then
 | 
			
		||||
 * the wear-leveling unit calculates the data CRC and stores it in the
 | 
			
		||||
 * @data_crc field. And of course, the @copy_flag is %in this case.
 | 
			
		||||
 *
 | 
			
		||||
 * The @data_size field is used only for static volumes because UBI has to know
 | 
			
		||||
 * how many bytes of data are stored in this eraseblock. For dynamic volumes,
 | 
			
		||||
 * this field usually contains zero. The only exception is when the data of the
 | 
			
		||||
 * physical eraseblock was moved to another physical eraseblock for
 | 
			
		||||
 * wear-leveling reasons. In this case, UBI calculates CRC checksum of the
 | 
			
		||||
 * contents and uses both @data_crc and @data_size fields. In this case, the
 | 
			
		||||
 * @data_size field contains data size.
 | 
			
		||||
 *
 | 
			
		||||
 * The @used_ebs field is used only for static volumes and indicates how many
 | 
			
		||||
 * eraseblocks the data of the volume takes. For dynamic volumes this field is
 | 
			
		||||
 * not used and always contains zero.
 | 
			
		||||
 *
 | 
			
		||||
 * The @data_pad is calculated when volumes are created using the alignment
 | 
			
		||||
 * parameter. So, effectively, the @data_pad field reduces the size of logical
 | 
			
		||||
 * eraseblocks of this volume. This is very handy when one uses block-oriented
 | 
			
		||||
 * software (say, cramfs) on top of the UBI volume.
 | 
			
		||||
 */
 | 
			
		||||
struct ubi_vid_hdr {
 | 
			
		||||
	ubi32_t magic;
 | 
			
		||||
	uint8_t version;
 | 
			
		||||
	uint8_t vol_type;
 | 
			
		||||
	uint8_t copy_flag;
 | 
			
		||||
	uint8_t compat;
 | 
			
		||||
	ubi32_t vol_id;
 | 
			
		||||
	ubi32_t lnum;
 | 
			
		||||
	ubi32_t leb_ver; /* obsolete, to be removed, don't use */
 | 
			
		||||
	ubi32_t data_size;
 | 
			
		||||
	ubi32_t used_ebs;
 | 
			
		||||
	ubi32_t data_pad;
 | 
			
		||||
	ubi32_t data_crc;
 | 
			
		||||
	uint8_t padding1[4];
 | 
			
		||||
	ubi64_t sqnum;
 | 
			
		||||
	uint8_t padding2[12];
 | 
			
		||||
	ubi32_t hdr_crc;
 | 
			
		||||
} __attribute__ ((packed));
 | 
			
		||||
 | 
			
		||||
/* Internal UBI volumes count */
 | 
			
		||||
#define UBI_INT_VOL_COUNT 1
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Starting ID of internal volumes. There is reserved room for 4096 internal
 | 
			
		||||
 * volumes.
 | 
			
		||||
 */
 | 
			
		||||
#define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096)
 | 
			
		||||
 | 
			
		||||
/* The layout volume contains the volume table */
 | 
			
		||||
 | 
			
		||||
#define UBI_LAYOUT_VOL_ID        UBI_INTERNAL_VOL_START
 | 
			
		||||
#define UBI_LAYOUT_VOLUME_EBS    2
 | 
			
		||||
#define UBI_LAYOUT_VOLUME_NAME   "layout volume"
 | 
			
		||||
#define UBI_LAYOUT_VOLUME_COMPAT UBI_COMPAT_REJECT
 | 
			
		||||
 | 
			
		||||
/* The maximum number of volumes per one UBI device */
 | 
			
		||||
#define UBI_MAX_VOLUMES 128
 | 
			
		||||
 | 
			
		||||
/* The maximum volume name length */
 | 
			
		||||
#define UBI_VOL_NAME_MAX 127
 | 
			
		||||
 | 
			
		||||
/* Size of the volume table record */
 | 
			
		||||
#define UBI_VTBL_RECORD_SIZE sizeof(struct ubi_vtbl_record)
 | 
			
		||||
 | 
			
		||||
/* Size of the volume table record without the ending CRC */
 | 
			
		||||
#define UBI_VTBL_RECORD_SIZE_CRC (UBI_VTBL_RECORD_SIZE - sizeof(ubi32_t))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct ubi_vtbl_record - a record in the volume table.
 | 
			
		||||
 * @reserved_pebs: how many physical eraseblocks are reserved for this volume
 | 
			
		||||
 * @alignment: volume alignment
 | 
			
		||||
 * @data_pad: how many bytes are unused at the end of the each physical
 | 
			
		||||
 * eraseblock to satisfy the requested alignment
 | 
			
		||||
 * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
 | 
			
		||||
 * @upd_marker: if volume update was started but not finished
 | 
			
		||||
 * @name_len: volume name length
 | 
			
		||||
 * @name: the volume name
 | 
			
		||||
 * @padding2: reserved, zeroes
 | 
			
		||||
 * @crc: a CRC32 checksum of the record
 | 
			
		||||
 *
 | 
			
		||||
 * The volume table records are stored in the volume table, which is stored in
 | 
			
		||||
 * the layout volume. The layout volume consists of 2 logical eraseblock, each
 | 
			
		||||
 * of which contains a copy of the volume table (i.e., the volume table is
 | 
			
		||||
 * duplicated). The volume table is an array of &struct ubi_vtbl_record
 | 
			
		||||
 * objects indexed by the volume ID.
 | 
			
		||||
 *
 | 
			
		||||
 * If the size of the logical eraseblock is large enough to fit
 | 
			
		||||
 * %UBI_MAX_VOLUMES records, the volume table contains %UBI_MAX_VOLUMES
 | 
			
		||||
 * records. Otherwise, it contains as many records as it can fit (i.e., size of
 | 
			
		||||
 * logical eraseblock divided by sizeof(struct ubi_vtbl_record)).
 | 
			
		||||
 *
 | 
			
		||||
 * The @upd_marker flag is used to implement volume update. It is set to %1
 | 
			
		||||
 * before update and set to %0 after the update. So if the update operation was
 | 
			
		||||
 * interrupted, UBI knows that the volume is corrupted.
 | 
			
		||||
 *
 | 
			
		||||
 * The @alignment field is specified when the volume is created and cannot be
 | 
			
		||||
 * later changed. It may be useful, for example, when a block-oriented file
 | 
			
		||||
 * system works on top of UBI. The @data_pad field is calculated using the
 | 
			
		||||
 * logical eraseblock size and @alignment. The alignment must be multiple to the
 | 
			
		||||
 * minimal flash I/O unit. If @alignment is 1, all the available space of
 | 
			
		||||
 * the physical eraseblocks is used.
 | 
			
		||||
 *
 | 
			
		||||
 * Empty records contain all zeroes and the CRC checksum of those zeroes.
 | 
			
		||||
 */
 | 
			
		||||
struct ubi_vtbl_record {
 | 
			
		||||
	ubi32_t reserved_pebs;
 | 
			
		||||
	ubi32_t alignment;
 | 
			
		||||
	ubi32_t data_pad;
 | 
			
		||||
	uint8_t vol_type;
 | 
			
		||||
	uint8_t upd_marker;
 | 
			
		||||
	ubi16_t name_len;
 | 
			
		||||
	uint8_t name[UBI_VOL_NAME_MAX+1];
 | 
			
		||||
	uint8_t padding2[24];
 | 
			
		||||
	ubi32_t crc;
 | 
			
		||||
} __attribute__ ((packed));
 | 
			
		||||
 | 
			
		||||
#endif /* !__UBI_HEADER_H__ */
 | 
			
		||||
							
								
								
									
										161
									
								
								include/linux/mtd/ubi-user.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								include/linux/mtd/ubi-user.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,161 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) International Business Machines Corp., 2006
 | 
			
		||||
 *
 | 
			
		||||
 * 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
 | 
			
		||||
 *
 | 
			
		||||
 * Author: Artem Bityutskiy (Битюцкий Артём)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __UBI_USER_H__
 | 
			
		||||
#define __UBI_USER_H__
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * UBI volume creation
 | 
			
		||||
 * ~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 *
 | 
			
		||||
 * UBI volumes are created via the %UBI_IOCMKVOL IOCTL command of UBI character
 | 
			
		||||
 * device. A &struct ubi_mkvol_req object has to be properly filled and a
 | 
			
		||||
 * pointer to it has to be passed to the IOCTL.
 | 
			
		||||
 *
 | 
			
		||||
 * UBI volume deletion
 | 
			
		||||
 * ~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 *
 | 
			
		||||
 * To delete a volume, the %UBI_IOCRMVOL IOCTL command of the UBI character
 | 
			
		||||
 * device should be used. A pointer to the 32-bit volume ID hast to be passed
 | 
			
		||||
 * to the IOCTL.
 | 
			
		||||
 *
 | 
			
		||||
 * UBI volume re-size
 | 
			
		||||
 * ~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 *
 | 
			
		||||
 * To re-size a volume, the %UBI_IOCRSVOL IOCTL command of the UBI character
 | 
			
		||||
 * device should be used. A &struct ubi_rsvol_req object has to be properly
 | 
			
		||||
 * filled and a pointer to it has to be passed to the IOCTL.
 | 
			
		||||
 *
 | 
			
		||||
 * UBI volume update
 | 
			
		||||
 * ~~~~~~~~~~~~~~~~~
 | 
			
		||||
 *
 | 
			
		||||
 * Volume update should be done via the %UBI_IOCVOLUP IOCTL command of the
 | 
			
		||||
 * corresponding UBI volume character device. A pointer to a 64-bit update
 | 
			
		||||
 * size should be passed to the IOCTL. After then, UBI expects user to write
 | 
			
		||||
 * this number of bytes to the volume character device. The update is finished
 | 
			
		||||
 * when the claimed number of bytes is passed. So, the volume update sequence
 | 
			
		||||
 * is something like:
 | 
			
		||||
 *
 | 
			
		||||
 * fd = open("/dev/my_volume");
 | 
			
		||||
 * ioctl(fd, UBI_IOCVOLUP, &image_size);
 | 
			
		||||
 * write(fd, buf, image_size);
 | 
			
		||||
 * close(fd);
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * When a new volume is created, users may either specify the volume number they
 | 
			
		||||
 * want to create or to let UBI automatically assign a volume number using this
 | 
			
		||||
 * constant.
 | 
			
		||||
 */
 | 
			
		||||
#define UBI_VOL_NUM_AUTO (-1)
 | 
			
		||||
 | 
			
		||||
/* Maximum volume name length */
 | 
			
		||||
#define UBI_MAX_VOLUME_NAME 127
 | 
			
		||||
 | 
			
		||||
/* IOCTL commands of UBI character devices */
 | 
			
		||||
 | 
			
		||||
#define UBI_IOC_MAGIC 'o'
 | 
			
		||||
 | 
			
		||||
/* Create an UBI volume */
 | 
			
		||||
#define UBI_IOCMKVOL _IOW(UBI_IOC_MAGIC, 0, struct ubi_mkvol_req)
 | 
			
		||||
/* Remove an UBI volume */
 | 
			
		||||
#define UBI_IOCRMVOL _IOW(UBI_IOC_MAGIC, 1, int32_t)
 | 
			
		||||
/* Re-size an UBI volume */
 | 
			
		||||
#define UBI_IOCRSVOL _IOW(UBI_IOC_MAGIC, 2, struct ubi_rsvol_req)
 | 
			
		||||
 | 
			
		||||
/* IOCTL commands of UBI volume character devices */
 | 
			
		||||
 | 
			
		||||
#define UBI_VOL_IOC_MAGIC 'O'
 | 
			
		||||
 | 
			
		||||
/* Start UBI volume update */
 | 
			
		||||
#define UBI_IOCVOLUP _IOW(UBI_VOL_IOC_MAGIC, 0, int64_t)
 | 
			
		||||
/* An eraseblock erasure command, used for debugging, disabled by default */
 | 
			
		||||
#define UBI_IOCEBER _IOW(UBI_VOL_IOC_MAGIC, 1, int32_t)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * UBI volume type constants.
 | 
			
		||||
 *
 | 
			
		||||
 * @UBI_DYNAMIC_VOLUME: dynamic volume
 | 
			
		||||
 * @UBI_STATIC_VOLUME:  static volume
 | 
			
		||||
 */
 | 
			
		||||
enum {
 | 
			
		||||
	UBI_DYNAMIC_VOLUME = 3,
 | 
			
		||||
	UBI_STATIC_VOLUME = 4
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct ubi_mkvol_req - volume description data structure used in
 | 
			
		||||
 * volume creation requests.
 | 
			
		||||
 * @vol_id: volume number
 | 
			
		||||
 * @alignment: volume alignment
 | 
			
		||||
 * @bytes: volume size in bytes
 | 
			
		||||
 * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
 | 
			
		||||
 * @padding1: reserved for future, not used
 | 
			
		||||
 * @name_len: volume name length
 | 
			
		||||
 * @padding2: reserved for future, not used
 | 
			
		||||
 * @name: volume name
 | 
			
		||||
 *
 | 
			
		||||
 * This structure is used by userspace programs when creating new volumes. The
 | 
			
		||||
 * @used_bytes field is only necessary when creating static volumes.
 | 
			
		||||
 *
 | 
			
		||||
 * The @alignment field specifies the required alignment of the volume logical
 | 
			
		||||
 * eraseblock. This means, that the size of logical eraseblocks will be aligned
 | 
			
		||||
 * to this number, i.e.,
 | 
			
		||||
 *	(UBI device logical eraseblock size) mod (@alignment) = 0.
 | 
			
		||||
 *
 | 
			
		||||
 * To put it differently, the logical eraseblock of this volume may be slightly
 | 
			
		||||
 * shortened in order to make it properly aligned. The alignment has to be
 | 
			
		||||
 * multiple of the flash minimal input/output unit, or %1 to utilize the entire
 | 
			
		||||
 * available space of logical eraseblocks.
 | 
			
		||||
 *
 | 
			
		||||
 * The @alignment field may be useful, for example, when one wants to maintain
 | 
			
		||||
 * a block device on top of an UBI volume. In this case, it is desirable to fit
 | 
			
		||||
 * an integer number of blocks in logical eraseblocks of this UBI volume. With
 | 
			
		||||
 * alignment it is possible to update this volume using plane UBI volume image
 | 
			
		||||
 * BLOBs, without caring about how to properly align them.
 | 
			
		||||
 */
 | 
			
		||||
struct ubi_mkvol_req {
 | 
			
		||||
	int32_t vol_id;
 | 
			
		||||
	int32_t alignment;
 | 
			
		||||
	int64_t bytes;
 | 
			
		||||
	int8_t vol_type;
 | 
			
		||||
	int8_t padding1;
 | 
			
		||||
	int16_t name_len;
 | 
			
		||||
	int8_t padding2[4];
 | 
			
		||||
	char name[UBI_MAX_VOLUME_NAME+1];
 | 
			
		||||
} __attribute__ ((packed));
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct ubi_rsvol_req - a data structure used in volume re-size requests.
 | 
			
		||||
 * @vol_id: ID of the volume to re-size
 | 
			
		||||
 * @bytes: new size of the volume in bytes
 | 
			
		||||
 *
 | 
			
		||||
 * Re-sizing is possible for both dynamic and static volumes. But while dynamic
 | 
			
		||||
 * volumes may be re-sized arbitrarily, static volumes cannot be made to be
 | 
			
		||||
 * smaller then the number of bytes they bear. To arbitrarily shrink a static
 | 
			
		||||
 * volume, it must be wiped out first (by means of volume update operation with
 | 
			
		||||
 * zero number of bytes).
 | 
			
		||||
 */
 | 
			
		||||
struct ubi_rsvol_req {
 | 
			
		||||
	int64_t bytes;
 | 
			
		||||
	int32_t vol_id;
 | 
			
		||||
} __attribute__ ((packed));
 | 
			
		||||
 | 
			
		||||
#endif /* __UBI_USER_H__ */
 | 
			
		||||
@ -84,6 +84,7 @@ struct nand_write_options {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct nand_write_options nand_write_options_t;
 | 
			
		||||
typedef struct mtd_oob_ops mtd_oob_ops_t;
 | 
			
		||||
 | 
			
		||||
struct nand_read_options {
 | 
			
		||||
	u_char *buffer;		/* memory block in which read image is written*/
 | 
			
		||||
@ -107,7 +108,7 @@ struct nand_erase_options {
 | 
			
		||||
 | 
			
		||||
typedef struct nand_erase_options nand_erase_options_t;
 | 
			
		||||
 | 
			
		||||
int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts);
 | 
			
		||||
int nand_write_opts(nand_info_t *mtd, loff_t to, mtd_oob_ops_t *ops);
 | 
			
		||||
 | 
			
		||||
int nand_read_opts(nand_info_t *meminfo, const nand_read_options_t *opts);
 | 
			
		||||
int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user