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