ded465b461bb864744378e621cd40b1c2f3f0955
[yaffs2.git] / direct / test-framework / nandsim.c
1 /*
2  * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
3  *
4  * Copyright (C) 2010-2011 Aleph One Ltd.
5  *
6  * Created by Charles Manning <charles@aleph1.co.uk>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12 /*
13  * Nand simulator modelled on a Samsung K9K2G08U0A 8-bit, but capable of
14  * simulating x16 access too.
15  *
16  * Page size 2k + 64
17  * Block size 64 pages
18  * Dev size 256 Mbytes
19  */
20
21 #include "nandsim.h"
22 #include "nand_chip.h"
23
24 #include <stdint.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30
31 static int nandsim_debug = 0;
32
33 #define debug(n, fmt, ...) \
34         do { \
35         if (n <= nandsim_debug) \
36                 printf(fmt, ## __VA_ARGS__); \
37         } while (0)
38
39
40
41 struct nandsim_private {
42
43         struct nand_store *store;
44         /*
45         * Access buffers.
46         * Address buffer has two parts to it:
47         * 2 byte column (byte) offset
48         * 3 byte row (page) offset
49         */
50
51         unsigned char *buffer;
52         int buff_size;
53
54         unsigned char addr_buffer[5];
55
56         /*
57         * Offsets used to access address, read or write buffer.
58         * If the offset is negative then accessing is illegal.
59         */
60
61         int addr_offset;
62         int addr_expected;
63         int addr_received;
64
65         int read_offset;
66         int write_offset;
67         int read_started;
68
69         /*
70         * busy_count: If greater than zero then the device is busy.
71         * Busy count is decremented by check_busy() and by read_status()
72         */
73         int busy_count;
74         int write_prog_error;
75         int reading_status;
76         unsigned char last_cmd_byte;
77
78         int ale;
79         int cle;
80 };
81
82 static void last_cmd(struct nandsim_private *ns, unsigned char val)
83 {
84         ns->last_cmd_byte = val;
85 }
86
87 static void check_last(struct nandsim_private *ns,
88                         unsigned char should_be, int line)
89 {
90         if(ns->last_cmd_byte != should_be)
91                 debug(1, "At line %d:, last_cmd should be %02x, but is %02x\n",
92                         line, should_be, ns->last_cmd_byte);
93 }
94
95 static void idle(struct nandsim_private *ns, int line)
96 {
97         (void) line;
98
99         ns->read_offset = -1;
100         ns->write_offset = -1;
101         ns->addr_offset = -1;
102         ns->addr_expected = -1;
103         ns->addr_received = -1;
104         last_cmd(ns, 0xff);
105         ns->busy_count = 0;
106         ns->reading_status = 0;
107         ns->read_started = 0;
108 }
109
110
111 static void expect_address(struct nandsim_private *ns,
112                         int nbytes, int line)
113 {
114         int from;
115         switch (nbytes) {
116         case 2:
117         case 5: /* contains an offset */
118                 from = 0;
119                 break;
120         case 3: /* no offset */
121                 from = 2;
122                 break;
123         default:
124                 debug(1, "expect_address illegal nbytes %d called at line %d\n",
125                                 nbytes, line);
126                 return;
127         }
128
129         ns->addr_offset = from;
130         ns->addr_expected = nbytes;
131         ns->addr_received = 0;
132         debug(1, "Expect %d address bytes\n",nbytes);
133 }
134
135 static int get_page_address(struct nandsim_private *ns)
136 {
137         int addr;
138
139         addr = (ns->addr_buffer[2]) |
140                 (ns->addr_buffer[3] << 8) |
141                 (ns->addr_buffer[4] << 16);
142         return addr;
143 }
144
145 static int get_page_offset(struct nandsim_private *ns)
146 {
147         int offs;
148
149         offs = (ns->addr_buffer[0]) |
150                 (ns->addr_buffer[1] << 8);
151         return offs;
152 }
153
154 static void check_address(struct nandsim_private *ns, int nbytes, int line)
155 {
156         if(ns->addr_expected != 0)
157                 debug(1, "Still expecting %d address bytes at line: %d\n",
158                                         ns->addr_expected, line);
159         if(ns->addr_received != nbytes)
160                 debug(1, "Only received %d address bytes instead of %d at line %d\n",
161                                         ns->addr_received, nbytes, line);
162 }
163
164 static void set_offset(struct nandsim_private *ns)
165 {
166         ns->read_offset = -1;
167         ns->write_offset = -1;
168
169         if(ns->last_cmd_byte == 0x80 )
170                 ns->write_offset = get_page_offset(ns);
171         else if(ns->last_cmd_byte == 0x00 || ns->last_cmd_byte == 0x05)
172                 ns->read_offset = get_page_offset(ns);
173         debug(2, "Last command was %02X offsets set to read %d write %d\n",
174                         ns->last_cmd_byte, ns->read_offset, ns->write_offset);
175 }
176
177 static void load_read_buffer(struct nandsim_private *ns)
178 {
179         int addr = get_page_address(ns);
180
181         debug(1, "Store read at address %d\n", addr);
182         ns->store->retrieve(ns->store, addr,ns->buffer);
183 }
184 static void save_write_buffer(struct nandsim_private *ns)
185 {
186         int addr = get_page_address(ns);
187
188         debug(1, "Store write at address %d\n", addr);
189         ns->store->store(ns->store, addr, ns->buffer);
190 }
191
192 static void check_read_buffer(struct nandsim_private *ns, int line)
193 {
194         (void) ns;
195         (void) line;
196 }
197
198 static void end_cmd(struct nandsim_private *ns, int line)
199 {
200         (void) line;
201
202         ns->last_cmd_byte = 0xff;
203 }
204
205 static void set_busy(struct nandsim_private *ns, int cycles, int line)
206 {
207         (void) line;
208
209         ns->busy_count = cycles;
210 }
211
212 static int check_not_busy(struct nandsim_private *ns, int line)
213 {
214         if(ns->busy_count > 0)
215                 debug(1, "Busy check failed at line %d\n",line);
216         return (ns->busy_count < 1);
217 }
218
219 /*
220  * Reset
221  * Cmd: 0xff
222  */
223 static void reset_0(struct nandsim_private *ns)
224 {
225         debug(2, "Reset\n");
226         last_cmd(ns, 0xff);
227         idle(ns, __LINE__);
228         end_cmd(ns, __LINE__);
229 }
230
231 /*
232  * Read
233  * cmd: 0x00, 5 address bytes, cmd: 0x30, wait not busy, read out data
234  *
235  * Note that 0x30 can also be used to exit the status reading state
236  * and return to data reading state.
237  *
238  * The following sequence uses the busy pin to wait:
239  *
240  *  Write cmd 0x00
241  *  Write 5 address bytes
242  *  Write cmd 0x30. Device now goes busy
243  *  Wait for busy pin to go idle
244  *  Read data bytes.
245  *
246  * The following sequence uses the status read to wait:
247  *  Write cmd 0x00
248  *  Write 5 address bytes
249  *  Write cmd 0x30. Device now goes busy
250  *  Write 0x70: (status)
251  *  Read status until device no longer busy
252  *  Write command byte 0x30 to exit status read. Can now read data
253  *  Read data bytes.
254
255  */
256
257
258 static void read_0(struct nandsim_private *ns)
259 {
260         debug(2, "Read 0\n");
261         check_last(ns, 0xff, __LINE__);
262         if(check_not_busy(ns, __LINE__))
263                 ns->reading_status = 0;
264         expect_address(ns, 5, __LINE__);
265         last_cmd(ns, 0x00);
266         ns->read_started = 1;
267 }
268
269 static void read_1(struct nandsim_private *ns)
270 {
271         debug(2, "Read 1\n");
272         if(check_not_busy(ns, __LINE__))
273                 ns->reading_status = 0;
274         if(ns->read_started){
275                 /* Doing a read */
276                 ns->read_started = 0;
277                 check_address(ns, 5, __LINE__);
278                 load_read_buffer(ns);
279                 set_busy(ns, 2, __LINE__);
280                 end_cmd(ns, __LINE__);
281         } else {
282                 /* reenter read mode after a status check */
283                 end_cmd(ns, __LINE__);
284         }
285 }
286
287 /*
288  * Random Data Output (sets read position in current page)
289  * Cmd: 0x05, 2-byte address, cmd: 0xE0. No busy
290  */
291
292 static void random_data_output_0(struct nandsim_private *ns)
293 {
294         debug(2, "Random data out 0\n");
295         check_last(ns, 0xff, __LINE__);
296         if(check_not_busy(ns, __LINE__))
297                 ns->reading_status = 0;
298         check_read_buffer(ns, __LINE__);
299         expect_address(ns, 2, __LINE__);
300         last_cmd(ns, 0x05);
301 }
302
303 static void random_data_output_1(struct nandsim_private *ns)
304 {
305         debug(2, "Random data out 1\n");
306         check_last(ns, 0x05, __LINE__);
307         check_address(ns, 2, __LINE__);
308 }
309
310
311 /*
312  * Program page
313  * Cmd: 0x80, 5-byte address, data bytes,  Cmd: 0x10, wait not busy
314  * That can be extended with random data input by inserting
315  * any number of random data input cycles before the 0x10 command
316  * Each random data input cycle is
317  *  Cmd 0x85 , 2 byte offset, data bytes
318  */
319
320 static void program_0(struct nandsim_private *ns)
321 {
322         debug(2, "Program 0\n");
323         check_last(ns, 0xff, __LINE__);
324         if(check_not_busy(ns, __LINE__))
325                 ns->reading_status = 0;
326         expect_address(ns, 5, __LINE__);
327         memset(ns->buffer, 0xff, ns->buff_size);
328         last_cmd(ns, 0x80);
329 }
330 static void random_data_input(struct nandsim_private *ns)
331 {
332         debug(2, "Random data input\n");
333         check_last(ns, 0x80, __LINE__);
334         expect_address(ns, 2, __LINE__);
335         last_cmd(ns, 0x80);
336 }
337
338 static void program_1(struct nandsim_private *ns)
339 {
340         debug(2, "Program 1\n");
341         if(check_not_busy(ns, __LINE__))
342                 ns->reading_status = 0;
343         check_last(ns, 0x80, __LINE__);
344         check_address(ns, 5, __LINE__);
345         save_write_buffer(ns);
346         set_busy(ns, 2, __LINE__);
347         end_cmd(ns, __LINE__);
348 }
349
350
351
352 /*
353  * Block erase
354  * Cmd: 0x60, 3-byte address, cmd: 0xD0. Wait not busy.
355  */
356 static void block_erase_0(struct nandsim_private *ns)
357 {
358         debug(2, "Block Erase 0\n");
359         check_last(ns, 0xff, __LINE__);
360         if(check_not_busy(ns, __LINE__))
361                 ns->reading_status = 0;
362         expect_address(ns, 3, __LINE__);
363         last_cmd(ns, 0x60);
364 }
365
366 static void block_erase_1(struct nandsim_private *ns)
367 {
368         int addr;
369
370         debug(2, "Block Erase 1\n");
371         check_last(ns, 0x60, __LINE__);
372         if(check_not_busy(ns, __LINE__))
373                 ns->reading_status = 0;
374         check_address(ns, 3, __LINE__);
375         set_busy(ns, 5, __LINE__);
376         addr = get_page_address(ns);
377         debug(1, "Erasing block at address %d\n", addr);
378         ns->store->erase(ns->store, addr);
379         end_cmd(ns, __LINE__);
380 }
381 /*
382  * Read stuatus
383  * Cmd 0x70
384  */
385 static void read_status(struct nandsim_private *ns)
386 {
387         debug(2, "Read status\n");
388         ns->reading_status = 1;
389 }
390
391 static void read_id(struct nandsim_private *ns)
392 {
393         (void) ns;
394 }
395
396
397 static void unsupported(struct nandsim_private *ns)
398 {
399         (void) ns;
400 }
401
402 static void nandsim_cl_write(struct nandsim_private *ns, unsigned char val)
403 {
404         debug(2, "CLE write %02X\n",val);
405         switch(val){
406                 case 0x00:
407                         read_0(ns);
408                         break;
409                 case 0x05:
410                         random_data_output_0(ns);
411                         break;
412                 case 0x10:
413                         program_1(ns);
414                         break;
415                 case 0x15:
416                         unsupported(ns);
417                         break;
418                 case 0x30:
419                         read_1(ns);
420                         break;
421                 case 0x35:
422                         unsupported(ns);
423                         break;
424                 case 0x60:
425                         block_erase_0(ns);
426                         break;
427                 case 0x70:
428                         read_status(ns);
429                         break;
430                 case 0x80:
431                         program_0(ns);
432                         break;
433                 case 0x85:
434                         random_data_input(ns);
435                         break;
436                 case 0x90:
437                         read_id(ns);
438                         break;
439                 case 0xD0:
440                         block_erase_1(ns);
441                         break;
442                 case 0xE0:
443                         random_data_output_1(ns);
444                         break;
445                 case 0xFF:
446                         reset_0(ns);
447                         break;
448                 default:
449                         debug(1, "CLE written with invalid value %02X.\n",val);
450                         break;
451                         /* Valid codes that we don't handle */
452                         debug(1, "CLE written with invalid value %02X.\n",val);
453         }
454 }
455
456
457 static void nandsim_al_write(struct nandsim_private *ns, unsigned char val)
458 {
459         check_not_busy(ns, __LINE__);
460         if(ns->addr_expected < 1 ||
461                 ns->addr_offset < 0 ||
462                 ns->addr_offset >= (int)sizeof(ns->addr_buffer)){
463                 debug(1, "Address write when not expected\n");
464         } else {
465                 debug(1, "Address write when expecting %d bytes\n",
466                         ns->addr_expected);
467                 ns->addr_buffer[ns->addr_offset] = val;
468                 ns->addr_offset++;
469                 ns->addr_received++;
470                 ns->addr_expected--;
471                 if(ns->addr_expected == 0)
472                         set_offset(ns);
473         }
474 }
475
476 static void nandsim_dl_write(struct nandsim_private *ns,
477                                 unsigned val,
478                                 int bus_width_shift)
479 {
480         check_not_busy(ns, __LINE__);
481         if( ns->write_offset < 0 || ns->write_offset >= ns->buff_size){
482                 debug(1, "Write at illegal buffer offset %d\n",
483                                 ns->write_offset);
484         } else if(bus_width_shift == 0) {
485                 ns->buffer[ns->write_offset] = val & 0xff;
486                 ns->write_offset++;
487         } else if(bus_width_shift == 1) {
488                 ns->buffer[ns->write_offset] = val & 0xff;
489                 ns->write_offset++;
490                 ns->buffer[ns->write_offset] = (val>>8) & 0xff;
491                 ns->write_offset++;
492         }
493 }
494
495 static unsigned nandsim_dl_read(struct nandsim_private *ns,
496                                 int bus_width_shift)
497 {
498         unsigned retval;
499         if(ns->reading_status){
500                 /*
501                  * bit 0 == 0 pass, == 1 fail.
502                  * bit 6 == 0 busy, == 1 ready
503                  */
504                 retval = 0xfe;
505                 if(ns->busy_count > 0){
506                         ns->busy_count--;
507                         retval&= ~(1<<6);
508                 }
509                 if(ns->write_prog_error)
510                         retval |= ~(1<<-0);
511                 debug(2, "Read status returning %02X\n",retval);
512         } else if(ns->busy_count > 0){
513                 debug(1, "Read while still busy\n");
514                 retval = 0;
515         } else if(ns->read_offset < 0 || ns->read_offset >= ns->buff_size){
516                 debug(1, "Read with no data available\n");
517                 retval = 0;
518         } else if(bus_width_shift == 0){
519                 retval = ns->buffer[ns->read_offset];
520                 ns->read_offset++;
521         } else if(bus_width_shift == 1){
522                 retval = ns->buffer[ns->read_offset];
523                 ns->read_offset++;
524                 retval |= (((unsigned)ns->buffer[ns->read_offset]) << 8);
525                 ns->read_offset++;
526         }
527
528         return retval;
529 }
530
531
532 static struct nandsim_private *
533 nandsim_init_private(struct nand_store *store)
534 {
535         struct nandsim_private *ns;
536         unsigned char *buffer;
537         int buff_size;
538
539         buff_size = (store->data_bytes_per_page + store->spare_bytes_per_page);
540
541         ns = malloc(sizeof(struct nandsim_private));
542         buffer = malloc(buff_size);
543         if(!ns || !buffer){
544                 free(ns);
545                 free(buffer);
546                 return NULL;
547         }
548
549         memset(ns, 0, sizeof(struct nandsim_private));
550         ns->buffer = buffer;
551         ns->buff_size = buff_size;
552         ns->store = store;
553         idle(ns, __LINE__);
554         return ns;
555 }
556
557
558 static void nandsim_set_ale(struct nand_chip * this, int ale)
559 {
560         struct nandsim_private *ns =
561                 (struct nandsim_private *)this->private_data;
562         ns->ale = ale;
563 }
564
565 static void nandsim_set_cle(struct nand_chip * this, int cle)
566 {
567         struct nandsim_private *ns =
568                 (struct nandsim_private *)this->private_data;
569         ns->cle = cle;
570 }
571
572 static unsigned nandsim_read_cycle(struct nand_chip * this)
573 {
574         unsigned retval;
575         struct nandsim_private *ns =
576                 (struct nandsim_private *)this->private_data;
577
578         if (ns->cle || ns->ale){
579                 debug(1, "Read cycle with CLE %s and ALE %s\n",
580                         ns->cle ? "high" : "low",
581                         ns->ale ? "high" : "low");
582                 retval = 0;
583         } else {
584                 retval =nandsim_dl_read(ns, this->bus_width_shift);
585         }
586         debug(5, "Read cycle returning %02X\n",retval);
587         return retval;
588 }
589
590 static void nandsim_write_cycle(struct nand_chip * this, unsigned b)
591 {
592         struct nandsim_private *ns =
593                 (struct nandsim_private *)this->private_data;
594         const char *x;
595
596         if(ns->ale && ns->cle)
597                 x = "ALE AND CLE";
598         else if (ns->ale)
599                 x = "ALE";
600         else if (ns->cle)
601                 x = "CLE";
602         else
603                 x = "data";
604
605         debug(5, "Write %02x to %s\n",
606                         b, x);
607         if (ns->cle && ns->ale)
608                 debug(1, "Write cycle with both ALE and CLE high\n");
609         else if (ns->cle)
610                 nandsim_cl_write(ns, b);
611         else if (ns->ale)
612                 nandsim_al_write(ns, b);
613         else
614                 nandsim_dl_write(ns, b, this->bus_width_shift);
615 }
616
617 static int nandsim_check_busy(struct nand_chip * this)
618 {
619         struct nandsim_private *ns =
620                 (struct nandsim_private *)this->private_data;
621
622
623         if (ns->busy_count> 0){
624                 ns->busy_count--;
625                 debug(2, "Still busy\n");
626                 return 1;
627         } else {
628                 debug(2, "Not busy\n");
629                 return 0;
630         }
631 }
632
633 static void nandsim_idle_fn(struct nand_chip *this)
634 {
635         struct nandsim_private *ns =
636                 (struct nandsim_private *)this->private_data;
637         ns = ns;
638 }
639
640 struct nand_chip *nandsim_init(struct nand_store *store, int bus_width_shift)
641 {
642         struct nand_chip *chip = NULL;
643         struct nandsim_private *ns = NULL;
644
645         chip = malloc(sizeof(struct nand_chip));
646         ns = nandsim_init_private(store);
647
648         if(chip && ns){
649                 memset(chip, 0, sizeof(struct nand_chip));;
650
651                 chip->private_data = ns;
652                 chip->set_ale = nandsim_set_ale;
653                 chip->set_cle = nandsim_set_cle;
654                 chip->read_cycle = nandsim_read_cycle;
655                 chip->write_cycle = nandsim_write_cycle;
656                 chip->check_busy = nandsim_check_busy;
657                 chip->idle_fn = nandsim_idle_fn;
658
659                 chip->bus_width_shift = bus_width_shift;
660
661                 chip->blocks = ns->store->blocks;
662                 chip->pages_per_block = ns->store->pages_per_block;
663                 chip->data_bytes_per_page = ns->store->data_bytes_per_page;
664                 chip->spare_bytes_per_page = ns->store->spare_bytes_per_page;
665
666                 return chip;
667         } else {
668                 free(chip);
669                 free(ns);
670                 return NULL;
671         }
672 }
673
674 void nandsim_set_debug(int d)
675 {
676         nandsim_debug = d;
677 }