blob: c3bca9590ad21cbf65ca9f81e12d991c8e3a5203 [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 */
Artem Bityutskiy4a0c50c2006-12-06 21:52:32 +0200163#define STATE_CMD_READSTART 0x00000003 /* read data second command (large page devices) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164#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 */
Vijay Kumara5602142006-10-14 21:33:34 +0530352static int alloc_device(struct nandsim *ns)
Vijay Kumard086d432006-10-08 22:02:31 +0530353{
354 int i;
355
356 ns->pages = vmalloc(ns->geom.pgnum * sizeof(union ns_mem));
357 if (!ns->pages) {
358 NS_ERR("alloc_map: unable to allocate page array\n");
359 return -ENOMEM;
360 }
361 for (i = 0; i < ns->geom.pgnum; i++) {
362 ns->pages[i].byte = NULL;
363 }
364
365 return 0;
366}
367
368/*
369 * Free any allocated pages, and free the array of page pointers.
370 */
Vijay Kumara5602142006-10-14 21:33:34 +0530371static void free_device(struct nandsim *ns)
Vijay Kumard086d432006-10-08 22:02:31 +0530372{
373 int i;
374
375 if (ns->pages) {
376 for (i = 0; i < ns->geom.pgnum; i++) {
377 if (ns->pages[i].byte)
378 kfree(ns->pages[i].byte);
379 }
380 vfree(ns->pages);
381 }
382}
383
384/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 * Initialize the nandsim structure.
386 *
387 * RETURNS: 0 if success, -ERRNO if failure.
388 */
Vijay Kumara5602142006-10-14 21:33:34 +0530389static int init_nandsim(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390{
391 struct nand_chip *chip = (struct nand_chip *)mtd->priv;
392 struct nandsim *ns = (struct nandsim *)(chip->priv);
393 int i;
394
395 if (NS_IS_INITIALIZED(ns)) {
396 NS_ERR("init_nandsim: nandsim is already initialized\n");
397 return -EIO;
398 }
399
400 /* Force mtd to not do delays */
401 chip->chip_delay = 0;
402
403 /* Initialize the NAND flash parameters */
404 ns->busw = chip->options & NAND_BUSWIDTH_16 ? 16 : 8;
405 ns->geom.totsz = mtd->size;
Joern Engel28318772006-05-22 23:18:05 +0200406 ns->geom.pgsz = mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 ns->geom.oobsz = mtd->oobsize;
408 ns->geom.secsz = mtd->erasesize;
409 ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz;
410 ns->geom.pgnum = ns->geom.totsz / ns->geom.pgsz;
411 ns->geom.totszoob = ns->geom.totsz + ns->geom.pgnum * ns->geom.oobsz;
412 ns->geom.secshift = ffs(ns->geom.secsz) - 1;
413 ns->geom.pgshift = chip->page_shift;
414 ns->geom.oobshift = ffs(ns->geom.oobsz) - 1;
415 ns->geom.pgsec = ns->geom.secsz / ns->geom.pgsz;
416 ns->geom.secszoob = ns->geom.secsz + ns->geom.oobsz * ns->geom.pgsec;
417 ns->options = 0;
418
419 if (ns->geom.pgsz == 256) {
420 ns->options |= OPT_PAGE256;
421 }
422 else if (ns->geom.pgsz == 512) {
423 ns->options |= (OPT_PAGE512 | OPT_AUTOINCR);
424 if (ns->busw == 8)
425 ns->options |= OPT_PAGE512_8BIT;
426 } else if (ns->geom.pgsz == 2048) {
427 ns->options |= OPT_PAGE2048;
428 } else {
429 NS_ERR("init_nandsim: unknown page size %u\n", ns->geom.pgsz);
430 return -EIO;
431 }
432
433 if (ns->options & OPT_SMALLPAGE) {
434 if (ns->geom.totsz < (64 << 20)) {
435 ns->geom.pgaddrbytes = 3;
436 ns->geom.secaddrbytes = 2;
437 } else {
438 ns->geom.pgaddrbytes = 4;
439 ns->geom.secaddrbytes = 3;
440 }
441 } else {
442 if (ns->geom.totsz <= (128 << 20)) {
Artem Bityutskiy4a0c50c2006-12-06 21:52:32 +0200443 ns->geom.pgaddrbytes = 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 ns->geom.secaddrbytes = 2;
445 } else {
446 ns->geom.pgaddrbytes = 5;
447 ns->geom.secaddrbytes = 3;
448 }
449 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000450
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 /* Detect how many ID bytes the NAND chip outputs */
452 for (i = 0; nand_flash_ids[i].name != NULL; i++) {
453 if (second_id_byte != nand_flash_ids[i].id)
454 continue;
455 if (!(nand_flash_ids[i].options & NAND_NO_AUTOINCR))
456 ns->options |= OPT_AUTOINCR;
457 }
458
459 if (ns->busw == 16)
460 NS_WARN("16-bit flashes support wasn't tested\n");
461
462 printk("flash size: %u MiB\n", ns->geom.totsz >> 20);
463 printk("page size: %u bytes\n", ns->geom.pgsz);
464 printk("OOB area size: %u bytes\n", ns->geom.oobsz);
465 printk("sector size: %u KiB\n", ns->geom.secsz >> 10);
466 printk("pages number: %u\n", ns->geom.pgnum);
467 printk("pages per sector: %u\n", ns->geom.pgsec);
468 printk("bus width: %u\n", ns->busw);
469 printk("bits in sector size: %u\n", ns->geom.secshift);
470 printk("bits in page size: %u\n", ns->geom.pgshift);
471 printk("bits in OOB size: %u\n", ns->geom.oobshift);
472 printk("flash size with OOB: %u KiB\n", ns->geom.totszoob >> 10);
473 printk("page address bytes: %u\n", ns->geom.pgaddrbytes);
474 printk("sector address bytes: %u\n", ns->geom.secaddrbytes);
475 printk("options: %#x\n", ns->options);
476
Vijay Kumard086d432006-10-08 22:02:31 +0530477 if (alloc_device(ns) != 0)
478 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479
480 /* Allocate / initialize the internal buffer */
481 ns->buf.byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL);
482 if (!ns->buf.byte) {
483 NS_ERR("init_nandsim: unable to allocate %u bytes for the internal buffer\n",
484 ns->geom.pgszoob);
485 goto error;
486 }
487 memset(ns->buf.byte, 0xFF, ns->geom.pgszoob);
488
489 /* Fill the partition_info structure */
490 ns->part.name = "NAND simulator partition";
491 ns->part.offset = 0;
492 ns->part.size = ns->geom.totsz;
493
494 return 0;
495
496error:
Vijay Kumard086d432006-10-08 22:02:31 +0530497 free_device(ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498
499 return -ENOMEM;
500}
501
502/*
503 * Free the nandsim structure.
504 */
Vijay Kumara5602142006-10-14 21:33:34 +0530505static void free_nandsim(struct nandsim *ns)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506{
507 kfree(ns->buf.byte);
Vijay Kumard086d432006-10-08 22:02:31 +0530508 free_device(ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509
510 return;
511}
512
513/*
514 * Returns the string representation of 'state' state.
515 */
Vijay Kumara5602142006-10-14 21:33:34 +0530516static char *get_state_name(uint32_t state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517{
518 switch (NS_STATE(state)) {
519 case STATE_CMD_READ0:
520 return "STATE_CMD_READ0";
521 case STATE_CMD_READ1:
522 return "STATE_CMD_READ1";
523 case STATE_CMD_PAGEPROG:
524 return "STATE_CMD_PAGEPROG";
525 case STATE_CMD_READOOB:
526 return "STATE_CMD_READOOB";
527 case STATE_CMD_READSTART:
528 return "STATE_CMD_READSTART";
529 case STATE_CMD_ERASE1:
530 return "STATE_CMD_ERASE1";
531 case STATE_CMD_STATUS:
532 return "STATE_CMD_STATUS";
533 case STATE_CMD_STATUS_M:
534 return "STATE_CMD_STATUS_M";
535 case STATE_CMD_SEQIN:
536 return "STATE_CMD_SEQIN";
537 case STATE_CMD_READID:
538 return "STATE_CMD_READID";
539 case STATE_CMD_ERASE2:
540 return "STATE_CMD_ERASE2";
541 case STATE_CMD_RESET:
542 return "STATE_CMD_RESET";
543 case STATE_ADDR_PAGE:
544 return "STATE_ADDR_PAGE";
545 case STATE_ADDR_SEC:
546 return "STATE_ADDR_SEC";
547 case STATE_ADDR_ZERO:
548 return "STATE_ADDR_ZERO";
549 case STATE_DATAIN:
550 return "STATE_DATAIN";
551 case STATE_DATAOUT:
552 return "STATE_DATAOUT";
553 case STATE_DATAOUT_ID:
554 return "STATE_DATAOUT_ID";
555 case STATE_DATAOUT_STATUS:
556 return "STATE_DATAOUT_STATUS";
557 case STATE_DATAOUT_STATUS_M:
558 return "STATE_DATAOUT_STATUS_M";
559 case STATE_READY:
560 return "STATE_READY";
561 case STATE_UNKNOWN:
562 return "STATE_UNKNOWN";
563 }
564
565 NS_ERR("get_state_name: unknown state, BUG\n");
566 return NULL;
567}
568
569/*
570 * Check if command is valid.
571 *
572 * RETURNS: 1 if wrong command, 0 if right.
573 */
Vijay Kumara5602142006-10-14 21:33:34 +0530574static int check_command(int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575{
576 switch (cmd) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000577
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 case NAND_CMD_READ0:
579 case NAND_CMD_READSTART:
580 case NAND_CMD_PAGEPROG:
581 case NAND_CMD_READOOB:
582 case NAND_CMD_ERASE1:
583 case NAND_CMD_STATUS:
584 case NAND_CMD_SEQIN:
585 case NAND_CMD_READID:
586 case NAND_CMD_ERASE2:
587 case NAND_CMD_RESET:
588 case NAND_CMD_READ1:
589 return 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000590
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 case NAND_CMD_STATUS_MULTI:
592 default:
593 return 1;
594 }
595}
596
597/*
598 * Returns state after command is accepted by command number.
599 */
Vijay Kumara5602142006-10-14 21:33:34 +0530600static uint32_t get_state_by_command(unsigned command)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601{
602 switch (command) {
603 case NAND_CMD_READ0:
604 return STATE_CMD_READ0;
605 case NAND_CMD_READ1:
606 return STATE_CMD_READ1;
607 case NAND_CMD_PAGEPROG:
608 return STATE_CMD_PAGEPROG;
609 case NAND_CMD_READSTART:
610 return STATE_CMD_READSTART;
611 case NAND_CMD_READOOB:
612 return STATE_CMD_READOOB;
613 case NAND_CMD_ERASE1:
614 return STATE_CMD_ERASE1;
615 case NAND_CMD_STATUS:
616 return STATE_CMD_STATUS;
617 case NAND_CMD_STATUS_MULTI:
618 return STATE_CMD_STATUS_M;
619 case NAND_CMD_SEQIN:
620 return STATE_CMD_SEQIN;
621 case NAND_CMD_READID:
622 return STATE_CMD_READID;
623 case NAND_CMD_ERASE2:
624 return STATE_CMD_ERASE2;
625 case NAND_CMD_RESET:
626 return STATE_CMD_RESET;
627 }
628
629 NS_ERR("get_state_by_command: unknown command, BUG\n");
630 return 0;
631}
632
633/*
634 * Move an address byte to the correspondent internal register.
635 */
Vijay Kumara5602142006-10-14 21:33:34 +0530636static inline void accept_addr_byte(struct nandsim *ns, u_char bt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637{
638 uint byte = (uint)bt;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000639
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 if (ns->regs.count < (ns->geom.pgaddrbytes - ns->geom.secaddrbytes))
641 ns->regs.column |= (byte << 8 * ns->regs.count);
642 else {
643 ns->regs.row |= (byte << 8 * (ns->regs.count -
644 ns->geom.pgaddrbytes +
645 ns->geom.secaddrbytes));
646 }
647
648 return;
649}
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000650
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651/*
652 * Switch to STATE_READY state.
653 */
Vijay Kumara5602142006-10-14 21:33:34 +0530654static inline void switch_to_ready_state(struct nandsim *ns, u_char status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655{
656 NS_DBG("switch_to_ready_state: switch to %s state\n", get_state_name(STATE_READY));
657
658 ns->state = STATE_READY;
659 ns->nxstate = STATE_UNKNOWN;
660 ns->op = NULL;
661 ns->npstates = 0;
662 ns->stateidx = 0;
663 ns->regs.num = 0;
664 ns->regs.count = 0;
665 ns->regs.off = 0;
666 ns->regs.row = 0;
667 ns->regs.column = 0;
668 ns->regs.status = status;
669}
670
671/*
672 * If the operation isn't known yet, try to find it in the global array
673 * of supported operations.
674 *
675 * Operation can be unknown because of the following.
676 * 1. New command was accepted and this is the firs call to find the
677 * correspondent states chain. In this case ns->npstates = 0;
678 * 2. There is several operations which begin with the same command(s)
679 * (for example program from the second half and read from the
680 * second half operations both begin with the READ1 command). In this
681 * case the ns->pstates[] array contains previous states.
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000682 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 * Thus, the function tries to find operation containing the following
684 * states (if the 'flag' parameter is 0):
685 * ns->pstates[0], ... ns->pstates[ns->npstates], ns->state
686 *
687 * If (one and only one) matching operation is found, it is accepted (
688 * ns->ops, ns->state, ns->nxstate are initialized, ns->npstate is
689 * zeroed).
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000690 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 * If there are several maches, the current state is pushed to the
692 * ns->pstates.
693 *
694 * The operation can be unknown only while commands are input to the chip.
695 * As soon as address command is accepted, the operation must be known.
696 * In such situation the function is called with 'flag' != 0, and the
697 * operation is searched using the following pattern:
698 * ns->pstates[0], ... ns->pstates[ns->npstates], <address input>
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000699 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 * It is supposed that this pattern must either match one operation on
701 * none. There can't be ambiguity in that case.
702 *
703 * If no matches found, the functions does the following:
704 * 1. if there are saved states present, try to ignore them and search
705 * again only using the last command. If nothing was found, switch
706 * to the STATE_READY state.
707 * 2. if there are no saved states, switch to the STATE_READY state.
708 *
709 * RETURNS: -2 - no matched operations found.
710 * -1 - several matches.
711 * 0 - operation is found.
712 */
Vijay Kumara5602142006-10-14 21:33:34 +0530713static int find_operation(struct nandsim *ns, uint32_t flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714{
715 int opsfound = 0;
716 int i, j, idx = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000717
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 for (i = 0; i < NS_OPER_NUM; i++) {
719
720 int found = 1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000721
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 if (!(ns->options & ops[i].reqopts))
723 /* Ignore operations we can't perform */
724 continue;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000725
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 if (flag) {
727 if (!(ops[i].states[ns->npstates] & STATE_ADDR_MASK))
728 continue;
729 } else {
730 if (NS_STATE(ns->state) != NS_STATE(ops[i].states[ns->npstates]))
731 continue;
732 }
733
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000734 for (j = 0; j < ns->npstates; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 if (NS_STATE(ops[i].states[j]) != NS_STATE(ns->pstates[j])
736 && (ns->options & ops[idx].reqopts)) {
737 found = 0;
738 break;
739 }
740
741 if (found) {
742 idx = i;
743 opsfound += 1;
744 }
745 }
746
747 if (opsfound == 1) {
748 /* Exact match */
749 ns->op = &ops[idx].states[0];
750 if (flag) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000751 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 * In this case the find_operation function was
753 * called when address has just began input. But it isn't
754 * yet fully input and the current state must
755 * not be one of STATE_ADDR_*, but the STATE_ADDR_*
756 * state must be the next state (ns->nxstate).
757 */
758 ns->stateidx = ns->npstates - 1;
759 } else {
760 ns->stateidx = ns->npstates;
761 }
762 ns->npstates = 0;
763 ns->state = ns->op[ns->stateidx];
764 ns->nxstate = ns->op[ns->stateidx + 1];
765 NS_DBG("find_operation: operation found, index: %d, state: %s, nxstate %s\n",
766 idx, get_state_name(ns->state), get_state_name(ns->nxstate));
767 return 0;
768 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000769
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 if (opsfound == 0) {
771 /* Nothing was found. Try to ignore previous commands (if any) and search again */
772 if (ns->npstates != 0) {
773 NS_DBG("find_operation: no operation found, try again with state %s\n",
774 get_state_name(ns->state));
775 ns->npstates = 0;
776 return find_operation(ns, 0);
777
778 }
779 NS_DBG("find_operation: no operations found\n");
780 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
781 return -2;
782 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000783
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 if (flag) {
785 /* This shouldn't happen */
786 NS_DBG("find_operation: BUG, operation must be known if address is input\n");
787 return -2;
788 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000789
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 NS_DBG("find_operation: there is still ambiguity\n");
791
792 ns->pstates[ns->npstates++] = ns->state;
793
794 return -1;
795}
796
797/*
Vijay Kumard086d432006-10-08 22:02:31 +0530798 * Returns a pointer to the current page.
799 */
800static inline union ns_mem *NS_GET_PAGE(struct nandsim *ns)
801{
802 return &(ns->pages[ns->regs.row]);
803}
804
805/*
806 * Retuns a pointer to the current byte, within the current page.
807 */
808static inline u_char *NS_PAGE_BYTE_OFF(struct nandsim *ns)
809{
810 return NS_GET_PAGE(ns)->byte + ns->regs.column + ns->regs.off;
811}
812
813/*
814 * Fill the NAND buffer with data read from the specified page.
815 */
816static void read_page(struct nandsim *ns, int num)
817{
818 union ns_mem *mypage;
819
820 mypage = NS_GET_PAGE(ns);
821 if (mypage->byte == NULL) {
822 NS_DBG("read_page: page %d not allocated\n", ns->regs.row);
823 memset(ns->buf.byte, 0xFF, num);
824 } else {
825 NS_DBG("read_page: page %d allocated, reading from %d\n",
826 ns->regs.row, ns->regs.column + ns->regs.off);
827 memcpy(ns->buf.byte, NS_PAGE_BYTE_OFF(ns), num);
828 }
829}
830
831/*
832 * Erase all pages in the specified sector.
833 */
834static void erase_sector(struct nandsim *ns)
835{
836 union ns_mem *mypage;
837 int i;
838
839 mypage = NS_GET_PAGE(ns);
840 for (i = 0; i < ns->geom.pgsec; i++) {
841 if (mypage->byte != NULL) {
842 NS_DBG("erase_sector: freeing page %d\n", ns->regs.row+i);
843 kfree(mypage->byte);
844 mypage->byte = NULL;
845 }
846 mypage++;
847 }
848}
849
850/*
851 * Program the specified page with the contents from the NAND buffer.
852 */
853static int prog_page(struct nandsim *ns, int num)
854{
Artem Bityutskiy82810b7b62006-10-20 11:23:56 +0300855 int i;
Vijay Kumard086d432006-10-08 22:02:31 +0530856 union ns_mem *mypage;
857 u_char *pg_off;
858
859 mypage = NS_GET_PAGE(ns);
860 if (mypage->byte == NULL) {
861 NS_DBG("prog_page: allocating page %d\n", ns->regs.row);
862 mypage->byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL);
863 if (mypage->byte == NULL) {
864 NS_ERR("prog_page: error allocating memory for page %d\n", ns->regs.row);
865 return -1;
866 }
867 memset(mypage->byte, 0xFF, ns->geom.pgszoob);
868 }
869
870 pg_off = NS_PAGE_BYTE_OFF(ns);
Artem Bityutskiy82810b7b62006-10-20 11:23:56 +0300871 for (i = 0; i < num; i++)
872 pg_off[i] &= ns->buf.byte[i];
Vijay Kumard086d432006-10-08 22:02:31 +0530873
874 return 0;
875}
876
877/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 * If state has any action bit, perform this action.
879 *
880 * RETURNS: 0 if success, -1 if error.
881 */
Vijay Kumara5602142006-10-14 21:33:34 +0530882static int do_state_action(struct nandsim *ns, uint32_t action)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883{
Vijay Kumard086d432006-10-08 22:02:31 +0530884 int num;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 int busdiv = ns->busw == 8 ? 1 : 2;
886
887 action &= ACTION_MASK;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000888
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 /* Check that page address input is correct */
890 if (action != ACTION_SECERASE && ns->regs.row >= ns->geom.pgnum) {
891 NS_WARN("do_state_action: wrong page number (%#x)\n", ns->regs.row);
892 return -1;
893 }
894
895 switch (action) {
896
897 case ACTION_CPY:
898 /*
899 * Copy page data to the internal buffer.
900 */
901
902 /* Column shouldn't be very large */
903 if (ns->regs.column >= (ns->geom.pgszoob - ns->regs.off)) {
904 NS_ERR("do_state_action: column number is too large\n");
905 break;
906 }
907 num = ns->geom.pgszoob - ns->regs.off - ns->regs.column;
Vijay Kumard086d432006-10-08 22:02:31 +0530908 read_page(ns, num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909
910 NS_DBG("do_state_action: (ACTION_CPY:) copy %d bytes to int buf, raw offset %d\n",
911 num, NS_RAW_OFFSET(ns) + ns->regs.off);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000912
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 if (ns->regs.off == 0)
914 NS_LOG("read page %d\n", ns->regs.row);
915 else if (ns->regs.off < ns->geom.pgsz)
916 NS_LOG("read page %d (second half)\n", ns->regs.row);
917 else
918 NS_LOG("read OOB of page %d\n", ns->regs.row);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000919
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 NS_UDELAY(access_delay);
921 NS_UDELAY(input_cycle * ns->geom.pgsz / 1000 / busdiv);
922
923 break;
924
925 case ACTION_SECERASE:
926 /*
927 * Erase sector.
928 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000929
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 if (ns->lines.wp) {
931 NS_ERR("do_state_action: device is write-protected, ignore sector erase\n");
932 return -1;
933 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000934
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 if (ns->regs.row >= ns->geom.pgnum - ns->geom.pgsec
936 || (ns->regs.row & ~(ns->geom.secsz - 1))) {
937 NS_ERR("do_state_action: wrong sector address (%#x)\n", ns->regs.row);
938 return -1;
939 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000940
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 ns->regs.row = (ns->regs.row <<
942 8 * (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) | ns->regs.column;
943 ns->regs.column = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000944
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 NS_DBG("do_state_action: erase sector at address %#x, off = %d\n",
946 ns->regs.row, NS_RAW_OFFSET(ns));
947 NS_LOG("erase sector %d\n", ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift));
948
Vijay Kumard086d432006-10-08 22:02:31 +0530949 erase_sector(ns);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000950
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 NS_MDELAY(erase_delay);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000952
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 break;
954
955 case ACTION_PRGPAGE:
956 /*
957 * Programm page - move internal buffer data to the page.
958 */
959
960 if (ns->lines.wp) {
961 NS_WARN("do_state_action: device is write-protected, programm\n");
962 return -1;
963 }
964
965 num = ns->geom.pgszoob - ns->regs.off - ns->regs.column;
966 if (num != ns->regs.count) {
967 NS_ERR("do_state_action: too few bytes were input (%d instead of %d)\n",
968 ns->regs.count, num);
969 return -1;
970 }
971
Vijay Kumard086d432006-10-08 22:02:31 +0530972 if (prog_page(ns, num) == -1)
973 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974
975 NS_DBG("do_state_action: copy %d bytes from int buf to (%#x, %#x), raw off = %d\n",
976 num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off);
977 NS_LOG("programm page %d\n", ns->regs.row);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000978
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 NS_UDELAY(programm_delay);
980 NS_UDELAY(output_cycle * ns->geom.pgsz / 1000 / busdiv);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000981
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000983
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 case ACTION_ZEROOFF:
985 NS_DBG("do_state_action: set internal offset to 0\n");
986 ns->regs.off = 0;
987 break;
988
989 case ACTION_HALFOFF:
990 if (!(ns->options & OPT_PAGE512_8BIT)) {
991 NS_ERR("do_state_action: BUG! can't skip half of page for non-512"
992 "byte page size 8x chips\n");
993 return -1;
994 }
995 NS_DBG("do_state_action: set internal offset to %d\n", ns->geom.pgsz/2);
996 ns->regs.off = ns->geom.pgsz/2;
997 break;
998
999 case ACTION_OOBOFF:
1000 NS_DBG("do_state_action: set internal offset to %d\n", ns->geom.pgsz);
1001 ns->regs.off = ns->geom.pgsz;
1002 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001003
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 default:
1005 NS_DBG("do_state_action: BUG! unknown action\n");
1006 }
1007
1008 return 0;
1009}
1010
1011/*
1012 * Switch simulator's state.
1013 */
Vijay Kumara5602142006-10-14 21:33:34 +05301014static void switch_state(struct nandsim *ns)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015{
1016 if (ns->op) {
1017 /*
1018 * The current operation have already been identified.
1019 * Just follow the states chain.
1020 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001021
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 ns->stateidx += 1;
1023 ns->state = ns->nxstate;
1024 ns->nxstate = ns->op[ns->stateidx + 1];
1025
1026 NS_DBG("switch_state: operation is known, switch to the next state, "
1027 "state: %s, nxstate: %s\n",
1028 get_state_name(ns->state), get_state_name(ns->nxstate));
1029
1030 /* See, whether we need to do some action */
1031 if ((ns->state & ACTION_MASK) && do_state_action(ns, ns->state) < 0) {
1032 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1033 return;
1034 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001035
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 } else {
1037 /*
1038 * We don't yet know which operation we perform.
1039 * Try to identify it.
1040 */
1041
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001042 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 * The only event causing the switch_state function to
1044 * be called with yet unknown operation is new command.
1045 */
1046 ns->state = get_state_by_command(ns->regs.command);
1047
1048 NS_DBG("switch_state: operation is unknown, try to find it\n");
1049
1050 if (find_operation(ns, 0) != 0)
1051 return;
1052
1053 if ((ns->state & ACTION_MASK) && do_state_action(ns, ns->state) < 0) {
1054 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1055 return;
1056 }
1057 }
1058
1059 /* For 16x devices column means the page offset in words */
1060 if ((ns->nxstate & STATE_ADDR_MASK) && ns->busw == 16) {
1061 NS_DBG("switch_state: double the column number for 16x device\n");
1062 ns->regs.column <<= 1;
1063 }
1064
1065 if (NS_STATE(ns->nxstate) == STATE_READY) {
1066 /*
1067 * The current state is the last. Return to STATE_READY
1068 */
1069
1070 u_char status = NS_STATUS_OK(ns);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001071
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 /* In case of data states, see if all bytes were input/output */
1073 if ((ns->state & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK))
1074 && ns->regs.count != ns->regs.num) {
1075 NS_WARN("switch_state: not all bytes were processed, %d left\n",
1076 ns->regs.num - ns->regs.count);
1077 status = NS_STATUS_FAILED(ns);
1078 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001079
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 NS_DBG("switch_state: operation complete, switch to STATE_READY state\n");
1081
1082 switch_to_ready_state(ns, status);
1083
1084 return;
1085 } else if (ns->nxstate & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK)) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001086 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 * If the next state is data input/output, switch to it now
1088 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001089
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 ns->state = ns->nxstate;
1091 ns->nxstate = ns->op[++ns->stateidx + 1];
1092 ns->regs.num = ns->regs.count = 0;
1093
1094 NS_DBG("switch_state: the next state is data I/O, switch, "
1095 "state: %s, nxstate: %s\n",
1096 get_state_name(ns->state), get_state_name(ns->nxstate));
1097
1098 /*
1099 * Set the internal register to the count of bytes which
1100 * are expected to be input or output
1101 */
1102 switch (NS_STATE(ns->state)) {
1103 case STATE_DATAIN:
1104 case STATE_DATAOUT:
1105 ns->regs.num = ns->geom.pgszoob - ns->regs.off - ns->regs.column;
1106 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001107
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 case STATE_DATAOUT_ID:
1109 ns->regs.num = ns->geom.idbytes;
1110 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001111
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 case STATE_DATAOUT_STATUS:
1113 case STATE_DATAOUT_STATUS_M:
1114 ns->regs.count = ns->regs.num = 0;
1115 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001116
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 default:
1118 NS_ERR("switch_state: BUG! unknown data state\n");
1119 }
1120
1121 } else if (ns->nxstate & STATE_ADDR_MASK) {
1122 /*
1123 * If the next state is address input, set the internal
1124 * register to the number of expected address bytes
1125 */
1126
1127 ns->regs.count = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001128
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 switch (NS_STATE(ns->nxstate)) {
1130 case STATE_ADDR_PAGE:
1131 ns->regs.num = ns->geom.pgaddrbytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001132
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 break;
1134 case STATE_ADDR_SEC:
1135 ns->regs.num = ns->geom.secaddrbytes;
1136 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001137
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 case STATE_ADDR_ZERO:
1139 ns->regs.num = 1;
1140 break;
1141
1142 default:
1143 NS_ERR("switch_state: BUG! unknown address state\n");
1144 }
1145 } else {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001146 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 * Just reset internal counters.
1148 */
1149
1150 ns->regs.num = 0;
1151 ns->regs.count = 0;
1152 }
1153}
1154
Vijay Kumara5602142006-10-14 21:33:34 +05301155static u_char ns_nand_read_byte(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156{
1157 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
1158 u_char outb = 0x00;
1159
1160 /* Sanity and correctness checks */
1161 if (!ns->lines.ce) {
1162 NS_ERR("read_byte: chip is disabled, return %#x\n", (uint)outb);
1163 return outb;
1164 }
1165 if (ns->lines.ale || ns->lines.cle) {
1166 NS_ERR("read_byte: ALE or CLE pin is high, return %#x\n", (uint)outb);
1167 return outb;
1168 }
1169 if (!(ns->state & STATE_DATAOUT_MASK)) {
1170 NS_WARN("read_byte: unexpected data output cycle, state is %s "
1171 "return %#x\n", get_state_name(ns->state), (uint)outb);
1172 return outb;
1173 }
1174
1175 /* Status register may be read as many times as it is wanted */
1176 if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS) {
1177 NS_DBG("read_byte: return %#x status\n", ns->regs.status);
1178 return ns->regs.status;
1179 }
1180
1181 /* Check if there is any data in the internal buffer which may be read */
1182 if (ns->regs.count == ns->regs.num) {
1183 NS_WARN("read_byte: no more data to output, return %#x\n", (uint)outb);
1184 return outb;
1185 }
1186
1187 switch (NS_STATE(ns->state)) {
1188 case STATE_DATAOUT:
1189 if (ns->busw == 8) {
1190 outb = ns->buf.byte[ns->regs.count];
1191 ns->regs.count += 1;
1192 } else {
1193 outb = (u_char)cpu_to_le16(ns->buf.word[ns->regs.count >> 1]);
1194 ns->regs.count += 2;
1195 }
1196 break;
1197 case STATE_DATAOUT_ID:
1198 NS_DBG("read_byte: read ID byte %d, total = %d\n", ns->regs.count, ns->regs.num);
1199 outb = ns->ids[ns->regs.count];
1200 ns->regs.count += 1;
1201 break;
1202 default:
1203 BUG();
1204 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001205
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 if (ns->regs.count == ns->regs.num) {
1207 NS_DBG("read_byte: all bytes were read\n");
1208
1209 /*
1210 * The OPT_AUTOINCR allows to read next conseqitive pages without
1211 * new read operation cycle.
1212 */
1213 if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) {
1214 ns->regs.count = 0;
1215 if (ns->regs.row + 1 < ns->geom.pgnum)
1216 ns->regs.row += 1;
1217 NS_DBG("read_byte: switch to the next page (%#x)\n", ns->regs.row);
1218 do_state_action(ns, ACTION_CPY);
1219 }
1220 else if (NS_STATE(ns->nxstate) == STATE_READY)
1221 switch_state(ns);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001222
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001224
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 return outb;
1226}
1227
Vijay Kumara5602142006-10-14 21:33:34 +05301228static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229{
1230 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001231
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 /* Sanity and correctness checks */
1233 if (!ns->lines.ce) {
1234 NS_ERR("write_byte: chip is disabled, ignore write\n");
1235 return;
1236 }
1237 if (ns->lines.ale && ns->lines.cle) {
1238 NS_ERR("write_byte: ALE and CLE pins are high simultaneously, ignore write\n");
1239 return;
1240 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001241
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 if (ns->lines.cle == 1) {
1243 /*
1244 * The byte written is a command.
1245 */
1246
1247 if (byte == NAND_CMD_RESET) {
1248 NS_LOG("reset chip\n");
1249 switch_to_ready_state(ns, NS_STATUS_OK(ns));
1250 return;
1251 }
1252
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001253 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 * Chip might still be in STATE_DATAOUT
1255 * (if OPT_AUTOINCR feature is supported), STATE_DATAOUT_STATUS or
1256 * STATE_DATAOUT_STATUS_M state. If so, switch state.
1257 */
1258 if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS
1259 || NS_STATE(ns->state) == STATE_DATAOUT_STATUS_M
1260 || ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT))
1261 switch_state(ns);
1262
1263 /* Check if chip is expecting command */
1264 if (NS_STATE(ns->nxstate) != STATE_UNKNOWN && !(ns->nxstate & STATE_CMD_MASK)) {
1265 /*
1266 * We are in situation when something else (not command)
1267 * was expected but command was input. In this case ignore
1268 * previous command(s)/state(s) and accept the last one.
1269 */
1270 NS_WARN("write_byte: command (%#x) wasn't expected, expected state is %s, "
1271 "ignore previous states\n", (uint)byte, get_state_name(ns->nxstate));
1272 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1273 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001274
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 /* Check that the command byte is correct */
1276 if (check_command(byte)) {
1277 NS_ERR("write_byte: unknown command %#x\n", (uint)byte);
1278 return;
1279 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001280
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 NS_DBG("command byte corresponding to %s state accepted\n",
1282 get_state_name(get_state_by_command(byte)));
1283 ns->regs.command = byte;
1284 switch_state(ns);
1285
1286 } else if (ns->lines.ale == 1) {
1287 /*
1288 * The byte written is an address.
1289 */
1290
1291 if (NS_STATE(ns->nxstate) == STATE_UNKNOWN) {
1292
1293 NS_DBG("write_byte: operation isn't known yet, identify it\n");
1294
1295 if (find_operation(ns, 1) < 0)
1296 return;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001297
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 if ((ns->state & ACTION_MASK) && do_state_action(ns, ns->state) < 0) {
1299 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1300 return;
1301 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001302
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 ns->regs.count = 0;
1304 switch (NS_STATE(ns->nxstate)) {
1305 case STATE_ADDR_PAGE:
1306 ns->regs.num = ns->geom.pgaddrbytes;
1307 break;
1308 case STATE_ADDR_SEC:
1309 ns->regs.num = ns->geom.secaddrbytes;
1310 break;
1311 case STATE_ADDR_ZERO:
1312 ns->regs.num = 1;
1313 break;
1314 default:
1315 BUG();
1316 }
1317 }
1318
1319 /* Check that chip is expecting address */
1320 if (!(ns->nxstate & STATE_ADDR_MASK)) {
1321 NS_ERR("write_byte: address (%#x) isn't expected, expected state is %s, "
1322 "switch to STATE_READY\n", (uint)byte, get_state_name(ns->nxstate));
1323 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1324 return;
1325 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001326
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 /* Check if this is expected byte */
1328 if (ns->regs.count == ns->regs.num) {
1329 NS_ERR("write_byte: no more address bytes expected\n");
1330 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1331 return;
1332 }
1333
1334 accept_addr_byte(ns, byte);
1335
1336 ns->regs.count += 1;
1337
1338 NS_DBG("write_byte: address byte %#x was accepted (%d bytes input, %d expected)\n",
1339 (uint)byte, ns->regs.count, ns->regs.num);
1340
1341 if (ns->regs.count == ns->regs.num) {
1342 NS_DBG("address (%#x, %#x) is accepted\n", ns->regs.row, ns->regs.column);
1343 switch_state(ns);
1344 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001345
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 } else {
1347 /*
1348 * The byte written is an input data.
1349 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001350
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 /* Check that chip is expecting data input */
1352 if (!(ns->state & STATE_DATAIN_MASK)) {
1353 NS_ERR("write_byte: data input (%#x) isn't expected, state is %s, "
1354 "switch to %s\n", (uint)byte,
1355 get_state_name(ns->state), get_state_name(STATE_READY));
1356 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1357 return;
1358 }
1359
1360 /* Check if this is expected byte */
1361 if (ns->regs.count == ns->regs.num) {
1362 NS_WARN("write_byte: %u input bytes has already been accepted, ignore write\n",
1363 ns->regs.num);
1364 return;
1365 }
1366
1367 if (ns->busw == 8) {
1368 ns->buf.byte[ns->regs.count] = byte;
1369 ns->regs.count += 1;
1370 } else {
1371 ns->buf.word[ns->regs.count >> 1] = cpu_to_le16((uint16_t)byte);
1372 ns->regs.count += 2;
1373 }
1374 }
1375
1376 return;
1377}
1378
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +02001379static void ns_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask)
1380{
1381 struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
1382
1383 ns->lines.cle = bitmask & NAND_CLE ? 1 : 0;
1384 ns->lines.ale = bitmask & NAND_ALE ? 1 : 0;
1385 ns->lines.ce = bitmask & NAND_NCE ? 1 : 0;
1386
1387 if (cmd != NAND_CMD_NONE)
1388 ns_nand_write_byte(mtd, cmd);
1389}
1390
Vijay Kumara5602142006-10-14 21:33:34 +05301391static int ns_device_ready(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392{
1393 NS_DBG("device_ready\n");
1394 return 1;
1395}
1396
Vijay Kumara5602142006-10-14 21:33:34 +05301397static uint16_t ns_nand_read_word(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398{
1399 struct nand_chip *chip = (struct nand_chip *)mtd->priv;
1400
1401 NS_DBG("read_word\n");
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001402
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 return chip->read_byte(mtd) | (chip->read_byte(mtd) << 8);
1404}
1405
Vijay Kumara5602142006-10-14 21:33:34 +05301406static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407{
1408 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
1409
1410 /* Check that chip is expecting data input */
1411 if (!(ns->state & STATE_DATAIN_MASK)) {
1412 NS_ERR("write_buf: data input isn't expected, state is %s, "
1413 "switch to STATE_READY\n", get_state_name(ns->state));
1414 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1415 return;
1416 }
1417
1418 /* Check if these are expected bytes */
1419 if (ns->regs.count + len > ns->regs.num) {
1420 NS_ERR("write_buf: too many input bytes\n");
1421 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1422 return;
1423 }
1424
1425 memcpy(ns->buf.byte + ns->regs.count, buf, len);
1426 ns->regs.count += len;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001427
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 if (ns->regs.count == ns->regs.num) {
1429 NS_DBG("write_buf: %d bytes were written\n", ns->regs.count);
1430 }
1431}
1432
Vijay Kumara5602142006-10-14 21:33:34 +05301433static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434{
1435 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
1436
1437 /* Sanity and correctness checks */
1438 if (!ns->lines.ce) {
1439 NS_ERR("read_buf: chip is disabled\n");
1440 return;
1441 }
1442 if (ns->lines.ale || ns->lines.cle) {
1443 NS_ERR("read_buf: ALE or CLE pin is high\n");
1444 return;
1445 }
1446 if (!(ns->state & STATE_DATAOUT_MASK)) {
1447 NS_WARN("read_buf: unexpected data output cycle, current state is %s\n",
1448 get_state_name(ns->state));
1449 return;
1450 }
1451
1452 if (NS_STATE(ns->state) != STATE_DATAOUT) {
1453 int i;
1454
1455 for (i = 0; i < len; i++)
1456 buf[i] = ((struct nand_chip *)mtd->priv)->read_byte(mtd);
1457
1458 return;
1459 }
1460
1461 /* Check if these are expected bytes */
1462 if (ns->regs.count + len > ns->regs.num) {
1463 NS_ERR("read_buf: too many bytes to read\n");
1464 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1465 return;
1466 }
1467
1468 memcpy(buf, ns->buf.byte + ns->regs.count, len);
1469 ns->regs.count += len;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001470
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 if (ns->regs.count == ns->regs.num) {
1472 if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) {
1473 ns->regs.count = 0;
1474 if (ns->regs.row + 1 < ns->geom.pgnum)
1475 ns->regs.row += 1;
1476 NS_DBG("read_buf: switch to the next page (%#x)\n", ns->regs.row);
1477 do_state_action(ns, ACTION_CPY);
1478 }
1479 else if (NS_STATE(ns->nxstate) == STATE_READY)
1480 switch_state(ns);
1481 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001482
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 return;
1484}
1485
Vijay Kumara5602142006-10-14 21:33:34 +05301486static int ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487{
1488 ns_nand_read_buf(mtd, (u_char *)&ns_verify_buf[0], len);
1489
1490 if (!memcmp(buf, &ns_verify_buf[0], len)) {
1491 NS_DBG("verify_buf: the buffer is OK\n");
1492 return 0;
1493 } else {
1494 NS_DBG("verify_buf: the buffer is wrong\n");
1495 return -EFAULT;
1496 }
1497}
1498
1499/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 * Module initialization function
1501 */
Adrian Bunk2b9175c2005-11-29 14:49:38 +00001502static int __init ns_init_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503{
1504 struct nand_chip *chip;
1505 struct nandsim *nand;
1506 int retval = -ENOMEM;
1507
1508 if (bus_width != 8 && bus_width != 16) {
1509 NS_ERR("wrong bus width (%d), use only 8 or 16\n", bus_width);
1510 return -EINVAL;
1511 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001512
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 /* Allocate and initialize mtd_info, nand_chip and nandsim structures */
Burman Yan95b93a02006-11-15 21:10:29 +02001514 nsmtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 + sizeof(struct nandsim), GFP_KERNEL);
1516 if (!nsmtd) {
1517 NS_ERR("unable to allocate core structures.\n");
1518 return -ENOMEM;
1519 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520 chip = (struct nand_chip *)(nsmtd + 1);
1521 nsmtd->priv = (void *)chip;
1522 nand = (struct nandsim *)(chip + 1);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001523 chip->priv = (void *)nand;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524
1525 /*
1526 * Register simulator's callbacks.
1527 */
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +02001528 chip->cmd_ctrl = ns_hwcontrol;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 chip->read_byte = ns_nand_read_byte;
1530 chip->dev_ready = ns_device_ready;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531 chip->write_buf = ns_nand_write_buf;
1532 chip->read_buf = ns_nand_read_buf;
1533 chip->verify_buf = ns_nand_verify_buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534 chip->read_word = ns_nand_read_word;
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001535 chip->ecc.mode = NAND_ECC_SOFT;
Artem B. Bityuckiy51502282005-03-19 15:33:59 +00001536 chip->options |= NAND_SKIP_BBTSCAN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001538 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 * Perform minimum nandsim structure initialization to handle
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001540 * the initial ID read command correctly
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 */
1542 if (third_id_byte != 0xFF || fourth_id_byte != 0xFF)
1543 nand->geom.idbytes = 4;
1544 else
1545 nand->geom.idbytes = 2;
1546 nand->regs.status = NS_STATUS_OK(nand);
1547 nand->nxstate = STATE_UNKNOWN;
1548 nand->options |= OPT_PAGE256; /* temporary value */
1549 nand->ids[0] = first_id_byte;
1550 nand->ids[1] = second_id_byte;
1551 nand->ids[2] = third_id_byte;
1552 nand->ids[3] = fourth_id_byte;
1553 if (bus_width == 16) {
1554 nand->busw = 16;
1555 chip->options |= NAND_BUSWIDTH_16;
1556 }
1557
David Woodhouse552d9202006-05-14 01:20:46 +01001558 nsmtd->owner = THIS_MODULE;
1559
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560 if ((retval = nand_scan(nsmtd, 1)) != 0) {
1561 NS_ERR("can't register NAND Simulator\n");
1562 if (retval > 0)
1563 retval = -ENXIO;
1564 goto error;
1565 }
1566
Artem B. Bityuckiy51502282005-03-19 15:33:59 +00001567 if ((retval = init_nandsim(nsmtd)) != 0) {
1568 NS_ERR("scan_bbt: can't initialize the nandsim structure\n");
1569 goto error;
1570 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001571
Artem B. Bityuckiy51502282005-03-19 15:33:59 +00001572 if ((retval = nand_default_bbt(nsmtd)) != 0) {
1573 free_nandsim(nand);
1574 goto error;
1575 }
1576
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 /* Register NAND as one big partition */
1578 add_mtd_partitions(nsmtd, &nand->part, 1);
1579
1580 return 0;
1581
1582error:
1583 kfree(nsmtd);
1584
1585 return retval;
1586}
1587
1588module_init(ns_init_module);
1589
1590/*
1591 * Module clean-up function
1592 */
1593static void __exit ns_cleanup_module(void)
1594{
1595 struct nandsim *ns = (struct nandsim *)(((struct nand_chip *)nsmtd->priv)->priv);
1596
1597 free_nandsim(ns); /* Free nandsim private resources */
1598 nand_release(nsmtd); /* Unregisterd drived */
1599 kfree(nsmtd); /* Free other structures */
1600}
1601
1602module_exit(ns_cleanup_module);
1603
1604MODULE_LICENSE ("GPL");
1605MODULE_AUTHOR ("Artem B. Bityuckiy");
1606MODULE_DESCRIPTION ("The NAND flash simulator");
1607