1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
6 * Purpose: MAC routines
13 * MACbIsRegBitsOff - Test if All test Bits Off
14 * MACbIsIntDisable - Test if MAC interrupt disable
15 * MACvSetShortRetryLimit - Set 802.11 Short Retry limit
16 * MACvSetLongRetryLimit - Set 802.11 Long Retry limit
17 * MACvSetLoopbackMode - Set MAC Loopback Mode
18 * MACvSaveContext - Save Context of MAC Registers
19 * MACvRestoreContext - Restore Context of MAC Registers
20 * MACbSoftwareReset - Software Reset MAC
21 * MACbSafeRxOff - Turn Off MAC Rx
22 * MACbSafeTxOff - Turn Off MAC Tx
23 * MACbSafeStop - Stop MAC function
24 * MACbShutdown - Shut down MAC
25 * MACvInitialize - Initialize MAC
26 * MACvSetCurrRxDescAddr - Set Rx Descriptors Address
27 * MACvSetCurrTx0DescAddr - Set Tx0 Descriptors Address
28 * MACvSetCurrTx1DescAddr - Set Tx1 Descriptors Address
29 * MACvTimer0MicroSDelay - Micro Second Delay Loop by MAC
32 * 08-22-2003 Kyle Hsu : Porting MAC functions from sim53
33 * 09-03-2003 Bryan YC Fan : Add MACvClearBusSusInd()&
34 * MACvEnableBusSusEn()
35 * 09-18-2003 Jerry Chen : Add MACvSetKeyEntry & MACvDisableKeyEntry
44 * Test if all test bits off
48 * io_base - Base Address for MAC
49 * byRegOfs - Offset of MAC Register
50 * byTestBits - Test bits
54 * Return Value: true if all test bits Off; otherwise false
57 bool MACbIsRegBitsOff(struct vnt_private *priv, unsigned char byRegOfs,
58 unsigned char byTestBits)
60 void __iomem *io_base = priv->port_offset;
62 return !(ioread8(io_base + byRegOfs) & byTestBits);
67 * Test if MAC interrupt disable
71 * io_base - Base Address for MAC
75 * Return Value: true if interrupt is disable; otherwise false
78 bool MACbIsIntDisable(struct vnt_private *priv)
80 void __iomem *io_base = priv->port_offset;
82 if (ioread32(io_base + MAC_REG_IMR))
90 * Set 802.11 Short Retry Limit
94 * io_base - Base Address for MAC
95 * byRetryLimit- Retry Limit
102 void MACvSetShortRetryLimit(struct vnt_private *priv,
103 unsigned char byRetryLimit)
105 void __iomem *io_base = priv->port_offset;
107 iowrite8(byRetryLimit, io_base + MAC_REG_SRT);
112 * Set 802.11 Long Retry Limit
116 * io_base - Base Address for MAC
117 * byRetryLimit- Retry Limit
124 void MACvSetLongRetryLimit(struct vnt_private *priv,
125 unsigned char byRetryLimit)
127 void __iomem *io_base = priv->port_offset;
129 iowrite8(byRetryLimit, io_base + MAC_REG_LRT);
134 * Set MAC Loopback mode
138 * io_base - Base Address for MAC
139 * byLoopbackMode - Loopback Mode
146 void MACvSetLoopbackMode(struct vnt_private *priv, unsigned char byLoopbackMode)
148 void __iomem *io_base = priv->port_offset;
150 byLoopbackMode <<= 6;
152 iowrite8((ioread8(io_base + MAC_REG_TEST) & 0x3f) | byLoopbackMode,
153 io_base + MAC_REG_TEST);
158 * Save MAC registers to context buffer
162 * io_base - Base Address for MAC
164 * cxt_buf - Context buffer
169 void MACvSaveContext(struct vnt_private *priv, unsigned char *cxt_buf)
171 void __iomem *io_base = priv->port_offset;
173 /* read page0 register */
174 memcpy_fromio(cxt_buf, io_base, MAC_MAX_CONTEXT_SIZE_PAGE0);
176 MACvSelectPage1(io_base);
178 /* read page1 register */
179 memcpy_fromio(cxt_buf + MAC_MAX_CONTEXT_SIZE_PAGE0, io_base,
180 MAC_MAX_CONTEXT_SIZE_PAGE1);
182 MACvSelectPage0(io_base);
187 * Restore MAC registers from context buffer
191 * io_base - Base Address for MAC
192 * cxt_buf - Context buffer
199 void MACvRestoreContext(struct vnt_private *priv, unsigned char *cxt_buf)
201 void __iomem *io_base = priv->port_offset;
203 MACvSelectPage1(io_base);
205 memcpy_toio(io_base, cxt_buf + MAC_MAX_CONTEXT_SIZE_PAGE0,
206 MAC_MAX_CONTEXT_SIZE_PAGE1);
208 MACvSelectPage0(io_base);
210 /* restore RCR,TCR,IMR... */
211 memcpy_toio(io_base + MAC_REG_RCR, cxt_buf + MAC_REG_RCR,
212 MAC_REG_ISR - MAC_REG_RCR);
214 /* restore MAC Config. */
215 memcpy_toio(io_base + MAC_REG_LRT, cxt_buf + MAC_REG_LRT,
216 MAC_REG_PAGE1SEL - MAC_REG_LRT);
218 iowrite8(*(cxt_buf + MAC_REG_CFG), io_base + MAC_REG_CFG);
220 /* restore PS Config. */
221 memcpy_toio(io_base + MAC_REG_PSCFG, cxt_buf + MAC_REG_PSCFG,
222 MAC_REG_BBREGCTL - MAC_REG_PSCFG);
224 /* restore CURR_RX_DESC_ADDR, CURR_TX_DESC_ADDR */
225 iowrite32(*(u32 *)(cxt_buf + MAC_REG_TXDMAPTR0),
226 io_base + MAC_REG_TXDMAPTR0);
227 iowrite32(*(u32 *)(cxt_buf + MAC_REG_AC0DMAPTR),
228 io_base + MAC_REG_AC0DMAPTR);
229 iowrite32(*(u32 *)(cxt_buf + MAC_REG_BCNDMAPTR),
230 io_base + MAC_REG_BCNDMAPTR);
231 iowrite32(*(u32 *)(cxt_buf + MAC_REG_RXDMAPTR0),
232 io_base + MAC_REG_RXDMAPTR0);
233 iowrite32(*(u32 *)(cxt_buf + MAC_REG_RXDMAPTR1),
234 io_base + MAC_REG_RXDMAPTR1);
243 * io_base - Base Address for MAC
247 * Return Value: true if Reset Success; otherwise false
250 bool MACbSoftwareReset(struct vnt_private *priv)
252 void __iomem *io_base = priv->port_offset;
255 /* turn on HOSTCR_SOFTRST, just write 0x01 to reset */
256 iowrite8(0x01, io_base + MAC_REG_HOSTCR);
258 for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
259 if (!(ioread8(io_base + MAC_REG_HOSTCR) & HOSTCR_SOFTRST))
262 if (ww == W_MAX_TIMEOUT)
269 * save some important register's value, then do reset, then restore
274 * io_base - Base Address for MAC
278 * Return Value: true if success; otherwise false
281 bool MACbSafeSoftwareReset(struct vnt_private *priv)
283 unsigned char abyTmpRegData[MAC_MAX_CONTEXT_SIZE_PAGE0 + MAC_MAX_CONTEXT_SIZE_PAGE1];
287 * save some important register's value, then do
288 * reset, then restore register's value
290 /* save MAC context */
291 MACvSaveContext(priv, abyTmpRegData);
293 bRetVal = MACbSoftwareReset(priv);
294 /* restore MAC context, except CR0 */
295 MACvRestoreContext(priv, abyTmpRegData);
306 * io_base - Base Address for MAC
310 * Return Value: true if success; otherwise false
313 bool MACbSafeRxOff(struct vnt_private *priv)
315 void __iomem *io_base = priv->port_offset;
318 /* turn off wow temp for turn off Rx safely */
320 /* Clear RX DMA0,1 */
321 iowrite32(DMACTL_CLRRUN, io_base + MAC_REG_RXDMACTL0);
322 iowrite32(DMACTL_CLRRUN, io_base + MAC_REG_RXDMACTL1);
323 for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
324 if (!(ioread32(io_base + MAC_REG_RXDMACTL0) & DMACTL_RUN))
327 if (ww == W_MAX_TIMEOUT) {
328 pr_debug(" DBG_PORT80(0x10)\n");
331 for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
332 if (!(ioread32(io_base + MAC_REG_RXDMACTL1) & DMACTL_RUN))
335 if (ww == W_MAX_TIMEOUT) {
336 pr_debug(" DBG_PORT80(0x11)\n");
340 /* try to safe shutdown RX */
341 MACvRegBitsOff(io_base, MAC_REG_HOSTCR, HOSTCR_RXON);
342 /* W_MAX_TIMEOUT is the timeout period */
343 for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
344 if (!(ioread8(io_base + MAC_REG_HOSTCR) & HOSTCR_RXONST))
347 if (ww == W_MAX_TIMEOUT) {
348 pr_debug(" DBG_PORT80(0x12)\n");
360 * io_base - Base Address for MAC
364 * Return Value: true if success; otherwise false
367 bool MACbSafeTxOff(struct vnt_private *priv)
369 void __iomem *io_base = priv->port_offset;
374 iowrite32(DMACTL_CLRRUN, io_base + MAC_REG_TXDMACTL0);
376 iowrite32(DMACTL_CLRRUN, io_base + MAC_REG_AC0DMACTL);
378 for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
379 if (!(ioread32(io_base + MAC_REG_TXDMACTL0) & DMACTL_RUN))
382 if (ww == W_MAX_TIMEOUT) {
383 pr_debug(" DBG_PORT80(0x20)\n");
386 for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
387 if (!(ioread32(io_base + MAC_REG_AC0DMACTL) & DMACTL_RUN))
390 if (ww == W_MAX_TIMEOUT) {
391 pr_debug(" DBG_PORT80(0x21)\n");
395 /* try to safe shutdown TX */
396 MACvRegBitsOff(io_base, MAC_REG_HOSTCR, HOSTCR_TXON);
398 /* W_MAX_TIMEOUT is the timeout period */
399 for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
400 if (!(ioread8(io_base + MAC_REG_HOSTCR) & HOSTCR_TXONST))
403 if (ww == W_MAX_TIMEOUT) {
404 pr_debug(" DBG_PORT80(0x24)\n");
416 * io_base - Base Address for MAC
420 * Return Value: true if success; otherwise false
423 bool MACbSafeStop(struct vnt_private *priv)
425 void __iomem *io_base = priv->port_offset;
427 MACvRegBitsOff(io_base, MAC_REG_TCR, TCR_AUTOBCNTX);
429 if (!MACbSafeRxOff(priv)) {
430 pr_debug(" MACbSafeRxOff == false)\n");
431 MACbSafeSoftwareReset(priv);
434 if (!MACbSafeTxOff(priv)) {
435 pr_debug(" MACbSafeTxOff == false)\n");
436 MACbSafeSoftwareReset(priv);
440 MACvRegBitsOff(io_base, MAC_REG_HOSTCR, HOSTCR_MACEN);
451 * io_base - Base Address for MAC
455 * Return Value: true if success; otherwise false
458 bool MACbShutdown(struct vnt_private *priv)
460 void __iomem *io_base = priv->port_offset;
461 /* disable MAC IMR */
462 MACvIntDisable(io_base);
463 MACvSetLoopbackMode(priv, MAC_LB_INTERNAL);
464 /* stop the adapter */
465 if (!MACbSafeStop(priv)) {
466 MACvSetLoopbackMode(priv, MAC_LB_NONE);
469 MACvSetLoopbackMode(priv, MAC_LB_NONE);
479 * io_base - Base Address for MAC
486 void MACvInitialize(struct vnt_private *priv)
488 void __iomem *io_base = priv->port_offset;
489 /* clear sticky bits */
490 MACvClearStckDS(io_base);
491 /* disable force PME-enable */
492 iowrite8(PME_OVR, io_base + MAC_REG_PMC1);
496 MACbSoftwareReset(priv);
498 /* reset TSF counter */
499 iowrite8(TFTCTL_TSFCNTRST, io_base + MAC_REG_TFTCTL);
500 /* enable TSF counter */
501 iowrite8(TFTCTL_TSFCNTREN, io_base + MAC_REG_TFTCTL);
506 * Set the chip with current rx descriptor address
510 * io_base - Base Address for MAC
511 * curr_desc_addr - Descriptor Address
518 void MACvSetCurrRx0DescAddr(struct vnt_private *priv, u32 curr_desc_addr)
520 void __iomem *io_base = priv->port_offset;
522 unsigned char org_dma_ctl;
524 org_dma_ctl = ioread8(io_base + MAC_REG_RXDMACTL0);
525 if (org_dma_ctl & DMACTL_RUN)
526 iowrite8(DMACTL_RUN, io_base + MAC_REG_RXDMACTL0 + 2);
528 for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
529 if (!(ioread8(io_base + MAC_REG_RXDMACTL0) & DMACTL_RUN))
533 iowrite32(curr_desc_addr, io_base + MAC_REG_RXDMAPTR0);
534 if (org_dma_ctl & DMACTL_RUN)
535 iowrite8(DMACTL_RUN, io_base + MAC_REG_RXDMACTL0);
540 * Set the chip with current rx descriptor address
544 * io_base - Base Address for MAC
545 * curr_desc_addr - Descriptor Address
552 void MACvSetCurrRx1DescAddr(struct vnt_private *priv, u32 curr_desc_addr)
554 void __iomem *io_base = priv->port_offset;
556 unsigned char org_dma_ctl;
558 org_dma_ctl = ioread8(io_base + MAC_REG_RXDMACTL1);
559 if (org_dma_ctl & DMACTL_RUN)
560 iowrite8(DMACTL_RUN, io_base + MAC_REG_RXDMACTL1 + 2);
562 for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
563 if (!(ioread8(io_base + MAC_REG_RXDMACTL1) & DMACTL_RUN))
567 iowrite32(curr_desc_addr, io_base + MAC_REG_RXDMAPTR1);
568 if (org_dma_ctl & DMACTL_RUN)
569 iowrite8(DMACTL_RUN, io_base + MAC_REG_RXDMACTL1);
574 * Set the chip with current tx0 descriptor address
578 * io_base - Base Address for MAC
579 * curr_desc_addr - Descriptor Address
586 void MACvSetCurrTx0DescAddrEx(struct vnt_private *priv,
589 void __iomem *io_base = priv->port_offset;
591 unsigned char org_dma_ctl;
593 org_dma_ctl = ioread8(io_base + MAC_REG_TXDMACTL0);
594 if (org_dma_ctl & DMACTL_RUN)
595 iowrite8(DMACTL_RUN, io_base + MAC_REG_TXDMACTL0 + 2);
597 for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
598 if (!(ioread8(io_base + MAC_REG_TXDMACTL0) & DMACTL_RUN))
602 iowrite32(curr_desc_addr, io_base + MAC_REG_TXDMAPTR0);
603 if (org_dma_ctl & DMACTL_RUN)
604 iowrite8(DMACTL_RUN, io_base + MAC_REG_TXDMACTL0);
609 * Set the chip with current AC0 descriptor address
613 * io_base - Base Address for MAC
614 * curr_desc_addr - Descriptor Address
621 /* TxDMA1 = AC0DMA */
622 void MACvSetCurrAC0DescAddrEx(struct vnt_private *priv,
625 void __iomem *io_base = priv->port_offset;
627 unsigned char org_dma_ctl;
629 org_dma_ctl = ioread8(io_base + MAC_REG_AC0DMACTL);
630 if (org_dma_ctl & DMACTL_RUN)
631 iowrite8(DMACTL_RUN, io_base + MAC_REG_AC0DMACTL + 2);
633 for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
634 if (!(ioread8(io_base + MAC_REG_AC0DMACTL) & DMACTL_RUN))
637 if (ww == W_MAX_TIMEOUT)
638 pr_debug(" DBG_PORT80(0x26)\n");
639 iowrite32(curr_desc_addr, io_base + MAC_REG_AC0DMAPTR);
640 if (org_dma_ctl & DMACTL_RUN)
641 iowrite8(DMACTL_RUN, io_base + MAC_REG_AC0DMACTL);
644 void MACvSetCurrTXDescAddr(int iTxType, struct vnt_private *priv,
647 if (iTxType == TYPE_AC0DMA)
648 MACvSetCurrAC0DescAddrEx(priv, curr_desc_addr);
649 else if (iTxType == TYPE_TXDMA0)
650 MACvSetCurrTx0DescAddrEx(priv, curr_desc_addr);
655 * Micro Second Delay via MAC
659 * io_base - Base Address for MAC
660 * uDelay - Delay time (timer resolution is 4 us)
667 void MACvTimer0MicroSDelay(struct vnt_private *priv, unsigned int uDelay)
669 void __iomem *io_base = priv->port_offset;
670 unsigned char byValue;
673 iowrite8(0, io_base + MAC_REG_TMCTL0);
674 iowrite32(uDelay, io_base + MAC_REG_TMDATA0);
675 iowrite8((TMCTL_TMD | TMCTL_TE), io_base + MAC_REG_TMCTL0);
676 for (ii = 0; ii < 66; ii++) { /* assume max PCI clock is 66Mhz */
677 for (uu = 0; uu < uDelay; uu++) {
678 byValue = ioread8(io_base + MAC_REG_TMCTL0);
679 if ((byValue == 0) ||
680 (byValue & TMCTL_TSUSP)) {
681 iowrite8(0, io_base + MAC_REG_TMCTL0);
686 iowrite8(0, io_base + MAC_REG_TMCTL0);
691 * Micro Second One shot timer via MAC
695 * io_base - Base Address for MAC
696 * uDelay - Delay time
703 void MACvOneShotTimer1MicroSec(struct vnt_private *priv,
704 unsigned int uDelayTime)
706 void __iomem *io_base = priv->port_offset;
708 iowrite8(0, io_base + MAC_REG_TMCTL1);
709 iowrite32(uDelayTime, io_base + MAC_REG_TMDATA1);
710 iowrite8((TMCTL_TMD | TMCTL_TE), io_base + MAC_REG_TMCTL1);
713 void MACvSetMISCFifo(struct vnt_private *priv, unsigned short offset,
716 void __iomem *io_base = priv->port_offset;
720 iowrite16(offset, io_base + MAC_REG_MISCFFNDEX);
721 iowrite32(data, io_base + MAC_REG_MISCFFDATA);
722 iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL);
725 bool MACbPSWakeup(struct vnt_private *priv)
727 void __iomem *io_base = priv->port_offset;
730 if (MACbIsRegBitsOff(priv, MAC_REG_PSCTL, PSCTL_PS))
734 MACvRegBitsOff(io_base, MAC_REG_PSCTL, PSCTL_PSEN);
736 /* Check if SyncFlushOK */
737 for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
738 if (ioread8(io_base + MAC_REG_PSCTL) & PSCTL_WAKEDONE)
741 if (ww == W_MAX_TIMEOUT) {
742 pr_debug(" DBG_PORT80(0x33)\n");
750 * Set the Key by MISCFIFO
754 * io_base - Base Address for MAC
763 void MACvSetKeyEntry(struct vnt_private *priv, unsigned short wKeyCtl,
764 unsigned int uEntryIdx, unsigned int uKeyIdx,
765 unsigned char *pbyAddr, u32 *pdwKey,
766 unsigned char local_id)
768 void __iomem *io_base = priv->port_offset;
769 unsigned short offset;
776 offset = MISCFIFO_KEYETRY0;
777 offset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE);
782 data |= MAKEWORD(*(pbyAddr + 4), *(pbyAddr + 5));
783 pr_debug("1. offset: %d, Data: %X, KeyCtl:%X\n",
784 offset, data, wKeyCtl);
786 iowrite16(offset, io_base + MAC_REG_MISCFFNDEX);
787 iowrite32(data, io_base + MAC_REG_MISCFFDATA);
788 iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL);
792 data |= *(pbyAddr + 3);
794 data |= *(pbyAddr + 2);
796 data |= *(pbyAddr + 1);
799 pr_debug("2. offset: %d, Data: %X\n", offset, data);
801 iowrite16(offset, io_base + MAC_REG_MISCFFNDEX);
802 iowrite32(data, io_base + MAC_REG_MISCFFDATA);
803 iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL);
806 offset += (uKeyIdx * 4);
807 for (ii = 0; ii < 4; ii++) {
808 /* always push 128 bits */
809 pr_debug("3.(%d) offset: %d, Data: %X\n",
810 ii, offset + ii, *pdwKey);
811 iowrite16(offset + ii, io_base + MAC_REG_MISCFFNDEX);
812 iowrite32(*pdwKey++, io_base + MAC_REG_MISCFFDATA);
813 iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL);
819 * Disable the Key Entry by MISCFIFO
823 * io_base - Base Address for MAC
831 void MACvDisableKeyEntry(struct vnt_private *priv, unsigned int uEntryIdx)
833 void __iomem *io_base = priv->port_offset;
834 unsigned short offset;
836 offset = MISCFIFO_KEYETRY0;
837 offset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE);
839 iowrite16(offset, io_base + MAC_REG_MISCFFNDEX);
840 iowrite32(0, io_base + MAC_REG_MISCFFDATA);
841 iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL);