tizen 2.4 release
[kernel/u-boot-tm1.git] / drivers / mtd / nand / sprd_nand_param.h
1
2 #ifndef __SPRD_NAND_PARAM_H__
3 #define __SPRD_NAND_PARAM_H__
4
5 #define NAND_MAX_ID_LEN 5
6
7 #define BW_08 0x00
8 #define BW_16 0x01
9
10 #define CYCLES_3 0x03
11 #define CYCLES_4 0x04
12 #define CYCLES_5 0x05
13
14 #define NUM_BLOCK(n) (n)
15
16 #define SZ_K_BLOCK(n) (n * 1024)
17 #define SZ_K_PAGE(n) (n * 1024)
18
19 #define SZ_B_BLOCK(n) (n)
20 #define SZ_B_PAGE(n) (n)
21
22 #define SZ_B_SPARE(n) (n)
23 #define SZ_B_OOB(n) (n)
24 #define SZ_B_SECTOR(n) (n)
25
26 #define ECC_BITS(n) (n)
27
28 #define SZ_ECC(n) (n)
29 #define POS_ECC(n) (n)
30 #define SZ_INFO(n) (n)
31 #define POS_INFO(n) (n)
32
33 #define CALC_ECC_SIZE(n) ((14 * (n) + 7) / 8)
34
35
36 struct sprd_nand_device {
37         uint8_t idDevice;
38         char* pName;
39         char* pType;
40 };
41
42 struct sprd_nand_maker {
43         uint8_t idMaker;
44         char* pName;
45         struct sprd_nand_device* pDevTab;
46 };
47
48 struct sprd_nand_oob {
49         uint16_t nOOBSize; //16
50         uint8_t nEccBits;
51         uint16_t nEccPos;
52         uint16_t nEccSize;  //4
53         uint16_t nInfoPos;
54         uint16_t nInfoSize;
55 };
56
57 struct sprd_nand_timing {
58         uint8_t ace_ns; /* ALE, CLE end of delay timing, unit: ns */
59         uint8_t rwl_ns; /* WE, RE, IO, pulse  timing, unit: ns */
60         uint8_t rwh_ns; /* WE, RE, IO, high hold  timing, unit: ns */
61 };
62
63 struct sprd_nand_param {
64         uint8_t id[NAND_MAX_ID_LEN];
65         uint8_t idMaker;
66         uint8_t idDevice;
67         uint32_t nBlkSize; //256K
68         uint32_t nBlkNum; //
69         uint32_t nPageSize; //4K
70         uint16_t nSecSize; //512
71         uint16_t nSpareSize;
72         uint8_t nBusWidth;
73         uint8_t nCycles;
74         struct sprd_nand_timing sTiming;
75         struct sprd_nand_oob sOOB;
76 };
77
78 struct sprd_nand_device micron_device_table[] = {
79         {0xBC,"MT29F4G16ABBEA","4Gb,x16,1.8V"},
80         {0x00,NULL,NULL}
81 };
82
83 struct sprd_nand_device adata_device_table[] = {
84         {0xBC,"APZZLA4GAZ-N22MAB","4Gb,x16,1.8V"},
85         {0x00,NULL,NULL}
86 };
87
88 struct sprd_nand_device kington_device_table[] = {
89         {0xBC,"KSLCCBL2GA2H2A","4Gb,x16,1.8V"},
90         {0x00,NULL,NULL}
91 };
92
93 struct sprd_nand_device hynix_device_table[] = {
94         {0xBC,"H9TA4GH2GDACPR","4Gb,x16,1.8V"},
95         {0x00,NULL,NULL}
96 };
97
98 struct sprd_nand_maker maker_table[] = {
99         {0x98,"Kington",kington_device_table},
100         {0x2C,"Micron",micron_device_table},
101         {0xC8,"Adata",adata_device_table},
102         {0xAD,"Hynix",hynix_device_table},
103         {0x00,NULL,NULL}
104 };
105
106 struct sprd_nand_param sprd_nand_param_table[] = {
107         {//Micron
108                 {0x2C,0xBC,0x90,0x66,0x54},0x2C,0xBC, 
109                 SZ_K_BLOCK(256),NUM_BLOCK(2048), SZ_K_PAGE(4),SZ_B_SECTOR(512),SZ_B_SPARE(224),BW_16,CYCLES_5,
110                 {10,15,10},
111                 {SZ_B_OOB(28),ECC_BITS(8),POS_ECC(14),SZ_ECC(14),POS_INFO(14),SZ_INFO(0)}
112         },
113         {//Kington
114                 {0x98,0xBC,0x90,0x66,0x76},0x98,0xBC, 
115                 SZ_K_BLOCK(256),NUM_BLOCK(2048), SZ_K_PAGE(4),SZ_B_SECTOR(512),SZ_B_SPARE(224),BW_16,CYCLES_5,
116                 {10,25,15},
117                 {SZ_B_OOB(28),ECC_BITS(8),POS_ECC(14),SZ_ECC(14),POS_INFO(14),SZ_INFO(0)}
118         },
119         {//Hynix
120                 {0xAD,0xBC,0x90,0x55,0x56},0xAD,0xBC, 
121                 SZ_K_BLOCK(128),NUM_BLOCK(4096), SZ_K_PAGE(2),SZ_B_SECTOR(512),SZ_B_SPARE(64),BW_16,CYCLES_5,
122                 {10,25,15},
123                 {SZ_B_OOB(16),ECC_BITS(4),POS_ECC(9),SZ_ECC(7),POS_INFO(9),SZ_INFO(0)}
124         },
125         {//Adata
126                 {0xC8,0xBC,0x90,0x55,0x54},0xC8,0xBC, 
127                 SZ_K_BLOCK(128),NUM_BLOCK(4096), SZ_K_PAGE(2),SZ_B_SECTOR(512),SZ_B_SPARE(64),BW_16,CYCLES_5,
128                 {10,25,15},
129                 {SZ_B_OOB(16),ECC_BITS(4),POS_ECC(9),SZ_ECC(7),POS_INFO(9),SZ_INFO(0)}
130         },
131         {
132                 {0x00, 0x00, 0x00, 0x00, 0x00},0x00,0x00, 
133                 SZ_K_BLOCK(256),NUM_BLOCK(2048), SZ_K_PAGE(4),SZ_B_SECTOR(512),SZ_B_SPARE(128),0x01,0x05,
134                 {10,21,15},
135                 {SZ_B_OOB(16),ECC_BITS(8),POS_ECC(2),SZ_ECC(14),POS_INFO(0),SZ_INFO(0)}
136         }
137 };
138
139 STATIC_FUNC struct sprd_nand_maker* __FindMaker(uint8_t idMaker) {
140         struct sprd_nand_maker* pmaker = maker_table;
141
142         while (pmaker->idMaker != 0) {
143                 if(pmaker->idMaker == idMaker) {
144                         return pmaker;
145                 }
146                 pmaker++;
147         }
148         return NULL;
149 }
150
151 STATIC_FUNC struct sprd_nand_device* __FindDevice(struct sprd_nand_maker* pmaker, uint8_t idDevice) {
152         struct sprd_nand_device* pdevice = pmaker->pDevTab;
153
154         while (pdevice->idDevice != 0) {
155                 if(pdevice->idDevice == idDevice) {
156                         return pdevice;
157                 }
158                 pdevice++;
159         }
160         return NULL;
161 }
162
163 STATIC_FUNC void __PrintNandInfo(struct sprd_nand_param* p) {
164         struct sprd_nand_device* pdevice;
165         struct sprd_nand_maker* pmaker;
166
167         DPRINT("%s\n", __func__);
168
169         pmaker = __FindMaker(p->idMaker);
170         pdevice = __FindDevice(pmaker, p->idDevice);
171         
172         DPRINT("device is %s:%s\n", pmaker->pName, pdevice->pName);
173         DPRINT("block size is %d\n", p->nBlkSize);
174         DPRINT("page size is %d\n", p->nPageSize);
175         DPRINT("spare size is %d\n", p->nSpareSize);
176         DPRINT("eccbits is %d\n", p->sOOB.nEccBits);
177 }
178
179
180 STATIC_FUNC void __ParseNandParam(uint8_t* id) {
181         struct sprd_nand_param* param = sprd_nand_param_table;
182
183         while(param->idMaker != 0) {
184                 if ((param->id[0] == id[0]) && 
185                         (param->id[4] == id[1])) {
186                         
187                         __PrintNandInfo(param);
188                         return param;
189                 }
190                 param++;
191         }
192         
193         return;
194 }
195
196 STATIC_FUNC int __SprdCheckNancParam(struct sprd_nand_param* param) {
197         struct sprd_nand_device* pdevice;
198         struct sprd_nand_maker* pmaker;
199         struct sprd_nand_oob* poob = &param->sOOB;
200         uint8_t sector_num = param->nPageSize / param->nSecSize;
201
202         DPRINT("%s\n", __func__);
203
204         if (param->idMaker != param->id[0]) {
205                 DPRINT("%s: id is not match!!!!!!!!!!!!!!!\n", __func__);
206                 SPRD_ASSERT(0);
207         }
208         if (param->idDevice != param->id[1]) {
209                 DPRINT("%s: id is not match!!!!!!!!!!!!!!!\n", __func__);
210                 SPRD_ASSERT(0);
211         }
212         if (poob->nOOBSize * sector_num > param->nSpareSize) {
213                 DPRINT("%s: OOB size is not match!!!!!!!!!!!!!!!\n", __func__);
214                 SPRD_ASSERT(0);
215         }
216         if (poob->nEccPos + poob->nEccSize > poob->nOOBSize) {
217                 DPRINT("%s: ECC size exceeds the oob!!!!!!!!!!!!!!!\n", __func__);
218                 SPRD_ASSERT(0);
219         }
220         if (CALC_ECC_SIZE(poob->nEccBits) != poob->nEccSize) {
221                 DPRINT("%s: ECC size is wrong!!!!!!!!!!!!!!!\n", __func__);
222                 SPRD_ASSERT(0);
223         }
224         if (poob->nInfoPos + poob->nInfoSize != poob->nEccPos) {
225                 DPRINT("%s: Info position is wrong!!!!!!!!!!!!!!!\n", __func__);
226                 SPRD_ASSERT(0);
227         }       
228
229         return 0;       
230 }
231
232 struct sprd_nand_param* SprdGetNandParam(uint8_t* id) {
233         struct sprd_nand_param* param = sprd_nand_param_table;
234         int i;
235
236         DPRINT("%s\n", __func__);
237
238         for (i = 0; i < 5; i++) {
239                 DPRINT("id[%d] is %x\n", i, id[i]);
240         }
241
242         //__ParseNandParam(id);
243
244         while(param->idMaker != 0) {
245                 if ((param->id[0] == id[0]) && 
246                         (param->id[1] == id[1]) &&
247                         (param->id[2] == id[2]) &&
248                         (param->id[3] == id[3]) &&
249                         (param->id[4] == id[4])) {
250
251                         __PrintNandInfo(param);
252                         __SprdCheckNancParam(param);
253                         return param;
254                 }
255                 param++;
256         }
257         DPRINT("Nand params unconfigured, please check it. Halt on booting!!!\n");
258         for(;;) /*relax*/;
259
260         return NULL;
261 }
262 #endif