blob: 638e6c256d3ea0efad77a29458db357ee5714c9a [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>
Adrian Hunter2b77a0e2007-03-19 12:46:43 +020040#include <linux/list.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
42/* Default simulator parameters values */
43#if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \
44 !defined(CONFIG_NANDSIM_SECOND_ID_BYTE) || \
45 !defined(CONFIG_NANDSIM_THIRD_ID_BYTE) || \
46 !defined(CONFIG_NANDSIM_FOURTH_ID_BYTE)
47#define CONFIG_NANDSIM_FIRST_ID_BYTE 0x98
48#define CONFIG_NANDSIM_SECOND_ID_BYTE 0x39
49#define CONFIG_NANDSIM_THIRD_ID_BYTE 0xFF /* No byte */
50#define CONFIG_NANDSIM_FOURTH_ID_BYTE 0xFF /* No byte */
51#endif
52
53#ifndef CONFIG_NANDSIM_ACCESS_DELAY
54#define CONFIG_NANDSIM_ACCESS_DELAY 25
55#endif
56#ifndef CONFIG_NANDSIM_PROGRAMM_DELAY
57#define CONFIG_NANDSIM_PROGRAMM_DELAY 200
58#endif
59#ifndef CONFIG_NANDSIM_ERASE_DELAY
60#define CONFIG_NANDSIM_ERASE_DELAY 2
61#endif
62#ifndef CONFIG_NANDSIM_OUTPUT_CYCLE
63#define CONFIG_NANDSIM_OUTPUT_CYCLE 40
64#endif
65#ifndef CONFIG_NANDSIM_INPUT_CYCLE
66#define CONFIG_NANDSIM_INPUT_CYCLE 50
67#endif
68#ifndef CONFIG_NANDSIM_BUS_WIDTH
69#define CONFIG_NANDSIM_BUS_WIDTH 8
70#endif
71#ifndef CONFIG_NANDSIM_DO_DELAYS
72#define CONFIG_NANDSIM_DO_DELAYS 0
73#endif
74#ifndef CONFIG_NANDSIM_LOG
75#define CONFIG_NANDSIM_LOG 0
76#endif
77#ifndef CONFIG_NANDSIM_DBG
78#define CONFIG_NANDSIM_DBG 0
79#endif
80
81static uint first_id_byte = CONFIG_NANDSIM_FIRST_ID_BYTE;
82static uint second_id_byte = CONFIG_NANDSIM_SECOND_ID_BYTE;
83static uint third_id_byte = CONFIG_NANDSIM_THIRD_ID_BYTE;
84static uint fourth_id_byte = CONFIG_NANDSIM_FOURTH_ID_BYTE;
85static uint access_delay = CONFIG_NANDSIM_ACCESS_DELAY;
86static uint programm_delay = CONFIG_NANDSIM_PROGRAMM_DELAY;
87static uint erase_delay = CONFIG_NANDSIM_ERASE_DELAY;
88static uint output_cycle = CONFIG_NANDSIM_OUTPUT_CYCLE;
89static uint input_cycle = CONFIG_NANDSIM_INPUT_CYCLE;
90static uint bus_width = CONFIG_NANDSIM_BUS_WIDTH;
91static uint do_delays = CONFIG_NANDSIM_DO_DELAYS;
92static uint log = CONFIG_NANDSIM_LOG;
93static uint dbg = CONFIG_NANDSIM_DBG;
Adrian Hunter2b77a0e2007-03-19 12:46:43 +020094static unsigned long parts[MAX_MTD_DEVICES];
95static unsigned int parts_num;
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
97module_param(first_id_byte, uint, 0400);
98module_param(second_id_byte, uint, 0400);
99module_param(third_id_byte, uint, 0400);
100module_param(fourth_id_byte, uint, 0400);
101module_param(access_delay, uint, 0400);
102module_param(programm_delay, uint, 0400);
103module_param(erase_delay, uint, 0400);
104module_param(output_cycle, uint, 0400);
105module_param(input_cycle, uint, 0400);
106module_param(bus_width, uint, 0400);
107module_param(do_delays, uint, 0400);
108module_param(log, uint, 0400);
109module_param(dbg, uint, 0400);
Adrian Hunter2b77a0e2007-03-19 12:46:43 +0200110module_param_array(parts, ulong, &parts_num, 0400);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111
112MODULE_PARM_DESC(first_id_byte, "The fist byte returned by NAND Flash 'read ID' command (manufaturer ID)");
113MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)");
114MODULE_PARM_DESC(third_id_byte, "The third byte returned by NAND Flash 'read ID' command");
115MODULE_PARM_DESC(fourth_id_byte, "The fourth byte returned by NAND Flash 'read ID' command");
116MODULE_PARM_DESC(access_delay, "Initial page access delay (microiseconds)");
117MODULE_PARM_DESC(programm_delay, "Page programm delay (microseconds");
118MODULE_PARM_DESC(erase_delay, "Sector erase delay (milliseconds)");
119MODULE_PARM_DESC(output_cycle, "Word output (from flash) time (nanodeconds)");
120MODULE_PARM_DESC(input_cycle, "Word input (to flash) time (nanodeconds)");
121MODULE_PARM_DESC(bus_width, "Chip's bus width (8- or 16-bit)");
122MODULE_PARM_DESC(do_delays, "Simulate NAND delays using busy-waits if not zero");
123MODULE_PARM_DESC(log, "Perform logging if not zero");
124MODULE_PARM_DESC(dbg, "Output debug information if not zero");
Adrian Hunter2b77a0e2007-03-19 12:46:43 +0200125MODULE_PARM_DESC(parts, "Partition sizes (in erase blocks) separated by commas");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
127/* The largest possible page size */
128#define NS_LARGEST_PAGE_SIZE 2048
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000129
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130/* The prefix for simulator output */
131#define NS_OUTPUT_PREFIX "[nandsim]"
132
133/* Simulator's output macros (logging, debugging, warning, error) */
134#define NS_LOG(args...) \
135 do { if (log) printk(KERN_DEBUG NS_OUTPUT_PREFIX " log: " args); } while(0)
136#define NS_DBG(args...) \
137 do { if (dbg) printk(KERN_DEBUG NS_OUTPUT_PREFIX " debug: " args); } while(0)
138#define NS_WARN(args...) \
Adrian Hunter2b77a0e2007-03-19 12:46:43 +0200139 do { printk(KERN_WARNING NS_OUTPUT_PREFIX " warning: " args); } while(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140#define NS_ERR(args...) \
Adrian Hunter2b77a0e2007-03-19 12:46:43 +0200141 do { printk(KERN_ERR NS_OUTPUT_PREFIX " error: " args); } while(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
143/* Busy-wait delay macros (microseconds, milliseconds) */
144#define NS_UDELAY(us) \
145 do { if (do_delays) udelay(us); } while(0)
146#define NS_MDELAY(us) \
147 do { if (do_delays) mdelay(us); } while(0)
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000148
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149/* Is the nandsim structure initialized ? */
150#define NS_IS_INITIALIZED(ns) ((ns)->geom.totsz != 0)
151
152/* Good operation completion status */
153#define NS_STATUS_OK(ns) (NAND_STATUS_READY | (NAND_STATUS_WP * ((ns)->lines.wp == 0)))
154
155/* Operation failed completion status */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000156#define NS_STATUS_FAILED(ns) (NAND_STATUS_FAIL | NS_STATUS_OK(ns))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157
158/* Calculate the page offset in flash RAM image by (row, column) address */
159#define NS_RAW_OFFSET(ns) \
160 (((ns)->regs.row << (ns)->geom.pgshift) + ((ns)->regs.row * (ns)->geom.oobsz) + (ns)->regs.column)
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000161
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162/* Calculate the OOB offset in flash RAM image by (row, column) address */
163#define NS_RAW_OFFSET_OOB(ns) (NS_RAW_OFFSET(ns) + ns->geom.pgsz)
164
165/* After a command is input, the simulator goes to one of the following states */
166#define STATE_CMD_READ0 0x00000001 /* read data from the beginning of page */
167#define STATE_CMD_READ1 0x00000002 /* read data from the second half of page */
Artem Bityutskiy4a0c50c2006-12-06 21:52:32 +0200168#define STATE_CMD_READSTART 0x00000003 /* read data second command (large page devices) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169#define STATE_CMD_PAGEPROG 0x00000004 /* start page programm */
170#define STATE_CMD_READOOB 0x00000005 /* read OOB area */
171#define STATE_CMD_ERASE1 0x00000006 /* sector erase first command */
172#define STATE_CMD_STATUS 0x00000007 /* read status */
173#define STATE_CMD_STATUS_M 0x00000008 /* read multi-plane status (isn't implemented) */
174#define STATE_CMD_SEQIN 0x00000009 /* sequential data imput */
175#define STATE_CMD_READID 0x0000000A /* read ID */
176#define STATE_CMD_ERASE2 0x0000000B /* sector erase second command */
177#define STATE_CMD_RESET 0x0000000C /* reset */
178#define STATE_CMD_MASK 0x0000000F /* command states mask */
179
180/* After an addres is input, the simulator goes to one of these states */
181#define STATE_ADDR_PAGE 0x00000010 /* full (row, column) address is accepted */
182#define STATE_ADDR_SEC 0x00000020 /* sector address was accepted */
183#define STATE_ADDR_ZERO 0x00000030 /* one byte zero address was accepted */
184#define STATE_ADDR_MASK 0x00000030 /* address states mask */
185
186/* Durind data input/output the simulator is in these states */
187#define STATE_DATAIN 0x00000100 /* waiting for data input */
188#define STATE_DATAIN_MASK 0x00000100 /* data input states mask */
189
190#define STATE_DATAOUT 0x00001000 /* waiting for page data output */
191#define STATE_DATAOUT_ID 0x00002000 /* waiting for ID bytes output */
192#define STATE_DATAOUT_STATUS 0x00003000 /* waiting for status output */
193#define STATE_DATAOUT_STATUS_M 0x00004000 /* waiting for multi-plane status output */
194#define STATE_DATAOUT_MASK 0x00007000 /* data output states mask */
195
196/* Previous operation is done, ready to accept new requests */
197#define STATE_READY 0x00000000
198
199/* This state is used to mark that the next state isn't known yet */
200#define STATE_UNKNOWN 0x10000000
201
202/* Simulator's actions bit masks */
203#define ACTION_CPY 0x00100000 /* copy page/OOB to the internal buffer */
204#define ACTION_PRGPAGE 0x00200000 /* programm the internal buffer to flash */
205#define ACTION_SECERASE 0x00300000 /* erase sector */
206#define ACTION_ZEROOFF 0x00400000 /* don't add any offset to address */
207#define ACTION_HALFOFF 0x00500000 /* add to address half of page */
208#define ACTION_OOBOFF 0x00600000 /* add to address OOB offset */
209#define ACTION_MASK 0x00700000 /* action mask */
210
211#define NS_OPER_NUM 12 /* Number of operations supported by the simulator */
212#define NS_OPER_STATES 6 /* Maximum number of states in operation */
213
214#define OPT_ANY 0xFFFFFFFF /* any chip supports this operation */
215#define OPT_PAGE256 0x00000001 /* 256-byte page chips */
216#define OPT_PAGE512 0x00000002 /* 512-byte page chips */
217#define OPT_PAGE2048 0x00000008 /* 2048-byte page chips */
218#define OPT_SMARTMEDIA 0x00000010 /* SmartMedia technology chips */
219#define OPT_AUTOINCR 0x00000020 /* page number auto inctimentation is possible */
220#define OPT_PAGE512_8BIT 0x00000040 /* 512-byte page chips with 8-bit bus width */
221#define OPT_LARGEPAGE (OPT_PAGE2048) /* 2048-byte page chips */
222#define OPT_SMALLPAGE (OPT_PAGE256 | OPT_PAGE512) /* 256 and 512-byte page chips */
223
224/* Remove action bits ftom state */
225#define NS_STATE(x) ((x) & ~ACTION_MASK)
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000226
227/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228 * Maximum previous states which need to be saved. Currently saving is
229 * only needed for page programm operation with preceeded read command
230 * (which is only valid for 512-byte pages).
231 */
232#define NS_MAX_PREVSTATES 1
233
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000234/*
Vijay Kumard086d432006-10-08 22:02:31 +0530235 * A union to represent flash memory contents and flash buffer.
236 */
237union ns_mem {
238 u_char *byte; /* for byte access */
239 uint16_t *word; /* for 16-bit word access */
240};
241
242/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 * The structure which describes all the internal simulator data.
244 */
245struct nandsim {
Adrian Hunter2b77a0e2007-03-19 12:46:43 +0200246 struct mtd_partition partitions[MAX_MTD_DEVICES];
247 unsigned int nbparts;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
249 uint busw; /* flash chip bus width (8 or 16) */
250 u_char ids[4]; /* chip's ID bytes */
251 uint32_t options; /* chip's characteristic bits */
252 uint32_t state; /* current chip state */
253 uint32_t nxstate; /* next expected state */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000254
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 uint32_t *op; /* current operation, NULL operations isn't known yet */
256 uint32_t pstates[NS_MAX_PREVSTATES]; /* previous states */
257 uint16_t npstates; /* number of previous states saved */
258 uint16_t stateidx; /* current state index */
259
Vijay Kumard086d432006-10-08 22:02:31 +0530260 /* The simulated NAND flash pages array */
261 union ns_mem *pages;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262
263 /* Internal buffer of page + OOB size bytes */
Vijay Kumard086d432006-10-08 22:02:31 +0530264 union ns_mem buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265
266 /* NAND flash "geometry" */
267 struct nandsin_geometry {
268 uint32_t totsz; /* total flash size, bytes */
269 uint32_t secsz; /* flash sector (erase block) size, bytes */
270 uint pgsz; /* NAND flash page size, bytes */
271 uint oobsz; /* page OOB area size, bytes */
272 uint32_t totszoob; /* total flash size including OOB, bytes */
273 uint pgszoob; /* page size including OOB , bytes*/
274 uint secszoob; /* sector size including OOB, bytes */
275 uint pgnum; /* total number of pages */
276 uint pgsec; /* number of pages per sector */
277 uint secshift; /* bits number in sector size */
278 uint pgshift; /* bits number in page size */
279 uint oobshift; /* bits number in OOB size */
280 uint pgaddrbytes; /* bytes per page address */
281 uint secaddrbytes; /* bytes per sector address */
282 uint idbytes; /* the number ID bytes that this chip outputs */
283 } geom;
284
285 /* NAND flash internal registers */
286 struct nandsim_regs {
287 unsigned command; /* the command register */
288 u_char status; /* the status register */
289 uint row; /* the page number */
290 uint column; /* the offset within page */
291 uint count; /* internal counter */
292 uint num; /* number of bytes which must be processed */
293 uint off; /* fixed page offset */
294 } regs;
295
296 /* NAND flash lines state */
297 struct ns_lines_status {
298 int ce; /* chip Enable */
299 int cle; /* command Latch Enable */
300 int ale; /* address Latch Enable */
301 int wp; /* write Protect */
302 } lines;
303};
304
305/*
306 * Operations array. To perform any operation the simulator must pass
307 * through the correspondent states chain.
308 */
309static struct nandsim_operations {
310 uint32_t reqopts; /* options which are required to perform the operation */
311 uint32_t states[NS_OPER_STATES]; /* operation's states */
312} ops[NS_OPER_NUM] = {
313 /* Read page + OOB from the beginning */
314 {OPT_SMALLPAGE, {STATE_CMD_READ0 | ACTION_ZEROOFF, STATE_ADDR_PAGE | ACTION_CPY,
315 STATE_DATAOUT, STATE_READY}},
316 /* Read page + OOB from the second half */
317 {OPT_PAGE512_8BIT, {STATE_CMD_READ1 | ACTION_HALFOFF, STATE_ADDR_PAGE | ACTION_CPY,
318 STATE_DATAOUT, STATE_READY}},
319 /* Read OOB */
320 {OPT_SMALLPAGE, {STATE_CMD_READOOB | ACTION_OOBOFF, STATE_ADDR_PAGE | ACTION_CPY,
321 STATE_DATAOUT, STATE_READY}},
322 /* Programm page starting from the beginning */
323 {OPT_ANY, {STATE_CMD_SEQIN, STATE_ADDR_PAGE, STATE_DATAIN,
324 STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}},
325 /* Programm page starting from the beginning */
326 {OPT_SMALLPAGE, {STATE_CMD_READ0, STATE_CMD_SEQIN | ACTION_ZEROOFF, STATE_ADDR_PAGE,
327 STATE_DATAIN, STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}},
328 /* Programm page starting from the second half */
329 {OPT_PAGE512, {STATE_CMD_READ1, STATE_CMD_SEQIN | ACTION_HALFOFF, STATE_ADDR_PAGE,
330 STATE_DATAIN, STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}},
331 /* Programm OOB */
332 {OPT_SMALLPAGE, {STATE_CMD_READOOB, STATE_CMD_SEQIN | ACTION_OOBOFF, STATE_ADDR_PAGE,
333 STATE_DATAIN, STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}},
334 /* Erase sector */
335 {OPT_ANY, {STATE_CMD_ERASE1, STATE_ADDR_SEC, STATE_CMD_ERASE2 | ACTION_SECERASE, STATE_READY}},
336 /* Read status */
337 {OPT_ANY, {STATE_CMD_STATUS, STATE_DATAOUT_STATUS, STATE_READY}},
338 /* Read multi-plane status */
339 {OPT_SMARTMEDIA, {STATE_CMD_STATUS_M, STATE_DATAOUT_STATUS_M, STATE_READY}},
340 /* Read ID */
341 {OPT_ANY, {STATE_CMD_READID, STATE_ADDR_ZERO, STATE_DATAOUT_ID, STATE_READY}},
342 /* Large page devices read page */
343 {OPT_LARGEPAGE, {STATE_CMD_READ0, STATE_ADDR_PAGE, STATE_CMD_READSTART | ACTION_CPY,
344 STATE_DATAOUT, STATE_READY}}
345};
346
347/* MTD structure for NAND controller */
348static struct mtd_info *nsmtd;
349
350static u_char ns_verify_buf[NS_LARGEST_PAGE_SIZE];
351
352/*
Vijay Kumard086d432006-10-08 22:02:31 +0530353 * Allocate array of page pointers and initialize the array to NULL
354 * pointers.
355 *
356 * RETURNS: 0 if success, -ENOMEM if memory alloc fails.
357 */
Vijay Kumara5602142006-10-14 21:33:34 +0530358static int alloc_device(struct nandsim *ns)
Vijay Kumard086d432006-10-08 22:02:31 +0530359{
360 int i;
361
362 ns->pages = vmalloc(ns->geom.pgnum * sizeof(union ns_mem));
363 if (!ns->pages) {
364 NS_ERR("alloc_map: unable to allocate page array\n");
365 return -ENOMEM;
366 }
367 for (i = 0; i < ns->geom.pgnum; i++) {
368 ns->pages[i].byte = NULL;
369 }
370
371 return 0;
372}
373
374/*
375 * Free any allocated pages, and free the array of page pointers.
376 */
Vijay Kumara5602142006-10-14 21:33:34 +0530377static void free_device(struct nandsim *ns)
Vijay Kumard086d432006-10-08 22:02:31 +0530378{
379 int i;
380
381 if (ns->pages) {
382 for (i = 0; i < ns->geom.pgnum; i++) {
383 if (ns->pages[i].byte)
384 kfree(ns->pages[i].byte);
385 }
386 vfree(ns->pages);
387 }
388}
389
Adrian Hunter2b77a0e2007-03-19 12:46:43 +0200390static char *get_partition_name(int i)
391{
392 char buf[64];
393 sprintf(buf, "NAND simulator partition %d", i);
394 return kstrdup(buf, GFP_KERNEL);
395}
396
Vijay Kumard086d432006-10-08 22:02:31 +0530397/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 * Initialize the nandsim structure.
399 *
400 * RETURNS: 0 if success, -ERRNO if failure.
401 */
Vijay Kumara5602142006-10-14 21:33:34 +0530402static int init_nandsim(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403{
404 struct nand_chip *chip = (struct nand_chip *)mtd->priv;
405 struct nandsim *ns = (struct nandsim *)(chip->priv);
Adrian Hunter2b77a0e2007-03-19 12:46:43 +0200406 int i, ret = 0;
407 u_int32_t remains;
408 u_int32_t next_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409
410 if (NS_IS_INITIALIZED(ns)) {
411 NS_ERR("init_nandsim: nandsim is already initialized\n");
412 return -EIO;
413 }
414
415 /* Force mtd to not do delays */
416 chip->chip_delay = 0;
417
418 /* Initialize the NAND flash parameters */
419 ns->busw = chip->options & NAND_BUSWIDTH_16 ? 16 : 8;
420 ns->geom.totsz = mtd->size;
Joern Engel28318772006-05-22 23:18:05 +0200421 ns->geom.pgsz = mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 ns->geom.oobsz = mtd->oobsize;
423 ns->geom.secsz = mtd->erasesize;
424 ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz;
425 ns->geom.pgnum = ns->geom.totsz / ns->geom.pgsz;
426 ns->geom.totszoob = ns->geom.totsz + ns->geom.pgnum * ns->geom.oobsz;
427 ns->geom.secshift = ffs(ns->geom.secsz) - 1;
428 ns->geom.pgshift = chip->page_shift;
429 ns->geom.oobshift = ffs(ns->geom.oobsz) - 1;
430 ns->geom.pgsec = ns->geom.secsz / ns->geom.pgsz;
431 ns->geom.secszoob = ns->geom.secsz + ns->geom.oobsz * ns->geom.pgsec;
432 ns->options = 0;
433
434 if (ns->geom.pgsz == 256) {
435 ns->options |= OPT_PAGE256;
436 }
437 else if (ns->geom.pgsz == 512) {
438 ns->options |= (OPT_PAGE512 | OPT_AUTOINCR);
439 if (ns->busw == 8)
440 ns->options |= OPT_PAGE512_8BIT;
441 } else if (ns->geom.pgsz == 2048) {
442 ns->options |= OPT_PAGE2048;
443 } else {
444 NS_ERR("init_nandsim: unknown page size %u\n", ns->geom.pgsz);
445 return -EIO;
446 }
447
448 if (ns->options & OPT_SMALLPAGE) {
449 if (ns->geom.totsz < (64 << 20)) {
450 ns->geom.pgaddrbytes = 3;
451 ns->geom.secaddrbytes = 2;
452 } else {
453 ns->geom.pgaddrbytes = 4;
454 ns->geom.secaddrbytes = 3;
455 }
456 } else {
457 if (ns->geom.totsz <= (128 << 20)) {
Artem Bityutskiy4a0c50c2006-12-06 21:52:32 +0200458 ns->geom.pgaddrbytes = 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 ns->geom.secaddrbytes = 2;
460 } else {
461 ns->geom.pgaddrbytes = 5;
462 ns->geom.secaddrbytes = 3;
463 }
464 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000465
Adrian Hunter2b77a0e2007-03-19 12:46:43 +0200466 /* Fill the partition_info structure */
467 if (parts_num > ARRAY_SIZE(ns->partitions)) {
468 NS_ERR("too many partitions.\n");
469 ret = -EINVAL;
470 goto error;
471 }
472 remains = ns->geom.totsz;
473 next_offset = 0;
474 for (i = 0; i < parts_num; ++i) {
475 unsigned long part = parts[i];
476 if (!part || part > remains / ns->geom.secsz) {
477 NS_ERR("bad partition size.\n");
478 ret = -EINVAL;
479 goto error;
480 }
481 ns->partitions[i].name = get_partition_name(i);
482 ns->partitions[i].offset = next_offset;
483 ns->partitions[i].size = part * ns->geom.secsz;
484 next_offset += ns->partitions[i].size;
485 remains -= ns->partitions[i].size;
486 }
487 ns->nbparts = parts_num;
488 if (remains) {
489 if (parts_num + 1 > ARRAY_SIZE(ns->partitions)) {
490 NS_ERR("too many partitions.\n");
491 ret = -EINVAL;
492 goto error;
493 }
494 ns->partitions[i].name = get_partition_name(i);
495 ns->partitions[i].offset = next_offset;
496 ns->partitions[i].size = remains;
497 ns->nbparts += 1;
498 }
499
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 /* Detect how many ID bytes the NAND chip outputs */
501 for (i = 0; nand_flash_ids[i].name != NULL; i++) {
502 if (second_id_byte != nand_flash_ids[i].id)
503 continue;
504 if (!(nand_flash_ids[i].options & NAND_NO_AUTOINCR))
505 ns->options |= OPT_AUTOINCR;
506 }
507
508 if (ns->busw == 16)
509 NS_WARN("16-bit flashes support wasn't tested\n");
510
511 printk("flash size: %u MiB\n", ns->geom.totsz >> 20);
512 printk("page size: %u bytes\n", ns->geom.pgsz);
513 printk("OOB area size: %u bytes\n", ns->geom.oobsz);
514 printk("sector size: %u KiB\n", ns->geom.secsz >> 10);
515 printk("pages number: %u\n", ns->geom.pgnum);
516 printk("pages per sector: %u\n", ns->geom.pgsec);
517 printk("bus width: %u\n", ns->busw);
518 printk("bits in sector size: %u\n", ns->geom.secshift);
519 printk("bits in page size: %u\n", ns->geom.pgshift);
520 printk("bits in OOB size: %u\n", ns->geom.oobshift);
521 printk("flash size with OOB: %u KiB\n", ns->geom.totszoob >> 10);
522 printk("page address bytes: %u\n", ns->geom.pgaddrbytes);
523 printk("sector address bytes: %u\n", ns->geom.secaddrbytes);
524 printk("options: %#x\n", ns->options);
525
Adrian Hunter2b77a0e2007-03-19 12:46:43 +0200526 if ((ret = alloc_device(ns)) != 0)
Vijay Kumard086d432006-10-08 22:02:31 +0530527 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528
529 /* Allocate / initialize the internal buffer */
530 ns->buf.byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL);
531 if (!ns->buf.byte) {
532 NS_ERR("init_nandsim: unable to allocate %u bytes for the internal buffer\n",
533 ns->geom.pgszoob);
Adrian Hunter2b77a0e2007-03-19 12:46:43 +0200534 ret = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 goto error;
536 }
537 memset(ns->buf.byte, 0xFF, ns->geom.pgszoob);
538
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 return 0;
540
541error:
Vijay Kumard086d432006-10-08 22:02:31 +0530542 free_device(ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543
Adrian Hunter2b77a0e2007-03-19 12:46:43 +0200544 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545}
546
547/*
548 * Free the nandsim structure.
549 */
Vijay Kumara5602142006-10-14 21:33:34 +0530550static void free_nandsim(struct nandsim *ns)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551{
552 kfree(ns->buf.byte);
Vijay Kumard086d432006-10-08 22:02:31 +0530553 free_device(ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554
555 return;
556}
557
558/*
559 * Returns the string representation of 'state' state.
560 */
Vijay Kumara5602142006-10-14 21:33:34 +0530561static char *get_state_name(uint32_t state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562{
563 switch (NS_STATE(state)) {
564 case STATE_CMD_READ0:
565 return "STATE_CMD_READ0";
566 case STATE_CMD_READ1:
567 return "STATE_CMD_READ1";
568 case STATE_CMD_PAGEPROG:
569 return "STATE_CMD_PAGEPROG";
570 case STATE_CMD_READOOB:
571 return "STATE_CMD_READOOB";
572 case STATE_CMD_READSTART:
573 return "STATE_CMD_READSTART";
574 case STATE_CMD_ERASE1:
575 return "STATE_CMD_ERASE1";
576 case STATE_CMD_STATUS:
577 return "STATE_CMD_STATUS";
578 case STATE_CMD_STATUS_M:
579 return "STATE_CMD_STATUS_M";
580 case STATE_CMD_SEQIN:
581 return "STATE_CMD_SEQIN";
582 case STATE_CMD_READID:
583 return "STATE_CMD_READID";
584 case STATE_CMD_ERASE2:
585 return "STATE_CMD_ERASE2";
586 case STATE_CMD_RESET:
587 return "STATE_CMD_RESET";
588 case STATE_ADDR_PAGE:
589 return "STATE_ADDR_PAGE";
590 case STATE_ADDR_SEC:
591 return "STATE_ADDR_SEC";
592 case STATE_ADDR_ZERO:
593 return "STATE_ADDR_ZERO";
594 case STATE_DATAIN:
595 return "STATE_DATAIN";
596 case STATE_DATAOUT:
597 return "STATE_DATAOUT";
598 case STATE_DATAOUT_ID:
599 return "STATE_DATAOUT_ID";
600 case STATE_DATAOUT_STATUS:
601 return "STATE_DATAOUT_STATUS";
602 case STATE_DATAOUT_STATUS_M:
603 return "STATE_DATAOUT_STATUS_M";
604 case STATE_READY:
605 return "STATE_READY";
606 case STATE_UNKNOWN:
607 return "STATE_UNKNOWN";
608 }
609
610 NS_ERR("get_state_name: unknown state, BUG\n");
611 return NULL;
612}
613
614/*
615 * Check if command is valid.
616 *
617 * RETURNS: 1 if wrong command, 0 if right.
618 */
Vijay Kumara5602142006-10-14 21:33:34 +0530619static int check_command(int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620{
621 switch (cmd) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000622
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 case NAND_CMD_READ0:
624 case NAND_CMD_READSTART:
625 case NAND_CMD_PAGEPROG:
626 case NAND_CMD_READOOB:
627 case NAND_CMD_ERASE1:
628 case NAND_CMD_STATUS:
629 case NAND_CMD_SEQIN:
630 case NAND_CMD_READID:
631 case NAND_CMD_ERASE2:
632 case NAND_CMD_RESET:
633 case NAND_CMD_READ1:
634 return 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000635
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 case NAND_CMD_STATUS_MULTI:
637 default:
638 return 1;
639 }
640}
641
642/*
643 * Returns state after command is accepted by command number.
644 */
Vijay Kumara5602142006-10-14 21:33:34 +0530645static uint32_t get_state_by_command(unsigned command)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646{
647 switch (command) {
648 case NAND_CMD_READ0:
649 return STATE_CMD_READ0;
650 case NAND_CMD_READ1:
651 return STATE_CMD_READ1;
652 case NAND_CMD_PAGEPROG:
653 return STATE_CMD_PAGEPROG;
654 case NAND_CMD_READSTART:
655 return STATE_CMD_READSTART;
656 case NAND_CMD_READOOB:
657 return STATE_CMD_READOOB;
658 case NAND_CMD_ERASE1:
659 return STATE_CMD_ERASE1;
660 case NAND_CMD_STATUS:
661 return STATE_CMD_STATUS;
662 case NAND_CMD_STATUS_MULTI:
663 return STATE_CMD_STATUS_M;
664 case NAND_CMD_SEQIN:
665 return STATE_CMD_SEQIN;
666 case NAND_CMD_READID:
667 return STATE_CMD_READID;
668 case NAND_CMD_ERASE2:
669 return STATE_CMD_ERASE2;
670 case NAND_CMD_RESET:
671 return STATE_CMD_RESET;
672 }
673
674 NS_ERR("get_state_by_command: unknown command, BUG\n");
675 return 0;
676}
677
678/*
679 * Move an address byte to the correspondent internal register.
680 */
Vijay Kumara5602142006-10-14 21:33:34 +0530681static inline void accept_addr_byte(struct nandsim *ns, u_char bt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682{
683 uint byte = (uint)bt;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000684
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 if (ns->regs.count < (ns->geom.pgaddrbytes - ns->geom.secaddrbytes))
686 ns->regs.column |= (byte << 8 * ns->regs.count);
687 else {
688 ns->regs.row |= (byte << 8 * (ns->regs.count -
689 ns->geom.pgaddrbytes +
690 ns->geom.secaddrbytes));
691 }
692
693 return;
694}
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000695
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696/*
697 * Switch to STATE_READY state.
698 */
Vijay Kumara5602142006-10-14 21:33:34 +0530699static inline void switch_to_ready_state(struct nandsim *ns, u_char status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700{
701 NS_DBG("switch_to_ready_state: switch to %s state\n", get_state_name(STATE_READY));
702
703 ns->state = STATE_READY;
704 ns->nxstate = STATE_UNKNOWN;
705 ns->op = NULL;
706 ns->npstates = 0;
707 ns->stateidx = 0;
708 ns->regs.num = 0;
709 ns->regs.count = 0;
710 ns->regs.off = 0;
711 ns->regs.row = 0;
712 ns->regs.column = 0;
713 ns->regs.status = status;
714}
715
716/*
717 * If the operation isn't known yet, try to find it in the global array
718 * of supported operations.
719 *
720 * Operation can be unknown because of the following.
721 * 1. New command was accepted and this is the firs call to find the
722 * correspondent states chain. In this case ns->npstates = 0;
723 * 2. There is several operations which begin with the same command(s)
724 * (for example program from the second half and read from the
725 * second half operations both begin with the READ1 command). In this
726 * case the ns->pstates[] array contains previous states.
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000727 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 * Thus, the function tries to find operation containing the following
729 * states (if the 'flag' parameter is 0):
730 * ns->pstates[0], ... ns->pstates[ns->npstates], ns->state
731 *
732 * If (one and only one) matching operation is found, it is accepted (
733 * ns->ops, ns->state, ns->nxstate are initialized, ns->npstate is
734 * zeroed).
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000735 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 * If there are several maches, the current state is pushed to the
737 * ns->pstates.
738 *
739 * The operation can be unknown only while commands are input to the chip.
740 * As soon as address command is accepted, the operation must be known.
741 * In such situation the function is called with 'flag' != 0, and the
742 * operation is searched using the following pattern:
743 * ns->pstates[0], ... ns->pstates[ns->npstates], <address input>
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000744 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 * It is supposed that this pattern must either match one operation on
746 * none. There can't be ambiguity in that case.
747 *
748 * If no matches found, the functions does the following:
749 * 1. if there are saved states present, try to ignore them and search
750 * again only using the last command. If nothing was found, switch
751 * to the STATE_READY state.
752 * 2. if there are no saved states, switch to the STATE_READY state.
753 *
754 * RETURNS: -2 - no matched operations found.
755 * -1 - several matches.
756 * 0 - operation is found.
757 */
Vijay Kumara5602142006-10-14 21:33:34 +0530758static int find_operation(struct nandsim *ns, uint32_t flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759{
760 int opsfound = 0;
761 int i, j, idx = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000762
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 for (i = 0; i < NS_OPER_NUM; i++) {
764
765 int found = 1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000766
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 if (!(ns->options & ops[i].reqopts))
768 /* Ignore operations we can't perform */
769 continue;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000770
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 if (flag) {
772 if (!(ops[i].states[ns->npstates] & STATE_ADDR_MASK))
773 continue;
774 } else {
775 if (NS_STATE(ns->state) != NS_STATE(ops[i].states[ns->npstates]))
776 continue;
777 }
778
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000779 for (j = 0; j < ns->npstates; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 if (NS_STATE(ops[i].states[j]) != NS_STATE(ns->pstates[j])
781 && (ns->options & ops[idx].reqopts)) {
782 found = 0;
783 break;
784 }
785
786 if (found) {
787 idx = i;
788 opsfound += 1;
789 }
790 }
791
792 if (opsfound == 1) {
793 /* Exact match */
794 ns->op = &ops[idx].states[0];
795 if (flag) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000796 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 * In this case the find_operation function was
798 * called when address has just began input. But it isn't
799 * yet fully input and the current state must
800 * not be one of STATE_ADDR_*, but the STATE_ADDR_*
801 * state must be the next state (ns->nxstate).
802 */
803 ns->stateidx = ns->npstates - 1;
804 } else {
805 ns->stateidx = ns->npstates;
806 }
807 ns->npstates = 0;
808 ns->state = ns->op[ns->stateidx];
809 ns->nxstate = ns->op[ns->stateidx + 1];
810 NS_DBG("find_operation: operation found, index: %d, state: %s, nxstate %s\n",
811 idx, get_state_name(ns->state), get_state_name(ns->nxstate));
812 return 0;
813 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000814
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 if (opsfound == 0) {
816 /* Nothing was found. Try to ignore previous commands (if any) and search again */
817 if (ns->npstates != 0) {
818 NS_DBG("find_operation: no operation found, try again with state %s\n",
819 get_state_name(ns->state));
820 ns->npstates = 0;
821 return find_operation(ns, 0);
822
823 }
824 NS_DBG("find_operation: no operations found\n");
825 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
826 return -2;
827 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000828
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 if (flag) {
830 /* This shouldn't happen */
831 NS_DBG("find_operation: BUG, operation must be known if address is input\n");
832 return -2;
833 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000834
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 NS_DBG("find_operation: there is still ambiguity\n");
836
837 ns->pstates[ns->npstates++] = ns->state;
838
839 return -1;
840}
841
842/*
Vijay Kumard086d432006-10-08 22:02:31 +0530843 * Returns a pointer to the current page.
844 */
845static inline union ns_mem *NS_GET_PAGE(struct nandsim *ns)
846{
847 return &(ns->pages[ns->regs.row]);
848}
849
850/*
851 * Retuns a pointer to the current byte, within the current page.
852 */
853static inline u_char *NS_PAGE_BYTE_OFF(struct nandsim *ns)
854{
855 return NS_GET_PAGE(ns)->byte + ns->regs.column + ns->regs.off;
856}
857
858/*
859 * Fill the NAND buffer with data read from the specified page.
860 */
861static void read_page(struct nandsim *ns, int num)
862{
863 union ns_mem *mypage;
864
865 mypage = NS_GET_PAGE(ns);
866 if (mypage->byte == NULL) {
867 NS_DBG("read_page: page %d not allocated\n", ns->regs.row);
868 memset(ns->buf.byte, 0xFF, num);
869 } else {
870 NS_DBG("read_page: page %d allocated, reading from %d\n",
871 ns->regs.row, ns->regs.column + ns->regs.off);
872 memcpy(ns->buf.byte, NS_PAGE_BYTE_OFF(ns), num);
873 }
874}
875
876/*
877 * Erase all pages in the specified sector.
878 */
879static void erase_sector(struct nandsim *ns)
880{
881 union ns_mem *mypage;
882 int i;
883
884 mypage = NS_GET_PAGE(ns);
885 for (i = 0; i < ns->geom.pgsec; i++) {
886 if (mypage->byte != NULL) {
887 NS_DBG("erase_sector: freeing page %d\n", ns->regs.row+i);
888 kfree(mypage->byte);
889 mypage->byte = NULL;
890 }
891 mypage++;
892 }
893}
894
895/*
896 * Program the specified page with the contents from the NAND buffer.
897 */
898static int prog_page(struct nandsim *ns, int num)
899{
Artem Bityutskiy82810b7b62006-10-20 11:23:56 +0300900 int i;
Vijay Kumard086d432006-10-08 22:02:31 +0530901 union ns_mem *mypage;
902 u_char *pg_off;
903
904 mypage = NS_GET_PAGE(ns);
905 if (mypage->byte == NULL) {
906 NS_DBG("prog_page: allocating page %d\n", ns->regs.row);
907 mypage->byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL);
908 if (mypage->byte == NULL) {
909 NS_ERR("prog_page: error allocating memory for page %d\n", ns->regs.row);
910 return -1;
911 }
912 memset(mypage->byte, 0xFF, ns->geom.pgszoob);
913 }
914
915 pg_off = NS_PAGE_BYTE_OFF(ns);
Artem Bityutskiy82810b7b62006-10-20 11:23:56 +0300916 for (i = 0; i < num; i++)
917 pg_off[i] &= ns->buf.byte[i];
Vijay Kumard086d432006-10-08 22:02:31 +0530918
919 return 0;
920}
921
922/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 * If state has any action bit, perform this action.
924 *
925 * RETURNS: 0 if success, -1 if error.
926 */
Vijay Kumara5602142006-10-14 21:33:34 +0530927static int do_state_action(struct nandsim *ns, uint32_t action)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928{
Vijay Kumard086d432006-10-08 22:02:31 +0530929 int num;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 int busdiv = ns->busw == 8 ? 1 : 2;
931
932 action &= ACTION_MASK;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000933
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 /* Check that page address input is correct */
935 if (action != ACTION_SECERASE && ns->regs.row >= ns->geom.pgnum) {
936 NS_WARN("do_state_action: wrong page number (%#x)\n", ns->regs.row);
937 return -1;
938 }
939
940 switch (action) {
941
942 case ACTION_CPY:
943 /*
944 * Copy page data to the internal buffer.
945 */
946
947 /* Column shouldn't be very large */
948 if (ns->regs.column >= (ns->geom.pgszoob - ns->regs.off)) {
949 NS_ERR("do_state_action: column number is too large\n");
950 break;
951 }
952 num = ns->geom.pgszoob - ns->regs.off - ns->regs.column;
Vijay Kumard086d432006-10-08 22:02:31 +0530953 read_page(ns, num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954
955 NS_DBG("do_state_action: (ACTION_CPY:) copy %d bytes to int buf, raw offset %d\n",
956 num, NS_RAW_OFFSET(ns) + ns->regs.off);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000957
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 if (ns->regs.off == 0)
959 NS_LOG("read page %d\n", ns->regs.row);
960 else if (ns->regs.off < ns->geom.pgsz)
961 NS_LOG("read page %d (second half)\n", ns->regs.row);
962 else
963 NS_LOG("read OOB of page %d\n", ns->regs.row);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000964
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 NS_UDELAY(access_delay);
966 NS_UDELAY(input_cycle * ns->geom.pgsz / 1000 / busdiv);
967
968 break;
969
970 case ACTION_SECERASE:
971 /*
972 * Erase sector.
973 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000974
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 if (ns->lines.wp) {
976 NS_ERR("do_state_action: device is write-protected, ignore sector erase\n");
977 return -1;
978 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000979
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 if (ns->regs.row >= ns->geom.pgnum - ns->geom.pgsec
981 || (ns->regs.row & ~(ns->geom.secsz - 1))) {
982 NS_ERR("do_state_action: wrong sector address (%#x)\n", ns->regs.row);
983 return -1;
984 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000985
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 ns->regs.row = (ns->regs.row <<
987 8 * (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) | ns->regs.column;
988 ns->regs.column = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000989
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 NS_DBG("do_state_action: erase sector at address %#x, off = %d\n",
991 ns->regs.row, NS_RAW_OFFSET(ns));
992 NS_LOG("erase sector %d\n", ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift));
993
Vijay Kumard086d432006-10-08 22:02:31 +0530994 erase_sector(ns);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000995
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 NS_MDELAY(erase_delay);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000997
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 break;
999
1000 case ACTION_PRGPAGE:
1001 /*
1002 * Programm page - move internal buffer data to the page.
1003 */
1004
1005 if (ns->lines.wp) {
1006 NS_WARN("do_state_action: device is write-protected, programm\n");
1007 return -1;
1008 }
1009
1010 num = ns->geom.pgszoob - ns->regs.off - ns->regs.column;
1011 if (num != ns->regs.count) {
1012 NS_ERR("do_state_action: too few bytes were input (%d instead of %d)\n",
1013 ns->regs.count, num);
1014 return -1;
1015 }
1016
Vijay Kumard086d432006-10-08 22:02:31 +05301017 if (prog_page(ns, num) == -1)
1018 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019
1020 NS_DBG("do_state_action: copy %d bytes from int buf to (%#x, %#x), raw off = %d\n",
1021 num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off);
1022 NS_LOG("programm page %d\n", ns->regs.row);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001023
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 NS_UDELAY(programm_delay);
1025 NS_UDELAY(output_cycle * ns->geom.pgsz / 1000 / busdiv);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001026
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001028
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 case ACTION_ZEROOFF:
1030 NS_DBG("do_state_action: set internal offset to 0\n");
1031 ns->regs.off = 0;
1032 break;
1033
1034 case ACTION_HALFOFF:
1035 if (!(ns->options & OPT_PAGE512_8BIT)) {
1036 NS_ERR("do_state_action: BUG! can't skip half of page for non-512"
1037 "byte page size 8x chips\n");
1038 return -1;
1039 }
1040 NS_DBG("do_state_action: set internal offset to %d\n", ns->geom.pgsz/2);
1041 ns->regs.off = ns->geom.pgsz/2;
1042 break;
1043
1044 case ACTION_OOBOFF:
1045 NS_DBG("do_state_action: set internal offset to %d\n", ns->geom.pgsz);
1046 ns->regs.off = ns->geom.pgsz;
1047 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001048
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 default:
1050 NS_DBG("do_state_action: BUG! unknown action\n");
1051 }
1052
1053 return 0;
1054}
1055
1056/*
1057 * Switch simulator's state.
1058 */
Vijay Kumara5602142006-10-14 21:33:34 +05301059static void switch_state(struct nandsim *ns)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060{
1061 if (ns->op) {
1062 /*
1063 * The current operation have already been identified.
1064 * Just follow the states chain.
1065 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001066
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 ns->stateidx += 1;
1068 ns->state = ns->nxstate;
1069 ns->nxstate = ns->op[ns->stateidx + 1];
1070
1071 NS_DBG("switch_state: operation is known, switch to the next state, "
1072 "state: %s, nxstate: %s\n",
1073 get_state_name(ns->state), get_state_name(ns->nxstate));
1074
1075 /* See, whether we need to do some action */
1076 if ((ns->state & ACTION_MASK) && do_state_action(ns, ns->state) < 0) {
1077 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1078 return;
1079 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001080
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 } else {
1082 /*
1083 * We don't yet know which operation we perform.
1084 * Try to identify it.
1085 */
1086
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001087 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 * The only event causing the switch_state function to
1089 * be called with yet unknown operation is new command.
1090 */
1091 ns->state = get_state_by_command(ns->regs.command);
1092
1093 NS_DBG("switch_state: operation is unknown, try to find it\n");
1094
1095 if (find_operation(ns, 0) != 0)
1096 return;
1097
1098 if ((ns->state & ACTION_MASK) && do_state_action(ns, ns->state) < 0) {
1099 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1100 return;
1101 }
1102 }
1103
1104 /* For 16x devices column means the page offset in words */
1105 if ((ns->nxstate & STATE_ADDR_MASK) && ns->busw == 16) {
1106 NS_DBG("switch_state: double the column number for 16x device\n");
1107 ns->regs.column <<= 1;
1108 }
1109
1110 if (NS_STATE(ns->nxstate) == STATE_READY) {
1111 /*
1112 * The current state is the last. Return to STATE_READY
1113 */
1114
1115 u_char status = NS_STATUS_OK(ns);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001116
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 /* In case of data states, see if all bytes were input/output */
1118 if ((ns->state & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK))
1119 && ns->regs.count != ns->regs.num) {
1120 NS_WARN("switch_state: not all bytes were processed, %d left\n",
1121 ns->regs.num - ns->regs.count);
1122 status = NS_STATUS_FAILED(ns);
1123 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001124
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 NS_DBG("switch_state: operation complete, switch to STATE_READY state\n");
1126
1127 switch_to_ready_state(ns, status);
1128
1129 return;
1130 } else if (ns->nxstate & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK)) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001131 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 * If the next state is data input/output, switch to it now
1133 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001134
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 ns->state = ns->nxstate;
1136 ns->nxstate = ns->op[++ns->stateidx + 1];
1137 ns->regs.num = ns->regs.count = 0;
1138
1139 NS_DBG("switch_state: the next state is data I/O, switch, "
1140 "state: %s, nxstate: %s\n",
1141 get_state_name(ns->state), get_state_name(ns->nxstate));
1142
1143 /*
1144 * Set the internal register to the count of bytes which
1145 * are expected to be input or output
1146 */
1147 switch (NS_STATE(ns->state)) {
1148 case STATE_DATAIN:
1149 case STATE_DATAOUT:
1150 ns->regs.num = ns->geom.pgszoob - ns->regs.off - ns->regs.column;
1151 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001152
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 case STATE_DATAOUT_ID:
1154 ns->regs.num = ns->geom.idbytes;
1155 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001156
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 case STATE_DATAOUT_STATUS:
1158 case STATE_DATAOUT_STATUS_M:
1159 ns->regs.count = ns->regs.num = 0;
1160 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001161
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 default:
1163 NS_ERR("switch_state: BUG! unknown data state\n");
1164 }
1165
1166 } else if (ns->nxstate & STATE_ADDR_MASK) {
1167 /*
1168 * If the next state is address input, set the internal
1169 * register to the number of expected address bytes
1170 */
1171
1172 ns->regs.count = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001173
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 switch (NS_STATE(ns->nxstate)) {
1175 case STATE_ADDR_PAGE:
1176 ns->regs.num = ns->geom.pgaddrbytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001177
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 break;
1179 case STATE_ADDR_SEC:
1180 ns->regs.num = ns->geom.secaddrbytes;
1181 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001182
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 case STATE_ADDR_ZERO:
1184 ns->regs.num = 1;
1185 break;
1186
1187 default:
1188 NS_ERR("switch_state: BUG! unknown address state\n");
1189 }
1190 } else {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001191 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 * Just reset internal counters.
1193 */
1194
1195 ns->regs.num = 0;
1196 ns->regs.count = 0;
1197 }
1198}
1199
Vijay Kumara5602142006-10-14 21:33:34 +05301200static u_char ns_nand_read_byte(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201{
1202 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
1203 u_char outb = 0x00;
1204
1205 /* Sanity and correctness checks */
1206 if (!ns->lines.ce) {
1207 NS_ERR("read_byte: chip is disabled, return %#x\n", (uint)outb);
1208 return outb;
1209 }
1210 if (ns->lines.ale || ns->lines.cle) {
1211 NS_ERR("read_byte: ALE or CLE pin is high, return %#x\n", (uint)outb);
1212 return outb;
1213 }
1214 if (!(ns->state & STATE_DATAOUT_MASK)) {
1215 NS_WARN("read_byte: unexpected data output cycle, state is %s "
1216 "return %#x\n", get_state_name(ns->state), (uint)outb);
1217 return outb;
1218 }
1219
1220 /* Status register may be read as many times as it is wanted */
1221 if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS) {
1222 NS_DBG("read_byte: return %#x status\n", ns->regs.status);
1223 return ns->regs.status;
1224 }
1225
1226 /* Check if there is any data in the internal buffer which may be read */
1227 if (ns->regs.count == ns->regs.num) {
1228 NS_WARN("read_byte: no more data to output, return %#x\n", (uint)outb);
1229 return outb;
1230 }
1231
1232 switch (NS_STATE(ns->state)) {
1233 case STATE_DATAOUT:
1234 if (ns->busw == 8) {
1235 outb = ns->buf.byte[ns->regs.count];
1236 ns->regs.count += 1;
1237 } else {
1238 outb = (u_char)cpu_to_le16(ns->buf.word[ns->regs.count >> 1]);
1239 ns->regs.count += 2;
1240 }
1241 break;
1242 case STATE_DATAOUT_ID:
1243 NS_DBG("read_byte: read ID byte %d, total = %d\n", ns->regs.count, ns->regs.num);
1244 outb = ns->ids[ns->regs.count];
1245 ns->regs.count += 1;
1246 break;
1247 default:
1248 BUG();
1249 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001250
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 if (ns->regs.count == ns->regs.num) {
1252 NS_DBG("read_byte: all bytes were read\n");
1253
1254 /*
1255 * The OPT_AUTOINCR allows to read next conseqitive pages without
1256 * new read operation cycle.
1257 */
1258 if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) {
1259 ns->regs.count = 0;
1260 if (ns->regs.row + 1 < ns->geom.pgnum)
1261 ns->regs.row += 1;
1262 NS_DBG("read_byte: switch to the next page (%#x)\n", ns->regs.row);
1263 do_state_action(ns, ACTION_CPY);
1264 }
1265 else if (NS_STATE(ns->nxstate) == STATE_READY)
1266 switch_state(ns);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001267
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001269
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 return outb;
1271}
1272
Vijay Kumara5602142006-10-14 21:33:34 +05301273static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274{
1275 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001276
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 /* Sanity and correctness checks */
1278 if (!ns->lines.ce) {
1279 NS_ERR("write_byte: chip is disabled, ignore write\n");
1280 return;
1281 }
1282 if (ns->lines.ale && ns->lines.cle) {
1283 NS_ERR("write_byte: ALE and CLE pins are high simultaneously, ignore write\n");
1284 return;
1285 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001286
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 if (ns->lines.cle == 1) {
1288 /*
1289 * The byte written is a command.
1290 */
1291
1292 if (byte == NAND_CMD_RESET) {
1293 NS_LOG("reset chip\n");
1294 switch_to_ready_state(ns, NS_STATUS_OK(ns));
1295 return;
1296 }
1297
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001298 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 * Chip might still be in STATE_DATAOUT
1300 * (if OPT_AUTOINCR feature is supported), STATE_DATAOUT_STATUS or
1301 * STATE_DATAOUT_STATUS_M state. If so, switch state.
1302 */
1303 if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS
1304 || NS_STATE(ns->state) == STATE_DATAOUT_STATUS_M
1305 || ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT))
1306 switch_state(ns);
1307
1308 /* Check if chip is expecting command */
1309 if (NS_STATE(ns->nxstate) != STATE_UNKNOWN && !(ns->nxstate & STATE_CMD_MASK)) {
1310 /*
1311 * We are in situation when something else (not command)
1312 * was expected but command was input. In this case ignore
1313 * previous command(s)/state(s) and accept the last one.
1314 */
1315 NS_WARN("write_byte: command (%#x) wasn't expected, expected state is %s, "
1316 "ignore previous states\n", (uint)byte, get_state_name(ns->nxstate));
1317 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1318 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001319
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 /* Check that the command byte is correct */
1321 if (check_command(byte)) {
1322 NS_ERR("write_byte: unknown command %#x\n", (uint)byte);
1323 return;
1324 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001325
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 NS_DBG("command byte corresponding to %s state accepted\n",
1327 get_state_name(get_state_by_command(byte)));
1328 ns->regs.command = byte;
1329 switch_state(ns);
1330
1331 } else if (ns->lines.ale == 1) {
1332 /*
1333 * The byte written is an address.
1334 */
1335
1336 if (NS_STATE(ns->nxstate) == STATE_UNKNOWN) {
1337
1338 NS_DBG("write_byte: operation isn't known yet, identify it\n");
1339
1340 if (find_operation(ns, 1) < 0)
1341 return;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001342
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 if ((ns->state & ACTION_MASK) && do_state_action(ns, ns->state) < 0) {
1344 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1345 return;
1346 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001347
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 ns->regs.count = 0;
1349 switch (NS_STATE(ns->nxstate)) {
1350 case STATE_ADDR_PAGE:
1351 ns->regs.num = ns->geom.pgaddrbytes;
1352 break;
1353 case STATE_ADDR_SEC:
1354 ns->regs.num = ns->geom.secaddrbytes;
1355 break;
1356 case STATE_ADDR_ZERO:
1357 ns->regs.num = 1;
1358 break;
1359 default:
1360 BUG();
1361 }
1362 }
1363
1364 /* Check that chip is expecting address */
1365 if (!(ns->nxstate & STATE_ADDR_MASK)) {
1366 NS_ERR("write_byte: address (%#x) isn't expected, expected state is %s, "
1367 "switch to STATE_READY\n", (uint)byte, get_state_name(ns->nxstate));
1368 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1369 return;
1370 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001371
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372 /* Check if this is expected byte */
1373 if (ns->regs.count == ns->regs.num) {
1374 NS_ERR("write_byte: no more address bytes expected\n");
1375 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1376 return;
1377 }
1378
1379 accept_addr_byte(ns, byte);
1380
1381 ns->regs.count += 1;
1382
1383 NS_DBG("write_byte: address byte %#x was accepted (%d bytes input, %d expected)\n",
1384 (uint)byte, ns->regs.count, ns->regs.num);
1385
1386 if (ns->regs.count == ns->regs.num) {
1387 NS_DBG("address (%#x, %#x) is accepted\n", ns->regs.row, ns->regs.column);
1388 switch_state(ns);
1389 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001390
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 } else {
1392 /*
1393 * The byte written is an input data.
1394 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001395
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 /* Check that chip is expecting data input */
1397 if (!(ns->state & STATE_DATAIN_MASK)) {
1398 NS_ERR("write_byte: data input (%#x) isn't expected, state is %s, "
1399 "switch to %s\n", (uint)byte,
1400 get_state_name(ns->state), get_state_name(STATE_READY));
1401 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1402 return;
1403 }
1404
1405 /* Check if this is expected byte */
1406 if (ns->regs.count == ns->regs.num) {
1407 NS_WARN("write_byte: %u input bytes has already been accepted, ignore write\n",
1408 ns->regs.num);
1409 return;
1410 }
1411
1412 if (ns->busw == 8) {
1413 ns->buf.byte[ns->regs.count] = byte;
1414 ns->regs.count += 1;
1415 } else {
1416 ns->buf.word[ns->regs.count >> 1] = cpu_to_le16((uint16_t)byte);
1417 ns->regs.count += 2;
1418 }
1419 }
1420
1421 return;
1422}
1423
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +02001424static void ns_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask)
1425{
1426 struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
1427
1428 ns->lines.cle = bitmask & NAND_CLE ? 1 : 0;
1429 ns->lines.ale = bitmask & NAND_ALE ? 1 : 0;
1430 ns->lines.ce = bitmask & NAND_NCE ? 1 : 0;
1431
1432 if (cmd != NAND_CMD_NONE)
1433 ns_nand_write_byte(mtd, cmd);
1434}
1435
Vijay Kumara5602142006-10-14 21:33:34 +05301436static int ns_device_ready(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437{
1438 NS_DBG("device_ready\n");
1439 return 1;
1440}
1441
Vijay Kumara5602142006-10-14 21:33:34 +05301442static uint16_t ns_nand_read_word(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443{
1444 struct nand_chip *chip = (struct nand_chip *)mtd->priv;
1445
1446 NS_DBG("read_word\n");
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001447
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 return chip->read_byte(mtd) | (chip->read_byte(mtd) << 8);
1449}
1450
Vijay Kumara5602142006-10-14 21:33:34 +05301451static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452{
1453 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
1454
1455 /* Check that chip is expecting data input */
1456 if (!(ns->state & STATE_DATAIN_MASK)) {
1457 NS_ERR("write_buf: data input isn't expected, state is %s, "
1458 "switch to STATE_READY\n", get_state_name(ns->state));
1459 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1460 return;
1461 }
1462
1463 /* Check if these are expected bytes */
1464 if (ns->regs.count + len > ns->regs.num) {
1465 NS_ERR("write_buf: too many input bytes\n");
1466 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1467 return;
1468 }
1469
1470 memcpy(ns->buf.byte + ns->regs.count, buf, len);
1471 ns->regs.count += len;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001472
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 if (ns->regs.count == ns->regs.num) {
1474 NS_DBG("write_buf: %d bytes were written\n", ns->regs.count);
1475 }
1476}
1477
Vijay Kumara5602142006-10-14 21:33:34 +05301478static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479{
1480 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
1481
1482 /* Sanity and correctness checks */
1483 if (!ns->lines.ce) {
1484 NS_ERR("read_buf: chip is disabled\n");
1485 return;
1486 }
1487 if (ns->lines.ale || ns->lines.cle) {
1488 NS_ERR("read_buf: ALE or CLE pin is high\n");
1489 return;
1490 }
1491 if (!(ns->state & STATE_DATAOUT_MASK)) {
1492 NS_WARN("read_buf: unexpected data output cycle, current state is %s\n",
1493 get_state_name(ns->state));
1494 return;
1495 }
1496
1497 if (NS_STATE(ns->state) != STATE_DATAOUT) {
1498 int i;
1499
1500 for (i = 0; i < len; i++)
1501 buf[i] = ((struct nand_chip *)mtd->priv)->read_byte(mtd);
1502
1503 return;
1504 }
1505
1506 /* Check if these are expected bytes */
1507 if (ns->regs.count + len > ns->regs.num) {
1508 NS_ERR("read_buf: too many bytes to read\n");
1509 switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
1510 return;
1511 }
1512
1513 memcpy(buf, ns->buf.byte + ns->regs.count, len);
1514 ns->regs.count += len;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001515
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 if (ns->regs.count == ns->regs.num) {
1517 if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) {
1518 ns->regs.count = 0;
1519 if (ns->regs.row + 1 < ns->geom.pgnum)
1520 ns->regs.row += 1;
1521 NS_DBG("read_buf: switch to the next page (%#x)\n", ns->regs.row);
1522 do_state_action(ns, ACTION_CPY);
1523 }
1524 else if (NS_STATE(ns->nxstate) == STATE_READY)
1525 switch_state(ns);
1526 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001527
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 return;
1529}
1530
Vijay Kumara5602142006-10-14 21:33:34 +05301531static int ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532{
1533 ns_nand_read_buf(mtd, (u_char *)&ns_verify_buf[0], len);
1534
1535 if (!memcmp(buf, &ns_verify_buf[0], len)) {
1536 NS_DBG("verify_buf: the buffer is OK\n");
1537 return 0;
1538 } else {
1539 NS_DBG("verify_buf: the buffer is wrong\n");
1540 return -EFAULT;
1541 }
1542}
1543
1544/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 * Module initialization function
1546 */
Adrian Bunk2b9175c2005-11-29 14:49:38 +00001547static int __init ns_init_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548{
1549 struct nand_chip *chip;
1550 struct nandsim *nand;
Adrian Hunter2b77a0e2007-03-19 12:46:43 +02001551 int retval = -ENOMEM, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552
1553 if (bus_width != 8 && bus_width != 16) {
1554 NS_ERR("wrong bus width (%d), use only 8 or 16\n", bus_width);
1555 return -EINVAL;
1556 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001557
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 /* Allocate and initialize mtd_info, nand_chip and nandsim structures */
Burman Yan95b93a02006-11-15 21:10:29 +02001559 nsmtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560 + sizeof(struct nandsim), GFP_KERNEL);
1561 if (!nsmtd) {
1562 NS_ERR("unable to allocate core structures.\n");
1563 return -ENOMEM;
1564 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565 chip = (struct nand_chip *)(nsmtd + 1);
1566 nsmtd->priv = (void *)chip;
1567 nand = (struct nandsim *)(chip + 1);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001568 chip->priv = (void *)nand;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569
1570 /*
1571 * Register simulator's callbacks.
1572 */
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +02001573 chip->cmd_ctrl = ns_hwcontrol;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 chip->read_byte = ns_nand_read_byte;
1575 chip->dev_ready = ns_device_ready;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576 chip->write_buf = ns_nand_write_buf;
1577 chip->read_buf = ns_nand_read_buf;
1578 chip->verify_buf = ns_nand_verify_buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 chip->read_word = ns_nand_read_word;
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001580 chip->ecc.mode = NAND_ECC_SOFT;
Artem B. Bityuckiy51502282005-03-19 15:33:59 +00001581 chip->options |= NAND_SKIP_BBTSCAN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001583 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 * Perform minimum nandsim structure initialization to handle
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001585 * the initial ID read command correctly
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586 */
1587 if (third_id_byte != 0xFF || fourth_id_byte != 0xFF)
1588 nand->geom.idbytes = 4;
1589 else
1590 nand->geom.idbytes = 2;
1591 nand->regs.status = NS_STATUS_OK(nand);
1592 nand->nxstate = STATE_UNKNOWN;
1593 nand->options |= OPT_PAGE256; /* temporary value */
1594 nand->ids[0] = first_id_byte;
1595 nand->ids[1] = second_id_byte;
1596 nand->ids[2] = third_id_byte;
1597 nand->ids[3] = fourth_id_byte;
1598 if (bus_width == 16) {
1599 nand->busw = 16;
1600 chip->options |= NAND_BUSWIDTH_16;
1601 }
1602
David Woodhouse552d9202006-05-14 01:20:46 +01001603 nsmtd->owner = THIS_MODULE;
1604
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 if ((retval = nand_scan(nsmtd, 1)) != 0) {
1606 NS_ERR("can't register NAND Simulator\n");
1607 if (retval > 0)
1608 retval = -ENXIO;
1609 goto error;
1610 }
1611
Adrian Hunter2b77a0e2007-03-19 12:46:43 +02001612 if ((retval = init_nandsim(nsmtd)) != 0)
1613 goto err_exit;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001614
Adrian Hunter2b77a0e2007-03-19 12:46:43 +02001615 if ((retval = nand_default_bbt(nsmtd)) != 0)
1616 goto err_exit;
Artem B. Bityuckiy51502282005-03-19 15:33:59 +00001617
Adrian Hunter2b77a0e2007-03-19 12:46:43 +02001618 /* Register NAND partitions */
1619 if ((retval = add_mtd_partitions(nsmtd, &nand->partitions[0], nand->nbparts)) != 0)
1620 goto err_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621
1622 return 0;
1623
Adrian Hunter2b77a0e2007-03-19 12:46:43 +02001624err_exit:
1625 free_nandsim(nand);
1626 nand_release(nsmtd);
1627 for (i = 0;i < ARRAY_SIZE(nand->partitions); ++i)
1628 kfree(nand->partitions[i].name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629error:
1630 kfree(nsmtd);
1631
1632 return retval;
1633}
1634
1635module_init(ns_init_module);
1636
1637/*
1638 * Module clean-up function
1639 */
1640static void __exit ns_cleanup_module(void)
1641{
1642 struct nandsim *ns = (struct nandsim *)(((struct nand_chip *)nsmtd->priv)->priv);
Adrian Hunter2b77a0e2007-03-19 12:46:43 +02001643 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644
1645 free_nandsim(ns); /* Free nandsim private resources */
Adrian Hunter2b77a0e2007-03-19 12:46:43 +02001646 nand_release(nsmtd); /* Unregister driver */
1647 for (i = 0;i < ARRAY_SIZE(ns->partitions); ++i)
1648 kfree(ns->partitions[i].name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649 kfree(nsmtd); /* Free other structures */
1650}
1651
1652module_exit(ns_cleanup_module);
1653
1654MODULE_LICENSE ("GPL");
1655MODULE_AUTHOR ("Artem B. Bityuckiy");
1656MODULE_DESCRIPTION ("The NAND flash simulator");