OneNAND support (take #2)

[PATCH 3/3] OneNAND support (take #2)

OneNAND support at U-Boot

Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
This commit is contained in:
Kyungmin Park 2007-09-10 17:15:14 +09:00 committed by Stefan Roese
parent 17aa280045
commit d7e8ce101a
11 changed files with 797 additions and 4 deletions

View File

@ -211,6 +211,7 @@ LIBS += drivers/libdrivers.a
LIBS += drivers/bios_emulator/libatibiosemu.a
LIBS += drivers/nand/libnand.a
LIBS += drivers/nand_legacy/libnand_legacy.a
LIBS += drivers/onenand/libonenand.a
LIBS += drivers/net/libnet.a
ifeq ($(CPU),mpc83xx)
LIBS += drivers/qe/qe.a

View File

@ -37,13 +37,14 @@ COBJS = main.o ACEX1K.o altera.o bedbug.o circbuf.o cmd_autoscript.o \
cmd_load.o cmd_log.o \
cmd_mem.o cmd_mii.o cmd_misc.o cmd_mmc.o \
cmd_nand.o cmd_net.o cmd_nvedit.o \
cmd_onenand.o \
cmd_pci.o cmd_pcmcia.o cmd_portio.o \
cmd_reginfo.o cmd_reiser.o cmd_sata.o cmd_scsi.o cmd_spi.o \
cmd_universe.o cmd_usb.o cmd_vfd.o \
command.o console.o cyclon2.o devices.o dlmalloc.o docecc.o \
environment.o env_common.o \
env_nand.o env_dataflash.o env_flash.o env_eeprom.o \
env_nvram.o env_nowhere.o \
env_onenand.o env_nvram.o env_nowhere.o \
exports.o \
fdt_support.o flash.o fpga.o ft_build.o \
hush.o kgdb.o lcd.o lists.o lynxkdi.o \

View File

@ -57,8 +57,9 @@ DECLARE_GLOBAL_DATA_PTR;
!defined(CFG_ENV_IS_IN_FLASH) && \
!defined(CFG_ENV_IS_IN_DATAFLASH) && \
!defined(CFG_ENV_IS_IN_NAND) && \
!defined(CFG_ENV_IS_IN_ONENAND) && \
!defined(CFG_ENV_IS_NOWHERE)
# error Define one of CFG_ENV_IS_IN_{NVRAM|EEPROM|FLASH|DATAFLASH|NOWHERE}
# error Define one of CFG_ENV_IS_IN_{NVRAM|EEPROM|FLASH|DATAFLASH|ONENAND|NOWHERE}
#endif
#define XMK_STR(x) #x
@ -553,7 +554,8 @@ int getenv_r (char *name, char *buf, unsigned len)
#if defined(CFG_ENV_IS_IN_NVRAM) || defined(CFG_ENV_IS_IN_EEPROM) \
|| (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_FLASH)) \
|| (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_NAND))
|| (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_NAND)) \
|| (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_ONENAND))
int do_saveenv (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
extern char * env_name_spec;
@ -608,7 +610,8 @@ U_BOOT_CMD(
#if defined(CFG_ENV_IS_IN_NVRAM) || defined(CFG_ENV_IS_IN_EEPROM) \
|| (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_FLASH)) \
|| (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_NAND))
|| (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_NAND)) \
|| (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_ONENAND))
U_BOOT_CMD(
saveenv, 1, 0, do_saveenv,
"saveenv - save environment variables to persistent storage\n",

155
common/cmd_onenand.c Normal file
View File

@ -0,0 +1,155 @@
/*
* U-Boot command for OneNAND support
*
* Copyright (C) 2005-2007 Samsung Electronics
* Kyungmin Park <kyungmin.park@samsung.com>
*
* 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.
*/
#include <common.h>
#include <command.h>
#ifdef CONFIG_CMD_ONENAND
#include <linux/mtd/compat.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>
#include <asm/io.h>
extern struct mtd_info onenand_mtd;
extern struct onenand_chip onenand_chip;
int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
int ret = 0;
switch (argc) {
case 0:
case 1:
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
case 2:
if (strncmp(argv[1], "open", 4) == 0) {
onenand_init();
return 0;
}
onenand_print_device_info(onenand_chip.device_id, 1);
return 0;
default:
/* At least 4 args */
if (strncmp(argv[1], "erase", 5) == 0) {
struct erase_info instr;
ulong start, end;
ulong block;
start = simple_strtoul(argv[2], NULL, 10);
end = simple_strtoul(argv[3], NULL, 10);
start -= (unsigned long)onenand_chip.base;
end -= (unsigned long)onenand_chip.base;
if (!end || end < 0)
end = start;
printf("Erase block from %d to %d\n", start, end);
for (block = start; block <= end; block++) {
instr.addr = block << onenand_chip.erase_shift;
instr.len = 1 << onenand_chip.erase_shift;
ret = onenand_erase(&onenand_mtd, &instr);
if (ret) {
printf("erase failed %d\n", block);
break;
}
}
return 0;
}
if (strncmp(argv[1], "read", 4) == 0) {
ulong addr = simple_strtoul(argv[2], NULL, 16);
ulong ofs = simple_strtoul(argv[3], NULL, 16);
size_t len = simple_strtoul(argv[4], NULL, 16);
size_t retlen = 0;
int oob = strncmp(argv[1], "read.oob", 8) ? 0 : 1;
ofs -= (unsigned long)onenand_chip.base;
if (oob)
onenand_read_oob(&onenand_mtd, ofs, len,
&retlen, (u_char *) addr);
else
onenand_read(&onenand_mtd, ofs, len, &retlen,
(u_char *) addr);
printf("Done\n");
return 0;
}
if (strncmp(argv[1], "write", 5) == 0) {
ulong addr = simple_strtoul(argv[2], NULL, 16);
ulong ofs = simple_strtoul(argv[3], NULL, 16);
size_t len = simple_strtoul(argv[4], NULL, 16);
size_t retlen = 0;
ofs -= (unsigned long)onenand_chip.base;
onenand_write(&onenand_mtd, ofs, len, &retlen,
(u_char *) addr);
printf("Done\n");
return 0;
}
if (strncmp(argv[1], "block", 5) == 0) {
ulong addr = simple_strtoul(argv[2], NULL, 16);
ulong block = simple_strtoul(argv[3], NULL, 10);
ulong page = simple_strtoul(argv[4], NULL, 10);
size_t len = simple_strtol(argv[5], NULL, 10);
size_t retlen = 0;
ulong ofs;
int oob = strncmp(argv[1], "block.oob", 9) ? 0 : 1;
ofs = block << onenand_chip.erase_shift;
if (page)
ofs += page << onenand_chip.page_shift;
if (!len) {
if (oob)
len = 64;
else
len = 512;
}
if (oob)
onenand_read_oob(&onenand_mtd, ofs, len,
&retlen, (u_char *) addr);
else
onenand_read(&onenand_mtd, ofs, len, &retlen,
(u_char *) addr);
return 0;
}
break;
}
return 0;
}
U_BOOT_CMD(
onenand, 6, 1, do_onenand,
"onenand - OneNAND sub-system\n",
"info - show available OneNAND devices\n"
"onenand read[.oob] addr ofs len - read data at ofs with len to addr\n"
"onenand write addr ofs len - write data at ofs with len from addr\n"
"onenand erase saddr eaddr - erase block start addr to end addr\n"
"onenand block[.oob] addr block [page] [len] - "
"read data with (block [, page]) to addr"
);
#endif /* CONFIG_CMD_ONENAND */

