mtd: nand: new base driver for memory mapped nand devices

The BF537-STAMP Blackfin board had a driver for working with NAND devices
that are simply memory mapped.  Since there is nothing Blackfin specific
about this, generalize the driver a bit so that everyone can leverage it.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Scott Wood <scottwood@freescale.com>
This commit is contained in:
Mike Frysinger 2009-05-25 22:42:28 -04:00 committed by Scott Wood
parent d27bc728cf
commit cd84423a09
6 changed files with 74 additions and 126 deletions

View file

@ -32,7 +32,6 @@ LIB = $(obj)lib$(BOARD).a
COBJS-y := $(BOARD).o cmd_bf537led.o
COBJS-$(CONFIG_BFIN_IDE) += ide-cf.o
COBJS-$(CONFIG_CMD_EEPROM) += spi_flash.o
COBJS-$(CONFIG_CMD_NAND) += nand.o
COBJS-$(CONFIG_POST) += post.o post-memory.o
SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)

View file

@ -1,100 +0,0 @@
/*
* Copyright (c) 2006-2007 Analog Devices Inc.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* 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
*/
#include <common.h>
#include <asm/io.h>
#include <nand.h>
#define CONCAT(a,b,c,d) a ## b ## c ## d
#define PORT(a,b) CONCAT(pPORT,a,b,)
#ifndef CONFIG_NAND_GPIO_PORT
#define CONFIG_NAND_GPIO_PORT F
#endif
/*
* hardware specific access to control-lines
*/
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;
if (ctrl & NAND_CTRL_CHANGE) {
if (ctrl & NAND_CLE)
IO_ADDR_W = CONFIG_SYS_NAND_BASE + BFIN_NAND_CLE;
else
IO_ADDR_W = CONFIG_SYS_NAND_BASE;
if (ctrl & NAND_ALE)
IO_ADDR_W = CONFIG_SYS_NAND_BASE + BFIN_NAND_ALE;
else
IO_ADDR_W = CONFIG_SYS_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)
{
int ret = (*PORT(CONFIG_NAND_GPIO_PORT, IO) & BFIN_NAND_READY) ? 1 : 0;
SSYNC();
return ret;
}
/*
* Board-specific NAND initialization. The following members of the
* 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
* - 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
* - 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
* nand_scan about special functionality. See the defines for further
* explanation
* Members with a "?" were not set in the merged testing-NAND branch,
* so they are not set here either.
*/
int board_nand_init(struct nand_chip *nand)
{
*PORT(CONFIG_NAND_GPIO_PORT, _FER) &= ~BFIN_NAND_READY;
*PORT(CONFIG_NAND_GPIO_PORT, IO_DIR) &= ~BFIN_NAND_READY;
*PORT(CONFIG_NAND_GPIO_PORT, IO_INEN) |= BFIN_NAND_READY;
nand->cmd_ctrl = bfin_hwcontrol;
nand->ecc.mode = NAND_ECC_SOFT;
nand->dev_ready = bfin_device_ready;
nand->chip_delay = 30;
return 0;
}

View file

@ -45,6 +45,7 @@ COBJS-$(CONFIG_NAND_NOMADIK) += nomadik.o
COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.c
COBJS-$(CONFIG_NAND_S3C64XX) += s3c64xx.o
COBJS-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o
COBJS-$(CONFIG_NAND_PLAT) += nand_plat.o
endif
COBJS := $(COBJS-y)

View file

