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 */
emu_load_file_to_mem(void)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 */
emu_write_mem_to_file(void)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 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
emu_Flash_Init(void)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 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
emu_Flash_Release(void)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 
emu_Read_Device_ID(void)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 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
emu_Flash_Reset(void)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 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
emu_Erase_Block(u32 block_add)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 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
emu_Write_Page_Main(u8 * write_data,u32 Block,u16 Page,u16 PageCount)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 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
emu_Read_Page_Main(u8 * read_data,u32 Block,u16 Page,u16 PageCount)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 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
emu_Read_Page_Main_Spare(u8 * read_data,u32 Block,u16 Page,u16 PageCount)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 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
emu_Write_Page_Main_Spare(u8 * write_data,u32 Block,u16 Page,u16 page_count)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 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
emu_Write_Page_Spare(u8 * write_data,u32 Block,u16 Page,u16 PageCount)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 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
emu_Read_Page_Spare(u8 * write_data,u32 Block,u16 Page,u16 PageCount)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 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
emu_Enable_Disable_Interrupts(u16 INT_ENABLE)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 
emu_Get_Bad_Block(u32 block)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 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
emu_CDMA_Flash_Init(void)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 
emu_isr(int irq,void * dev_id)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 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
emu_CDMA_Execute_CMDs(u16 tag_count)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 */
777