From cfa460adfdefcc30d104e1a9ee44994ee349bb7b Mon Sep 17 00:00:00 2001 From: William Juul Date: Wed, 31 Oct 2007 13:53:06 +0100 Subject: 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 Signed-off-by: Stig Olsen Signed-off-by: Scott Wood --- board/bf537-stamp/nand.c | 43 ++++++++++------------ board/dave/PPChameleonEVB/nand.c | 49 ++++++++++++------------- board/delta/nand.c | 41 +++++---------------- board/esd/common/esd405ep_nand.c | 42 +++++++++++----------- board/freescale/m5329evb/nand.c | 42 +++++++++------------- board/nc650/nand.c | 78 ++++++++++++++++++---------------------- board/netstar/nand.c | 20 +++++++---- board/prodrive/alpr/nand.c | 59 ++++++++++-------------------- board/prodrive/pdnb3/nand.c | 53 ++++++++++----------------- board/sc3/sc3nand.c | 44 +++++++++++------------ board/tqc/tqm8272/tqm8272.c | 34 +++++++++--------- board/zylonite/nand.c | 39 +++++--------------- 12 files changed, 216 insertions(+), 328 deletions(-) (limited to 'board') diff --git a/board/bf537-stamp/nand.c b/board/bf537-stamp/nand.c index 6ff0f4f..bdf1d6e 100644 --- a/board/bf537-stamp/nand.c +++ b/board/bf537-stamp/nand.c @@ -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; } diff --git a/board/dave/PPChameleonEVB/nand.c b/board/dave/PPChameleonEVB/nand.c index 09c0b04..4bc4257 100644 --- a/board/dave/PPChameleonEVB/nand.c +++ b/board/dave/PPChameleonEVB/nand.c @@ -21,7 +21,7 @@ */ #include - +#include #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; diff --git a/board/delta/nand.c b/board/delta/nand.c index 5024056..51520f5 100644 --- a/board/delta/nand.c +++ b/board/delta/nand.c @@ -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; } diff --git a/board/esd/common/esd405ep_nand.c b/board/esd/common/esd405ep_nand.c index 7bf6847..4bf81ab 100644 --- a/board/esd/common/esd405ep_nand.c +++ b/board/esd/common/esd405ep_nand.c @@ -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; diff --git a/board/freescale/m5329evb/nand.c b/board/freescale/m5329evb/nand.c index 344a614..f84912e 100644 --- a/board/freescale/m5329evb/nand.c +++ b/board/freescale/m5329evb/nand.c @@ -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; diff --git a/board/nc650/nand.c b/board/nc650/nand.c index 8617f74..faec605 100644 --- a/board/nc650/nand.c +++ b/board/nc650/nand.c @@ -22,7 +22,7 @@ */ #include - +#include #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; diff --git a/board/netstar/nand.c b/board/netstar/nand.c index b76d2a3..302d78e 100644 --- a/board/netstar/nand.c +++ b/board/netstar/nand.c @@ -21,6 +21,7 @@ */ #include +#include #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; } diff --git a/board/prodrive/alpr/nand.c b/board/prodrive/alpr/nand.c index 097e183..3224d3d 100644 --- a/board/prodrive/alpr/nand.c +++ b/board/prodrive/alpr/nand.c @@ -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; -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 (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)); + } + 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; diff --git a/board/prodrive/pdnb3/nand.c b/board/prodrive/pdnb3/nand.c index b1e7041..281ae70 100644 --- a/board/prodrive/pdnb3/nand.c +++ b/board/prodrive/pdnb3/nand.c @@ -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; - - 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; + 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, &(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; diff --git a/board/sc3/sc3nand.c b/board/sc3/sc3nand.c index 009567b..2f2e745 100644 --- a/board/sc3/sc3nand.c +++ b/board/sc3/sc3nand.c @@ -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; diff --git a/board/tqc/tqm8272/tqm8272.c b/board/tqc/tqm8272/tqm8272.c index cde0296..5148f3d 100644 --- a/board/tqc/tqm8272/tqm8272.c +++ b/board/tqc/tqm8272/tqm8272.c @@ -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; - - case NAND_CTL_SETALE: - hwctl |= 0x2; - break; - - case NAND_CTL_CLRALE: - hwctl &= ~0x2; - break; + 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 (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; diff --git a/board/zylonite/nand.c b/board/zylonite/nand.c index ca16578..47d5d4b 100644 --- a/board/zylonite/nand.c +++ b/board/zylonite/nand.c @@ -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; } -- cgit v1.1