@ -0,0 +1,53 @@
/*
* Genericish driver for memory mapped NAND devices
*
* Copyright (c) 2006-2009 Analog Devices Inc.
* Licensed under the GPL-2 or later.
*/
/* Your board must implement the following macros:
* NAND_PLAT_WRITE_CMD(chip, cmd)
* NAND_PLAT_WRITE_ADR(chip, cmd)
* NAND_PLAT_INIT()
*
* It may also implement the following:
* NAND_PLAT_DEV_READY(chip)
*/
#include <common.h>
#include <asm/io.h>
#include <nand.h>
static void plat_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *this = mtd->priv;
if (cmd == NAND_CMD_NONE)
return;
if (ctrl & NAND_CLE)
NAND_PLAT_WRITE_CMD(this, cmd);
else
NAND_PLAT_WRITE_ADR(this, cmd);
}
#ifdef NAND_PLAT_DEV_READY
static int plat_dev_ready(struct mtd_info *mtd)
{
return NAND_PLAT_DEV_READY((struct nand_chip *)mtd->priv);
}
#else
# define plat_dev_ready NULL
#endif
int board_nand_init(struct nand_chip *nand)
{
NAND_PLAT_INIT();
nand->cmd_ctrl = plat_cmd_ctrl;
nand->dev_ready = plat_dev_ready;
nand->ecc.mode = NAND_ECC_SOFT;
return 0;
}

View file

@ -151,36 +151,28 @@
/*
* NAND Settings
*/
/* #define CONFIG_BF537_NAND */
#ifdef CONFIG_BF537_NAND
# define CONFIG_CMD_NAND
#endif
#define CONFIG_SYS_NAND_ADDR 0x20212000
#define CONFIG_SYS_NAND_BASE CONFIG_SYS_NAND_ADDR
/* #define CONFIG_NAND_PLAT */
#define CONFIG_SYS_NAND_BASE 0x20212000
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define SECTORSIZE 512
#define ADDR_COLUMN 1
#define ADDR_PAGE 2
#define ADDR_COLUMN_PAGE 3
#define NAND_ChipID_UNKNOWN 0x00
#define NAND_MAX_FLOORS 1
#define BFIN_NAND_READY PF3
#define NAND_WAIT_READY(nand) \
#define BFIN_NAND_CLE(chip) ((unsigned long)(chip)->IO_ADDR_W | (1 << 2))
#define BFIN_NAND_ALE(chip) ((unsigned long)(chip)->IO_ADDR_W | (1 << 1))
#define BFIN_NAND_READY PF3
#define BFIN_NAND_WRITE(addr, cmd) \
do { \
int timeout = 0; \
while (!(*pPORTFIO & PF3)) \
if (timeout++ > 100000) \
break; \
bfin_write8(addr, cmd); \
SSYNC(); \
} while (0)
#define BFIN_NAND_CLE (1 << 2) /* A2 -> Command Enable */
#define BFIN_NAND_ALE (1 << 1) /* A1 -> Address Enable */
#define WRITE_NAND_COMMAND(d, adr) bfin_write8(adr | BFIN_NAND_CLE, d)
#define WRITE_NAND_ADDRESS(d, adr) bfin_write8(adr | BFIN_NAND_ALE, d)
#define WRITE_NAND(d, adr) bfin_write8(adr, d)
#define READ_NAND(adr) bfin_read8(adr)
#define NAND_PLAT_WRITE_CMD(chip, cmd) BFIN_NAND_WRITE(BFIN_NAND_CLE(chip), cmd)
#define NAND_PLAT_WRITE_ADR(chip, cmd) BFIN_NAND_WRITE(BFIN_NAND_ALE(chip), cmd)
#define NAND_PLAT_DEV_READY(chip) (bfin_read_PORTFIO() & BFIN_NAND_READY)
#define NAND_PLAT_INIT() \
do { \
bfin_write_PORTF_FER(bfin_read_PORTF_FER() & ~BFIN_NAND_READY); \
bfin_write_PORTFIO_DIR(bfin_read_PORTFIO_DIR() & ~BFIN_NAND_READY); \
bfin_write_PORTFIO_INEN(bfin_read_PORTFIO_INEN() | BFIN_NAND_READY); \
} while (0)
/*

View file

@ -38,6 +38,9 @@
# define CONFIG_CMD_USB_STORAGE
# define CONFIG_DOS_PARTITION
# endif
# ifdef CONFIG_NAND_PLAT
# define CONFIG_CMD_NAND
# endif
# ifdef CONFIG_POST
# define CONFIG_CMD_DIAG
# endif