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>master
parent
17aa280045
commit
d7e8ce101a
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
Loading…
Reference in new issue