tizen 2.4 release
[profile/mobile/platform/kernel/u-boot-tm1.git] / arch / arm / cpu / armv7 / sc8830 / efuse_debug.c
1 /******************************************************************************\r
2  ** File Name:      module_test.c                                             *\r
3  ** Author:         Yong.Li                                                   *\r
4  ** DATE:           15/01/2010                                                *\r
5  ** Copyright:      2003 Spreatrum, Incoporated. All Rights Reserved.         *\r
6  ** Description:    define trace interface just for testing usage             *\r
7  ******************************************************************************\r
8 \r
9  ******************************************************************************\r
10  **                        Edit History                                       *\r
11  ** ------------------------------------------------------------------------- *\r
12  ** DATE           NAME             DESCRIPTION                               *\r
13  ** 15/01/2010     Yong.Li          Create                                    *\r
14  ******************************************************************************/\r
15 #include "asm/arch/sprd_reg.h"\r
16 #include "asm/arch/efuse_drv.h"\r
17 #include "asm/arch/chip_drv_common_io.h"\r
18 \r
19 #define EFUSE_MAX_BLOCK          (8)\r
20 #define GR_SOFT_REST             (0x4b00004c)\r
21 #define EFUSE_REG_BASE           (SPRD_UIDEFUSE_PHYS)\r
22 #define EFUSE_EB                 BIT_7\r
23 #define EFUSE_SOFT_RST           BIT_28\r
24 \r
25 #define EFUSE_DATA_RD            (EFUSE_REG_BASE + 0x0000)\r
26 #define EFUSE_DATA_WR            (EFUSE_REG_BASE + 0x0004)\r
27 \r
28 #define EFUSE_BLOCK_INDEX        (EFUSE_REG_BASE + 0x0008)\r
29 #define EFUSE_MODE_CTRL          (EFUSE_REG_BASE + 0x000c)\r
30 #define EFUSE_PGM_PARA           (EFUSE_REG_BASE + 0x0010)\r
31 #define EFUSE_STATUS             (EFUSE_REG_BASE + 0x0014)\r
32 #define EUSE_MEM_BLOCK_FLAGS     (EFUSE_REG_BASE + 0x0018)\r
33 #define EUSE_MEM_BLOCK_FLAGS_CLR (EFUSE_REG_BASE + 0x001c)\r
34 #define EFUSE_MAGIC_NUMBER       (EFUSE_REG_BASE + 0x0020)\r
35 \r
36 #define EFuse_LOCK_BIT           BIT_31\r
37 //efuse mode ctrl register bit define\r
38 #define EFUSE_PG_START           BIT_0\r
39 #define EFUSE_RD_START           BIT_1\r
40 #define EFUSE_BIST_START         BIT_31\r
41 \r
42 //efuse block index bit define\r
43 #define READ_INDEX_OFFSET        (0)\r
44 #define PGM_INDEX_OFFSET         (16)\r
45 #define BIST_START_INDEX_OFFSET  (26)\r
46 #define BIST_END_INDEX_OFFSET    (29)\r
47 \r
48 //PGM_PARA register bit define\r
49 #define EFUSE_AUTO_TEST_EN       BIT_16\r
50 #define CLK_EFS_EN               BIT_28\r
51 #define EFS_VDD_ON               BIT_29\r
52 #define PGM_EN                   BIT_31\r
53 \r
54 //efuse status register bit define\r
55 #define EFUSE_PRG_BUSY           BIT_0\r
56 #define EFUSE_READ_BUSY          BIT_1\r
57 #define EFUSE_BIST_FAIL          BIT_4\r
58 #define EFUSE_BIST_BUSY          BIT_5\r
59 \r
60 //Mem_block_flags register bit define\r
61 #define EFUSE_BLOCK_ERR_FLAG     BIT_8\r
62 #define WDG_EB_BIT               (1  <<   2)\r
63 #define RTC_WDG_EB_BIT           (1  <<  10)\r
64 \r
65 //timeout define\r
66 #define EFUSE_READ_TIMEOUT       5 //ms\r
67 #define EFUSE_WRITE_TIMEOUT      5 //ms\r
68 \r
69 PUBLIC EFuse_RETURN_E IsEfuseLock(int block_id)\r
70 {\r
71     uint32 read_data;\r
72     EFuse_RETURN_E ret;\r
73     ret = EFuseRead(block_id, (unsigned int *)&read_data);\r
74     //if read fail return\r
75     if(ret != EFuse_RESULT_SUCCESS)\r
76     {\r
77         return EFuse_READ_FAIL;\r
78     }\r
79     // if the lock bit is set return locked else return not locked\r
80     if((read_data & (EFuse_LOCK_BIT)) == EFuse_LOCK_BIT)\r
81     {\r
82         return EFuse_LOCKED;\r
83     }\r
84     else\r
85     {\r
86         return EFuse_NOT_LOCK;\r
87     }\r
88 }\r
89 \r
90 PUBLIC EFuse_RETURN_E EFuseWrite(\r
91     unsigned int block_id,                  // the selected EFuse block id\r
92     unsigned int data                       // the data to be writen into the EFuse block\r
93 )\r
94 {\r
95     uint32 old_tick = 0;\r
96     uint32 new_tick = 0;\r
97     uint32 sts = 0; //states of efuse\r
98     unsigned int read_data;\r
99     EFuse_RETURN_E ret;\r
100 \r
101     EFuse_RETURN_E result = EFuse_RESULT_SUCCESS;  // return value\r
102 \r
103     if(((int32)block_id < EFuse_MIN_ID) || ((int32)block_id > EFuse_MAX_ID))\r
104     {\r
105         return EFuse_ID_ERROR;\r
106     }\r
107 \r
108     /* if the block has locked return now */\r
109     if(IsEfuseLock(block_id) == EFuse_LOCKED)\r
110     {\r
111         return EFuse_LOCKED;\r
112     }\r
113 \r
114     REG32(EFUSE_MAGIC_NUMBER) = 0x8810;// Enable program\r
115     REG32(EFUSE_BLOCK_INDEX)  = (block_id << READ_INDEX_OFFSET) | (block_id << PGM_INDEX_OFFSET);\r
116     REG32(EFUSE_DATA_WR)      =  data & (~(EFuse_LOCK_BIT));\r
117     REG32(EFUSE_PGM_PARA)    |=  (EFUSE_AUTO_TEST_EN << block_id);\r
118     REG32(EFUSE_MODE_CTRL)   |=  EFUSE_PG_START;\r
119 \r
120     sts = (*(volatile uint32 *)EFUSE_STATUS) & EFUSE_PRG_BUSY;\r
121     old_tick = SCI_GetTickCount();\r
122 \r
123     while((EFUSE_PRG_BUSY == sts))\r
124     {\r
125         sts = (*(volatile uint32 *)EFUSE_STATUS) & EFUSE_PRG_BUSY;\r
126         new_tick = SCI_GetTickCount();\r
127         if((new_tick - old_tick) > EFUSE_WRITE_TIMEOUT)\r
128             break;\r
129     }\r
130 \r
131     if(sts == EFUSE_PRG_BUSY)\r
132     {\r
133         *(volatile uint32 *)EFUSE_MAGIC_NUMBER = 0; // disable program\r
134         return EFuse_WRITE_FAIL;\r
135     }\r
136     else\r
137     {\r
138         // get the hardware compare result\r
139         sts = (*(volatile uint32 *)EUSE_MEM_BLOCK_FLAGS) & (EFUSE_BLOCK_ERR_FLAG << block_id);\r
140 \r
141         /* read data and compare */\r
142         result = EFuseRead(block_id, &read_data);\r
143         if(EFuse_RESULT_SUCCESS != result)\r
144         {\r
145             ret = EFuse_WRITE_VERIFY_FAIL;\r
146         }\r
147         else\r
148         {\r
149             //compare write and read data\r
150             if((data & (((unsigned int)~EFuse_LOCK_BIT))) == (read_data & ((unsigned int)(~EFuse_LOCK_BIT))))\r
151             {\r
152                 if(0 != sts)\r
153                     ret = EFuse_WRITE_HARD_COMPARE_FAIL;\r
154                 else\r
155                     ret = EFuse_RESULT_SUCCESS;\r
156             }\r
157             else\r
158             {\r
159                 if(0 != sts)\r
160                     ret = EFuse_WRITE_SOFT_HARD_COMPARE_FAIL;\r
161                 else\r
162                     ret = EFuse_WRITE_SOFT_COMPARE_FAIL;\r
163             }\r
164         }\r
165     }\r
166     REG32(EFUSE_MAGIC_NUMBER) = 0;// disable program\r
167     return ret;\r
168 }\r
169 \r
170 PUBLIC EFuse_RETURN_E EFuseLock(\r
171     unsigned int block_id                     // the selected EFuse block id\r
172 )\r
173 {\r
174     unsigned int read_data;\r
175     EFuse_RETURN_E ret;\r
176     ret = EFuseRead(block_id, &read_data);\r
177     if(ret != EFuse_RESULT_SUCCESS)\r
178         return ret;\r
179 \r
180     if((read_data & ((unsigned int)EFuse_LOCK_BIT)) == ((unsigned int)EFuse_LOCK_BIT))\r
181         return EFuse_RESULT_SUCCESS;\r
182 \r
183     read_data |= (unsigned int)EFuse_LOCK_BIT;\r
184     return EFuseWrite(block_id, read_data);\r
185 }\r
186 \r
187 PUBLIC void EFuseInitilize(void)\r
188 {\r
189     uint32 i = 0;\r
190     REG32(REG_AON_APB_APB_EB0)  |= BIT_13;        // enable efuse clock\r
191 \r
192     // efuse reset\r
193     REG32(REG_AON_APB_APB_RST0) |=  BIT_14;        // enable efuse clock\r
194     for(i = 0; i < 100; i++);\r
195     REG32(REG_AON_APB_APB_RST0) &= ~BIT_14;        // enable efuse clock\r
196     /* power on effuse */\r
197     REG32(EFUSE_PGM_PARA)       |= EFS_VDD_ON;\r
198     udelay(2000);\r
199 \r
200     REG32(REG_AON_APB_PWR_CTRL) |= BIT_3;\r
201     udelay(2000);\r
202 \r
203     *(volatile uint32 *)EFUSE_PGM_PARA |= CLK_EFS_EN; // open efuse clk\r
204     *(volatile uint32 *)EFUSE_PGM_PARA |= PGM_EN; // Enable program\r
205     *(volatile uint32 *)EFUSE_MAGIC_NUMBER = 0x8810; // Enable program\r
206     udelay(1000);\r
207 }\r
208 \r
209 PUBLIC  EFuse_RETURN_E EFuseRead(\r
210     unsigned int block_id,                 // the selected efuse block id\r
211     unsigned int *r_data_ptr               // pointer of block data read from EFuse block\r
212 )\r
213 {\r
214     uint32 old_tick = 0;\r
215     uint32 new_tick = 0;\r
216     uint32 sts = 0; //states of efuse\r
217     EFuse_RETURN_E result = EFuse_RESULT_SUCCESS;  // return value\r
218 \r
219     /* check the block_id */\r
220     if(((int32)block_id < EFuse_MIN_ID) || ((int32)block_id > EFuse_MAX_ID))\r
221         return EFuse_ID_ERROR;\r
222 \r
223     /* read index must be the same of the write index */\r
224     *(volatile uint32 *)EFUSE_BLOCK_INDEX = (block_id << READ_INDEX_OFFSET) | (block_id << PGM_INDEX_OFFSET);\r
225     *(volatile uint32 *)EFUSE_MODE_CTRL |= EFUSE_RD_START; // send read commmand\r
226     sts = (*(volatile uint32 *)EFUSE_STATUS) & EFUSE_READ_BUSY;\r
227 \r
228     old_tick = SCI_GetTickCount();\r
229     while((EFUSE_READ_BUSY == sts))\r
230     {\r
231         sts = (*(volatile uint32 *)EFUSE_STATUS) & EFUSE_READ_BUSY;\r
232         new_tick = SCI_GetTickCount();\r
233         if((new_tick - old_tick) > EFUSE_READ_TIMEOUT)\r
234             break;\r
235     }\r
236     if(sts == EFUSE_READ_BUSY)\r
237         result =  EFuse_READ_FAIL;\r
238     else\r
239         *r_data_ptr = *(volatile uint32 *)(EFUSE_DATA_RD);\r
240     return result;\r
241 }\r
242 \r
243 LOCAL void EFuseClose(void)\r
244 {\r
245     REG32(EFUSE_PGM_PARA)       &= ~CLK_EFS_EN; // close efuse clk\r
246     REG32(EFUSE_PGM_PARA)       &= ~PGM_EN; // disable program\r
247     REG32(REG_AON_APB_PWR_CTRL) &= ~BIT_3;\r
248     /* shut down the efuse power */\r
249     REG32(EFUSE_PGM_PARA)       &= ~EFS_VDD_ON;\r
250     REG32(REG_AON_APB_APB_EB0)  &= ~BIT_13;        // enable efuse clock\r
251     *(volatile uint32 *)EFUSE_MAGIC_NUMBER = 0; // Enable program\r
252 }\r
253 \r
254 typedef struct SHA1Context32\r
255 {\r
256     unsigned int Intermediate_Hash[5]; /* Message Digest */\r
257     unsigned int Length_Low; /* Message length in bits */\r
258     unsigned int Length_High; /* Message length in bits */\r
259     /* Index into message block array */\r
260     unsigned int Message_Block_Index;\r
261     unsigned int W[80]; /* 512-bit message blocks */\r
262 } SHA1Context_32;\r
263 \r
264 struct ROM_CALLBACK_TABLE {\r
265         unsigned int version; //version number\r
266 #define SHA1_SUPPORT            BIT_0\r
267 #define MD5_SUPPORT             BIT_1\r
268 #define RSA_256_SUPPORT         BIT_2\r
269 #define RSA_512_SUPPORT         BIT_3\r
270 #define RSA_1024_SUPPORT        BIT_4\r
271 #define RSA_2048_SUPPORT        BIT_5\r
272         unsigned int cap;//capability\r
273         void (*Efuse_Init)   (void);\r
274         void (*Efuse_Close)  (void);\r
275         int  (*Efuse_Read)   (unsigned int block_id, unsigned int* r_data_ptr);\r
276         int  (*SHA1Reset_32) (SHA1Context_32 *);\r
277         int  (*SHA1Input_32) (SHA1Context_32 *,const unsigned int *message, unsigned int len);\r
278         int  (*SHA1Result_32)(SHA1Context_32 *context,unsigned char * Message_Digest);\r
279         void (*RSA_ModPower) (unsigned int *p, unsigned int *m, unsigned int *r2, unsigned int e);\r
280 };\r
281 \r
282 typedef struct\r
283 {\r
284         uint32 mVersion; // 1\r
285         uint32 mMagicNum; // 0xaa55a5a5\r
286         uint32 mCheckSum;//check sum value for bootloader header\r
287         uint32 mHashLen;//word length\r
288         uint32 mSectorSize; // sector size 1-1024\r
289         uint32 mAcyCle; // 0, 1, 2\r
290         uint32 mBusWidth; // 0--8 bit, 1--16bit\r
291         uint32 mSpareSize; // spare part size for one sector\r
292         uint32 mEccMode; // 0--1bit, 1-- 2bit, 2--4bit, 3--8bit, 4--12bit, 5--16bit, 6--24bit\r
293         uint32 mEccPostion; // ECC postion at spare part\r
294         uint32 mSectPerPage; // sector per page\r
295         uint32 mSinfoPos;\r
296         uint32 mSinfoSize;\r
297         uint32 mECCValue[27];\r
298 } NBLHeader;\r
299 \r
300 typedef struct\r
301 {\r
302         uint32 mVersion; // 1\r
303         uint32 mMagicNum; // 0xaa55a5a5\r
304         uint32 mCheckSum;//check sum value for bootloader header\r
305         uint32 mHashLen;//word length\r
306 }EBLHeader;\r
307 \r
308 PUBLIC void EfuseHashWrite(uint8 *bsc_code, uint32 hash_len)\r
309 {\r
310         uint32         block_index, ret, softHashValue[8], readHashValue[8];\r
311         NBLHeader*     eblheader = (NBLHeader *)(bsc_code+ 0x20);\r
312         SHA1Context_32 sha;\r
313         struct ROM_CALLBACK_TABLE  *rom_callback;\r
314 \r
315         printf("EfuseHashWrite\r\n");\r
316 \r
317         rom_callback = (struct ROM_CALLBACK_TABLE*)(*((unsigned int *)0xFFFF0020));\r
318 \r
319         memset(eblheader,     0, sizeof(NBLHeader));\r
320         memset(softHashValue, 0, sizeof(softHashValue));\r
321         memset(readHashValue, 0, sizeof(readHashValue));\r
322 \r
323         eblheader->mHashLen = hash_len>>2;\r
324         rom_callback->SHA1Reset_32 (&sha);\r
325         rom_callback->SHA1Input_32 (&sha, (unsigned int*)bsc_code, hash_len>>2);\r
326         rom_callback->SHA1Result_32(&sha, (unsigned char*)(&softHashValue[2]));\r
327 \r
328         EFuseClose();\r
329         udelay(100000);\r
330         EFuseInitilize();\r
331         udelay(100000);\r
332 \r
333         do\r
334         {\r
335                 //softHashValue[1] = BIT_18;\r
336                 for(block_index = 2; block_index < 7; block_index++)\r
337                 {\r
338                         ret = EFuseWrite(block_index, softHashValue[block_index]);\r
339                         printf("block : %d", block_index);\r
340                         switch (ret)\r
341                         {\r
342                                 case EFuse_ID_ERROR:\r
343                                         printf("EFuse_ID_ERROR\r\n");\r
344                                         break;\r
345                                 case EFuse_LOCKED:\r
346                                         printf("EFuse_LOCKED\r\n");\r
347                                         break;\r
348                                 case EFuse_WRITE_FAIL:\r
349                                         printf("EFuse_WRITE_FAIL\r\n");\r
350                                         break;\r
351                                 case EFuse_WRITE_VERIFY_FAIL:\r
352                                         printf("EFuse_WRITE_VERIFY_FAIL\r\n");\r
353                                         break;\r
354                                 case EFuse_WRITE_HARD_COMPARE_FAIL:\r
355                                         printf("EFuse_WRITE_SOFT_HARD_COMPARE_FAIL\r\n");\r
356                                         break;\r
357                                 case EFuse_RESULT_SUCCESS:\r
358                                         printf("EFuse_RESULT_SUCCESS\r\n");\r
359                                         break;\r
360                                 case EFuse_WRITE_SOFT_COMPARE_FAIL:\r
361                                         printf("EFuse_WRITE_SOFT_COMPARE_FAIL\r\n");\r
362                                         break;\r
363                                 default:\r
364                                         printf("UNKOWN Error.\r\n");\r
365                                         break;\r
366                         }\r
367                         if (ret != EFuse_RESULT_SUCCESS)\r
368                         {\r
369                                 //block_index--;\r
370                                 udelay(1000000);\r
371                         }\r
372                         udelay(10000);\r
373                 }\r
374                 udelay(100000);\r
375                 for(block_index = 0; block_index < 8; block_index++)\r
376                 {\r
377                         ret = EFuseRead(block_index, &readHashValue[block_index]);\r
378                         {\r
379                                 printf("[%d] write: %08x, read: %08x\r\n", block_index, softHashValue[block_index], readHashValue[block_index]);\r
380                         }\r
381                 }\r
382                 udelay(1000000);\r
383                 for(block_index = 0; block_index < 8; block_index++)\r
384                 {\r
385                         ret = EFuseRead(block_index, &readHashValue[block_index]);\r
386                         {\r
387                                 printf("[%d] write: %08x, read: %08x\r\n", block_index, softHashValue[block_index], readHashValue[block_index]);\r
388                         }\r
389                 }\r
390                 for (block_index=0; block_index<8; block_index++)\r
391                 {\r
392                         ret = EFuseWrite(block_index, 0);\r
393                 }\r
394                 udelay(1000000);\r
395         }while (0);\r
396         EFuseClose();\r
397 }\r
398 \r