2 #ifndef __SPRD_NAND_PARAM_H__
3 #define __SPRD_NAND_PARAM_H__
5 #define NAND_MAX_ID_LEN 5
14 #define NUM_BLOCK(n) (n)
16 #define SZ_K_BLOCK(n) (n * 1024)
17 #define SZ_K_PAGE(n) (n * 1024)
19 #define SZ_B_BLOCK(n) (n)
20 #define SZ_B_PAGE(n) (n)
22 #define SZ_B_SPARE(n) (n)
23 #define SZ_B_OOB(n) (n)
24 #define SZ_B_SECTOR(n) (n)
26 #define ECC_BITS(n) (n)
29 #define POS_ECC(n) (n)
30 #define SZ_INFO(n) (n)
31 #define POS_INFO(n) (n)
33 #define CALC_ECC_SIZE(n) ((14 * (n) + 7) / 8)
36 struct sprd_nand_device {
42 struct sprd_nand_maker {
45 struct sprd_nand_device* pDevTab;
48 struct sprd_nand_oob {
49 uint16_t nOOBSize; //16
52 uint16_t nEccSize; //4
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 */
63 struct sprd_nand_param {
64 uint8_t id[NAND_MAX_ID_LEN];
67 uint32_t nBlkSize; //256K
69 uint32_t nPageSize; //4K
70 uint16_t nSecSize; //512
74 struct sprd_nand_timing sTiming;
75 struct sprd_nand_oob sOOB;
78 struct sprd_nand_device micron_device_table[] = {
79 {0xBC,"MT29F4G16ABBEA","4Gb,x16,1.8V"},
83 struct sprd_nand_device adata_device_table[] = {
84 {0xBC,"APZZLA4GAZ-N22MAB","4Gb,x16,1.8V"},
88 struct sprd_nand_device kington_device_table[] = {
89 {0xBC,"KSLCCBL2GA2H2A","4Gb,x16,1.8V"},
93 struct sprd_nand_device hynix_device_table[] = {
94 {0xBC,"H9TA4GH2GDACPR","4Gb,x16,1.8V"},
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},
106 struct sprd_nand_param sprd_nand_param_table[] = {
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,
111 {SZ_B_OOB(28),ECC_BITS(8),POS_ECC(14),SZ_ECC(14),POS_INFO(14),SZ_INFO(0)}
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,
117 {SZ_B_OOB(28),ECC_BITS(8),POS_ECC(14),SZ_ECC(14),POS_INFO(14),SZ_INFO(0)}
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,
123 {SZ_B_OOB(16),ECC_BITS(4),POS_ECC(9),SZ_ECC(7),POS_INFO(9),SZ_INFO(0)}
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,
129 {SZ_B_OOB(16),ECC_BITS(4),POS_ECC(9),SZ_ECC(7),POS_INFO(9),SZ_INFO(0)}
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,
135 {SZ_B_OOB(16),ECC_BITS(8),POS_ECC(2),SZ_ECC(14),POS_INFO(0),SZ_INFO(0)}
139 STATIC_FUNC struct sprd_nand_maker* __FindMaker(uint8_t idMaker) {
140 struct sprd_nand_maker* pmaker = maker_table;
142 while (pmaker->idMaker != 0) {
143 if(pmaker->idMaker == idMaker) {
151 STATIC_FUNC struct sprd_nand_device* __FindDevice(struct sprd_nand_maker* pmaker, uint8_t idDevice) {
152 struct sprd_nand_device* pdevice = pmaker->pDevTab;
154 while (pdevice->idDevice != 0) {
155 if(pdevice->idDevice == idDevice) {
163 STATIC_FUNC void __PrintNandInfo(struct sprd_nand_param* p) {
164 struct sprd_nand_device* pdevice;
165 struct sprd_nand_maker* pmaker;
167 DPRINT("%s\n", __func__);
169 pmaker = __FindMaker(p->idMaker);
170 pdevice = __FindDevice(pmaker, p->idDevice);
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);
180 STATIC_FUNC void __ParseNandParam(uint8_t* id) {
181 struct sprd_nand_param* param = sprd_nand_param_table;
183 while(param->idMaker != 0) {
184 if ((param->id[0] == id[0]) &&
185 (param->id[4] == id[1])) {
187 __PrintNandInfo(param);
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 = ¶m->sOOB;
200 uint8_t sector_num = param->nPageSize / param->nSecSize;
202 DPRINT("%s\n", __func__);
204 if (param->idMaker != param->id[0]) {
205 DPRINT("%s: id is not match!!!!!!!!!!!!!!!\n", __func__);
208 if (param->idDevice != param->id[1]) {
209 DPRINT("%s: id is not match!!!!!!!!!!!!!!!\n", __func__);
212 if (poob->nOOBSize * sector_num > param->nSpareSize) {
213 DPRINT("%s: OOB size is not match!!!!!!!!!!!!!!!\n", __func__);
216 if (poob->nEccPos + poob->nEccSize > poob->nOOBSize) {
217 DPRINT("%s: ECC size exceeds the oob!!!!!!!!!!!!!!!\n", __func__);
220 if (CALC_ECC_SIZE(poob->nEccBits) != poob->nEccSize) {
221 DPRINT("%s: ECC size is wrong!!!!!!!!!!!!!!!\n", __func__);
224 if (poob->nInfoPos + poob->nInfoSize != poob->nEccPos) {
225 DPRINT("%s: Info position is wrong!!!!!!!!!!!!!!!\n", __func__);
232 struct sprd_nand_param* SprdGetNandParam(uint8_t* id) {
233 struct sprd_nand_param* param = sprd_nand_param_table;
236 DPRINT("%s\n", __func__);
238 for (i = 0; i < 5; i++) {
239 DPRINT("id[%d] is %x\n", i, id[i]);
242 //__ParseNandParam(id);
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])) {
251 __PrintNandInfo(param);
252 __SprdCheckNancParam(param);
257 DPRINT("Nand params unconfigured, please check it. Halt on booting!!!\n");