diff options
Diffstat (limited to 'drivers/mtd/nand/nandsim.c')
-rw-r--r-- | drivers/mtd/nand/nandsim.c | 1613 |
1 files changed, 1613 insertions, 0 deletions
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c new file mode 100644 index 000000000000..13feefd7d8ca --- /dev/null +++ b/drivers/mtd/nand/nandsim.c | |||
@@ -0,0 +1,1613 @@ | |||
1 | /* | ||
2 | * NAND flash simulator. | ||
3 | * | ||
4 | * Author: Artem B. Bityuckiy <dedekind@oktetlabs.ru>, <dedekind@infradead.org> | ||
5 | * | ||
6 | * Copyright (C) 2004 Nokia Corporation | ||
7 | * | ||
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 | * | ||
25 | * $Id: nandsim.c,v 1.7 2004/12/06 11:53:06 dedekind Exp $ | ||
26 | */ | ||
27 | |||
28 | #include <linux/config.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/types.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/moduleparam.h> | ||
33 | #include <linux/vmalloc.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/errno.h> | ||
36 | #include <linux/string.h> | ||
37 | #include <linux/mtd/mtd.h> | ||
38 | #include <linux/mtd/nand.h> | ||
39 | #include <linux/mtd/partitions.h> | ||
40 | #include <linux/delay.h> | ||
41 | #ifdef CONFIG_NS_ABS_POS | ||
42 | #include <asm/io.h> | ||
43 | #endif | ||
44 | |||
45 | |||
46 | /* Default simulator parameters values */ | ||
47 | #if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \ | ||
48 | !defined(CONFIG_NANDSIM_SECOND_ID_BYTE) || \ | ||
49 | !defined(CONFIG_NANDSIM_THIRD_ID_BYTE) || \ | ||
50 | !defined(CONFIG_NANDSIM_FOURTH_ID_BYTE) | ||
51 | #define CONFIG_NANDSIM_FIRST_ID_BYTE 0x98 | ||
52 | #define CONFIG_NANDSIM_SECOND_ID_BYTE 0x39 | ||
53 | #define CONFIG_NANDSIM_THIRD_ID_BYTE 0xFF /* No byte */ | ||
54 | #define CONFIG_NANDSIM_FOURTH_ID_BYTE 0xFF /* No byte */ | ||
55 | #endif | ||
56 | |||
57 | #ifndef CONFIG_NANDSIM_ACCESS_DELAY | ||
58 | #define CONFIG_NANDSIM_ACCESS_DELAY 25 | ||
59 | #endif | ||
60 | #ifndef CONFIG_NANDSIM_PROGRAMM_DELAY | ||
61 | #define CONFIG_NANDSIM_PROGRAMM_DELAY 200 | ||
62 | #endif | ||
63 | #ifndef CONFIG_NANDSIM_ERASE_DELAY | ||
64 | #define CONFIG_NANDSIM_ERASE_DELAY 2 | ||
65 | #endif | ||
66 | #ifndef CONFIG_NANDSIM_OUTPUT_CYCLE | ||
67 | #define CONFIG_NANDSIM_OUTPUT_CYCLE 40 | ||
68 | #endif | ||
69 | #ifndef CONFIG_NANDSIM_INPUT_CYCLE | ||
70 | #define CONFIG_NANDSIM_INPUT_CYCLE 50 | ||
71 | #endif | ||
72 | #ifndef CONFIG_NANDSIM_BUS_WIDTH | ||
73 | #define CONFIG_NANDSIM_BUS_WIDTH 8 | ||
74 | #endif | ||
75 | #ifndef CONFIG_NANDSIM_DO_DELAYS | ||
76 | #define CONFIG_NANDSIM_DO_DELAYS 0 | ||
77 | #endif | ||
78 | #ifndef CONFIG_NANDSIM_LOG | ||
79 | #define CONFIG_NANDSIM_LOG 0 | ||
80 | #endif | ||
81 | #ifndef CONFIG_NANDSIM_DBG | ||
82 | #define CONFIG_NANDSIM_DBG 0 | ||
83 | #endif | ||
84 | |||
85 | static uint first_id_byte = CONFIG_NANDSIM_FIRST_ID_BYTE; | ||
86 | static uint second_id_byte = CONFIG_NANDSIM_SECOND_ID_BYTE; | ||
87 | static uint third_id_byte = CONFIG_NANDSIM_THIRD_ID_BYTE; | ||
88 | static uint fourth_id_byte = CONFIG_NANDSIM_FOURTH_ID_BYTE; | ||
89 | static uint access_delay = CONFIG_NANDSIM_ACCESS_DELAY; | ||
90 | static uint programm_delay = CONFIG_NANDSIM_PROGRAMM_DELAY; | ||
91 | static uint erase_delay = CONFIG_NANDSIM_ERASE_DELAY; | ||
92 | static uint output_cycle = CONFIG_NANDSIM_OUTPUT_CYCLE; | ||
93 | static uint input_cycle = CONFIG_NANDSIM_INPUT_CYCLE; | ||
94 | static uint bus_width = CONFIG_NANDSIM_BUS_WIDTH; | ||
95 | static uint do_delays = CONFIG_NANDSIM_DO_DELAYS; | ||
96 | static uint log = CONFIG_NANDSIM_LOG; | ||
97 | static uint dbg = CONFIG_NANDSIM_DBG; | ||
98 | |||
99 | module_param(first_id_byte, uint, 0400); | ||
100 | module_param(second_id_byte, uint, 0400); | ||
101 | module_param(third_id_byte, uint, 0400); | ||
102 | module_param(fourth_id_byte, uint, 0400); | ||
103 | module_param(access_delay, uint, 0400); | ||
104 | module_param(programm_delay, uint, 0400); | ||
105 | module_param(erase_delay, uint, 0400); | ||
106 | module_param(output_cycle, uint, 0400); | ||
107 | module_param(input_cycle, uint, 0400); | ||
108 | module_param(bus_width, uint, 0400); | ||
109 | module_param(do_delays, uint, 0400); | ||
110 | module_param(log, uint, 0400); | ||
111 | module_param(dbg, uint, 0400); | ||
112 | |||
113 | MODULE_PARM_DESC(first_id_byte, "The fist byte returned by NAND Flash 'read ID' command (manufaturer ID)"); | ||
114 | MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)"); | ||
115 | MODULE_PARM_DESC(third_id_byte, "The third byte returned by NAND Flash 'read ID' command"); | ||
116 | MODULE_PARM_DESC(fourth_id_byte, "The fourth byte returned by NAND Flash 'read ID' command"); | ||
117 | MODULE_PARM_DESC(access_delay, "Initial page access delay (microiseconds)"); | ||
118 | MODULE_PARM_DESC(programm_delay, "Page programm delay (microseconds"); | ||
119 | MODULE_PARM_DESC(erase_delay, "Sector erase delay (milliseconds)"); | ||
120 | MODULE_PARM_DESC(output_cycle, "Word output (from flash) time (nanodeconds)"); | ||
121 | MODULE_PARM_DESC(input_cycle, "Word input (to flash) time (nanodeconds)"); | ||
122 | MODULE_PARM_DESC(bus_width, "Chip's bus width (8- or 16-bit)"); | ||
123 | MODULE_PARM_DESC(do_delays, "Simulate NAND delays using busy-waits if not zero"); | ||
124 | MODULE_PARM_DESC(log, "Perform logging if not zero"); | ||
125 | MODULE_PARM_DESC(dbg, "Output debug information if not zero"); | ||
126 | |||
127 | /* The largest possible page size */ | ||
128 | #define NS_LARGEST_PAGE_SIZE 2048 | ||
129 | |||
130 | /* 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...) \ | ||
139 | do { printk(KERN_WARNING NS_OUTPUT_PREFIX " warnig: " args); } while(0) | ||
140 | #define NS_ERR(args...) \ | ||
141 | do { printk(KERN_ERR NS_OUTPUT_PREFIX " errorr: " args); } while(0) | ||
142 | |||
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) | ||
148 | |||
149 | /* 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 */ | ||
156 | #define NS_STATUS_FAILED(ns) (NAND_STATUS_FAIL | NS_STATUS_OK(ns)) | ||
157 | |||
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) | ||
161 | |||
162 | /* 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 */ | ||
168 | #define STATE_CMD_READSTART 0x00000003 /* read data second command (large page devices) */ | ||
169 | #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) | ||
226 | |||
227 | /* | ||
228 | * 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 | |||
234 | /* | ||
235 | * The structure which describes all the internal simulator data. | ||
236 | */ | ||
237 | struct nandsim { | ||
238 | struct mtd_partition part; | ||
239 | |||
240 | uint busw; /* flash chip bus width (8 or 16) */ | ||
241 | u_char ids[4]; /* chip's ID bytes */ | ||
242 | uint32_t options; /* chip's characteristic bits */ | ||
243 | uint32_t state; /* current chip state */ | ||
244 | uint32_t nxstate; /* next expected state */ | ||
245 | |||
246 | uint32_t *op; /* current operation, NULL operations isn't known yet */ | ||
247 | uint32_t pstates[NS_MAX_PREVSTATES]; /* previous states */ | ||
248 | uint16_t npstates; /* number of previous states saved */ | ||
249 | uint16_t stateidx; /* current state index */ | ||
250 | |||
251 | /* The simulated NAND flash image */ | ||
252 | union flash_media { | ||
253 | u_char *byte; | ||
254 | uint16_t *word; | ||
255 | } mem; | ||
256 | |||
257 | /* Internal buffer of page + OOB size bytes */ | ||
258 | union internal_buffer { | ||
259 | u_char *byte; /* for byte access */ | ||
260 | uint16_t *word; /* for 16-bit word access */ | ||
261 | } buf; | ||
262 | |||
263 | /* NAND flash "geometry" */ | ||
264 | struct nandsin_geometry { | ||
265 | uint32_t totsz; /* total flash size, bytes */ | ||
266 | uint32_t secsz; /* flash sector (erase block) size, bytes */ | ||
267 | uint pgsz; /* NAND flash page size, bytes */ | ||
268 | uint oobsz; /* page OOB area size, bytes */ | ||
269 | uint32_t totszoob; /* total flash size including OOB, bytes */ | ||
270 | uint pgszoob; /* page size including OOB , bytes*/ | ||
271 | uint secszoob; /* sector size including OOB, bytes */ | ||
272 | uint pgnum; /* total number of pages */ | ||
273 | uint pgsec; /* number of pages per sector */ | ||
274 | uint secshift; /* bits number in sector size */ | ||
275 | uint pgshift; /* bits number in page size */ | ||
276 | uint oobshift; /* bits number in OOB size */ | ||
277 | uint pgaddrbytes; /* bytes per page address */ | ||
278 | uint secaddrbytes; /* bytes per sector address */ | ||
279 | uint idbytes; /* the number ID bytes that this chip outputs */ | ||
280 | } geom; | ||
281 | |||
282 | /* NAND flash internal registers */ | ||
283 | struct nandsim_regs { | ||
284 | unsigned command; /* the command register */ | ||
285 | u_char status; /* the status register */ | ||
286 | uint row; /* the page number */ | ||
287 | uint column; /* the offset within page */ | ||
288 | uint count; /* internal counter */ | ||
289 | uint num; /* number of bytes which must be processed */ | ||
290 | uint off; /* fixed page offset */ | ||
291 | } regs; | ||
292 | |||
293 | /* NAND flash lines state */ | ||
294 | struct ns_lines_status { | ||
295 | int ce; /* chip Enable */ | ||
296 | int cle; /* command Latch Enable */ | ||
297 | int ale; /* address Latch Enable */ | ||
298 | int wp; /* write Protect */ | ||
299 | } lines; | ||
300 | }; | ||
301 | |||
302 | /* | ||
303 | * Operations array. To perform any operation the simulator must pass | ||
304 | * through the correspondent states chain. | ||
305 | */ | ||
306 | static struct nandsim_operations { | ||
307 | uint32_t reqopts; /* options which are required to perform the operation */ | ||
308 | uint32_t states[NS_OPER_STATES]; /* operation's states */ | ||
309 | } ops[NS_OPER_NUM] = { | ||
310 | /* Read page + OOB from the beginning */ | ||
311 | {OPT_SMALLPAGE, {STATE_CMD_READ0 | ACTION_ZEROOFF, STATE_ADDR_PAGE | ACTION_CPY, | ||
312 | STATE_DATAOUT, STATE_READY}}, | ||
313 | /* Read page + OOB from the second half */ | ||
314 | {OPT_PAGE512_8BIT, {STATE_CMD_READ1 | ACTION_HALFOFF, STATE_ADDR_PAGE | ACTION_CPY, | ||
315 | STATE_DATAOUT, STATE_READY}}, | ||
316 | /* Read OOB */ | ||
317 | {OPT_SMALLPAGE, {STATE_CMD_READOOB | ACTION_OOBOFF, STATE_ADDR_PAGE | ACTION_CPY, | ||
318 | STATE_DATAOUT, STATE_READY}}, | ||
319 | /* Programm page starting from the beginning */ | ||
320 | {OPT_ANY, {STATE_CMD_SEQIN, STATE_ADDR_PAGE, STATE_DATAIN, | ||
321 | STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}}, | ||
322 | /* Programm page starting from the beginning */ | ||
323 | {OPT_SMALLPAGE, {STATE_CMD_READ0, STATE_CMD_SEQIN | ACTION_ZEROOFF, STATE_ADDR_PAGE, | ||
324 | STATE_DATAIN, STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}}, | ||
325 | /* Programm page starting from the second half */ | ||
326 | {OPT_PAGE512, {STATE_CMD_READ1, STATE_CMD_SEQIN | ACTION_HALFOFF, STATE_ADDR_PAGE, | ||
327 | STATE_DATAIN, STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}}, | ||
328 | /* Programm OOB */ | ||
329 | {OPT_SMALLPAGE, {STATE_CMD_READOOB, STATE_CMD_SEQIN | ACTION_OOBOFF, STATE_ADDR_PAGE, | ||
330 | STATE_DATAIN, STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}}, | ||
331 | /* Erase sector */ | ||
332 | {OPT_ANY, {STATE_CMD_ERASE1, STATE_ADDR_SEC, STATE_CMD_ERASE2 | ACTION_SECERASE, STATE_READY}}, | ||
333 | /* Read status */ | ||
334 | {OPT_ANY, {STATE_CMD_STATUS, STATE_DATAOUT_STATUS, STATE_READY}}, | ||
335 | /* Read multi-plane status */ | ||
336 | {OPT_SMARTMEDIA, {STATE_CMD_STATUS_M, STATE_DATAOUT_STATUS_M, STATE_READY}}, | ||
337 | /* Read ID */ | ||
338 | {OPT_ANY, {STATE_CMD_READID, STATE_ADDR_ZERO, STATE_DATAOUT_ID, STATE_READY}}, | ||
339 | /* Large page devices read page */ | ||
340 | {OPT_LARGEPAGE, {STATE_CMD_READ0, STATE_ADDR_PAGE, STATE_CMD_READSTART | ACTION_CPY, | ||
341 | STATE_DATAOUT, STATE_READY}} | ||
342 | }; | ||
343 | |||
344 | /* MTD structure for NAND controller */ | ||
345 | static struct mtd_info *nsmtd; | ||
346 | |||
347 | static u_char ns_verify_buf[NS_LARGEST_PAGE_SIZE]; | ||
348 | |||
349 | /* | ||
350 | * Initialize the nandsim structure. | ||
351 | * | ||
352 | * RETURNS: 0 if success, -ERRNO if failure. | ||
353 | */ | ||
354 | static int | ||
355 | init_nandsim(struct mtd_info *mtd) | ||
356 | { | ||
357 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; | ||
358 | struct nandsim *ns = (struct nandsim *)(chip->priv); | ||
359 | int i; | ||
360 | |||
361 | if (NS_IS_INITIALIZED(ns)) { | ||
362 | NS_ERR("init_nandsim: nandsim is already initialized\n"); | ||
363 | return -EIO; | ||
364 | } | ||
365 | |||
366 | /* Force mtd to not do delays */ | ||
367 | chip->chip_delay = 0; | ||
368 | |||
369 | /* Initialize the NAND flash parameters */ | ||
370 | ns->busw = chip->options & NAND_BUSWIDTH_16 ? 16 : 8; | ||
371 | ns->geom.totsz = mtd->size; | ||
372 | ns->geom.pgsz = mtd->oobblock; | ||
373 | ns->geom.oobsz = mtd->oobsize; | ||
374 | ns->geom.secsz = mtd->erasesize; | ||
375 | ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz; | ||
376 | ns->geom.pgnum = ns->geom.totsz / ns->geom.pgsz; | ||
377 | ns->geom.totszoob = ns->geom.totsz + ns->geom.pgnum * ns->geom.oobsz; | ||
378 | ns->geom.secshift = ffs(ns->geom.secsz) - 1; | ||
379 | ns->geom.pgshift = chip->page_shift; | ||
380 | ns->geom.oobshift = ffs(ns->geom.oobsz) - 1; | ||
381 | ns->geom.pgsec = ns->geom.secsz / ns->geom.pgsz; | ||
382 | ns->geom.secszoob = ns->geom.secsz + ns->geom.oobsz * ns->geom.pgsec; | ||
383 | ns->options = 0; | ||
384 | |||
385 | if (ns->geom.pgsz == 256) { | ||
386 | ns->options |= OPT_PAGE256; | ||
387 | } | ||
388 | else if (ns->geom.pgsz == 512) { | ||
389 | ns->options |= (OPT_PAGE512 | OPT_AUTOINCR); | ||
390 | if (ns->busw == 8) | ||
391 | ns->options |= OPT_PAGE512_8BIT; | ||
392 | } else if (ns->geom.pgsz == 2048) { | ||
393 | ns->options |= OPT_PAGE2048; | ||
394 | } else { | ||
395 | NS_ERR("init_nandsim: unknown page size %u\n", ns->geom.pgsz); | ||
396 | return -EIO; | ||
397 | } | ||
398 | |||
399 | if (ns->options & OPT_SMALLPAGE) { | ||
400 | if (ns->geom.totsz < (64 << 20)) { | ||
401 | ns->geom.pgaddrbytes = 3; | ||
402 | ns->geom.secaddrbytes = 2; | ||
403 | } else { | ||
404 | ns->geom.pgaddrbytes = 4; | ||
405 | ns->geom.secaddrbytes = 3; | ||
406 | } | ||
407 | } else { | ||
408 | if (ns->geom.totsz <= (128 << 20)) { | ||
409 | ns->geom.pgaddrbytes = 5; | ||
410 | ns->geom.secaddrbytes = 2; | ||
411 | } else { | ||
412 | ns->geom.pgaddrbytes = 5; | ||
413 | ns->geom.secaddrbytes = 3; | ||
414 | } | ||
415 | } | ||
416 | |||
417 | /* Detect how many ID bytes the NAND chip outputs */ | ||
418 | for (i = 0; nand_flash_ids[i].name != NULL; i++) { | ||
419 | if (second_id_byte != nand_flash_ids[i].id) | ||
420 | continue; | ||
421 | if (!(nand_flash_ids[i].options & NAND_NO_AUTOINCR)) | ||
422 | ns->options |= OPT_AUTOINCR; | ||
423 | } | ||
424 | |||
425 | if (ns->busw == 16) | ||
426 | NS_WARN("16-bit flashes support wasn't tested\n"); | ||
427 | |||
428 | printk("flash size: %u MiB\n", ns->geom.totsz >> 20); | ||
429 | printk("page size: %u bytes\n", ns->geom.pgsz); | ||
430 | printk("OOB area size: %u bytes\n", ns->geom.oobsz); | ||
431 | printk("sector size: %u KiB\n", ns->geom.secsz >> 10); | ||
432 | printk("pages number: %u\n", ns->geom.pgnum); | ||
433 | printk("pages per sector: %u\n", ns->geom.pgsec); | ||
434 | printk("bus width: %u\n", ns->busw); | ||
435 | printk("bits in sector size: %u\n", ns->geom.secshift); | ||
436 | printk("bits in page size: %u\n", ns->geom.pgshift); | ||
437 | printk("bits in OOB size: %u\n", ns->geom.oobshift); | ||
438 | printk("flash size with OOB: %u KiB\n", ns->geom.totszoob >> 10); | ||
439 | printk("page address bytes: %u\n", ns->geom.pgaddrbytes); | ||
440 | printk("sector address bytes: %u\n", ns->geom.secaddrbytes); | ||
441 | printk("options: %#x\n", ns->options); | ||
442 | |||
443 | /* Map / allocate and initialize the flash image */ | ||
444 | #ifdef CONFIG_NS_ABS_POS | ||
445 | ns->mem.byte = ioremap(CONFIG_NS_ABS_POS, ns->geom.totszoob); | ||
446 | if (!ns->mem.byte) { | ||
447 | NS_ERR("init_nandsim: failed to map the NAND flash image at address %p\n", | ||
448 | (void *)CONFIG_NS_ABS_POS); | ||
449 | return -ENOMEM; | ||
450 | } | ||
451 | #else | ||
452 | ns->mem.byte = vmalloc(ns->geom.totszoob); | ||
453 | if (!ns->mem.byte) { | ||
454 | NS_ERR("init_nandsim: unable to allocate %u bytes for flash image\n", | ||
455 | ns->geom.totszoob); | ||
456 | return -ENOMEM; | ||
457 | } | ||
458 | memset(ns->mem.byte, 0xFF, ns->geom.totszoob); | ||
459 | #endif | ||
460 | |||
461 | /* Allocate / initialize the internal buffer */ | ||
462 | ns->buf.byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL); | ||
463 | if (!ns->buf.byte) { | ||
464 | NS_ERR("init_nandsim: unable to allocate %u bytes for the internal buffer\n", | ||
465 | ns->geom.pgszoob); | ||
466 | goto error; | ||
467 | } | ||
468 | memset(ns->buf.byte, 0xFF, ns->geom.pgszoob); | ||
469 | |||
470 | /* Fill the partition_info structure */ | ||
471 | ns->part.name = "NAND simulator partition"; | ||
472 | ns->part.offset = 0; | ||
473 | ns->part.size = ns->geom.totsz; | ||
474 | |||
475 | return 0; | ||
476 | |||
477 | error: | ||
478 | #ifdef CONFIG_NS_ABS_POS | ||
479 | iounmap(ns->mem.byte); | ||
480 | #else | ||
481 | vfree(ns->mem.byte); | ||
482 | #endif | ||
483 | |||
484 | return -ENOMEM; | ||
485 | } | ||
486 | |||
487 | /* | ||
488 | * Free the nandsim structure. | ||
489 | */ | ||
490 | static void | ||
491 | free_nandsim(struct nandsim *ns) | ||
492 | { | ||
493 | kfree(ns->buf.byte); | ||
494 | |||
495 | #ifdef CONFIG_NS_ABS_POS | ||
496 | iounmap(ns->mem.byte); | ||
497 | #else | ||
498 | vfree(ns->mem.byte); | ||
499 | #endif | ||
500 | |||
501 | return; | ||
502 | } | ||
503 | |||
504 | /* | ||
505 | * Returns the string representation of 'state' state. | ||
506 | */ | ||
507 | static char * | ||
508 | get_state_name(uint32_t state) | ||
509 | { | ||
510 | switch (NS_STATE(state)) { | ||
511 | case STATE_CMD_READ0: | ||
512 | return "STATE_CMD_READ0"; | ||
513 | case STATE_CMD_READ1: | ||
514 | return "STATE_CMD_READ1"; | ||
515 | case STATE_CMD_PAGEPROG: | ||
516 | return "STATE_CMD_PAGEPROG"; | ||
517 | case STATE_CMD_READOOB: | ||
518 | return "STATE_CMD_READOOB"; | ||
519 | case STATE_CMD_READSTART: | ||
520 | return "STATE_CMD_READSTART"; | ||
521 | case STATE_CMD_ERASE1: | ||
522 | return "STATE_CMD_ERASE1"; | ||
523 | case STATE_CMD_STATUS: | ||
524 | return "STATE_CMD_STATUS"; | ||
525 | case STATE_CMD_STATUS_M: | ||
526 | return "STATE_CMD_STATUS_M"; | ||
527 | case STATE_CMD_SEQIN: | ||
528 | return "STATE_CMD_SEQIN"; | ||
529 | case STATE_CMD_READID: | ||
530 | return "STATE_CMD_READID"; | ||
531 | case STATE_CMD_ERASE2: | ||
532 | return "STATE_CMD_ERASE2"; | ||
533 | case STATE_CMD_RESET: | ||
534 | return "STATE_CMD_RESET"; | ||
535 | case STATE_ADDR_PAGE: | ||
536 | return "STATE_ADDR_PAGE"; | ||
537 | case STATE_ADDR_SEC: | ||
538 | return "STATE_ADDR_SEC"; | ||
539 | case STATE_ADDR_ZERO: | ||
540 | return "STATE_ADDR_ZERO"; | ||
541 | case STATE_DATAIN: | ||
542 | return "STATE_DATAIN"; | ||
543 | case STATE_DATAOUT: | ||
544 | return "STATE_DATAOUT"; | ||
545 | case STATE_DATAOUT_ID: | ||
546 | return "STATE_DATAOUT_ID"; | ||
547 | case STATE_DATAOUT_STATUS: | ||
548 | return "STATE_DATAOUT_STATUS"; | ||
549 | case STATE_DATAOUT_STATUS_M: | ||
550 | return "STATE_DATAOUT_STATUS_M"; | ||
551 | case STATE_READY: | ||
552 | return "STATE_READY"; | ||
553 | case STATE_UNKNOWN: | ||
554 | return "STATE_UNKNOWN"; | ||
555 | } | ||
556 | |||
557 | NS_ERR("get_state_name: unknown state, BUG\n"); | ||
558 | return NULL; | ||
559 | } | ||
560 | |||
561 | /* | ||
562 | * Check if command is valid. | ||
563 | * | ||
564 | * RETURNS: 1 if wrong command, 0 if right. | ||
565 | */ | ||
566 | static int | ||
567 | check_command(int cmd) | ||
568 | { | ||
569 | switch (cmd) { | ||
570 | |||
571 | case NAND_CMD_READ0: | ||
572 | case NAND_CMD_READSTART: | ||
573 | case NAND_CMD_PAGEPROG: | ||
574 | case NAND_CMD_READOOB: | ||
575 | case NAND_CMD_ERASE1: | ||
576 | case NAND_CMD_STATUS: | ||
577 | case NAND_CMD_SEQIN: | ||
578 | case NAND_CMD_READID: | ||
579 | case NAND_CMD_ERASE2: | ||
580 | case NAND_CMD_RESET: | ||
581 | case NAND_CMD_READ1: | ||
582 | return 0; | ||
583 | |||
584 | case NAND_CMD_STATUS_MULTI: | ||
585 | default: | ||
586 | return 1; | ||
587 | } | ||
588 | } | ||
589 | |||
590 | /* | ||
591 | * Returns state after command is accepted by command number. | ||
592 | */ | ||
593 | static uint32_t | ||
594 | get_state_by_command(unsigned command) | ||
595 | { | ||
596 | switch (command) { | ||
597 | case NAND_CMD_READ0: | ||
598 | return STATE_CMD_READ0; | ||
599 | case NAND_CMD_READ1: | ||
600 | return STATE_CMD_READ1; | ||
601 | case NAND_CMD_PAGEPROG: | ||
602 | return STATE_CMD_PAGEPROG; | ||
603 | case NAND_CMD_READSTART: | ||
604 | return STATE_CMD_READSTART; | ||
605 | case NAND_CMD_READOOB: | ||
606 | return STATE_CMD_READOOB; | ||
607 | case NAND_CMD_ERASE1: | ||
608 | return STATE_CMD_ERASE1; | ||
609 | case NAND_CMD_STATUS: | ||
610 | return STATE_CMD_STATUS; | ||
611 | case NAND_CMD_STATUS_MULTI: | ||
612 | return STATE_CMD_STATUS_M; | ||
613 | case NAND_CMD_SEQIN: | ||
614 | return STATE_CMD_SEQIN; | ||
615 | case NAND_CMD_READID: | ||
616 | return STATE_CMD_READID; | ||
617 | case NAND_CMD_ERASE2: | ||
618 | return STATE_CMD_ERASE2; | ||
619 | case NAND_CMD_RESET: | ||
620 | return STATE_CMD_RESET; | ||
621 | } | ||
622 | |||
623 | NS_ERR("get_state_by_command: unknown command, BUG\n"); | ||
624 | return 0; | ||
625 | } | ||
626 | |||
627 | /* | ||
628 | * Move an address byte to the correspondent internal register. | ||
629 | */ | ||
630 | static inline void | ||
631 | accept_addr_byte(struct nandsim *ns, u_char bt) | ||
632 | { | ||
633 | uint byte = (uint)bt; | ||
634 | |||
635 | if (ns->regs.count < (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) | ||
636 | ns->regs.column |= (byte << 8 * ns->regs.count); | ||
637 | else { | ||
638 | ns->regs.row |= (byte << 8 * (ns->regs.count - | ||
639 | ns->geom.pgaddrbytes + | ||
640 | ns->geom.secaddrbytes)); | ||
641 | } | ||
642 | |||
643 | return; | ||
644 | } | ||
645 | |||
646 | /* | ||
647 | * Switch to STATE_READY state. | ||
648 | */ | ||
649 | static inline void | ||
650 | switch_to_ready_state(struct nandsim *ns, u_char status) | ||
651 | { | ||
652 | NS_DBG("switch_to_ready_state: switch to %s state\n", get_state_name(STATE_READY)); | ||
653 | |||
654 | ns->state = STATE_READY; | ||
655 | ns->nxstate = STATE_UNKNOWN; | ||
656 | ns->op = NULL; | ||
657 | ns->npstates = 0; | ||
658 | ns->stateidx = 0; | ||
659 | ns->regs.num = 0; | ||
660 | ns->regs.count = 0; | ||
661 | ns->regs.off = 0; | ||
662 | ns->regs.row = 0; | ||
663 | ns->regs.column = 0; | ||
664 | ns->regs.status = status; | ||
665 | } | ||
666 | |||
667 | /* | ||
668 | * If the operation isn't known yet, try to find it in the global array | ||
669 | * of supported operations. | ||
670 | * | ||
671 | * Operation can be unknown because of the following. | ||
672 | * 1. New command was accepted and this is the firs call to find the | ||
673 | * correspondent states chain. In this case ns->npstates = 0; | ||
674 | * 2. There is several operations which begin with the same command(s) | ||
675 | * (for example program from the second half and read from the | ||
676 | * second half operations both begin with the READ1 command). In this | ||
677 | * case the ns->pstates[] array contains previous states. | ||
678 | * | ||
679 | * Thus, the function tries to find operation containing the following | ||
680 | * states (if the 'flag' parameter is 0): | ||
681 | * ns->pstates[0], ... ns->pstates[ns->npstates], ns->state | ||
682 | * | ||
683 | * If (one and only one) matching operation is found, it is accepted ( | ||
684 | * ns->ops, ns->state, ns->nxstate are initialized, ns->npstate is | ||
685 | * zeroed). | ||
686 | * | ||
687 | * If there are several maches, the current state is pushed to the | ||
688 | * ns->pstates. | ||
689 | * | ||
690 | * The operation can be unknown only while commands are input to the chip. | ||
691 | * As soon as address command is accepted, the operation must be known. | ||
692 | * In such situation the function is called with 'flag' != 0, and the | ||
693 | * operation is searched using the following pattern: | ||
694 | * ns->pstates[0], ... ns->pstates[ns->npstates], <address input> | ||
695 | * | ||
696 | * It is supposed that this pattern must either match one operation on | ||
697 | * none. There can't be ambiguity in that case. | ||
698 | * | ||
699 | * If no matches found, the functions does the following: | ||
700 | * 1. if there are saved states present, try to ignore them and search | ||
701 | * again only using the last command. If nothing was found, switch | ||
702 | * to the STATE_READY state. | ||
703 | * 2. if there are no saved states, switch to the STATE_READY state. | ||
704 | * | ||
705 | * RETURNS: -2 - no matched operations found. | ||
706 | * -1 - several matches. | ||
707 | * 0 - operation is found. | ||
708 | */ | ||
709 | static int | ||
710 | find_operation(struct nandsim *ns, uint32_t flag) | ||
711 | { | ||
712 | int opsfound = 0; | ||
713 | int i, j, idx = 0; | ||
714 | |||
715 | for (i = 0; i < NS_OPER_NUM; i++) { | ||
716 | |||
717 | int found = 1; | ||
718 | |||
719 | if (!(ns->options & ops[i].reqopts)) | ||
720 | /* Ignore operations we can't perform */ | ||
721 | continue; | ||
722 | |||
723 | if (flag) { | ||
724 | if (!(ops[i].states[ns->npstates] & STATE_ADDR_MASK)) | ||
725 | continue; | ||
726 | } else { | ||
727 | if (NS_STATE(ns->state) != NS_STATE(ops[i].states[ns->npstates])) | ||
728 | continue; | ||
729 | } | ||
730 | |||
731 | for (j = 0; j < ns->npstates; j++) | ||
732 | if (NS_STATE(ops[i].states[j]) != NS_STATE(ns->pstates[j]) | ||
733 | && (ns->options & ops[idx].reqopts)) { | ||
734 | found = 0; | ||
735 | break; | ||
736 | } | ||
737 | |||
738 | if (found) { | ||
739 | idx = i; | ||
740 | opsfound += 1; | ||
741 | } | ||
742 | } | ||
743 | |||
744 | if (opsfound == 1) { | ||
745 | /* Exact match */ | ||
746 | ns->op = &ops[idx].states[0]; | ||
747 | if (flag) { | ||
748 | /* | ||
749 | * In this case the find_operation function was | ||
750 | * called when address has just began input. But it isn't | ||
751 | * yet fully input and the current state must | ||
752 | * not be one of STATE_ADDR_*, but the STATE_ADDR_* | ||
753 | * state must be the next state (ns->nxstate). | ||
754 | */ | ||
755 | ns->stateidx = ns->npstates - 1; | ||
756 | } else { | ||
757 | ns->stateidx = ns->npstates; | ||
758 | } | ||
759 | ns->npstates = 0; | ||
760 | ns->state = ns->op[ns->stateidx]; | ||
761 | ns->nxstate = ns->op[ns->stateidx + 1]; | ||
762 | NS_DBG("find_operation: operation found, index: %d, state: %s, nxstate %s\n", | ||
763 | idx, get_state_name(ns->state), get_state_name(ns->nxstate)); | ||
764 | return 0; | ||
765 | } | ||
766 | |||
767 | if (opsfound == 0) { | ||
768 | /* Nothing was found. Try to ignore previous commands (if any) and search again */ | ||
769 | if (ns->npstates != 0) { | ||
770 | NS_DBG("find_operation: no operation found, try again with state %s\n", | ||
771 | get_state_name(ns->state)); | ||
772 | ns->npstates = 0; | ||
773 | return find_operation(ns, 0); | ||
774 | |||
775 | } | ||
776 | NS_DBG("find_operation: no operations found\n"); | ||
777 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
778 | return -2; | ||
779 | } | ||
780 | |||
781 | if (flag) { | ||
782 | /* This shouldn't happen */ | ||
783 | NS_DBG("find_operation: BUG, operation must be known if address is input\n"); | ||
784 | return -2; | ||
785 | } | ||
786 | |||
787 | NS_DBG("find_operation: there is still ambiguity\n"); | ||
788 | |||
789 | ns->pstates[ns->npstates++] = ns->state; | ||
790 | |||
791 | return -1; | ||
792 | } | ||
793 | |||
794 | /* | ||
795 | * If state has any action bit, perform this action. | ||
796 | * | ||
797 | * RETURNS: 0 if success, -1 if error. | ||
798 | */ | ||
799 | static int | ||
800 | do_state_action(struct nandsim *ns, uint32_t action) | ||
801 | { | ||
802 | int i, num; | ||
803 | int busdiv = ns->busw == 8 ? 1 : 2; | ||
804 | |||
805 | action &= ACTION_MASK; | ||
806 | |||
807 | /* Check that page address input is correct */ | ||
808 | if (action != ACTION_SECERASE && ns->regs.row >= ns->geom.pgnum) { | ||
809 | NS_WARN("do_state_action: wrong page number (%#x)\n", ns->regs.row); | ||
810 | return -1; | ||
811 | } | ||
812 | |||
813 | switch (action) { | ||
814 | |||
815 | case ACTION_CPY: | ||
816 | /* | ||
817 | * Copy page data to the internal buffer. | ||
818 | */ | ||
819 | |||
820 | /* Column shouldn't be very large */ | ||
821 | if (ns->regs.column >= (ns->geom.pgszoob - ns->regs.off)) { | ||
822 | NS_ERR("do_state_action: column number is too large\n"); | ||
823 | break; | ||
824 | } | ||
825 | num = ns->geom.pgszoob - ns->regs.off - ns->regs.column; | ||
826 | memcpy(ns->buf.byte, ns->mem.byte + NS_RAW_OFFSET(ns) + ns->regs.off, num); | ||
827 | |||
828 | NS_DBG("do_state_action: (ACTION_CPY:) copy %d bytes to int buf, raw offset %d\n", | ||
829 | num, NS_RAW_OFFSET(ns) + ns->regs.off); | ||
830 | |||
831 | if (ns->regs.off == 0) | ||
832 | NS_LOG("read page %d\n", ns->regs.row); | ||
833 | else if (ns->regs.off < ns->geom.pgsz) | ||
834 | NS_LOG("read page %d (second half)\n", ns->regs.row); | ||
835 | else | ||
836 | NS_LOG("read OOB of page %d\n", ns->regs.row); | ||
837 | |||
838 | NS_UDELAY(access_delay); | ||
839 | NS_UDELAY(input_cycle * ns->geom.pgsz / 1000 / busdiv); | ||
840 | |||
841 | break; | ||
842 | |||
843 | case ACTION_SECERASE: | ||
844 | /* | ||
845 | * Erase sector. | ||
846 | */ | ||
847 | |||
848 | if (ns->lines.wp) { | ||
849 | NS_ERR("do_state_action: device is write-protected, ignore sector erase\n"); | ||
850 | return -1; | ||
851 | } | ||
852 | |||
853 | if (ns->regs.row >= ns->geom.pgnum - ns->geom.pgsec | ||
854 | || (ns->regs.row & ~(ns->geom.secsz - 1))) { | ||
855 | NS_ERR("do_state_action: wrong sector address (%#x)\n", ns->regs.row); | ||
856 | return -1; | ||
857 | } | ||
858 | |||
859 | ns->regs.row = (ns->regs.row << | ||
860 | 8 * (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) | ns->regs.column; | ||
861 | ns->regs.column = 0; | ||
862 | |||
863 | NS_DBG("do_state_action: erase sector at address %#x, off = %d\n", | ||
864 | ns->regs.row, NS_RAW_OFFSET(ns)); | ||
865 | NS_LOG("erase sector %d\n", ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift)); | ||
866 | |||
867 | memset(ns->mem.byte + NS_RAW_OFFSET(ns), 0xFF, ns->geom.secszoob); | ||
868 | |||
869 | NS_MDELAY(erase_delay); | ||
870 | |||
871 | break; | ||
872 | |||
873 | case ACTION_PRGPAGE: | ||
874 | /* | ||
875 | * Programm page - move internal buffer data to the page. | ||
876 | */ | ||
877 | |||
878 | if (ns->lines.wp) { | ||
879 | NS_WARN("do_state_action: device is write-protected, programm\n"); | ||
880 | return -1; | ||
881 | } | ||
882 | |||
883 | num = ns->geom.pgszoob - ns->regs.off - ns->regs.column; | ||
884 | if (num != ns->regs.count) { | ||
885 | NS_ERR("do_state_action: too few bytes were input (%d instead of %d)\n", | ||
886 | ns->regs.count, num); | ||
887 | return -1; | ||
888 | } | ||
889 | |||
890 | for (i = 0; i < num; i++) | ||
891 | ns->mem.byte[NS_RAW_OFFSET(ns) + ns->regs.off + i] &= ns->buf.byte[i]; | ||
892 | |||
893 | NS_DBG("do_state_action: copy %d bytes from int buf to (%#x, %#x), raw off = %d\n", | ||
894 | num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off); | ||
895 | NS_LOG("programm page %d\n", ns->regs.row); | ||
896 | |||
897 | NS_UDELAY(programm_delay); | ||
898 | NS_UDELAY(output_cycle * ns->geom.pgsz / 1000 / busdiv); | ||
899 | |||
900 | break; | ||
901 | |||
902 | case ACTION_ZEROOFF: | ||
903 | NS_DBG("do_state_action: set internal offset to 0\n"); | ||
904 | ns->regs.off = 0; | ||
905 | break; | ||
906 | |||
907 | case ACTION_HALFOFF: | ||
908 | if (!(ns->options & OPT_PAGE512_8BIT)) { | ||
909 | NS_ERR("do_state_action: BUG! can't skip half of page for non-512" | ||
910 | "byte page size 8x chips\n"); | ||
911 | return -1; | ||
912 | } | ||
913 | NS_DBG("do_state_action: set internal offset to %d\n", ns->geom.pgsz/2); | ||
914 | ns->regs.off = ns->geom.pgsz/2; | ||
915 | break; | ||
916 | |||
917 | case ACTION_OOBOFF: | ||
918 | NS_DBG("do_state_action: set internal offset to %d\n", ns->geom.pgsz); | ||
919 | ns->regs.off = ns->geom.pgsz; | ||
920 | break; | ||
921 | |||
922 | default: | ||
923 | NS_DBG("do_state_action: BUG! unknown action\n"); | ||
924 | } | ||
925 | |||
926 | return 0; | ||
927 | } | ||
928 | |||
929 | /* | ||
930 | * Switch simulator's state. | ||
931 | */ | ||
932 | static void | ||
933 | switch_state(struct nandsim *ns) | ||
934 | { | ||
935 | if (ns->op) { | ||
936 | /* | ||
937 | * The current operation have already been identified. | ||
938 | * Just follow the states chain. | ||
939 | */ | ||
940 | |||
941 | ns->stateidx += 1; | ||
942 | ns->state = ns->nxstate; | ||
943 | ns->nxstate = ns->op[ns->stateidx + 1]; | ||
944 | |||
945 | NS_DBG("switch_state: operation is known, switch to the next state, " | ||
946 | "state: %s, nxstate: %s\n", | ||
947 | get_state_name(ns->state), get_state_name(ns->nxstate)); | ||
948 | |||
949 | /* See, whether we need to do some action */ | ||
950 | if ((ns->state & ACTION_MASK) && do_state_action(ns, ns->state) < 0) { | ||
951 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
952 | return; | ||
953 | } | ||
954 | |||
955 | } else { | ||
956 | /* | ||
957 | * We don't yet know which operation we perform. | ||
958 | * Try to identify it. | ||
959 | */ | ||
960 | |||
961 | /* | ||
962 | * The only event causing the switch_state function to | ||
963 | * be called with yet unknown operation is new command. | ||
964 | */ | ||
965 | ns->state = get_state_by_command(ns->regs.command); | ||
966 | |||
967 | NS_DBG("switch_state: operation is unknown, try to find it\n"); | ||
968 | |||
969 | if (find_operation(ns, 0) != 0) | ||
970 | return; | ||
971 | |||
972 | if ((ns->state & ACTION_MASK) && do_state_action(ns, ns->state) < 0) { | ||
973 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
974 | return; | ||
975 | } | ||
976 | } | ||
977 | |||
978 | /* For 16x devices column means the page offset in words */ | ||
979 | if ((ns->nxstate & STATE_ADDR_MASK) && ns->busw == 16) { | ||
980 | NS_DBG("switch_state: double the column number for 16x device\n"); | ||
981 | ns->regs.column <<= 1; | ||
982 | } | ||
983 | |||
984 | if (NS_STATE(ns->nxstate) == STATE_READY) { | ||
985 | /* | ||
986 | * The current state is the last. Return to STATE_READY | ||
987 | */ | ||
988 | |||
989 | u_char status = NS_STATUS_OK(ns); | ||
990 | |||
991 | /* In case of data states, see if all bytes were input/output */ | ||
992 | if ((ns->state & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK)) | ||
993 | && ns->regs.count != ns->regs.num) { | ||
994 | NS_WARN("switch_state: not all bytes were processed, %d left\n", | ||
995 | ns->regs.num - ns->regs.count); | ||
996 | status = NS_STATUS_FAILED(ns); | ||
997 | } | ||
998 | |||
999 | NS_DBG("switch_state: operation complete, switch to STATE_READY state\n"); | ||
1000 | |||
1001 | switch_to_ready_state(ns, status); | ||
1002 | |||
1003 | return; | ||
1004 | } else if (ns->nxstate & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK)) { | ||
1005 | /* | ||
1006 | * If the next state is data input/output, switch to it now | ||
1007 | */ | ||
1008 | |||
1009 | ns->state = ns->nxstate; | ||
1010 | ns->nxstate = ns->op[++ns->stateidx + 1]; | ||
1011 | ns->regs.num = ns->regs.count = 0; | ||
1012 | |||
1013 | NS_DBG("switch_state: the next state is data I/O, switch, " | ||
1014 | "state: %s, nxstate: %s\n", | ||
1015 | get_state_name(ns->state), get_state_name(ns->nxstate)); | ||
1016 | |||
1017 | /* | ||
1018 | * Set the internal register to the count of bytes which | ||
1019 | * are expected to be input or output | ||
1020 | */ | ||
1021 | switch (NS_STATE(ns->state)) { | ||
1022 | case STATE_DATAIN: | ||
1023 | case STATE_DATAOUT: | ||
1024 | ns->regs.num = ns->geom.pgszoob - ns->regs.off - ns->regs.column; | ||
1025 | break; | ||
1026 | |||
1027 | case STATE_DATAOUT_ID: | ||
1028 | ns->regs.num = ns->geom.idbytes; | ||
1029 | break; | ||
1030 | |||
1031 | case STATE_DATAOUT_STATUS: | ||
1032 | case STATE_DATAOUT_STATUS_M: | ||
1033 | ns->regs.count = ns->regs.num = 0; | ||
1034 | break; | ||
1035 | |||
1036 | default: | ||
1037 | NS_ERR("switch_state: BUG! unknown data state\n"); | ||
1038 | } | ||
1039 | |||
1040 | } else if (ns->nxstate & STATE_ADDR_MASK) { | ||
1041 | /* | ||
1042 | * If the next state is address input, set the internal | ||
1043 | * register to the number of expected address bytes | ||
1044 | */ | ||
1045 | |||
1046 | ns->regs.count = 0; | ||
1047 | |||
1048 | switch (NS_STATE(ns->nxstate)) { | ||
1049 | case STATE_ADDR_PAGE: | ||
1050 | ns->regs.num = ns->geom.pgaddrbytes; | ||
1051 | |||
1052 | break; | ||
1053 | case STATE_ADDR_SEC: | ||
1054 | ns->regs.num = ns->geom.secaddrbytes; | ||
1055 | break; | ||
1056 | |||
1057 | case STATE_ADDR_ZERO: | ||
1058 | ns->regs.num = 1; | ||
1059 | break; | ||
1060 | |||
1061 | default: | ||
1062 | NS_ERR("switch_state: BUG! unknown address state\n"); | ||
1063 | } | ||
1064 | } else { | ||
1065 | /* | ||
1066 | * Just reset internal counters. | ||
1067 | */ | ||
1068 | |||
1069 | ns->regs.num = 0; | ||
1070 | ns->regs.count = 0; | ||
1071 | } | ||
1072 | } | ||
1073 | |||
1074 | static void | ||
1075 | ns_hwcontrol(struct mtd_info *mtd, int cmd) | ||
1076 | { | ||
1077 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | ||
1078 | |||
1079 | switch (cmd) { | ||
1080 | |||
1081 | /* set CLE line high */ | ||
1082 | case NAND_CTL_SETCLE: | ||
1083 | NS_DBG("ns_hwcontrol: start command latch cycles\n"); | ||
1084 | ns->lines.cle = 1; | ||
1085 | break; | ||
1086 | |||
1087 | /* set CLE line low */ | ||
1088 | case NAND_CTL_CLRCLE: | ||
1089 | NS_DBG("ns_hwcontrol: stop command latch cycles\n"); | ||
1090 | ns->lines.cle = 0; | ||
1091 | break; | ||
1092 | |||
1093 | /* set ALE line high */ | ||
1094 | case NAND_CTL_SETALE: | ||
1095 | NS_DBG("ns_hwcontrol: start address latch cycles\n"); | ||
1096 | ns->lines.ale = 1; | ||
1097 | break; | ||
1098 | |||
1099 | /* set ALE line low */ | ||
1100 | case NAND_CTL_CLRALE: | ||
1101 | NS_DBG("ns_hwcontrol: stop address latch cycles\n"); | ||
1102 | ns->lines.ale = 0; | ||
1103 | break; | ||
1104 | |||
1105 | /* set WP line high */ | ||
1106 | case NAND_CTL_SETWP: | ||
1107 | NS_DBG("ns_hwcontrol: enable write protection\n"); | ||
1108 | ns->lines.wp = 1; | ||
1109 | break; | ||
1110 | |||
1111 | /* set WP line low */ | ||
1112 | case NAND_CTL_CLRWP: | ||
1113 | NS_DBG("ns_hwcontrol: disable write protection\n"); | ||
1114 | ns->lines.wp = 0; | ||
1115 | break; | ||
1116 | |||
1117 | /* set CE line low */ | ||
1118 | case NAND_CTL_SETNCE: | ||
1119 | NS_DBG("ns_hwcontrol: enable chip\n"); | ||
1120 | ns->lines.ce = 1; | ||
1121 | break; | ||
1122 | |||
1123 | /* set CE line high */ | ||
1124 | case NAND_CTL_CLRNCE: | ||
1125 | NS_DBG("ns_hwcontrol: disable chip\n"); | ||
1126 | ns->lines.ce = 0; | ||
1127 | break; | ||
1128 | |||
1129 | default: | ||
1130 | NS_ERR("hwcontrol: unknown command\n"); | ||
1131 | } | ||
1132 | |||
1133 | return; | ||
1134 | } | ||
1135 | |||
1136 | static u_char | ||
1137 | ns_nand_read_byte(struct mtd_info *mtd) | ||
1138 | { | ||
1139 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | ||
1140 | u_char outb = 0x00; | ||
1141 | |||
1142 | /* Sanity and correctness checks */ | ||
1143 | if (!ns->lines.ce) { | ||
1144 | NS_ERR("read_byte: chip is disabled, return %#x\n", (uint)outb); | ||
1145 | return outb; | ||
1146 | } | ||
1147 | if (ns->lines.ale || ns->lines.cle) { | ||
1148 | NS_ERR("read_byte: ALE or CLE pin is high, return %#x\n", (uint)outb); | ||
1149 | return outb; | ||
1150 | } | ||
1151 | if (!(ns->state & STATE_DATAOUT_MASK)) { | ||
1152 | NS_WARN("read_byte: unexpected data output cycle, state is %s " | ||
1153 | "return %#x\n", get_state_name(ns->state), (uint)outb); | ||
1154 | return outb; | ||
1155 | } | ||
1156 | |||
1157 | /* Status register may be read as many times as it is wanted */ | ||
1158 | if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS) { | ||
1159 | NS_DBG("read_byte: return %#x status\n", ns->regs.status); | ||
1160 | return ns->regs.status; | ||
1161 | } | ||
1162 | |||
1163 | /* Check if there is any data in the internal buffer which may be read */ | ||
1164 | if (ns->regs.count == ns->regs.num) { | ||
1165 | NS_WARN("read_byte: no more data to output, return %#x\n", (uint)outb); | ||
1166 | return outb; | ||
1167 | } | ||
1168 | |||
1169 | switch (NS_STATE(ns->state)) { | ||
1170 | case STATE_DATAOUT: | ||
1171 | if (ns->busw == 8) { | ||
1172 | outb = ns->buf.byte[ns->regs.count]; | ||
1173 | ns->regs.count += 1; | ||
1174 | } else { | ||
1175 | outb = (u_char)cpu_to_le16(ns->buf.word[ns->regs.count >> 1]); | ||
1176 | ns->regs.count += 2; | ||
1177 | } | ||
1178 | break; | ||
1179 | case STATE_DATAOUT_ID: | ||
1180 | NS_DBG("read_byte: read ID byte %d, total = %d\n", ns->regs.count, ns->regs.num); | ||
1181 | outb = ns->ids[ns->regs.count]; | ||
1182 | ns->regs.count += 1; | ||
1183 | break; | ||
1184 | default: | ||
1185 | BUG(); | ||
1186 | } | ||
1187 | |||
1188 | if (ns->regs.count == ns->regs.num) { | ||
1189 | NS_DBG("read_byte: all bytes were read\n"); | ||
1190 | |||
1191 | /* | ||
1192 | * The OPT_AUTOINCR allows to read next conseqitive pages without | ||
1193 | * new read operation cycle. | ||
1194 | */ | ||
1195 | if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) { | ||
1196 | ns->regs.count = 0; | ||
1197 | if (ns->regs.row + 1 < ns->geom.pgnum) | ||
1198 | ns->regs.row += 1; | ||
1199 | NS_DBG("read_byte: switch to the next page (%#x)\n", ns->regs.row); | ||
1200 | do_state_action(ns, ACTION_CPY); | ||
1201 | } | ||
1202 | else if (NS_STATE(ns->nxstate) == STATE_READY) | ||
1203 | switch_state(ns); | ||
1204 | |||
1205 | } | ||
1206 | |||
1207 | return outb; | ||
1208 | } | ||
1209 | |||
1210 | static void | ||
1211 | ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | ||
1212 | { | ||
1213 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | ||
1214 | |||
1215 | /* Sanity and correctness checks */ | ||
1216 | if (!ns->lines.ce) { | ||
1217 | NS_ERR("write_byte: chip is disabled, ignore write\n"); | ||
1218 | return; | ||
1219 | } | ||
1220 | if (ns->lines.ale && ns->lines.cle) { | ||
1221 | NS_ERR("write_byte: ALE and CLE pins are high simultaneously, ignore write\n"); | ||
1222 | return; | ||
1223 | } | ||
1224 | |||
1225 | if (ns->lines.cle == 1) { | ||
1226 | /* | ||
1227 | * The byte written is a command. | ||
1228 | */ | ||
1229 | |||
1230 | if (byte == NAND_CMD_RESET) { | ||
1231 | NS_LOG("reset chip\n"); | ||
1232 | switch_to_ready_state(ns, NS_STATUS_OK(ns)); | ||
1233 | return; | ||
1234 | } | ||
1235 | |||
1236 | /* | ||
1237 | * Chip might still be in STATE_DATAOUT | ||
1238 | * (if OPT_AUTOINCR feature is supported), STATE_DATAOUT_STATUS or | ||
1239 | * STATE_DATAOUT_STATUS_M state. If so, switch state. | ||
1240 | */ | ||
1241 | if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS | ||
1242 | || NS_STATE(ns->state) == STATE_DATAOUT_STATUS_M | ||
1243 | || ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT)) | ||
1244 | switch_state(ns); | ||
1245 | |||
1246 | /* Check if chip is expecting command */ | ||
1247 | if (NS_STATE(ns->nxstate) != STATE_UNKNOWN && !(ns->nxstate & STATE_CMD_MASK)) { | ||
1248 | /* | ||
1249 | * We are in situation when something else (not command) | ||
1250 | * was expected but command was input. In this case ignore | ||
1251 | * previous command(s)/state(s) and accept the last one. | ||
1252 | */ | ||
1253 | NS_WARN("write_byte: command (%#x) wasn't expected, expected state is %s, " | ||
1254 | "ignore previous states\n", (uint)byte, get_state_name(ns->nxstate)); | ||
1255 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
1256 | } | ||
1257 | |||
1258 | /* Check that the command byte is correct */ | ||
1259 | if (check_command(byte)) { | ||
1260 | NS_ERR("write_byte: unknown command %#x\n", (uint)byte); | ||
1261 | return; | ||
1262 | } | ||
1263 | |||
1264 | NS_DBG("command byte corresponding to %s state accepted\n", | ||
1265 | get_state_name(get_state_by_command(byte))); | ||
1266 | ns->regs.command = byte; | ||
1267 | switch_state(ns); | ||
1268 | |||
1269 | } else if (ns->lines.ale == 1) { | ||
1270 | /* | ||
1271 | * The byte written is an address. | ||
1272 | */ | ||
1273 | |||
1274 | if (NS_STATE(ns->nxstate) == STATE_UNKNOWN) { | ||
1275 | |||
1276 | NS_DBG("write_byte: operation isn't known yet, identify it\n"); | ||
1277 | |||
1278 | if (find_operation(ns, 1) < 0) | ||
1279 | return; | ||
1280 | |||
1281 | if ((ns->state & ACTION_MASK) && do_state_action(ns, ns->state) < 0) { | ||
1282 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
1283 | return; | ||
1284 | } | ||
1285 | |||
1286 | ns->regs.count = 0; | ||
1287 | switch (NS_STATE(ns->nxstate)) { | ||
1288 | case STATE_ADDR_PAGE: | ||
1289 | ns->regs.num = ns->geom.pgaddrbytes; | ||
1290 | break; | ||
1291 | case STATE_ADDR_SEC: | ||
1292 | ns->regs.num = ns->geom.secaddrbytes; | ||
1293 | break; | ||
1294 | case STATE_ADDR_ZERO: | ||
1295 | ns->regs.num = 1; | ||
1296 | break; | ||
1297 | default: | ||
1298 | BUG(); | ||
1299 | } | ||
1300 | } | ||
1301 | |||
1302 | /* Check that chip is expecting address */ | ||
1303 | if (!(ns->nxstate & STATE_ADDR_MASK)) { | ||
1304 | NS_ERR("write_byte: address (%#x) isn't expected, expected state is %s, " | ||
1305 | "switch to STATE_READY\n", (uint)byte, get_state_name(ns->nxstate)); | ||
1306 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
1307 | return; | ||
1308 | } | ||
1309 | |||
1310 | /* Check if this is expected byte */ | ||
1311 | if (ns->regs.count == ns->regs.num) { | ||
1312 | NS_ERR("write_byte: no more address bytes expected\n"); | ||
1313 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
1314 | return; | ||
1315 | } | ||
1316 | |||
1317 | accept_addr_byte(ns, byte); | ||
1318 | |||
1319 | ns->regs.count += 1; | ||
1320 | |||
1321 | NS_DBG("write_byte: address byte %#x was accepted (%d bytes input, %d expected)\n", | ||
1322 | (uint)byte, ns->regs.count, ns->regs.num); | ||
1323 | |||
1324 | if (ns->regs.count == ns->regs.num) { | ||
1325 | NS_DBG("address (%#x, %#x) is accepted\n", ns->regs.row, ns->regs.column); | ||
1326 | switch_state(ns); | ||
1327 | } | ||
1328 | |||
1329 | } else { | ||
1330 | /* | ||
1331 | * The byte written is an input data. | ||
1332 | */ | ||
1333 | |||
1334 | /* Check that chip is expecting data input */ | ||
1335 | if (!(ns->state & STATE_DATAIN_MASK)) { | ||
1336 | NS_ERR("write_byte: data input (%#x) isn't expected, state is %s, " | ||
1337 | "switch to %s\n", (uint)byte, | ||
1338 | get_state_name(ns->state), get_state_name(STATE_READY)); | ||
1339 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
1340 | return; | ||
1341 | } | ||
1342 | |||
1343 | /* Check if this is expected byte */ | ||
1344 | if (ns->regs.count == ns->regs.num) { | ||
1345 | NS_WARN("write_byte: %u input bytes has already been accepted, ignore write\n", | ||
1346 | ns->regs.num); | ||
1347 | return; | ||
1348 | } | ||
1349 | |||
1350 | if (ns->busw == 8) { | ||
1351 | ns->buf.byte[ns->regs.count] = byte; | ||
1352 | ns->regs.count += 1; | ||
1353 | } else { | ||
1354 | ns->buf.word[ns->regs.count >> 1] = cpu_to_le16((uint16_t)byte); | ||
1355 | ns->regs.count += 2; | ||
1356 | } | ||
1357 | } | ||
1358 | |||
1359 | return; | ||
1360 | } | ||
1361 | |||
1362 | static int | ||
1363 | ns_device_ready(struct mtd_info *mtd) | ||
1364 | { | ||
1365 | NS_DBG("device_ready\n"); | ||
1366 | return 1; | ||
1367 | } | ||
1368 | |||
1369 | static uint16_t | ||
1370 | ns_nand_read_word(struct mtd_info *mtd) | ||
1371 | { | ||
1372 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; | ||
1373 | |||
1374 | NS_DBG("read_word\n"); | ||
1375 | |||
1376 | return chip->read_byte(mtd) | (chip->read_byte(mtd) << 8); | ||
1377 | } | ||
1378 | |||
1379 | static void | ||
1380 | ns_nand_write_word(struct mtd_info *mtd, uint16_t word) | ||
1381 | { | ||
1382 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; | ||
1383 | |||
1384 | NS_DBG("write_word\n"); | ||
1385 | |||
1386 | chip->write_byte(mtd, word & 0xFF); | ||
1387 | chip->write_byte(mtd, word >> 8); | ||
1388 | } | ||
1389 | |||
1390 | static void | ||
1391 | ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | ||
1392 | { | ||
1393 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | ||
1394 | |||
1395 | /* Check that chip is expecting data input */ | ||
1396 | if (!(ns->state & STATE_DATAIN_MASK)) { | ||
1397 | NS_ERR("write_buf: data input isn't expected, state is %s, " | ||
1398 | "switch to STATE_READY\n", get_state_name(ns->state)); | ||
1399 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
1400 | return; | ||
1401 | } | ||
1402 | |||
1403 | /* Check if these are expected bytes */ | ||
1404 | if (ns->regs.count + len > ns->regs.num) { | ||
1405 | NS_ERR("write_buf: too many input bytes\n"); | ||
1406 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
1407 | return; | ||
1408 | } | ||
1409 | |||
1410 | memcpy(ns->buf.byte + ns->regs.count, buf, len); | ||
1411 | ns->regs.count += len; | ||
1412 | |||
1413 | if (ns->regs.count == ns->regs.num) { | ||
1414 | NS_DBG("write_buf: %d bytes were written\n", ns->regs.count); | ||
1415 | } | ||
1416 | } | ||
1417 | |||
1418 | static void | ||
1419 | ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | ||
1420 | { | ||
1421 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | ||
1422 | |||
1423 | /* Sanity and correctness checks */ | ||
1424 | if (!ns->lines.ce) { | ||
1425 | NS_ERR("read_buf: chip is disabled\n"); | ||
1426 | return; | ||
1427 | } | ||
1428 | if (ns->lines.ale || ns->lines.cle) { | ||
1429 | NS_ERR("read_buf: ALE or CLE pin is high\n"); | ||
1430 | return; | ||
1431 | } | ||
1432 | if (!(ns->state & STATE_DATAOUT_MASK)) { | ||
1433 | NS_WARN("read_buf: unexpected data output cycle, current state is %s\n", | ||
1434 | get_state_name(ns->state)); | ||
1435 | return; | ||
1436 | } | ||
1437 | |||
1438 | if (NS_STATE(ns->state) != STATE_DATAOUT) { | ||
1439 | int i; | ||
1440 | |||
1441 | for (i = 0; i < len; i++) | ||
1442 | buf[i] = ((struct nand_chip *)mtd->priv)->read_byte(mtd); | ||
1443 | |||
1444 | return; | ||
1445 | } | ||
1446 | |||
1447 | /* Check if these are expected bytes */ | ||
1448 | if (ns->regs.count + len > ns->regs.num) { | ||
1449 | NS_ERR("read_buf: too many bytes to read\n"); | ||
1450 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
1451 | return; | ||
1452 | } | ||
1453 | |||
1454 | memcpy(buf, ns->buf.byte + ns->regs.count, len); | ||
1455 | ns->regs.count += len; | ||
1456 | |||
1457 | if (ns->regs.count == ns->regs.num) { | ||
1458 | if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) { | ||
1459 | ns->regs.count = 0; | ||
1460 | if (ns->regs.row + 1 < ns->geom.pgnum) | ||
1461 | ns->regs.row += 1; | ||
1462 | NS_DBG("read_buf: switch to the next page (%#x)\n", ns->regs.row); | ||
1463 | do_state_action(ns, ACTION_CPY); | ||
1464 | } | ||
1465 | else if (NS_STATE(ns->nxstate) == STATE_READY) | ||
1466 | switch_state(ns); | ||
1467 | } | ||
1468 | |||
1469 | return; | ||
1470 | } | ||
1471 | |||
1472 | static int | ||
1473 | ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) | ||
1474 | { | ||
1475 | ns_nand_read_buf(mtd, (u_char *)&ns_verify_buf[0], len); | ||
1476 | |||
1477 | if (!memcmp(buf, &ns_verify_buf[0], len)) { | ||
1478 | NS_DBG("verify_buf: the buffer is OK\n"); | ||
1479 | return 0; | ||
1480 | } else { | ||
1481 | NS_DBG("verify_buf: the buffer is wrong\n"); | ||
1482 | return -EFAULT; | ||
1483 | } | ||
1484 | } | ||
1485 | |||
1486 | /* | ||
1487 | * Having only NAND chip IDs we call nand_scan which detects NAND flash | ||
1488 | * parameters and then calls scan_bbt in order to scan/find/build the | ||
1489 | * NAND flash bad block table. But since at that moment the NAND flash | ||
1490 | * image isn't allocated in the simulator, errors arise. To avoid this | ||
1491 | * we redefine the scan_bbt callback and initialize the nandsim structure | ||
1492 | * before the flash media scanning. | ||
1493 | */ | ||
1494 | int ns_scan_bbt(struct mtd_info *mtd) | ||
1495 | { | ||
1496 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; | ||
1497 | struct nandsim *ns = (struct nandsim *)(chip->priv); | ||
1498 | int retval; | ||
1499 | |||
1500 | if (!NS_IS_INITIALIZED(ns)) | ||
1501 | if ((retval = init_nandsim(mtd)) != 0) { | ||
1502 | NS_ERR("scan_bbt: can't initialize the nandsim structure\n"); | ||
1503 | return retval; | ||
1504 | } | ||
1505 | if ((retval = nand_default_bbt(mtd)) != 0) { | ||
1506 | free_nandsim(ns); | ||
1507 | return retval; | ||
1508 | } | ||
1509 | |||
1510 | return 0; | ||
1511 | } | ||
1512 | |||
1513 | /* | ||
1514 | * Module initialization function | ||
1515 | */ | ||
1516 | int __init ns_init_module(void) | ||
1517 | { | ||
1518 | struct nand_chip *chip; | ||
1519 | struct nandsim *nand; | ||
1520 | int retval = -ENOMEM; | ||
1521 | |||
1522 | if (bus_width != 8 && bus_width != 16) { | ||
1523 | NS_ERR("wrong bus width (%d), use only 8 or 16\n", bus_width); | ||
1524 | return -EINVAL; | ||
1525 | } | ||
1526 | |||
1527 | /* Allocate and initialize mtd_info, nand_chip and nandsim structures */ | ||
1528 | nsmtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip) | ||
1529 | + sizeof(struct nandsim), GFP_KERNEL); | ||
1530 | if (!nsmtd) { | ||
1531 | NS_ERR("unable to allocate core structures.\n"); | ||
1532 | return -ENOMEM; | ||
1533 | } | ||
1534 | memset(nsmtd, 0, sizeof(struct mtd_info) + sizeof(struct nand_chip) + | ||
1535 | sizeof(struct nandsim)); | ||
1536 | chip = (struct nand_chip *)(nsmtd + 1); | ||
1537 | nsmtd->priv = (void *)chip; | ||
1538 | nand = (struct nandsim *)(chip + 1); | ||
1539 | chip->priv = (void *)nand; | ||
1540 | |||
1541 | /* | ||
1542 | * Register simulator's callbacks. | ||
1543 | */ | ||
1544 | chip->hwcontrol = ns_hwcontrol; | ||
1545 | chip->read_byte = ns_nand_read_byte; | ||
1546 | chip->dev_ready = ns_device_ready; | ||
1547 | chip->scan_bbt = ns_scan_bbt; | ||
1548 | chip->write_byte = ns_nand_write_byte; | ||
1549 | chip->write_buf = ns_nand_write_buf; | ||
1550 | chip->read_buf = ns_nand_read_buf; | ||
1551 | chip->verify_buf = ns_nand_verify_buf; | ||
1552 | chip->write_word = ns_nand_write_word; | ||
1553 | chip->read_word = ns_nand_read_word; | ||
1554 | chip->eccmode = NAND_ECC_SOFT; | ||
1555 | |||
1556 | /* | ||
1557 | * Perform minimum nandsim structure initialization to handle | ||
1558 | * the initial ID read command correctly | ||
1559 | */ | ||
1560 | if (third_id_byte != 0xFF || fourth_id_byte != 0xFF) | ||
1561 | nand->geom.idbytes = 4; | ||
1562 | else | ||
1563 | nand->geom.idbytes = 2; | ||
1564 | nand->regs.status = NS_STATUS_OK(nand); | ||
1565 | nand->nxstate = STATE_UNKNOWN; | ||
1566 | nand->options |= OPT_PAGE256; /* temporary value */ | ||
1567 | nand->ids[0] = first_id_byte; | ||
1568 | nand->ids[1] = second_id_byte; | ||
1569 | nand->ids[2] = third_id_byte; | ||
1570 | nand->ids[3] = fourth_id_byte; | ||
1571 | if (bus_width == 16) { | ||
1572 | nand->busw = 16; | ||
1573 | chip->options |= NAND_BUSWIDTH_16; | ||
1574 | } | ||
1575 | |||
1576 | if ((retval = nand_scan(nsmtd, 1)) != 0) { | ||
1577 | NS_ERR("can't register NAND Simulator\n"); | ||
1578 | if (retval > 0) | ||
1579 | retval = -ENXIO; | ||
1580 | goto error; | ||
1581 | } | ||
1582 | |||
1583 | /* Register NAND as one big partition */ | ||
1584 | add_mtd_partitions(nsmtd, &nand->part, 1); | ||
1585 | |||
1586 | return 0; | ||
1587 | |||
1588 | error: | ||
1589 | kfree(nsmtd); | ||
1590 | |||
1591 | return retval; | ||
1592 | } | ||
1593 | |||
1594 | module_init(ns_init_module); | ||
1595 | |||
1596 | /* | ||
1597 | * Module clean-up function | ||
1598 | */ | ||
1599 | static void __exit ns_cleanup_module(void) | ||
1600 | { | ||
1601 | struct nandsim *ns = (struct nandsim *)(((struct nand_chip *)nsmtd->priv)->priv); | ||
1602 | |||
1603 | free_nandsim(ns); /* Free nandsim private resources */ | ||
1604 | nand_release(nsmtd); /* Unregisterd drived */ | ||
1605 | kfree(nsmtd); /* Free other structures */ | ||
1606 | } | ||
1607 | |||
1608 | module_exit(ns_cleanup_module); | ||
1609 | |||
1610 | MODULE_LICENSE ("GPL"); | ||
1611 | MODULE_AUTHOR ("Artem B. Bityuckiy"); | ||
1612 | MODULE_DESCRIPTION ("The NAND flash simulator"); | ||
1613 | |||