Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

authored by

Kyungmin Park and committed by
Thomas Gleixner
cd5f6346 4ce1f562

+1990 -6
+6 -4
drivers/mtd/Kconfig
··· 1 - # $Id: Kconfig,v 1.9 2005/06/16 08:49:29 sean Exp $ 1 + # $Id: Kconfig,v 1.10 2005/07/11 10:39:27 gleixner Exp $ 2 2 3 3 menu "Memory Technology Devices (MTD)" 4 4 ··· 259 259 ---help--- 260 260 This provides support for the flash translation layer known 261 261 as the Resident Flash Disk (RFD), as used by the Embedded BIOS 262 - of General Software. 263 - See http://www.gensw.com/pages/prod/bios/rfd.htm for further 264 - information. 262 + of General Software. There is a blurb at: 263 + 264 + http://www.gensw.com/pages/prod/bios/rfd.htm 265 265 266 266 source "drivers/mtd/chips/Kconfig" 267 267 ··· 270 270 source "drivers/mtd/devices/Kconfig" 271 271 272 272 source "drivers/mtd/nand/Kconfig" 273 + 274 + source "drivers/mtd/onenand/Kconfig" 273 275 274 276 endmenu 275 277
+2 -2
drivers/mtd/Makefile
··· 1 1 # 2 2 # Makefile for the memory technology device drivers. 3 3 # 4 - # $Id: Makefile.common,v 1.6 2005/06/16 08:49:29 sean Exp $ 4 + # $Id: Makefile.common,v 1.7 2005/07/11 10:39:27 gleixner Exp $ 5 5 6 6 # Core functionality. 7 7 mtd-y := mtdcore.o ··· 25 25 nftl-objs := nftlcore.o nftlmount.o 26 26 inftl-objs := inftlcore.o inftlmount.o 27 27 28 - obj-y += chips/ maps/ devices/ nand/ 28 + obj-y += chips/ maps/ devices/ nand/ onenand/
+32
drivers/mtd/onenand/Kconfig
··· 1 + # 2 + # linux/drivers/mtd/onenand/Kconfig 3 + # 4 + 5 + menu "OneNAND Flash Device Drivers (EXPERIMENTAL)" 6 + depends on MTD != n && EXPERIMENTAL 7 + 8 + config MTD_ONENAND 9 + tristate "OneNAND Device Support" 10 + depends on MTD 11 + help 12 + This enables support for accessing all type of OneNAND flash 13 + devices. For further information see 14 + <http://www.samsung.com/Products/Semiconductor/Flash/OneNAND_TM/index.htm>. 15 + 16 + config MTD_ONENAND_VERIFY_WRITE 17 + bool "Verify OneNAND page writes" 18 + depends on MTD_ONENAND 19 + help 20 + This adds an extra check when data is written to the flash. The 21 + OneNAND flash device internally checks only bits transitioning 22 + from 1 to 0. There is a rare possibility that even though the 23 + device thinks the write was successful, a bit could have been 24 + flipped accidentaly due to device wear or something else. 25 + 26 + config MTD_ONENAND_OMAP 27 + tristate "OneNAND Flash device on OMAP board" 28 + depends on ARCH_OMAP && MTD_ONENAND 29 + help 30 + Support for OneNAND flash on TI OMAP board. 31 + 32 + endmenu
+9
drivers/mtd/onenand/Makefile
··· 1 + # 2 + # Makefile for the OneNAND MTD 3 + # 4 + 5 + # Core functionality. 6 + obj-$(CONFIG_MTD_ONENAND) += onenand_base.o 7 + 8 + # Board specific. 9 + obj-$(CONFIG_MTD_ONENAND_OMAP) += omap-onenand.o
+178
drivers/mtd/onenand/omap-onenand.c
··· 1 + /* 2 + * linux/drivers/mtd/onenand/omap-onenand.c 3 + * 4 + * Copyright (c) 2005 Samsung Electronics 5 + * Kyungmin Park <kyungmin.park@samsung.com> 6 + * 7 + * Derived from linux/drivers/mtd/nand/omap-nand-flash.c 8 + * 9 + * This program is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License version 2 as 11 + * published by the Free Software Foundation. 12 + * 13 + * Overview: 14 + * This is a device driver for the OneNAND flash device for TI OMAP boards. 15 + */ 16 + 17 + #include <linux/slab.h> 18 + #include <linux/init.h> 19 + #include <linux/module.h> 20 + #include <linux/mtd/mtd.h> 21 + #include <linux/mtd/onenand.h> 22 + #include <linux/mtd/partitions.h> 23 + 24 + #include <asm/io.h> 25 + #include <asm/arch/hardware.h> 26 + #include <asm/arch/tc.h> 27 + #include <asm/sizes.h> 28 + 29 + #define OMAP_ONENAND_FLASH_START1 OMAP_CS2A_PHYS 30 + #define OMAP_ONENAND_FLASH_START2 OMAP_CS0_PHYS 31 + /* 32 + * MTD structure for OMAP board 33 + */ 34 + static struct mtd_info *omap_onenand_mtd = NULL; 35 + 36 + /* 37 + * Define partitions for flash devices 38 + */ 39 + 40 + #ifdef CONFIG_MTD_PARTITIONS 41 + static struct mtd_partition static_partition[] = { 42 + { 43 + .name = "X-Loader + U-Boot", 44 + .offset = 0, 45 + .size = SZ_128K, 46 + .mask_flags = MTD_WRITEABLE /* force read-only */ 47 + }, 48 + { 49 + .name = "U-Boot Environment", 50 + .offset = MTDPART_OFS_APPEND, 51 + .size = SZ_128K, 52 + .mask_flags = MTD_WRITEABLE /* force read-only */ 53 + }, 54 + { 55 + .name = "kernel", 56 + .offset = MTDPART_OFS_APPEND, 57 + .size = 2 * SZ_1M 58 + }, 59 + { 60 + .name = "filesystem0", 61 + .offset = MTDPART_OFS_APPEND, 62 + .size = SZ_16M, 63 + }, 64 + { 65 + .name = "filesystem1", 66 + .offset = MTDPART_OFS_APPEND, 67 + .size = MTDPART_SIZ_FULL, 68 + }, 69 + }; 70 + 71 + const char *part_probes[] = { "cmdlinepart", NULL, }; 72 + 73 + #endif 74 + 75 + /* Scan to find existance of the device at base. 76 + This also allocates oob and data internal buffers */ 77 + static char onenand_name[] = "onenand"; 78 + 79 + /* 80 + * Main initialization routine 81 + */ 82 + static int __init omap_onenand_init (void) 83 + { 84 + struct onenand_chip *this; 85 + struct mtd_partition *dynamic_partition = 0; 86 + int err = 0; 87 + 88 + /* Allocate memory for MTD device structure and private data */ 89 + omap_onenand_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct onenand_chip), 90 + GFP_KERNEL); 91 + if (!omap_onenand_mtd) { 92 + printk (KERN_WARNING "Unable to allocate OneNAND MTD device structure.\n"); 93 + err = -ENOMEM; 94 + goto out; 95 + } 96 + 97 + /* Get pointer to private data */ 98 + this = (struct onenand_chip *) (&omap_onenand_mtd[1]); 99 + 100 + /* Initialize structures */ 101 + memset((char *) omap_onenand_mtd, 0, sizeof(struct mtd_info) + sizeof(struct onenand_chip)); 102 + 103 + /* Link the private data with the MTD structure */ 104 + omap_onenand_mtd->priv = this; 105 + 106 + /* try the first address */ 107 + this->base = ioremap(OMAP_ONENAND_FLASH_START1, SZ_128K); 108 + omap_onenand_mtd->name = onenand_name; 109 + if (onenand_scan(omap_onenand_mtd, 1)){ 110 + /* try the second address */ 111 + iounmap(this->base); 112 + this->base = ioremap(OMAP_ONENAND_FLASH_START2, SZ_128K); 113 + if (onenand_scan(omap_onenand_mtd, 1)) { 114 + iounmap(this->base); 115 + err = -ENXIO; 116 + goto out_mtd; 117 + } 118 + } 119 + 120 + /* Register the partitions */ 121 + switch (omap_onenand_mtd->size) { 122 + case SZ_128M: 123 + case SZ_64M: 124 + case SZ_32M: 125 + #ifdef CONFIG_MTD_PARTITIONS 126 + err = parse_mtd_partitions(omap_onenand_mtd, part_probes, 127 + &dynamic_partition, 0); 128 + if (err > 0) 129 + err = add_mtd_partitions(omap_onenand_mtd, 130 + dynamic_partition, err); 131 + else if (1) 132 + err = add_mtd_partitions(omap_onenand_mtd, 133 + static_partition, 134 + ARRAY_SIZE(static_partition)); 135 + else 136 + #endif 137 + err = add_mtd_device(omap_onenand_mtd); 138 + if (err) 139 + goto out_buf; 140 + break; 141 + 142 + default: 143 + printk(KERN_WARNING "Unsupported OneNAND device\n"); 144 + err = -ENXIO; 145 + goto out_buf; 146 + } 147 + 148 + return 0; 149 + 150 + out_buf: 151 + onenand_release(omap_onenand_mtd); 152 + iounmap(this->base); 153 + out_mtd: 154 + kfree(omap_onenand_mtd); 155 + out: 156 + return err; 157 + } 158 + 159 + /* 160 + * Clean up routine 161 + */ 162 + static void __exit omap_onenand_cleanup (void) 163 + { 164 + struct onenand_chip *this = omap_onenand_mtd->priv; 165 + 166 + /* onenand_release frees MTD partitions, MTD structure 167 + and onenand internal buffers */ 168 + onenand_release(omap_onenand_mtd); 169 + iounmap(this->base); 170 + kfree(omap_onenand_mtd); 171 + } 172 + 173 + module_init(omap_onenand_init); 174 + module_exit(omap_onenand_cleanup); 175 + 176 + MODULE_LICENSE("GPL"); 177 + MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>"); 178 + MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP boards");
+1462
drivers/mtd/onenand/onenand_base.c
··· 1 + /* 2 + * linux/drivers/mtd/onenand/onenand_base.c 3 + * 4 + * Copyright (C) 2005 Samsung Electronics 5 + * Kyungmin Park <kyungmin.park@samsung.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + */ 11 + 12 + #include <linux/kernel.h> 13 + #include <linux/module.h> 14 + #include <linux/init.h> 15 + #include <linux/mtd/mtd.h> 16 + #include <linux/mtd/onenand.h> 17 + #include <linux/mtd/partitions.h> 18 + 19 + #include <asm/io.h> 20 + 21 + /** 22 + * onenand_oob_64 - oob info for large (2KB) page 23 + */ 24 + static struct nand_oobinfo onenand_oob_64 = { 25 + .useecc = MTD_NANDECC_AUTOPLACE, 26 + .eccbytes = 20, 27 + .eccpos = { 28 + 8, 9, 10, 11, 12, 29 + 24, 25, 26, 27, 28, 30 + 40, 41, 42, 43, 44, 31 + 56, 57, 58, 59, 60, 32 + }, 33 + .oobfree = { 34 + {2, 3}, {14, 2}, {18, 3}, {30, 2}, 35 + {24, 3}, {46, 2}, {40, 3}, {62, 2} } 36 + }; 37 + 38 + /** 39 + * onenand_oob_32 - oob info for middle (1KB) page 40 + */ 41 + static struct nand_oobinfo onenand_oob_32 = { 42 + .useecc = MTD_NANDECC_AUTOPLACE, 43 + .eccbytes = 10, 44 + .eccpos = { 45 + 8, 9, 10, 11, 12, 46 + 24, 25, 26, 27, 28, 47 + }, 48 + .oobfree = { {2, 3}, {14, 2}, {18, 3}, {30, 2} } 49 + }; 50 + 51 + static const unsigned char ffchars[] = { 52 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 53 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16 */ 54 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 55 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 32 */ 56 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 57 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 48 */ 58 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 59 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 64 */ 60 + }; 61 + 62 + /** 63 + * onenand_readw - [OneNAND Interface] Read OneNAND register 64 + * @param addr address to read 65 + * 66 + * Read OneNAND register 67 + */ 68 + static unsigned short onenand_readw(void __iomem *addr) 69 + { 70 + return readw(addr); 71 + } 72 + 73 + /** 74 + * onenand_writew - [OneNAND Interface] Write OneNAND register with value 75 + * @param value value to write 76 + * @param addr address to write 77 + * 78 + * Write OneNAND register with value 79 + */ 80 + static void onenand_writew(unsigned short value, void __iomem *addr) 81 + { 82 + writew(value, addr); 83 + } 84 + 85 + /** 86 + * onenand_block_address - [DEFAULT] Get block address 87 + * @param device the device id 88 + * @param block the block 89 + * @return translated block address if DDP, otherwise same 90 + * 91 + * Setup Start Address 1 Register (F100h) 92 + */ 93 + static int onenand_block_address(int device, int block) 94 + { 95 + if (device & ONENAND_DEVICE_IS_DDP) { 96 + /* Device Flash Core select, NAND Flash Block Address */ 97 + int dfs = 0, density, mask; 98 + 99 + density = device >> ONENAND_DEVICE_DENSITY_SHIFT; 100 + mask = (1 << (density + 6)); 101 + 102 + if (block & mask) 103 + dfs = 1; 104 + 105 + return (dfs << ONENAND_DDP_SHIFT) | (block & (mask - 1)); 106 + } 107 + 108 + return block; 109 + } 110 + 111 + /** 112 + * onenand_bufferram_address - [DEFAULT] Get bufferram address 113 + * @param device the device id 114 + * @param block the block 115 + * @return set DBS value if DDP, otherwise 0 116 + * 117 + * Setup Start Address 2 Register (F101h) for DDP 118 + */ 119 + static int onenand_bufferram_address(int device, int block) 120 + { 121 + if (device & ONENAND_DEVICE_IS_DDP) { 122 + /* Device BufferRAM Select */ 123 + int dbs = 0, density, mask; 124 + 125 + density = device >> ONENAND_DEVICE_DENSITY_SHIFT; 126 + mask = (1 << (density + 6)); 127 + 128 + if (block & mask) 129 + dbs = 1; 130 + 131 + return (dbs << ONENAND_DDP_SHIFT); 132 + } 133 + 134 + return 0; 135 + } 136 + 137 + /** 138 + * onenand_page_address - [DEFAULT] Get page address 139 + * @param page the page address 140 + * @param sector the sector address 141 + * @return combined page and sector address 142 + * 143 + * Setup Start Address 8 Register (F107h) 144 + */ 145 + static int onenand_page_address(int page, int sector) 146 + { 147 + /* Flash Page Address, Flash Sector Address */ 148 + int fpa, fsa; 149 + 150 + fpa = page & ONENAND_FPA_MASK; 151 + fsa = sector & ONENAND_FSA_MASK; 152 + 153 + return ((fpa << ONENAND_FPA_SHIFT) | fsa); 154 + } 155 + 156 + /** 157 + * onenand_buffer_address - [DEFAULT] Get buffer address 158 + * @param dataram1 DataRAM index 159 + * @param sectors the sector address 160 + * @param count the number of sectors 161 + * @return the start buffer value 162 + * 163 + * Setup Start Buffer Register (F200h) 164 + */ 165 + static int onenand_buffer_address(int dataram1, int sectors, int count) 166 + { 167 + int bsa, bsc; 168 + 169 + /* BufferRAM Sector Address */ 170 + bsa = sectors & ONENAND_BSA_MASK; 171 + 172 + if (dataram1) 173 + bsa |= ONENAND_BSA_DATARAM1; /* DataRAM1 */ 174 + else 175 + bsa |= ONENAND_BSA_DATARAM0; /* DataRAM0 */ 176 + 177 + /* BufferRAM Sector Count */ 178 + bsc = count & ONENAND_BSC_MASK; 179 + 180 + return ((bsa << ONENAND_BSA_SHIFT) | bsc); 181 + } 182 + 183 + /** 184 + * onenand_command - [DEFAULT] Send command to OneNAND device 185 + * @param mtd MTD device structure 186 + * @param cmd the command to be sent 187 + * @param addr offset to read from or write to 188 + * @param len number of bytes to read or write 189 + * 190 + * Send command to OneNAND device. This function is used for middle/large page 191 + * devices (1KB/2KB Bytes per page) 192 + */ 193 + static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t len) 194 + { 195 + struct onenand_chip *this = mtd->priv; 196 + int value, readcmd = 0; 197 + int block, page; 198 + /* Now we use page size operation */ 199 + int sectors = 4, count = 4; 200 + 201 + /* Address translation */ 202 + switch (cmd) { 203 + case ONENAND_CMD_UNLOCK: 204 + case ONENAND_CMD_LOCK: 205 + case ONENAND_CMD_LOCK_TIGHT: 206 + block = -1; 207 + page = -1; 208 + break; 209 + 210 + case ONENAND_CMD_ERASE: 211 + case ONENAND_CMD_BUFFERRAM: 212 + block = (int) (addr >> this->erase_shift); 213 + page = -1; 214 + break; 215 + 216 + default: 217 + block = (int) (addr >> this->erase_shift); 218 + page = (int) (addr >> this->page_shift); 219 + page &= this->page_mask; 220 + break; 221 + } 222 + 223 + /* NOTE: The setting order of the registers is very important! */ 224 + if (cmd == ONENAND_CMD_BUFFERRAM) { 225 + /* Select DataRAM for DDP */ 226 + value = onenand_bufferram_address(this->device_id, block); 227 + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); 228 + 229 + /* Switch to the next data buffer */ 230 + ONENAND_SET_NEXT_BUFFERRAM(this); 231 + 232 + return 0; 233 + } 234 + 235 + if (block != -1) { 236 + /* Write 'DFS, FBA' of Flash */ 237 + value = onenand_block_address(this->device_id, block); 238 + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); 239 + } 240 + 241 + if (page != -1) { 242 + int dataram; 243 + 244 + switch (cmd) { 245 + case ONENAND_CMD_READ: 246 + case ONENAND_CMD_READOOB: 247 + dataram = ONENAND_SET_NEXT_BUFFERRAM(this); 248 + readcmd = 1; 249 + break; 250 + 251 + default: 252 + dataram = ONENAND_CURRENT_BUFFERRAM(this); 253 + break; 254 + } 255 + 256 + /* Write 'FPA, FSA' of Flash */ 257 + value = onenand_page_address(page, sectors); 258 + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS8); 259 + 260 + /* Write 'BSA, BSC' of DataRAM */ 261 + value = onenand_buffer_address(dataram, sectors, count); 262 + this->write_word(value, this->base + ONENAND_REG_START_BUFFER); 263 + 264 + if (readcmd) { 265 + /* Select DataRAM for DDP */ 266 + value = onenand_bufferram_address(this->device_id, block); 267 + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); 268 + } 269 + } 270 + 271 + /* Interrupt clear */ 272 + this->write_word(ONENAND_INT_CLEAR, this->base + ONENAND_REG_INTERRUPT); 273 + 274 + /* Write command */ 275 + this->write_word(cmd, this->base + ONENAND_REG_COMMAND); 276 + 277 + return 0; 278 + } 279 + 280 + /** 281 + * onenand_wait - [DEFAULT] wait until the command is done 282 + * @param mtd MTD device structure 283 + * @param state state to select the max. timeout value 284 + * 285 + * Wait for command done. This applies to all OneNAND command 286 + * Read can take up to 30us, erase up to 2ms and program up to 350us 287 + * according to general OneNAND specs 288 + */ 289 + static int onenand_wait(struct mtd_info *mtd, int state) 290 + { 291 + struct onenand_chip * this = mtd->priv; 292 + unsigned long timeout; 293 + unsigned int flags = ONENAND_INT_MASTER; 294 + unsigned int interrupt = 0; 295 + unsigned int ctrl, ecc; 296 + 297 + /* The 20 msec is enough */ 298 + timeout = jiffies + msecs_to_jiffies(20); 299 + while (time_before(jiffies, timeout)) { 300 + interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); 301 + 302 + if (interrupt & flags) 303 + break; 304 + 305 + if (state != FL_READING) 306 + cond_resched(); 307 + } 308 + /* To get correct interrupt status in timeout case */ 309 + interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); 310 + 311 + ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); 312 + 313 + if (ctrl & ONENAND_CTRL_ERROR) { 314 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x", ctrl); 315 + return -EIO; 316 + } 317 + 318 + if (ctrl & ONENAND_CTRL_LOCK) { 319 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error = 0x%04x", ctrl); 320 + return -EIO; 321 + } 322 + 323 + if (interrupt & ONENAND_INT_READ) { 324 + ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS); 325 + if (ecc & ONENAND_ECC_2BIT_ALL) { 326 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x", ecc); 327 + return -EBADMSG; 328 + } 329 + } 330 + 331 + return 0; 332 + } 333 + 334 + /** 335 + * onenand_bufferram_offset - [DEFAULT] BufferRAM offset 336 + * @param mtd MTD data structure 337 + * @param area BufferRAM area 338 + * @return offset given area 339 + * 340 + * Return BufferRAM offset given area 341 + */ 342 + static inline int onenand_bufferram_offset(struct mtd_info *mtd, int area) 343 + { 344 + struct onenand_chip *this = mtd->priv; 345 + 346 + if (ONENAND_CURRENT_BUFFERRAM(this)) { 347 + if (area == ONENAND_DATARAM) 348 + return mtd->oobblock; 349 + if (area == ONENAND_SPARERAM) 350 + return mtd->oobsize; 351 + } 352 + 353 + return 0; 354 + } 355 + 356 + /** 357 + * onenand_read_bufferram - [OneNAND Interface] Read the bufferram area 358 + * @param mtd MTD data structure 359 + * @param area BufferRAM area 360 + * @param buffer the databuffer to put/get data 361 + * @param offset offset to read from or write to 362 + * @param count number of bytes to read/write 363 + * 364 + * Read the BufferRAM area 365 + */ 366 + static int onenand_read_bufferram(struct mtd_info *mtd, int area, 367 + unsigned char *buffer, int offset, size_t count) 368 + { 369 + struct onenand_chip *this = mtd->priv; 370 + void __iomem *bufferram; 371 + 372 + bufferram = this->base + area; 373 + 374 + bufferram += onenand_bufferram_offset(mtd, area); 375 + 376 + memcpy(buffer, bufferram + offset, count); 377 + 378 + return 0; 379 + } 380 + 381 + /** 382 + * onenand_write_bufferram - [OneNAND Interface] Write the bufferram area 383 + * @param mtd MTD data structure 384 + * @param area BufferRAM area 385 + * @param buffer the databuffer to put/get data 386 + * @param offset offset to read from or write to 387 + * @param count number of bytes to read/write 388 + * 389 + * Write the BufferRAM area 390 + */ 391 + static int onenand_write_bufferram(struct mtd_info *mtd, int area, 392 + const unsigned char *buffer, int offset, size_t count) 393 + { 394 + struct onenand_chip *this = mtd->priv; 395 + void __iomem *bufferram; 396 + 397 + bufferram = this->base + area; 398 + 399 + bufferram += onenand_bufferram_offset(mtd, area); 400 + 401 + memcpy(bufferram + offset, buffer, count); 402 + 403 + return 0; 404 + } 405 + 406 + /** 407 + * onenand_check_bufferram - [GENERIC] Check BufferRAM information 408 + * @param mtd MTD data structure 409 + * @param addr address to check 410 + * @return 1 if there are valid data, otherwise 0 411 + * 412 + * Check bufferram if there is data we required 413 + */ 414 + static int onenand_check_bufferram(struct mtd_info *mtd, loff_t addr) 415 + { 416 + struct onenand_chip *this = mtd->priv; 417 + int block, page; 418 + int i; 419 + 420 + block = (int) (addr >> this->erase_shift); 421 + page = (int) (addr >> this->page_shift); 422 + page &= this->page_mask; 423 + 424 + i = ONENAND_CURRENT_BUFFERRAM(this); 425 + 426 + /* Is there valid data? */ 427 + if (this->bufferram[i].block == block && 428 + this->bufferram[i].page == page && 429 + this->bufferram[i].valid) 430 + return 1; 431 + 432 + return 0; 433 + } 434 + 435 + /** 436 + * onenand_update_bufferram - [GENERIC] Update BufferRAM information 437 + * @param mtd MTD data structure 438 + * @param addr address to update 439 + * @param valid valid flag 440 + * 441 + * Update BufferRAM information 442 + */ 443 + static int onenand_update_bufferram(struct mtd_info *mtd, loff_t addr, 444 + int valid) 445 + { 446 + struct onenand_chip *this = mtd->priv; 447 + int block, page; 448 + int i; 449 + 450 + block = (int) (addr >> this->erase_shift); 451 + page = (int) (addr >> this->page_shift); 452 + page &= this->page_mask; 453 + 454 + /* Invalidate BufferRAM */ 455 + for (i = 0; i < MAX_BUFFERRAM; i++) { 456 + if (this->bufferram[i].block == block && 457 + this->bufferram[i].page == page) 458 + this->bufferram[i].valid = 0; 459 + } 460 + 461 + /* Update BufferRAM */ 462 + i = ONENAND_CURRENT_BUFFERRAM(this); 463 + this->bufferram[i].block = block; 464 + this->bufferram[i].page = page; 465 + this->bufferram[i].valid = valid; 466 + 467 + return 0; 468 + } 469 + 470 + /** 471 + * onenand_get_device - [GENERIC] Get chip for selected access 472 + * @param mtd MTD device structure 473 + * @param new_state the state which is requested 474 + * 475 + * Get the device and lock it for exclusive access 476 + */ 477 + static void onenand_get_device(struct mtd_info *mtd, int new_state) 478 + { 479 + struct onenand_chip *this = mtd->priv; 480 + DECLARE_WAITQUEUE(wait, current); 481 + 482 + /* 483 + * Grab the lock and see if the device is available 484 + */ 485 + while (1) { 486 + spin_lock(&this->chip_lock); 487 + if (this->state == FL_READY) { 488 + this->state = new_state; 489 + spin_unlock(&this->chip_lock); 490 + break; 491 + } 492 + set_current_state(TASK_UNINTERRUPTIBLE); 493 + add_wait_queue(&this->wq, &wait); 494 + spin_unlock(&this->chip_lock); 495 + schedule(); 496 + remove_wait_queue(&this->wq, &wait); 497 + } 498 + } 499 + 500 + /** 501 + * onenand_release_device - [GENERIC] release chip 502 + * @param mtd MTD device structure 503 + * 504 + * Deselect, release chip lock and wake up anyone waiting on the device 505 + */ 506 + static void onenand_release_device(struct mtd_info *mtd) 507 + { 508 + struct onenand_chip *this = mtd->priv; 509 + 510 + /* Release the chip */ 511 + spin_lock(&this->chip_lock); 512 + this->state = FL_READY; 513 + wake_up(&this->wq); 514 + spin_unlock(&this->chip_lock); 515 + } 516 + 517 + /** 518 + * onenand_read_ecc - [MTD Interface] Read data with ECC 519 + * @param mtd MTD device structure 520 + * @param from offset to read from 521 + * @param len number of bytes to read 522 + * @param retlen pointer to variable to store the number of read bytes 523 + * @param buf the databuffer to put data 524 + * @param oob_buf filesystem supplied oob data buffer 525 + * @param oobsel oob selection structure 526 + * 527 + * OneNAND read with ECC 528 + */ 529 + static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, 530 + size_t *retlen, u_char *buf, 531 + u_char *oob_buf, struct nand_oobinfo *oobsel) 532 + { 533 + struct onenand_chip *this = mtd->priv; 534 + int read = 0, column; 535 + int thislen; 536 + int ret = 0; 537 + 538 + DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); 539 + 540 + /* Do not allow reads past end of device */ 541 + if ((from + len) > mtd->size) { 542 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_ecc: Attempt read beyond end of device\n"); 543 + *retlen = 0; 544 + return -EINVAL; 545 + } 546 + 547 + /* Grab the lock and see if the device is available */ 548 + onenand_get_device(mtd, FL_READING); 549 + 550 + /* TODO handling oob */ 551 + 552 + while (read < len) { 553 + thislen = min_t(int, mtd->oobblock, len - read); 554 + 555 + column = from & (mtd->oobblock - 1); 556 + if (column + thislen > mtd->oobblock) 557 + thislen = mtd->oobblock - column; 558 + 559 + if (!onenand_check_bufferram(mtd, from)) { 560 + this->command(mtd, ONENAND_CMD_READ, from, mtd->oobblock); 561 + 562 + ret = this->wait(mtd, FL_READING); 563 + /* First copy data and check return value for ECC handling */ 564 + onenand_update_bufferram(mtd, from, 1); 565 + } 566 + 567 + this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen); 568 + 569 + read += thislen; 570 + 571 + if (read == len) 572 + break; 573 + 574 + if (ret) { 575 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_ecc: read failed = %d\n", ret); 576 + goto out; 577 + } 578 + 579 + from += thislen; 580 + buf += thislen; 581 + } 582 + 583 + out: 584 + /* Deselect and wake up anyone waiting on the device */ 585 + onenand_release_device(mtd); 586 + 587 + /* 588 + * Return success, if no ECC failures, else -EBADMSG 589 + * fs driver will take care of that, because 590 + * retlen == desired len and result == -EBADMSG 591 + */ 592 + *retlen = read; 593 + return ret; 594 + } 595 + 596 + /** 597 + * onenand_read - [MTD Interface] MTD compability function for onenand_read_ecc 598 + * @param mtd MTD device structure 599 + * @param from offset to read from 600 + * @param len number of bytes to read 601 + * @param retlen pointer to variable to store the number of read bytes 602 + * @param buf the databuffer to put data 603 + * 604 + * This function simply calls onenand_read_ecc with oob buffer and oobsel = NULL 605 + */ 606 + static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len, 607 + size_t *retlen, u_char *buf) 608 + { 609 + return onenand_read_ecc(mtd, from, len, retlen, buf, NULL, NULL); 610 + } 611 + 612 + /** 613 + * onenand_read_oob - [MTD Interface] OneNAND read out-of-band 614 + * @param mtd MTD device structure 615 + * @param from offset to read from 616 + * @param len number of bytes to read 617 + * @param retlen pointer to variable to store the number of read bytes 618 + * @param buf the databuffer to put data 619 + * 620 + * OneNAND read out-of-band data from the spare area 621 + */ 622 + static int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len, 623 + size_t *retlen, u_char *buf) 624 + { 625 + struct onenand_chip *this = mtd->priv; 626 + int read = 0, thislen, column; 627 + int ret = 0; 628 + 629 + DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); 630 + 631 + /* Initialize return length value */ 632 + *retlen = 0; 633 + 634 + /* Do not allow reads past end of device */ 635 + if (unlikely((from + len) > mtd->size)) { 636 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: Attempt read beyond end of device\n"); 637 + return -EINVAL; 638 + } 639 + 640 + /* Grab the lock and see if the device is available */ 641 + onenand_get_device(mtd, FL_READING); 642 + 643 + column = from & (mtd->oobsize - 1); 644 + 645 + while (read < len) { 646 + thislen = mtd->oobsize - column; 647 + thislen = min_t(int, thislen, len); 648 + 649 + this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize); 650 + 651 + onenand_update_bufferram(mtd, from, 0); 652 + 653 + ret = this->wait(mtd, FL_READING); 654 + /* First copy data and check return value for ECC handling */ 655 + 656 + this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); 657 + 658 + read += thislen; 659 + 660 + if (read == len) 661 + break; 662 + 663 + if (ret) { 664 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: read failed = %d\n", ret); 665 + goto out; 666 + } 667 + 668 + buf += thislen; 669 + 670 + /* Read more? */ 671 + if (read < len) { 672 + /* Page size */ 673 + from += mtd->oobblock; 674 + column = 0; 675 + } 676 + } 677 + 678 + out: 679 + /* Deselect and wake up anyone waiting on the device */ 680 + onenand_release_device(mtd); 681 + 682 + *retlen = read; 683 + return ret; 684 + } 685 + 686 + #ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE 687 + /** 688 + * onenand_verify_page - [GENERIC] verify the chip contents after a write 689 + * @param mtd MTD device structure 690 + * @param buf the databuffer to verify 691 + * @param block block address 692 + * @param page page address 693 + * 694 + * Check DataRAM area directly 695 + */ 696 + static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, 697 + loff_t addr, int block, int page) 698 + { 699 + struct onenand_chip *this = mtd->priv; 700 + void __iomem *dataram0, *dataram1; 701 + int ret = 0; 702 + 703 + this->command(mtd, ONENAND_CMD_READ, addr, mtd->oobblock); 704 + 705 + ret = this->wait(mtd, FL_READING); 706 + if (ret) 707 + return ret; 708 + 709 + onenand_update_bufferram(mtd, addr, 1); 710 + 711 + /* Check, if the two dataram areas are same */ 712 + dataram0 = this->base + ONENAND_DATARAM; 713 + dataram1 = dataram0 + mtd->oobblock; 714 + 715 + if (memcmp(dataram0, dataram1, mtd->oobblock)) 716 + return -EBADMSG; 717 + 718 + return 0; 719 + } 720 + #else 721 + #define onenand_verify_page(...) (0) 722 + #endif 723 + 724 + #define NOTALIGNED(x) ((x & (mtd->oobblock - 1)) != 0) 725 + 726 + /** 727 + * onenand_write_ecc - [MTD Interface] OneNAND write with ECC 728 + * @param mtd MTD device structure 729 + * @param to offset to write to 730 + * @param len number of bytes to write 731 + * @param retlen pointer to variable to store the number of written bytes 732 + * @param buf the data to write 733 + * @param eccbuf filesystem supplied oob data buffer 734 + * @param oobsel oob selection structure 735 + * 736 + * OneNAND write with ECC 737 + */ 738 + static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, 739 + size_t *retlen, const u_char *buf, 740 + u_char *eccbuf, struct nand_oobinfo *oobsel) 741 + { 742 + struct onenand_chip *this = mtd->priv; 743 + int written = 0; 744 + int ret = 0; 745 + 746 + DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); 747 + 748 + /* Initialize retlen, in case of early exit */ 749 + *retlen = 0; 750 + 751 + /* Do not allow writes past end of device */ 752 + if (unlikely((to + len) > mtd->size)) { 753 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: Attempt write to past end of device\n"); 754 + return -EINVAL; 755 + } 756 + 757 + /* Reject writes, which are not page aligned */ 758 + if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) { 759 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: Attempt to write not page aligned data\n"); 760 + return -EINVAL; 761 + } 762 + 763 + /* Grab the lock and see if the device is available */ 764 + onenand_get_device(mtd, FL_WRITING); 765 + 766 + /* Loop until all data write */ 767 + while (written < len) { 768 + int thislen = min_t(int, mtd->oobblock, len - written); 769 + 770 + this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock); 771 + 772 + this->write_bufferram(mtd, ONENAND_DATARAM, buf, 0, thislen); 773 + this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize); 774 + 775 + this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock); 776 + 777 + onenand_update_bufferram(mtd, to, 1); 778 + 779 + ret = this->wait(mtd, FL_WRITING); 780 + if (ret) { 781 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: write filaed %d\n", ret); 782 + goto out; 783 + } 784 + 785 + written += thislen; 786 + 787 + /* Only check verify write turn on */ 788 + ret = onenand_verify_page(mtd, (u_char *) buf, to, block, page); 789 + if (ret) { 790 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: verify failed %d\n", ret); 791 + goto out; 792 + } 793 + 794 + if (written == len) 795 + break; 796 + 797 + to += thislen; 798 + buf += thislen; 799 + } 800 + 801 + out: 802 + /* Deselect and wake up anyone waiting on the device */ 803 + onenand_release_device(mtd); 804 + 805 + *retlen = written; 806 + 807 + return ret; 808 + } 809 + 810 + /** 811 + * onenand_write - [MTD Interface] compability function for onenand_write_ecc 812 + * @param mtd MTD device structure 813 + * @param to offset to write to 814 + * @param len number of bytes to write 815 + * @param retlen pointer to variable to store the number of written bytes 816 + * @param buf the data to write 817 + * 818 + * This function simply calls onenand_write_ecc 819 + * with oob buffer and oobsel = NULL 820 + */ 821 + static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len, 822 + size_t *retlen, const u_char *buf) 823 + { 824 + return onenand_write_ecc(mtd, to, len, retlen, buf, NULL, NULL); 825 + } 826 + 827 + /** 828 + * onenand_write_oob - [MTD Interface] OneNAND write out-of-band 829 + * @param mtd MTD device structure 830 + * @param to offset to write to 831 + * @param len number of bytes to write 832 + * @param retlen pointer to variable to store the number of written bytes 833 + * @param buf the data to write 834 + * 835 + * OneNAND write out-of-band 836 + */ 837 + static int onenand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, 838 + size_t *retlen, const u_char *buf) 839 + { 840 + struct onenand_chip *this = mtd->priv; 841 + int column, status; 842 + int written = 0; 843 + 844 + DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); 845 + 846 + /* Initialize retlen, in case of early exit */ 847 + *retlen = 0; 848 + 849 + /* Do not allow writes past end of device */ 850 + if (unlikely((to + len) > mtd->size)) { 851 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: Attempt write to past end of device\n"); 852 + return -EINVAL; 853 + } 854 + 855 + /* Grab the lock and see if the device is available */ 856 + onenand_get_device(mtd, FL_WRITING); 857 + 858 + /* Loop until all data write */ 859 + while (written < len) { 860 + int thislen = min_t(int, mtd->oobsize, len - written); 861 + 862 + column = to & (mtd->oobsize - 1); 863 + 864 + this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobsize); 865 + 866 + this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize); 867 + this->write_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); 868 + 869 + this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize); 870 + 871 + onenand_update_bufferram(mtd, to, 0); 872 + 873 + status = this->wait(mtd, FL_WRITING); 874 + if (status) 875 + goto out; 876 + 877 + written += thislen; 878 + 879 + if (written == len) 880 + break; 881 + 882 + to += thislen; 883 + buf += thislen; 884 + } 885 + 886 + out: 887 + /* Deselect and wake up anyone waiting on the device */ 888 + onenand_release_device(mtd); 889 + 890 + *retlen = written; 891 + 892 + return 0; 893 + } 894 + 895 + /** 896 + * onenand_writev_ecc - [MTD Interface] write with iovec with ecc 897 + * @param mtd MTD device structure 898 + * @param vecs the iovectors to write 899 + * @param count number of vectors 900 + * @param to offset to write to 901 + * @param retlen pointer to variable to store the number of written bytes 902 + * @param eccbuf filesystem supplied oob data buffer 903 + * @param oobsel oob selection structure 904 + * 905 + * OneNAND write with iovec with ecc 906 + */ 907 + static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, 908 + unsigned long count, loff_t to, size_t *retlen, 909 + u_char *eccbuf, struct nand_oobinfo *oobsel) 910 + { 911 + struct onenand_chip *this = mtd->priv; 912 + unsigned char buffer[mtd->oobblock], *pbuf; 913 + size_t total_len, len; 914 + int i, written = 0; 915 + int ret = 0; 916 + 917 + /* Preset written len for early exit */ 918 + *retlen = 0; 919 + 920 + /* Calculate total length of data */ 921 + total_len = 0; 922 + for (i = 0; i < count; i++) 923 + total_len += vecs[i].iov_len; 924 + 925 + DEBUG(MTD_DEBUG_LEVEL3, "onenand_writev_ecc: to = 0x%08x, len = %i, count = %ld\n", (unsigned int) to, (unsigned int) total_len, count); 926 + 927 + /* Do not allow write past end of the device */ 928 + if (unlikely((to + total_len) > mtd->size)) { 929 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: Attempted write past end of device\n"); 930 + return -EINVAL; 931 + } 932 + 933 + /* Reject writes, which are not page aligned */ 934 + if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(total_len))) { 935 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: Attempt to write not page aligned data\n"); 936 + return -EINVAL; 937 + } 938 + 939 + /* Grab the lock and see if the device is available */ 940 + onenand_get_device(mtd, FL_WRITING); 941 + 942 + /* TODO handling oob */ 943 + 944 + /* Loop until all keve's data has been written */ 945 + len = 0; 946 + while (count) { 947 + pbuf = buffer; 948 + /* 949 + * If the given tuple is >= pagesize then 950 + * write it out from the iov 951 + */ 952 + if ((vecs->iov_len - len) >= mtd->oobblock) { 953 + pbuf = vecs->iov_base + len; 954 + 955 + len += mtd->oobblock; 956 + 957 + /* Check, if we have to switch to the next tuple */ 958 + if (len >= (int) vecs->iov_len) { 959 + vecs++; 960 + len = 0; 961 + count--; 962 + } 963 + } else { 964 + int cnt = 0, thislen; 965 + while (cnt < mtd->oobblock) { 966 + thislen = min_t(int, mtd->oobblock - cnt, vecs->iov_len - len); 967 + memcpy(buffer + cnt, vecs->iov_base + len, thislen); 968 + cnt += thislen; 969 + len += thislen; 970 + 971 + /* Check, if we have to switch to the next tuple */ 972 + if (len >= (int) vecs->iov_len) { 973 + vecs++; 974 + len = 0; 975 + count--; 976 + } 977 + } 978 + } 979 + 980 + this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock); 981 + 982 + this->write_bufferram(mtd, ONENAND_DATARAM, pbuf, 0, mtd->oobblock); 983 + this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize); 984 + 985 + this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock); 986 + 987 + onenand_update_bufferram(mtd, to, 1); 988 + 989 + ret = this->wait(mtd, FL_WRITING); 990 + if (ret) { 991 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: write failed %d\n", ret); 992 + goto out; 993 + } 994 + 995 + 996 + /* Only check verify write turn on */ 997 + ret = onenand_verify_page(mtd, (u_char *) pbuf, to, block, page); 998 + if (ret) { 999 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: verify failed %d\n", ret); 1000 + goto out; 1001 + } 1002 + 1003 + written += mtd->oobblock; 1004 + 1005 + to += mtd->oobblock; 1006 + } 1007 + 1008 + out: 1009 + /* Deselect and wakt up anyone waiting on the device */ 1010 + onenand_release_device(mtd); 1011 + 1012 + *retlen = written; 1013 + 1014 + return 0; 1015 + } 1016 + 1017 + /** 1018 + * onenand_writev - [MTD Interface] compabilty function for onenand_writev_ecc 1019 + * @param mtd MTD device structure 1020 + * @param vecs the iovectors to write 1021 + * @param count number of vectors 1022 + * @param to offset to write to 1023 + * @param retlen pointer to variable to store the number of written bytes 1024 + * 1025 + * OneNAND write with kvec. This just calls the ecc function 1026 + */ 1027 + static int onenand_writev(struct mtd_info *mtd, const struct kvec *vecs, 1028 + unsigned long count, loff_t to, size_t *retlen) 1029 + { 1030 + return onenand_writev_ecc(mtd, vecs, count, to, retlen, NULL, NULL); 1031 + } 1032 + 1033 + /** 1034 + * onenand_erase - [MTD Interface] erase block(s) 1035 + * @param mtd MTD device structure 1036 + * @param instr erase instruction 1037 + * 1038 + * Erase one ore more blocks 1039 + */ 1040 + static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr) 1041 + { 1042 + struct onenand_chip *this = mtd->priv; 1043 + unsigned int block_size; 1044 + loff_t addr; 1045 + int len; 1046 + int ret = 0; 1047 + 1048 + DEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%08x, len = %i\n", (unsigned int) instr->addr, (unsigned int) instr->len); 1049 + 1050 + block_size = (1 << this->erase_shift); 1051 + 1052 + /* Start address must align on block boundary */ 1053 + if (unlikely(instr->addr & (block_size - 1))) { 1054 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Unaligned address\n"); 1055 + return -EINVAL; 1056 + } 1057 + 1058 + /* Length must align on block boundary */ 1059 + if (unlikely(instr->len & (block_size - 1))) { 1060 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Length not block aligned\n"); 1061 + return -EINVAL; 1062 + } 1063 + 1064 + /* Do not allow erase past end of device */ 1065 + if (unlikely((instr->len + instr->addr) > mtd->size)) { 1066 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Erase past end of device\n"); 1067 + return -EINVAL; 1068 + } 1069 + 1070 + instr->fail_addr = 0xffffffff; 1071 + 1072 + /* Grab the lock and see if the device is available */ 1073 + onenand_get_device(mtd, FL_ERASING); 1074 + 1075 + /* Loop throught the pages */ 1076 + len = instr->len; 1077 + addr = instr->addr; 1078 + 1079 + instr->state = MTD_ERASING; 1080 + 1081 + while (len) { 1082 + 1083 + /* TODO Check badblock */ 1084 + 1085 + this->command(mtd, ONENAND_CMD_ERASE, addr, block_size); 1086 + 1087 + ret = this->wait(mtd, FL_ERASING); 1088 + /* Check, if it is write protected */ 1089 + if (ret) { 1090 + if (ret == -EPERM) 1091 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Device is write protected!!!\n"); 1092 + else 1093 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift)); 1094 + instr->state = MTD_ERASE_FAILED; 1095 + instr->fail_addr = addr; 1096 + goto erase_exit; 1097 + } 1098 + 1099 + len -= block_size; 1100 + addr += block_size; 1101 + } 1102 + 1103 + instr->state = MTD_ERASE_DONE; 1104 + 1105 + erase_exit: 1106 + 1107 + ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO; 1108 + /* Do call back function */ 1109 + if (!ret) 1110 + mtd_erase_callback(instr); 1111 + 1112 + /* Deselect and wake up anyone waiting on the device */ 1113 + onenand_release_device(mtd); 1114 + 1115 + return ret; 1116 + } 1117 + 1118 + /** 1119 + * onenand_sync - [MTD Interface] sync 1120 + * @param mtd MTD device structure 1121 + * 1122 + * Sync is actually a wait for chip ready function 1123 + */ 1124 + static void onenand_sync(struct mtd_info *mtd) 1125 + { 1126 + DEBUG(MTD_DEBUG_LEVEL3, "onenand_sync: called\n"); 1127 + 1128 + /* Grab the lock and see if the device is available */ 1129 + onenand_get_device(mtd, FL_SYNCING); 1130 + 1131 + /* Release it and go back */ 1132 + onenand_release_device(mtd); 1133 + } 1134 + 1135 + /** 1136 + * onenand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad 1137 + * @param mtd MTD device structure 1138 + * @param ofs offset relative to mtd start 1139 + */ 1140 + static int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs) 1141 + { 1142 + /* 1143 + * TODO 1144 + * 1. Bad block table (BBT) 1145 + * -> using NAND BBT to support JFFS2 1146 + * 2. Bad block management (BBM) 1147 + * -> bad block replace scheme 1148 + * 1149 + * Currently we do nothing 1150 + */ 1151 + return 0; 1152 + } 1153 + 1154 + /** 1155 + * onenand_block_markbad - [MTD Interface] Mark the block at the given offset as bad 1156 + * @param mtd MTD device structure 1157 + * @param ofs offset relative to mtd start 1158 + */ 1159 + static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs) 1160 + { 1161 + /* see above */ 1162 + return 0; 1163 + } 1164 + 1165 + /** 1166 + * onenand_unlock - [MTD Interface] Unlock block(s) 1167 + * @param mtd MTD device structure 1168 + * @param ofs offset relative to mtd start 1169 + * @param len number of bytes to unlock 1170 + * 1171 + * Unlock one or more blocks 1172 + */ 1173 + static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) 1174 + { 1175 + struct onenand_chip *this = mtd->priv; 1176 + int start, end, block, value, status; 1177 + 1178 + start = ofs >> this->erase_shift; 1179 + end = len >> this->erase_shift; 1180 + 1181 + /* Continuous lock scheme */ 1182 + if (this->options & ONENAND_CONT_LOCK) { 1183 + /* Set start block address */ 1184 + this->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS); 1185 + /* Set end block address */ 1186 + this->write_word(end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS); 1187 + /* Write unlock command */ 1188 + this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0); 1189 + 1190 + /* There's no return value */ 1191 + this->wait(mtd, FL_UNLOCKING); 1192 + 1193 + /* Sanity check */ 1194 + while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) 1195 + & ONENAND_CTRL_ONGO) 1196 + continue; 1197 + 1198 + /* Check lock status */ 1199 + status = this->read_word(this->base + ONENAND_REG_WP_STATUS); 1200 + if (!(status & ONENAND_WP_US)) 1201 + printk(KERN_ERR "wp status = 0x%x\n", status); 1202 + 1203 + return 0; 1204 + } 1205 + 1206 + /* Block lock scheme */ 1207 + for (block = start; block < end; block++) { 1208 + /* Set start block address */ 1209 + this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS); 1210 + /* Write unlock command */ 1211 + this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0); 1212 + 1213 + /* There's no return value */ 1214 + this->wait(mtd, FL_UNLOCKING); 1215 + 1216 + /* Sanity check */ 1217 + while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) 1218 + & ONENAND_CTRL_ONGO) 1219 + continue; 1220 + 1221 + /* Set block address for read block status */ 1222 + value = onenand_block_address(this->device_id, block); 1223 + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); 1224 + 1225 + /* Check lock status */ 1226 + status = this->read_word(this->base + ONENAND_REG_WP_STATUS); 1227 + if (!(status & ONENAND_WP_US)) 1228 + printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status); 1229 + } 1230 + 1231 + return 0; 1232 + } 1233 + 1234 + /** 1235 + * onenand_print_device_info - Print device ID 1236 + * @param device device ID 1237 + * 1238 + * Print device ID 1239 + */ 1240 + static void onenand_print_device_info(int device) 1241 + { 1242 + int vcc, demuxed, ddp, density; 1243 + 1244 + vcc = device & ONENAND_DEVICE_VCC_MASK; 1245 + demuxed = device & ONENAND_DEVICE_IS_DEMUX; 1246 + ddp = device & ONENAND_DEVICE_IS_DDP; 1247 + density = device >> ONENAND_DEVICE_DENSITY_SHIFT; 1248 + printk(KERN_INFO "%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n", 1249 + demuxed ? "" : "Muxed ", 1250 + ddp ? "(DDP)" : "", 1251 + (16 << density), 1252 + vcc ? "2.65/3.3" : "1.8", 1253 + device); 1254 + } 1255 + 1256 + static const struct onenand_manufacturers onenand_manuf_ids[] = { 1257 + {ONENAND_MFR_SAMSUNG, "Samsung"}, 1258 + {ONENAND_MFR_UNKNOWN, "Unknown"} 1259 + }; 1260 + 1261 + /** 1262 + * onenand_check_maf - Check manufacturer ID 1263 + * @param manuf manufacturer ID 1264 + * 1265 + * Check manufacturer ID 1266 + */ 1267 + static int onenand_check_maf(int manuf) 1268 + { 1269 + int i; 1270 + 1271 + for (i = 0; onenand_manuf_ids[i].id; i++) { 1272 + if (manuf == onenand_manuf_ids[i].id) 1273 + break; 1274 + } 1275 + 1276 + printk(KERN_DEBUG "OneNAND Manufacturer: %s\n", 1277 + onenand_manuf_ids[i].name); 1278 + 1279 + return (i != ONENAND_MFR_UNKNOWN); 1280 + } 1281 + 1282 + /** 1283 + * onenand_probe - [OneNAND Interface] Probe the OneNAND device 1284 + * @param mtd MTD device structure 1285 + * 1286 + * OneNAND detection method: 1287 + * Compare the the values from command with ones from register 1288 + */ 1289 + static int onenand_probe(struct mtd_info *mtd) 1290 + { 1291 + struct onenand_chip *this = mtd->priv; 1292 + int bram_maf_id, bram_dev_id, maf_id, dev_id; 1293 + int version_id; 1294 + int density; 1295 + 1296 + /* Send the command for reading device ID from BootRAM */ 1297 + this->write_word(ONENAND_CMD_READID, this->base + ONENAND_BOOTRAM); 1298 + 1299 + /* Read manufacturer and device IDs from BootRAM */ 1300 + bram_maf_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x0); 1301 + bram_dev_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x2); 1302 + 1303 + /* Check manufacturer ID */ 1304 + if (onenand_check_maf(bram_maf_id)) 1305 + return -ENXIO; 1306 + 1307 + /* Reset OneNAND to read default register values */ 1308 + this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM); 1309 + 1310 + /* Read manufacturer and device IDs from Register */ 1311 + maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); 1312 + dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); 1313 + 1314 + /* Check OneNAND device */ 1315 + if (maf_id != bram_maf_id || dev_id != bram_dev_id) 1316 + return -ENXIO; 1317 + 1318 + /* Flash device information */ 1319 + onenand_print_device_info(dev_id); 1320 + this->device_id = dev_id; 1321 + 1322 + density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT; 1323 + this->chipsize = (16 << density) << 20; 1324 + 1325 + /* OneNAND page size & block size */ 1326 + /* The data buffer size is equal to page size */ 1327 + mtd->oobblock = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE); 1328 + mtd->oobsize = mtd->oobblock >> 5; 1329 + /* Pagers per block is always 64 in OneNAND */ 1330 + mtd->erasesize = mtd->oobblock << 6; 1331 + 1332 + this->erase_shift = ffs(mtd->erasesize) - 1; 1333 + this->page_shift = ffs(mtd->oobblock) - 1; 1334 + this->ppb_shift = (this->erase_shift - this->page_shift); 1335 + this->page_mask = (mtd->erasesize / mtd->oobblock) - 1; 1336 + 1337 + /* REVIST: Multichip handling */ 1338 + 1339 + mtd->size = this->chipsize; 1340 + 1341 + /* Version ID */ 1342 + version_id = this->read_word(this->base + ONENAND_REG_VERSION_ID); 1343 + printk(KERN_DEBUG "OneNAND version = 0x%04x\n", version_id); 1344 + 1345 + /* Lock scheme */ 1346 + if (density <= ONENAND_DEVICE_DENSITY_512Mb && 1347 + !(version_id >> ONENAND_VERSION_PROCESS_SHIFT)) { 1348 + printk(KERN_INFO "Lock scheme is Continues Lock\n"); 1349 + this->options |= ONENAND_CONT_LOCK; 1350 + } 1351 + 1352 + return 0; 1353 + } 1354 + 1355 + 1356 + /** 1357 + * onenand_scan - [OneNAND Interface] Scan for the OneNAND device 1358 + * @param mtd MTD device structure 1359 + * @param maxchips Number of chips to scan for 1360 + * 1361 + * This fills out all the not initialized function pointers 1362 + * with the defaults. 1363 + * The flash ID is read and the mtd/chip structures are 1364 + * filled with the appropriate values. 1365 + */ 1366 + int onenand_scan(struct mtd_info *mtd, int maxchips) 1367 + { 1368 + struct onenand_chip *this = mtd->priv; 1369 + 1370 + if (!this->read_word) 1371 + this->read_word = onenand_readw; 1372 + if (!this->write_word) 1373 + this->write_word = onenand_writew; 1374 + 1375 + if (!this->command) 1376 + this->command = onenand_command; 1377 + if (!this->wait) 1378 + this->wait = onenand_wait; 1379 + 1380 + if (!this->read_bufferram) 1381 + this->read_bufferram = onenand_read_bufferram; 1382 + if (!this->write_bufferram) 1383 + this->write_bufferram = onenand_write_bufferram; 1384 + 1385 + if (onenand_probe(mtd)) 1386 + return -ENXIO; 1387 + 1388 + this->state = FL_READY; 1389 + init_waitqueue_head(&this->wq); 1390 + spin_lock_init(&this->chip_lock); 1391 + 1392 + switch (mtd->oobsize) { 1393 + case 64: 1394 + this->autooob = &onenand_oob_64; 1395 + break; 1396 + 1397 + case 32: 1398 + this->autooob = &onenand_oob_32; 1399 + break; 1400 + 1401 + default: 1402 + printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n", 1403 + mtd->oobsize); 1404 + /* To prevent kernel oops */ 1405 + this->autooob = &onenand_oob_32; 1406 + break; 1407 + } 1408 + 1409 + memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo)); 1410 + 1411 + /* Fill in remaining MTD driver data */ 1412 + mtd->type = MTD_NANDFLASH; 1413 + mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC; 1414 + mtd->ecctype = MTD_ECC_SW; 1415 + mtd->erase = onenand_erase; 1416 + mtd->point = NULL; 1417 + mtd->unpoint = NULL; 1418 + mtd->read = onenand_read; 1419 + mtd->write = onenand_write; 1420 + mtd->read_ecc = onenand_read_ecc; 1421 + mtd->write_ecc = onenand_write_ecc; 1422 + mtd->read_oob = onenand_read_oob; 1423 + mtd->write_oob = onenand_write_oob; 1424 + mtd->readv = NULL; 1425 + mtd->readv_ecc = NULL; 1426 + mtd->writev = onenand_writev; 1427 + mtd->writev_ecc = onenand_writev_ecc; 1428 + mtd->sync = onenand_sync; 1429 + mtd->lock = NULL; 1430 + mtd->unlock = onenand_unlock; 1431 + mtd->suspend = NULL; 1432 + mtd->resume = NULL; 1433 + mtd->block_isbad = onenand_block_isbad; 1434 + mtd->block_markbad = onenand_block_markbad; 1435 + mtd->owner = THIS_MODULE; 1436 + 1437 + /* Unlock whole block */ 1438 + mtd->unlock(mtd, 0x0, this->chipsize); 1439 + 1440 + return 0; 1441 + } 1442 + 1443 + /** 1444 + * onenand_release - [OneNAND Interface] Free resources held by the OneNAND device 1445 + * @param mtd MTD device structure 1446 + */ 1447 + void onenand_release(struct mtd_info *mtd) 1448 + { 1449 + #ifdef CONFIG_MTD_PARTITIONS 1450 + /* Deregister partitions */ 1451 + del_mtd_partitions (mtd); 1452 + #endif 1453 + /* Deregister the device */ 1454 + del_mtd_device (mtd); 1455 + } 1456 + 1457 + EXPORT_SYMBOL_GPL(onenand_scan); 1458 + EXPORT_SYMBOL_GPL(onenand_release); 1459 + 1460 + MODULE_LICENSE("GPL"); 1461 + MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>"); 1462 + MODULE_DESCRIPTION("Generic OneNAND flash driver code");
+134
include/linux/mtd/onenand.h
··· 1 + /* 2 + * linux/include/linux/mtd/onenand.h 3 + * 4 + * Copyright (C) 2005 Samsung Electronics 5 + * Kyungmin Park <kyungmin.park@samsung.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + */ 11 + 12 + #ifndef __LINUX_MTD_ONENAND_H 13 + #define __LINUX_MTD_ONENAND_H 14 + 15 + #include <linux/spinlock.h> 16 + #include <linux/mtd/onenand_regs.h> 17 + 18 + #define MAX_BUFFERRAM 2 19 + 20 + /* Scan and identify a OneNAND device */ 21 + extern int onenand_scan(struct mtd_info *mtd, int max_chips); 22 + /* Free resources held by the OneNAND device */ 23 + extern void onenand_release(struct mtd_info *mtd); 24 + 25 + /** 26 + * onenand_state_t - chip states 27 + * Enumeration for OneNAND flash chip state 28 + */ 29 + typedef enum { 30 + FL_READY, 31 + FL_READING, 32 + FL_WRITING, 33 + FL_ERASING, 34 + FL_SYNCING, 35 + FL_UNLOCKING, 36 + FL_LOCKING, 37 + } onenand_state_t; 38 + 39 + /** 40 + * struct onenand_bufferram - OneNAND BufferRAM Data 41 + * @param block block address in BufferRAM 42 + * @param page page address in BufferRAM 43 + * @param valid valid flag 44 + */ 45 + struct onenand_bufferram { 46 + int block; 47 + int page; 48 + int valid; 49 + }; 50 + 51 + /** 52 + * struct onenand_chip - OneNAND Private Flash Chip Data 53 + * @param base [BOARDSPECIFIC] address to access OneNAND 54 + * @param chipsize [INTERN] the size of one chip for multichip arrays 55 + * @param device_id [INTERN] device ID 56 + * @param verstion_id [INTERN] version ID 57 + * @param options [BOARDSPECIFIC] various chip options. They can partly be set to inform onenand_scan about 58 + * @param erase_shift [INTERN] number of address bits in a block 59 + * @param page_shift [INTERN] number of address bits in a page 60 + * @param ppb_shift [INTERN] number of address bits in a pages per block 61 + * @param page_mask [INTERN] a page per block mask 62 + * @param bufferam_index [INTERN] BufferRAM index 63 + * @param bufferam [INTERN] BufferRAM info 64 + * @param readw [REPLACEABLE] hardware specific function for read short 65 + * @param writew [REPLACEABLE] hardware specific function for write short 66 + * @param command [REPLACEABLE] hardware specific function for writing commands to the chip 67 + * @param wait [REPLACEABLE] hardware specific function for wait on ready 68 + * @param read_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area 69 + * @param write_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area 70 + * @param chip_lock [INTERN] spinlock used to protect access to this structure and the chip 71 + * @param wq [INTERN] wait queue to sleep on if a OneNAND operation is in progress 72 + * @param state [INTERN] the current state of the OneNAND device 73 + * @param autooob [REPLACEABLE] the default (auto)placement scheme 74 + * @param priv [OPTIONAL] pointer to private chip date 75 + */ 76 + struct onenand_chip { 77 + void __iomem *base; 78 + unsigned int chipsize; 79 + unsigned int device_id; 80 + unsigned int options; 81 + 82 + unsigned int erase_shift; 83 + unsigned int page_shift; 84 + unsigned int ppb_shift; /* Pages per block shift */ 85 + unsigned int page_mask; 86 + 87 + unsigned int bufferram_index; 88 + struct onenand_bufferram bufferram[MAX_BUFFERRAM]; 89 + 90 + int (*command)(struct mtd_info *mtd, int cmd, loff_t address, size_t len); 91 + int (*wait)(struct mtd_info *mtd, int state); 92 + int (*read_bufferram)(struct mtd_info *mtd, int area, 93 + unsigned char *buffer, int offset, size_t count); 94 + int (*write_bufferram)(struct mtd_info *mtd, int area, 95 + const unsigned char *buffer, int offset, size_t count); 96 + unsigned short (*read_word)(void __iomem *addr); 97 + void (*write_word)(unsigned short value, void __iomem *addr); 98 + 99 + spinlock_t chip_lock; 100 + wait_queue_head_t wq; 101 + onenand_state_t state; 102 + 103 + struct nand_oobinfo *autooob; 104 + 105 + void *priv; 106 + }; 107 + 108 + #define ONENAND_CURRENT_BUFFERRAM(this) (this->bufferram_index) 109 + #define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1) 110 + #define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1) 111 + 112 + /* 113 + * Options bits 114 + */ 115 + #define ONENAND_CONT_LOCK (0x0001) 116 + 117 + 118 + /* 119 + * OneNAND Flash Manufacturer ID Codes 120 + */ 121 + #define ONENAND_MFR_SAMSUNG 0xec 122 + #define ONENAND_MFR_UNKNOWN 0x00 123 + 124 + /** 125 + * struct nand_manufacturers - NAND Flash Manufacturer ID Structure 126 + * @param name: Manufacturer name 127 + * @param id: manufacturer ID code of device. 128 + */ 129 + struct onenand_manufacturers { 130 + int id; 131 + char *name; 132 + }; 133 + 134 + #endif /* __LINUX_MTD_ONENAND_H */
+167
include/linux/mtd/onenand_regs.h
··· 1 + /* 2 + * linux/include/linux/mtd/onenand_regs.h 3 + * 4 + * OneNAND Register header file 5 + * 6 + * Copyright (C) 2005 Samsung Electronics 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + */ 12 + 13 + #ifndef __ONENAND_REG_H 14 + #define __ONENAND_REG_H 15 + 16 + /* Memory Address Map Translation (Word order) */ 17 + #define ONENAND_MEMORY_MAP(x) ((x) << 1) 18 + 19 + /* 20 + * External BufferRAM area 21 + */ 22 + #define ONENAND_BOOTRAM ONENAND_MEMORY_MAP(0x0000) 23 + #define ONENAND_DATARAM ONENAND_MEMORY_MAP(0x0200) 24 + #define ONENAND_SPARERAM ONENAND_MEMORY_MAP(0x8010) 25 + 26 + /* 27 + * OneNAND Registers 28 + */ 29 + #define ONENAND_REG_MANUFACTURER_ID ONENAND_MEMORY_MAP(0xF000) 30 + #define ONENAND_REG_DEVICE_ID ONENAND_MEMORY_MAP(0xF001) 31 + #define ONENAND_REG_VERSION_ID ONENAND_MEMORY_MAP(0xF002) 32 + #define ONENAND_REG_DATA_BUFFER_SIZE ONENAND_MEMORY_MAP(0xF003) 33 + #define ONENAND_REG_BOOT_BUFFER_SIZE ONENAND_MEMORY_MAP(0xF004) 34 + #define ONENAND_REG_NUM_BUFFERS ONENAND_MEMORY_MAP(0xF005) 35 + #define ONENAND_REG_TECHNOLOGY ONENAND_MEMORY_MAP(0xF006) 36 + 37 + #define ONENAND_REG_START_ADDRESS1 ONENAND_MEMORY_MAP(0xF100) 38 + #define ONENAND_REG_START_ADDRESS2 ONENAND_MEMORY_MAP(0xF101) 39 + #define ONENAND_REG_START_ADDRESS3 ONENAND_MEMORY_MAP(0xF102) 40 + #define ONENAND_REG_START_ADDRESS4 ONENAND_MEMORY_MAP(0xF103) 41 + #define ONENAND_REG_START_ADDRESS5 ONENAND_MEMORY_MAP(0xF104) 42 + #define ONENAND_REG_START_ADDRESS6 ONENAND_MEMORY_MAP(0xF105) 43 + #define ONENAND_REG_START_ADDRESS7 ONENAND_MEMORY_MAP(0xF106) 44 + #define ONENAND_REG_START_ADDRESS8 ONENAND_MEMORY_MAP(0xF107) 45 + 46 + #define ONENAND_REG_START_BUFFER ONENAND_MEMORY_MAP(0xF200) 47 + #define ONENAND_REG_COMMAND ONENAND_MEMORY_MAP(0xF220) 48 + #define ONENAND_REG_SYS_CFG1 ONENAND_MEMORY_MAP(0xF221) 49 + #define ONENAND_REG_SYS_CFG2 ONENAND_MEMORY_MAP(0xF222) 50 + #define ONENAND_REG_CTRL_STATUS ONENAND_MEMORY_MAP(0xF240) 51 + #define ONENAND_REG_INTERRUPT ONENAND_MEMORY_MAP(0xF241) 52 + #define ONENAND_REG_START_BLOCK_ADDRESS ONENAND_MEMORY_MAP(0xF24C) 53 + #define ONENAND_REG_END_BLOCK_ADDRESS ONENAND_MEMORY_MAP(0xF24D) 54 + #define ONENAND_REG_WP_STATUS ONENAND_MEMORY_MAP(0xF24E) 55 + 56 + #define ONENAND_REG_ECC_STATUS ONENAND_MEMORY_MAP(0xFF00) 57 + #define ONENAND_REG_ECC_M0 ONENAND_MEMORY_MAP(0xFF01) 58 + #define ONENAND_REG_ECC_S0 ONENAND_MEMORY_MAP(0xFF02) 59 + #define ONENAND_REG_ECC_M1 ONENAND_MEMORY_MAP(0xFF03) 60 + #define ONENAND_REG_ECC_S1 ONENAND_MEMORY_MAP(0xFF04) 61 + #define ONENAND_REG_ECC_M2 ONENAND_MEMORY_MAP(0xFF05) 62 + #define ONENAND_REG_ECC_S2 ONENAND_MEMORY_MAP(0xFF06) 63 + #define ONENAND_REG_ECC_M3 ONENAND_MEMORY_MAP(0xFF07) 64 + #define ONENAND_REG_ECC_S3 ONENAND_MEMORY_MAP(0xFF08) 65 + 66 + /* 67 + * Device ID Register F001h (R) 68 + */ 69 + #define ONENAND_DEVICE_DENSITY_SHIFT (4) 70 + #define ONENAND_DEVICE_IS_DDP (1 << 3) 71 + #define ONENAND_DEVICE_IS_DEMUX (1 << 2) 72 + #define ONENAND_DEVICE_VCC_MASK (0x3) 73 + 74 + #define ONENAND_DEVICE_DENSITY_512Mb (0x002) 75 + 76 + /* 77 + * Version ID Register F002h (R) 78 + */ 79 + #define ONENAND_VERSION_PROCESS_SHIFT (8) 80 + 81 + /* 82 + * Start Address 1 F100h (R/W) 83 + */ 84 + #define ONENAND_DDP_SHIFT (15) 85 + 86 + /* 87 + * Start Address 8 F107h (R/W) 88 + */ 89 + #define ONENAND_FPA_MASK (0x3f) 90 + #define ONENAND_FPA_SHIFT (2) 91 + #define ONENAND_FSA_MASK (0x03) 92 + 93 + /* 94 + * Start Buffer Register F200h (R/W) 95 + */ 96 + #define ONENAND_BSA_MASK (0x03) 97 + #define ONENAND_BSA_SHIFT (8) 98 + #define ONENAND_BSA_BOOTRAM (0 << 2) 99 + #define ONENAND_BSA_DATARAM0 (2 << 2) 100 + #define ONENAND_BSA_DATARAM1 (3 << 2) 101 + #define ONENAND_BSC_MASK (0x03) 102 + 103 + /* 104 + * Command Register F220h (R/W) 105 + */ 106 + #define ONENAND_CMD_READ (0x00) 107 + #define ONENAND_CMD_READOOB (0x13) 108 + #define ONENAND_CMD_PROG (0x80) 109 + #define ONENAND_CMD_PROGOOB (0x1A) 110 + #define ONENAND_CMD_UNLOCK (0x23) 111 + #define ONENAND_CMD_LOCK (0x2A) 112 + #define ONENAND_CMD_LOCK_TIGHT (0x2C) 113 + #define ONENAND_CMD_ERASE (0x94) 114 + #define ONENAND_CMD_RESET (0xF0) 115 + #define ONENAND_CMD_READID (0x90) 116 + 117 + /* NOTE: Those are not *REAL* commands */ 118 + #define ONENAND_CMD_BUFFERRAM (0x1978) 119 + 120 + /* 121 + * System Configuration 1 Register F221h (R, R/W) 122 + */ 123 + #define ONENAND_SYS_CFG1_SYNC_READ (1 << 15) 124 + #define ONENAND_SYS_CFG1_BRL (1 << 12) 125 + #define ONENAND_SYS_CFG1_BL (1 << 9) 126 + #define ONENAND_SYS_CFG1_NO_ECC (1 << 8) 127 + #define ONENAND_SYS_CFG1_RDY (1 << 7) 128 + #define ONENAND_SYS_CFG1_INT (1 << 6) 129 + #define ONENAND_SYS_CFG1_IOBE (1 << 5) 130 + #define ONENAND_SYS_CFG1_RDY_CONF (1 << 4) 131 + 132 + /* 133 + * Controller Status Register F240h (R) 134 + */ 135 + #define ONENAND_CTRL_ONGO (1 << 15) 136 + #define ONENAND_CTRL_LOCK (1 << 14) 137 + #define ONENAND_CTRL_LOAD (1 << 13) 138 + #define ONENAND_CTRL_PROGRAM (1 << 12) 139 + #define ONENAND_CTRL_ERASE (1 << 11) 140 + #define ONENAND_CTRL_ERROR (1 << 10) 141 + #define ONENAND_CTRL_RSTB (1 << 7) 142 + 143 + /* 144 + * Interrupt Status Register F241h (R) 145 + */ 146 + #define ONENAND_INT_MASTER (1 << 15) 147 + #define ONENAND_INT_READ (1 << 7) 148 + #define ONENAND_INT_WRITE (1 << 6) 149 + #define ONENAND_INT_ERASE (1 << 5) 150 + #define ONENAND_INT_RESET (1 << 4) 151 + #define ONENAND_INT_CLEAR (0 << 0) 152 + 153 + /* 154 + * NAND Flash Write Protection Status Register F24Eh (R) 155 + */ 156 + #define ONENAND_WP_US (1 << 2) 157 + #define ONENAND_WP_LS (1 << 1) 158 + #define ONENAND_WP_LTS (1 << 0) 159 + 160 + /* 161 + * ECC Status Reigser FF00h (R) 162 + */ 163 + #define ONENAND_ECC_1BIT (1 << 0) 164 + #define ONENAND_ECC_2BIT (1 << 1) 165 + #define ONENAND_ECC_2BIT_ALL (0xAAAA) 166 + 167 + #endif /* __ONENAND_REG_H */