134
common/env_onenand.c Normal file
View File

@ -0,0 +1,134 @@
/*
* (C) Copyright 2005-2007 Samsung Electronics
* Kyungmin Park <kyungmin.park@samsung.com>
*
* 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>
#if defined(CFG_ENV_IS_IN_ONENAND) /* Environment is in OneNAND */
#include <command.h>
#include <environment.h>
#include <linux/stddef.h>
#include <malloc.h>
#include <linux/mtd/compat.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>
extern struct mtd_info onenand_mtd;
extern struct onenand_chip onenand_chip;
/* References to names in env_common.c */
extern uchar default_environment[];
#define ONENAND_ENV_SIZE(mtd) (mtd.oobblock - ENV_HEADER_SIZE)
char *env_name_spec = "OneNAND";
#ifdef ENV_IS_EMBEDDED
extern uchar environment[];
env_t *env_ptr = (env_t *) (&environment[0]);
#else /* ! ENV_IS_EMBEDDED */
static unsigned char onenand_env[MAX_ONENAND_PAGESIZE];
env_t *env_ptr = (env_t *) onenand_env;
#endif /* ENV_IS_EMBEDDED */
uchar env_get_char_spec(int index)
{
DECLARE_GLOBAL_DATA_PTR;
return (*((uchar *) (gd->env_addr + index)));
}
void env_relocate_spec(void)
{
DECLARE_GLOBAL_DATA_PTR;
unsigned long env_addr;
int use_default = 0;
int retlen;
env_addr = CFG_ENV_ADDR;
env_addr -= (unsigned long)onenand_chip.base;
/* Check OneNAND exist */
if (onenand_mtd.oobblock)
/* Ignore read fail */
onenand_read(&onenand_mtd, env_addr, onenand_mtd.oobblock,
&retlen, (u_char *) env_ptr);
else
onenand_mtd.oobblock = MAX_ONENAND_PAGESIZE;
if (crc32(0, env_ptr->data, ONENAND_ENV_SIZE(onenand_mtd)) !=
env_ptr->crc)
use_default = 1;
if (use_default) {
memcpy(env_ptr->data, default_environment,
ONENAND_ENV_SIZE(onenand_mtd));
env_ptr->crc =
crc32(0, env_ptr->data, ONENAND_ENV_SIZE(onenand_mtd));
}
gd->env_addr = (ulong) & env_ptr->data;
gd->env_valid = 1;
}
int saveenv(void)
{
unsigned long env_addr = CFG_ENV_ADDR;
struct erase_info instr;
int retlen;
instr.len = CFG_ENV_SIZE;
instr.addr = env_addr;
instr.addr -= (unsigned long)onenand_chip.base;
if (onenand_erase(&onenand_mtd, &instr)) {
printf("OneNAND: erase failed at 0x%08x\n", env_addr);
return 1;
}
/* update crc */
env_ptr->crc =
crc32(0, env_ptr->data, onenand_mtd.oobblock - ENV_HEADER_SIZE);
env_addr -= (unsigned long)onenand_chip.base;
if (onenand_write(&onenand_mtd, env_addr, onenand_mtd.oobblock, &retlen,
(u_char *) env_ptr)) {
printf("OneNAND: write failed at 0x%08x\n", instr.addr);
return 2;
}
return 0;
}
int env_init(void)
{
DECLARE_GLOBAL_DATA_PTR;
/* use default */
gd->env_addr = (ulong) & default_environment[0];
gd->env_valid = 1;
return 0;
}
#endif /* CFG_ENV_IS_IN_ONENAND */

View File

@ -59,6 +59,7 @@
#define CONFIG_CMD_NAND /* NAND support */
#define CONFIG_CMD_NET /* bootp, tftpboot, rarpboot */
#define CONFIG_CMD_NFS /* NFS support */
#define CONFIG_CMD_ONENAND /* OneNAND support */
#define CONFIG_CMD_PCI /* pciinfo */
#define CONFIG_CMD_PCMCIA /* PCMCIA support */
#define CONFIG_CMD_PING /* ping support */

127
include/linux/mtd/bbm.h Normal file
View File

@ -0,0 +1,127 @@
/*
* linux/include/linux/mtd/bbm.h
*
* NAND family Bad Block Management (BBM) header file
* - Bad Block Table (BBT) implementation
*
* Copyright (c) 2005-2007 Samsung Electronics
* Kyungmin Park <kyungmin.park@samsung.com>
*
* Copyright (c) 2000-2005
* Thomas Gleixner <tglx@linuxtronix.de>
*
* 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.
*/
#ifndef __LINUX_MTD_BBM_H
#define __LINUX_MTD_BBM_H
/* The maximum number of NAND chips in an array */
#ifndef NAND_MAX_CHIPS
#define NAND_MAX_CHIPS 8
#endif
/**
* struct nand_bbt_descr - bad block table descriptor
* @param options options for this descriptor
* @param pages the page(s) where we find the bbt, used with
* option BBT_ABSPAGE when bbt is searched,
* then we store the found bbts pages here.
* Its an array and supports up to 8 chips now
* @param offs offset of the pattern in the oob area of the page
* @param veroffs offset of the bbt version counter in the oob are of the page
* @param version version read from the bbt page during scan
* @param len length of the pattern, if 0 no pattern check is performed
* @param maxblocks maximum number of blocks to search for a bbt. This number of
* blocks is reserved at the end of the device
* where the tables are written.
* @param reserved_block_code if non-0, this pattern denotes a reserved
* (rather than bad) block in the stored bbt
* @param pattern pattern to identify bad block table or factory marked
* good / bad blocks, can be NULL, if len = 0
*
* Descriptor for the bad block table marker and the descriptor for the
* pattern which identifies good and bad blocks. The assumption is made
* that the pattern and the version count are always located in the oob area
* of the first block.
*/
struct nand_bbt_descr {
int options;
int pages[NAND_MAX_CHIPS];
int offs;
int veroffs;
uint8_t version[NAND_MAX_CHIPS];
int len;
int maxblocks;
int reserved_block_code;
uint8_t *pattern;
};
/* Options for the bad block table descriptors */
/* The number of bits used per block in the bbt on the device */
#define NAND_BBT_NRBITS_MSK 0x0000000F
#define NAND_BBT_1BIT 0x00000001
#define NAND_BBT_2BIT 0x00000002
#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
/* 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 */
#define NAND_BBT_SEARCH 0x00000040
/* bbt is stored per chip on multichip devices */
#define NAND_BBT_PERCHIP 0x00000080
/* bbt has a version counter at offset veroffs */
#define NAND_BBT_VERSION 0x00000100
/* Create a bbt if none axists */
#define NAND_BBT_CREATE 0x00000200
/* Search good / bad pattern through all pages of a block */
#define NAND_BBT_SCANALLPAGES 0x00000400
/* Scan block empty during good / bad block scan */
#define NAND_BBT_SCANEMPTY 0x00000800
/* Write bbt if neccecary */
#define NAND_BBT_WRITE 0x00001000
/* Read and write back block contents when writing bbt */
#define NAND_BBT_SAVECONTENT 0x00002000
/* Search good / bad pattern on the first and the second page */
#define NAND_BBT_SCAN2NDPAGE 0x00004000
/* The maximum number of blocks to scan for a bbt */
#define NAND_BBT_SCAN_MAXBLOCKS 4
/*
* Constants for oob configuration
*/
#define ONENAND_BADBLOCK_POS 0
/**
* struct bbt_info - [GENERIC] Bad Block Table data structure
* @param bbt_erase_shift [INTERN] number of address bits in a bbt entry
* @param badblockpos [INTERN] position of the bad block marker in the oob area
* @param bbt [INTERN] bad block table pointer
* @param badblock_pattern [REPLACEABLE] bad block scan pattern used for initial bad block scan
* @param priv [OPTIONAL] pointer to private bbm date
*/
struct bbm_info {
int bbt_erase_shift;
int badblockpos;
int options;
uint8_t *bbt;
int (*isbad_bbt) (struct mtd_info * mtd, loff_t ofs, int allowbbt);
/* TODO Add more NAND specific fileds */
struct nand_bbt_descr *badblock_pattern;
void *priv;
};
/* OneNAND BBT interface */
extern int onenand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd);
extern int onenand_default_bbt (struct mtd_info *mtd);
#endif /* __LINUX_MTD_BBM_H */

143
include/linux/mtd/onenand.h Normal file
View File

@ -0,0 +1,143 @@
/*
* linux/include/linux/mtd/onenand.h
*
* Copyright (C) 2005-2007 Samsung Electronics
* Kyungmin Park <kyungmin.park@samsung.com>
*
* 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.
*/
#ifndef __LINUX_MTD_ONENAND_H
#define __LINUX_MTD_ONENAND_H
#include <linux/mtd/onenand_regs.h>
/* Note: The header order is impoertant */
#include <onenand_uboot.h>
#include <linux/mtd/bbm.h>
#define MAX_BUFFERRAM 2
#define MAX_ONENAND_PAGESIZE (2048 + 64)
/* Scan and identify a OneNAND device */
extern int onenand_scan (struct mtd_info *mtd, int max_chips);
/* Free resources held by the OneNAND device */
extern void onenand_release (struct mtd_info *mtd);
/**
* onenand_state_t - chip states
* Enumeration for OneNAND flash chip state
*/
typedef enum {
FL_READY,
FL_READING,
FL_WRITING,
FL_ERASING,
FL_SYNCING,
FL_UNLOCKING,
FL_LOCKING,
} onenand_state_t;
/**
* struct onenand_bufferram - OneNAND BufferRAM Data
* @param block block address in BufferRAM
* @param page page address in BufferRAM
* @param valid valid flag
*/
struct onenand_bufferram {
int block;
int page;
int valid;
};
/**
* struct onenand_chip - OneNAND Private Flash Chip Data
* @param base [BOARDSPECIFIC] address to access OneNAND
* @param chipsize [INTERN] the size of one chip for multichip arrays
* @param device_id [INTERN] device ID
* @param verstion_id [INTERN] version ID
* @param options [BOARDSPECIFIC] various chip options. They can partly be set to inform onenand_scan about
* @param erase_shift [INTERN] number of address bits in a block
* @param page_shift [INTERN] number of address bits in a page
* @param ppb_shift [INTERN] number of address bits in a pages per block
* @param page_mask [INTERN] a page per block mask
* @param bufferam_index [INTERN] BufferRAM index
* @param bufferam [INTERN] BufferRAM info
* @param readw [REPLACEABLE] hardware specific function for read short
* @param writew [REPLACEABLE] hardware specific function for write short
* @param command [REPLACEABLE] hardware specific function for writing commands to the chip
* @param wait [REPLACEABLE] hardware specific function for wait on ready
* @param read_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area
* @param write_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area
* @param chip_lock [INTERN] spinlock used to protect access to this structure and the chip
* @param wq [INTERN] wait queue to sleep on if a OneNAND operation is in progress
* @param state [INTERN] the current state of the OneNAND device
* @param autooob [REPLACEABLE] the default (auto)placement scheme
* @param priv [OPTIONAL] pointer to private chip date
*/
struct onenand_chip {
void __iomem *base;
unsigned int chipsize;
unsigned int device_id;
unsigned int options;
unsigned int erase_shift;
unsigned int page_shift;
unsigned int ppb_shift; /* Pages per block shift */
unsigned int page_mask;
unsigned int bufferram_index;
struct onenand_bufferram bufferram[MAX_BUFFERRAM];
int (*command) (struct mtd_info * mtd, int cmd, loff_t address,
size_t len);
int (*wait) (struct mtd_info * mtd, int state);
int (*read_bufferram) (struct mtd_info * mtd, int area,
unsigned char *buffer, int offset, size_t count);
int (*write_bufferram) (struct mtd_info * mtd, int area,
const unsigned char *buffer, int offset,
size_t count);
unsigned short (*read_word) (void __iomem * addr);
void (*write_word) (unsigned short value, void __iomem * addr);
void (*mmcontrol) (struct mtd_info * mtd, int sync_read);
spinlock_t chip_lock;
wait_queue_head_t wq;
onenand_state_t state;
struct nand_oobinfo *autooob;
void *bbm;
void *priv;
};
#define ONENAND_CURRENT_BUFFERRAM(this) (this->bufferram_index)
#define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1)
#define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1)
/*
* Options bits
*/
#define ONENAND_CONT_LOCK (0x0001)
/*
* OneNAND Flash Manufacturer ID Codes
*/
#define ONENAND_MFR_SAMSUNG 0xec
#define ONENAND_MFR_UNKNOWN 0x00
/**
* struct nand_manufacturers - NAND Flash Manufacturer ID Structure
* @param name: Manufacturer name
* @param id: manufacturer ID code of device.
*/
struct onenand_manufacturers {
int id;
char *name;
};
#endif /* __LINUX_MTD_ONENAND_H */

