MOXA linux-2.6.x / linux-2.6.19-uc1 from UC-7110-LX-BOOTLOADER-1.9_VERSION-4.2.tgz
[linux-2.6.19-moxart.git] / drivers / net / ks8695 / ks8695_fxhw.c
blob8062c683d74f85efcff468c04047abeb8483ed61
1 /*
2 Copyright (c) 2002-2003, Micrel Semiconductor
4 Written 2002 by LIQUN RUAN
6 This software may be used and distributed according to the terms of
7 the GNU General Public License (GPL), incorporated herein by reference.
8 Drivers based on or derived from this code fall under the GPL and must
9 retain the authorship, copyright and license notice. This file is not
10 a complete program and may only be used when the entire operating
11 system is licensed under the GPL.
13 The author may be reached as liqun.ruan@micrel.com
14 Micrel Semiconductor
15 1931 Fortune Dr.
16 San Jose, CA 95131
18 This driver is for Micrel's KS8695/KS8695P SOHO Router Chipset as ethernet driver.
20 Support and updates available at
21 www.micrel.com/ks8695/ not ready yet!!!
24 #include "ks8695_drv.h"
25 #include "ks8695_chipdef.h"
26 #include "ks8695_ioctrl.h"
27 #include "ks8695_cache.h"
29 static int macReset(PADAPTER_STRUCT Adapter);
30 static void macConfigure(PADAPTER_STRUCT Adapter);
31 static void macConfigureFlow(PADAPTER_STRUCT Adapter, uint8_t bFlowCtrl);
32 static void macConfigureInterrupt(PADAPTER_STRUCT Adapter);
34 static void swConfigure(PADAPTER_STRUCT Adapter);
35 static void swCreateLookUpTable(PADAPTER_STRUCT Adapter);
37 static void gpioConfigure(PADAPTER_STRUCT Adapter);
39 #ifdef CONFIG_ARCH_KS8695P
40 void forceFlowControl(PADAPTER_STRUCT Adapter, UINT uPort, UINT bOn);
41 void backPressureEnable(PADAPTER_STRUCT Adapter, UINT uPort, UINT bOn);
42 #endif
45 * ks8695_ChipInit
46 * This function is used to do chip initialization.
48 * Argument(s)
49 * Adapter pointer to ADAPTER_STRUCT structure.
50 * bResetPhy flag indicates whether to reset PHY as well
52 * Return(s)
53 * TRUE if success
54 * FALSE otherwise
56 BOOLEAN ks8695_ChipInit(PADAPTER_STRUCT Adapter, BOOLEAN bResetPhy)
58 BOOLEAN bStatus;
59 struct net_device *netdev = Adapter->netdev;
60 UINT i;
62 #ifdef DEBUG_THIS
63 DRV_INFO("%s", __FUNCTION__);
64 #endif
66 if (bResetPhy) {
67 /* phy related initialization */
68 i = 0;
69 swPhyReset(Adapter, i);
70 if (DMA_LAN == DI.usDMAId) {
71 for (i = 1; i < SW_MAX_LAN_PORTS; i++) {
72 swPhyReset(Adapter, i);
73 /* turn off GPIO, to make sure that if there is no cable connection, no light */
74 gpioSet(Adapter, i, FALSE);
77 swAutoNegoAdvertisement(Adapter, 0);
78 if (DMA_LAN == DI.usDMAId) {
79 for (i = 1; i < SW_MAX_LAN_PORTS; i++) {
80 swAutoNegoAdvertisement(Adapter, i);
85 /* setup mac related stuff */
86 bStatus = macReset(Adapter);
87 if (bStatus) {
88 DRV_ERR("%s: macReset failed", __FUNCTION__);
89 return FALSE;
91 macConfigure(Adapter);
92 macConfigureInterrupt(Adapter);
94 /* turn off GPIO, to make sure that if there is no cable connection, no light */
95 gpioSet(Adapter, 0, FALSE);
96 /* configuration switch related to LAN only */
97 if (DMA_LAN == DI.usDMAId) {
98 swConfigure(Adapter);
99 swCreateLookUpTable(Adapter);
100 for (i = 1; i < SW_MAX_LAN_PORTS; i++) {
101 /* turn off GPIO, to make sure that if there is no cable connection, no light */
102 gpioSet(Adapter, i, FALSE);
106 /* copy the MAC address out of Station registers */
107 macSetStationAddress(Adapter, DI.stMacStation);
108 if (netdev->addr_len < MAC_ADDRESS_LEN)
109 netdev->addr_len = MAC_ADDRESS_LEN;
110 memcpy(netdev->dev_addr, DI.stMacStation, netdev->addr_len);
111 memcpy(DI.stMacCurrent, netdev->dev_addr, netdev->addr_len);
113 #ifdef DEBUG_THIS
114 DRV_INFO("MAC address %02X:%02X:%02X:%02X:%02X:%02X",
115 DI.stMacStation[0],
116 DI.stMacStation[1],
117 DI.stMacStation[2],
118 DI.stMacStation[3],
119 DI.stMacStation[4],
120 DI.stMacStation[5]);
121 #endif
123 gpioConfigure(Adapter);
125 /*RLQ, 11/20/2002, fix based on AN112. Changing transmitter gain in KS8695 to improve
126 the calbe length at which the Ethernet can operate */
127 if (0 == Adapter->rev) {
128 /* for KS8695 */
129 KS8695_WRITE_REG(KS8695_WAN_PHY_CONTROL, 0x0000b000);
131 else {
132 /* for KS8695P, rev A */
133 KS8695_WRITE_REG(KS8695_WAN_PHY_CONTROL, 0x0200b000);
136 return bStatus ? FALSE : TRUE;
139 #define IRQ_WAN_LEVEL 12
140 #define IRQ_LAN_LEVEL 10
141 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
142 #define IRQ_HPNA_LEVEL 8
143 #endif
145 /* move to source file later */
146 static INTCFG stDMAIntCfg[32] = {
147 { 0, -1 }, /* -1 don't touch, it's not ours */
148 { 0, -1 },
149 { 0, -1 },
150 { 0, -1 },
151 { 0, -1 },
152 { 0, -1 },
153 { 0, -1 },
154 { 0, -1 },
155 { 0, -1 },
156 { 0, -1 },
157 { 0, -1 },
158 { 0, -1 }, /* bit 11 */
160 { 0, 0x0b }, /* bit 12, LAN */
161 { 0, 0x0b },
162 { 0, 0x0a },
163 { 0, 0x0a },
164 { 0, 0x0f },
165 { 0, 0x0f },
167 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
168 { 0, IRQ_HPNA_LEVEL }, /* bit 18, HPNA */
169 { 0, IRQ_HPNA_LEVEL },
170 { 0, IRQ_HPNA_LEVEL },
171 { 0, IRQ_HPNA_LEVEL },
172 { 0, IRQ_HPNA_LEVEL },
173 { 0, IRQ_HPNA_LEVEL },
174 #else
175 { 0, -1 }, /* bit 18, KS8695P doesn't have HPNA port */
176 { 0, -1 },
177 { 0, -1 },
178 { 0, -1 },
179 { 0, -1 },
180 { 0, -1 },
181 #endif
182 { 0, -1 }, /* bit 24 */
184 { 0, 0x0b }, /* bit 25, WAN */
185 { 0, 0x0b },
186 { 0, 0x0a },
187 { 0, 0x0a },
188 { 0, 0x0f },
189 { 0, 0x0f },
190 { 0, IRQ_WAN_LEVEL } /* WAN link */
194 * macReset
195 * This function will execute a soft reset the chipset.
197 * Argument(s)
198 * Adapter pointer to ADAPTER_STRUCT structure.
200 * Return(s)
201 * 0 if success
202 * none zero otherwise
204 int macReset(PADAPTER_STRUCT Adapter)
206 int nTimeOut = 1000;
207 UINT32 uReg;
208 unsigned long flags;
210 #ifdef DEBUG_THIS
211 DRV_INFO("%s", __FUNCTION__);
212 #endif
214 spin_lock_irqsave(&DI.lock, flags);
215 /*spin_lock(&DI.lock);*/
216 /* disable IER if any */
217 uReg = KS8695_READ_REG(KS8695_INT_ENABLE);
218 switch (DI.usDMAId) {
219 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
220 case DMA_HPNA:
221 uReg &= ~INT_HPNA_MASK;
222 break;
223 #endif
225 case DMA_LAN:
226 uReg &= ~INT_LAN_MASK;
227 break;
229 default:
230 case DMA_WAN:
231 uReg &= ~INT_WAN_MASK;
232 break;
234 KS8695_WRITE_REG(KS8695_INT_ENABLE, uReg);
235 /*spin_unlock(&DI.lock);*/
236 spin_unlock_irqrestore(&DI.lock, flags);
238 /* reset corresponding register and wait for completion */
239 KS8695_WRITE_REG(REG_TXCTRL + DI.nOffset, DMA_SOFTRESET);
242 DelayInMilliseconds(1);
243 uReg = KS8695_READ_REG(REG_TXCTRL + DI.nOffset);
244 if (!(uReg & DMA_SOFTRESET))
245 break;
246 } while (--nTimeOut);
248 if (nTimeOut < 1) {
249 DRV_ERR("%s> timeout error", __FUNCTION__);
250 return -ETIMEDOUT;
253 /* clear statistic counters */
254 swResetSNMPInfo(Adapter);
255 #ifdef DEBUG_THIS
256 DRV_INFO("%s> succeeded (timeout count=%d)", __FUNCTION__, nTimeOut);
257 #endif
259 return 0;
263 * macConfigure
264 * This function is used to set MAC control register based on configurable
265 * option settings.
267 * Argument(s)
268 * Adapter pointer to ADAPTER_STRUCT structure.
270 * Return(s)
271 * NONE
273 void macConfigure(PADAPTER_STRUCT Adapter)
275 UINT uRxReg, uTxReg;
277 #ifdef DEBUG_THIS
278 DRV_INFO("%s", __FUNCTION__);
279 #endif
281 /* read TX mode register */
282 uTxReg = KS8695_READ_REG(REG_TXCTRL + DI.nOffset);
283 /* clear PBL bits first */
284 uTxReg &= ~DMA_PBLTMASK; /* 29:24 */
285 if (DI.byTxPBL)
286 uTxReg |= ((uint32_t)DI.byTxPBL << DMA_PBLTSHIFT);
288 if (DI.bTxChecksum) {
289 uTxReg |= (DMA_IPCHECKSUM | DMA_TCPCHECKSUM | DMA_UDPCHECKSUM);
291 else {
292 uTxReg &= ~(DMA_IPCHECKSUM | DMA_TCPCHECKSUM | DMA_UDPCHECKSUM);
295 if (DI.bTxFlowCtrl)
297 uTxReg |= DMA_FLOWCTRL;
299 else {
300 uTxReg &= ~DMA_FLOWCTRL;
302 uTxReg |= (DMA_PADDING | DMA_CRC);
303 /* write TX mode register */
304 KS8695_WRITE_REG(REG_TXCTRL + DI.nOffset, uTxReg);
306 /* read RX mode register */
307 uRxReg = KS8695_READ_REG(REG_RXCTRL + DI.nOffset);
308 /* clear PBL bits first */
309 uRxReg &= ~DMA_PBLTMASK; /* 29:24 */
310 if (DI.byRxPBL)
311 uRxReg |= ((uint32_t)DI.byRxPBL << DMA_PBLTSHIFT);
312 /* checksum */
313 if (DI.bRxChecksum) {
314 uRxReg |= (DMA_IPCHECKSUM | DMA_TCPCHECKSUM | DMA_UDPCHECKSUM);
316 else {
317 uRxReg &= ~(DMA_IPCHECKSUM | DMA_TCPCHECKSUM | DMA_UDPCHECKSUM);
319 /* flow control */
320 if (DI.bRxFlowCtrl)
322 uRxReg |= DMA_FLOWCTRL;
324 else {
325 uRxReg &= ~DMA_FLOWCTRL;
327 /* set unicast only, and let ks8695_set_multi function to set the rest */
328 uRxReg |= DMA_UNICAST;
330 /* write RX mode register */
331 KS8695_WRITE_REG(REG_RXCTRL + DI.nOffset, uRxReg);
335 * macConfigureFlow
336 * This function is used to set mac flow control as a workaround for WAN port.
337 * option settings.
339 * Argument(s)
340 * Adapter pointer to ADAPTER_STRUCT structure.
341 * bFlowCtrl flow control to set
343 * Return(s)
344 * NONE
346 void macConfigureFlow(PADAPTER_STRUCT Adapter, uint8_t bFlowCtrl)
348 UINT uRxReg, uTxReg;
349 BOOLEAN bTxStarted, bRxStarted;
351 #ifdef DEBUG_THIS
352 DRV_INFO("%s: flowctrl = %d", __FUNCTION__, bFlowCtrl);
353 #endif
355 /* need to stop mac engines if started */
356 bTxStarted = DI.bTxStarted;
357 bRxStarted = DI.bRxStarted;
358 if (bRxStarted)
359 macStartRx(Adapter, FALSE);
360 if (bTxStarted)
361 macStartTx(Adapter, FALSE);
363 /* read TX mode register */
364 uTxReg = KS8695_READ_REG(REG_TXCTRL + DI.nOffset);
365 if (bFlowCtrl)
367 uTxReg |= DMA_FLOWCTRL;
369 else {
370 uTxReg &= ~DMA_FLOWCTRL;
372 /* write TX mode register */
373 KS8695_WRITE_REG(REG_TXCTRL + DI.nOffset, uTxReg);
375 /* read RX mode register */
376 uRxReg = KS8695_READ_REG(REG_RXCTRL + DI.nOffset);
377 if (bFlowCtrl)
379 uRxReg |= DMA_FLOWCTRL;
381 else {
382 uRxReg &= ~DMA_FLOWCTRL;
384 /* write RX mode register */
385 KS8695_WRITE_REG(REG_RXCTRL + DI.nOffset, uRxReg);
387 if (bRxStarted)
388 macStartRx(Adapter, TRUE);
389 if (bTxStarted)
390 macStartTx(Adapter, TRUE);
394 * macSetLoopback
395 * This function is used to set MAC lookback mode (for debugging purpose)
397 * Argument(s)
398 * Adapter pointer to ADAPTER_STRUCT structure.
400 * Return(s)
401 * NONE
403 void macSetLoopback(PADAPTER_STRUCT Adapter, BOOLEAN bLoopback)
405 UINT uTxReg;
406 BOOLEAN bTxStarted, bRxStarted;
408 bTxStarted = DI.bTxStarted;
409 bRxStarted = DI.bRxStarted;
410 if (bRxStarted)
411 macStartRx(Adapter, FALSE);
412 if (bTxStarted)
413 macStartTx(Adapter, FALSE);
415 /* read TX mode register */
416 uTxReg = KS8695_READ_REG(REG_TXCTRL + DI.nOffset);
418 if (bLoopback)
420 uTxReg |= DMA_LOOPBACK;
422 else {
423 uTxReg &= ~DMA_LOOPBACK;
426 /* write TX mode register */
427 KS8695_WRITE_REG(REG_TXCTRL + DI.nOffset, uTxReg);
429 if (bRxStarted)
430 macStartRx(Adapter, TRUE);
431 if (bTxStarted)
432 macStartTx(Adapter, TRUE);
436 * macStartRx
437 * This routine will start/stop RX machine.
439 * Inputs:
440 * Adapter pointer to ADAPTER_STRUCT data structure.
441 * bStart TRUE if start Rx machine, FALSE if stop it
443 * Returns:
444 * NONE
446 void macStartRx(PADAPTER_STRUCT Adapter, BOOLEAN bStart)
448 UINT32 uReg;
450 uReg = KS8695_READ_REG(REG_RXCTRL + DI.nOffset);
451 if (bStart) {
452 /* start RX machine */
453 uReg |= DMA_START;
454 DI.bRxStarted = FALSE;
455 } else {
456 /* Stop RX machine */
457 uReg &= ~DMA_START;
458 DI.bRxStarted = FALSE;
460 KS8695_WRITE_REG(REG_RXCTRL + DI.nOffset, uReg);
462 /* if there descriptors available for rx, tick off Rx engine */
463 if (bStart) {
464 if (atomic_read(&DI.RxDescEmpty) < DI.nRxDescTotal) {
465 KS8695_WRITE_REG(REG_RXSTART + DI.nOffset, 1);
468 else {
469 /* clear corresponding ISR bits after stopped */
470 KS8695_WRITE_REG(KS8695_INT_STATUS, DI.uIntMask);
475 * macStartTx
476 * This routine will start/stop TX machine.
478 * Inputs:
479 * Adapter pionter to ADAPTER_STRUCT data structure.
480 * bStart TRUE if start Tx machine, FALSE if stop it
482 * Returns:
483 * NONE
485 void macStartTx(PADAPTER_STRUCT Adapter, BOOLEAN bStart)
487 UINT32 uReg;
489 uReg = KS8695_READ_REG(REG_TXCTRL + DI.nOffset);
490 if (bStart) {
491 /* start TX machine */
492 uReg |= DMA_START;
493 KS8695_WRITE_REG(REG_TXCTRL + DI.nOffset, uReg);
494 DI.bTxStarted = FALSE;
495 /* clear corresponding ISR bits after stopped */
496 KS8695_WRITE_REG(KS8695_INT_STATUS, DI.uIntMask);
497 } else {
498 /* Stop TX machine */
499 uReg &= ~DMA_START;
500 KS8695_WRITE_REG(REG_TXCTRL + DI.nOffset, uReg);
501 DelayInMilliseconds(2);
502 DI.bTxStarted = FALSE;
507 * macStopAll
508 * This function is use to stop both Tx/Rx.
510 * Argument(s)
511 * Adapter pionter to ADAPTER_STRUCT data structure.
513 * Return(s)
514 * NONE
516 void macStopAll(PADAPTER_STRUCT Adapter)
518 /* stop Rx and Tx */
519 macStartRx(Adapter, FALSE);
520 macStartTx(Adapter, FALSE);
522 /* disable interrupt!!! */
523 macEnableInterrupt(Adapter, FALSE);
527 * macSetStationEx
528 * This function is use to set extra MAC station address
530 * Argument(s)
531 * Adapter pionter to ADAPTER_STRUCT data structure.
532 * pMac pointer to mac address buffer (should be 6)
533 * uIndex index of extra mac address to set
535 * Return(s)
536 * 0 if success
537 * negative value if failed
539 int macSetStationEx(PADAPTER_STRUCT Adapter, UCHAR *pMac, UINT uIndex)
541 #ifdef DEBUG_THIS
542 DRV_INFO("%s", __FUNCTION__);
543 #endif
545 /* do we need to set multicast addr to extra station registers? */
546 if (uIndex < MAC_MAX_EXTRA) {
547 uint32_t uLowAddress, uHighAddress;
549 uLowAddress = (*(pMac + 5) |
550 (*(pMac + 4) << 8) |
551 (*(pMac + 3) << 16)|
552 *(pMac + 2) << 24);
554 uHighAddress = (*(pMac + 1) |
555 *pMac << 8);
557 /* make sure mac address is not all zero */
558 if (uLowAddress | uHighAddress) {
559 /* enable additional MAC */
560 uHighAddress |= DMA_MACENABLE;
561 KS8695_WRITE_REG(REG_MAC0_LOW + DI.nOffset + uIndex * 8, uLowAddress);
562 KS8695_WRITE_REG(REG_MAC0_HIGH + DI.nOffset + uIndex * 8, uHighAddress);
563 return 0;
567 return ~EINVAL;
571 * macResetStationEx
572 * This function is use to clear extra MAC station address if set before
574 * Argument(s)
575 * Adapter pionter to ADAPTER_STRUCT data structure.
576 * nIndex index of extra mac address to set
577 * pMac pointer to mac address buffer (should be 6)
579 * Return(s)
580 * 0 if success
581 * negative value if failed
583 int macResetStationEx(PADAPTER_STRUCT Adapter, UCHAR *pMac)
585 int i, j;
586 uint32_t uLowAddress, uHighAddress;
588 #ifdef DEBUG_THIS
589 DRV_INFO("%s", __FUNCTION__);
590 #endif
592 uLowAddress = (*(pMac + 5) |
593 (*(pMac + 4) << 8) |
594 (*(pMac + 3) << 16)|
595 *(pMac + 2) << 24);
597 uHighAddress = (*(pMac + 1) |
598 *pMac << 8);
600 /* set mac enable bit for comparison purpose only! */
601 uHighAddress |= DMA_MACENABLE;
603 /* if match is found, remove it (set to 0) */
604 for (i = 0; i < MAC_MAX_EXTRA; i++) {
605 j = i * 8;
606 if (uLowAddress == KS8695_READ_REG(REG_MAC0_LOW + DI.nOffset + j) &&
607 uHighAddress == KS8695_READ_REG(REG_MAC0_HIGH + DI.nOffset + j)) {
608 KS8695_WRITE_REG(REG_MAC0_LOW + DI.nOffset + j, 0);
609 KS8695_WRITE_REG(REG_MAC0_HIGH + DI.nOffset + j, 0);
613 return 0;
617 * macGetIndexStationEx
618 * This function is use to get the index of empty station
620 * Argument(s)
621 * Adapter pionter to ADAPTER_STRUCT data structure.
623 * Return(s)
624 * nIndex index of empty to use
625 * negative value if it is full
627 int macGetIndexStationEx(PADAPTER_STRUCT Adapter)
629 int i;
631 #ifdef DEBUG_THIS
632 DRV_INFO("%s", __FUNCTION__);
633 #endif
635 for (i = 0; i < MAC_MAX_EXTRA; i++) {
636 if (!(KS8695_READ_REG(REG_MAC0_HIGH + DI.nOffset + i * 8) & DMA_MACENABLE)) {
637 return i;
641 DRV_WARN("%s: no empty slot for Additional Station Address", __FUNCTION__);
642 return -1;
645 /* Interrupt Bit definitions */
646 #define IB_WAN_LINK 31
647 #define IB_WAN_RX_STOPPED 25
648 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
649 #define IB_HPNA_TX 23
650 #define IB_HPNA_RX_STOPPED 18
651 #endif
652 #define IB_LAN_TX 17
653 #define IB_LAN_RX_STOPPED 12
656 * macConfigureInterrupt
657 * This routine is used to configure interrupt priority
659 * Inputs:
660 * Adapter pionter to ADAPTER_STRUCT data structure.
662 * Returns:
663 * NONE
665 void macConfigureInterrupt(PADAPTER_STRUCT Adapter)
667 int i;
668 UINT uIMR, uIPR = 0;
669 unsigned long flags;
671 #ifdef DEBUG_THIS
672 DRV_INFO("%s", __FUNCTION__);
673 #endif
675 spin_lock_irqsave(&DI.lock, flags);
676 /*spin_lock(&DI.lock);*/
677 uIMR = KS8695_READ_REG(KS8695_INT_CONTL);
678 switch (DI.usDMAId) {
679 case DMA_LAN:
680 for (i = IB_LAN_RX_STOPPED; i <= IB_LAN_TX; i++) {
681 if (stDMAIntCfg[i].bFIQ) {
682 uIMR |= (1L << i);
683 DI.bUseFIQ = TRUE;
685 else {
686 uIMR &= ~(1L << i);
687 uIPR |= ((UINT)(stDMAIntCfg[i].byPriority) & 0xf) << (i - IB_LAN_RX_STOPPED + 1) * 4;
690 KS8695_WRITE_REG(KS8695_INT_LAN_PRIORITY, uIPR);
691 break;
693 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
694 case DMA_HPNA:
695 for (i = IB_HPNA_RX_STOPPED; i <= IB_HPNA_TX; i++) {
696 if (stDMAIntCfg[i].bFIQ) {
697 uIMR |= (1L << i);
698 DI.bUseFIQ = TRUE;
700 else {
701 uIMR &= ~(1L << i);
702 uIPR |= ((UINT)(stDMAIntCfg[i].byPriority) & 0xf) << (i - IB_HPNA_RX_STOPPED + 1) * 4;
705 KS8695_WRITE_REG(KS8695_INT_HPNA_PRIORITY, uIPR);
706 break;
707 #endif
709 case DMA_WAN:
710 default:
711 for (i = IB_WAN_RX_STOPPED; i <= IB_WAN_LINK; i++) {
712 if (stDMAIntCfg[i].bFIQ) {
713 uIMR |= (1L << i);
714 DI.bUseFIQ = TRUE;
716 else {
717 uIMR &= ~(1L << i);
718 uIPR |= ((UINT)(stDMAIntCfg[i].byPriority) & 0xf) << (i - IB_WAN_RX_STOPPED + 1) * 4;
721 KS8695_WRITE_REG(KS8695_INT_WAN_PRIORITY, uIPR);
722 break;
724 KS8695_WRITE_REG(KS8695_INT_CONTL, uIMR);
725 /*spin_unlock(&DI.lock);*/
726 spin_unlock_irqrestore(&DI.lock, flags);
730 * macEnableInterrupt
731 * This routine is used to enable/disable interrupt related to MAC only
733 * Inputs:
734 * Adapter pionter to ADAPTER_STRUCT data structure.
735 * bEnable enable/disable interrupt
737 * Returns:
738 * NONE
740 void macEnableInterrupt(PADAPTER_STRUCT Adapter, BOOLEAN bEnable)
742 UINT uIER;
744 spin_lock(&DI.lock);
745 uIER = KS8695_READ_REG(KS8695_INT_ENABLE);
746 switch (DI.usDMAId) {
747 case DMA_LAN:
748 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
749 case DMA_HPNA:
750 #endif
751 if (bEnable)
752 uIER |= DI.uIntMask;
753 else
754 uIER &= ~DI.uIntMask;
755 break;
757 case DMA_WAN:
758 if (bEnable)
759 uIER |= (DI.uIntMask | DI.uLinkIntMask);
760 else
761 uIER &= ~(DI.uIntMask | DI.uLinkIntMask);
762 break;
764 default:
765 DRV_INFO("unsupported option");
766 break;
768 KS8695_WRITE_REG(KS8695_INT_ENABLE, uIER);
769 spin_unlock(&DI.lock);
770 ks8695_power_saving(bEnable);
774 * macGetStationAddress
775 * This function reads MAC address from station address registers.
777 * Argument(s)
778 * Adapter pointer to ADAPTER_STRUCT struct
779 * pMacAddress pointer to a byte array to hold MAC address (at least 6 bytes long)
781 * Return(s)
782 * NONE.
784 void macGetStationAddress(PADAPTER_STRUCT Adapter, uint8_t *pMacAddress)
786 UINT32 uTmp;
787 int i;
789 #ifdef DEBUG_THIS
790 DRV_INFO("%s", __FUNCTION__);
791 #endif
793 /* read low 4 buytes, byte order (e.g. in our NIC card, 00101a00000d) */
794 uTmp = KS8695_READ_REG(REG_STATION_LOW + DI.nOffset);
795 for (i = (MAC_ADDRESS_LEN - 1); i > 1; i--)
797 pMacAddress[i] = (UCHAR)(uTmp & 0x0ff);
798 uTmp >>= 8;
800 /* read high 2 bytes */
801 uTmp = KS8695_READ_REG(REG_STATION_HIGH + DI.nOffset);
802 pMacAddress[1] = (UCHAR)(uTmp & 0x0ff);
803 uTmp >>= 8;
804 pMacAddress[0] = (UCHAR)(uTmp & 0x0ff);
808 * macSetStationAddress
809 * This function sets MAC address to given type (WAN, LAN or HPHA)
811 * Argument(s)
812 * Adapter pointer to ADAPTER_STRUCT struct
813 * pMacAddress pointer to a byte array to hold MAC address (at least 6 bytes long)
815 * Return(s)
816 * NONE.
818 void macSetStationAddress(PADAPTER_STRUCT Adapter, uint8_t *pMacAddress)
820 UINT32 uLow, uHigh;
822 #ifdef DEBUG_THIS
823 DRV_INFO("%s", __FUNCTION__);
824 #endif
826 uLow = ((UINT32)pMacAddress[2] << 24);
827 uLow += ((UINT32)pMacAddress[3] << 16);
828 uLow += ((UINT32)pMacAddress[4] << 8);
829 uLow += pMacAddress[5];
830 uHigh = ((UINT32)pMacAddress[0] << 8) + pMacAddress[1];
831 KS8695_WRITE_REG(REG_STATION_LOW + DI.nOffset, uLow);
832 KS8695_WRITE_REG(REG_STATION_HIGH + DI.nOffset, uHigh);
836 * swConfigurePort
837 * This function is used to configure a give port for LAN.
839 * Argument(s)
840 * Adapter pointer to ADAPTER_STRUCT struct
841 * uPort port to start
843 * Return(s)
844 * NONE.
846 void swConfigurePort(PADAPTER_STRUCT Adapter, UINT uPort)
848 UINT uReg, uOff;
849 BOOLEAN bPort5 = FALSE;
851 if (uPort >= SW_MAX_LAN_PORTS) {
852 if (SW_MAX_LAN_PORTS == uPort) {
853 /* port 5 */
854 bPort5 = TRUE;
856 else {
857 /* out of range */
858 DRV_INFO("%s: port %d to configure out of range", __FUNCTION__, uPort);
859 return;
862 #ifndef CONFIG_ARCH_KS8695P
863 uOff = KS8695_SWITCH_PORT1 + uPort * 4;
864 #else
865 if (bPort5)
866 uOff = KS8695_SEP5C1;
867 else
868 uOff = KS8695_SEP1C1 + uPort * 0x0c;
869 #endif
871 uReg = 0;
872 uReg |= (UINT)DPI[uPort].usTag << 16;
874 if (!bPort5) {
875 /* connection media type */
876 /*uReg &= ~(SW_PORT_DISABLE_AUTONEG | SW_PORT_100BASE | SW_PORT_FULLDUPLEX);*/
877 if (SW_PHY_AUTO != DI.usCType[uPort]) {
878 uReg |= SW_PORT_DISABLE_AUTONEG;
879 if (SW_PHY_100BASE_TX == DI.usCType[uPort] ||
880 SW_PHY_100BASE_TX_FD == DI.usCType[uPort]) {
881 uReg |= SW_PORT_100BASE;
883 if (SW_PHY_10BASE_T_FD == DI.usCType[uPort] ||
884 SW_PHY_100BASE_TX_FD == DI.usCType[uPort]) {
885 uReg |= SW_PORT_FULLDUPLEX;
889 else {
890 /* Rx direct mode */
891 if (DI.bRxDirectMode) {
892 uReg |= SW_PORT_RX_DIRECT_MODE;
894 /* Tx Pre-tag mode */
895 if (DI.bTxRreTagMode) {
896 uReg |= SW_PORT_TX_PRETAG_MODE;
900 /* cross talk bit mask */
901 uReg |= ((UINT)(DPI[uPort].byCrossTalkMask & 0x1f)) << 8;
903 /* spanning tree */
904 if (SW_SPANNINGTREE_ALL == DPI[uPort].bySpanningTree) {
905 uReg |= SW_PORT_TX_SPANNINGTREE | SW_PORT_RX_SPANNINGTREE;
907 else {
908 if (SW_SPANNINGTREE_TX == DPI[uPort].bySpanningTree) {
909 uReg |= SW_PORT_TX_SPANNINGTREE;
911 if (SW_SPANNINGTREE_RX == DPI[uPort].bySpanningTree) {
912 uReg |= SW_PORT_RX_SPANNINGTREE;
915 if (DPI[uPort].byDisableSpanningTreeLearn) {
916 uReg |= SW_PORT_NO_SPANNINGTREE;
918 /* ingress broadcast storm protection */
919 if (DPI[uPort].byStormProtection) {
920 uReg |= SW_PORT_STORM_PROCTION;
922 /* ingress priority */
923 if (DPI[uPort].byIngressPriority) {
924 uReg |= SW_PORT_HI_PRIORITY;
926 if (DPI[uPort].byIngressPriorityTOS) {
927 uReg |= SW_PORT_TOS_ENABLE;
929 if (DPI[uPort].byIngressPriority802_1P) {
930 uReg |= SW_PORT_8021Q_ENABLE;
932 /* egress priority */
933 if (DPI[uPort].byEgressPriority) {
934 uReg |= SW_PORT_PRIOTIRY_ENABLE;
936 KS8695_WRITE_REG(uOff, uReg);
937 /* need 20 cpu clock delay for switch related registers */
938 DelayInMicroseconds(10);
940 #ifdef DEBUG_THIS
941 DRV_INFO("%s: uOff=0x%08x, reg=0x%08x", __FUNCTION__, uOff, uReg);
942 #endif
946 * swEnableSwitch
947 * This function is used to enable/disable switch
949 * Argument(s)
950 * Adapter pointer to ADAPTER_STRUCT struct
951 * enable enable/disable switch
953 * Return(s)
954 * NONE.
956 void swEnableSwitch(PADAPTER_STRUCT Adapter, UINT enable)
958 UINT uReg;
960 uReg = KS8695_READ_REG(KS8695_SWITCH_CTRL0);
961 if (enable) {
962 uReg |= SW_CTRL0_SWITCH_ENABLE;
963 /* for debug purpose */
964 /*uReg |= 0x00080000;*/
965 } else {
966 uReg &= ~SW_CTRL0_SWITCH_ENABLE;
967 /* for debug purpose */
968 /*uReg &= ~0x00080000;*/
971 KS8695_WRITE_REG(KS8695_SWITCH_CTRL0, uReg);
972 /* need 20 cpu clock delay for switch related registers */
973 DelayInMicroseconds(10);
977 * swReadSNMPReg
978 * This function is used to read SNMP registers
980 * Argument(s)
981 * Adapter pointer to ADAPTER_STRUCT structure.
982 * uIndex index of SNMP register to read
984 * Return(s)
985 * value read
987 UINT swReadSNMPReg(PADAPTER_STRUCT Adapter, UINT uIndex)
989 #ifndef CONFIG_ARCH_KS8695P
990 UINT uValue, uTimeout = 0;
992 if (uIndex >= 512)
993 uIndex = 511;
995 KS8695_WRITE_REG(KS8695_MANAGE_COUNTER, uIndex);
996 DelayInMicroseconds(10);
997 do {
998 uValue = KS8695_READ_REG(KS8695_MANAGE_DATA);
999 if (uValue & SW_SNMP_DATA_VALID) {
1000 if (uValue & SW_SNMP_DATA_OVERFLOW) {
1001 KS8695_WRITE_REG(KS8695_MANAGE_DATA, SW_SNMP_DATA_OVERFLOW);
1003 /* clear status bits */
1004 uValue &= 0x3fffffff;
1005 return uValue;
1007 DelayInMilliseconds(1);
1009 while (uTimeout++ < 2000);
1011 if (uValue & SW_SNMP_DATA_OVERFLOW) {
1012 KS8695_WRITE_REG(KS8695_MANAGE_DATA, SW_SNMP_DATA_OVERFLOW);
1014 #else
1015 u32 reg, value, timeout = 0;
1017 reg = KS8695_SEIAC_READ | KS8695_SEIAC_TAB_MIB | (KS8695_SEIAC_INDEX_MASK & uIndex);
1018 do {
1019 KS8695_WRITE_REG(KS8695_SEIAC, reg);
1020 DelayInMicroseconds(10);
1022 value = KS8695_READ_REG(KS8695_SEIADL);
1023 if (value & SW_SNMP_DATA_VALID) {
1024 if (value & SW_SNMP_DATA_OVERFLOW) {
1025 reg = KS8695_SEIAC_WRITE | KS8695_SEIAC_TAB_MIB | (KS8695_SEIAC_INDEX_MASK & uIndex);
1026 KS8695_WRITE_REG(KS8695_SEIAC, reg);
1028 /* clear status bits */
1029 value &= 0x3fffffff;
1030 return value;
1033 while (timeout++ < 2000);
1035 printk("%s: timeout\n", __FUNCTION__);
1036 #endif
1037 return 0;
1041 * swConfigure
1042 * This function is used to config switch engine. It is assume that
1043 * the BIST is performed already (by boot loader).
1045 * Argument(s)
1046 * Adapter pointer to ADAPTER_STRUCT structure.
1048 * Return(s)
1049 * NONE
1051 void swConfigure(PADAPTER_STRUCT Adapter)
1053 UINT uReg, i;
1055 #ifdef DEBUG_THIS
1056 DRV_INFO("%s", __FUNCTION__);
1057 #endif
1059 if (DMA_LAN == DI.usDMAId) {
1060 /* read switch control 0 register */
1061 uReg = KS8695_READ_REG(KS8695_SWITCH_CTRL0);
1062 /* flow control for LAN ports */
1063 if (DI.bPort5FlowCtrl)
1065 /* flow control for port 5 */
1066 uReg |= SW_CTRL0_ENABLE_PORT5;
1068 else {
1069 uReg &= ~SW_CTRL0_ENABLE_PORT5;
1071 #ifndef CONFIG_ARCH_KS8695P
1072 if (DI.bPortsFlowCtrl)
1074 /* four flow control for each LAN port */
1075 uReg |= SW_CTRL0_ENABLE_PORTS;
1077 else {
1078 uReg &= ~SW_CTRL0_ENABLE_PORTS;
1080 #else
1081 #if 0
1082 /* RLQ, need to verify */
1083 for (i = 0; i < SW_MAX_LAN_PORTS; i++) {
1084 forceFlowControl(Adapter, i, DI.bPortsFlowCtrl);
1085 //if (!DI.bPortsFlowCtrl)
1086 // backPressureEnable(Adapter, i, DI.bPortsFlowCtrl);
1087 backPressureEnable(Adapter, i, TRUE);
1089 #endif
1090 #endif
1092 /*RLQ, 11/20/2002, requested by Hock, backpressure will fix packet
1093 * drop problem in half duplex mode
1095 uReg |= 0x00000020; /* bit 5 */
1097 /* set flow control fairness mode based on LAN flow control settings, should use */
1099 /* read switch control 0 register */
1100 KS8695_WRITE_REG(KS8695_SWITCH_CTRL0, uReg);
1101 /* need 20 cpu clock delay for switch related registers */
1102 DelayInMicroseconds(10);
1104 /* configure LAN port 1-4 and Port 5 */
1105 for (i = 0; i <= SW_MAX_LAN_PORTS; i++)
1106 swConfigurePort(Adapter, i);
1108 else {
1109 DRV_INFO("%s: type (%x) not supported", __FUNCTION__, DI.usDMAId);
1114 * swSetLED
1115 * This function is used to set given LED
1117 * Argument(s)
1118 * Adapter pointer to ADAPTER_STRUCT struct
1119 * bLED1 TRUE for LED1 and FALSE for LED0
1120 * nSel emum type LED_SELECTOR
1122 * Return(s)
1123 * NONE.
1125 void swSetLED(PADAPTER_STRUCT Adapter, BOOLEAN bLED1, LED_SELECTOR nSel)
1127 UINT32 uReg;
1129 switch (DI.usDMAId) {
1130 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
1131 case DMA_HPNA:
1132 /* there is no LED for HPNA */
1133 break;
1134 #endif
1136 case DMA_WAN:
1137 uReg = KS8695_READ_REG(KS8695_WAN_CONTROL);
1138 if (bLED1) {
1139 uReg &= 0xffffff8f; /* 6:4 */
1140 uReg |= (UINT)(nSel & 0x07) << 4;
1142 else {
1143 uReg &= 0xfffffff8; /* 2:0 */
1144 uReg |= (UINT)(nSel & 0x07);
1146 KS8695_WRITE_REG(KS8695_WAN_CONTROL, uReg);
1147 /* need 20 cpu clock delay for switch related registers */
1148 DelayInMicroseconds(10);
1149 return;
1151 default:
1152 case DMA_LAN:
1153 uReg = KS8695_READ_REG(KS8695_SWITCH_CTRL0);
1154 if (bLED1) {
1155 uReg &= 0xf1ffffff; /* 27:25 */
1156 uReg |= (UINT)(nSel & 0x07) << 25;
1158 else {
1159 uReg &= 0xfe3fffff; /* 24:22 */
1160 uReg |= (UINT)(nSel & 0x07) << 22;
1162 KS8695_WRITE_REG(KS8695_SWITCH_CTRL0, uReg);
1163 /* need 20 cpu clock delay for switch related registers */
1164 DelayInMicroseconds(10);
1165 break;
1170 * swAutoNegoStart
1171 * This function is used to start auto negotiation process
1173 * Argument(s)
1174 * Adapter pointer to ADAPTER_STRUCT struct
1175 * uPort port to start
1177 * Return(s)
1178 * NONE.
1180 void swAutoNegoStart(PADAPTER_STRUCT Adapter, UINT uPort)
1182 UINT uReg, uOff, uShift = 0;
1184 #ifdef DEBUG_THIS
1185 DRV_INFO("%s: port=%d, bAutoNegoInProgress=%d", __FUNCTION__, uPort, DI.bAutoNegoInProgress[uPort]);
1186 #endif
1188 switch (DI.usDMAId) {
1189 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
1190 case DMA_HPNA:
1191 /* there is no auto nego for HPNA */
1192 return;
1193 #endif
1195 case DMA_WAN:
1196 uOff = KS8695_WAN_CONTROL;
1197 uShift = 16;
1198 break;
1200 default:
1201 case DMA_LAN:
1202 switch (uPort) {
1203 case SW_PORT_4:
1204 uOff = KS8695_SWITCH_AUTO1;
1205 uShift = 16;
1206 break;
1208 case SW_PORT_3:
1209 uOff = KS8695_SWITCH_AUTO1;
1210 break;
1212 case SW_PORT_2:
1213 uOff = KS8695_SWITCH_AUTO0;
1214 uShift = 16;
1215 break;
1217 case SW_PORT_1:
1218 default:
1219 uOff = KS8695_SWITCH_AUTO0;
1220 break;
1222 break;
1225 /* if not auto nego */
1226 if (SW_PHY_AUTO != DI.usCType[uPort]) {
1227 return;
1229 DI.bAutoNegoInProgress[uPort] = TRUE;
1230 uReg = KS8695_READ_REG(uOff);
1231 uReg |= ((UINT)SW_AUTONEGO_RESTART << uShift);
1232 KS8695_WRITE_REG(uOff, uReg);
1233 /* need 20 cpu clock delay for switch related registers */
1234 DelayInMicroseconds(10);
1238 * swAutoNegoAdvertisement
1239 * This function is used to set PHY Advertisement.
1241 * Argument(s)
1242 * Adapter pointer to ADAPTER_STRUCT structure.
1243 * uPort port to advertise
1245 * Return(s)
1246 * NONE
1248 void swAutoNegoAdvertisement(PADAPTER_STRUCT Adapter, UINT uPort)
1250 UINT uReg, uOff, uShift = 0;
1252 #ifdef DEBUG_THIS
1253 DRV_INFO("%s", __FUNCTION__);
1254 #endif
1256 switch (DI.usDMAId) {
1257 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
1258 case DMA_HPNA:
1259 /* there is no auto nego feature for HPNA DMA, but I'll assume that
1260 if SW_PHY_AUTO is set, use 100/FD as default
1262 uReg = KS8695_READ_REG(KS8695_MISC_CONTROL) & 0xfffffffc;
1263 if (SW_PHY_AUTO == DI.usCType[uPort]) {
1264 uReg |= 0x00000003;
1266 else {
1267 if (SW_PHY_100BASE_TX == DI.usCType[uPort] ||
1268 SW_PHY_100BASE_TX_FD == DI.usCType[uPort]) {
1269 uReg |= 0x00000002;
1271 if (SW_PHY_10BASE_T_FD == DI.usCType[uPort] ||
1272 SW_PHY_100BASE_TX_FD == DI.usCType[uPort]) {
1273 uReg |= 0x00000001;
1276 KS8695_WRITE_REG(REG_MISC_CONTROL, uReg);
1277 /* need 20 cpu clock delay for switch related registers */
1278 DelayInMicroseconds(10);
1279 return;
1280 #endif
1282 case DMA_WAN:
1283 uOff = KS8695_WAN_CONTROL;
1284 uShift = 16;
1285 break;
1287 default:
1288 case DMA_LAN:
1289 switch (uPort) {
1290 case SW_PORT_4:
1291 uOff = KS8695_SWITCH_AUTO1;
1292 break;
1294 case SW_PORT_3:
1295 uOff = KS8695_SWITCH_AUTO1;
1296 uShift = 16;
1297 break;
1299 case SW_PORT_2:
1300 uOff = KS8695_SWITCH_AUTO0;
1301 break;
1303 case SW_PORT_1:
1304 default:
1305 uOff = KS8695_SWITCH_AUTO0;
1306 uShift = 16;
1307 break;
1309 break;
1311 uReg = KS8695_READ_REG(uOff);
1312 /* clear corresponding bits first */
1313 uReg &= ~(SW_AUTONEGO_ADV_MASK << uShift);
1314 if (SW_PHY_AUTO == DI.usCType[uPort])
1316 uReg |= (SW_AUTONEGO_ADV_100FD | SW_AUTONEGO_ADV_100HD |
1317 SW_AUTONEGO_ADV_10FD | SW_AUTONEGO_ADV_10HD) << uShift;
1319 else
1321 /* Manually set */
1322 switch (DI.usCType[uPort])
1324 case SW_PHY_100BASE_TX_FD:
1325 uReg |= SW_AUTONEGO_ADV_100FD << uShift;
1326 break;
1328 case SW_PHY_100BASE_TX:
1329 uReg |= SW_AUTONEGO_ADV_100HD << uShift;
1330 break;
1332 case SW_PHY_10BASE_T_FD:
1333 uReg |= SW_AUTONEGO_ADV_10FD << uShift;
1334 break;
1336 case SW_PHY_10BASE_T:
1337 uReg |= SW_AUTONEGO_ADV_10HD << uShift;
1338 break;
1340 default:
1341 /* Unsupported media type found! */
1342 DRV_WARN("%s> Unsupported media type found!", __FUNCTION__);
1343 return;
1347 if (DI.bRxFlowCtrl)
1348 uReg |= SW_AUTONEGO_ADV_PUASE << uShift;
1350 uReg &= ~((UINT)SW_AUTONEGO_RESTART << uShift);
1351 KS8695_WRITE_REG(uOff, uReg);
1352 /* need 20 cpu clock delay for switch related registers */
1353 DelayInMicroseconds(10);
1357 * swGetWANLinkStatus
1358 * This function is used to get WAN link status.
1360 * Argument(s)
1361 * Adapter pointer to ADAPTER_STRUCT structure.
1362 * uPort port to query
1364 * Return(s)
1365 * TRUE if link is up
1366 * FALSE if link is down
1368 BOOLEAN swGetWANLinkStatus(PADAPTER_STRUCT Adapter)
1370 UINT uReg;
1372 uReg = KS8695_READ_REG(KS8695_WAN_CONTROL);
1373 /* if not linked yet */
1374 if (!(uReg & ((UINT)SW_AUTONEGO_STAT_LINK << 16))) {
1375 #ifdef DEBUG_THIS
1376 DRV_INFO("WAN link is down");
1377 #endif
1378 return FALSE;
1380 #ifdef DEBUG_THIS
1381 DRV_INFO("WAN link is up");
1382 #endif
1384 return TRUE;
1388 * swGetPhyStatus
1389 * This function is used to get the status of auto negotiation.
1391 * Argument(s)
1392 * Adapter pointer to ADAPTER_STRUCT structure.
1393 * uPort port to query
1395 * Return(s)
1396 * TRUE if connected
1397 * FALSE otherwise
1399 int swGetPhyStatus(PADAPTER_STRUCT Adapter, UINT uPort)
1401 UINT uReg, uOff, uShift = 0;
1403 #ifdef DEBUG_THIS
1404 DRV_INFO("%s", __FUNCTION__);
1405 #endif
1407 switch (DI.usDMAId) {
1408 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
1409 case DMA_HPNA:
1410 /* temp */
1411 uReg = KS8695_READ_REG(REG_MISC_CONTROL);
1412 DI.usLinkSpeed[uPort] = (uReg & 0x00000002) ? SPEED_100 : SPEED_10;
1413 DI.bHalfDuplex[uPort] = (uReg & 0x00000001) ? FULL_DUPLEX : HALF_DUPLEX;
1414 /* note that there is no register bit corresponding to HPNA's link status
1415 therefore don't report it */
1416 DI.bLinkActive[uPort] = TRUE;
1417 return TRUE;
1418 #endif
1420 case DMA_WAN:
1421 uOff = KS8695_WAN_CONTROL;
1422 uShift = 16;
1423 break;
1425 default:
1426 case DMA_LAN:
1427 switch (uPort) {
1428 case SW_PORT_4:
1429 uOff = KS8695_SWITCH_AUTO1;
1430 break;
1432 case SW_PORT_3:
1433 uOff = KS8695_SWITCH_AUTO1;
1434 uShift = 16;
1435 break;
1437 case SW_PORT_2:
1438 uOff = KS8695_SWITCH_AUTO0;
1439 break;
1441 case SW_PORT_1:
1442 default:
1443 uOff = KS8695_SWITCH_AUTO0;
1444 uShift = 16;
1445 break;
1449 uReg = KS8695_READ_REG(uOff);
1450 /* if not linked yet */
1451 if (!(uReg & ((UINT)SW_AUTONEGO_STAT_LINK << uShift))) {
1452 DI.bLinkActive[uPort] = FALSE;
1453 DI.usLinkSpeed[uPort] = SPEED_UNKNOWN;
1454 DI.bHalfDuplex[uPort] = 0;
1455 gpioSet(Adapter, uPort, FALSE);
1456 return FALSE;
1458 DI.bLinkActive[uPort] = TRUE;
1459 if (SW_PHY_AUTO == DI.usCType[uPort]) {
1460 /* if auto nego complete */
1461 //RLQ, 12/18/2003, bug
1462 if (uReg & ((UINT)SW_AUTONEGO_COMPLETE << uShift)) {
1463 /* clear auto nego restart bit */
1464 uReg &= ~((UINT)SW_AUTONEGO_RESTART << uShift);
1465 KS8695_WRITE_REG(uOff, uReg);
1466 DelayInMicroseconds(10);
1468 DI.usLinkSpeed[uPort] = (uReg & ((UINT)SW_AUTONEGO_STAT_SPEED << uShift)) ? SPEED_100 : SPEED_10;
1469 DI.bHalfDuplex[uPort] = (uReg & ((UINT)SW_AUTONEGO_STAT_DUPLEX << uShift)) ? FULL_DUPLEX : HALF_DUPLEX;
1470 DI.bAutoNegoInProgress[uPort] = FALSE;
1472 gpioSet(Adapter, uPort, SPEED_100 == DI.usLinkSpeed[uPort]);
1473 /*RLQ, need to verify real duplex mode instead report it correct here */
1474 /* duplex bit may not right if partner doesn't support all mode, do further detection */
1475 if ((uReg & (SW_AUTONEGO_PART_100FD | SW_AUTONEGO_PART_100HD | SW_AUTONEGO_PART_10FD | SW_AUTONEGO_PART_10HD) << uShift)
1476 != (SW_AUTONEGO_PART_100FD | SW_AUTONEGO_PART_100HD | SW_AUTONEGO_PART_10FD | SW_AUTONEGO_PART_10HD)) {
1477 if (SPEED_100 == DI.usLinkSpeed[uPort]) {
1478 if ((uReg & (SW_AUTONEGO_PART_100FD << uShift))) {
1479 DI.bHalfDuplexDetected[uPort] = FULL_DUPLEX;
1480 #ifdef CONFIG_ARCH_KS8695P
1481 forceFlowControl(Adapter, uPort, TRUE);
1482 backPressureEnable(Adapter, uPort, FALSE);
1483 #endif
1484 } else {
1485 DI.bHalfDuplexDetected[uPort] = HALF_DUPLEX;
1486 #ifdef CONFIG_ARCH_KS8695P
1487 forceFlowControl(Adapter, uPort, FALSE);
1488 backPressureEnable(Adapter, uPort, TRUE);
1489 #endif
1492 else {
1493 if ((uReg & (SW_AUTONEGO_PART_10FD << uShift))) {
1494 DI.bHalfDuplexDetected[uPort] = FULL_DUPLEX;
1495 #ifdef CONFIG_ARCH_KS8695P
1496 forceFlowControl(Adapter, uPort, TRUE);
1497 backPressureEnable(Adapter, uPort, FALSE);
1498 #endif
1500 else {
1501 DI.bHalfDuplexDetected[uPort] = HALF_DUPLEX;
1502 #ifdef CONFIG_ARCH_KS8695P
1503 forceFlowControl(Adapter, uPort, FALSE);
1504 backPressureEnable(Adapter, uPort, TRUE);
1505 #endif
1510 /* software workaround for flow control, need to know partner's flow control */
1511 if (DMA_WAN == DI.usDMAId) { /* currently do it to WAN only, there is no problem to LAN, will do HPNA later */
1512 uint8_t bFlowCtrl;
1514 /* we need to check partner's control flow setting for the matching, if not, changes ours */
1515 bFlowCtrl = ((SW_AUTONEGO_PART_PAUSE << uShift) & uReg) ? TRUE : FALSE;
1516 if (bFlowCtrl != DI.bRxFlowCtrl) { /* Tx same as Rx, so test Rx should be enough */
1517 /* need to change ours accordingly, which will overwrite current one */
1518 macConfigureFlow(Adapter, bFlowCtrl);
1521 #ifdef DEBUG_THIS
1522 DRV_INFO("%s> Auto Nego completed", __FUNCTION__);
1523 #endif
1525 else {
1526 #ifdef DEBUG_THIS
1527 /* auto nego in progress */
1528 DRV_INFO("%s> Auto Nego in progress...", __FUNCTION__);
1529 #endif
1530 /* wait for next timer */
1531 DI.bLinkActive[uPort] = FALSE;
1532 DI.usLinkSpeed[uPort] = SPEED_UNKNOWN;
1533 DI.bHalfDuplex[uPort] = 0;
1536 else {
1537 #ifdef DEBUG_THIS
1538 DRV_INFO("%s: media type=%d, port=%d", __FUNCTION__, DI.usCType[uPort], uPort);
1539 #endif
1541 /* manually connection */
1542 if (SW_PHY_10BASE_T_FD == DI.usCType[uPort] || SW_PHY_100BASE_TX_FD == DI.usCType[uPort]) {
1543 DI.bHalfDuplex[uPort] = FULL_DUPLEX;
1544 #ifdef CONFIG_ARCH_KS8695P
1545 forceFlowControl(Adapter, uPort, TRUE);
1546 backPressureEnable(Adapter, uPort, FALSE);
1547 #endif
1549 else {
1550 DI.bHalfDuplex[uPort] = HALF_DUPLEX;
1551 #ifdef CONFIG_ARCH_KS8695P
1552 forceFlowControl(Adapter, uPort, FALSE);
1553 backPressureEnable(Adapter, uPort, TRUE);
1554 #endif
1556 if (SW_PHY_100BASE_TX_FD == DI.usCType[uPort] || SW_PHY_100BASE_TX == DI.usCType[uPort]) {
1557 DI.usLinkSpeed[uPort] = SPEED_100;
1558 gpioSet(Adapter, uPort, TRUE);
1560 else {
1561 DI.usLinkSpeed[uPort] = SPEED_10;
1562 gpioSet(Adapter, uPort, FALSE);
1565 /* software workaround for flow control, need to know partner's flow control */
1566 if (DMA_WAN == DI.usDMAId) { /* currently do it to WAN only, there is no problem to LAN, will do HPNA later */
1567 macConfigureFlow(Adapter, FULL_DUPLEX == DI.bHalfDuplex[uPort] ? TRUE : FALSE);
1570 return TRUE;
1574 * swDetectPhyConnection
1575 * This function is used to start auto negotiation
1577 * Argument(s)
1578 * Adapter pointer to ADAPTER_STRUCT struct
1579 * uPort port to start
1581 * Return(s)
1582 * NONE.
1584 void swDetectPhyConnection(PADAPTER_STRUCT Adapter, UINT uPort)
1586 /*if (SW_PHY_AUTO == DI.usCType[uPort] && !DI.bAutoNegoInProgress[uPort] && DI.bLinkChanged[uPort]) {*/
1587 if (LINK_SELECTION_FORCED != DI.byDisableAutoNego[uPort] && !DI.bAutoNegoInProgress[uPort] && DI.bLinkChanged[uPort]) {
1588 swAutoNegoStart(Adapter, uPort);
1589 DI.bLinkChanged[uPort] = FALSE;
1590 DI.bLinkActive[uPort] = FALSE;
1592 swGetPhyStatus(Adapter, uPort);
1596 * swPhyReset
1597 * This function is used to reset phy chipset (powerdown or soft reset).
1599 * Argument(s)
1600 * Adapter pointer to ADAPTER_STRUCT structure.
1601 * uPort port to start
1603 * Return(s)
1604 * NONE
1606 void swPhyReset(PADAPTER_STRUCT Adapter, UINT uPort)
1608 UINT uReg, uShift = 0;
1609 UINT uPowerReg;
1610 /*RLQ, workaround */
1611 UINT uReg1;
1613 #ifdef DEBUG_THIS
1614 DRV_INFO("%s", __FUNCTION__);
1615 #endif
1617 /* IEEE spec. of auto nego bit */
1618 uReg1 = BIT(7);
1619 switch (DI.usDMAId) {
1620 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
1621 case DMA_HPNA:
1622 return;
1623 #endif
1625 case DMA_WAN:
1626 uPowerReg = KS8695_WAN_POWERMAGR;
1627 break;
1629 default:
1630 case DMA_LAN:
1631 switch (uPort) {
1632 case SW_PORT_4:
1633 uPowerReg = KS8695_LAN34_POWERMAGR;
1634 break;
1636 case SW_PORT_3:
1637 uPowerReg = KS8695_LAN34_POWERMAGR;
1638 uShift = 16;
1639 break;
1641 case SW_PORT_2:
1642 uPowerReg = KS8695_LAN12_POWERMAGR;
1643 break;
1645 case SW_PORT_1:
1646 default:
1647 uPowerReg = KS8695_LAN12_POWERMAGR;
1648 uShift = 16;
1649 break;
1653 if (DI.bPowerDownReset) {
1654 int nCount = 0;
1656 uReg = KS8695_READ_REG(uPowerReg);
1657 KS8695_WRITE_REG(uPowerReg, uReg | ((UINT)POWER_POWERDOWN << uShift));
1658 /* need 20 cpu clock delay for switch related registers */
1659 /*DelayInMicroseconds(10);*/
1660 do {
1661 DelayInMilliseconds(50);
1662 } while (nCount++ < 4);
1663 uReg &= ~((UINT)POWER_POWERDOWN << uShift);
1664 /* turn off IEEE auto nego */
1665 uReg &= ~(uReg1 << uShift);
1666 KS8695_WRITE_REG(uPowerReg, uReg);
1667 /* need 20 cpu clock delay for switch related registers */
1668 DelayInMicroseconds(10);
1670 else {
1671 uReg = KS8695_READ_REG(uPowerReg);
1672 /* turn off IEEE auto nego */
1673 uReg &= ~(uReg1 << uShift);
1674 KS8695_WRITE_REG(uPowerReg, uReg);
1675 /* need 20 cpu clock delay for switch related registers */
1676 DelayInMicroseconds(10);
1681 * swConfigureMediaType
1682 * This function is used to set linke media type (forced)
1684 * Argument(s)
1685 * Adapter pointer to ADAPTER_STRUCT structure.
1686 * uPort port to start
1687 * uSpeed media speed to set
1688 * uDuplex media duplex to set
1690 * Return(s)
1691 * TRUE if succeeded
1692 * FALSE otherwise
1694 void swConfigureMediaType(PADAPTER_STRUCT Adapter, UINT uPort, UINT uSpeed, UINT uDuplex)
1696 UINT32 uReg, uOffset;
1698 #ifdef DEBUG_THIS
1699 DRV_INFO("%s", __FUNCTION__);
1700 #endif
1702 switch (DI.usDMAId) {
1703 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
1704 case DMA_HPNA:
1705 /* there is no way to force HPNA */
1706 return;
1707 #endif
1709 case DMA_WAN:
1710 uOffset = KS8695_WAN_CONTROL;
1711 uPort = 0;
1712 break;
1714 default:
1715 case DMA_LAN:
1716 if (uPort >= SW_MAX_LAN_PORTS) {
1717 DRV_WARN("%s: port (%d) gave is out of range", __FUNCTION__, uPort);
1718 return;
1720 #ifndef CONFIG_ARCH_KS8695P
1721 uOffset = KS8695_SWITCH_PORT1 + uPort * 4;
1722 #else
1723 if (SW_MAX_LAN_PORTS == uPort)
1724 uOffset = KS8695_SEP5C1;
1725 else
1726 uOffset = KS8695_SWITCH_PORT1 + uPort * 0x0c;
1727 #endif
1728 break;
1731 uReg = KS8695_READ_REG(uOffset);
1732 /* clear corresponding bits first */
1733 uReg &= 0xFFFF1FFF;
1734 if (LINK_SELECTION_FORCED == DI.byDisableAutoNego[uPort]) {
1735 uReg |= SW_PORT_DISABLE_AUTONEG;
1736 /* force to half duplex */
1737 DI.bRxFlowCtrl = FALSE;
1738 DI.bTxFlowCtrl = FALSE;
1739 if (uSpeed) {
1740 uReg |= SW_PORT_100BASE;
1741 if (uDuplex) {
1742 uReg |= SW_PORT_FULLDUPLEX;
1743 DI.usCType[uPort] = SW_PHY_100BASE_TX_FD;
1745 else {
1746 DI.usCType[uPort] = SW_PHY_100BASE_TX;
1749 else {
1750 if (uDuplex) {
1751 uReg |= SW_PORT_FULLDUPLEX;
1752 DI.usCType[uPort] = SW_PHY_10BASE_T_FD;
1754 else {
1755 DI.usCType[uPort] = SW_PHY_10BASE_T;
1759 else {
1760 if (DMA_WAN == DI.usDMAId) {
1761 DI.bRxFlowCtrl = FLOWCONTROL_DEFAULT;
1762 DI.bTxFlowCtrl = FLOWCONTROL_DEFAULT;
1764 if (LINK_SELECTION_FULL_AUTO == DI.byDisableAutoNego[uPort]) {
1765 DI.usCType[uPort] = SW_PHY_AUTO;
1766 } else {
1767 switch (uSpeed) {
1768 case 0:
1769 if (uDuplex)
1770 DI.usCType[uPort] = SW_PHY_10BASE_T_FD; /* 10Base-TX Full Duplex */
1771 else {
1772 /* don't advertise flow control in half duplex case */
1773 if (DMA_WAN == DI.usDMAId) {
1774 DI.bRxFlowCtrl = FALSE;
1775 DI.bTxFlowCtrl = FALSE;
1777 DI.usCType[uPort] = SW_PHY_10BASE_T; /* 10Base-T Half Duplex */
1779 break;
1781 case 1:
1782 default:
1783 if (uDuplex)
1784 DI.usCType[uPort] = SW_PHY_100BASE_TX_FD; /* 100Base-TX Full Duplex */
1785 else {
1786 /* don't advertise flow control in half duplex case */
1787 if (DMA_WAN == DI.usDMAId) {
1788 DI.bRxFlowCtrl = FALSE;
1789 DI.bTxFlowCtrl = FALSE;
1791 DI.usCType[uPort] = SW_PHY_100BASE_TX; /* 100Base-TX Half Duplex */
1793 break;
1798 KS8695_WRITE_REG(uOffset, uReg);
1799 /* need 20 cpu clock delay for switch related registers */
1800 DelayInMicroseconds(10);
1801 #ifdef DEBUG_THIS
1802 DRV_INFO("%s: media type=%d, offset=0x%08x, port=%d", __FUNCTION__, DI.usCType[uPort], uOffset, uPort);
1803 #endif
1805 DI.bLinkChanged[uPort] = TRUE;
1806 DI.bLinkActive[uPort] = FALSE; /* watchdog routine will check link status if reset this variable!!! */
1807 swPhyReset(Adapter, uPort);
1808 swAutoNegoAdvertisement(Adapter, uPort);
1809 swDetectPhyConnection(Adapter, uPort);
1813 * swPhyLoopback
1814 * This function is used to set loopback in PHY layer.
1816 * Argument(s)
1817 * Adapter pointer to ADAPTER_STRUCT structure.
1818 * uPort port to start
1819 * bLoopback indicates loopback enable or not
1821 * Return(s)
1822 * TRUE if succeeded
1823 * FALSE otherwise
1825 BOOLEAN swPhyLoopback(PADAPTER_STRUCT Adapter, UINT uPort, BOOLEAN bLoopback)
1827 UINT uReg, uOff, uShift = 0;
1829 switch (DI.usDMAId) {
1830 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
1831 case DMA_HPNA:
1832 return FALSE;
1833 #endif
1835 case DMA_WAN:
1836 uOff = KS8695_WAN_POWERMAGR;
1837 uShift = 0;
1838 break;
1840 default:
1841 case DMA_LAN:
1842 switch (uPort) {
1843 case SW_PORT_4:
1844 uOff = KS8695_LAN34_POWERMAGR;
1845 break;
1847 case SW_PORT_3:
1848 uOff = KS8695_LAN34_POWERMAGR;
1849 uShift = 16;
1850 break;
1852 case SW_PORT_2:
1853 uOff = KS8695_LAN12_POWERMAGR;
1854 break;
1856 case SW_PORT_1:
1857 default:
1858 uOff = KS8695_LAN12_POWERMAGR;
1859 uShift = 16;
1860 break;
1864 uReg = KS8695_READ_REG(uOff);
1865 if (bLoopback)
1866 uReg |= ((UINT)POWER_LOOPBACK << uShift);
1867 else
1868 uReg &= ~((UINT)POWER_LOOPBACK << uShift);
1869 KS8695_WRITE_REG(uOff, uReg);
1870 /* need 20 cpu clock delay for switch related registers */
1871 DelayInMicroseconds(10);
1873 return TRUE;
1877 * swGetMacAddress
1878 * This function is use to get switch engine Mac address and store it in stSwitchMac.
1880 * Argument(s)
1881 * Adapter pionter to ADAPTER_STRUCT data structure.
1883 * Return(s)
1884 * NONE
1886 void swGetMacAddress(PADAPTER_STRUCT Adapter)
1888 UINT32 uTmp;
1889 int i;
1891 #ifdef DEBUG_THIS
1892 DRV_INFO("%s", __FUNCTION__);
1893 #endif
1895 uTmp = KS8695_READ_REG(KS8695_SWITCH_MAC_LOW);
1896 for (i = (MAC_ADDRESS_LEN - 1); i > 1; i--)
1898 DI.stSwitchMac[i] = (UCHAR)(uTmp & 0x0ff);
1899 uTmp >>= 8;
1901 /* read high 2 bytes */
1902 uTmp = KS8695_READ_REG(KS8695_SWITCH_MAC_HIGH);
1903 DI.stSwitchMac[1] = (UCHAR)(uTmp & 0x0ff);
1904 uTmp >>= 8;
1905 DI.stSwitchMac[0] = (UCHAR)(uTmp & 0x0ff);
1909 * swSetMacAddress
1910 * This function is use to set switch engine Mac address.
1912 * Argument(s)
1913 * Adapter pionter to ADAPTER_STRUCT data structure.
1914 * pMac pointer to mac address buffer (should be 6)
1916 * Return(s)
1917 * NONE
1919 void swSetMacAddress(PADAPTER_STRUCT Adapter, UCHAR *pMac)
1921 uint32_t uLowAddress, uHighAddress;
1923 #ifdef DEBUG_THIS
1924 DRV_INFO("%s", __FUNCTION__);
1925 #endif
1927 memcpy(&DI.stSwitchMac, pMac, MAC_ADDRESS_LEN);
1928 uLowAddress = (*(pMac + 5) |
1929 (*(pMac + 4) << 8) |
1930 (*(pMac + 3) << 16)|
1931 *(pMac + 3) << 24);
1933 uHighAddress = (*(pMac + 1) |
1934 *pMac << 8);
1936 KS8695_WRITE_REG(KS8695_SWITCH_MAC_LOW, uLowAddress);
1937 /* need 20 cpu clock delay for switch related registers */
1938 DelayInMicroseconds(10);
1939 KS8695_WRITE_REG(KS8695_SWITCH_MAC_HIGH, uHighAddress);
1940 /* need 20 cpu clock delay for switch related registers */
1941 DelayInMicroseconds(10);
1945 * swResetSNMPInfo
1946 * This function is use to get SNMP counters information
1948 * Argument(s)
1949 * Adapter pionter to ADAPTER_STRUCT data structure.
1951 * Return(s)
1952 * NONE
1954 void swResetSNMPInfo(PADAPTER_STRUCT Adapter)
1956 memset(&Adapter->net_stats, 0, sizeof(Adapter->net_stats));
1960 * swCreateLookUpTable
1961 * This function is use to create loopup table.
1963 * Argument(s)
1964 * Adapter pionter to ADAPTER_STRUCT data structure.
1966 * Return(s)
1967 * NONE
1969 void swCreateLookUpTable(PADAPTER_STRUCT Adapter)
1971 unsigned int mac = 0, index = 0, tmp = 0, portmap = 0;
1973 #ifdef DEBUG_THIS
1974 DRV_INFO("%s", __FUNCTION__);
1975 #endif
1977 mac = 0x01020304;
1978 portmap = 0x10000;
1980 #ifndef CONFIG_ARCH_KS8695P
1981 for (index=0; index<5; index++)
1983 KS8695_WRITE_REG(KS8695_SWITCH_LUE_HIGH, 0x200000 + (portmap << index));
1984 DelayInMicroseconds(10);
1986 KS8695_WRITE_REG(KS8695_SWITCH_LUE_LOW, mac++);
1987 DelayInMicroseconds(10);
1989 KS8695_WRITE_REG(KS8695_SWITCH_LUE_CTRL, index);
1990 DelayInMicroseconds(10);
1994 tmp = KS8695_READ_REG(KS8695_SWITCH_LUE_CTRL) & 0x1000;
1995 } while (tmp);
1997 #else
1998 index = index; /* no complain pls */
1999 /* the user can program other MAC addresses for static table */
2000 tmp = 0x0002; /* e.g. this is the MAC high and low addr for the notebook I am using for test */
2001 mac = 0xa55d1590;
2003 KS8695_WRITE_REG(KS8695_SEIAC,
2004 KS8695_SEIAC_WRITE | KS8695_SEIAC_TAB_STATIC | (KS8695_SEIAC_INDEX_MASK & index));
2005 DelayInMicroseconds(10);
2007 KS8695_WRITE_REG(KS8695_SEIADH1, 0x200000 + (portmap << index) + tmp);
2008 DelayInMicroseconds(10);
2010 KS8695_WRITE_REG(KS8695_SEIADL, mac);
2011 DelayInMicroseconds(10);
2012 #endif
2016 * swConfigTagRemoval
2017 * This function is use to configure tag removal for ingress to given port.
2019 * Argument(s)
2020 * Adapter pionter to ADAPTER_STRUCT data structure.
2021 * uPort port for the tag to insert
2022 * bRemoval enable/disable removal
2024 * Return(s)
2025 * NONE
2027 void swConfigTagRemoval(PADAPTER_STRUCT Adapter, UINT uPort, UINT bRemoval)
2029 uint32_t uReg;
2031 uReg = KS8695_READ_REG(KS8695_SWITCH_ADVANCED);
2032 if (bRemoval) {
2033 uReg |= (1L << (22 + uPort));
2035 else {
2036 uReg &= ~(1L << (22 + uPort));
2038 KS8695_WRITE_REG(KS8695_SWITCH_ADVANCED, uReg);
2039 /* need 20 cpu clock delay for switch related registers */
2040 DelayInMicroseconds(10);
2044 * swConfigTagInsertion
2045 * This function is use to configure tag insertion for engress to given port.
2047 * Argument(s)
2048 * Adapter pionter to ADAPTER_STRUCT data structure.
2049 * uPort port for the tag to insert
2050 * bInsert enable/disable insertion
2052 * Return(s)
2053 * NONE
2055 void swConfigTagInsertion(PADAPTER_STRUCT Adapter, UINT uPort, UINT bInsert)
2057 uint32_t uReg;
2059 uReg = KS8695_READ_REG(KS8695_SWITCH_ADVANCED);
2060 if (bInsert) {
2061 uReg |= (1L << (17 + uPort));
2063 else {
2064 uReg &= ~(1L << (17 + uPort));
2066 KS8695_WRITE_REG(KS8695_SWITCH_ADVANCED, uReg);
2067 /* need 20 cpu clock delay for switch related registers */
2068 DelayInMicroseconds(10);
2072 * gpioConfigure
2073 * This function is use to configure GPIO pins required for extra LEDs
2074 * as speed indicators.
2076 * Argument(s)
2077 * Adapter pionter to ADAPTER_STRUCT data structure.
2079 * Return(s)
2080 * NONE
2082 void gpioConfigure(PADAPTER_STRUCT Adapter)
2084 #if !defined(CONFIG_MACH_CM4002) && !defined(CONFIG_MACH_CM4008) && \
2085 !defined(CONFIG_MACH_CM41xx)
2086 uint32_t uReg;
2087 uint32_t shift = 0;
2089 #ifdef KS8695P_MEDIABOX /* note that flag is defined in platform.h for mediabox platform */
2090 shift = 1; /* shift one bit to right for mediabox, that is from 3-7 - 5-8 */
2091 #endif
2093 uReg = KS8695_READ_REG(KS8695_GPIO_MODE);
2094 switch (DI.usDMAId) {
2095 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
2096 case DMA_HPNA:
2097 return;
2098 #endif
2100 case DMA_LAN:
2101 uReg |= (0xf0 << shift); /* GPIO 4-7 for port 1-4 or 5-8 for 1-4 for mediabox, configure them as output */
2102 break;
2104 default:
2105 case DMA_WAN:
2106 uReg |= (0x08 << shift); /* GPIO 3 for WAN port, or GPIO 4 in mediabox platform */
2107 break;
2109 KS8695_WRITE_REG(KS8695_GPIO_MODE, uReg);
2110 #endif
2114 * gpioSet
2115 * This function is use to set/reset given GPIO pin corresponding to the port.
2117 * Argument(s)
2118 * Adapter pionter to ADAPTER_STRUCT data structure.
2119 * uPort port for the tag to insert
2120 * bSet enable/disable LED
2122 * Return(s)
2123 * NONE
2125 void gpioSet(PADAPTER_STRUCT Adapter, UINT uPort, UINT bSet)
2127 #if !defined(CONFIG_MACH_CM4002) && !defined(CONFIG_MACH_CM4008) && \
2128 !defined(CONFIG_MACH_CM41xx) && !defined(CONFIG_MACH_SE4200)
2129 uint32_t uReg;
2130 uint32_t shift = 0;
2132 #ifdef KS8695P_MEDIABOX /* note that flag is defined in platform.h for mediabox platform */
2133 shift = 1; /* if mediabox, shift one bit to right, that is from bit 4-7 shift to bit 5-8 */
2134 #endif
2136 #ifdef DEBUG_THIS
2137 DRV_INFO("%s: port %d, %s", __FUNCTION__, uPort, bSet ? "100" : "10");
2138 #endif
2140 uReg = KS8695_READ_REG(KS8695_GPIO_DATA);
2141 switch (DI.usDMAId) {
2142 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
2143 case DMA_HPNA:
2144 return;
2145 #endif
2147 case DMA_LAN:
2148 if (bSet)
2149 uReg &= ~(1 << (uPort + 4 + shift)); /* low for LED on */
2150 else
2151 uReg |= (1 << (uPort + 4 + shift)); /* high for LED off */
2152 break;
2154 default:
2155 case DMA_WAN:
2156 if (bSet)
2157 uReg &= ~(0x08 << shift); /* low for LED on */
2158 else
2159 uReg |= (0x08 << shift); /* high for LED off */
2160 break;
2162 KS8695_WRITE_REG(KS8695_GPIO_DATA, uReg);
2163 #endif
2166 #ifdef CONFIG_ARCH_KS8695P
2168 * configureVID
2169 * This function is use to configure VID for given port
2171 * Argument(s)
2172 * Adapter pionter to ADAPTER_STRUCT data structure.
2173 * uPort uport to turn on/off Led
2174 * bFilter enable/disable ingress VLAN filtering
2175 * bDiscard discard Non PVID packets or not
2177 * Return(s)
2178 * NONE
2180 void configureVID(PADAPTER_STRUCT Adapter, UINT uPort, UINT bFilter, UINT bDiscard)
2182 u32 uReg, off;
2184 if (uPort > SW_MAX_LAN_PORTS) {
2185 printk("%s: port is out of range\n", __FUNCTION__);
2186 return;
2188 if (SW_MAX_LAN_PORTS == uPort)
2189 off = KS8695_SEP5C2;
2190 else
2191 off = KS8695_SEP1C2 + uPort * 0x0c;
2193 uReg = KS8695_READ_REG(off);
2194 if (bFilter)
2195 uReg &= ~KS8695_SEPC2_VLAN_FILTER;
2196 else
2197 uReg |= KS8695_SEPC2_VLAN_FILTER;
2198 if (bDiscard)
2199 uReg &= ~KS8695_SEPC2_DISCARD_NON_PVID;
2200 else
2201 uReg |= KS8695_SEPC2_DISCARD_NON_PVID;
2202 KS8695_WRITE_REG(off, uReg);
2203 DelayInMicroseconds(10);
2207 * backPressureEnable
2208 * This function is use to enable/disable back pressure for given port
2210 * Argument(s)
2211 * Adapter pionter to ADAPTER_STRUCT data structure.
2212 * uPort uport to turn on/off Led
2213 * bOn on/off the flow control
2215 * Return(s)
2216 * NONE
2218 void backPressureEnable(PADAPTER_STRUCT Adapter, UINT uPort, UINT bOn)
2220 u32 uReg, off;
2222 if (uPort > SW_MAX_LAN_PORTS) {
2223 printk("%s: port is out of range\n", __FUNCTION__);
2224 return;
2226 if (SW_MAX_LAN_PORTS == uPort)
2227 off = KS8695_SEP5C2;
2228 else
2229 off = KS8695_SEP1C2 + uPort * 0x0c;
2231 uReg = KS8695_READ_REG(off);
2232 if (bOn)
2233 uReg &= ~KS8695_SEPC2_BACK_PRESSURE_EN;
2234 else
2235 uReg |= KS8695_SEPC2_BACK_PRESSURE_EN;
2236 KS8695_WRITE_REG(off, uReg);
2237 DelayInMicroseconds(10);
2241 * forceFlowControl
2242 * This function is use to force flow control on the port, regardless of AN result
2244 * Argument(s)
2245 * Adapter pionter to ADAPTER_STRUCT data structure.
2246 * uPort uport to turn on/off Led
2247 * bOn on/off the flow control
2249 * Return(s)
2250 * NONE
2252 void forceFlowControl(PADAPTER_STRUCT Adapter, UINT uPort, UINT bOn)
2254 u32 uReg, off;
2256 if (uPort > SW_MAX_LAN_PORTS) {
2257 printk("%s: port is out of range\n", __FUNCTION__);
2258 return;
2260 if (SW_MAX_LAN_PORTS == uPort)
2261 off = KS8695_SEP5C2;
2262 else
2263 off = KS8695_SEP1C2 + uPort * 0x0c;
2265 uReg = KS8695_READ_REG(off);
2266 if (bOn) {
2267 uReg &= ~KS8695_SEPC2_FORCE_FLOW_CTRL;
2268 } else {
2269 uReg |= KS8695_SEPC2_FORCE_FLOW_CTRL;
2271 KS8695_WRITE_REG(off, uReg);
2272 DelayInMicroseconds(10);
2276 * setTxRate
2277 * This function is use to set transmit priority rate control for KS8695P
2279 * Argument(s)
2280 * Adapter pionter to ADAPTER_STRUCT data structure.
2281 * uPort uport to set
2282 * lrate low rate to set
2283 * hrate high rate to set
2285 * Return(s)
2286 * NONE
2288 void setTxRate(PADAPTER_STRUCT Adapter, UINT uPort, UINT lrate, UINT hrate)
2290 u32 uReg, off;
2292 if (uPort > SW_MAX_LAN_PORTS) {
2293 printk("%s: port is out of range\n", __FUNCTION__);
2294 return;
2296 if (SW_MAX_LAN_PORTS == uPort)
2297 off = KS8695_SEP5C2;
2298 else
2299 off = KS8695_SEP1C2 + uPort * 0x0c;
2300 uReg = KS8695_READ_REG(off);
2301 /* clear rate bits first */
2302 uReg &= ~(KS8695_SEPC2_TX_H_RATECTRL_MASK + KS8695_SEPC2_TX_L_RATECTRL_MASK);
2303 uReg = ((hrate << 12) & KS8695_SEPC2_TX_H_RATECTRL_MASK) + (lrate & KS8695_SEPC2_TX_L_RATECTRL_MASK);
2304 KS8695_WRITE_REG(off, uReg);
2305 DelayInMicroseconds(10);
2309 * setRxRate
2310 * This function is use to set receive priority rate control for KS8695P
2312 * Argument(s)
2313 * Adapter pionter to ADAPTER_STRUCT data structure.
2314 * uPort uport to set
2315 * lrate low rate to set
2316 * hrate high rate to set
2318 * Return(s)
2319 * NONE
2321 void setRxRate(PADAPTER_STRUCT Adapter, UINT uPort, UINT lrate, UINT hrate)
2323 u32 uReg, off;
2325 if (uPort > SW_MAX_LAN_PORTS) {
2326 printk("%s: port is out of range\n", __FUNCTION__);
2327 return;
2329 if (SW_MAX_LAN_PORTS == uPort)
2330 off = KS8695_SEP5C3;
2331 else
2332 off = KS8695_SEP1C3 + uPort * 0x0c;
2333 uReg = KS8695_READ_REG(off);
2334 /* clear rate bits first */
2335 uReg &= ~(KS8695_SEPC3_RX_H_RATECTRL_MASK + KS8695_SEPC3_RX_L_RATECTRL_MASK);
2336 uReg = ((hrate << 20) & KS8695_SEPC3_RX_H_RATECTRL_MASK) +
2337 ((lrate << 8) & KS8695_SEPC3_RX_L_RATECTRL_MASK);
2338 KS8695_WRITE_REG(off, uReg);
2339 DelayInMicroseconds(10);
2343 * enableRxRateFlowControl
2344 * This function is use to enable/disalbe receive priority rate flow control for KS8695P
2346 * Argument(s)
2347 * Adapter pionter to ADAPTER_STRUCT data structure.
2348 * uPort uport to set
2349 * bEnableLowFlow enable low rate flow control
2350 * bEnableHighFlow enable high rate flow control
2352 * Return(s)
2353 * NONE
2355 void enableRxRateFlowControl(PADAPTER_STRUCT Adapter, UINT uPort,
2356 UINT bEnableLowFlow, UINT bEnableHighFlow)
2358 u32 uReg, off;
2360 if (uPort > SW_MAX_LAN_PORTS) {
2361 printk("%s: port is out of range\n", __FUNCTION__);
2362 return;
2364 if (SW_MAX_LAN_PORTS == uPort)
2365 off = KS8695_SEP5C3;
2366 else
2367 off = KS8695_SEP1C3 + uPort * 0x0c;
2368 uReg = KS8695_READ_REG(off);
2369 if (bEnableLowFlow)
2370 uReg |= KS8695_SEPC3_RX_L_RATEFLOW_EN;
2371 else
2372 uReg &= ~KS8695_SEPC3_RX_L_RATEFLOW_EN;
2373 if (bEnableHighFlow)
2374 uReg |= KS8695_SEPC3_RX_H_RATEFLOW_EN;
2375 else
2376 uReg &= ~KS8695_SEPC3_RX_H_RATEFLOW_EN;
2378 KS8695_WRITE_REG(off, uReg);
2379 DelayInMicroseconds(10);
2383 * enableRxRateControl
2384 * This function is use to enable/disalbe receive priority rate control for KS8695P
2386 * Argument(s)
2387 * Adapter pionter to ADAPTER_STRUCT data structure.
2388 * uPort uport to set
2389 * bEnable enable/disable differential priority control
2390 * bEnableLow enable low rate control
2391 * bEnableHigh enable high rate control
2393 * Return(s)
2394 * NONE
2396 void enableRxRateControl(PADAPTER_STRUCT Adapter, UINT uPort, UINT bEnable,
2397 UINT bEnableLow, UINT bEnableHigh)
2399 u32 uReg, off;
2401 if (uPort > SW_MAX_LAN_PORTS) {
2402 printk("%s: port is out of range\n", __FUNCTION__);
2403 return;
2405 if (SW_MAX_LAN_PORTS == uPort)
2406 off = KS8695_SEP5C3;
2407 else
2408 off = KS8695_SEP1C3 + uPort * 0x0c;
2409 uReg = KS8695_READ_REG(off);
2410 if (bEnable)
2411 uReg |= KS8695_SEPC3_RX_DIF_RATECTRL_EN;
2412 else
2413 uReg &= ~KS8695_SEPC3_RX_DIF_RATECTRL_EN;
2414 if (bEnableLow)
2415 uReg |= KS8695_SEPC3_RX_L_RATECTRL_EN;
2416 else
2417 uReg &= ~KS8695_SEPC3_RX_L_RATECTRL_EN;
2418 if (bEnableHigh)
2419 uReg |= KS8695_SEPC3_RX_H_RATECTRL_EN;
2420 else
2421 uReg &= ~KS8695_SEPC3_RX_H_RATECTRL_EN;
2423 KS8695_WRITE_REG(off, uReg);
2424 DelayInMicroseconds(10);
2428 * enableTxRateControl
2429 * This function is use to enable/disalbe transmit priority rate control for KS8695P
2431 * Argument(s)
2432 * Adapter pionter to ADAPTER_STRUCT data structure.
2433 * uPort uport to set
2434 * bEnable enable/disable differential priority control
2435 * bEnableLow enable low rate control
2436 * bEnableHigh enable high rate control
2438 * Return(s)
2439 * NONE
2441 void enableTxRateControl(PADAPTER_STRUCT Adapter, UINT uPort, UINT bEnable,
2442 UINT bEnableLow, UINT bEnableHigh)
2444 u32 uReg, off;
2446 if (uPort > SW_MAX_LAN_PORTS) {
2447 printk("%s: port is out of range\n", __FUNCTION__);
2448 return;
2450 if (SW_MAX_LAN_PORTS == uPort)
2451 off = KS8695_SEP5C3;
2452 else
2453 off = KS8695_SEP1C3 + uPort * 0x0c;
2454 uReg = KS8695_READ_REG(off);
2455 if (bEnable)
2456 uReg |= KS8695_SEPC3_TX_DIF_RATECTRL_EN;
2457 else
2458 uReg &= ~KS8695_SEPC3_TX_DIF_RATECTRL_EN;
2459 if (bEnableLow)
2460 uReg |= KS8695_SEPC3_TX_L_RATECTRL_EN;
2461 else
2462 uReg &= ~KS8695_SEPC3_TX_L_RATECTRL_EN;
2463 if (bEnableHigh)
2464 uReg |= KS8695_SEPC3_TX_H_RATECTRL_EN;
2465 else
2466 uReg &= ~KS8695_SEPC3_TX_H_RATECTRL_EN;
2468 KS8695_WRITE_REG(off, uReg);
2469 DelayInMicroseconds(10);
2473 * dumpDynamicMacTable
2474 * This function is use to dump entries in dynamic MAC table
2476 * Argument(s)
2477 * Adapter pionter to ADAPTER_STRUCT data structure.
2479 * Return(s)
2480 * NONE
2482 void dumpDynamicMacTable(PADAPTER_STRUCT Adapter)
2484 u32 reg, v1, v2, timeout = 1000, i = 0;
2486 printk("Entry Port FID Mac\n");
2487 do {
2488 reg = KS8695_SEIAC_READ | KS8695_SEIAC_TAB_DYNAMIC | (KS8695_SEIAC_INDEX_MASK & i);
2489 KS8695_WRITE_REG(KS8695_SEIAC, reg);
2490 DelayInMicroseconds(10);
2492 v1 = KS8695_READ_REG(KS8695_SEIADH2);
2493 if (v1 & 0x10) { /* bit 68 = (68 - 64) */
2494 /* no valid entries */
2495 printk("0 entry\n");
2496 return;
2498 v2 = KS8695_READ_REG(KS8695_SEIADH1);
2499 /* if valid entries */
2500 if (!(v2 & 0x00800000)) { /* bit 55 */
2501 #if 0
2502 entries = ((v1 & 0xf) << 6) + (v2 >> 26) + 1;
2503 /* currently just dump first 16 entries (max 1K entries) for demon purpose */
2504 if (entries > 16) {
2505 printk("%s: more than 16 entries...(v1=0x%08x, v2=0x%08x)\n",
2506 __FUNCTION__, v1, v2);
2507 return;
2509 #endif
2510 v1 = KS8695_READ_REG(KS8695_SEIADL);
2511 printk("%04d %04d %4d %02x:%02x:%02x:%02x:%02x:%02x\n", i,
2512 (v2 >> 20) & 0x7, (v2 >> 16) & 0xf,
2513 ((v2 >> 8) & 0xff), (v2 & 0xff),
2514 ((v1 >> 24) & 0xff), ((v1 >> 16) & 0xff), ((v1 >> 8) & 0xff), (v1 & 0xff));
2515 timeout = 0;
2516 i++;
2518 DelayInMicroseconds(1);
2519 } while (timeout-- > 0 || i >= 16);
2521 if (timeout < 1)
2522 printk("%s: timeout error\n", __FUNCTION__);
2523 if (i >= 16) {
2524 printk("%s: more than 16 entries...v2=0x%08x\n",
2525 __FUNCTION__, v2);
2530 * disable8021xFlowControl
2531 * This function is use to disable IEEE 802.1x flow control
2533 * Argument(s)
2534 * Adapter pionter to ADAPTER_STRUCT data structure.
2535 * bTxDisable disable/enable IEEE 802.1x transmit flow control
2536 * bRxDisable disable/enable IEEE 802.1x receive flow control
2538 * Return(s)
2539 * NONE
2541 void disable8021xFlowControl(PADAPTER_STRUCT Adapter, UINT bTxDisable, UINT bRxDisable)
2543 u32 uReg, off;
2545 off = KS8695_SEC1;
2546 uReg = KS8695_READ_REG(off);
2547 if (bTxDisable) {
2548 uReg |= KS8695_SEC1_NO_TX_8021X_FLOW_CTRL;
2549 } else {
2550 uReg &= ~KS8695_SEC1_NO_TX_8021X_FLOW_CTRL;
2552 if (bRxDisable) {
2553 uReg |= KS8695_SEC1_NO_RX_8021X_FLOW_CTRL;
2554 } else {
2555 uReg &= ~KS8695_SEC1_NO_RX_8021X_FLOW_CTRL;
2557 KS8695_WRITE_REG(off, uReg);
2558 DelayInMicroseconds(10);
2562 * enablePhyLoopback
2563 * This function is enable/disable phy loopback for given port
2565 * Argument(s)
2566 * Adapter pionter to ADAPTER_STRUCT data structure.
2567 * uPort port to set
2568 * bEnable disable/enable phy loopback
2570 * Return(s)
2571 * NONE
2573 void enablePhyLoopback(PADAPTER_STRUCT Adapter, UINT uPort, UINT bEnable)
2575 u32 uReg, off, shift;
2577 if (uPort > SW_MAX_LAN_PORTS) {
2578 printk("%s: port is out of range\n", __FUNCTION__);
2579 return;
2581 if (SW_MAX_LAN_PORTS == uPort) {
2582 off = KS8695_WAN_POWERMAGR;
2584 else {
2585 if (uPort < 2)
2586 off = KS8695_LPPM12;
2587 else
2588 off = KS8695_LPPM34;
2590 shift = uPort % 2 ? 0: 1;
2591 uReg = KS8695_READ_REG(off);
2592 if (bEnable) {
2593 uReg |= (KS8695_LPPM_PHY_LOOPBACK << (shift * 16));
2594 } else {
2595 uReg &= ~(KS8695_LPPM_PHY_LOOPBACK << (shift * 16));
2597 KS8695_WRITE_REG(off, uReg);
2598 DelayInMicroseconds(10);
2602 * enableRemoteLoopback
2603 * This function is enable/disable remote loopback for given port
2605 * Argument(s)
2606 * Adapter pionter to ADAPTER_STRUCT data structure.
2607 * uPort port to set
2608 * bEnable disable/enable remote loopback
2610 * Return(s)
2611 * NONE
2613 void enableRemoteLoopback(PADAPTER_STRUCT Adapter, UINT uPort, UINT bEnable)
2615 u32 uReg, off, shift;
2617 if (uPort > SW_MAX_LAN_PORTS) {
2618 printk("%s: port is out of range\n", __FUNCTION__);
2619 return;
2621 if (SW_MAX_LAN_PORTS == uPort) {
2622 off = KS8695_WAN_POWERMAGR;
2624 else {
2625 if (uPort < 2)
2626 off = KS8695_LPPM12;
2627 else
2628 off = KS8695_LPPM34;
2630 shift = uPort % 2 ? 0: 1;
2631 uReg = KS8695_READ_REG(off);
2632 if (bEnable) {
2633 uReg |= (KS8695_LPPM_RMT_LOOPBACK << (shift * 16));
2634 } else {
2635 uReg &= ~(KS8695_LPPM_RMT_LOOPBACK << (shift * 16));
2637 KS8695_WRITE_REG(off, uReg);
2638 DelayInMicroseconds(10);
2642 * enablePhyIsolate
2643 * This function is enable/disable phy isolation for given port
2645 * Argument(s)
2646 * Adapter pionter to ADAPTER_STRUCT data structure.
2647 * uPort port to set
2648 * bEnable disable/enable phy isolation
2650 * Return(s)
2651 * NONE
2653 void enablePhyIsolate(PADAPTER_STRUCT Adapter, UINT uPort, UINT bEnable)
2655 u32 uReg, off, shift;
2657 if (uPort > SW_MAX_LAN_PORTS) {
2658 printk("%s: port is out of range\n", __FUNCTION__);
2659 return;
2661 if (SW_MAX_LAN_PORTS == uPort) {
2662 off = KS8695_WAN_POWERMAGR;
2664 else {
2665 if (uPort < 2)
2666 off = KS8695_LPPM12;
2667 else
2668 off = KS8695_LPPM34;
2670 shift = uPort % 2 ? 0: 1;
2671 uReg = KS8695_READ_REG(off);
2672 if (bEnable) {
2673 uReg |= (KS8695_LPPM_PHY_ISOLATE << (shift * 16));
2674 } else {
2675 uReg &= ~(KS8695_LPPM_PHY_ISOLATE << (shift * 16));
2677 KS8695_WRITE_REG(off, uReg);
2678 DelayInMicroseconds(10);
2682 * forcePhyLink
2683 * This function is enable/disable Link for give port
2685 * Argument(s)
2686 * Adapter pionter to ADAPTER_STRUCT data structure.
2687 * uPort port to set
2688 * bEnable disable/enable phy isolation
2690 * Return(s)
2691 * NONE
2693 void forcePhyLink(PADAPTER_STRUCT Adapter, UINT uPort, UINT bEnable)
2695 u32 uReg, off, shift;
2697 if (uPort > SW_MAX_LAN_PORTS) {
2698 printk("%s: port is out of range\n", __FUNCTION__);
2699 return;
2701 if (SW_MAX_LAN_PORTS == uPort) {
2702 off = KS8695_WAN_POWERMAGR;
2704 else {
2705 if (uPort < 2)
2706 off = KS8695_LPPM12;
2707 else
2708 off = KS8695_LPPM34;
2710 shift = uPort % 2 ? 0: 1;
2711 uReg = KS8695_READ_REG(off);
2712 if (bEnable) {
2713 uReg |= (KS8695_LPPM_FORCE_LINK << (shift * 16));
2714 } else {
2715 uReg &= ~(KS8695_LPPM_FORCE_LINK << (shift * 16));
2717 KS8695_WRITE_REG(off, uReg);
2718 DelayInMicroseconds(10);
2722 * dumpStaticMacTable
2723 * This function is use to dump entries in static MAC table
2725 * Argument(s)
2726 * Adapter pionter to ADAPTER_STRUCT data structure.
2728 * Return(s)
2729 * NONE
2731 void dumpStaticMacTable(PADAPTER_STRUCT Adapter)
2733 u32 reg, v1, v2, i = 0;
2735 printk("Entry Port FID Mac\n");
2736 for (i = 0; i < 8; i++) {
2737 reg = KS8695_SEIAC_READ | KS8695_SEIAC_TAB_STATIC | (KS8695_SEIAC_INDEX_MASK & i);
2738 KS8695_WRITE_REG(KS8695_SEIAC, reg);
2739 DelayInMicroseconds(10);
2741 v2 = KS8695_READ_REG(KS8695_SEIADH1);
2742 /* if table entry is valid */
2743 if (v2 & 0x00200000) {
2744 v1 = KS8695_READ_REG(KS8695_SEIADL);
2745 printk("%04d 0x%02x %4d %02x:%02x:%02x:%02x:%02x:%02x\n", i,
2746 (v2 >> 16) & 0x1f, (v2 >> 24) & 0xf,
2747 ((v2 >> 8) & 0xff), (v2 & 0xff),
2748 ((v1 >> 24) & 0xff), ((v1 >> 16) & 0xff), ((v1 >> 8) & 0xff), (v1 & 0xff));
2752 #endif