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