1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
8 * Purpose: MAC routines
15 * MACbIsRegBitsOff - Test if All test Bits Off
16 * MACbIsIntDisable - Test if MAC interrupt disable
17 * MACvSetShortRetryLimit - Set 802.11 Short Retry limit
18 * MACvSetLongRetryLimit - Set 802.11 Long Retry limit
19 * MACvSetLoopbackMode - Set MAC Loopback Mode
20 * MACvSaveContext - Save Context of MAC Registers
21 * MACvRestoreContext - Restore Context of MAC Registers
22 * MACbSoftwareReset - Software Reset MAC
23 * MACbSafeRxOff - Turn Off MAC Rx
24 * MACbSafeTxOff - Turn Off MAC Tx
25 * MACbSafeStop - Stop MAC function
26 * MACbShutdown - Shut down MAC
27 * MACvInitialize - Initialize MAC
28 * MACvSetCurrRxDescAddr - Set Rx Descriptors Address
29 * MACvSetCurrTx0DescAddr - Set Tx0 Descriptors Address
30 * MACvSetCurrTx1DescAddr - Set Tx1 Descriptors Address
31 * MACvTimer0MicroSDelay - Micro Second Delay Loop by MAC
34 * 08-22-2003 Kyle Hsu : Porting MAC functions from sim53
35 * 09-03-2003 Bryan YC Fan : Add MACvClearBusSusInd()&
36 * MACvEnableBusSusEn()
37 * 09-18-2003 Jerry Chen : Add MACvSetKeyEntry & MACvDisableKeyEntry
46 * Test if all test bits off
50 * io_base - Base Address for MAC
51 * byRegOfs - Offset of MAC Register
52 * byTestBits - Test bits
56 * Return Value: true if all test bits Off; otherwise false
59 bool MACbIsRegBitsOff(struct vnt_private
*priv
, unsigned char byRegOfs
,
60 unsigned char byTestBits
)
62 void __iomem
*io_base
= priv
->PortOffset
;
64 return !(ioread8(io_base
+ byRegOfs
) & byTestBits
);
69 * Test if MAC interrupt disable
73 * io_base - Base Address for MAC
77 * Return Value: true if interrupt is disable; otherwise false
80 bool MACbIsIntDisable(struct vnt_private
*priv
)
82 void __iomem
*io_base
= priv
->PortOffset
;
84 if (ioread32(io_base
+ MAC_REG_IMR
))
92 * Set 802.11 Short Retry Limit
96 * io_base - Base Address for MAC
97 * byRetryLimit- Retry Limit
104 void MACvSetShortRetryLimit(struct vnt_private
*priv
,
105 unsigned char byRetryLimit
)
107 void __iomem
*io_base
= priv
->PortOffset
;
109 iowrite8(byRetryLimit
, io_base
+ MAC_REG_SRT
);
114 * Set 802.11 Long Retry Limit
118 * io_base - Base Address for MAC
119 * byRetryLimit- Retry Limit
126 void MACvSetLongRetryLimit(struct vnt_private
*priv
,
127 unsigned char byRetryLimit
)
129 void __iomem
*io_base
= priv
->PortOffset
;
131 iowrite8(byRetryLimit
, io_base
+ MAC_REG_LRT
);
136 * Set MAC Loopback mode
140 * io_base - Base Address for MAC
141 * byLoopbackMode - Loopback Mode
148 void MACvSetLoopbackMode(struct vnt_private
*priv
, unsigned char byLoopbackMode
)
150 void __iomem
*io_base
= priv
->PortOffset
;
152 byLoopbackMode
<<= 6;
154 iowrite8((ioread8(io_base
+ MAC_REG_TEST
) & 0x3f) | byLoopbackMode
,
155 io_base
+ MAC_REG_TEST
);
160 * Save MAC registers to context buffer
164 * io_base - Base Address for MAC
166 * cxt_buf - Context buffer
171 void MACvSaveContext(struct vnt_private
*priv
, unsigned char *cxt_buf
)
173 void __iomem
*io_base
= priv
->PortOffset
;
175 /* read page0 register */
176 memcpy_fromio(cxt_buf
, io_base
, MAC_MAX_CONTEXT_SIZE_PAGE0
);
178 MACvSelectPage1(io_base
);
180 /* read page1 register */
181 memcpy_fromio(cxt_buf
+ MAC_MAX_CONTEXT_SIZE_PAGE0
, io_base
,
182 MAC_MAX_CONTEXT_SIZE_PAGE1
);
184 MACvSelectPage0(io_base
);
189 * Restore MAC registers from context buffer
193 * io_base - Base Address for MAC
194 * cxt_buf - Context buffer
201 void MACvRestoreContext(struct vnt_private
*priv
, unsigned char *cxt_buf
)
203 void __iomem
*io_base
= priv
->PortOffset
;
205 MACvSelectPage1(io_base
);
207 memcpy_toio(io_base
, cxt_buf
+ MAC_MAX_CONTEXT_SIZE_PAGE0
,
208 MAC_MAX_CONTEXT_SIZE_PAGE1
);
210 MACvSelectPage0(io_base
);
212 /* restore RCR,TCR,IMR... */
213 memcpy_toio(io_base
+ MAC_REG_RCR
, cxt_buf
+ MAC_REG_RCR
,
214 MAC_REG_ISR
- MAC_REG_RCR
);
216 /* restore MAC Config. */
217 memcpy_toio(io_base
+ MAC_REG_LRT
, cxt_buf
+ MAC_REG_LRT
,
218 MAC_REG_PAGE1SEL
- MAC_REG_LRT
);
220 iowrite8(*(cxt_buf
+ MAC_REG_CFG
), io_base
+ MAC_REG_CFG
);
222 /* restore PS Config. */
223 memcpy_toio(io_base
+ MAC_REG_PSCFG
, cxt_buf
+ MAC_REG_PSCFG
,
224 MAC_REG_BBREGCTL
- MAC_REG_PSCFG
);
226 /* restore CURR_RX_DESC_ADDR, CURR_TX_DESC_ADDR */
227 iowrite32(*(u32
*)(cxt_buf
+ MAC_REG_TXDMAPTR0
),
228 io_base
+ MAC_REG_TXDMAPTR0
);
229 iowrite32(*(u32
*)(cxt_buf
+ MAC_REG_AC0DMAPTR
),
230 io_base
+ MAC_REG_AC0DMAPTR
);
231 iowrite32(*(u32
*)(cxt_buf
+ MAC_REG_BCNDMAPTR
),
232 io_base
+ MAC_REG_BCNDMAPTR
);
233 iowrite32(*(u32
*)(cxt_buf
+ MAC_REG_RXDMAPTR0
),
234 io_base
+ MAC_REG_RXDMAPTR0
);
235 iowrite32(*(u32
*)(cxt_buf
+ MAC_REG_RXDMAPTR1
),
236 io_base
+ MAC_REG_RXDMAPTR1
);
245 * io_base - Base Address for MAC
249 * Return Value: true if Reset Success; otherwise false
252 bool MACbSoftwareReset(struct vnt_private
*priv
)
254 void __iomem
*io_base
= priv
->PortOffset
;
257 /* turn on HOSTCR_SOFTRST, just write 0x01 to reset */
258 iowrite8(0x01, io_base
+ MAC_REG_HOSTCR
);
260 for (ww
= 0; ww
< W_MAX_TIMEOUT
; ww
++) {
261 if (!(ioread8(io_base
+ MAC_REG_HOSTCR
) & HOSTCR_SOFTRST
))
264 if (ww
== W_MAX_TIMEOUT
)
271 * save some important register's value, then do reset, then restore
276 * io_base - Base Address for MAC
280 * Return Value: true if success; otherwise false
283 bool MACbSafeSoftwareReset(struct vnt_private
*priv
)
285 unsigned char abyTmpRegData
[MAC_MAX_CONTEXT_SIZE_PAGE0
+ MAC_MAX_CONTEXT_SIZE_PAGE1
];
289 * save some important register's value, then do
290 * reset, then restore register's value
292 /* save MAC context */
293 MACvSaveContext(priv
, abyTmpRegData
);
295 bRetVal
= MACbSoftwareReset(priv
);
296 /* restore MAC context, except CR0 */
297 MACvRestoreContext(priv
, abyTmpRegData
);
308 * io_base - Base Address for MAC
312 * Return Value: true if success; otherwise false
315 bool MACbSafeRxOff(struct vnt_private
*priv
)
317 void __iomem
*io_base
= priv
->PortOffset
;
320 /* turn off wow temp for turn off Rx safely */
322 /* Clear RX DMA0,1 */
323 iowrite32(DMACTL_CLRRUN
, io_base
+ MAC_REG_RXDMACTL0
);
324 iowrite32(DMACTL_CLRRUN
, io_base
+ MAC_REG_RXDMACTL1
);
325 for (ww
= 0; ww
< W_MAX_TIMEOUT
; ww
++) {
326 if (!(ioread32(io_base
+ MAC_REG_RXDMACTL0
) & DMACTL_RUN
))
329 if (ww
== W_MAX_TIMEOUT
) {
330 pr_debug(" DBG_PORT80(0x10)\n");
333 for (ww
= 0; ww
< W_MAX_TIMEOUT
; ww
++) {
334 if (!(ioread32(io_base
+ MAC_REG_RXDMACTL1
) & DMACTL_RUN
))
337 if (ww
== W_MAX_TIMEOUT
) {
338 pr_debug(" DBG_PORT80(0x11)\n");
342 /* try to safe shutdown RX */
343 MACvRegBitsOff(io_base
, MAC_REG_HOSTCR
, HOSTCR_RXON
);
344 /* W_MAX_TIMEOUT is the timeout period */
345 for (ww
= 0; ww
< W_MAX_TIMEOUT
; ww
++) {
346 if (!(ioread8(io_base
+ MAC_REG_HOSTCR
) & HOSTCR_RXONST
))
349 if (ww
== W_MAX_TIMEOUT
) {
350 pr_debug(" DBG_PORT80(0x12)\n");
362 * io_base - Base Address for MAC
366 * Return Value: true if success; otherwise false
369 bool MACbSafeTxOff(struct vnt_private
*priv
)
371 void __iomem
*io_base
= priv
->PortOffset
;
376 iowrite32(DMACTL_CLRRUN
, io_base
+ MAC_REG_TXDMACTL0
);
378 iowrite32(DMACTL_CLRRUN
, io_base
+ MAC_REG_AC0DMACTL
);
380 for (ww
= 0; ww
< W_MAX_TIMEOUT
; ww
++) {
381 if (!(ioread32(io_base
+ MAC_REG_TXDMACTL0
) & DMACTL_RUN
))
384 if (ww
== W_MAX_TIMEOUT
) {
385 pr_debug(" DBG_PORT80(0x20)\n");
388 for (ww
= 0; ww
< W_MAX_TIMEOUT
; ww
++) {
389 if (!(ioread32(io_base
+ MAC_REG_AC0DMACTL
) & DMACTL_RUN
))
392 if (ww
== W_MAX_TIMEOUT
) {
393 pr_debug(" DBG_PORT80(0x21)\n");
397 /* try to safe shutdown TX */
398 MACvRegBitsOff(io_base
, MAC_REG_HOSTCR
, HOSTCR_TXON
);
400 /* W_MAX_TIMEOUT is the timeout period */
401 for (ww
= 0; ww
< W_MAX_TIMEOUT
; ww
++) {
402 if (!(ioread8(io_base
+ MAC_REG_HOSTCR
) & HOSTCR_TXONST
))
405 if (ww
== W_MAX_TIMEOUT
) {
406 pr_debug(" DBG_PORT80(0x24)\n");
418 * io_base - Base Address for MAC
422 * Return Value: true if success; otherwise false
425 bool MACbSafeStop(struct vnt_private
*priv
)
427 void __iomem
*io_base
= priv
->PortOffset
;
429 MACvRegBitsOff(io_base
, MAC_REG_TCR
, TCR_AUTOBCNTX
);
431 if (!MACbSafeRxOff(priv
)) {
432 pr_debug(" MACbSafeRxOff == false)\n");
433 MACbSafeSoftwareReset(priv
);
436 if (!MACbSafeTxOff(priv
)) {
437 pr_debug(" MACbSafeTxOff == false)\n");
438 MACbSafeSoftwareReset(priv
);
442 MACvRegBitsOff(io_base
, MAC_REG_HOSTCR
, HOSTCR_MACEN
);
453 * io_base - Base Address for MAC
457 * Return Value: true if success; otherwise false
460 bool MACbShutdown(struct vnt_private
*priv
)
462 void __iomem
*io_base
= priv
->PortOffset
;
463 /* disable MAC IMR */
464 MACvIntDisable(io_base
);
465 MACvSetLoopbackMode(priv
, MAC_LB_INTERNAL
);
466 /* stop the adapter */
467 if (!MACbSafeStop(priv
)) {
468 MACvSetLoopbackMode(priv
, MAC_LB_NONE
);
471 MACvSetLoopbackMode(priv
, MAC_LB_NONE
);
481 * io_base - Base Address for MAC
488 void MACvInitialize(struct vnt_private
*priv
)
490 void __iomem
*io_base
= priv
->PortOffset
;
491 /* clear sticky bits */
492 MACvClearStckDS(io_base
);
493 /* disable force PME-enable */
494 iowrite8(PME_OVR
, io_base
+ MAC_REG_PMC1
);
498 MACbSoftwareReset(priv
);
500 /* reset TSF counter */
501 iowrite8(TFTCTL_TSFCNTRST
, io_base
+ MAC_REG_TFTCTL
);
502 /* enable TSF counter */
503 iowrite8(TFTCTL_TSFCNTREN
, io_base
+ MAC_REG_TFTCTL
);
508 * Set the chip with current rx descriptor address
512 * io_base - Base Address for MAC
513 * curr_desc_addr - Descriptor Address
520 void MACvSetCurrRx0DescAddr(struct vnt_private
*priv
, u32 curr_desc_addr
)
522 void __iomem
*io_base
= priv
->PortOffset
;
524 unsigned char org_dma_ctl
;
526 org_dma_ctl
= ioread8(io_base
+ MAC_REG_RXDMACTL0
);
527 if (org_dma_ctl
& DMACTL_RUN
)
528 iowrite8(DMACTL_RUN
, io_base
+ MAC_REG_RXDMACTL0
+ 2);
530 for (ww
= 0; ww
< W_MAX_TIMEOUT
; ww
++) {
531 if (!(ioread8(io_base
+ MAC_REG_RXDMACTL0
) & DMACTL_RUN
))
535 iowrite32(curr_desc_addr
, io_base
+ MAC_REG_RXDMAPTR0
);
536 if (org_dma_ctl
& DMACTL_RUN
)
537 iowrite8(DMACTL_RUN
, io_base
+ MAC_REG_RXDMACTL0
);
542 * Set the chip with current rx descriptor address
546 * io_base - Base Address for MAC
547 * curr_desc_addr - Descriptor Address
554 void MACvSetCurrRx1DescAddr(struct vnt_private
*priv
, u32 curr_desc_addr
)
556 void __iomem
*io_base
= priv
->PortOffset
;
558 unsigned char org_dma_ctl
;
560 org_dma_ctl
= ioread8(io_base
+ MAC_REG_RXDMACTL1
);
561 if (org_dma_ctl
& DMACTL_RUN
)
562 iowrite8(DMACTL_RUN
, io_base
+ MAC_REG_RXDMACTL1
+ 2);
564 for (ww
= 0; ww
< W_MAX_TIMEOUT
; ww
++) {
565 if (!(ioread8(io_base
+ MAC_REG_RXDMACTL1
) & DMACTL_RUN
))
569 iowrite32(curr_desc_addr
, io_base
+ MAC_REG_RXDMAPTR1
);
570 if (org_dma_ctl
& DMACTL_RUN
)
571 iowrite8(DMACTL_RUN
, io_base
+ MAC_REG_RXDMACTL1
);
576 * Set the chip with current tx0 descriptor address
580 * io_base - Base Address for MAC
581 * curr_desc_addr - Descriptor Address
588 void MACvSetCurrTx0DescAddrEx(struct vnt_private
*priv
,
591 void __iomem
*io_base
= priv
->PortOffset
;
593 unsigned char org_dma_ctl
;
595 org_dma_ctl
= ioread8(io_base
+ MAC_REG_TXDMACTL0
);
596 if (org_dma_ctl
& DMACTL_RUN
)
597 iowrite8(DMACTL_RUN
, io_base
+ MAC_REG_TXDMACTL0
+ 2);
599 for (ww
= 0; ww
< W_MAX_TIMEOUT
; ww
++) {
600 if (!(ioread8(io_base
+ MAC_REG_TXDMACTL0
) & DMACTL_RUN
))
604 iowrite32(curr_desc_addr
, io_base
+ MAC_REG_TXDMAPTR0
);
605 if (org_dma_ctl
& DMACTL_RUN
)
606 iowrite8(DMACTL_RUN
, io_base
+ MAC_REG_TXDMACTL0
);
611 * Set the chip with current AC0 descriptor address
615 * io_base - Base Address for MAC
616 * curr_desc_addr - Descriptor Address
623 /* TxDMA1 = AC0DMA */
624 void MACvSetCurrAC0DescAddrEx(struct vnt_private
*priv
,
627 void __iomem
*io_base
= priv
->PortOffset
;
629 unsigned char org_dma_ctl
;
631 org_dma_ctl
= ioread8(io_base
+ MAC_REG_AC0DMACTL
);
632 if (org_dma_ctl
& DMACTL_RUN
)
633 iowrite8(DMACTL_RUN
, io_base
+ MAC_REG_AC0DMACTL
+ 2);
635 for (ww
= 0; ww
< W_MAX_TIMEOUT
; ww
++) {
636 if (!(ioread8(io_base
+ MAC_REG_AC0DMACTL
) & DMACTL_RUN
))
639 if (ww
== W_MAX_TIMEOUT
)
640 pr_debug(" DBG_PORT80(0x26)\n");
641 iowrite32(curr_desc_addr
, io_base
+ MAC_REG_AC0DMAPTR
);
642 if (org_dma_ctl
& DMACTL_RUN
)
643 iowrite8(DMACTL_RUN
, io_base
+ MAC_REG_AC0DMACTL
);
646 void MACvSetCurrTXDescAddr(int iTxType
, struct vnt_private
*priv
,
649 if (iTxType
== TYPE_AC0DMA
)
650 MACvSetCurrAC0DescAddrEx(priv
, curr_desc_addr
);
651 else if (iTxType
== TYPE_TXDMA0
)
652 MACvSetCurrTx0DescAddrEx(priv
, curr_desc_addr
);
657 * Micro Second Delay via MAC
661 * io_base - Base Address for MAC
662 * uDelay - Delay time (timer resolution is 4 us)
669 void MACvTimer0MicroSDelay(struct vnt_private
*priv
, unsigned int uDelay
)
671 void __iomem
*io_base
= priv
->PortOffset
;
672 unsigned char byValue
;
675 iowrite8(0, io_base
+ MAC_REG_TMCTL0
);
676 iowrite32(uDelay
, io_base
+ MAC_REG_TMDATA0
);
677 iowrite8((TMCTL_TMD
| TMCTL_TE
), io_base
+ MAC_REG_TMCTL0
);
678 for (ii
= 0; ii
< 66; ii
++) { /* assume max PCI clock is 66Mhz */
679 for (uu
= 0; uu
< uDelay
; uu
++) {
680 byValue
= ioread8(io_base
+ MAC_REG_TMCTL0
);
681 if ((byValue
== 0) ||
682 (byValue
& TMCTL_TSUSP
)) {
683 iowrite8(0, io_base
+ MAC_REG_TMCTL0
);
688 iowrite8(0, io_base
+ MAC_REG_TMCTL0
);
693 * Micro Second One shot timer via MAC
697 * io_base - Base Address for MAC
698 * uDelay - Delay time
705 void MACvOneShotTimer1MicroSec(struct vnt_private
*priv
,
706 unsigned int uDelayTime
)
708 void __iomem
*io_base
= priv
->PortOffset
;
710 iowrite8(0, io_base
+ MAC_REG_TMCTL1
);
711 iowrite32(uDelayTime
, io_base
+ MAC_REG_TMDATA1
);
712 iowrite8((TMCTL_TMD
| TMCTL_TE
), io_base
+ MAC_REG_TMCTL1
);
715 void MACvSetMISCFifo(struct vnt_private
*priv
, unsigned short offset
,
718 void __iomem
*io_base
= priv
->PortOffset
;
722 iowrite16(offset
, io_base
+ MAC_REG_MISCFFNDEX
);
723 iowrite32(data
, io_base
+ MAC_REG_MISCFFDATA
);
724 iowrite16(MISCFFCTL_WRITE
, io_base
+ MAC_REG_MISCFFCTL
);
727 bool MACbPSWakeup(struct vnt_private
*priv
)
729 void __iomem
*io_base
= priv
->PortOffset
;
732 if (MACbIsRegBitsOff(priv
, MAC_REG_PSCTL
, PSCTL_PS
))
736 MACvRegBitsOff(io_base
, MAC_REG_PSCTL
, PSCTL_PSEN
);
738 /* Check if SyncFlushOK */
739 for (ww
= 0; ww
< W_MAX_TIMEOUT
; ww
++) {
740 if (ioread8(io_base
+ MAC_REG_PSCTL
) & PSCTL_WAKEDONE
)
743 if (ww
== W_MAX_TIMEOUT
) {
744 pr_debug(" DBG_PORT80(0x33)\n");
752 * Set the Key by MISCFIFO
756 * io_base - Base Address for MAC
765 void MACvSetKeyEntry(struct vnt_private
*priv
, unsigned short wKeyCtl
,
766 unsigned int uEntryIdx
, unsigned int uKeyIdx
,
767 unsigned char *pbyAddr
, u32
*pdwKey
,
768 unsigned char byLocalID
)
770 void __iomem
*io_base
= priv
->PortOffset
;
771 unsigned short offset
;
778 pr_debug("%s\n", __func__
);
779 offset
= MISCFIFO_KEYETRY0
;
780 offset
+= (uEntryIdx
* MISCFIFO_KEYENTRYSIZE
);
785 data
|= MAKEWORD(*(pbyAddr
+ 4), *(pbyAddr
+ 5));
786 pr_debug("1. offset: %d, Data: %X, KeyCtl:%X\n",
787 offset
, data
, wKeyCtl
);
789 iowrite16(offset
, io_base
+ MAC_REG_MISCFFNDEX
);
790 iowrite32(data
, io_base
+ MAC_REG_MISCFFDATA
);
791 iowrite16(MISCFFCTL_WRITE
, io_base
+ MAC_REG_MISCFFCTL
);
795 data
|= *(pbyAddr
+ 3);
797 data
|= *(pbyAddr
+ 2);
799 data
|= *(pbyAddr
+ 1);
802 pr_debug("2. offset: %d, Data: %X\n", offset
, data
);
804 iowrite16(offset
, io_base
+ MAC_REG_MISCFFNDEX
);
805 iowrite32(data
, io_base
+ MAC_REG_MISCFFDATA
);
806 iowrite16(MISCFFCTL_WRITE
, io_base
+ MAC_REG_MISCFFCTL
);
809 offset
+= (uKeyIdx
* 4);
810 for (ii
= 0; ii
< 4; ii
++) {
811 /* always push 128 bits */
812 pr_debug("3.(%d) offset: %d, Data: %X\n",
813 ii
, offset
+ ii
, *pdwKey
);
814 iowrite16(offset
+ ii
, io_base
+ MAC_REG_MISCFFNDEX
);
815 iowrite32(*pdwKey
++, io_base
+ MAC_REG_MISCFFDATA
);
816 iowrite16(MISCFFCTL_WRITE
, io_base
+ MAC_REG_MISCFFCTL
);
822 * Disable the Key Entry by MISCFIFO
826 * io_base - Base Address for MAC
834 void MACvDisableKeyEntry(struct vnt_private
*priv
, unsigned int uEntryIdx
)
836 void __iomem
*io_base
= priv
->PortOffset
;
837 unsigned short offset
;
839 offset
= MISCFIFO_KEYETRY0
;
840 offset
+= (uEntryIdx
* MISCFIFO_KEYENTRYSIZE
);
842 iowrite16(offset
, io_base
+ MAC_REG_MISCFFNDEX
);
843 iowrite32(0, io_base
+ MAC_REG_MISCFFDATA
);
844 iowrite16(MISCFFCTL_WRITE
, io_base
+ MAC_REG_MISCFFCTL
);