[omap]: switch the am335x-evmsk to the new wlcore bindings
[openwrt.git] / target / linux / ramips / files / drivers / usb / host / mtk-phy-7621.c
1 #include "mtk-phy.h"
2
3 #ifdef CONFIG_PROJECT_7621
4 #include "mtk-phy-7621.h"
5
6 //not used on SoC
7 PHY_INT32 phy_init(struct u3phy_info *info){    
8         return PHY_TRUE;
9 }
10
11 //not used on SoC
12 PHY_INT32 phy_change_pipe_phase(struct u3phy_info *info, PHY_INT32 phy_drv, PHY_INT32 pipe_phase){
13         return PHY_TRUE;
14 }
15
16 //--------------------------------------------------------
17 //    Function : fgEyeScanHelper_CheckPtInRegion()
18 // Description : Check if the test point is in a rectangle region.
19 //               If it is in the rectangle, also check if this point
20 //               is on the multiple of deltaX and deltaY.
21 //   Parameter : strucScanRegion * prEye - the region
22 //               BYTE bX
23 //               BYTE bY
24 //      Return : BYTE - TRUE :  This point needs to be tested
25 //                      FALSE:  This point will be omitted
26 //        Note : First check within the rectangle.
27 //               Secondly, use modulous to check if the point will be tested.
28 //--------------------------------------------------------
29 static PHY_INT8 fgEyeScanHelper_CheckPtInRegion(struct strucScanRegion * prEye, PHY_INT8 bX, PHY_INT8 bY)
30 {
31   PHY_INT8 fgValid = true;
32
33
34   /// Be careful, the axis origin is on the TOP-LEFT corner.
35   /// Therefore the top-left point has the minimum X and Y
36   /// Botton-right point is the maximum X and Y
37   if ( (prEye->bX_tl <= bX) && (bX <= prEye->bX_br)
38     && (prEye->bY_tl <= bY) && (bY <= prEye->bX_br))
39   {
40     // With the region, now check whether or not the input test point is
41     // on the multiples of X and Y
42     // Do not have to worry about negative value, because we have already
43     // check the input bX, and bY is within the region.
44     if ( ((bX - prEye->bX_tl) % (prEye->bDeltaX))
45       || ((bY - prEye->bY_tl) % (prEye->bDeltaY)) )
46     {
47       // if the division will have remainder, that means
48       // the input test point is on the multiples of X and Y
49       fgValid = false;
50     }
51     else
52     {
53     }
54   }
55   else
56   {
57     
58     fgValid = false;
59   }
60   return fgValid;
61 }
62
63 //--------------------------------------------------------
64 //    Function : EyeScanHelper_RunTest()
65 // Description : Enable the test, and wait til it is completed
66 //   Parameter : None
67 //      Return : None
68 //        Note : None
69 //--------------------------------------------------------
70 static void EyeScanHelper_RunTest(struct u3phy_info *info)
71 {
72         DRV_UDELAY(100);
73         // Disable the test
74         U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0)
75                 , RG_SSUSB_EQ_EYE_CNT_EN_OFST, RG_SSUSB_EQ_EYE_CNT_EN, 0);      //RG_SSUSB_RX_EYE_CNT_EN = 0
76         DRV_UDELAY(100);
77         // Run the test
78         U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0)
79                 , RG_SSUSB_EQ_EYE_CNT_EN_OFST, RG_SSUSB_EQ_EYE_CNT_EN, 1);      //RG_SSUSB_RX_EYE_CNT_EN = 1
80         DRV_UDELAY(100);
81         // Wait til it's done
82         //RGS_SSUSB_RX_EYE_CNT_RDY
83         while(!U3PhyReadField32(((PHY_UINT32)&info->u3phyd_regs->phya_rx_mon5)
84                 , RGS_SSUSB_EQ_EYE_CNT_RDY_OFST, RGS_SSUSB_EQ_EYE_CNT_RDY));
85 }
86
87 //--------------------------------------------------------
88 //    Function : fgEyeScanHelper_CalNextPoint()
89 // Description : Calcualte the test point for the measurement
90 //   Parameter : None
91 //      Return : BOOL - TRUE :  the next point is within the
92 //                              boundaryof HW limit
93 //                      FALSE:  the next point is out of the HW limit
94 //        Note : The next point is obtained by calculating
95 //               from the bottom left of the region rectangle
96 //               and then scanning up until it reaches the upper
97 //               limit. At this time, the x will increment, and
98 //               start scanning downwards until the y hits the
99 //               zero.
100 //--------------------------------------------------------
101 static PHY_INT8 fgEyeScanHelper_CalNextPoint(void)
102 {
103   if ( ((_bYcurr == MAX_Y) && (_eScanDir == SCAN_DN))
104     || ((_bYcurr == MIN_Y) && (_eScanDir == SCAN_UP))
105         )
106   {
107     /// Reaches the limit of Y axis
108     /// Increment X
109     _bXcurr++;
110     _fgXChged = true;
111     _eScanDir = (_eScanDir == SCAN_UP) ? SCAN_DN : SCAN_UP;
112
113     if (_bXcurr > MAX_X)
114     {
115       return false;
116     }
117   }
118   else
119   {
120     _bYcurr = (_eScanDir == SCAN_DN) ? _bYcurr + 1 : _bYcurr - 1;
121     _fgXChged = false;
122   }
123   return PHY_TRUE;
124 }
125
126 PHY_INT32 eyescan_init(struct u3phy_info *info){
127         //initial PHY setting
128         U3PhyWriteField32(((PHY_UINT32)&info->u3phya_regs->rega)
129                 , RG_SSUSB_CDR_EPEN_OFST, RG_SSUSB_CDR_EPEN, 1);        
130         U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->phyd_mix3)
131                 , RG_SSUSB_FORCE_CDR_PI_PWD_OFST, RG_SSUSB_FORCE_CDR_PI_PWD, 1);
132         U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_bank2_regs->b2_phyd_misc0)
133                 , RG_SSUSB_RX_PI_CAL_EN_SEL_OFST, RG_SSUSB_RX_PI_CAL_EN_SEL, 1);    //RG_SSUSB_RX_PI_CAL_MANUAL_SEL = 1
134         U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_bank2_regs->b2_phyd_misc0)
135                 , RG_SSUSB_RX_PI_CAL_EN_OFST, RG_SSUSB_RX_PI_CAL_EN, 1);        //RG_SSUSB_RX_PI_CAL_MANUAL_EN = 1
136         return PHY_TRUE;
137 }
138
139 PHY_INT32 phy_eyescan(struct u3phy_info *info, PHY_INT32 x_t1, PHY_INT32 y_t1, PHY_INT32 x_br, PHY_INT32 y_br, PHY_INT32 delta_x, PHY_INT32 delta_y
140                 , PHY_INT32 eye_cnt, PHY_INT32 num_cnt, PHY_INT32 PI_cal_en, PHY_INT32 num_ignore_cnt){
141         PHY_INT32 cOfst = 0;
142         PHY_UINT8 bIdxX = 0;
143         PHY_UINT8 bIdxY = 0;
144         //PHY_INT8 bCnt = 0;
145         PHY_UINT8 bIdxCycCnt = 0;
146         PHY_INT8 fgValid;
147         PHY_INT8 cX;
148         PHY_INT8 cY;
149         PHY_UINT8 bExtendCnt;
150         PHY_INT8 isContinue;
151         //PHY_INT8 isBreak;
152         PHY_UINT32 wErr0 = 0, wErr1 = 0;
153         //PHY_UINT32 temp;
154
155         PHY_UINT32 pwErrCnt0[CYCLE_COUNT_MAX][ERRCNT_MAX][ERRCNT_MAX];
156         PHY_UINT32 pwErrCnt1[CYCLE_COUNT_MAX][ERRCNT_MAX][ERRCNT_MAX];
157
158         _rEye1.bX_tl = x_t1;
159         _rEye1.bY_tl = y_t1;
160         _rEye1.bX_br = x_br;
161         _rEye1.bY_br = y_br;
162         _rEye1.bDeltaX = delta_x;
163         _rEye1.bDeltaY = delta_y;
164
165         _rEye2.bX_tl = x_t1;
166         _rEye2.bY_tl = y_t1;
167         _rEye2.bX_br = x_br;
168         _rEye2.bY_br = y_br;
169         _rEye2.bDeltaX = delta_x;
170         _rEye2.bDeltaY = delta_y;
171
172         _rTestCycle.wEyeCnt = eye_cnt;
173         _rTestCycle.bNumOfEyeCnt = num_cnt;
174         _rTestCycle.bNumOfIgnoreCnt = num_ignore_cnt;
175         _rTestCycle.bPICalEn = PI_cal_en;       
176
177         _bXcurr = 0;
178         _bYcurr = 0;
179         _eScanDir = SCAN_DN;
180         _fgXChged = false;
181
182         printk("x_t1: %x, y_t1: %x, x_br: %x, y_br: %x, delta_x: %x, delta_y: %x, \
183                 eye_cnt: %x, num_cnt: %x, PI_cal_en: %x, num_ignore_cnt: %x\n", \
184                 x_t1, y_t1, x_br, y_br, delta_x, delta_y, eye_cnt, num_cnt, PI_cal_en, num_ignore_cnt);         
185
186         //force SIGDET to OFF
187         U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_bank2_regs->b2_phyd_misc0)
188                 , RG_SSUSB_RX_SIGDET_EN_SEL_OFST, RG_SSUSB_RX_SIGDET_EN_SEL, 1);                                                //RG_SSUSB_RX_SIGDET_SEL = 1
189         U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_bank2_regs->b2_phyd_misc0)
190                 , RG_SSUSB_RX_SIGDET_EN_OFST, RG_SSUSB_RX_SIGDET_EN, 0);                                                //RG_SSUSB_RX_SIGDET_EN = 0
191         U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye1)
192                 , RG_SSUSB_EQ_SIGDET_OFST, RG_SSUSB_EQ_SIGDET, 0);                              //RG_SSUSB_RX_SIGDET = 0
193
194         // RX_TRI_DET_EN to Disable
195         U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq3)
196                 , RG_SSUSB_EQ_TRI_DET_EN_OFST, RG_SSUSB_EQ_TRI_DET_EN, 0);              //RG_SSUSB_RX_TRI_DET_EN = 0
197
198         U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0)
199                 , RG_SSUSB_EQ_EYE_MON_EN_OFST, RG_SSUSB_EQ_EYE_MON_EN, 1);              //RG_SSUSB_EYE_MON_EN = 1
200         U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0)
201                 , RG_SSUSB_EQ_EYE_XOFFSET_OFST, RG_SSUSB_EQ_EYE_XOFFSET, 0);            //RG_SSUSB_RX_EYE_XOFFSET = 0
202         U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0)
203                 , RG_SSUSB_EQ_EYE0_Y_OFST, RG_SSUSB_EQ_EYE0_Y, 0);                              //RG_SSUSB_RX_EYE0_Y = 0
204         U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0)
205                 , RG_SSUSB_EQ_EYE1_Y_OFST, RG_SSUSB_EQ_EYE1_Y, 0);                              //RG_SSUSB_RX_EYE1_Y = 0
206
207
208         if (PI_cal_en){
209                 // PI Calibration
210                 U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_bank2_regs->b2_phyd_misc0)
211                         , RG_SSUSB_RX_PI_CAL_EN_SEL_OFST, RG_SSUSB_RX_PI_CAL_EN_SEL, 1);        //RG_SSUSB_RX_PI_CAL_MANUAL_SEL = 1
212                 U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_bank2_regs->b2_phyd_misc0)
213                         , RG_SSUSB_RX_PI_CAL_EN_OFST, RG_SSUSB_RX_PI_CAL_EN, 0);                //RG_SSUSB_RX_PI_CAL_MANUAL_EN = 0
214                 U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_bank2_regs->b2_phyd_misc0)
215                         , RG_SSUSB_RX_PI_CAL_EN_OFST, RG_SSUSB_RX_PI_CAL_EN, 1);                //RG_SSUSB_RX_PI_CAL_MANUAL_EN = 1
216
217                 DRV_UDELAY(20);
218
219                 U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_bank2_regs->b2_phyd_misc0)
220                         , RG_SSUSB_RX_PI_CAL_EN_OFST, RG_SSUSB_RX_PI_CAL_EN, 0);                //RG_SSUSB_RX_PI_CAL_MANUAL_EN = 0
221                 _bPIResult = U3PhyReadField32(((PHY_UINT32)&info->u3phyd_regs->phya_rx_mon5)
222                         , RGS_SSUSB_EQ_PILPO_OFST, RGS_SSUSB_EQ_PILPO);                         //read RGS_SSUSB_RX_PILPO
223
224                 printk(KERN_ERR "PI result: %d\n", _bPIResult);
225         }
226         // Read Initial DAC
227         // Set CYCLE
228         U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye3)
229                 ,RG_SSUSB_EQ_EYE_CNT_OFST, RG_SSUSB_EQ_EYE_CNT, eye_cnt);                       //RG_SSUSB_RX_EYE_CNT
230
231         // Eye Monitor Feature
232         U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye1)
233                 , RG_SSUSB_EQ_EYE_MASK_OFST, RG_SSUSB_EQ_EYE_MASK, 0x3ff);              //RG_SSUSB_RX_EYE_MASK = 0x3ff
234         U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0)
235                 , RG_SSUSB_EQ_EYE_MON_EN_OFST, RG_SSUSB_EQ_EYE_MON_EN, 1);              //RG_SSUSB_EYE_MON_EN = 1
236
237         // Move X,Y to the top-left corner
238         for (cOfst = 0; cOfst >= -64; cOfst--)
239         {
240                 U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0)
241                         ,RG_SSUSB_EQ_EYE_XOFFSET_OFST, RG_SSUSB_EQ_EYE_XOFFSET, cOfst); //RG_SSUSB_RX_EYE_XOFFSET
242         }
243         for (cOfst = 0; cOfst < 64; cOfst++)
244         {
245                 U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0)
246                         , RG_SSUSB_EQ_EYE0_Y_OFST, RG_SSUSB_EQ_EYE0_Y, cOfst);                  //RG_SSUSB_RX_EYE0_Y
247                 U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0)
248                         , RG_SSUSB_EQ_EYE1_Y_OFST, RG_SSUSB_EQ_EYE1_Y, cOfst);                  //RG_SSUSB_RX_EYE1_Y
249         }
250         //ClearErrorResult
251         for(bIdxCycCnt = 0; bIdxCycCnt < CYCLE_COUNT_MAX; bIdxCycCnt++){
252                 for(bIdxX = 0; bIdxX < ERRCNT_MAX; bIdxX++)
253                 {
254                         for(bIdxY = 0; bIdxY < ERRCNT_MAX; bIdxY++){
255                                 pwErrCnt0[bIdxCycCnt][bIdxX][bIdxY] = 0;
256                                 pwErrCnt1[bIdxCycCnt][bIdxX][bIdxY] = 0;
257                         }
258                 }
259         }
260         isContinue = true;
261         while(isContinue){
262                 //printk(KERN_ERR "_bXcurr: %d, _bYcurr: %d\n", _bXcurr, _bYcurr);
263                 // The point is within the boundary, then let's check if it is within
264             // the testing region.
265             // The point is only test-able if one of the eye region
266             // includes this point.
267             fgValid = fgEyeScanHelper_CheckPtInRegion(&_rEye1, _bXcurr, _bYcurr)
268            || fgEyeScanHelper_CheckPtInRegion(&_rEye2, _bXcurr, _bYcurr);
269                 // Translate bX and bY to 2's complement from where the origin was on the
270                 // top left corner.
271                 // 0x40 and 0x3F needs a bit of thinking!!!! >"<
272                 cX = (_bXcurr ^ 0x40);
273                 cY = (_bYcurr ^ 0x3F);
274
275                 // Set X if necessary
276                 if (_fgXChged == true)
277                 {
278                         U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0)
279                                 , RG_SSUSB_EQ_EYE_XOFFSET_OFST, RG_SSUSB_EQ_EYE_XOFFSET, cX);           //RG_SSUSB_RX_EYE_XOFFSET
280                 }
281                 // Set Y
282                 U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0)
283                         , RG_SSUSB_EQ_EYE0_Y_OFST, RG_SSUSB_EQ_EYE0_Y, cY);                     //RG_SSUSB_RX_EYE0_Y
284                 U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0)
285                         , RG_SSUSB_EQ_EYE1_Y_OFST, RG_SSUSB_EQ_EYE1_Y, cY);                     //RG_SSUSB_RX_EYE1_Y
286
287                 /// Test this point!
288                 if (fgValid){
289                         for (bExtendCnt = 0; bExtendCnt < num_ignore_cnt; bExtendCnt++)
290                         {
291                                 //run test
292                                 EyeScanHelper_RunTest(info);
293                         }
294                         for (bExtendCnt = 0; bExtendCnt < num_cnt; bExtendCnt++)
295                         {
296                                 EyeScanHelper_RunTest(info);
297                                 wErr0 = U3PhyReadField32(((PHY_UINT32)&info->u3phyd_regs->phya_rx_mon3)
298                                         , RGS_SSUSB_EQ_EYE_MONITOR_ERRCNT_0_OFST, RGS_SSUSB_EQ_EYE_MONITOR_ERRCNT_0);
299                                 wErr1 = U3PhyReadField32(((PHY_UINT32)&info->u3phyd_regs->phya_rx_mon4)
300                                         , RGS_SSUSB_EQ_EYE_MONITOR_ERRCNT_1_OFST, RGS_SSUSB_EQ_EYE_MONITOR_ERRCNT_1);
301
302                                 pwErrCnt0[bExtendCnt][_bXcurr][_bYcurr] = wErr0;
303                                 pwErrCnt1[bExtendCnt][_bXcurr][_bYcurr] = wErr1;
304
305                                 //EyeScanHelper_GetResult(&_rRes.pwErrCnt0[bCnt], &_rRes.pwErrCnt1[bCnt]);
306 //                              printk(KERN_ERR "cnt[%d] cur_x,y [0x%x][0x%x], cX,cY [0x%x][0x%x], ErrCnt[%d][%d]\n"
307 //                                      , bExtendCnt, _bXcurr, _bYcurr, cX, cY, pwErrCnt0[bExtendCnt][_bXcurr][_bYcurr], pwErrCnt1[bExtendCnt][_bXcurr][_bYcurr]);
308                         }
309                         //printk(KERN_ERR "cur_x,y [0x%x][0x%x], cX,cY [0x%x][0x%x], ErrCnt[%d][%d]\n", _bXcurr, _bYcurr, cX, cY, pwErrCnt0[0][_bXcurr][_bYcurr], pwErrCnt1[0][_bXcurr][_bYcurr]);
310                 }
311                 else{
312                         
313                 }
314                 if (fgEyeScanHelper_CalNextPoint() == false){
315 #if 0
316                         printk(KERN_ERR "Xcurr [0x%x] Ycurr [0x%x]\n", _bXcurr, _bYcurr);
317                         printk(KERN_ERR "XcurrREG [0x%x] YcurrREG [0x%x]\n", cX, cY);
318 #endif
319                         printk(KERN_ERR "end of eye scan\n");
320                         isContinue = false;
321                 }
322         }
323         printk(KERN_ERR "CurX [0x%x] CurY [0x%x]\n"
324                 , U3PhyReadField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0), RG_SSUSB_EQ_EYE_XOFFSET_OFST, RG_SSUSB_EQ_EYE_XOFFSET)
325                 , U3PhyReadField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0), RG_SSUSB_EQ_EYE0_Y_OFST, RG_SSUSB_EQ_EYE0_Y));
326
327         // Move X,Y to the top-left corner
328         for (cOfst = 63; cOfst >= 0; cOfst--)
329         {
330                 U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0)
331                         , RG_SSUSB_EQ_EYE_XOFFSET_OFST, RG_SSUSB_EQ_EYE_XOFFSET, cOfst);        //RG_SSUSB_RX_EYE_XOFFSET
332         }
333         for (cOfst = 63; cOfst >= 0; cOfst--)
334         {
335                 U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0)
336                         , RG_SSUSB_EQ_EYE0_Y_OFST, RG_SSUSB_EQ_EYE0_Y, cOfst);
337                 U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0)
338                         , RG_SSUSB_EQ_EYE1_Y_OFST, RG_SSUSB_EQ_EYE1_Y, cOfst);
339
340         }
341         printk(KERN_ERR "CurX [0x%x] CurY [0x%x]\n"
342                 , U3PhyReadField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0), RG_SSUSB_EQ_EYE_XOFFSET_OFST, RG_SSUSB_EQ_EYE_XOFFSET)
343                 , U3PhyReadField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0), RG_SSUSB_EQ_EYE0_Y_OFST, RG_SSUSB_EQ_EYE0_Y));
344
345         printk(KERN_ERR "PI result: %d\n", _bPIResult);
346         printk(KERN_ERR "pwErrCnt0 addr: 0x%x\n", (PHY_UINT32)pwErrCnt0);
347         printk(KERN_ERR "pwErrCnt1 addr: 0x%x\n", (PHY_UINT32)pwErrCnt1);
348         
349         return PHY_TRUE;
350 }
351
352 //not used on SoC
353 PHY_INT32 u2_save_cur_en(struct u3phy_info *info){
354         return PHY_TRUE;
355 }
356
357 //not used on SoC
358 PHY_INT32 u2_save_cur_re(struct u3phy_info *info){
359         return PHY_TRUE;
360 }
361
362 PHY_INT32 u2_slew_rate_calibration(struct u3phy_info *info){
363         PHY_INT32 i=0;
364         //PHY_INT32 j=0;
365         //PHY_INT8 u1SrCalVal = 0;
366         //PHY_INT8 u1Reg_addr_HSTX_SRCAL_EN;
367         PHY_INT32 fgRet = 0;    
368         PHY_INT32 u4FmOut = 0;  
369         PHY_INT32 u4Tmp = 0;
370         //PHY_INT32 temp;
371
372         // => RG_USB20_HSTX_SRCAL_EN = 1
373         // enable HS TX SR calibration
374         U3PhyWriteField32(((PHY_UINT32)&info->u2phy_regs->u2phyacr0)
375                 , RG_USB20_HSTX_SRCAL_EN_OFST, RG_USB20_HSTX_SRCAL_EN, 0x1);
376         DRV_MSLEEP(1);
377
378         // => RG_FRCK_EN = 1    
379         // Enable free run clock
380         U3PhyWriteField32(((PHY_UINT32)&info->sifslv_fm_regs->fmmonr1)
381                 , RG_FRCK_EN_OFST, RG_FRCK_EN, 1);
382
383         // MT6290 HS signal quality patch
384         // => RG_CYCLECNT = 400
385         // Setting cyclecnt =400
386         U3PhyWriteField32(((PHY_UINT32)&info->sifslv_fm_regs->fmcr0)
387                 , RG_CYCLECNT_OFST, RG_CYCLECNT, 0x400);
388
389         // => RG_FREQDET_EN = 1
390         // Enable frequency meter
391         U3PhyWriteField32(((PHY_UINT32)&info->sifslv_fm_regs->fmcr0)
392                 , RG_FREQDET_EN_OFST, RG_FREQDET_EN, 0x1);
393
394         // wait for FM detection done, set 10ms timeout
395         for(i=0; i<10; i++){
396                 // => u4FmOut = USB_FM_OUT
397                 // read FM_OUT
398                 u4FmOut = U3PhyReadReg32(((PHY_UINT32)&info->sifslv_fm_regs->fmmonr0));
399                 printk("FM_OUT value: u4FmOut = %d(0x%08X)\n", u4FmOut, u4FmOut);
400
401                 // check if FM detection done 
402                 if (u4FmOut != 0)
403                 {
404                         fgRet = 0;
405                         printk("FM detection done! loop = %d\n", i);
406                         
407                         break;
408                 }
409
410                 fgRet = 1;
411                 DRV_MSLEEP(1);
412         }
413         // => RG_FREQDET_EN = 0
414         // disable frequency meter
415         U3PhyWriteField32(((PHY_UINT32)&info->sifslv_fm_regs->fmcr0)
416                 , RG_FREQDET_EN_OFST, RG_FREQDET_EN, 0);
417
418         // => RG_FRCK_EN = 0
419         // disable free run clock
420         U3PhyWriteField32(((PHY_UINT32)&info->sifslv_fm_regs->fmmonr1)
421                 , RG_FRCK_EN_OFST, RG_FRCK_EN, 0);
422
423         // => RG_USB20_HSTX_SRCAL_EN = 0
424         // disable HS TX SR calibration
425         U3PhyWriteField32(((PHY_UINT32)&info->u2phy_regs->u2phyacr0)
426                 , RG_USB20_HSTX_SRCAL_EN_OFST, RG_USB20_HSTX_SRCAL_EN, 0);
427         DRV_MSLEEP(1);
428
429         if(u4FmOut == 0){
430                 U3PhyWriteField32(((PHY_UINT32)&info->u2phy_regs->u2phyacr0)
431                         , RG_USB20_HSTX_SRCTRL_OFST, RG_USB20_HSTX_SRCTRL, 0x4);
432                 
433                 fgRet = 1;
434         }
435         else{
436                 // set reg = (1024/FM_OUT) * 25 * 0.028 (round to the nearest digits)
437                 u4Tmp = (((1024 * 25 * U2_SR_COEF_7621) / u4FmOut) + 500) / 1000;
438                 printk("SR calibration value u1SrCalVal = %d\n", (PHY_UINT8)u4Tmp);
439                 U3PhyWriteField32(((PHY_UINT32)&info->u2phy_regs->u2phyacr0)
440                         , RG_USB20_HSTX_SRCTRL_OFST, RG_USB20_HSTX_SRCTRL, u4Tmp);
441         }
442         return fgRet;
443 }
444
445 #endif