tizen 2.4 release
[kernel/u-boot-tm1.git] / drivers / mtd / sprd_fill_spl.c
1
2 #include <linux/mtd/mtd.h>
3 #include <nand.h>
4 #include <linux/mtd/nand.h>
5 #include <common.h>
6 #if defined CONFIG_NAND_DOLPHIN 
7 #include <asm/arch/sprd_nfc_reg_v2.h>
8 #elif defined CONFIG_NAND_SC8830
9 #include <asm/arch/sprd_nfc_reg_v2.h>
10 #elif defined CONFIG_NAND_TIGER
11 #include <asm/arch/sprd_nfc_reg_v2.h>
12 #elif defined CONFIG_NAND_SC8810
13 #include <asm/arch/regs_nfc.h>
14 #else
15 #include "asm/arch/nand_controller.h"
16 #endif
17
18 #define BOOTLOADER_HEADER_OFFSET    32
19 #define CONFIG_SYS_SPL_ECC_POS    8
20 #if defined CONFIG_SPX30G
21 #define MAX_SPL_SIZE    0x8000
22 #else
23 #define MAX_SPL_SIZE    0x6000
24 #endif
25
26
27 #if defined CONFIG_NAND_SC7710G2
28 struct bootloader_header
29 {
30         uint32_t version; //version, fot tiger this member must be 0
31         uint32_t magic_num; //0xaa55a5a5
32         uint32_t sct_size; //
33         uint32_t hash_len;//word length, only used when secure boot enable
34         uint32_t acycle; // 3, 4, 5
35         uint32_t bus_width; //0 ,1
36         uint32_t spare_size; //spare part sise for one sector
37         uint32_t ecc_mode; //0--1bit, 1--2bit,2--4bit,3--8bit,4--12bit, 5--16bit, 6--24bit
38         uint32_t ecc_pos; // ecc postion at spare part
39         uint32_t sct_per_page; //sector per page
40         uint32_t info_pos;
41         uint32_t info_size;
42         uint32_t ecc_value[27];
43 };
44
45 /*
46  * spare info data is don't used at the romcode, so the fdl only set the s_info size to 1, and the data value 0xff
47  */
48 void set_header_info(u8 *bl_data, struct mtd_info *nand, int ecc_pos)
49 {
50         struct bootloader_header *header;
51         struct nand_chip *chip = nand->priv;
52         struct sc8810_ecc_param param;
53         u8 ecc[44];
54         header = (struct bootloader_header *)(bl_data + BOOTLOADER_HEADER_OFFSET);
55         memset(header, 0, sizeof(struct bootloader_header));
56         memset(ecc, 0xff, sizeof(ecc));
57
58         header->version = 0x1;
59         header->sct_size = chip->ecc.size;
60         header->hash_len = 0x400;
61         if (chip->options & NAND_BUSWIDTH_16){
62                 header->bus_width = 1;
63         }
64         if(nand->writesize > 512) {
65                 if (chip->chipsize > (128 << 20)){
66                         header->acycle = 5;
67                 }
68                 else{
69                         header->acycle = 4;
70                 }
71         }
72         else{
73                 /* One more address cycle for devices > 32MiB */
74                 if (chip->chipsize > (32 << 20)){
75                         header->acycle = 3;
76                 }
77                 else{
78                         header->acycle = 3;
79                 }
80         }
81
82         header->acycle -= 3;
83
84         header->magic_num = 0xaa55a5a5;
85         header->spare_size = (nand->oobsize/chip->ecc.steps);
86         header->ecc_mode = ecc_mode_convert(chip->eccbitmode);
87         header->ecc_pos = ecc_pos;
88         header->sct_size = (nand->writesize/chip->ecc.steps);
89
90         header->sct_per_page = chip->ecc.steps;
91
92         param.mode = 24;
93         param.ecc_num = 1;
94         param.sp_size = sizeof(ecc);
95         param.ecc_pos = 0;
96         param.m_size = chip->ecc.size;
97         param.p_mbuf = (u8 *)bl_data;
98         param.p_sbuf = ecc;
99
100         sc8810_ecc_encode(&param);
101         memcpy(header->ecc_value, ecc, sizeof(ecc));
102
103 }
104
105 static int nand_write_spl_page(u8 *buf, struct mtd_info *mtd, u32 pg, u32 ecc_pos)
106 {
107         int eccsteps;
108         u32 eccsize;
109         struct nand_chip *chip = mtd->priv;
110         int eccbytes = chip->ecc.bytes;
111         u32 i;
112         u32 page;
113         u32 spare_per_sct;
114         uint8_t *ecc_calc = chip->buffers->ecccalc;
115         eccsteps = chip->ecc.steps;
116         eccsize = chip->ecc.size;
117         spare_per_sct = mtd->oobsize / eccsteps;
118         memset(chip->buffers->ecccode, 0xff, mtd->oobsize);
119         
120         page = (int)(pg >> chip->page_shift);
121         
122         chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
123         
124         for (i = 0; i < eccsteps; i ++, buf += eccsize) {
125                 chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
126                 chip->write_buf(mtd, buf, eccsize);
127                 chip->ecc.calculate(mtd, buf, &ecc_calc[0]);
128                 memcpy(chip->buffers->ecccode + i * spare_per_sct + ecc_pos, &ecc_calc[0], eccbytes);
129         }
130         chip->write_buf(mtd, chip->buffers->ecccode, mtd->oobsize);
131         chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
132         chip->waitfunc(mtd, chip);
133         
134         return 0;
135 }
136
137 #elif defined CONFIG_NAND_DOLPHIN
138
139 struct bootloader_header
140 {
141         uint32_t version; //version
142         uint32_t magic_num; //0xaa55a5a5        
143         uint32_t check_sum;
144         uint32_t hash_len; //word length, only used when secure boot enable
145         uint32_t sct_size; //
146         uint32_t acycle; // 3, 4, 5
147         uint32_t bus_width; //0 ,1
148         uint32_t spare_size; //spare part sise for one sector
149         uint32_t ecc_mode; //0--1bit, 1--2bit,2--4bit,3--8bit,4--12bit, 5--16bit, 6--24bit
150         uint32_t ecc_pos; // ecc postion at spare part
151         uint32_t sct_per_page; //sector per page
152         uint32_t info_pos;
153         uint32_t info_size;
154         uint32_t ecc_value[27];
155 };
156
157 /*
158  * spare info data is don't used at the romcode, so the fdl only set the s_info size to 1, and the data value 0xff
159  */
160 static void set_header_info(u8 *bl_data, struct mtd_info *nand, int ecc_pos)
161 {
162         struct bootloader_header *header;
163         struct nand_chip *chip = nand->priv;
164         struct sprd_ecc_param param;
165         u8 ecc[108];
166
167         header = (struct bootloader_header *)(bl_data + BOOTLOADER_HEADER_OFFSET);
168         memset(header, 0, sizeof(struct bootloader_header));
169         memset(ecc, 0xff, sizeof(ecc));
170         header->version = 1;
171         header->sct_size = chip->ecc.size;
172         if (chip->options & NAND_BUSWIDTH_16)   {
173                 header->bus_width = 1;
174         }
175         if(nand->writesize > 512) {
176                 if (chip->chipsize > (128 << 20))               {
177                         header->acycle = 5;
178                 }
179                 else     {
180                         header->acycle = 4;
181                 }
182         }
183         else{
184                 /* One more address cycle for devices > 32MiB */
185
186                 if (chip->chipsize > (32 << 20)) {
187                         header->acycle = 4;
188                 }
189                 else    {
190                         header->acycle = 3;
191                 }
192         }
193
194         header->magic_num = 0xaa55a5a5;
195         header->spare_size = (nand->oobsize/chip->ecc.steps);
196         header->ecc_mode = ecc_mode_convert(chip->eccbitmode);
197         /*ecc is at the last postion at spare part*/
198         header->ecc_pos = header->spare_size - (chip->ecc.bytes);
199         header->sct_per_page = chip->ecc.steps;
200
201         header->info_pos = header->ecc_pos;
202         header->info_size = 0;
203
204         param.mode = 60;
205         param.ecc_pos = 0;
206         param.sinfo_size = 1;
207         param.ecc_num = 1;
208         param.sp_size = sizeof(ecc);
209         param.m_size = chip->ecc.size;
210         param.p_mbuf = (u8 *)bl_data;
211         param.p_sbuf = ecc;
212         param.sinfo_pos = 0;
213         sprd_ecc_encode(&param);
214         memcpy(header->ecc_value, ecc, sizeof(ecc));
215 }
216
217 static int nand_write_spl_page(u8 *buf, struct mtd_info *mtd, u32 pg, u32 ecc_pos)
218 {
219         struct nand_chip *chip = mtd->priv;
220
221         chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, pg);
222         //chip->ecc.write_page(mtd, chip, buf);
223         chip->ecc.write_page(mtd, chip, buf);
224         chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
225         chip->waitfunc(mtd, chip);
226
227         return 0;
228 }
229
230
231 #elif defined CONFIG_NAND_SC8830
232 struct bootloader_header
233 {
234         uint32_t version; //version
235         uint32_t magic_num; //0xaa55a5a5        
236         uint32_t check_sum;
237         uint32_t hash_len; //word length, only used when secure boot enable
238         uint32_t sct_size; //
239         uint32_t acycle; // 3, 4, 5
240         uint32_t bus_width; //0 ,1
241         uint32_t spare_size; //spare part sise for one sector
242         uint32_t ecc_mode; //0--1bit, 1--2bit,2--4bit,3--8bit,4--12bit, 5--16bit, 6--24bit
243         uint32_t ecc_pos; // ecc postion at spare part
244         uint32_t sct_per_page; //sector per page
245         uint32_t info_pos;
246         uint32_t info_size;
247         uint32_t ecc_value[27];
248         uint32_t page_per_blk;
249     uint32_t img_page[5];
250 };
251
252 /*
253  * spare info data is don't used at the romcode, so the fdl only set the s_info size to 1, and the data value 0xff
254  */
255 static void set_header_info(u8 *bl_data, struct mtd_info *nand, int ecc_pos)
256 {
257         struct bootloader_header *header;
258         struct nand_chip *chip = nand->priv;
259         struct sprd_ecc_param param;
260         u8 ecc[108];
261
262         header = (struct bootloader_header *)(bl_data + BOOTLOADER_HEADER_OFFSET);
263         memset(header, 0, sizeof(struct bootloader_header));
264         memset(ecc, 0xff, sizeof(ecc));
265         header->version = 1;
266         header->sct_size = chip->ecc.size;
267         if (chip->options & NAND_BUSWIDTH_16)   {
268                 header->bus_width = 1;
269         }
270         if(nand->writesize > 512) {
271                 if (chip->chipsize > (128 << 20))               {
272                         header->acycle = 5;
273                 }
274                 else     {
275                         header->acycle = 4;
276                 }
277         }
278         else{
279                 /* One more address cycle for devices > 32MiB */
280
281                 if (chip->chipsize > (32 << 20)) {
282                         header->acycle = 4;
283                 }
284                 else    {
285                         header->acycle = 3;
286                 }
287         }
288
289         header->magic_num = 0xaa55a5a5;
290         header->spare_size = (nand->oobsize/chip->ecc.steps);
291         header->ecc_mode = ecc_mode_convert(chip->eccbitmode);
292
293         header->ecc_pos = chip->ecc.layout->eccpos[0];
294         header->sct_per_page = chip->ecc.steps;
295
296         header->info_pos = chip->ecc.layout->oobfree[0].offset;
297         header->info_size = chip->ecc.layout->oobfree[0].length;
298 #ifdef CONFIG_SECURE_BOOT
299         header->hash_len  = CONFIG_SPL_HASH_LEN>>2;
300 #else
301         header->hash_len  = 0;
302 #endif
303
304         param.mode = 60;
305         param.ecc_pos = 0;
306         param.sinfo_size = 1;
307         param.ecc_num = 1;
308         param.sp_size = sizeof(ecc);
309         param.m_size = chip->ecc.size;
310         param.p_mbuf = (u8 *)bl_data;
311         param.p_sbuf = ecc;
312         param.sinfo_pos = 0;
313         sprd_ecc_encode(&param);
314         memcpy(header->ecc_value, ecc, sizeof(ecc));
315 }
316
317 static int nand_write_spl_page(u8 *buf, struct mtd_info *mtd, u32 pg, u32 ecc_pos)
318 {
319         struct nand_chip *chip = mtd->priv;
320
321         chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, pg);
322         //chip->ecc.write_page(mtd, chip, buf);
323         chip->ecc.write_page(mtd, chip, buf);
324         chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
325         chip->waitfunc(mtd, chip);
326
327         return 0;
328 }
329
330 #else
331 //dummy
332 static void set_header_info(u8 *bl_data, struct mtd_info *nand, int ecc_pos)
333 {
334         return;
335 }
336
337 static int nand_write_spl_page(u8 *buf, struct mtd_info *mtd, u32 pg, u32 ecc_pos)
338 {
339         return -1;
340 }
341 #endif
342
343 int sprd_nand_write_spl(u8 *buf, struct mtd_info *mtd)
344 {
345         u32 i = 0;
346         u32 pg_start;
347         u32 pg_end;
348         u32 pg;
349         u8 * data;
350         int ret = 0;
351
352         set_header_info(buf, mtd, CONFIG_SYS_SPL_ECC_POS);
353
354         /* write spl to flash*/
355         for (i = 0; i < 2; i++)
356         {
357                 pg_start = i * MAX_SPL_SIZE / mtd->writesize;
358                 pg_end = (i + 1) * MAX_SPL_SIZE / mtd->writesize;
359                 data = buf;
360                 for(pg  = pg_start; pg < pg_end; pg += 1) {
361                         ret = nand_write_spl_page(data, mtd, pg, CONFIG_SYS_SPL_ECC_POS);
362                         data += mtd->writesize;
363                 }
364         }
365         return ret;
366 }