blob: f00e195f4711150471c4d848f01dcc48f5c21905 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * NAND flash simulator.
3 *
4 * Author: Artem B. Bityuckiy <dedekind@oktetlabs.ru>, <dedekind@infradead.org>
5 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00006 * Copyright (C) 2004 Nokia Corporation
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 *
8 * Note: NS means "NAND Simulator".
9 * Note: Input means input TO flash chip, output means output FROM chip.
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2, or (at your option) any later
14 * version.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
19 * Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
24 *
Artem B. Bityuckiy51502282005-03-19 15:33:59 +000025 * $Id: nandsim.c,v 1.8 2005/03/19 15:33:56 dedekind Exp $
Linus Torvalds1da177e2005-04-16 15:20:36 -070026 */
27
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/init.h>
29#include <linux/types.h>
30#include <linux/module.h>
31#include <linux/moduleparam.h>
32#include <linux/vmalloc.h>
33#include <linux/slab.h>
34#include <linux/errno.h>
35#include <linux/string.h>
36#include <linux/mtd/mtd.h>
37#include <linux/mtd/nand.h>
38#include <linux/mtd/partitions.h>
39#include <linux/delay.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
41/* Default simulator parameters values */
42#if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \
43 !defined(CONFIG_NANDSIM_SECOND_ID_BYTE) || \
44 !defined(CONFIG_NANDSIM_THIRD_ID_BYTE) || \
45 !defined(CONFIG_NANDSIM_FOURTH_ID_BYTE)
46#define CONFIG_NANDSIM_FIRST_ID_BYTE 0x98
47#define CONFIG_NANDSIM_SECOND_ID_BYTE 0x39
48#define CONFIG_NANDSIM_THIRD_ID_BYTE 0xFF /* No byte */
49#define CONFIG_NANDSIM_FOURTH_ID_BYTE 0xFF /* No byte */
50#endif
51
52#ifndef CONFIG_NANDSIM_ACCESS_DELAY
53#define CONFIG_NANDSIM_ACCESS_DELAY 25
54#endif
55#ifndef CONFIG_NANDSIM_PROGRAMM_DELAY
56#define CONFIG_NANDSIM_PROGRAMM_DELAY 200
57#endif
58#ifndef CONFIG_NANDSIM_ERASE_DELAY
59#define CONFIG_NANDSIM_ERASE_DELAY 2
60#endif
61#ifndef CONFIG_NANDSIM_OUTPUT_CYCLE
62#define CONFIG_NANDSIM_OUTPUT_CYCLE 40
63#endif
64#ifndef CONFIG_NANDSIM_INPUT_CYCLE
65#define CONFIG_NANDSIM_INPUT_CYCLE 50
66#endif
67#ifndef CONFIG_NANDSIM_BUS_WIDTH
68#define CONFIG_NANDSIM_BUS_WIDTH 8
69#endif
70#ifndef CONFIG_NANDSIM_DO_DELAYS
71#define CONFIG_NANDSIM_DO_DELAYS 0
72#endif
73#ifndef CONFIG_NANDSIM_LOG
74#define CONFIG_NANDSIM_LOG 0
75#endif
76#ifndef CONFIG_NANDSIM_DBG
77#define CONFIG_NANDSIM_DBG 0
78#endif
79
80static uint first_id_byte = CONFIG_NANDSIM_FIRST_ID_BYTE;
81static uint second_id_byte = CONFIG_NANDSIM_SECOND_ID_BYTE;
82static uint third_id_byte = CONFIG_NANDSIM_THIRD_ID_BYTE;
83static uint fourth_id_byte = CONFIG_NANDSIM_FOURTH_ID_BYTE;
84static uint access_delay = CONFIG_NANDSIM_ACCESS_DELAY;
85static uint programm_delay = CONFIG_NANDSIM_PROGRAMM_DELAY;
86static uint erase_delay = CONFIG_NANDSIM_ERASE_DELAY;
87static uint output_cycle = CONFIG_NANDSIM_OUTPUT_CYCLE;
88static uint input_cycle = CONFIG_NANDSIM_INPUT_CYCLE;
89static uint bus_width = CONFIG_NANDSIM_BUS_WIDTH;
90static uint do_delays = CONFIG_NANDSIM_DO_DELAYS;
91static uint log = CONFIG_NANDSIM_LOG;
92static uint dbg = CONFIG_NANDSIM_DBG;
93
94module_param(first_id_byte, uint, 0400);
95module_param(second_id_byte, uint, 0400);
96module_param(third_id_byte, uint, 0400);
97module_param(fourth_id_byte, uint, 0400);
98module_param(access_delay, uint, 0400);
99module_param(programm_delay, uint, 0400);
100module_param(erase_delay, uint, 0400);
101module_param(output_cycle, uint, 0400);
102module_param(input_cycle, uint, 0400);
103module_param(bus_width, uint, 0400);
104module_param(do_delays, uint, 0400);
105module_param(log, uint, 0400);
106module_param(dbg, uint, 0400);
107
108MODULE_PARM_DESC(first_id_byte, "The fist byte returned by NAND Flash 'read ID' command (manufaturer ID)");
109MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)");
110MODULE_PARM_DESC(third_id_byte, "The third byte returned by NAND Flash 'read ID' command");
111MODULE_PARM_DESC(fourth_id_byte, "The fourth byte returned by NAND Flash 'read ID' command");
112MODULE_PARM_DESC(access_delay, "Initial page access delay (microiseconds)");
113MODULE_PARM_DESC(programm_delay, "Page programm delay (microseconds");
114MODULE_PARM_DESC(erase_delay, "Sector erase delay (milliseconds)");
115MODULE_PARM_DESC(output_cycle, "Word output (from flash) time (nanodeconds)");
116MODULE_PARM_DESC(input_cycle, "Word input (to flash) time (nanodeconds)");
117MODULE_PARM_DESC(bus_width, "Chip's bus width (8- or 16-bit)");
118MODULE_PARM_DESC(do_delays, "Simulate NAND delays using busy-waits if not zero");
119MODULE_PARM_DESC(log, "Perform logging if not zero");
120MODULE_PARM_DESC(dbg, "Output debug information if not zero");
121
122/* The largest possible page size */
123#define NS_LARGEST_PAGE_SIZE 2048
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000124
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125/* The prefix for simulator output */
126#define NS_OUTPUT_PREFIX "[nandsim]"
127
128/* Simulator's output macros (logging, debugging, warning, error) */
129#define NS_LOG(args...) \
130 do { if (log) printk(KERN_DEBUG NS_OUTPUT_PREFIX " log: " args); } while(0)
131#define NS_DBG(args...) \
132 do { if (dbg) printk(KERN_DEBUG NS_OUTPUT_PREFIX " debug: " args); } while(0)
133#define NS_WARN(args...) \
134 do { printk(KERN_WARNING NS_OUTPUT_PREFIX " warnig: " args); } while(0)
135#define NS_ERR(args...) \
136 do { printk(KERN_ERR NS_OUTPUT_PREFIX " errorr: " args); } while(0)
137
138/* Busy-wait delay macros (microseconds, milliseconds) */
139#define NS_UDELAY(us) \
140 do { if (do_delays) udelay(us); } while(0)
141#define NS_MDELAY(us) \
142 do { if (do_delays) mdelay(us); } while(0)
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000143
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144/* Is the nandsim structure initialized ? */
145#define NS_IS_INITIALIZED(ns) ((ns)->geom.totsz != 0)
146
147/* Good operation completion status */
148#define NS_STATUS_OK(ns) (NAND_STATUS_READY | (NAND_STATUS_WP * ((ns)->lines.wp == 0)))
149
150/* Operation failed completion status */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000151#define NS_STATUS_FAILED(ns) (NAND_STATUS_FAIL | NS_STATUS_OK(ns))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152
153/* Calculate the page offset in flash RAM image by (row, column) address */
154#define NS_RAW_OFFSET(ns) \
155 (((ns)->regs.row << (ns)->geom.pgshift) + ((ns)->regs.row * (ns)->geom.oobsz) + (ns)->regs.column)
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000156
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157/* Calculate the OOB offset in flash RAM image by (row, column) address */
158#define NS_RAW_OFFSET_OOB(ns) (NS_RAW_OFFSET(ns) + ns->geom.pgsz)
159
160/* After a command is input, the simulator goes to one of the following states */
161#define STATE_CMD_READ0 0x00000001 /* read data from the beginning of page */
162#define STATE_CMD_READ1 0x00000002 /* read data from the second half of page */
163#define STATE_CMD_READSTART 0x00000003 /* read data second command (large page devices) */
164#define STATE_CMD_PAGEPROG 0x00000004 /* start page programm */
165#define STATE_CMD_READOOB 0x00000005 /* read OOB area */
166#define STATE_CMD_ERASE1 0x00000006 /* sector erase first command */
167#define STATE_CMD_STATUS 0x00000007 /* read status */
168#define STATE_CMD_STATUS_M 0x00000008 /* read multi-plane status (isn't implemented) */
169#define STATE_CMD_SEQIN 0x00000009 /* sequential data imput */
170#define STATE_CMD_READID 0x0000000A /* read ID */
171#define STATE_CMD_ERASE2 0x0000000B /* sector erase second command */
172#define STATE_CMD_RESET 0x0000000C /* reset */
173#define STATE_CMD_MASK 0x0000000F /* command states mask */
174
175/* After an addres is input, the simulator goes to one of these states */
176#define STATE_ADDR_PAGE 0x00000010 /* full (row, column) address is accepted */
177#define STATE_ADDR_SEC 0x00000020 /* sector address was accepted */
178#define STATE_ADDR_ZERO 0x00000030 /* one byte zero address was accepted */
179#define STATE_ADDR_MASK 0x00000030 /* address states mask */
180
181/* Durind data input/output the simulator is in these states */
182#define STATE_DATAIN 0x00000100 /* waiting for data input */
183#define STATE_DATAIN_MASK 0x00000100 /* data input states mask */
184
185#define STATE_DATAOUT 0x00001000 /* waiting for page data output */
186#define STATE_DATAOUT_ID 0x00002000 /* waiting for ID bytes output */
187#define STATE_DATAOUT_STATUS 0x00003000 /* waiting for status output */
188#define STATE_DATAOUT_STATUS_M 0x00004000 /* waiting for multi-plane status output */
189#define STATE_DATAOUT_MASK 0x00007000 /* data output states mask */
190
191/* Previous operation is done, ready to accept new requests */
192#define STATE_READY 0x00000000
193
194/* This state is used to mark that the next state isn't known yet */
195#define STATE_UNKNOWN 0x10000000
196
197/* Simulator's actions bit masks */
198#define ACTION_CPY 0x00100000 /* copy page/OOB to the internal buffer */
199#define ACTION_PRGPAGE 0x00200000 /* programm the internal buffer to flash */
200#define ACTION_SECERASE 0x00300000 /* erase sector */
201#define ACTION_ZEROOFF 0x00400000 /* don't add any offset to address */
202#define ACTION_HALFOFF 0x00500000 /* add to address half of page */
203#define ACTION_OOBOFF 0x00600000 /* add to address OOB offset */
204#define ACTION_MASK 0x00700000 /* action mask */
205
206#define NS_OPER_NUM 12 /* Number of operations supported by the simulator */
207#define NS_OPER_STATES 6 /* Maximum number of states in operation */
208
209#define OPT_ANY 0xFFFFFFFF /* any chip supports this operation */
210#define OPT_PAGE256 0x00000001 /* 256-byte page chips */
211#define OPT_PAGE512 0x00000002 /* 512-byte page chips */
212#define OPT_PAGE2048 0x00000008 /* 2048-byte page chips */
213#define OPT_SMARTMEDIA 0x00000010 /* SmartMedia technology chips */
214#define OPT_AUTOINCR 0x00000020 /* page number auto inctimentation is possible */
215#define OPT_PAGE512_8BIT 0x00000040 /* 512-byte page chips with 8-bit bus width */
216#define OPT_LARGEPAGE (OPT_PAGE2048) /* 2048-byte page chips */
217#define OPT_SMALLPAGE (OPT_PAGE256 | OPT_PAGE512) /* 256 and 512-byte page chips */
218
219/* Remove action bits ftom state */
220#define NS_STATE(x) ((x) & ~ACTION_MASK)
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000221
222/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 * Maximum previous states which need to be saved. Currently saving is
224 * only needed for page programm operation with preceeded read command
225 * (which is only valid for 512-byte pages).
226 */
227#define NS_MAX_PREVSTATES 1
228
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000229/*
Vijay Kumard086d432006-10-08 22:02:31 +0530230 * A union to represent flash memory contents and flash buffer.
231 */
232union ns_mem {
233 u_char *byte; /* for byte access */
234 uint16_t *word; /* for 16-bit word access */
235};
236
237/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 * The structure which describes all the internal simulator data.
239 */
240struct nandsim {
241 struct mtd_partition part;
242
243 uint busw; /* flash chip bus width (8 or 16) */
244 u_char ids[4]; /* chip's ID bytes */
245 uint32_t options; /* chip's characteristic bits */
246 uint32_t state; /* current chip state */
247 uint32_t nxstate; /* next expected state */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000248
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 uint32_t *op; /* current operation, NULL operations isn't known yet */
250 uint32_t pstates[NS_MAX_PREVSTATES]; /* previous states */
251 uint16_t npstates; /* number of previous states saved */
252 uint16_t stateidx; /* current state index */
253
Vijay Kumard086d432006-10-08 22:02:31 +0530254 /* The simulated NAND flash pages array */
255 union ns_mem *pages;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256
257 /* Internal buffer of page + OOB size bytes */
Vijay Kumard086d432006-10-08 22:02:31 +0530258 union ns_mem buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259
260 /* NAND flash "geometry" */
261 struct nandsin_geometry {
262 uint32_t totsz; /* total flash size, bytes */
263 uint32_t secsz; /* flash sector (erase block) size, bytes */
264 uint pgsz; /* NAND flash page size, bytes */
265 uint oobsz; /* page OOB area size, bytes */
266 uint32_t totszoob; /* total flash size including OOB, bytes */
267 uint pgszoob; /* page size including OOB , bytes*/
268 uint secszoob; /* sector size including OOB, bytes */
269 uint pgnum; /* total number of pages */
270 uint pgsec; /* number of pages per sector */
271 uint secshift; /* bits number in sector size */
272 uint pgshift; /* bits number in page size */
273 uint oobshift; /* bits number in OOB size */
274 uint pgaddrbytes; /* bytes per page address */
275 uint secaddrbytes; /* bytes per sector address */
276 uint idbytes; /* the number ID bytes that this chip outputs */
277 } geom;
278
279 /* NAND flash internal registers */
280 struct nandsim_regs {
281 unsigned command; /* the command register */
282 u_char status; /* the status register */
283 uint row; /* the page number */
284 uint column; /* the offset within page */
285 uint count; /* internal counter */
286 uint num; /* number of bytes which must be processed */
287 uint off; /* fixed page offset */
288 } regs;
289
290 /* NAND flash lines state */
291 struct ns_lines_status {
292 int ce; /* chip Enable */
293 int cle; /* command Latch Enable */
294 int ale; /* address Latch Enable */
295 int wp; /* write Protect */
296 } lines;
297};
298
299/*
300 * Operations array. To perform any operation the simulator must pass
301 * through the correspondent states chain.
302 */
303static struct nandsim_operations {
304 uint32_t reqopts; /* options which are required to perform the operation */
305 uint32_t states[NS_OPER_STATES]; /* operation's states */
306} ops[NS_OPER_NUM] = {
307 /* Read page + OOB from the beginning */
308 {OPT_SMALLPAGE, {STATE_CMD_READ0 | ACTION_ZEROOFF, STATE_ADDR_PAGE | ACTION_CPY,
309 STATE_DATAOUT, STATE_READY}},
310 /* Read page + OOB from the second half */
311 {OPT_PAGE512_8BIT, {STATE_CMD_READ1 | ACTION_HALFOFF, STATE_ADDR_PAGE | ACTION_CPY,
312 STATE_DATAOUT, STATE_READY}},
313 /* Read OOB */
314 {OPT_SMALLPAGE, {STATE_CMD_READOOB | ACTION_OOBOFF, STATE_ADDR_PAGE | ACTION_CPY,
315 STATE_DATAOUT, STATE_READY}},
316 /* Programm page starting from the beginning */
317 {OPT_ANY, {STATE_CMD_SEQIN, STATE_ADDR_PAGE, STATE_DATAIN,
318 STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}},
319 /* Programm page starting from the beginning */
320 {OPT_SMALLPAGE, {STATE_CMD_READ0, STATE_CMD_SEQIN | ACTION_ZEROOFF, STATE_ADDR_PAGE,
321 STATE_DATAIN, STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}},
322 /* Programm page starting from the second half */
323 {OPT_PAGE512, {STATE_CMD_READ1, STATE_CMD_SEQIN | ACTION_HALFOFF, STATE_ADDR_PAGE,
324 STATE_DATAIN, STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}},
325 /* Programm OOB */
326 {OPT_SMALLPAGE, {STATE_CMD_READOOB, STATE_CMD_SEQIN | ACTION_OOBOFF, STATE_ADDR_PAGE,
327 STATE_DATAIN, STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}},
328 /* Erase sector */
329 {OPT_ANY, {STATE_CMD_ERASE1, STATE_ADDR_SEC, STATE_CMD_ERASE2 | ACTION_SECERASE, STATE_READY}},
330 /* Read status */
331 {OPT_ANY, {STATE_CMD_STATUS, STATE_DATAOUT_STATUS, STATE_READY}},
332 /* Read multi-plane status */
333 {OPT_SMARTMEDIA, {STATE_CMD_STATUS_M, STATE_DATAOUT_STATUS_M, STATE_READY}},
334 /* Read ID */
335 {OPT_ANY, {STATE_CMD_READID, STATE_ADDR_ZERO, STATE_DATAOUT_ID, STATE_READY}},
336 /* Large page devices read page */
337 {OPT_LARGEPAGE, {STATE_CMD_READ0, STATE_ADDR_PAGE, STATE_CMD_READSTART | ACTION_CPY,
338 STATE_DATAOUT, STATE_READY}}
339};
340
341/* MTD structure for NAND controller */
342static struct mtd_info *nsmtd;
343
344static u_char ns_verify_buf[NS_LARGEST_PAGE_SIZE];
345
346/*
Vijay Kumard086d432006-10-08 22:02:31 +0530347 * Allocate array of page pointers and initialize the array to NULL
348 * pointers.
349 *
350 * RETURNS: 0 if success, -ENOMEM if memory alloc fails.
351 */
352static int
353alloc_device(struct nandsim *ns)
354{
355 int i;
356
357 ns->pages = vmalloc(ns->geom.pgnum * sizeof(union ns_mem));
358 if (!ns->pages) {
359 NS_ERR("alloc_map: unable to allocate page array\n");
360 return -ENOMEM;
361 }
362 for (i = 0; i < ns->geom.pgnum; i++) {
363 ns->pages[i].byte = NULL;
364 }
365
366 return 0;
367}
368
369/*
370 * Free any allocated pages, and free the array of page pointers.
371 */
372static void
373free_device(struct nandsim *ns)
374{
375 int i;
376
377 if (ns->pages) {
378 for (i = 0; i < ns->geom.pgnum; i++) {
379 if (ns->pages[i].byte)
380 kfree(ns->pages[i].byte);
381 }
382 vfree(ns->pages);
383 }
384}
385
386/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 * Initialize the nandsim structure.
388 *
389 * RETURNS: 0 if success, -ERRNO if failure.
390 */
391static int
392init_nandsim(struct mtd_info *mtd)
393{
394 struct nand_chip *chip = (struct nand_chip *)mtd->priv;
395 struct nandsim *ns = (struct nandsim *)(chip->priv);
396 int i;
397
398 if (NS_IS_INITIALIZED(ns)) {
399 NS_ERR("init_nandsim: nandsim is already initialized\n");
400 return -EIO;
401 }
402
403 /* Force mtd to not do delays */
404 chip->chip_delay = 0;
405
406 /* Initialize the NAND flash parameters */
407 ns->busw = chip->options & NAND_BUSWIDTH_16 ? 16 : 8;
408 ns->geom.totsz = mtd->size;
Joern Engel28318772006-05-22 23:18:05 +0200409 ns->geom.pgsz = mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 ns->geom.oobsz = mtd->oobsize;
411 ns->geom.secsz = mtd->erasesize;
412 ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz;
413 ns->geom.pgnum = ns->geom.totsz / ns->geom.pgsz;
414 ns->geom.totszoob = ns->geom.totsz + ns->geom.pgnum * ns->geom.oobsz;
415 ns->geom.secshift = ffs(ns->geom.secsz) - 1;
416 ns->geom.pgshift = chip->page_shift;
417 ns->geom.oobshift = ffs(ns->geom.oobsz) - 1;
418 ns->geom.pgsec = ns->geom.secsz / ns->geom.pgsz;
419 ns->geom.secszoob = ns->geom.secsz + ns->geom.oobsz * ns->geom.pgsec;
420 ns->options = 0;
421
422 if (ns->geom.pgsz == 256) {
423 ns->options |= OPT_PAGE256;
424 }
425 else if (ns->geom.pgsz == 512) {
426 ns->options |= (OPT_PAGE512 | OPT_AUTOINCR);
427 if (ns->busw == 8)
428 ns->options |= OPT_PAGE512_8BIT;
429 } else if (ns->geom.pgsz == 2048) {
430 ns->options |= OPT_PAGE2048;
431 } else {
432 NS_ERR("init_nandsim: unknown page size %u\n", ns->geom.pgsz);
433 return -EIO;
434 }
435
436 if (ns->options & OPT_SMALLPAGE) {
437 if (ns->geom.totsz < (64 << 20)) {
438 ns->geom.pgaddrbytes = 3;
439 ns->geom.secaddrbytes = 2;
440 } else {
441 ns->geom.pgaddrbytes = 4;
442 ns->geom.secaddrbytes = 3;
443 }
444 } else {
445 if (ns->geom.totsz <= (128 << 20)) {
446 ns->geom.pgaddrbytes = 5;
447 ns->geom.secaddrbytes = 2;
448 } else {
449 ns->geom.pgaddrbytes = 5;
450 ns->geom.secaddrbytes = 3;
451 }
452 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000453
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 /* Detect how many ID bytes the NAND chip outputs */
455 for (i = 0; nand_flash_ids[i].name != NULL; i++) {
456 if (second_id_byte != nand_flash_ids[i].id)
457 continue;
458 if (!(nand_flash_ids[i].options & NAND_NO_AUTOINCR))
459 ns->options |= OPT_AUTOINCR;
460 }
461
462 if (ns->busw == 16)
463 NS_WARN("16-bit flashes support wasn't tested\n");
464
465 printk("flash size: %u MiB\n", ns->geom.totsz >> 20);
466 printk("page size: %u bytes\n", ns->geom.pgsz);
467 printk("OOB area size: %u bytes\n", ns->geom.oobsz);
468 printk("sector size: %u KiB\n", ns->geom.secsz >> 10);
469 printk("pages number: %u\n", ns->geom.pgnum);
470 printk("pages per sector: %u\n", ns->geom.pgsec);
471 printk("bus width: %u\n", ns->busw);
472 printk("bits in sector size: %u\n", ns->geom.secshift);
473 printk("bits in page size: %u\n", ns->geom.pgshift);
474 printk("bits in OOB size: %u\n", ns->geom.oobshift);
475 printk("flash size with OOB: %u KiB\n", ns->geom.totszoob >> 10);
476 printk("page address bytes: %u\n", ns->geom.pgaddrbytes);
477 printk("sector address bytes: %u\n", ns->geom.secaddrbytes);
478 printk("options: %#x\n", ns->options);
479
Vijay Kumard086d432006-10-08 22:02:31 +0530480 if (alloc_device(ns) != 0)
481 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482
483 /* Allocate / initialize the internal buffer */
484 ns->buf.byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL);
485 if (!ns->buf.byte) {
486 NS_ERR("init_nandsim: unable to allocate %u bytes for the internal buffer\n",
487 ns->geom.pgszoob);
488 goto error;
489 }
490 memset(ns->buf.byte, 0xFF, ns->geom.pgszoob);
491
492 /* Fill the partition_info structure */
493 ns->part.name = "NAND simulator partition";
494 ns->part.offset = 0;
495 ns->part.size = ns->geom.totsz;
496
497 return 0;
498
499error:
Vijay Kumard086d432006-10-08 22:02:31 +0530500 free_device(ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501
502 return -ENOMEM;
503}
504
505/*
506 * Free the nandsim structure.
507 */
508static void
509free_nandsim(struct nandsim *ns)
510{
511 kfree(ns->buf.byte);
Vijay Kumard086d432006-10-08 22:02:31 +0530512 free_device(ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513
514 return;
515}
516
517/*
518 * Returns the string representation of 'state' state.
519 */
520static char *
521get_state_name(uint32_t state)
522{
523 switch (NS_STATE(state)) {
524 case STATE_CMD_READ0:
525 return "STATE_CMD_READ0";
526 case STATE_CMD_READ1:
527 return "STATE_CMD_READ1";
528 case STATE_CMD_PAGEPROG:
529 return "STATE_CMD_PAGEPROG";
530 case STATE_CMD_READOOB:
531 return "STATE_CMD_READOOB";
532 case STATE_CMD_READSTART:
533 return "STATE_CMD_READSTART";
534 case STATE_CMD_ERASE1:
535 return "STATE_CMD_ERASE1";
536 case STATE_CMD_STATUS:
537 return "STATE_CMD_STATUS";
538 case STATE_CMD_STATUS_M:
539 return "STATE_CMD_STATUS_M";
540 case STATE_CMD_SEQIN:
541 return "STATE_CMD_SEQIN";
542 case STATE_CMD_READID:
543 return "STATE_CMD_READID";
544 case STATE_CMD_ERASE2:
545 return "STATE_CMD_ERASE2";
546 case STATE_CMD_RESET:
547 return "STATE_CMD_RESET";
548 case STATE_ADDR_PAGE:
549 return "STATE_ADDR_PAGE";
550 case STATE_ADDR_SEC:
551 return "STATE_ADDR_SEC";
552 case STATE_ADDR_ZERO:
553 return "STATE_ADDR_ZERO";
554 case STATE_DATAIN:
555 return "STATE_DATAIN";
556 case STATE_DATAOUT:
557 return "STATE_DATAOUT";
558 case STATE_DATAOUT_ID:
559 return "STATE_DATAOUT_ID";
560 case STATE_DATAOUT_STATUS:
561 return "STATE_DATAOUT_STATUS";
562 case STATE_DATAOUT_STATUS_M:
563 return "STATE_DATAOUT_STATUS_M";
564 case STATE_READY:
565 return "STATE_READY";
566 case STATE_UNKNOWN:
567 return "STATE_UNKNOWN";
568 }
569
570 NS_ERR("get_state_name: unknown state, BUG\n");
571 return NULL;
572}
573
574/*
575 * Check if command is valid.
576 *
577 * RETURNS: 1 if wrong command, 0 if right.
578 */
579static int
580check_command(int cmd)
581{
582 switch (cmd) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000583
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 case NAND_CMD_READ0:
585 case NAND_CMD_READSTART:
586 case NAND_CMD_PAGEPROG:
587 case NAND_CMD_READOOB:
588 case NAND_CMD_ERASE1:
589 case NAND_CMD_STATUS:
590 case NAND_CMD_SEQIN:
591 case NAND_CMD_READID:
592 case NAND_CMD_ERASE2:
593 case NAND_CMD_RESET:
594 case NAND_CMD_READ1:
595 return 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000596
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 case NAND_CMD_STATUS_MULTI:
598 default:
599 return 1;
600 }
601}
602
603/*
604 * Returns state after command is accepted by command number.
605 */
606static uint32_t
607get_state_by_command(unsigned command)
608{
609 switch (command) {
610 case NAND_CMD_READ0:
611 return STATE_CMD_READ0;
612 case NAND_CMD_READ1:
613 return STATE_CMD_READ1;
614 case NAND_CMD_PAGEPROG:
615 return STATE_CMD_PAGEPROG;
616 case NAND_CMD_READSTART:
617 return STATE_CMD_READSTART;
618 case NAND_CMD_READOOB:
619 return STATE_CMD_READOOB;
620 case NAND_CMD_ERASE1:
621 return STATE_CMD_ERASE1;
622 case NAND_CMD_STATUS:
623 return STATE_CMD_STATUS;
624 case NAND_CMD_STATUS_MULTI:
625 return STATE_CMD_STATUS_M;
626 case NAND_CMD_SEQIN:
627 return STATE_CMD_SEQIN;
628 case NAND_CMD_READID:
629 return STATE_CMD_READID;
630 case NAND_CMD_ERASE2:
631 return STATE_CMD_ERASE2;
632 case NAND_CMD_RESET:
633 return STATE_CMD_RESET;
634 }
635
636 NS_ERR("get_state_by_command: unknown command, BUG\n");
637 return 0;
638}
639
640/*
641 * Move an address byte to the correspondent internal register.
642 */
643static inline void
644accept_addr_byte(struct nandsim *ns, u_char bt)
645{
646 uint byte = (uint)bt;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000647
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 if (ns->regs.count < (ns->geom.pgaddrbytes - ns->geom.secaddrbytes))
649 ns->regs.column |= (byte << 8 * ns->regs.count);
650 else {
651 ns->regs.row |= (byte << 8 * (ns->regs.count -
652 ns->geom.pgaddrbytes +
653 ns->geom.secaddrbytes));
654 }
655
656 return;
657}
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000658
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659/*
660 * Switch to STATE_READY state.
661 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000662static inline void
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663switch_to_ready_state(struct nandsim *ns, u_char status)
664{
665 NS_DBG("switch_to_ready_state: switch to %s state\n", get_state_name(STATE_READY));
666
667 ns->state = STATE_READY;
668 ns->nxstate = STATE_UNKNOWN;
669 ns->op = NULL;
670 ns->npstates = 0;
671 ns->stateidx = 0;
672 ns->regs.num = 0;
673 ns->regs.count = 0;
674 ns->regs.off = 0;
675 ns->regs.row = 0;
676 ns->regs.column = 0;
677 ns->regs.status = status;
678}
679
680/*
681 * If the operation isn't known yet, try to find it in the global array
682 * of supported operations.
683 *
684 * Operation can be unknown because of the following.
685 * 1. New command was accepted and this is the firs call to find the
686 * correspondent states chain. In this case ns->npstates = 0;
687 * 2. There is several operations which begin with the same command(s)
688 * (for example program from the second half and read from the
689 * second half operations both begin with the READ1 command). In this
690 * case the ns->pstates[] array contains previous states.
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000691 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 * Thus, the function tries to find operation containing the following
693 * states (if the 'flag' parameter is 0):
694 * ns->pstates[0], ... ns->pstates[ns->npstates], ns->state
695 *
696 * If (one and only one) matching operation is found, it is accepted (
697 * ns->ops, ns->state, ns->nxstate are initialized, ns->npstate is
698 * zeroed).
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000699 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 * If there are several maches, the current state is pushed to the
701 * ns->pstates.
702 *
703 * The operation can be unknown only while commands are input to the chip.
704 * As soon as address command is accepted, the operation must be known.
705 * In such situation the function is called with 'flag' != 0, and the
706 * operation is searched using the following pattern:
707 * ns->pstates[0], ... ns->pstates[ns->npstates], <address input>
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000708 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 * It is supposed that this pattern must either match one operation on
710 * none. There can't be ambiguity in that case.
711 *
712 * If no matches found, the functions does the following:
713 * 1. if there are saved states present, try to ignore them and search
714 * again only using the last command. If nothing was found, switch
715 * to the STATE_READY state.
716 * 2. if there are no saved states, switch to the STATE_READY state.
717 *
718 * RETURNS: -2 - no matched operations found.
719 * -1 - several matches.
720 * 0 - operation is found.
721 */
722static int
723find_operation(struct nandsim *ns, uint32_t flag)
724{
725 int opsfound = 0;
726 int i, j, idx = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000727
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 for (i = 0; i < NS_OPER_NUM; i++) {
729
730 int found = 1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000731
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 if (!(ns->options & ops[i].reqopts))
733 /* Ignore operations we can't perform */
734 continue;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000735
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 if (flag) {
737 if (!(ops[i].states[ns->npstates] & STATE_ADDR_MASK))
738 continue;
739 } else {
740 if (NS_STATE(ns->state) != NS_STATE(ops[i].states[ns->npstates]))
741 continue;
742 }
743
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000744 for (j = 0; j < ns->npstates; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 if (NS_STATE(ops[i].states[j]) != NS_STATE(ns->pstates[j])
746 && (ns->options & ops[idx].reqopts)) {
747 found = 0;
748 break;
749 }
750
751 if (found) {
752 idx = i;
753 opsfound += 1;
754 }
755 }
756
757 if (opsfound == 1) {
758 /* Exact match */
759 ns->op = &ops[idx].states[0];
760 if (flag) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000761 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 * In this case the find_operation function was
763 * called when address has just began input. But it isn't
764 * yet fully input and the current state must
765 * not be one of STATE_ADDR_*, but the STATE_ADDR_*
766 * state must be the next state (ns->nxstate).
767 */
768 ns->stateidx = ns->npstates - 1;
769 } else {
770 ns->stateidx = ns->npstates;
771 }
772 ns->npstates = 0;
773 ns->state = ns->op[ns->stateidx];
774 ns->nxstate = ns->op[ns->stateidx + 1];
775 NS_DBG("find_operation: operation found, index: %d, state: %s, nxstate %s\n",
776 idx, get_state_name(ns->state), get_state_name(ns->nxstate));
777 return 0;
778 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000779
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 if (opsfound == 0) {
781 /* Nothing was found. Try to ignore previous commands (if any) and search again */
782 if (ns->npstates != 0) {
783 NS_DBG("find_operation: no operation found, try again with state %s\n",
784 get_state_name(ns->state));
785 ns->npstates = 0;
786 return find_operation(ns, 0);
787
788 }
789 NS_DBG("find_operation: no operations found\n");
790 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
791 return -2;
792 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000793
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 if (flag) {
795 /* This shouldn't happen */
796 NS_DBG("find_operation: BUG, operation must be known if address is input\n");
797 return -2;
798 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000799
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 NS_DBG("find_operation: there is still ambiguity\n");
801
802 ns->pstates[ns->npstates++] = ns->state;
803
804 return -1;
805}
806
807/*
Vijay Kumard086d432006-10-08 22:02:31 +0530808 * Returns a pointer to the current page.
809 */
810static inline union ns_mem *NS_GET_PAGE(struct nandsim *ns)
811{
812 return &(ns->pages[ns->regs.row]);
813}
814
815/*
816 * Retuns a pointer to the current byte, within the current page.
817 */
818static inline u_char *NS_PAGE_BYTE_OFF(struct nandsim *ns)
819{
820 return NS_GET_PAGE(ns)->byte + ns->regs.column + ns->regs.off;
821}
822
823/*
824 * Fill the NAND buffer with data read from the specified page.
825 */
826static void read_page(struct nandsim *ns, int num)
827{
828 union ns_mem *mypage;
829
830 mypage = NS_GET_PAGE(ns);
831 if (mypage->byte == NULL) {
832 NS_DBG("read_page: page %d not allocated\n", ns->regs.row);
833 memset(ns->buf.byte, 0xFF, num);
834 } else {
835 NS_DBG("read_page: page %d allocated, reading from %d\n",
836 ns->regs.row, ns->regs.column + ns->regs.off);
837 memcpy(ns->buf.byte, NS_PAGE_BYTE_OFF(ns), num);
838 }
839}
840
841/*
842 * Erase all pages in the specified sector.
843 */
844static void erase_sector(struct nandsim *ns)
845{
846 union ns_mem *mypage;
847 int i;
848
849 mypage = NS_GET_PAGE(ns);
850 for (i = 0; i < ns->geom.pgsec; i++) {
851 if (mypage->byte != NULL) {
852 NS_DBG("erase_sector: freeing page %d\n", ns->regs.row+i);
853 kfree(mypage->byte);
854 mypage->byte = NULL;
855 }
856 mypage++;
857 }
858}
859
860/*
861 * Program the specified page with the contents from the NAND buffer.
862 */
863static int prog_page(struct nandsim *ns, int num)
864{
865 union ns_mem *mypage;
866 u_char *pg_off;
867
868 mypage = NS_GET_PAGE(ns);
869 if (mypage->byte == NULL) {
870 NS_DBG("prog_page: allocating page %d\n", ns->regs.row);
871 mypage->byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL);
872 if (mypage->byte == NULL) {
873 NS_ERR("prog_page: error allocating memory for page %d\n", ns->regs.row);
874 return -1;
875 }
876 memset(mypage->byte, 0xFF, ns->geom.pgszoob);
877 }
878
879 pg_off = NS_PAGE_BYTE_OFF(ns);
880 memcpy(pg_off, ns->buf.byte, num);
881
882 return 0;
883}
884
885/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 * If state has any action bit, perform this action.
887 *
888 * RETURNS: 0 if success, -1 if error.
889 */
890static int
891do_state_action(struct nandsim *ns, uint32_t action)
892{
Vijay Kumard086d432006-10-08 22:02:31 +0530893 int num;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 int busdiv = ns->busw == 8 ? 1 : 2;
895
896 action &= ACTION_MASK;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000897
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 /* Check that page address input is correct */
899 if (action != ACTION_SECERASE && ns->regs.row >= ns->geom.pgnum) {
900 NS_WARN("do_state_action: wrong page number (%#x)\n", ns->regs.row);
901 return -1;
902 }
903
904 switch (action) {
905
906 case ACTION_CPY:
907 /*
908 * Copy page data to the internal buffer.
909 */
910
911 /* Column shouldn't be very large */
912 if (ns->regs.column >= (ns->geom.pgszoob - ns->regs.off)) {
913 NS_ERR("do_state_action: column number is too large\n");
914 break;
915 }
916 num = ns->geom.pgszoob - ns->regs.off - ns->regs.column;
Vijay Kumard086d432006-10-08 22:02:31 +0530917 read_page(ns, num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918
919 NS_DBG("do_state_action: (ACTION_CPY:) copy %d bytes to int buf, raw offset %d\n",
920 num, NS_RAW_OFFSET(ns) + ns->regs.off);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000921
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 if (ns->regs.off == 0)
923 NS_LOG("read page %d\n", ns->regs.row);
924 else if (ns->regs.off < ns->geom.pgsz)
925 NS_LOG("read page %d (second half)\n", ns->regs.row);
926 else
927 NS_LOG("read OOB of page %d\n", ns->regs.row);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000928
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 NS_UDELAY(access_delay);
930 NS_UDELAY(input_cycle * ns->geom.pgsz / 1000 / busdiv);
931
932 break;
933
934 case ACTION_SECERASE:
935 /*
936 * Erase sector.
937 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000938
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 if (ns->lines.wp) {
940 NS_ERR("do_state_action: device is write-protected, ignore sector erase\n");
941 return -1;
942 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000943
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 if (ns->regs.row >= ns->geom.pgnum - ns->geom.pgsec
945 || (ns->regs.row & ~(ns->geom.secsz - 1))) {
946 NS_ERR("do_state_action: wrong sector address (%#x)\n", ns->regs.row);
947 return -1;
948 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000949
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 ns->regs.row = (ns->regs.row <<
951 8 * (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) | ns->regs.column;
952 ns->regs.column = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000953
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 NS_DBG("do_state_action: erase sector at address %#x, off = %d\n",
955 ns->regs.row, NS_RAW_OFFSET(ns));
956 NS_LOG("erase sector %d\n", ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift));
957
Vijay Kumard086d432006-10-08 22:02:31 +0530958 erase_sector(ns);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000959
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 NS_MDELAY(erase_delay);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000961
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 break;
963
964 case ACTION_PRGPAGE:
965 /*
966 * Programm page - move internal buffer data to the page.
967 */
968
969 if (ns->lines.wp) {
970 NS_WARN("do_state_action: device is write-protected, programm\n");
971 return -1;
972 }
973
974 num = ns->geom.pgszoob - ns->regs.off - ns->regs.column;
975 if (num != ns->regs.count) {
976 NS_ERR("do_state_action: too few bytes were input (%d instead of %d)\n",
977 ns->regs.count, num);
978 return -1;
979 }
980
Vijay Kumard086d432006-10-08 22:02:31 +0530981 if (prog_page(ns, num) == -1)
982 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983
984 NS_DBG("do_state_action: copy %d bytes from int buf to (%#x, %#x), raw off = %d\n",
985 num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off);
986 NS_LOG("programm page %d\n", ns->regs.row);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000987
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 NS_UDELAY(programm_delay);
989 NS_UDELAY(output_cycle * ns->geom.pgsz / 1000 / busdiv);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000990
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000992
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 case ACTION_ZEROOFF:
994 NS_DBG("do_state_action: set internal offset to 0\n");
995 ns->regs.off = 0;
996 break;
997
998 case ACTION_HALFOFF:
999 if (!(ns->options & OPT_PAGE512_8BIT)) {
1000 NS_ERR("do_state_action: BUG! can't skip half of page for non-512"
1001 "byte page size 8x chips\n");
1002 return -1;
1003 }
1004 NS_DBG("do_state_action: set internal offset to %d\n", ns->geom.pgsz/2);
1005 ns->regs.off = ns->geom.pgsz/2;
1006 break;
1007
1008 case ACTION_OOBOFF:
1009 NS_DBG("do_state_action: set internal offset to %d\n", ns->geom.pgsz);
1010 ns->regs.off = ns->geom.pgsz;
1011 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001012
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 default:
1014 NS_DBG("do_state_action: BUG! unknown action\n");
1015 }
1016
1017 return 0;
1018}
1019
1020/*
1021 * Switch simulator's state.
1022 */
1023static void
1024switch_state(struct nandsim *ns)
1025{
1026 if (ns->op) {
1027 /*
1028 * The current operation have already been identified.
1029 * Just follow the states chain.
1030 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001031
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 ns->stateidx += 1;
1033 ns->state = ns->nxstate;
1034 ns->nxstate = ns->op[ns->stateidx + 1];
1035
1036 NS_DBG("switch_state: operation is known, switch to the next state, "
1037 "state: %s, nxstate: %s\n",
1038 get_state_name(ns->state), get_state_name(ns->nxstate));
1039
1040 /* See, whether we need to do some action */
1041 if ((ns->state & ACTION_MASK) && do_state_action(ns, ns->state) < 0) {
1042 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1043 return;
1044 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001045
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 } else {
1047 /*
1048 * We don't yet know which operation we perform.
1049 * Try to identify it.
1050 */
1051
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001052 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 * The only event causing the switch_state function to
1054 * be called with yet unknown operation is new command.
1055 */
1056 ns->state = get_state_by_command(ns->regs.command);
1057
1058 NS_DBG("switch_state: operation is unknown, try to find it\n");
1059
1060 if (find_operation(ns, 0) != 0)
1061 return;
1062
1063 if ((ns->state & ACTION_MASK) && do_state_action(ns, ns->state) < 0) {
1064 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1065 return;
1066 }
1067 }
1068
1069 /* For 16x devices column means the page offset in words */
1070 if ((ns->nxstate & STATE_ADDR_MASK) && ns->busw == 16) {
1071 NS_DBG("switch_state: double the column number for 16x device\n");
1072 ns->regs.column <<= 1;
1073 }
1074
1075 if (NS_STATE(ns->nxstate) == STATE_READY) {
1076 /*
1077 * The current state is the last. Return to STATE_READY
1078 */
1079
1080 u_char status = NS_STATUS_OK(ns);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001081
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 /* In case of data states, see if all bytes were input/output */
1083 if ((ns->state & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK))
1084 && ns->regs.count != ns->regs.num) {
1085 NS_WARN("switch_state: not all bytes were processed, %d left\n",
1086 ns->regs.num - ns->regs.count);
1087 status = NS_STATUS_FAILED(ns);
1088 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001089
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 NS_DBG("switch_state: operation complete, switch to STATE_READY state\n");
1091
1092 switch_to_ready_state(ns, status);
1093
1094 return;
1095 } else if (ns->nxstate & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK)) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001096 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 * If the next state is data input/output, switch to it now
1098 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001099
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 ns->state = ns->nxstate;
1101 ns->nxstate = ns->op[++ns->stateidx + 1];
1102 ns->regs.num = ns->regs.count = 0;
1103
1104 NS_DBG("switch_state: the next state is data I/O, switch, "
1105 "state: %s, nxstate: %s\n",
1106 get_state_name(ns->state), get_state_name(ns->nxstate));
1107
1108 /*
1109 * Set the internal register to the count of bytes which
1110 * are expected to be input or output
1111 */
1112 switch (NS_STATE(ns->state)) {
1113 case STATE_DATAIN:
1114 case STATE_DATAOUT:
1115 ns->regs.num = ns->geom.pgszoob - ns->regs.off - ns->regs.column;
1116 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001117
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 case STATE_DATAOUT_ID:
1119 ns->regs.num = ns->geom.idbytes;
1120 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001121
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 case STATE_DATAOUT_STATUS:
1123 case STATE_DATAOUT_STATUS_M:
1124 ns->regs.count = ns->regs.num = 0;
1125 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001126
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 default:
1128 NS_ERR("switch_state: BUG! unknown data state\n");
1129 }
1130
1131 } else if (ns->nxstate & STATE_ADDR_MASK) {
1132 /*
1133 * If the next state is address input, set the internal
1134 * register to the number of expected address bytes
1135 */
1136
1137 ns->regs.count = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001138
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 switch (NS_STATE(ns->nxstate)) {
1140 case STATE_ADDR_PAGE:
1141 ns->regs.num = ns->geom.pgaddrbytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001142
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 break;
1144 case STATE_ADDR_SEC:
1145 ns->regs.num = ns->geom.secaddrbytes;
1146 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001147
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 case STATE_ADDR_ZERO:
1149 ns->regs.num = 1;
1150 break;
1151
1152 default:
1153 NS_ERR("switch_state: BUG! unknown address state\n");
1154 }
1155 } else {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001156 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 * Just reset internal counters.
1158 */
1159
1160 ns->regs.num = 0;
1161 ns->regs.count = 0;
1162 }
1163}
1164
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165static u_char
1166ns_nand_read_byte(struct mtd_info *mtd)
1167{
1168 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
1169 u_char outb = 0x00;
1170
1171 /* Sanity and correctness checks */
1172 if (!ns->lines.ce) {
1173 NS_ERR("read_byte: chip is disabled, return %#x\n", (uint)outb);
1174 return outb;
1175 }
1176 if (ns->lines.ale || ns->lines.cle) {
1177 NS_ERR("read_byte: ALE or CLE pin is high, return %#x\n", (uint)outb);
1178 return outb;
1179 }
1180 if (!(ns->state & STATE_DATAOUT_MASK)) {
1181 NS_WARN("read_byte: unexpected data output cycle, state is %s "
1182 "return %#x\n", get_state_name(ns->state), (uint)outb);
1183 return outb;
1184 }
1185
1186 /* Status register may be read as many times as it is wanted */
1187 if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS) {
1188 NS_DBG("read_byte: return %#x status\n", ns->regs.status);
1189 return ns->regs.status;
1190 }
1191
1192 /* Check if there is any data in the internal buffer which may be read */
1193 if (ns->regs.count == ns->regs.num) {
1194 NS_WARN("read_byte: no more data to output, return %#x\n", (uint)outb);
1195 return outb;
1196 }
1197
1198 switch (NS_STATE(ns->state)) {
1199 case STATE_DATAOUT:
1200 if (ns->busw == 8) {
1201 outb = ns->buf.byte[ns->regs.count];
1202 ns->regs.count += 1;
1203 } else {
1204 outb = (u_char)cpu_to_le16(ns->buf.word[ns->regs.count >> 1]);
1205 ns->regs.count += 2;
1206 }
1207 break;
1208 case STATE_DATAOUT_ID:
1209 NS_DBG("read_byte: read ID byte %d, total = %d\n", ns->regs.count, ns->regs.num);
1210 outb = ns->ids[ns->regs.count];
1211 ns->regs.count += 1;
1212 break;
1213 default:
1214 BUG();
1215 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001216
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 if (ns->regs.count == ns->regs.num) {
1218 NS_DBG("read_byte: all bytes were read\n");
1219
1220 /*
1221 * The OPT_AUTOINCR allows to read next conseqitive pages without
1222 * new read operation cycle.
1223 */
1224 if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) {
1225 ns->regs.count = 0;
1226 if (ns->regs.row + 1 < ns->geom.pgnum)
1227 ns->regs.row += 1;
1228 NS_DBG("read_byte: switch to the next page (%#x)\n", ns->regs.row);
1229 do_state_action(ns, ACTION_CPY);
1230 }
1231 else if (NS_STATE(ns->nxstate) == STATE_READY)
1232 switch_state(ns);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001233
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001235
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 return outb;
1237}
1238
1239static void
1240ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
1241{
1242 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001243
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 /* Sanity and correctness checks */
1245 if (!ns->lines.ce) {
1246 NS_ERR("write_byte: chip is disabled, ignore write\n");
1247 return;
1248 }
1249 if (ns->lines.ale && ns->lines.cle) {
1250 NS_ERR("write_byte: ALE and CLE pins are high simultaneously, ignore write\n");
1251 return;
1252 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001253
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 if (ns->lines.cle == 1) {
1255 /*
1256 * The byte written is a command.
1257 */
1258
1259 if (byte == NAND_CMD_RESET) {
1260 NS_LOG("reset chip\n");
1261 switch_to_ready_state(ns, NS_STATUS_OK(ns));
1262 return;
1263 }
1264
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001265 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 * Chip might still be in STATE_DATAOUT
1267 * (if OPT_AUTOINCR feature is supported), STATE_DATAOUT_STATUS or
1268 * STATE_DATAOUT_STATUS_M state. If so, switch state.
1269 */
1270 if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS
1271 || NS_STATE(ns->state) == STATE_DATAOUT_STATUS_M
1272 || ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT))
1273 switch_state(ns);
1274
1275 /* Check if chip is expecting command */
1276 if (NS_STATE(ns->nxstate) != STATE_UNKNOWN && !(ns->nxstate & STATE_CMD_MASK)) {
1277 /*
1278 * We are in situation when something else (not command)
1279 * was expected but command was input. In this case ignore
1280 * previous command(s)/state(s) and accept the last one.
1281 */
1282 NS_WARN("write_byte: command (%#x) wasn't expected, expected state is %s, "
1283 "ignore previous states\n", (uint)byte, get_state_name(ns->nxstate));
1284 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1285 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001286
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 /* Check that the command byte is correct */
1288 if (check_command(byte)) {
1289 NS_ERR("write_byte: unknown command %#x\n", (uint)byte);
1290 return;
1291 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001292
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 NS_DBG("command byte corresponding to %s state accepted\n",
1294 get_state_name(get_state_by_command(byte)));
1295 ns->regs.command = byte;
1296 switch_state(ns);
1297
1298 } else if (ns->lines.ale == 1) {
1299 /*
1300 * The byte written is an address.
1301 */
1302
1303 if (NS_STATE(ns->nxstate) == STATE_UNKNOWN) {
1304
1305 NS_DBG("write_byte: operation isn't known yet, identify it\n");
1306
1307 if (find_operation(ns, 1) < 0)
1308 return;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001309
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 if ((ns->state & ACTION_MASK) && do_state_action(ns, ns->state) < 0) {
1311 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1312 return;
1313 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001314
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 ns->regs.count = 0;
1316 switch (NS_STATE(ns->nxstate)) {
1317 case STATE_ADDR_PAGE:
1318 ns->regs.num = ns->geom.pgaddrbytes;
1319 break;
1320 case STATE_ADDR_SEC:
1321 ns->regs.num = ns->geom.secaddrbytes;
1322 break;
1323 case STATE_ADDR_ZERO:
1324 ns->regs.num = 1;
1325 break;
1326 default:
1327 BUG();
1328 }
1329 }
1330
1331 /* Check that chip is expecting address */
1332 if (!(ns->nxstate & STATE_ADDR_MASK)) {
1333 NS_ERR("write_byte: address (%#x) isn't expected, expected state is %s, "
1334 "switch to STATE_READY\n", (uint)byte, get_state_name(ns->nxstate));
1335 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1336 return;
1337 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001338
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 /* Check if this is expected byte */
1340 if (ns->regs.count == ns->regs.num) {
1341 NS_ERR("write_byte: no more address bytes expected\n");
1342 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1343 return;
1344 }
1345
1346 accept_addr_byte(ns, byte);
1347
1348 ns->regs.count += 1;
1349
1350 NS_DBG("write_byte: address byte %#x was accepted (%d bytes input, %d expected)\n",
1351 (uint)byte, ns->regs.count, ns->regs.num);
1352
1353 if (ns->regs.count == ns->regs.num) {
1354 NS_DBG("address (%#x, %#x) is accepted\n", ns->regs.row, ns->regs.column);
1355 switch_state(ns);
1356 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001357
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 } else {
1359 /*
1360 * The byte written is an input data.
1361 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001362
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 /* Check that chip is expecting data input */
1364 if (!(ns->state & STATE_DATAIN_MASK)) {
1365 NS_ERR("write_byte: data input (%#x) isn't expected, state is %s, "
1366 "switch to %s\n", (uint)byte,
1367 get_state_name(ns->state), get_state_name(STATE_READY));
1368 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1369 return;
1370 }
1371
1372 /* Check if this is expected byte */
1373 if (ns->regs.count == ns->regs.num) {
1374 NS_WARN("write_byte: %u input bytes has already been accepted, ignore write\n",
1375 ns->regs.num);
1376 return;
1377 }
1378
1379 if (ns->busw == 8) {
1380 ns->buf.byte[ns->regs.count] = byte;
1381 ns->regs.count += 1;
1382 } else {
1383 ns->buf.word[ns->regs.count >> 1] = cpu_to_le16((uint16_t)byte);
1384 ns->regs.count += 2;
1385 }
1386 }
1387
1388 return;
1389}
1390
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +02001391static void ns_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask)
1392{
1393 struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
1394
1395 ns->lines.cle = bitmask & NAND_CLE ? 1 : 0;
1396 ns->lines.ale = bitmask & NAND_ALE ? 1 : 0;
1397 ns->lines.ce = bitmask & NAND_NCE ? 1 : 0;
1398
1399 if (cmd != NAND_CMD_NONE)
1400 ns_nand_write_byte(mtd, cmd);
1401}
1402
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403static int
1404ns_device_ready(struct mtd_info *mtd)
1405{
1406 NS_DBG("device_ready\n");
1407 return 1;
1408}
1409
1410static uint16_t
1411ns_nand_read_word(struct mtd_info *mtd)
1412{
1413 struct nand_chip *chip = (struct nand_chip *)mtd->priv;
1414
1415 NS_DBG("read_word\n");
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001416
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 return chip->read_byte(mtd) | (chip->read_byte(mtd) << 8);
1418}
1419
1420static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
1422{
1423 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
1424
1425 /* Check that chip is expecting data input */
1426 if (!(ns->state & STATE_DATAIN_MASK)) {
1427 NS_ERR("write_buf: data input isn't expected, state is %s, "
1428 "switch to STATE_READY\n", get_state_name(ns->state));
1429 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1430 return;
1431 }
1432
1433 /* Check if these are expected bytes */
1434 if (ns->regs.count + len > ns->regs.num) {
1435 NS_ERR("write_buf: too many input bytes\n");
1436 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1437 return;
1438 }
1439
1440 memcpy(ns->buf.byte + ns->regs.count, buf, len);
1441 ns->regs.count += len;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001442
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 if (ns->regs.count == ns->regs.num) {
1444 NS_DBG("write_buf: %d bytes were written\n", ns->regs.count);
1445 }
1446}
1447
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001448static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
1450{
1451 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
1452
1453 /* Sanity and correctness checks */
1454 if (!ns->lines.ce) {
1455 NS_ERR("read_buf: chip is disabled\n");
1456 return;
1457 }
1458 if (ns->lines.ale || ns->lines.cle) {
1459 NS_ERR("read_buf: ALE or CLE pin is high\n");
1460 return;
1461 }
1462 if (!(ns->state & STATE_DATAOUT_MASK)) {
1463 NS_WARN("read_buf: unexpected data output cycle, current state is %s\n",
1464 get_state_name(ns->state));
1465 return;
1466 }
1467
1468 if (NS_STATE(ns->state) != STATE_DATAOUT) {
1469 int i;
1470
1471 for (i = 0; i < len; i++)
1472 buf[i] = ((struct nand_chip *)mtd->priv)->read_byte(mtd);
1473
1474 return;
1475 }
1476
1477 /* Check if these are expected bytes */
1478 if (ns->regs.count + len > ns->regs.num) {
1479 NS_ERR("read_buf: too many bytes to read\n");
1480 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1481 return;
1482 }
1483
1484 memcpy(buf, ns->buf.byte + ns->regs.count, len);
1485 ns->regs.count += len;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001486
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 if (ns->regs.count == ns->regs.num) {
1488 if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) {
1489 ns->regs.count = 0;
1490 if (ns->regs.row + 1 < ns->geom.pgnum)
1491 ns->regs.row += 1;
1492 NS_DBG("read_buf: switch to the next page (%#x)\n", ns->regs.row);
1493 do_state_action(ns, ACTION_CPY);
1494 }
1495 else if (NS_STATE(ns->nxstate) == STATE_READY)
1496 switch_state(ns);
1497 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001498
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 return;
1500}
1501
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001502static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
1504{
1505 ns_nand_read_buf(mtd, (u_char *)&ns_verify_buf[0], len);
1506
1507 if (!memcmp(buf, &ns_verify_buf[0], len)) {
1508 NS_DBG("verify_buf: the buffer is OK\n");
1509 return 0;
1510 } else {
1511 NS_DBG("verify_buf: the buffer is wrong\n");
1512 return -EFAULT;
1513 }
1514}
1515
1516/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 * Module initialization function
1518 */
Adrian Bunk2b9175c2005-11-29 14:49:38 +00001519static int __init ns_init_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520{
1521 struct nand_chip *chip;
1522 struct nandsim *nand;
1523 int retval = -ENOMEM;
1524
1525 if (bus_width != 8 && bus_width != 16) {
1526 NS_ERR("wrong bus width (%d), use only 8 or 16\n", bus_width);
1527 return -EINVAL;
1528 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001529
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 /* Allocate and initialize mtd_info, nand_chip and nandsim structures */
1531 nsmtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip)
1532 + sizeof(struct nandsim), GFP_KERNEL);
1533 if (!nsmtd) {
1534 NS_ERR("unable to allocate core structures.\n");
1535 return -ENOMEM;
1536 }
1537 memset(nsmtd, 0, sizeof(struct mtd_info) + sizeof(struct nand_chip) +
1538 sizeof(struct nandsim));
1539 chip = (struct nand_chip *)(nsmtd + 1);
1540 nsmtd->priv = (void *)chip;
1541 nand = (struct nandsim *)(chip + 1);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001542 chip->priv = (void *)nand;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543
1544 /*
1545 * Register simulator's callbacks.
1546 */
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +02001547 chip->cmd_ctrl = ns_hwcontrol;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 chip->read_byte = ns_nand_read_byte;
1549 chip->dev_ready = ns_device_ready;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 chip->write_buf = ns_nand_write_buf;
1551 chip->read_buf = ns_nand_read_buf;
1552 chip->verify_buf = ns_nand_verify_buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 chip->read_word = ns_nand_read_word;
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001554 chip->ecc.mode = NAND_ECC_SOFT;
Artem B. Bityuckiy51502282005-03-19 15:33:59 +00001555 chip->options |= NAND_SKIP_BBTSCAN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001557 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 * Perform minimum nandsim structure initialization to handle
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001559 * the initial ID read command correctly
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560 */
1561 if (third_id_byte != 0xFF || fourth_id_byte != 0xFF)
1562 nand->geom.idbytes = 4;
1563 else
1564 nand->geom.idbytes = 2;
1565 nand->regs.status = NS_STATUS_OK(nand);
1566 nand->nxstate = STATE_UNKNOWN;
1567 nand->options |= OPT_PAGE256; /* temporary value */
1568 nand->ids[0] = first_id_byte;
1569 nand->ids[1] = second_id_byte;
1570 nand->ids[2] = third_id_byte;
1571 nand->ids[3] = fourth_id_byte;
1572 if (bus_width == 16) {
1573 nand->busw = 16;
1574 chip->options |= NAND_BUSWIDTH_16;
1575 }
1576
David Woodhouse552d9202006-05-14 01:20:46 +01001577 nsmtd->owner = THIS_MODULE;
1578
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 if ((retval = nand_scan(nsmtd, 1)) != 0) {
1580 NS_ERR("can't register NAND Simulator\n");
1581 if (retval > 0)
1582 retval = -ENXIO;
1583 goto error;
1584 }
1585
Artem B. Bityuckiy51502282005-03-19 15:33:59 +00001586 if ((retval = init_nandsim(nsmtd)) != 0) {
1587 NS_ERR("scan_bbt: can't initialize the nandsim structure\n");
1588 goto error;
1589 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001590
Artem B. Bityuckiy51502282005-03-19 15:33:59 +00001591 if ((retval = nand_default_bbt(nsmtd)) != 0) {
1592 free_nandsim(nand);
1593 goto error;
1594 }
1595
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 /* Register NAND as one big partition */
1597 add_mtd_partitions(nsmtd, &nand->part, 1);
1598
1599 return 0;
1600
1601error:
1602 kfree(nsmtd);
1603
1604 return retval;
1605}
1606
1607module_init(ns_init_module);
1608
1609/*
1610 * Module clean-up function
1611 */
1612static void __exit ns_cleanup_module(void)
1613{
1614 struct nandsim *ns = (struct nandsim *)(((struct nand_chip *)nsmtd->priv)->priv);
1615
1616 free_nandsim(ns); /* Free nandsim private resources */
1617 nand_release(nsmtd); /* Unregisterd drived */
1618 kfree(nsmtd); /* Free other structures */
1619}
1620
1621module_exit(ns_cleanup_module);
1622
1623MODULE_LICENSE ("GPL");
1624MODULE_AUTHOR ("Artem B. Bityuckiy");
1625MODULE_DESCRIPTION ("The NAND flash simulator");
1626