View File

@ -0,0 +1,181 @@
/*
* linux/include/linux/mtd/onenand_regs.h
*
* OneNAND Register header file
*
* Copyright (C) 2005-2007 Samsung Electronics
* Kyungmin Park <kyungmin.park@samsung.com>
*
* 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.
*/
#ifndef __ONENAND_REG_H
#define __ONENAND_REG_H
/* Memory Address Map Translation (Word order) */
#define ONENAND_MEMORY_MAP(x) ((x) << 1)
/*
* External BufferRAM area
*/
#define ONENAND_BOOTRAM ONENAND_MEMORY_MAP(0x0000)
#define ONENAND_DATARAM ONENAND_MEMORY_MAP(0x0200)
#define ONENAND_SPARERAM ONENAND_MEMORY_MAP(0x8010)
/*
* OneNAND Registers
*/
#define ONENAND_REG_MANUFACTURER_ID ONENAND_MEMORY_MAP(0xF000)
#define ONENAND_REG_DEVICE_ID ONENAND_MEMORY_MAP(0xF001)
#define ONENAND_REG_VERSION_ID ONENAND_MEMORY_MAP(0xF002)
#define ONENAND_REG_DATA_BUFFER_SIZE ONENAND_MEMORY_MAP(0xF003)
#define ONENAND_REG_BOOT_BUFFER_SIZE ONENAND_MEMORY_MAP(0xF004)
#define ONENAND_REG_NUM_BUFFERS ONENAND_MEMORY_MAP(0xF005)
#define ONENAND_REG_TECHNOLOGY ONENAND_MEMORY_MAP(0xF006)
#define ONENAND_REG_START_ADDRESS1 ONENAND_MEMORY_MAP(0xF100)
#define ONENAND_REG_START_ADDRESS2 ONENAND_MEMORY_MAP(0xF101)
#define ONENAND_REG_START_ADDRESS3 ONENAND_MEMORY_MAP(0xF102)
#define ONENAND_REG_START_ADDRESS4 ONENAND_MEMORY_MAP(0xF103)
#define ONENAND_REG_START_ADDRESS5 ONENAND_MEMORY_MAP(0xF104)
#define ONENAND_REG_START_ADDRESS6 ONENAND_MEMORY_MAP(0xF105)
#define ONENAND_REG_START_ADDRESS7 ONENAND_MEMORY_MAP(0xF106)
#define ONENAND_REG_START_ADDRESS8 ONENAND_MEMORY_MAP(0xF107)
#define ONENAND_REG_START_BUFFER ONENAND_MEMORY_MAP(0xF200)
#define ONENAND_REG_COMMAND ONENAND_MEMORY_MAP(0xF220)
#define ONENAND_REG_SYS_CFG1 ONENAND_MEMORY_MAP(0xF221)
#define ONENAND_REG_SYS_CFG2 ONENAND_MEMORY_MAP(0xF222)
#define ONENAND_REG_CTRL_STATUS ONENAND_MEMORY_MAP(0xF240)
#define ONENAND_REG_INTERRUPT ONENAND_MEMORY_MAP(0xF241)
#define ONENAND_REG_START_BLOCK_ADDRESS ONENAND_MEMORY_MAP(0xF24C)
#define ONENAND_REG_END_BLOCK_ADDRESS ONENAND_MEMORY_MAP(0xF24D)
#define ONENAND_REG_WP_STATUS ONENAND_MEMORY_MAP(0xF24E)
#define ONENAND_REG_ECC_STATUS ONENAND_MEMORY_MAP(0xFF00)
#define ONENAND_REG_ECC_M0 ONENAND_MEMORY_MAP(0xFF01)
#define ONENAND_REG_ECC_S0 ONENAND_MEMORY_MAP(0xFF02)
#define ONENAND_REG_ECC_M1 ONENAND_MEMORY_MAP(0xFF03)
#define ONENAND_REG_ECC_S1 ONENAND_MEMORY_MAP(0xFF04)
#define ONENAND_REG_ECC_M2 ONENAND_MEMORY_MAP(0xFF05)
#define ONENAND_REG_ECC_S2 ONENAND_MEMORY_MAP(0xFF06)
#define ONENAND_REG_ECC_M3 ONENAND_MEMORY_MAP(0xFF07)
#define ONENAND_REG_ECC_S3 ONENAND_MEMORY_MAP(0xFF08)
/*
* Device ID Register F001h (R)
*/
#define ONENAND_DEVICE_DENSITY_SHIFT (4)
#define ONENAND_DEVICE_IS_DDP (1 << 3)
#define ONENAND_DEVICE_IS_DEMUX (1 << 2)
#define ONENAND_DEVICE_VCC_MASK (0x3)
#define ONENAND_DEVICE_DENSITY_512Mb (0x002)
/*
* Version ID Register F002h (R)
*/
#define ONENAND_VERSION_PROCESS_SHIFT (8)
/*
* Start Address 1 F100h (R/W)
*/
#define ONENAND_DDP_SHIFT (15)
/*
* Start Address 8 F107h (R/W)
*/
#define ONENAND_FPA_MASK (0x3f)
#define ONENAND_FPA_SHIFT (2)
#define ONENAND_FSA_MASK (0x03)
/*
* Start Buffer Register F200h (R/W)
*/
#define ONENAND_BSA_MASK (0x03)
#define ONENAND_BSA_SHIFT (8)
#define ONENAND_BSA_BOOTRAM (0 << 2)
#define ONENAND_BSA_DATARAM0 (2 << 2)
#define ONENAND_BSA_DATARAM1 (3 << 2)
#define ONENAND_BSC_MASK (0x03)
/*
* Command Register F220h (R/W)
*/
#define ONENAND_CMD_READ (0x00)
#define ONENAND_CMD_READOOB (0x13)
#define ONENAND_CMD_PROG (0x80)
#define ONENAND_CMD_PROGOOB (0x1A)
#define ONENAND_CMD_UNLOCK (0x23)
#define ONENAND_CMD_LOCK (0x2A)
#define ONENAND_CMD_LOCK_TIGHT (0x2C)
#define ONENAND_CMD_ERASE (0x94)
#define ONENAND_CMD_RESET (0xF0)
#define ONENAND_CMD_READID (0x90)
/* NOTE: Those are not *REAL* commands */
#define ONENAND_CMD_BUFFERRAM (0x1978)
/*
* System Configuration 1 Register F221h (R, R/W)
*/
#define ONENAND_SYS_CFG1_SYNC_READ (1 << 15)
#define ONENAND_SYS_CFG1_BRL_7 (7 << 12)
#define ONENAND_SYS_CFG1_BRL_6 (6 << 12)
#define ONENAND_SYS_CFG1_BRL_5 (5 << 12)
#define ONENAND_SYS_CFG1_BRL_4 (4 << 12)
#define ONENAND_SYS_CFG1_BRL_3 (3 << 12)
#define ONENAND_SYS_CFG1_BRL_10 (2 << 12)
#define ONENAND_SYS_CFG1_BRL_9 (1 << 12)
#define ONENAND_SYS_CFG1_BRL_8 (0 << 12)
#define ONENAND_SYS_CFG1_BRL_SHIFT (12)
#define ONENAND_SYS_CFG1_BL_32 (4 << 9)
#define ONENAND_SYS_CFG1_BL_16 (3 << 9)
#define ONENAND_SYS_CFG1_BL_8 (2 << 9)
#define ONENAND_SYS_CFG1_BL_4 (1 << 9)
#define ONENAND_SYS_CFG1_BL_CONT (0 << 9)
#define ONENAND_SYS_CFG1_BL_SHIFT (9)
#define ONENAND_SYS_CFG1_NO_ECC (1 << 8)
#define ONENAND_SYS_CFG1_RDY (1 << 7)
#define ONENAND_SYS_CFG1_INT (1 << 6)
#define ONENAND_SYS_CFG1_IOBE (1 << 5)
#define ONENAND_SYS_CFG1_RDY_CONF (1 << 4)
/*
* Controller Status Register F240h (R)
*/
#define ONENAND_CTRL_ONGO (1 << 15)
#define ONENAND_CTRL_LOCK (1 << 14)
#define ONENAND_CTRL_LOAD (1 << 13)
#define ONENAND_CTRL_PROGRAM (1 << 12)
#define ONENAND_CTRL_ERASE (1 << 11)
#define ONENAND_CTRL_ERROR (1 << 10)
#define ONENAND_CTRL_RSTB (1 << 7)
/*
* Interrupt Status Register F241h (R)
*/
#define ONENAND_INT_MASTER (1 << 15)
#define ONENAND_INT_READ (1 << 7)
#define ONENAND_INT_WRITE (1 << 6)
#define ONENAND_INT_ERASE (1 << 5)
#define ONENAND_INT_RESET (1 << 4)
#define ONENAND_INT_CLEAR (0 << 0)
/*
* NAND Flash Write Protection Status Register F24Eh (R)
*/
#define ONENAND_WP_US (1 << 2)
#define ONENAND_WP_LS (1 << 1)
#define ONENAND_WP_LTS (1 << 0)
/*
* ECC Status Reigser FF00h (R)
*/
#define ONENAND_ECC_1BIT (1 << 0)
#define ONENAND_ECC_2BIT (1 << 1)
#define ONENAND_ECC_2BIT_ALL (0xAAAA)
#endif /* __ONENAND_REG_H */

39
include/onenand_uboot.h Normal file
View File

@ -0,0 +1,39 @@
/*
* Header file for OneNAND support for U-Boot
*
* Adaptation from kernel to U-Boot
*
* Copyright (C) 2005-2007 Samsung Electronics
* Kyungmin Park <kyungmin.park@samsung.com>
*
* 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.
*/
#ifndef __UBOOT_ONENAND_H
#define __UBOOT_ONENAND_H
struct kvec {
void *iov_base;
size_t iov_len;
};
typedef int spinlock_t;
typedef int wait_queue_head_t;
/* Functions */
extern void onenand_init(void);
extern int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t * retlen, u_char * buf);
extern int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
size_t * retlen, u_char * buf);
extern int onenand_write(struct mtd_info *mtd, loff_t from, size_t len,
size_t * retlen, const u_char * buf);
extern int onenand_erase(struct mtd_info *mtd, struct erase_info *instr);
extern int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len);
extern void onenand_print_device_info(int device, int verbose);
#endif /* __UBOOT_ONENAND_H */

View File

@ -58,6 +58,10 @@ DECLARE_GLOBAL_DATA_PTR;
void nand_init (void);
#endif
#if defined(CONFIG_CMD_ONENAND)
void onenand_init(void);
#endif
ulong monitor_flash_len;
#ifdef CONFIG_HAS_DATAFLASH
@ -301,6 +305,10 @@ void start_armboot (void)
nand_init(); /* go init the NAND */
#endif
#if defined(CONFIG_CMD_ONENAND)
onenand_init();
#endif
#ifdef CONFIG_HAS_DATAFLASH
AT91F_DataflashInit();
dataflash_print_info();