8429306279b31700b56a8b0d50577fb136b978b1
[open-ath9k-htc-firmware.git] / target_firmware / magpie_fw_dev / build / magpie_1_1 / sboot / cmnos / eeprom / src / cmnos_eeprom.c
1 #include "athos_api.h"
2
3
4 #if SYSTEM_MODULE_EEPROM
5
6 // DEBUG DELAY OF RC ACCESS!!!!!! SHOULD BE FIXED!
7 #define PCIE_RC_ACCESS_DELAY    20
8
9 #define PCI_RC_RESET_BIT                            BIT6
10 #define PCI_RC_PHY_RESET_BIT                        BIT7
11 #define PCI_RC_PLL_RESET_BIT                        BIT8
12 #define PCI_RC_PHY_SHIFT_RESET_BIT                  BIT10
13
14 #define H_EEPROM_CTRL                               0x401c
15     #define B_EEP_CTRL_CLKDIV                       (BIT2|BIT3|BIT4|BIT5|BIT6|BIT7)
16     #define B_EEP_CTRL_NOT_PRESENT                  (BIT8)
17     #define B_EEP_CTRL_CORRUPT                      (BIT9)
18
19 #define H_EEPROM_STS_DATA                           0x407c
20     #define B_EEP_STS_STATE_BUSY                    (BIT16)
21     #define B_EEP_STS_IS_BUSY                       (BIT17)
22     #define B_EEP_STS_PROTECTED                     (BIT18)
23     #define B_EEP_STS_DATA_NOT_EXIST                (BIT19)
24
25 #define CMD_PCI_RC_RESET_ON()    HAL_WORD_REG_WRITE(MAGPIE_REG_RST_RESET_ADDR,  \
26                                     (HAL_WORD_REG_READ(MAGPIE_REG_RST_RESET_ADDR)|  \
27                                         (PCI_RC_PHY_SHIFT_RESET_BIT|PCI_RC_PLL_RESET_BIT|PCI_RC_PHY_RESET_BIT|PCI_RC_RESET_BIT)))
28
29 #define CMD_PCI_RC_RESET_CLR()   HAL_WORD_REG_WRITE(MAGPIE_REG_RST_RESET_ADDR, \
30                                     (HAL_WORD_REG_READ(MAGPIE_REG_RST_RESET_ADDR)&   \
31                                         (~(PCI_RC_PHY_SHIFT_RESET_BIT|PCI_RC_PLL_RESET_BIT|PCI_RC_PHY_RESET_BIT|PCI_RC_RESET_BIT))))
32
33
34 ////////////////////////////////////////////////////////////////////////////////////////////////
35
36
37 /*! eep write half word
38  *
39  * offset: is the offset address you want to do the write operation
40  * data: is the data to write to eeprom
41  *
42  * return: TRUE/FALSE
43  */
44 LOCAL BOOLEAN cmnos_eeprom_write_hword(uint16_t offset, uint16_t data)
45 {
46         /*! - Livy sugguest not use the retry, since it'll be huge retry count
47          *    so that, supposed that if the apb or pcie_rc is working fine,
48          *    we should always could see the NOT_BUSY, otherwise,
49          *        it should have something worng!, put a little delay in there,
50      *
51          *  - debug string here will be noisy!!
52          */
53     //uint16_t retryCnt = 1000;
54
55 #if defined(PROJECT_MAGPIE)
56     //gpio configuration, set GPIOs output to value set in output reg
57     HAL_WORD_REG_WRITE((EEPROM_CTRL_BASE+0x4054), (HAL_WORD_REG_READ((EEPROM_CTRL_BASE+0x4054)) | 0x20000));
58     HAL_WORD_REG_WRITE((EEPROM_CTRL_BASE+0x4060), 0);
59     HAL_WORD_REG_WRITE((EEPROM_CTRL_BASE+0x4064), 0);
60
61     //GPIO3 always drive output
62     HAL_WORD_REG_WRITE((EEPROM_CTRL_BASE+0x404c), 0xc0);
63
64     //Set 0 on GPIO3
65     HAL_WORD_REG_WRITE((EEPROM_CTRL_BASE+0x4048), 0x0);
66 #endif
67
68     HAL_WORD_REG_WRITE(EEPROM_ADDR_BASE + offset*4, (uint32_t)data);
69
70     //while( retryCnt-- > 0 )
71         while(1)
72     {
73         if( (HAL_WORD_REG_READ((EEPROM_CTRL_BASE+H_EEPROM_STS_DATA))&(B_EEP_STS_STATE_BUSY | B_EEP_STS_IS_BUSY)) == 0 )
74         {
75             return(TRUE);
76         }
77 //        A_DELAY_USECS(100);
78     }
79
80     return FALSE;
81 }
82
83 /*! eep read half word
84  *
85  *  offset: is the offset address you want to do the read operation
86  *
87  *  return: the data we read from eeprom
88  */
89 LOCAL BOOLEAN cmnos_eeprom_read_hword(uint16_t offset, uint16_t *mData)
90 {
91     uint32_t mStsData;
92     //uint16_t retryCnt = 1000;
93
94     HAL_WORD_REG_READ(EEPROM_ADDR_BASE + offset*4);
95
96     //while( retryCnt-- > 0 )
97         while(1)
98     {
99         mStsData = HAL_WORD_REG_READ((EEPROM_CTRL_BASE+H_EEPROM_STS_DATA));
100
101         if( (mStsData&(B_EEP_STS_STATE_BUSY | B_EEP_STS_IS_BUSY)) == 0 )
102         {
103             *mData = (uint16_t)(mStsData & 0xffff);
104             return TRUE;
105         }
106 //              A_DELAY_USECS(100);
107     }
108
109     return FALSE;
110 }
111 //////////////////////////////////////////////////////////////////////////////////////////////////////
112
113 LOCAL BOOLEAN eep_state = FALSE;
114 LOCAL BOOLEAN eep_exist = FALSE;
115
116
117 /*!- Initialize eeprom, actually we link up the pcie_rc for accessing the eeprom in client card
118  *
119  */
120 LOCAL T_EEP_RET
121 cmnos_eep_is_exist(void)
122 {
123     if( FALSE != eep_state )
124     {
125         if( FALSE == eep_exist )
126         {
127             uint16_t mData = HAL_WORD_REG_READ((EEPROM_CTRL_BASE+H_EEPROM_CTRL));
128
129             if( mData&B_EEP_CTRL_NOT_PRESENT )
130                 return RET_NOT_EXIST;
131             else if ( mData&B_EEP_CTRL_CORRUPT )
132                 return RET_EEP_CORRUPT;
133             else {
134                 eep_exist = TRUE;
135                 return RET_SUCCESS;
136                 }
137         }
138         else    // already done the checking, fast response
139             return RET_SUCCESS;
140     }
141
142     return RET_NOT_INIT;
143 }
144
145 /*!- eeprom write
146  *
147  * offset: where to write
148  * len:    number of half-word of the pBuf
149  * pBuf:   data buffer to write
150  */
151 LOCAL T_EEP_RET
152 cmnos_eep_write(uint16_t offset, uint16_t len, uint16_t *pBuf)
153 {
154     T_EEP_RET retVal;
155     uint16_t *pData = (uint16_t*)pBuf;
156     uint16_t i, j;
157
158     uint16_t eep_start_ofst = EEPROM_START_OFFSET;
159     uint16_t eep_end_ofst = EEPROM_END_OFFSET;
160     
161
162     if( FALSE != eep_state )
163     {
164                 if( (offset < eep_start_ofst) || (offset > eep_end_ofst) || ((offset+len) > eep_end_ofst) )
165                 {
166                     A_PUTS("-E10-");
167             retVal = RET_EEP_OVERFLOW;
168                 }
169         else
170         {
171             for(i=offset, j=0; i<len+(offset); i++, j++)
172             {
173                 if( TRUE == cmnos_eeprom_write_hword(i, pData[j]) )
174                 {
175                     retVal = RET_SUCCESS;
176                 }
177                 else
178                     A_PUTS("-E11-");
179             }
180         }
181     }
182     else
183     {
184         A_PUTS("-E12-");
185         retVal = RET_NOT_INIT;
186     }
187
188     return retVal;
189 }
190
191 /*!- eeprom read
192  *
193  * offset: where to read
194  * len:    number of bytes to read
195  * pBuf:   data buffer to read
196  */
197 LOCAL T_EEP_RET
198 cmnos_eep_read(uint16_t offset, uint16_t len, uint16_t *pBuf)
199 {
200     T_EEP_RET retVal;
201     uint16_t i;
202     uint16_t *mData = pBuf;
203
204     uint16_t eep_start_ofst = EEPROM_START_OFFSET;
205     uint16_t eep_end_ofst = EEPROM_END_OFFSET;
206
207     if( FALSE != eep_state )
208     {
209                 if( (offset < eep_start_ofst) || (offset > eep_end_ofst) || ((offset+len) > eep_end_ofst) )
210                 {
211                     A_PUTS("-E13-");
212             retVal = RET_EEP_OVERFLOW;
213                 }
214                 else
215                 {
216                     for(i=(offset); i<len+(offset); i++)
217                     {
218                         if( cmnos_eeprom_read_hword(i, mData) )
219                 {
220                     mData++;
221                         }
222                     }
223
224                     retVal = RET_SUCCESS;
225                 }
226     }
227     else
228         retVal = RET_NOT_INIT;
229
230     return retVal;
231
232 }
233
234
235 /*!- Initialize eeprom, actually we link up the pcie_rc for accessing the eeprom in client card
236  *
237  * Ryan - Add setup for PLL, refer to bug#37418
238  *
239  *  5. clear PCIE_RC_PLL PCIE_PHY_SHIFT, PCIE_PHY, PCIE_RC rst bit
240  *  6. clear PCIE_PLL bypass mode and PWD bit (BIT16 and BIT18)
241  *  7. set bus master and memory space enable 
242  *  8. set app_ltssm_enable
243  *
244  *  200ns in each access
245  *
246  */
247 LOCAL void
248 cmnos_eep_init(void)
249 {
250     uint32_t mStsData;
251     volatile int32_t i = 10000;
252     volatile reg_value = 0x0;
253
254 #if defined(PROJECT_MAGPIE)
255     if( TRUE != eep_state )
256     {
257         DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xff)) | 0x40;
258
259         /* 5 */
260 #if defined(MAGPIE_FPGA)
261         if (*(volatile uint32_t *)(WATCH_DOG_MAGIC_PATTERN_ADDR) == WDT_MAGIC_PATTERN )
262         {
263         // fpga will hang since external pcie_rc is not able to reset, do a wdt check here, and avoid toching pcie_rc phy reset
264         // not know will real chip have same issue, ryan
265         //
266             DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xff)) | 0x41;
267         
268 /*        
269     // Paddu sugguest to remove these, since PCIE_RC's reset state is 1 already
270     //
271             HAL_WORD_REG_WRITE(MAGPIE_REG_RST_RESET_ADDR,  \
272                 (HAL_WORD_REG_READ(MAGPIE_REG_RST_RESET_ADDR)|  \
273                     (PCI_RC_PLL_RESET_BIT|PCI_RC_RESET_BIT)));
274
275             A_DELAY_USECS(PCIE_RC_ACCESS_DELAY);
276             
277             DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xff)) | 0x42;
278 */         
279             HAL_WORD_REG_WRITE(MAGPIE_REG_RST_RESET_ADDR, \
280                 (HAL_WORD_REG_READ(MAGPIE_REG_RST_RESET_ADDR)&   \
281                     (~(PCI_RC_PLL_RESET_BIT|PCI_RC_RESET_BIT))));
282
283             A_DELAY_USECS(PCIE_RC_ACCESS_DELAY);
284         }
285         else
286 #endif
287         {
288 /*
289      // Paddu sugguest to remove these, since PCIE_RC's reset state is 1 already
290      // rom1.0 fix: looks like resetting the rc even already in reset state is fine 
291      //             but this would fix the eeprom-less issue, when we do the 2n init
292 */
293             /* asser the reset to pcie_rc */
294             DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xff)) | 0x43;
295             CMD_PCI_RC_RESET_ON();
296             A_DELAY_USECS(PCIE_RC_ACCESS_DELAY);
297
298             /* dereset the reset */
299             DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xff)) | 0x44;
300             CMD_PCI_RC_RESET_CLR();
301             A_DELAY_USECS(500);
302         }
303
304 /*!
305  * Ryan - clr MAGPIE_REG_AHB_ARB_ADDR, BIT1 is needed no mater FPGA or ASIC
306  */
307 //#if defined(MAGPIE_FPGA)
308     // workaround for FPGA, do we need to enable the PCIE_RC DMA just for accessing the EEPROM?
309     //HAL_WORD_REG_WRITE(0x00050018, 0x6);, purpose is to enable pcie_rc access internal memory
310     //HAL_WORD_REG_WRITE(MAGPIE_REG_AHB_ARB_ADDR, (HAL_WORD_REG_READ(MAGPIE_REG_AHB_ARB_ADDR)|(BIT1|BIT2)));
311         
312         DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xff)) | 0x49;
313         HAL_WORD_REG_WRITE(MAGPIE_REG_AHB_ARB_ADDR,
314             (HAL_WORD_REG_READ(MAGPIE_REG_AHB_ARB_ADDR)|(BIT1)));
315         A_DELAY_USECS(PCIE_RC_ACCESS_DELAY);
316 //#endif
317
318         /* 7.5. asser pcie_ep reset */
319         HAL_WORD_REG_WRITE(0x00040018, (HAL_WORD_REG_READ(0x00040018) & ~(0x1 << 2))); 
320
321 #if defined(MAGPIE_ASIC)
322         /* PLL setup should be ASIC/DV specific */
323         /* 6. set PCIE_PLL in bypass mode, and get out of power-down,  */
324         DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xff)) | 0x50;
325         HAL_WORD_REG_WRITE(MAGPIE_REG_PCIE_PLL_CONFIG_ADDR, \
326             (HAL_WORD_REG_READ(MAGPIE_REG_PCIE_PLL_CONFIG_ADDR)&(~(BIT16|BIT18))));
327
328         /* 100us delay wait for PCIE PLL stable */
329         A_DELAY_USECS(100); 
330 #endif      
331
332         /* 7. set bus master and memory space enable */
333         DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xff)) | 0x45;
334         HAL_WORD_REG_WRITE(0x00020004, (HAL_WORD_REG_READ(0x00020004)|(BIT1|BIT2)));
335         A_DELAY_USECS(PCIE_RC_ACCESS_DELAY);
336
337         /* 7.5. de-asser pcie_ep reset */
338         HAL_WORD_REG_WRITE(0x00040018, (HAL_WORD_REG_READ(0x00040018)|(0x1 << 2)));
339         A_DELAY_USECS(PCIE_RC_ACCESS_DELAY);
340
341         /* 8. set app_ltssm_enable */
342         DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xff)) | 0x46;
343         HAL_WORD_REG_WRITE(0x00040000, (HAL_WORD_REG_READ(0x00040000)|0xffc1));
344         
345         /*!
346          * Receive control (PCIE_RESET), 
347          *  0x40018, BIT0: LINK_UP, PHY Link up -PHY Link up/down indicator
348          *  in case the link up is not ready and we access the 0x14000000, 
349          *  vmc will hang here
350          */
351
352         /* poll 0x40018/bit0 (1000 times) until it turns to 1 */
353         while(i-->0)
354         {
355             reg_value = HAL_WORD_REG_READ(0x00040018);
356             if( reg_value & BIT0 ) 
357                 break;
358             A_DELAY_USECS(PCIE_RC_ACCESS_DELAY); 
359         }
360
361         /* init fail, can't detect PCI_RC LINK UP, give up the init */
362         if( i<=0 )
363         {
364                         DEBUG_SYSTEM_STATE |= BIT26;
365             goto ERR_DONE;
366         }
367
368         DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xff)) | 0x47;
369         HAL_WORD_REG_WRITE(0x14000004, (HAL_WORD_REG_READ(0x14000004)|0x116));
370         A_DELAY_USECS(PCIE_RC_ACCESS_DELAY);
371
372         DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xff)) | 0x48;
373         HAL_WORD_REG_WRITE(0x14000010, (HAL_WORD_REG_READ(0x14000010)|EEPROM_CTRL_BASE));
374         eep_state = TRUE;
375     }
376
377 #elif defined(PROJECT_K2)
378     eep_state = TRUE;
379 #endif /* End of #if defined(PROJECT_MAGPIE) */
380     if (TRUE == eep_state)
381     {
382         /* Read offset 1 location to determine if this EEPROM is protected somewhere */
383         HAL_WORD_REG_READ(EEPROM_ADDR_BASE + 4);
384
385         while(1)
386         {
387             mStsData = HAL_WORD_REG_READ((EEPROM_CTRL_BASE+H_EEPROM_STS_DATA));
388
389             /* If this location is protected or EEPROM does not exist, return immediately */
390             if ( mStsData & (B_EEP_STS_PROTECTED | B_EEP_STS_DATA_NOT_EXIST) )
391             {
392                 eep_state = FALSE;
393                 break;
394             }
395
396             if ( ( mStsData & (B_EEP_STS_STATE_BUSY | B_EEP_STS_IS_BUSY) ) == 0 )
397             {
398                 if (mStsData & 0xffff)
399                     cmnos_eeprom_write_hword( (uint16_t)1, (uint16_t)0 );
400
401                 break;
402             }
403
404                 A_DELAY_USECS(100);
405         }
406     }
407 ERR_DONE:
408     
409 }
410
411
412 void
413 cmnos_eep_module_install(struct eep_api *tbl)
414 {
415     tbl->_eep_init          = cmnos_eep_init;
416     tbl->_eep_read          = cmnos_eep_read;
417     tbl->_eep_write         = cmnos_eep_write;
418     tbl->_eep_is_exist      = cmnos_eep_is_exist;
419 }
420
421 #endif /* SYSTEM_MODULE_EEPROM */
422