]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/staging/spectra/lld_emu.c
OMAP: DSS2: Introduce omap_channel as an omap_dss_device parameter, add new overlay...
[mv-sheeva.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] = (u8 *)vmalloc(GLOB_LLD_PAGE_SIZE *
184                                                    GLOB_LLD_BLOCKS *
185                                                    GLOB_LLD_PAGES *
186                                                    sizeof(u8));
187         if (!flash_memory[0]) {
188                 printk(KERN_ERR "Fail to allocate memory "
189                        "for nand emulator!\n");
190                 return ERR;
191         }
192
193         memset((char *)(flash_memory[0]), 0xFF,
194                GLOB_LLD_PAGE_SIZE * GLOB_LLD_BLOCKS * GLOB_LLD_PAGES *
195                sizeof(u8));
196
197         for (i = 1; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++)
198                 flash_memory[i] = flash_memory[i - 1] + GLOB_LLD_PAGE_SIZE;
199
200         emu_load_file_to_mem(); /* Load nand emu file to mem */
201
202         return PASS;
203 }
204
205 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
206 * Function:     emu_Flash_Release
207 * Inputs:       none
208 * Outputs:      PASS=0 (notice 0=ok here)
209 * Description:          Releases the flash.
210 *
211 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
212 int emu_Flash_Release(void)
213 {
214         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
215                        __FILE__, __LINE__, __func__);
216
217         emu_write_mem_to_file();  /* Write back mem to nand emu file */
218
219         vfree(flash_memory[0]);
220         return PASS;
221 }
222
223 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
224 * Function:     emu_Read_Device_ID
225 * Inputs:       none
226 * Outputs:      PASS=1 FAIL=0
227 * Description:  Reads the info from the controller registers.
228 *               Sets up DeviceInfo structure with device parameters
229 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
230
231 u16 emu_Read_Device_ID(void)
232 {
233         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
234                        __FILE__, __LINE__, __func__);
235
236         DeviceInfo.wDeviceMaker = 0;
237         DeviceInfo.wDeviceType = 8;
238         DeviceInfo.wSpectraStartBlock = 36;
239         DeviceInfo.wSpectraEndBlock = GLOB_LLD_BLOCKS - 1;
240         DeviceInfo.wTotalBlocks = GLOB_LLD_BLOCKS;
241         DeviceInfo.wPagesPerBlock = GLOB_LLD_PAGES;
242         DeviceInfo.wPageSize = GLOB_LLD_PAGE_SIZE;
243         DeviceInfo.wPageDataSize = GLOB_LLD_PAGE_DATA_SIZE;
244         DeviceInfo.wPageSpareSize = GLOB_LLD_PAGE_SIZE -
245             GLOB_LLD_PAGE_DATA_SIZE;
246         DeviceInfo.wBlockSize = DeviceInfo.wPageSize * GLOB_LLD_PAGES;
247         DeviceInfo.wBlockDataSize = DeviceInfo.wPageDataSize * GLOB_LLD_PAGES;
248         DeviceInfo.wDataBlockNum = (u32) (DeviceInfo.wSpectraEndBlock -
249                                                 DeviceInfo.wSpectraStartBlock
250                                                 + 1);
251         DeviceInfo.MLCDevice = 1; /* Emulate MLC device */
252         DeviceInfo.nBitsInPageNumber =
253                 (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock);
254         DeviceInfo.nBitsInPageDataSize =
255                 (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize);
256         DeviceInfo.nBitsInBlockDataSize =
257                 (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize);
258
259 #if CMD_DMA
260         totalUsedBanks = 4;
261         valid_banks[0] = 1;
262         valid_banks[1] = 1;
263         valid_banks[2] = 1;
264         valid_banks[3] = 1;
265 #endif
266
267         return PASS;
268 }
269
270 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
271 * Function:     emu_Flash_Reset
272 * Inputs:       none
273 * Outputs:      PASS=0 (notice 0=ok here)
274 * Description:          Reset the flash
275 *
276 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
277 u16 emu_Flash_Reset(void)
278 {
279         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
280                        __FILE__, __LINE__, __func__);
281
282         return PASS;
283 }
284
285 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
286 * Function:     emu_Erase_Block
287 * Inputs:       Address
288 * Outputs:      PASS=0 (notice 0=ok here)
289 * Description:          Erase a block
290 *
291 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
292 u16 emu_Erase_Block(u32 block_add)
293 {
294         int i;
295
296         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
297                        __FILE__, __LINE__, __func__);
298
299         if (block_add >= DeviceInfo.wTotalBlocks) {
300                 printk(KERN_ERR "emu_Erase_Block error! "
301                        "Too big block address: %d\n", block_add);
302                 return FAIL;
303         }
304
305         nand_dbg_print(NAND_DBG_DEBUG, "Erasing block %d\n",
306                 (int)block_add);
307
308         for (i = block_add * GLOB_LLD_PAGES;
309              i < ((block_add + 1) * GLOB_LLD_PAGES); i++) {
310                 if (flash_memory[i]) {
311                         memset((u8 *)(flash_memory[i]), 0xFF,
312                                DeviceInfo.wPageSize * sizeof(u8));
313                 }
314         }
315
316         return PASS;
317 }
318
319 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
320 * Function:     emu_Write_Page_Main
321 * Inputs:       Write buffer address pointer
322 *               Block number
323 *               Page  number
324 *               Number of pages to process
325 * Outputs:      PASS=0 (notice 0=ok here)
326 * Description:  Write the data in the buffer to main area of flash
327 *
328 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
329 u16 emu_Write_Page_Main(u8 *write_data, u32 Block,
330                            u16 Page, u16 PageCount)
331 {
332         int i;
333
334         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
335                        __FILE__, __LINE__, __func__);
336
337         if (Block >= DeviceInfo.wTotalBlocks)
338                 return FAIL;
339
340         if (Page + PageCount > DeviceInfo.wPagesPerBlock)
341                 return FAIL;
342
343         nand_dbg_print(NAND_DBG_DEBUG, "emu_Write_Page_Main: "
344                        "lba %u Page %u PageCount %u\n",
345                        (unsigned int)Block,
346                        (unsigned int)Page, (unsigned int)PageCount);
347
348         for (i = 0; i < PageCount; i++) {
349                 if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
350                         printk(KERN_ERR "Run out of memory\n");
351                         return FAIL;
352                 }
353                 memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]),
354                        write_data, DeviceInfo.wPageDataSize);
355                 write_data += DeviceInfo.wPageDataSize;
356                 Page++;
357         }
358
359         return PASS;
360 }
361
362 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
363 * Function:     emu_Read_Page_Main
364 * Inputs:       Read buffer address pointer
365 *               Block number
366 *               Page  number
367 *               Number of pages to process
368 * Outputs:      PASS=0 (notice 0=ok here)
369 * Description:  Read the data from the flash main area to the buffer
370 *
371 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
372 u16 emu_Read_Page_Main(u8 *read_data, u32 Block,
373                           u16 Page, u16 PageCount)
374 {
375         int i;
376
377         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
378                        __FILE__, __LINE__, __func__);
379
380         if (Block >= DeviceInfo.wTotalBlocks)
381                 return FAIL;
382
383         if (Page + PageCount > DeviceInfo.wPagesPerBlock)
384                 return FAIL;
385
386         nand_dbg_print(NAND_DBG_DEBUG, "emu_Read_Page_Main: "
387                        "lba %u Page %u PageCount %u\n",
388                        (unsigned int)Block,
389                        (unsigned int)Page, (unsigned int)PageCount);
390
391         for (i = 0; i < PageCount; i++) {
392                 if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
393                         memset(read_data, 0xFF, DeviceInfo.wPageDataSize);
394                 } else {
395                         memcpy(read_data,
396                                (u8 *) (flash_memory[Block * GLOB_LLD_PAGES
397                                                       + Page]),
398                                DeviceInfo.wPageDataSize);
399                 }
400                 read_data += DeviceInfo.wPageDataSize;
401                 Page++;
402         }
403
404         return PASS;
405 }
406
407 #ifndef ELDORA
408 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
409 * Function:     emu_Read_Page_Main_Spare
410 * Inputs:       Write Buffer
411 *                       Address
412 *                       Buffer size
413 * Outputs:      PASS=0 (notice 0=ok here)
414 * Description:          Read from flash main+spare area
415 *
416 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
417 u16 emu_Read_Page_Main_Spare(u8 *read_data, u32 Block,
418                                 u16 Page, u16 PageCount)
419 {
420         int i;
421
422         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
423                        __FILE__, __LINE__, __func__);
424
425         if (Block >= DeviceInfo.wTotalBlocks) {
426                 printk(KERN_ERR "Read Page Main+Spare "
427                        "Error: Block Address too big\n");
428                 return FAIL;
429         }
430
431         if (Page + PageCount > DeviceInfo.wPagesPerBlock) {
432                 printk(KERN_ERR "Read Page Main+Spare "
433                        "Error: Page number too big\n");
434                 return FAIL;
435         }
436
437         nand_dbg_print(NAND_DBG_DEBUG, "Read Page Main + Spare - "
438                        "No. of pages %u block %u start page %u\n",
439                        (unsigned int)PageCount,
440                        (unsigned int)Block, (unsigned int)Page);
441
442         for (i = 0; i < PageCount; i++) {
443                 if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
444                         memset(read_data, 0xFF, DeviceInfo.wPageSize);
445                 } else {
446                         memcpy(read_data, (u8 *) (flash_memory[Block *
447                                                                  GLOB_LLD_PAGES
448                                                                  + Page]),
449                                DeviceInfo.wPageSize);
450                 }
451
452                 read_data += DeviceInfo.wPageSize;
453                 Page++;
454         }
455
456         return PASS;
457 }
458
459 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
460 * Function:     emu_Write_Page_Main_Spare
461 * Inputs:       Write buffer
462 *                       address
463 *                       buffer length
464 * Outputs:      PASS=0 (notice 0=ok here)
465 * Description:          Write the buffer to main+spare area of flash
466 *
467 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
468 u16 emu_Write_Page_Main_Spare(u8 *write_data, u32 Block,
469                                  u16 Page, u16 page_count)
470 {
471         u16 i;
472
473         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
474                        __FILE__, __LINE__, __func__);
475
476         if (Block >= DeviceInfo.wTotalBlocks) {
477                 printk(KERN_ERR "Write Page Main + Spare "
478                        "Error: Block Address too big\n");
479                 return FAIL;
480         }
481
482         if (Page + page_count > DeviceInfo.wPagesPerBlock) {
483                 printk(KERN_ERR "Write Page Main + Spare "
484                        "Error: Page number too big\n");
485                 return FAIL;
486         }
487
488         nand_dbg_print(NAND_DBG_DEBUG, "Write Page Main+Spare - "
489                        "No. of pages %u block %u start page %u\n",
490                        (unsigned int)page_count,
491                        (unsigned int)Block, (unsigned int)Page);
492
493         for (i = 0; i < page_count; i++) {
494                 if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
495                         printk(KERN_ERR "Run out of memory!\n");
496                         return FAIL;
497                 }
498                 memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]),
499                        write_data, DeviceInfo.wPageSize);
500                 write_data += DeviceInfo.wPageSize;
501                 Page++;
502         }
503
504         return PASS;
505 }
506
507 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
508 * Function:     emu_Write_Page_Spare
509 * Inputs:       Write buffer
510 *                       Address
511 *                       buffer size
512 * Outputs:      PASS=0 (notice 0=ok here)
513 * Description:          Write the buffer in the spare area
514 *
515 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
516 u16 emu_Write_Page_Spare(u8 *write_data, u32 Block,
517                             u16 Page, u16 PageCount)
518 {
519         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
520                        __FILE__, __LINE__, __func__);
521
522         if (Block >= DeviceInfo.wTotalBlocks) {
523                 printk(KERN_ERR "Read Page Spare Error: "
524                        "Block Address too big\n");
525                 return FAIL;
526         }
527
528         if (Page + PageCount > DeviceInfo.wPagesPerBlock) {
529                 printk(KERN_ERR "Read Page Spare Error: "
530                        "Page number too big\n");
531                 return FAIL;
532         }
533
534         nand_dbg_print(NAND_DBG_DEBUG, "Write Page Spare- "
535                        "block %u page %u\n",
536                        (unsigned int)Block, (unsigned int)Page);
537
538         if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
539                 printk(KERN_ERR "Run out of memory!\n");
540                 return FAIL;
541         }
542
543         memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page] +
544                          DeviceInfo.wPageDataSize), write_data,
545                (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize));
546
547         return PASS;
548 }
549
550 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
551 * Function:     emu_Read_Page_Spare
552 * Inputs:       Write Buffer
553 *                       Address
554 *                       Buffer size
555 * Outputs:      PASS=0 (notice 0=ok here)
556 * Description:          Read data from the spare area
557 *
558 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
559 u16 emu_Read_Page_Spare(u8 *write_data, u32 Block,
560                            u16 Page, u16 PageCount)
561 {
562         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
563                        __FILE__, __LINE__, __func__);
564
565         if (Block >= DeviceInfo.wTotalBlocks) {
566                 printk(KERN_ERR "Read Page Spare "
567                        "Error: Block Address too big\n");
568                 return FAIL;
569         }
570
571         if (Page + PageCount > DeviceInfo.wPagesPerBlock) {
572                 printk(KERN_ERR "Read Page Spare "
573                        "Error: Page number too big\n");
574                 return FAIL;
575         }
576
577         nand_dbg_print(NAND_DBG_DEBUG, "Read Page Spare- "
578                        "block %u page %u\n",
579                        (unsigned int)Block, (unsigned int)Page);
580
581         if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
582                 memset(write_data, 0xFF,
583                        (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize));
584         } else {
585                 memcpy(write_data,
586                        (u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]
587                                  + DeviceInfo.wPageDataSize),
588                        (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize));
589         }
590
591         return PASS;
592 }
593
594 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
595 * Function:     emu_Enable_Disable_Interrupts
596 * Inputs:       enable or disable
597 * Outputs:      none
598 * Description:  NOP
599 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
600 void emu_Enable_Disable_Interrupts(u16 INT_ENABLE)
601 {
602         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
603                        __FILE__, __LINE__, __func__);
604 }
605
606 u16 emu_Get_Bad_Block(u32 block)
607 {
608         return 0;
609 }
610
611 #if CMD_DMA
612 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
613 * Support for CDMA functions
614 ************************************
615 *       emu_CDMA_Flash_Init
616 *           CDMA_process_data command   (use LLD_CDMA)
617 *           CDMA_MemCopy_CMD            (use LLD_CDMA)
618 *       emu_CDMA_execute all commands
619 *       emu_CDMA_Event_Status
620 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
621 u16 emu_CDMA_Flash_Init(void)
622 {
623         u16 i;
624
625         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
626                        __FILE__, __LINE__, __func__);
627
628         for (i = 0; i < MAX_DESCS + MAX_CHANS; i++) {
629                 PendingCMD[i].CMD = 0;
630                 PendingCMD[i].Tag = 0;
631                 PendingCMD[i].DataAddr = 0;
632                 PendingCMD[i].Block = 0;
633                 PendingCMD[i].Page = 0;
634                 PendingCMD[i].PageCount = 0;
635                 PendingCMD[i].DataDestAddr = 0;
636                 PendingCMD[i].DataSrcAddr = 0;
637                 PendingCMD[i].MemCopyByteCnt = 0;
638                 PendingCMD[i].ChanSync[0] = 0;
639                 PendingCMD[i].ChanSync[1] = 0;
640                 PendingCMD[i].ChanSync[2] = 0;
641                 PendingCMD[i].ChanSync[3] = 0;
642                 PendingCMD[i].ChanSync[4] = 0;
643                 PendingCMD[i].Status = 3;
644         }
645
646         return PASS;
647 }
648
649 static void emu_isr(int irq, void *dev_id)
650 {
651         /* TODO:  ... */
652 }
653
654 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
655 * Function:     CDMA_Execute_CMDs
656 * Inputs:       tag_count:  the number of pending cmds to do
657 * Outputs:      PASS/FAIL
658 * Description:  execute each command in the pending CMD array
659 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
660 u16 emu_CDMA_Execute_CMDs(u16 tag_count)
661 {
662         u16 i, j;
663         u8 CMD;         /* cmd parameter */
664         u8 *data;
665         u32 block;
666         u16 page;
667         u16 count;
668         u16 status = PASS;
669
670         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
671                        __FILE__, __LINE__, __func__);
672
673         nand_dbg_print(NAND_DBG_TRACE, "At start of Execute CMDs: "
674                        "Tag Count %u\n", tag_count);
675
676         for (i = 0; i < totalUsedBanks; i++) {
677                 PendingCMD[i].CMD = DUMMY_CMD;
678                 PendingCMD[i].Tag = 0xFF;
679                 PendingCMD[i].Block =
680                     (DeviceInfo.wTotalBlocks / totalUsedBanks) * i;
681
682                 for (j = 0; j <= MAX_CHANS; j++)
683                         PendingCMD[i].ChanSync[j] = 0;
684         }
685
686         CDMA_Execute_CMDs(tag_count);
687
688         print_pending_cmds(tag_count);
689
690 #if DEBUG_SYNC
691         }
692         debug_sync_cnt++;
693 #endif
694
695         for (i = MAX_CHANS;
696              i < tag_count + MAX_CHANS; i++) {
697                 CMD = PendingCMD[i].CMD;
698                 data = PendingCMD[i].DataAddr;
699                 block = PendingCMD[i].Block;
700                 page = PendingCMD[i].Page;
701                 count = PendingCMD[i].PageCount;
702
703                 switch (CMD) {
704                 case ERASE_CMD:
705                         emu_Erase_Block(block);
706                         PendingCMD[i].Status = PASS;
707                         break;
708                 case WRITE_MAIN_CMD:
709                         emu_Write_Page_Main(data, block, page, count);
710                         PendingCMD[i].Status = PASS;
711                         break;
712                 case WRITE_MAIN_SPARE_CMD:
713                         emu_Write_Page_Main_Spare(data, block, page, count);
714                         PendingCMD[i].Status = PASS;
715                         break;
716                 case READ_MAIN_CMD:
717                         emu_Read_Page_Main(data, block, page, count);
718                         PendingCMD[i].Status = PASS;
719                         break;
720                 case MEMCOPY_CMD:
721                         memcpy(PendingCMD[i].DataDestAddr,
722                                PendingCMD[i].DataSrcAddr,
723                                PendingCMD[i].MemCopyByteCnt);
724                 case DUMMY_CMD:
725                         PendingCMD[i].Status = PASS;
726                         break;
727                 default:
728                         PendingCMD[i].Status = FAIL;
729                         break;
730                 }
731         }
732
733         /*
734          * Temperory adding code to reset PendingCMD array for basic testing.
735          * It should be done at the end of  event status function.
736          */
737         for (i = tag_count + MAX_CHANS; i < MAX_DESCS; i++) {
738                 PendingCMD[i].CMD = 0;
739                 PendingCMD[i].Tag = 0;
740                 PendingCMD[i].DataAddr = 0;
741                 PendingCMD[i].Block = 0;
742                 PendingCMD[i].Page = 0;
743                 PendingCMD[i].PageCount = 0;
744                 PendingCMD[i].DataDestAddr = 0;
745                 PendingCMD[i].DataSrcAddr = 0;
746                 PendingCMD[i].MemCopyByteCnt = 0;
747                 PendingCMD[i].ChanSync[0] = 0;
748                 PendingCMD[i].ChanSync[1] = 0;
749                 PendingCMD[i].ChanSync[2] = 0;
750                 PendingCMD[i].ChanSync[3] = 0;
751                 PendingCMD[i].ChanSync[4] = 0;
752                 PendingCMD[i].Status = CMD_NOT_DONE;
753         }
754
755         nand_dbg_print(NAND_DBG_TRACE, "At end of Execute CMDs.\n");
756
757         emu_isr(0, 0); /* This is a null isr now. Need fill it in future */
758
759         return status;
760 }
761
762 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
763 * Function:     emu_Event_Status
764 * Inputs:       none
765 * Outputs:      Event_Status code
766 * Description:  This function can also be used to force errors
767 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
768 u16 emu_CDMA_Event_Status(void)
769 {
770         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
771                        __FILE__, __LINE__, __func__);
772
773         return EVENT_PASS;
774 }
775
776 #endif /* CMD_DMA */
777 #endif /* !ELDORA */
778 #endif /* FLASH_EMU */