aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/Kconfig10
-rw-r--r--drivers/mtd/Makefile4
-rw-r--r--drivers/mtd/onenand/Kconfig32
-rw-r--r--drivers/mtd/onenand/Makefile9
-rw-r--r--drivers/mtd/onenand/omap-onenand.c178
-rw-r--r--drivers/mtd/onenand/onenand_base.c1462
-rw-r--r--include/linux/mtd/onenand.h134
-rw-r--r--include/linux/mtd/onenand_regs.h167
8 files changed, 1990 insertions, 6 deletions
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 843a1cbe0866..3dbfbafb3481 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -1,4 +1,4 @@
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
3menu "Memory Technology Devices (MTD)" 3menu "Memory Technology Devices (MTD)"
4 4
@@ -259,9 +259,9 @@ config RFD_FTL
259 ---help--- 259 ---help---
260 This provides support for the flash translation layer known 260 This provides support for the flash translation layer known
261 as the Resident Flash Disk (RFD), as used by the Embedded BIOS 261 as the Resident Flash Disk (RFD), as used by the Embedded BIOS
262 of General Software. 262 of General Software. There is a blurb at:
263 See http://www.gensw.com/pages/prod/bios/rfd.htm for further 263
264 information. 264 http://www.gensw.com/pages/prod/bios/rfd.htm
265 265
266source "drivers/mtd/chips/Kconfig" 266source "drivers/mtd/chips/Kconfig"
267 267
@@ -271,5 +271,7 @@ source "drivers/mtd/devices/Kconfig"
271 271
272source "drivers/mtd/nand/Kconfig" 272source "drivers/mtd/nand/Kconfig"
273 273
274source "drivers/mtd/onenand/Kconfig"
275
274endmenu 276endmenu
275 277
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index cb16b7d478ce..fc9374407c2b 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -1,7 +1,7 @@
1# 1#
2# Makefile for the memory technology device drivers. 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# Core functionality. 6# Core functionality.
7mtd-y := mtdcore.o 7mtd-y := mtdcore.o
@@ -25,4 +25,4 @@ obj-$(CONFIG_RFD_FTL) += rfd_ftl.o mtd_blkdevs.o
25nftl-objs := nftlcore.o nftlmount.o 25nftl-objs := nftlcore.o nftlmount.o
26inftl-objs := inftlcore.o inftlmount.o 26inftl-objs := inftlcore.o inftlmount.o
27 27
28obj-y += chips/ maps/ devices/ nand/ 28obj-y += chips/ maps/ devices/ nand/ onenand/
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig
new file mode 100644
index 000000000000..7d76ede984d8
--- /dev/null
+++ b/drivers/mtd/onenand/Kconfig
@@ -0,0 +1,32 @@
1#
2# linux/drivers/mtd/onenand/Kconfig
3#
4
5menu "OneNAND Flash Device Drivers (EXPERIMENTAL)"
6 depends on MTD != n && EXPERIMENTAL
7
8config 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
16config 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
26config 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
32endmenu
diff --git a/drivers/mtd/onenand/Makefile b/drivers/mtd/onenand/Makefile
new file mode 100644
index 000000000000..f4e75864d8b5
--- /dev/null
+++ b/drivers/mtd/onenand/Makefile
@@ -0,0 +1,9 @@
1#
2# Makefile for the OneNAND MTD
3#
4
5# Core functionality.
6obj-$(CONFIG_MTD_ONENAND) += onenand_base.o
7
8# Board specific.
9obj-$(CONFIG_MTD_ONENAND_OMAP) += omap-onenand.o
diff --git a/drivers/mtd/onenand/omap-onenand.c b/drivers/mtd/onenand/omap-onenand.c
new file mode 100644
index 000000000000..56e1aec6b835
--- /dev/null
+++ b/drivers/mtd/onenand/omap-onenand.c
@@ -0,0 +1,178 @@
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 */
34static struct mtd_info *omap_onenand_mtd = NULL;
35
36/*
37 * Define partitions for flash devices
38 */
39
40#ifdef CONFIG_MTD_PARTITIONS
41static 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
71const 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 */
77static char onenand_name[] = "onenand";
78
79/*
80 * Main initialization routine
81 */
82static 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
150out_buf:
151 onenand_release(omap_onenand_mtd);
152 iounmap(this->base);
153out_mtd:
154 kfree(omap_onenand_mtd);
155out:
156 return err;
157}
158
159/*
160 * Clean up routine
161 */
162static 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
173module_init(omap_onenand_init);
174module_exit(omap_onenand_cleanup);
175
176MODULE_LICENSE("GPL");
177MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>");
178MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP boards");
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
new file mode 100644
index 000000000000..bcce22ae3cb1
--- /dev/null
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -0,0 +1,1462 @@
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 */
24static 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 */
41static 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
51static 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 */
68static 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 */
80static 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 */
93static 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 */
119static 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 */
145static 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 */
165static 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 */
193static 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 */
289static 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 */
342static 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 */
366static 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 */
391static 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 */
414static 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 */
443static 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 */
477static 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 */
506static 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 */
529static 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
583out:
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*/
606static 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 */
622static 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
678out:
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 */
696static 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 */
738static 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
801out:
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 */
821static 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 */
837static 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
886out:
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 */
907static 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
1008out:
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 */
1027static 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 */
1040static 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
1105erase_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 */
1124static 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 */
1140static 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 */
1159static 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 */
1173static 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 */
1240static 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
1256static 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 */
1267static 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 */
1289static 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 */
1366int 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 */
1447void 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
1457EXPORT_SYMBOL_GPL(onenand_scan);
1458EXPORT_SYMBOL_GPL(onenand_release);
1459
1460MODULE_LICENSE("GPL");
1461MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>");
1462MODULE_DESCRIPTION("Generic OneNAND flash driver code");
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
new file mode 100644
index 000000000000..b9a64117d646
--- /dev/null
+++ b/include/linux/mtd/onenand.h
@@ -0,0 +1,134 @@
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 */
21extern int onenand_scan(struct mtd_info *mtd, int max_chips);
22/* Free resources held by the OneNAND device */
23extern void onenand_release(struct mtd_info *mtd);
24
25/**
26 * onenand_state_t - chip states
27 * Enumeration for OneNAND flash chip state
28 */
29typedef 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 */
45struct 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 */
76struct 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*/
129struct onenand_manufacturers {
130 int id;
131 char *name;
132};
133
134#endif /* __LINUX_MTD_ONENAND_H */
diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h
new file mode 100644
index 000000000000..4a2daad7d738
--- /dev/null
+++ b/include/linux/mtd/onenand_regs.h
@@ -0,0 +1,167 @@
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 */