Commit cd5f6346 authored by Kyungmin Park's avatar Kyungmin Park Committed by Thomas Gleixner

[MTD] Add initial support for OneNAND flash chips

OneNAND is a new flash technology from Samsung with integrated SRAM
buffers and logic interface.
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 4ce1f562
# $Id: Kconfig,v 1.9 2005/06/16 08:49:29 sean Exp $ # $Id: Kconfig,v 1.10 2005/07/11 10:39:27 gleixner Exp $
menu "Memory Technology Devices (MTD)" menu "Memory Technology Devices (MTD)"
...@@ -259,9 +259,9 @@ config RFD_FTL ...@@ -259,9 +259,9 @@ config RFD_FTL
---help--- ---help---
This provides support for the flash translation layer known This provides support for the flash translation layer known
as the Resident Flash Disk (RFD), as used by the Embedded BIOS as the Resident Flash Disk (RFD), as used by the Embedded BIOS
of General Software. of General Software. There is a blurb at:
See http://www.gensw.com/pages/prod/bios/rfd.htm for further
information. http://www.gensw.com/pages/prod/bios/rfd.htm
source "drivers/mtd/chips/Kconfig" source "drivers/mtd/chips/Kconfig"
...@@ -271,5 +271,7 @@ source "drivers/mtd/devices/Kconfig" ...@@ -271,5 +271,7 @@ source "drivers/mtd/devices/Kconfig"
source "drivers/mtd/nand/Kconfig" source "drivers/mtd/nand/Kconfig"
source "drivers/mtd/onenand/Kconfig"
endmenu endmenu
# #
# Makefile for the memory technology device drivers. # Makefile for the memory technology device drivers.
# #
# $Id: Makefile.common,v 1.6 2005/06/16 08:49:29 sean Exp $ # $Id: Makefile.common,v 1.7 2005/07/11 10:39:27 gleixner Exp $
# Core functionality. # Core functionality.
mtd-y := mtdcore.o mtd-y := mtdcore.o
...@@ -25,4 +25,4 @@ obj-$(CONFIG_RFD_FTL) += rfd_ftl.o mtd_blkdevs.o ...@@ -25,4 +25,4 @@ obj-$(CONFIG_RFD_FTL) += rfd_ftl.o mtd_blkdevs.o
nftl-objs := nftlcore.o nftlmount.o nftl-objs := nftlcore.o nftlmount.o
inftl-objs := inftlcore.o inftlmount.o inftl-objs := inftlcore.o inftlmount.o
obj-y += chips/ maps/ devices/ nand/ obj-y += chips/ maps/ devices/ nand/ onenand/
#
# linux/drivers/mtd/onenand/Kconfig
#
menu "OneNAND Flash Device Drivers (EXPERIMENTAL)"
depends on MTD != n && EXPERIMENTAL
config MTD_ONENAND
tristate "OneNAND Device Support"
depends on MTD
help
This enables support for accessing all type of OneNAND flash
devices. For further information see
<http://www.samsung.com/Products/Semiconductor/Flash/OneNAND_TM/index.htm>.
config MTD_ONENAND_VERIFY_WRITE
bool "Verify OneNAND page writes"
depends on MTD_ONENAND
help
This adds an extra check when data is written to the flash. The
OneNAND flash device internally checks only bits transitioning
from 1 to 0. There is a rare possibility that even though the
device thinks the write was successful, a bit could have been
flipped accidentaly due to device wear or something else.
config MTD_ONENAND_OMAP
tristate "OneNAND Flash device on OMAP board"
depends on ARCH_OMAP && MTD_ONENAND
help
Support for OneNAND flash on TI OMAP board.
endmenu
#
# Makefile for the OneNAND MTD
#
# Core functionality.
obj-$(CONFIG_MTD_ONENAND) += onenand_base.o
# Board specific.
obj-$(CONFIG_MTD_ONENAND_OMAP) += omap-onenand.o
/*
* linux/drivers/mtd/onenand/omap-onenand.c
*
* Copyright (c) 2005 Samsung Electronics
* Kyungmin Park <kyungmin.park@samsung.com>
*
* Derived from linux/drivers/mtd/nand/omap-nand-flash.c
*
* 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.
*
* Overview:
* This is a device driver for the OneNAND flash device for TI OMAP boards.
*/
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
#include <asm/arch/tc.h>
#include <asm/sizes.h>
#define OMAP_ONENAND_FLASH_START1 OMAP_CS2A_PHYS
#define OMAP_ONENAND_FLASH_START2 OMAP_CS0_PHYS
/*
* MTD structure for OMAP board
*/
static struct mtd_info *omap_onenand_mtd = NULL;
/*
* Define partitions for flash devices
*/
#ifdef CONFIG_MTD_PARTITIONS
static struct mtd_partition static_partition[] = {
{
.name = "X-Loader + U-Boot",
.offset = 0,
.size = SZ_128K,
.mask_flags = MTD_WRITEABLE /* force read-only */
},
{
.name = "U-Boot Environment",
.offset = MTDPART_OFS_APPEND,
.size = SZ_128K,
.mask_flags = MTD_WRITEABLE /* force read-only */
},
{
.name = "kernel",
.offset = MTDPART_OFS_APPEND,
.size = 2 * SZ_1M
},
{
.name = "filesystem0",
.offset = MTDPART_OFS_APPEND,
.size = SZ_16M,
},
{
.name = "filesystem1",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL,
},
};
const char *part_probes[] = { "cmdlinepart", NULL, };
#endif
/* Scan to find existance of the device at base.
This also allocates oob and data internal buffers */
static char onenand_name[] = "onenand";
/*
* Main initialization routine
*/
static int __init omap_onenand_init (void)
{
struct onenand_chip *this;
struct mtd_partition *dynamic_partition = 0;
int err = 0;
/* Allocate memory for MTD device structure and private data */
omap_onenand_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct onenand_chip),
GFP_KERNEL);
if (!omap_onenand_mtd) {
printk (KERN_WARNING "Unable to allocate OneNAND MTD device structure.\n");
err = -ENOMEM;
goto out;
}
/* Get pointer to private data */
this = (struct onenand_chip *) (&omap_onenand_mtd[1]);
/* Initialize structures */
memset((char *) omap_onenand_mtd, 0, sizeof(struct mtd_info) + sizeof(struct onenand_chip));
/* Link the private data with the MTD structure */
omap_onenand_mtd->priv = this;
/* try the first address */
this->base = ioremap(OMAP_ONENAND_FLASH_START1, SZ_128K);
omap_onenand_mtd->name = onenand_name;
if (onenand_scan(omap_onenand_mtd, 1)){
/* try the second address */
iounmap(this->base);
this->base = ioremap(OMAP_ONENAND_FLASH_START2, SZ_128K);
if (onenand_scan(omap_onenand_mtd, 1)) {
iounmap(this->base);
err = -ENXIO;
goto out_mtd;
}
}
/* Register the partitions */
switch (omap_onenand_mtd->size) {
case SZ_128M:
case SZ_64M:
case SZ_32M:
#ifdef CONFIG_MTD_PARTITIONS
err = parse_mtd_partitions(omap_onenand_mtd, part_probes,
&dynamic_partition, 0);
if (err > 0)
err = add_mtd_partitions(omap_onenand_mtd,
dynamic_partition, err);
else if (1)
err = add_mtd_partitions(omap_onenand_mtd,
static_partition,
ARRAY_SIZE(static_partition));
else
#endif
err = add_mtd_device(omap_onenand_mtd);
if (err)
goto out_buf;
break;
default:
printk(KERN_WARNING "Unsupported OneNAND device\n");
err = -ENXIO;
goto out_buf;
}
return 0;
out_buf:
onenand_release(omap_onenand_mtd);
iounmap(this->base);
out_mtd:
kfree(omap_onenand_mtd);
out:
return err;
}
/*
* Clean up routine
*/
static void __exit omap_onenand_cleanup (void)
{
struct onenand_chip *this = omap_onenand_mtd->priv;
/* onenand_release frees MTD partitions, MTD structure
and onenand internal buffers */
onenand_release(omap_onenand_mtd);
iounmap(this->base);
kfree(omap_onenand_mtd);
}
module_init(omap_onenand_init);
module_exit(omap_onenand_cleanup);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>");
MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP boards");
This diff is collapsed.
/*
* linux/include/linux/mtd/onenand.h
*
* Copyright (C) 2005 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/spinlock.h>
#include <linux/mtd/onenand_regs.h>
#define MAX_BUFFERRAM 2
/* 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);
spinlock_t chip_lock;
wait_queue_head_t wq;
onenand_state_t state;
struct nand_oobinfo *autooob;
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 */
/*
* linux/include/linux/mtd/onenand_regs.h
*
* OneNAND Register header file
*
* Copyright (C) 2005 Samsung Electronics
*
* 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 (1 << 12)
#define ONENAND_SYS_CFG1_BL (1 << 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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment