1 #include <asm/arch/sci_types.h>
3 #include <linux/mtd/mtd.h>
4 #include <linux/mtd/nand.h>
5 #include "yaffs_format_data_translate.h"
6 #define TRANS_CODE_SIZE (12 * 1024)
7 #define DATA_BUFFER_SIZE (TRANS_CODE_SIZE * 2)
10 #define NAND_SYSTEM_ERROR 1
11 #define NAND_UNKNOWN_DEVICE 2
12 #define NAND_INVALID_DEVICE_SIZE 3
13 #define NAND_INCOMPATIBLE_PART 4
14 #define NAND_INVALID_ADDR 5
15 #define NAND_INVALID_SIZE 6
16 extern int nand_curr_device;
17 unsigned long yaffs_buffer_size = 0;
18 unsigned long g_BigSize = 0;
19 unsigned long g_ReadBufLen = 0;
20 unsigned long code_yaffs_buflen = 0;
21 unsigned long code_yaffs_onewrite = 0;
22 unsigned char *g_BigBUF = NULL;
24 int nand_write_to_device(int dev_id,unsigned int size, unsigned char *buf)
26 struct mtd_info *nand;
27 struct nand_chip *chip;
29 int cur_offset = get_end_write_pos();
31 if ((dev_id < 0) || (dev_id >= CONFIG_SYS_MAX_NAND_DEVICE))
32 return NAND_SYSTEM_ERROR;
33 nand = &nand_info[dev_id];
35 //find a good block to write
36 while(!(cur_offset & (nand->erasesize-1))) {
37 // printf("function: %s to check bad block, check address 0x%x\n", __FUNCTION__,cur_offset&(~(nand->erasesize - 1)));
38 if (nand_block_isbad(nand, cur_offset&(~(nand->erasesize - 1)))) {
39 printf("%s skip bad block 0x%x\n", __FUNCTION__, cur_offset&(~(nand->erasesize - 1)));
40 cur_offset = (cur_offset + nand->erasesize)&(~(nand->erasesize - 1));
46 if(size != (nand->writesize + nand->oobsize)){
47 return NAND_INVALID_SIZE;
50 chip->ops.mode = MTD_OOB_AUTO;
51 chip->ops.len = nand->writesize;
52 chip->ops.datbuf = (uint8_t *)buf;
53 chip->ops.oobbuf = (uint8_t *)buf + nand->writesize;
54 chip->ops.ooblen = sizeof(yaffs_PackedTags2);
55 chip->ops.ooboffs = 0;
57 // printf("call nand_do_write_ops cur_offset = 0x%x\n",cur_offset );
58 ret = nand_do_write_ops(nand, (unsigned long long)cur_offset, &(chip->ops));
60 cur_offset += nand->writesize;
62 printf("\nwrite error, mark bad block : 0x%08x\n", cur_offset);
63 nand->block_markbad(nand, cur_offset&~(nand->erasesize - 1));
64 printf("find new good partition to move and write data again\n");
65 move2goodblk(nand, 1);
66 printf("move and write end. new write pos : 0x%08x\n", cur_offset);
69 set_current_write_pos(cur_offset);
73 int init_yaffs_convert_variables(int writesize,int oobsize,int is_yaffs)
76 yaffs_buffer_size = (DATA_BUFFER_SIZE + (DATA_BUFFER_SIZE / writesize) * oobsize);
81 code_yaffs_buflen = DATA_BUFFER_SIZE;
82 code_yaffs_onewrite = writesize;
83 } else if (is_yaffs == 1) {
84 code_yaffs_buflen = yaffs_buffer_size;
85 code_yaffs_onewrite = writesize + oobsize;
90 g_BigBUF = (unsigned char *)malloc(yaffs_buffer_size);
92 if (g_BigBUF == NULL) {
93 printf("malloc is wrong : %d\n", yaffs_buffer_size);
94 ret = NAND_SYSTEM_ERROR;
97 memset(g_BigBUF, 0xff, yaffs_buffer_size);
99 printf("code_yaffs_onewrite = %d code_yaffs_buflen = %d yaffs_buffer_size = %d\n", code_yaffs_onewrite, code_yaffs_buflen, yaffs_buffer_size);
103 int yaffs2_convertAndWrite(int last_flag,int writesize,int oobsize,char *buffer)
105 yaffs_page src = {0};
106 yaffs_page dst = {0};
108 unsigned int size_threshold = 0;
109 int ret = NAND_SUCCESS;
110 unsigned int remaindata = 0;
114 src.p_pagedata = g_BigBUF;
115 dst.oobsize = oobsize;
116 dst.pagesize = writesize;
117 dst.p_pagedata = buffer;
118 count = dst.pagesize/src.pagesize;
119 size_threshold = (src.oobsize + src.pagesize)*count;
121 size_threshold = src.oobsize + src.pagesize;
123 while ((g_BigSize - g_ReadBufLen) >= size_threshold) {
124 //we have received more than one page data.
125 count = yaffs_page_translate(&src, &dst);
126 // printf("trans_count= 0x%x ,Big=0x%x ,read=0x%x, threshod=0x%x\n",count,g_BigSize,g_ReadBufLen,size_threshold);
128 //update global buffer
129 g_ReadBufLen += count*(src.oobsize + src.pagesize);
130 //update src data stream pointer
131 src.p_pagedata = (unsigned char*)&src.p_pagedata[count*(src.oobsize + src.pagesize)];
132 //restore one page data
133 ret = nand_write_to_device(nand_curr_device,dst.pagesize+ dst.oobsize, dst.p_pagedata);
134 if(ret != NAND_SUCCESS){
135 return NAND_SYSTEM_ERROR;
140 remaindata = g_BigSize - g_ReadBufLen;
141 memcpy(g_BigBUF, g_BigBUF + g_ReadBufLen, remaindata);
142 memset(g_BigBUF + remaindata, 0xff, yaffs_buffer_size - remaindata);
143 g_BigSize = remaindata;
149 void save_to_convert_buffer(char *buffer, int size)
151 memcpy((g_BigBUF + g_BigSize), buffer, size);
153 //printf("g_BigSize = %d code_yaffs_buflen=%d\n",g_BigSize,code_yaffs_buflen);
155 int convert_buffer_is_full(void)
157 if (g_BigSize < (code_yaffs_buflen / 2))
161 void set_convert_buffer(char *buffer,int size)