mediatek: add support for rtl8367c
[openwrt/staging/jow.git] / target / linux / mediatek / files-5.4 / drivers / net / phy / rtk / rtl8367c / rtl8367c_asicdrv_green.c
1 /*
2 * Copyright (C) 2013 Realtek Semiconductor Corp.
3 * All Rights Reserved.
4 *
5 * Unless you and Realtek execute a separate written software license
6 * agreement governing use of this software, this software is licensed
7 * to you under the terms of the GNU General Public License version 2,
8 * available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
9 *
10 * $Revision: 76306 $
11 * $Date: 2017-03-08 15:13:58 +0800 (週三, 08 三月 2017) $
12 *
13 * Purpose : RTL8367C switch high-level API for RTL8367C
14 * Feature : Green ethernet related functions
15 *
16 */
17 #include <rtl8367c_asicdrv_green.h>
18
19 /* Function Name:
20 * rtl8367c_getAsicGreenPortPage
21 * Description:
22 * Get per-Port ingress page usage per second
23 * Input:
24 * port - Physical port number (0~7)
25 * pPage - page number of ingress packet occuping per second
26 * Output:
27 * None
28 * Return:
29 * RT_ERR_OK - Success
30 * RT_ERR_SMI - SMI access error
31 * RT_ERR_PORT_ID - Invalid port number
32 * Note:
33 * Ingress traffic occuping page number per second for high layer green feature usage
34 */
35 ret_t rtl8367c_getAsicGreenPortPage(rtk_uint32 port, rtk_uint32* pPage)
36 {
37 ret_t retVal;
38 rtk_uint32 regData;
39 rtk_uint32 pageMeter;
40
41 if(port > RTL8367C_PORTIDMAX)
42 return RT_ERR_PORT_ID;
43
44 retVal = rtl8367c_getAsicReg(RTL8367C_PAGEMETER_PORT_REG(port), &regData);
45 if(retVal != RT_ERR_OK)
46 return retVal;
47
48 pageMeter = regData;
49
50 retVal = rtl8367c_getAsicReg(RTL8367C_PAGEMETER_PORT_REG(port) + 1, &regData);
51 if(retVal != RT_ERR_OK)
52 return retVal;
53
54 pageMeter = pageMeter + (regData << 16);
55
56 *pPage = pageMeter;
57 return RT_ERR_OK;
58 }
59 /* Function Name:
60 * rtl8367c_setAsicGreenTrafficType
61 * Description:
62 * Set traffic type for each priority
63 * Input:
64 * priority - internal priority (0~7)
65 * traffictype - high/low traffic type, 1:high priority traffic type, 0:low priority traffic type
66 * Output:
67 * None
68 * Return:
69 * RT_ERR_OK - Success
70 * RT_ERR_SMI - SMI access error
71 * RT_ERR_QOS_INT_PRIORITY - Invalid priority
72 * Note:
73 * None
74 */
75 ret_t rtl8367c_setAsicGreenTrafficType(rtk_uint32 priority, rtk_uint32 traffictype)
76 {
77
78 if(priority > RTL8367C_PRIMAX)
79 return RT_ERR_QOS_INT_PRIORITY;
80
81 return rtl8367c_setAsicRegBit(RTL8367C_REG_HIGHPRI_CFG, priority, (traffictype?1:0));
82 }
83 /* Function Name:
84 * rtl8367c_getAsicGreenTrafficType
85 * Description:
86 * Get traffic type for each priority
87 * Input:
88 * priority - internal priority (0~7)
89 * pTraffictype - high/low traffic type, 1:high priority traffic type, 0:low priority traffic type
90 * Output:
91 * None
92 * Return:
93 * RT_ERR_OK - Success
94 * RT_ERR_SMI - SMI access error
95 * RT_ERR_QOS_INT_PRIORITY - Invalid priority
96 * Note:
97 * None
98 */
99 ret_t rtl8367c_getAsicGreenTrafficType(rtk_uint32 priority, rtk_uint32* pTraffictype)
100 {
101 if(priority > RTL8367C_PRIMAX)
102 return RT_ERR_QOS_INT_PRIORITY;
103
104 return rtl8367c_getAsicRegBit(RTL8367C_REG_HIGHPRI_CFG, priority, pTraffictype);
105 }
106
107 /* Function Name:
108 * rtl8367c_setAsicGreenHighPriorityTraffic
109 * Description:
110 * Set indicator which ASIC had received high priority traffic
111 * Input:
112 * port - Physical port number (0~7)
113 * Output:
114 * None
115 * Return:
116 * RT_ERR_OK - Success
117 * RT_ERR_SMI - SMI access error
118 * RT_ERR_PORT_ID - Invalid port number
119 * Note:
120 * None
121 */
122 ret_t rtl8367c_setAsicGreenHighPriorityTraffic(rtk_uint32 port)
123 {
124 if(port > RTL8367C_PORTIDMAX)
125 return RT_ERR_PORT_ID;
126
127 return rtl8367c_setAsicRegBit(RTL8367C_REG_HIGHPRI_INDICATOR, port, 1);
128 }
129
130
131 /* Function Name:
132 * rtl8367c_getAsicGreenHighPriorityTraffic
133 * Description:
134 * Get indicator which ASIC had received high priority traffic or not
135 * Input:
136 * port - Physical port number (0~7)
137 * pIndicator - Have received high priority traffic indicator. If 1 means ASCI had received high priority in 1second checking priod
138 * Output:
139 * None
140 * Return:
141 * RT_ERR_OK - Success
142 * RT_ERR_SMI - SMI access error
143 * RT_ERR_PORT_ID - Invalid port number
144 * Note:
145 * None
146 */
147 ret_t rtl8367c_getAsicGreenHighPriorityTraffic(rtk_uint32 port, rtk_uint32* pIndicator)
148 {
149 if(port > RTL8367C_PORTIDMAX)
150 return RT_ERR_PORT_ID;
151
152 return rtl8367c_getAsicRegBit(RTL8367C_REG_HIGHPRI_INDICATOR, port, pIndicator);
153 }
154
155 /*
156 @func rtk_int32 | rtl8367c_setAsicGreenEthernet | Set green ethernet function.
157 @parm rtk_uint32 | green | Green feature function usage 1:enable 0:disable.
158 @rvalue RT_ERR_OK | Success.
159 @rvalue RT_ERR_SMI | SMI access error.
160 @comm
161 The API can set Green Ethernet function to reduce power consumption. While green feature is enabled, ASIC will automatic
162 detect the cable length and then select different power mode for best performance with minimums power consumption. Link down
163 ports will enter power savining mode in 10 seconds after the cable disconnected if power saving function is enabled.
164 */
165 ret_t rtl8367c_setAsicGreenEthernet(rtk_uint32 port, rtk_uint32 green)
166 {
167 ret_t retVal;
168 rtk_uint32 checkCounter;
169 rtk_uint32 regData;
170 rtk_uint32 phy_status;
171 rtk_uint32 patchData[6][2] = { {0x809A, 0x8911}, {0x80A3, 0x9233}, {0x80AC, 0xA444}, {0x809F, 0x6B20}, {0x80A8, 0x6B22}, {0x80B1, 0x6B23} };
172 rtk_uint32 idx;
173 rtk_uint32 data;
174
175 if (green > 1)
176 return RT_ERR_INPUT;
177
178 /* 0xa420[2:0] */
179 if((retVal = rtl8367c_getAsicPHYOCPReg(port, 0xA420, &regData)) != RT_ERR_OK)
180 return retVal;
181 phy_status = (regData & 0x0007);
182
183 if(phy_status == 3)
184 {
185 /* 0xb820[4] = 1 */
186 if((retVal = rtl8367c_getAsicPHYOCPReg(port, 0xB820, &regData)) != RT_ERR_OK)
187 return retVal;
188
189 regData |= (0x0001 << 4);
190
191 if((retVal = rtl8367c_setAsicPHYOCPReg(port, 0xB820, regData)) != RT_ERR_OK)
192 return retVal;
193
194 /* wait 0xb800[6] = 1 */
195 checkCounter = 100;
196 while(checkCounter)
197 {
198 retVal = rtl8367c_getAsicPHYOCPReg(port, 0xB800, &regData);
199 if( (retVal != RT_ERR_OK) || ((regData & 0x0040) != 0x0040) )
200 {
201 checkCounter --;
202 if(0 == checkCounter)
203 return RT_ERR_BUSYWAIT_TIMEOUT;
204 }
205 else
206 checkCounter = 0;
207 }
208 }
209
210 if((retVal = rtl8367c_setAsicReg(0x13C2, 0x0249)) != RT_ERR_OK)
211 return retVal;
212
213 if((retVal = rtl8367c_getAsicReg(0x1300, &data)) != RT_ERR_OK)
214 return retVal;
215
216 if((retVal = rtl8367c_setAsicReg(0x13C2, 0x0000)) != RT_ERR_OK)
217 return retVal;
218
219 switch (data)
220 {
221 case 0x0276:
222 case 0x0597:
223 case 0x6367:
224 if(green)
225 {
226 for(idx = 0; idx < 6; idx++ )
227 {
228 if((retVal = rtl8367c_setAsicPHYOCPReg(port, 0xA436, patchData[idx][0])) != RT_ERR_OK)
229 return retVal;
230
231 if((retVal = rtl8367c_setAsicPHYOCPReg(port, 0xA438, patchData[idx][1])) != RT_ERR_OK)
232 return retVal;
233 }
234 }
235 break;
236 default:
237 break;;
238 }
239
240
241
242 /* 0xa436 = 0x8011 */
243 if((retVal = rtl8367c_setAsicPHYOCPReg(port, 0xA436, 0x8011)) != RT_ERR_OK)
244 return retVal;
245
246 /* wr 0xa438[15] = 0: disable, 1: enable */
247 if((retVal = rtl8367c_getAsicPHYOCPReg(port, 0xA438, &regData)) != RT_ERR_OK)
248 return retVal;
249
250 if(green)
251 regData |= 0x8000;
252 else
253 regData &= 0x7FFF;
254
255 if((retVal = rtl8367c_setAsicPHYOCPReg(port, 0xA438, regData)) != RT_ERR_OK)
256 return retVal;
257
258 if(phy_status == 3)
259 {
260 /* 0xb820[4] = 0 */
261 if((retVal = rtl8367c_getAsicPHYOCPReg(port, 0xB820, &regData)) != RT_ERR_OK)
262 return retVal;
263
264 regData &= ~(0x0001 << 4);
265
266 if((retVal = rtl8367c_setAsicPHYOCPReg(port, 0xB820, regData)) != RT_ERR_OK)
267 return retVal;
268
269 /* wait 0xb800[6] = 0 */
270 checkCounter = 100;
271 while(checkCounter)
272 {
273 retVal = rtl8367c_getAsicPHYOCPReg(port, 0xB800, &regData);
274 if( (retVal != RT_ERR_OK) || ((regData & 0x0040) != 0x0000) )
275 {
276 checkCounter --;
277 if(0 == checkCounter)
278 return RT_ERR_BUSYWAIT_TIMEOUT;
279 }
280 else
281 checkCounter = 0;
282 }
283 }
284
285 return RT_ERR_OK;
286 }
287
288 /*
289 @func rtk_int32 | rtl8367c_getAsicGreenEthernet | Get green ethernet function.
290 @parm rtk_uint32 | *green | Green feature function usage 1:enable 0:disable.
291 @rvalue RT_ERR_OK | Success.
292 @rvalue RT_ERR_SMI | SMI access error.
293 @comm
294 The API can set Green Ethernet function to reduce power consumption. While green feature is enabled, ASIC will automatic
295 detect the cable length and then select different power mode for best performance with minimums power consumption. Link down
296 ports will enter power savining mode in 10 seconds after the cable disconnected if power saving function is enabled.
297 */
298 ret_t rtl8367c_getAsicGreenEthernet(rtk_uint32 port, rtk_uint32* green)
299 {
300 ret_t retVal;
301 rtk_uint32 regData;
302
303 /* 0xa436 = 0x8011 */
304 if((retVal = rtl8367c_setAsicPHYOCPReg(port, 0xA436, 0x8011)) != RT_ERR_OK)
305 return retVal;
306
307 /* wr 0xa438[15] = 0: disable, 1: enable */
308 if((retVal = rtl8367c_getAsicPHYOCPReg(port, 0xA438, &regData)) != RT_ERR_OK)
309 return retVal;
310
311 if(regData & 0x8000)
312 *green = ENABLED;
313 else
314 *green = DISABLED;
315
316 return RT_ERR_OK;
317 }
318
319
320 /*
321 @func ret_t | rtl8367c_setAsicPowerSaving | Set power saving mode
322 @parm rtk_uint32 | phy | phy number
323 @parm rtk_uint32 | enable | enable power saving mode.
324 @rvalue RT_ERR_OK | Success.
325 @rvalue RT_ERR_SMI | SMI access error.
326 @rvalue RT_ERR_PORT_ID | Invalid port number.
327 @comm
328 The API can set power saving mode per phy.
329 */
330 ret_t rtl8367c_setAsicPowerSaving(rtk_uint32 phy, rtk_uint32 enable)
331 {
332 rtk_api_ret_t retVal;
333 rtk_uint32 phyData;
334 rtk_uint32 regData;
335 rtk_uint32 phy_status;
336 rtk_uint32 checkCounter;
337
338 if (enable > 1)
339 return RT_ERR_INPUT;
340
341 /* 0xa420[2:0] */
342 if((retVal = rtl8367c_getAsicPHYOCPReg(phy, 0xA420, &regData)) != RT_ERR_OK)
343 return retVal;
344
345 phy_status = (regData & 0x0007);
346
347 if(phy_status == 3)
348 {
349 /* 0xb820[4] = 1 */
350 if((retVal = rtl8367c_getAsicPHYOCPReg(phy, 0xB820, &regData)) != RT_ERR_OK)
351 return retVal;
352
353 regData |= (0x0001 << 4);
354
355 if((retVal = rtl8367c_setAsicPHYOCPReg(phy, 0xB820, regData)) != RT_ERR_OK)
356 return retVal;
357
358 /* wait 0xb800[6] = 1 */
359 checkCounter = 100;
360 while(checkCounter)
361 {
362 retVal = rtl8367c_getAsicPHYOCPReg(phy, 0xB800, &regData);
363 if( (retVal != RT_ERR_OK) || ((regData & 0x0040) != 0x0040) )
364 {
365 checkCounter --;
366 if(0 == checkCounter)
367 {
368 return RT_ERR_BUSYWAIT_TIMEOUT;
369 }
370 }
371 else
372 checkCounter = 0;
373 }
374 }
375
376 if ((retVal = rtl8367c_getAsicPHYReg(phy,PHY_POWERSAVING_REG,&phyData))!=RT_ERR_OK)
377 return retVal;
378
379 phyData = phyData & ~(0x0001 << 2);
380 phyData = phyData | (enable << 2);
381
382 if ((retVal = rtl8367c_setAsicPHYReg(phy,PHY_POWERSAVING_REG,phyData))!=RT_ERR_OK)
383 return retVal;
384
385 if(phy_status == 3)
386 {
387 /* 0xb820[4] = 0 */
388 if((retVal = rtl8367c_getAsicPHYOCPReg(phy, 0xB820, &regData)) != RT_ERR_OK)
389 return retVal;
390
391 regData &= ~(0x0001 << 4);
392
393 if((retVal = rtl8367c_setAsicPHYOCPReg(phy, 0xB820, regData)) != RT_ERR_OK)
394 return retVal;
395
396 /* wait 0xb800[6] = 0 */
397 checkCounter = 100;
398 while(checkCounter)
399 {
400 retVal = rtl8367c_getAsicPHYOCPReg(phy, 0xB800, &regData);
401 if( (retVal != RT_ERR_OK) || ((regData & 0x0040) != 0x0000) )
402 {
403 checkCounter --;
404 if(0 == checkCounter)
405 {
406 return RT_ERR_BUSYWAIT_TIMEOUT;
407 }
408 }
409 else
410 checkCounter = 0;
411 }
412 }
413
414 return RT_ERR_OK;
415 }
416
417 /*
418 @func ret_t | rtl8367c_getAsicPowerSaving | Get power saving mode
419 @parm rtk_uint32 | port | The port number
420 @parm rtk_uint32* | enable | enable power saving mode.
421 @rvalue RT_ERR_OK | Success.
422 @rvalue RT_ERR_SMI | SMI access error.
423 @rvalue RT_ERR_PORT_ID | Invalid port number.
424 @comm
425 The API can get power saving mode per phy.
426 */
427 ret_t rtl8367c_getAsicPowerSaving(rtk_uint32 phy, rtk_uint32* enable)
428 {
429 rtk_api_ret_t retVal;
430 rtk_uint32 phyData;
431
432 if(NULL == enable)
433 return RT_ERR_NULL_POINTER;
434
435 if ((retVal = rtl8367c_getAsicPHYReg(phy,PHY_POWERSAVING_REG,&phyData))!=RT_ERR_OK)
436 return retVal;
437
438 if ((phyData & 0x0004) > 0)
439 *enable = 1;
440 else
441 *enable = 0;
442
443 return RT_ERR_OK;
444 }
445