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);