Merge branch 'staging-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
[pandora-kernel.git] / drivers / staging / spectra / lld_emu.c
1 /*
2  * NAND Flash Controller Device Driver
3  * Copyright (c) 2009, Intel Corporation and its suppliers.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17  *
18  */
19
20 #include <linux/fs.h>
21 #include <linux/slab.h>
22 #include "flash.h"
23 #include "ffsdefs.h"
24 #include "lld_emu.h"
25 #include "lld.h"
26 #if CMD_DMA
27 #include "lld_cdma.h"
28 #if FLASH_EMU
29 u32 totalUsedBanks;
30 u32 valid_banks[MAX_CHANS];
31 #endif
32 #endif
33
34 #define GLOB_LLD_PAGES           64
35 #define GLOB_LLD_PAGE_SIZE       (512+16)
36 #define GLOB_LLD_PAGE_DATA_SIZE  512
37 #define GLOB_LLD_BLOCKS          2048
38
39 #if FLASH_EMU                   /* This is for entire module */
40
41 static u8 *flash_memory[GLOB_LLD_BLOCKS * GLOB_LLD_PAGES];
42
43 /* Read nand emu file and then fill it's content to flash_memory */
44 int emu_load_file_to_mem(void)
45 {
46         mm_segment_t fs;
47         struct file *nef_filp = NULL;
48         struct inode *inode = NULL;
49         loff_t nef_size = 0;
50         loff_t tmp_file_offset, file_offset;
51         ssize_t nread;
52         int i, rc = -EINVAL;
53
54         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
55                        __FILE__, __LINE__, __func__);
56
57         fs = get_fs();
58         set_fs(get_ds());
59
60         nef_filp = filp_open("/root/nand_emu_file", O_RDWR | O_LARGEFILE, 0);
61         if (IS_ERR(nef_filp)) {
62                 printk(KERN_ERR "filp_open error: "
63                        "Unable to open nand emu file!\n");
64                 return PTR_ERR(nef_filp);
65         }
66
67         if (nef_filp->f_path.dentry) {
68                 inode = nef_filp->f_path.dentry->d_inode;
69         } else {
70                 printk(KERN_ERR "Can not get valid inode!\n");
71                 goto out;
72         }
73
74         nef_size = i_size_read(inode->i_mapping->host);
75         if (nef_size <= 0) {
76                 printk(KERN_ERR "Invalid nand emu file size: "
77                        "0x%llx\n", nef_size);
78                 goto out;
79         } else {
80                 nand_dbg_print(NAND_DBG_DEBUG, "nand emu file size: %lld\n",
81                                nef_size);
82         }
83
84         file_offset = 0;
85         for (i = 0; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) {
86                 tmp_file_offset = file_offset;
87                 nread = vfs_read(nef_filp,
88                                  (char __user *)flash_memory[i],
89                                  GLOB_LLD_PAGE_SIZE, &tmp_file_offset);
90                 if (nread < GLOB_LLD_PAGE_SIZE) {
91                         printk(KERN_ERR "%s, Line %d - "
92                                "nand emu file partial read: "
93                                "%d bytes\n", __FILE__, __LINE__, (int)nread);
94                         goto out;
95                 }
96                 file_offset += GLOB_LLD_PAGE_SIZE;
97         }
98         rc = 0;
99
100 out:
101         filp_close(nef_filp, current->files);
102         set_fs(fs);
103         return rc;
104 }
105
106 /* Write contents of flash_memory to nand emu file */
107 int emu_write_mem_to_file(void)
108 {
109         mm_segment_t fs;
110         struct file *nef_filp = NULL;
111         struct inode *inode = NULL;
112         loff_t nef_size = 0;
113         loff_t tmp_file_offset, file_offset;
114         ssize_t nwritten;
115         int i, rc = -EINVAL;
116
117         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
118                        __FILE__, __LINE__, __func__);
119
120         fs = get_fs();
121         set_fs(get_ds());
122
123         nef_filp = filp_open("/root/nand_emu_file", O_RDWR | O_LARGEFILE, 0);
124         if (IS_ERR(nef_filp)) {
125                 printk(KERN_ERR "filp_open error: "
126                        "Unable to open nand emu file!\n");
127                 return PTR_ERR(nef_filp);
128         }
129
130         if (nef_filp->f_path.dentry) {
131                 inode = nef_filp->f_path.dentry->d_inode;
132         } else {
133                 printk(KERN_ERR "Invalid " "nef_filp->f_path.dentry value!\n");
134                 goto out;
135         }
136
137         nef_size = i_size_read(inode->i_mapping->host);
138         if (nef_size <= 0) {
139                 printk(KERN_ERR "Invalid "
140                        "nand emu file size: 0x%llx\n", nef_size);
141                 goto out;
142         } else {
143                 nand_dbg_print(NAND_DBG_DEBUG, "nand emu file size: "
144                                "%lld\n", nef_size);
145         }
146
147         file_offset = 0;
148         for (i = 0; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) {
149                 tmp_file_offset = file_offset;
150                 nwritten = vfs_write(nef_filp,
151                                      (char __user *)flash_memory[i],
152                                      GLOB_LLD_PAGE_SIZE, &tmp_file_offset);
153                 if (nwritten < GLOB_LLD_PAGE_SIZE) {
154                         printk(KERN_ERR "%s, Line %d - "
155                                "nand emu file partial write: "
156                                "%d bytes\n", __FILE__, __LINE__, (int)nwritten);
157                         goto out;
158                 }
159                 file_offset += GLOB_LLD_PAGE_SIZE;
160         }
161         rc = 0;
162
163 out:
164         filp_close(nef_filp, current->files);
165         set_fs(fs);
166         return rc;
167 }
168
169 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
170 * Function:     emu_Flash_Init
171 * Inputs:       none
172 * Outputs:      PASS=0 (notice 0=ok here)
173 * Description:  Creates & initializes the flash RAM array.
174 *
175 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
176 u16 emu_Flash_Init(void)
177 {
178         int i;
179
180         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
181                        __FILE__, __LINE__, __func__);
182
183         flash_memory[0] = vmalloc(GLOB_LLD_PAGE_SIZE * GLOB_LLD_BLOCKS *
184                                   GLOB_LLD_PAGES * sizeof(u8));
185         if (!flash_memory[0]) {
186                 printk(KERN_ERR "Fail to allocate memory "
187                        "for nand emulator!\n");
188                 return ERR;
189         }
190
191         memset((char *)(flash_memory[0]), 0xFF,
192                GLOB_LLD_PAGE_SIZE * GLOB_LLD_BLOCKS * GLOB_LLD_PAGES *
193                sizeof(u8));
194
195         for (i = 1; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++)
196                 flash_memory[i] = flash_memory[i - 1] + GLOB_LLD_PAGE_SIZE;
197
198         emu_load_file_to_mem(); /* Load nand emu file to mem */
199
200         return PASS;
201 }
202
203 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
204 * Function:     emu_Flash_Release
205 * Inputs:       none
206 * Outputs:      PASS=0 (notice 0=ok here)
207 * Description:          Releases the flash.
208 *
209 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
210 int emu_Flash_Release(void)
211 {
212         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
213                        __FILE__, __LINE__, __func__);
214
215         emu_write_mem_to_file();  /* Write back mem to nand emu file */
216
217         vfree(flash_memory[0]);
218         return PASS;
219 }
220
221 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
222 * Function:     emu_Read_Device_ID
223 * Inputs:       none
224 * Outputs:      PASS=1 FAIL=0
225 * Description:  Reads the info from the controller registers.
226 *               Sets up DeviceInfo structure with device parameters
227 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
228
229 u16 emu_Read_Device_ID(void)
230 {
231         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
232                        __FILE__, __LINE__, __func__);
233
234         DeviceInfo.wDeviceMaker = 0;
235         DeviceInfo.wDeviceType = 8;
236         DeviceInfo.wSpectraStartBlock = 36;
237         DeviceInfo.wSpectraEndBlock = GLOB_LLD_BLOCKS - 1;
238         DeviceInfo.wTotalBlocks = GLOB_LLD_BLOCKS;
239         DeviceInfo.wPagesPerBlock = GLOB_LLD_PAGES;
240         DeviceInfo.wPageSize = GLOB_LLD_PAGE_SIZE;
241         DeviceInfo.wPageDataSize = GLOB_LLD_PAGE_DATA_SIZE;
242         DeviceInfo.wPageSpareSize = GLOB_LLD_PAGE_SIZE -
243             GLOB_LLD_PAGE_DATA_SIZE;
244         DeviceInfo.wBlockSize = DeviceInfo.wPageSize * GLOB_LLD_PAGES;
245         DeviceInfo.wBlockDataSize = DeviceInfo.wPageDataSize * GLOB_LLD_PAGES;
246         DeviceInfo.wDataBlockNum = (u32) (DeviceInfo.wSpectraEndBlock -
247                                                 DeviceInfo.wSpectraStartBlock
248                                                 + 1);
249         DeviceInfo.MLCDevice = 1; /* Emulate MLC device */
250         DeviceInfo.nBitsInPageNumber =
251                 (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock);
252         DeviceInfo.nBitsInPageDataSize =
253                 (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize);
254         DeviceInfo.nBitsInBlockDataSize =
255                 (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize);
256
257 #if CMD_DMA
258         totalUsedBanks = 4;
259         valid_banks[0] = 1;
260         valid_banks[1] = 1;
261         valid_banks[2] = 1;
262         valid_banks[3] = 1;
263 #endif
264
265         return PASS;
266 }
267
268 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
269 * Function:     emu_Flash_Reset
270 * Inputs:       none
271 * Outputs:      PASS=0 (notice 0=ok here)
272 * Description:          Reset the flash
273 *
274 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
275 u16 emu_Flash_Reset(void)
276 {
277         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
278                        __FILE__, __LINE__, __func__);
279
280         return PASS;
281 }
282
283 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
284 * Function:     emu_Erase_Block
285 * Inputs:       Address
286 * Outputs:      PASS=0 (notice 0=ok here)
287 * Description:          Erase a block
288 *
289 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
290 u16 emu_Erase_Block(u32 block_add)
291 {
292         int i;
293
294         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
295                        __FILE__, __LINE__, __func__);
296
297         if (block_add >= DeviceInfo.wTotalBlocks) {
298                 printk(KERN_ERR "emu_Erase_Block error! "
299                        "Too big block address: %d\n", block_add);
300                 return FAIL;
301         }
302
303         nand_dbg_print(NAND_DBG_DEBUG, "Erasing block %d\n",
304                 (int)block_add);
305
306         for (i = block_add * GLOB_LLD_PAGES;
307              i < ((block_add + 1) * GLOB_LLD_PAGES); i++) {
308                 if (flash_memory[i]) {
309                         memset((u8 *)(flash_memory[i]), 0xFF,
310                                DeviceInfo.wPageSize * sizeof(u8));
311                 }
312         }
313
314         return PASS;
315 }
316
317 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
318 * Function:     emu_Write_Page_Main
319 * Inputs:       Write buffer address pointer
320 *               Block number
321 *               Page  number
322 *               Number of pages to process
323 * Outputs:      PASS=0 (notice 0=ok here)
324 * Description:  Write the data in the buffer to main area of flash
325 *
326 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
327 u16 emu_Write_Page_Main(u8 *write_data, u32 Block,
328                            u16 Page, u16 PageCount)
329 {
330         int i;
331
332         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
333                        __FILE__, __LINE__, __func__);
334
335         if (Block >= DeviceInfo.wTotalBlocks)
336                 return FAIL;
337
338         if (Page + PageCount > DeviceInfo.wPagesPerBlock)
339                 return FAIL;
340
341         nand_dbg_print(NAND_DBG_DEBUG, "emu_Write_Page_Main: "
342                        "lba %u Page %u PageCount %u\n",
343                        (unsigned int)Block,
344                        (unsigned int)Page, (unsigned int)PageCount);
345
346         for (i = 0; i < PageCount; i++) {
347                 if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
348                         printk(KERN_ERR "Run out of memory\n");
349                         return FAIL;
350                 }
351                 memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]),
352                        write_data, DeviceInfo.wPageDataSize);
353                 write_data += DeviceInfo.wPageDataSize;
354                 Page++;
355         }
356
357         return PASS;
358 }
359
360 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
361 * Function:     emu_Read_Page_Main
362 * Inputs:       Read buffer address pointer
363 *               Block number
364 *               Page  number
365 *               Number of pages to process
366 * Outputs:      PASS=0 (notice 0=ok here)
367 * Description:  Read the data from the flash main area to the buffer
368 *
369 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
370 u16 emu_Read_Page_Main(u8 *read_data, u32 Block,
371                           u16 Page, u16 PageCount)
372 {
373         int i;
374
375         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
376                        __FILE__, __LINE__, __func__);
377
378         if (Block >= DeviceInfo.wTotalBlocks)
379                 return FAIL;
380
381         if (Page + PageCount > DeviceInfo.wPagesPerBlock)
382                 return FAIL;
383
384         nand_dbg_print(NAND_DBG_DEBUG, "emu_Read_Page_Main: "
385                        "lba %u Page %u PageCount %u\n",
386                        (unsigned int)Block,
387                        (unsigned int)Page, (unsigned int)PageCount);
388
389         for (i = 0; i < PageCount; i++) {
390                 if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
391                         memset(read_data, 0xFF, DeviceInfo.wPageDataSize);
392                 } else {
393                         memcpy(read_data,
394                                (u8 *) (flash_memory[Block * GLOB_LLD_PAGES
395                                                       + Page]),
396                                DeviceInfo.wPageDataSize);
397                 }
398                 read_data += DeviceInfo.wPageDataSize;
399                 Page++;
400         }
401
402         return PASS;
403 }
404
405 #ifndef ELDORA
406 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
407 * Function:     emu_Read_Page_Main_Spare
408 * Inputs:       Write Buffer
409 *                       Address
410 *                       Buffer size
411 * Outputs:      PASS=0 (notice 0=ok here)
412 * Description:          Read from flash main+spare area
413 *
414 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
415 u16 emu_Read_Page_Main_Spare(u8 *read_data, u32 Block,
416                                 u16 Page, u16 PageCount)
417 {
418         int i;
419
420         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
421                        __FILE__, __LINE__, __func__);
422
423         if (Block >= DeviceInfo.wTotalBlocks) {
424                 printk(KERN_ERR "Read Page Main+Spare "
425                        "Error: Block Address too big\n");
426                 return FAIL;
427         }
428
429         if (Page + PageCount > DeviceInfo.wPagesPerBlock) {
430                 printk(KERN_ERR "Read Page Main+Spare "
431                        "Error: Page number too big\n");
432                 return FAIL;
433         }
434
435         nand_dbg_print(NAND_DBG_DEBUG, "Read Page Main + Spare - "
436                        "No. of pages %u block %u start page %u\n",
437                        (unsigned int)PageCount,
438                        (unsigned int)Block, (unsigned int)Page);
439
440         for (i = 0; i < PageCount; i++) {
441                 if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
442                         memset(read_data, 0xFF, DeviceInfo.wPageSize);
443                 } else {
444                         memcpy(read_data, (u8 *) (flash_memory[Block *
445                                                                  GLOB_LLD_PAGES
446                                                                  + Page]),
447                                DeviceInfo.wPageSize);
448                 }
449
450                 read_data += DeviceInfo.wPageSize;
451                 Page++;
452         }
453
454         return PASS;
455 }
456
457 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
458 * Function:     emu_Write_Page_Main_Spare
459 * Inputs:       Write buffer
460 *                       address
461 *                       buffer length
462 * Outputs:      PASS=0 (notice 0=ok here)
463 * Description:          Write the buffer to main+spare area of flash
464 *
465 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
466 u16 emu_Write_Page_Main_Spare(u8 *write_data, u32 Block,
467                                  u16 Page, u16 page_count)
468 {
469         u16 i;
470
471         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
472                        __FILE__, __LINE__, __func__);
473
474         if (Block >= DeviceInfo.wTotalBlocks) {
475                 printk(KERN_ERR "Write Page Main + Spare "
476                        "Error: Block Address too big\n");
477                 return FAIL;
478         }
479
480         if (Page + page_count > DeviceInfo.wPagesPerBlock) {
481                 printk(KERN_ERR "Write Page Main + Spare "
482                        "Error: Page number too big\n");
483                 return FAIL;
484         }
485
486         nand_dbg_print(NAND_DBG_DEBUG, "Write Page Main+Spare - "
487                        "No. of pages %u block %u start page %u\n",
488                        (unsigned int)page_count,
489                        (unsigned int)Block, (unsigned int)Page);
490
491         for (i = 0; i < page_count; i++) {
492                 if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
493                         printk(KERN_ERR "Run out of memory!\n");
494                         return FAIL;
495                 }
496                 memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]),
497                        write_data, DeviceInfo.wPageSize);
498                 write_data += DeviceInfo.wPageSize;
499                 Page++;
500         }
501
502         return PASS;
503 }
504
505 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
506 * Function:     emu_Write_Page_Spare
507 * Inputs:       Write buffer
508 *                       Address
509 *                       buffer size
510 * Outputs:      PASS=0 (notice 0=ok here)
511 * Description:          Write the buffer in the spare area
512 *
513 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
514 u16 emu_Write_Page_Spare(u8 *write_data, u32 Block,
515                             u16 Page, u16 PageCount)
516 {
517         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
518                        __FILE__, __LINE__, __func__);
519
520         if (Block >= DeviceInfo.wTotalBlocks) {
521                 printk(KERN_ERR "Read Page Spare Error: "
522                        "Block Address too big\n");
523                 return FAIL;
524         }
525
526         if (Page + PageCount > DeviceInfo.wPagesPerBlock) {
527                 printk(KERN_ERR "Read Page Spare Error: "
528                        "Page number too big\n");
529                 return FAIL;
530         }
531
532         nand_dbg_print(NAND_DBG_DEBUG, "Write Page Spare- "
533                        "block %u page %u\n",
534                        (unsigned int)Block, (unsigned int)Page);
535
536         if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
537                 printk(KERN_ERR "Run out of memory!\n");
538                 return FAIL;
539         }
540
541         memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page] +
542                          DeviceInfo.wPageDataSize), write_data,
543                (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize));
544
545         return PASS;
546 }
547
548 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
549 * Function:     emu_Read_Page_Spare
550 * Inputs:       Write Buffer
551 *                       Address
552 *                       Buffer size
553 * Outputs:      PASS=0 (notice 0=ok here)
554 * Description:          Read data from the spare area
555 *
556 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
557 u16 emu_Read_Page_Spare(u8 *write_data, u32 Block,
558                            u16 Page, u16 PageCount)
559 {
560         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
561                        __FILE__, __LINE__, __func__);
562
563         if (Block >= DeviceInfo.wTotalBlocks) {
564                 printk(KERN_ERR "Read Page Spare "
565                        "Error: Block Address too big\n");
566                 return FAIL;
567         }
568
569         if (Page + PageCount > DeviceInfo.wPagesPerBlock) {
570                 printk(KERN_ERR "Read Page Spare "
571                        "Error: Page number too big\n");
572                 return FAIL;
573         }
574
575         nand_dbg_print(NAND_DBG_DEBUG, "Read Page Spare- "
576                        "block %u page %u\n",
577                        (unsigned int)Block, (unsigned int)Page);
578
579         if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
580                 memset(write_data, 0xFF,
581                        (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize));
582         } else {
583                 memcpy(write_data,
584                        (u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]
585                                  + DeviceInfo.wPageDataSize),
586                        (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize));
587         }
588
589         return PASS;
590 }
591
592 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
593 * Function:     emu_Enable_Disable_Interrupts
594 * Inputs:       enable or disable
595 * Outputs:      none
596 * Description:  NOP
597 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
598 void emu_Enable_Disable_Interrupts(u16 INT_ENABLE)
599 {
600         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
601                        __FILE__, __LINE__, __func__);
602 }
603
604 u16 emu_Get_Bad_Block(u32 block)
605 {
606         return 0;
607 }
608
609 #if CMD_DMA
610 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
611 * Support for CDMA functions
612 ************************************
613 *       emu_CDMA_Flash_Init
614 *           CDMA_process_data command   (use LLD_CDMA)
615 *           CDMA_MemCopy_CMD            (use LLD_CDMA)
616 *       emu_CDMA_execute all commands
617 *       emu_CDMA_Event_Status
618 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
619 u16 emu_CDMA_Flash_Init(void)
620 {
621         u16 i;
622
623         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
624                        __FILE__, __LINE__, __func__);
625
626         for (i = 0; i < MAX_DESCS + MAX_CHANS; i++) {
627                 PendingCMD[i].CMD = 0;
628                 PendingCMD[i].Tag = 0;
629                 PendingCMD[i].DataAddr = 0;
630                 PendingCMD[i].Block = 0;
631                 PendingCMD[i].Page = 0;
632                 PendingCMD[i].PageCount = 0;
633                 PendingCMD[i].DataDestAddr = 0;
634                 PendingCMD[i].DataSrcAddr = 0;
635                 PendingCMD[i].MemCopyByteCnt = 0;
636                 PendingCMD[i].ChanSync[0] = 0;
637                 PendingCMD[i].ChanSync[1] = 0;
638                 PendingCMD[i].ChanSync[2] = 0;
639                 PendingCMD[i].ChanSync[3] = 0;
640                 PendingCMD[i].ChanSync[4] = 0;
641                 PendingCMD[i].Status = 3;
642         }
643
644         return PASS;
645 }
646
647 static void emu_isr(int irq, void *dev_id)
648 {
649         /* TODO:  ... */
650 }
651
652 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
653 * Function:     CDMA_Execute_CMDs
654 * Inputs:       tag_count:  the number of pending cmds to do
655 * Outputs:      PASS/FAIL
656 * Description:  execute each command in the pending CMD array
657 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
658 u16 emu_CDMA_Execute_CMDs(u16 tag_count)
659 {
660         u16 i, j;
661         u8 CMD;         /* cmd parameter */
662         u8 *data;
663         u32 block;
664         u16 page;
665         u16 count;
666         u16 status = PASS;
667
668         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
669                        __FILE__, __LINE__, __func__);
670
671         nand_dbg_print(NAND_DBG_TRACE, "At start of Execute CMDs: "
672                        "Tag Count %u\n", tag_count);
673
674         for (i = 0; i < totalUsedBanks; i++) {
675                 PendingCMD[i].CMD = DUMMY_CMD;
676                 PendingCMD[i].Tag = 0xFF;
677                 PendingCMD[i].Block =
678                     (DeviceInfo.wTotalBlocks / totalUsedBanks) * i;
679
680                 for (j = 0; j <= MAX_CHANS; j++)
681                         PendingCMD[i].ChanSync[j] = 0;
682         }
683
684         CDMA_Execute_CMDs(tag_count);
685
686         print_pending_cmds(tag_count);
687
688 #if DEBUG_SYNC
689         }
690         debug_sync_cnt++;
691 #endif
692
693         for (i = MAX_CHANS;
694              i < tag_count + MAX_CHANS; i++) {
695                 CMD = PendingCMD[i].CMD;
696                 data = PendingCMD[i].DataAddr;
697                 block = PendingCMD[i].Block;
698                 page = PendingCMD[i].Page;
699                 count = PendingCMD[i].PageCount;
700
701                 switch (CMD) {
702                 case ERASE_CMD:
703                         emu_Erase_Block(block);
704                         PendingCMD[i].Status = PASS;
705                         break;
706                 case WRITE_MAIN_CMD:
707                         emu_Write_Page_Main(data, block, page, count);
708                         PendingCMD[i].Status = PASS;
709                         break;
710                 case WRITE_MAIN_SPARE_CMD:
711                         emu_Write_Page_Main_Spare(data, block, page, count);
712                         PendingCMD[i].Status = PASS;
713                         break;
714                 case READ_MAIN_CMD:
715                         emu_Read_Page_Main(data, block, page, count);
716                         PendingCMD[i].Status = PASS;
717                         break;
718                 case MEMCOPY_CMD:
719                         memcpy(PendingCMD[i].DataDestAddr,
720                                PendingCMD[i].DataSrcAddr,
721                                PendingCMD[i].MemCopyByteCnt);
722                 case DUMMY_CMD:
723                         PendingCMD[i].Status = PASS;
724                         break;
725                 default:
726                         PendingCMD[i].Status = FAIL;
727                         break;
728                 }
729         }
730
731         /*
732          * Temperory adding code to reset PendingCMD array for basic testing.
733          * It should be done at the end of  event status function.
734          */
735         for (i = tag_count + MAX_CHANS; i < MAX_DESCS; i++) {
736                 PendingCMD[i].CMD = 0;
737                 PendingCMD[i].Tag = 0;
738                 PendingCMD[i].DataAddr = 0;
739                 PendingCMD[i].Block = 0;
740                 PendingCMD[i].Page = 0;
741                 PendingCMD[i].PageCount = 0;
742                 PendingCMD[i].DataDestAddr = 0;
743                 PendingCMD[i].DataSrcAddr = 0;
744                 PendingCMD[i].MemCopyByteCnt = 0;
745                 PendingCMD[i].ChanSync[0] = 0;
746                 PendingCMD[i].ChanSync[1] = 0;
747                 PendingCMD[i].ChanSync[2] = 0;
748                 PendingCMD[i].ChanSync[3] = 0;
749                 PendingCMD[i].ChanSync[4] = 0;
750                 PendingCMD[i].Status = CMD_NOT_DONE;
751         }
752
753         nand_dbg_print(NAND_DBG_TRACE, "At end of Execute CMDs.\n");
754
755         emu_isr(0, 0); /* This is a null isr now. Need fill it in future */
756
757         return status;
758 }
759
760 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
761 * Function:     emu_Event_Status
762 * Inputs:       none
763 * Outputs:      Event_Status code
764 * Description:  This function can also be used to force errors
765 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
766 u16 emu_CDMA_Event_Status(void)
767 {
768         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
769                        __FILE__, __LINE__, __func__);
770
771         return EVENT_PASS;
772 }
773
774 #endif /* CMD_DMA */
775 #endif /* !ELDORA */
776 #endif /* FLASH_EMU */