1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
6 * Purpose: Provide functions to setup NIC operation mode
8 * s_vSafeResetTx - Rest Tx
9 * CARDvSetRSPINF - Set RSPINF
10 * CARDvUpdateBasicTopRate - Update BasicTopRate
11 * CARDbAddBasicRate - Add to BasicRateSet
12 * CARDbIsOFDMinBasicRate - Check if any OFDM rate is in BasicRateSet
13 * CARDqGetTSFOffset - Calculate TSFOffset
14 * vt6655_get_current_tsf - Read Current NIC TSF counter
15 * CARDqGetNextTBTT - Calculate Next Beacon TSF counter
16 * CARDvSetFirstNextTBTT - Set NIC Beacon time
17 * CARDvUpdateNextTBTT - Sync. NIC Beacon time
18 * CARDbRadioPowerOff - Turn Off NIC Radio Power
21 * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec.
22 * 08-26-2003 Kyle Hsu: Modify the definition type of iobase.
23 * 09-01-2003 Bryan YC Fan: Add vUpdateIFS().
34 /*--------------------- Static Definitions -------------------------*/
36 #define C_SIFS_A 16 /* micro sec. */
39 #define C_EIFS 80 /* micro sec. */
41 #define C_SLOT_SHORT 9 /* micro sec. */
42 #define C_SLOT_LONG 20
44 #define C_CWMIN_A 15 /* slot time */
47 #define C_CWMAX 1023 /* slot time */
49 #define WAIT_BEACON_TX_DOWN_TMO 3 /* Times */
51 /*--------------------- Static Variables --------------------------*/
53 static const unsigned short cwRXBCNTSFOff[MAX_RATE] = {
54 17, 17, 17, 17, 34, 23, 17, 11, 8, 5, 4, 3};
56 /*--------------------- Static Functions --------------------------*/
58 static void s_vCalculateOFDMRParameter(unsigned char rate, u8 bb_type,
59 unsigned char *pbyTxRate,
60 unsigned char *pbyRsvTime);
62 /*--------------------- Export Functions --------------------------*/
65 * Description: Calculate TxRate and RsvTime fields for RSPINF in OFDM mode.
70 * byPktType - Tx Packet type
72 * pbyTxRate - pointer to RSPINF TxRate field
73 * pbyRsvTime - pointer to RSPINF RsvTime field
77 static void s_vCalculateOFDMRParameter(unsigned char rate,
79 unsigned char *pbyTxRate,
80 unsigned char *pbyRsvTime)
84 if (bb_type == BB_TYPE_11A) { /* 5GHZ */
94 if (bb_type == BB_TYPE_11A) { /* 5GHZ */
104 if (bb_type == BB_TYPE_11A) { /* 5GHZ */
114 if (bb_type == BB_TYPE_11A) { /* 5GHZ */
124 if (bb_type == BB_TYPE_11A) { /* 5GHZ */
134 if (bb_type == BB_TYPE_11A) { /* 5GHZ */
144 if (bb_type == BB_TYPE_11A) { /* 5GHZ */
155 if (bb_type == BB_TYPE_11A) { /* 5GHZ */
166 /*--------------------- Export Functions --------------------------*/
169 * Description: Update IFS
173 * priv - The adapter to be set
177 * Return Value: None.
179 bool CARDbSetPhyParameter(struct vnt_private *priv, u8 bb_type)
181 unsigned char byCWMaxMin = 0;
182 unsigned char bySlot = 0;
183 unsigned char bySIFS = 0;
184 unsigned char byDIFS = 0;
187 /* Set SIFS, DIFS, EIFS, SlotTime, CwMin */
188 if (bb_type == BB_TYPE_11A) {
189 MACvSetBBType(priv->port_offset, BB_TYPE_11A);
190 bb_write_embedded(priv, 0x88, 0x03);
191 bySlot = C_SLOT_SHORT;
193 byDIFS = C_SIFS_A + 2 * C_SLOT_SHORT;
195 } else if (bb_type == BB_TYPE_11B) {
196 MACvSetBBType(priv->port_offset, BB_TYPE_11B);
197 bb_write_embedded(priv, 0x88, 0x02);
198 bySlot = C_SLOT_LONG;
200 byDIFS = C_SIFS_BG + 2 * C_SLOT_LONG;
202 } else { /* PK_TYPE_11GA & PK_TYPE_11GB */
203 MACvSetBBType(priv->port_offset, BB_TYPE_11G);
204 bb_write_embedded(priv, 0x88, 0x08);
207 if (priv->short_slot_time) {
208 bySlot = C_SLOT_SHORT;
209 byDIFS = C_SIFS_BG + 2 * C_SLOT_SHORT;
211 bySlot = C_SLOT_LONG;
212 byDIFS = C_SIFS_BG + 2 * C_SLOT_LONG;
217 for (i = RATE_54M; i >= RATE_6M; i--) {
218 if (priv->basic_rates & ((u32)(0x1 << i))) {
225 if (priv->byRFType == RF_RFMD2959) {
227 * bcs TX_PE will reserve 3 us hardware's processing
233 * TX_PE will reserve 3 us for MAX2829 A mode only, it is for
234 * better TX throughput; MAC will need 2 us to process, so the
235 * SIFS, DIFS can be shorter by 2 us.
239 if (priv->bySIFS != bySIFS) {
240 priv->bySIFS = bySIFS;
241 iowrite8(priv->bySIFS, priv->port_offset + MAC_REG_SIFS);
243 if (priv->byDIFS != byDIFS) {
244 priv->byDIFS = byDIFS;
245 iowrite8(priv->byDIFS, priv->port_offset + MAC_REG_DIFS);
247 if (priv->byEIFS != C_EIFS) {
248 priv->byEIFS = C_EIFS;
249 iowrite8(priv->byEIFS, priv->port_offset + MAC_REG_EIFS);
251 if (priv->bySlot != bySlot) {
252 priv->bySlot = bySlot;
253 iowrite8(priv->bySlot, priv->port_offset + MAC_REG_SLOT);
255 bb_set_short_slot_time(priv);
257 if (priv->byCWMaxMin != byCWMaxMin) {
258 priv->byCWMaxMin = byCWMaxMin;
259 iowrite8(priv->byCWMaxMin, priv->port_offset + MAC_REG_CWMAXMIN0);
262 priv->byPacketType = CARDbyGetPktType(priv);
264 CARDvSetRSPINF(priv, bb_type);
270 * Description: Sync. TSF counter to BSS
271 * Get TSF offset and write to HW
275 * priv - The adapter to be sync.
276 * byRxRate - data rate of receive beacon
277 * qwBSSTimestamp - Rx BCN's TSF
278 * qwLocalTSF - Local TSF
284 bool CARDbUpdateTSF(struct vnt_private *priv, unsigned char byRxRate,
290 local_tsf = vt6655_get_current_tsf(priv);
292 if (qwBSSTimestamp != local_tsf) {
293 qwTSFOffset = CARDqGetTSFOffset(byRxRate, qwBSSTimestamp,
295 /* adjust TSF, HW's TSF add TSF Offset reg */
296 VNSvOutPortD(priv->port_offset + MAC_REG_TSFOFST,
298 VNSvOutPortD(priv->port_offset + MAC_REG_TSFOFST + 4,
299 (u32)(qwTSFOffset >> 32));
300 MACvRegBitsOn(priv->port_offset, MAC_REG_TFTCTL,
307 * Description: Set NIC TSF counter for first Beacon time
308 * Get NEXTTBTT from adjusted TSF and Beacon Interval
312 * priv - The adapter to be set.
313 * wBeaconInterval - Beacon Interval
317 * Return Value: true if succeed; otherwise false
319 bool CARDbSetBeaconPeriod(struct vnt_private *priv,
320 unsigned short wBeaconInterval)
324 qwNextTBTT = vt6655_get_current_tsf(priv); /* Get Local TSF counter */
326 qwNextTBTT = CARDqGetNextTBTT(qwNextTBTT, wBeaconInterval);
328 /* set HW beacon interval */
329 VNSvOutPortW(priv->port_offset + MAC_REG_BI, wBeaconInterval);
330 priv->wBeaconInterval = wBeaconInterval;
332 VNSvOutPortD(priv->port_offset + MAC_REG_NEXTTBTT, (u32)qwNextTBTT);
333 VNSvOutPortD(priv->port_offset + MAC_REG_NEXTTBTT + 4,
334 (u32)(qwNextTBTT >> 32));
335 MACvRegBitsOn(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN);
341 * Description: Turn off Radio power
345 * priv - The adapter to be turned off
350 void CARDbRadioPowerOff(struct vnt_private *priv)
355 switch (priv->byRFType) {
357 MACvWordRegBitsOff(priv->port_offset, MAC_REG_SOFTPWRCTL,
359 MACvWordRegBitsOn(priv->port_offset, MAC_REG_SOFTPWRCTL,
365 MACvWordRegBitsOff(priv->port_offset, MAC_REG_SOFTPWRCTL,
367 MACvWordRegBitsOff(priv->port_offset, MAC_REG_SOFTPWRCTL,
372 MACvRegBitsOff(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_RXON);
374 bb_set_deep_sleep(priv, priv->local_id);
376 priv->radio_off = true;
377 pr_debug("chester power off\n");
378 MACvRegBitsOn(priv->port_offset, MAC_REG_GPIOCTL0,
379 LED_ACTSET); /* LED issue */
382 void CARDvSafeResetTx(struct vnt_private *priv)
385 struct vnt_tx_desc *pCurrTD;
387 /* initialize TD index */
388 priv->apTailTD[0] = &priv->apTD0Rings[0];
389 priv->apCurrTD[0] = &priv->apTD0Rings[0];
391 priv->apTailTD[1] = &priv->apTD1Rings[0];
392 priv->apCurrTD[1] = &priv->apTD1Rings[0];
394 for (uu = 0; uu < TYPE_MAXTD; uu++)
395 priv->iTDUsed[uu] = 0;
397 for (uu = 0; uu < priv->opts.tx_descs[0]; uu++) {
398 pCurrTD = &priv->apTD0Rings[uu];
399 pCurrTD->td0.owner = OWNED_BY_HOST;
400 /* init all Tx Packet pointer to NULL */
402 for (uu = 0; uu < priv->opts.tx_descs[1]; uu++) {
403 pCurrTD = &priv->apTD1Rings[uu];
404 pCurrTD->td0.owner = OWNED_BY_HOST;
405 /* init all Tx Packet pointer to NULL */
408 /* set MAC TD pointer */
409 MACvSetCurrTXDescAddr(TYPE_TXDMA0, priv, priv->td0_pool_dma);
411 MACvSetCurrTXDescAddr(TYPE_AC0DMA, priv, priv->td1_pool_dma);
413 /* set MAC Beacon TX pointer */
414 MACvSetCurrBCNTxDescAddr(priv->port_offset,
415 (priv->tx_beacon_dma));
424 * priv - Pointer to the adapter
430 void CARDvSafeResetRx(struct vnt_private *priv)
433 struct vnt_rx_desc *pDesc;
435 /* initialize RD index */
436 priv->pCurrRD[0] = &priv->aRD0Ring[0];
437 priv->pCurrRD[1] = &priv->aRD1Ring[0];
439 /* init state, all RD is chip's */
440 for (uu = 0; uu < priv->opts.rx_descs0; uu++) {
441 pDesc = &priv->aRD0Ring[uu];
442 pDesc->rd0.res_count = cpu_to_le16(priv->rx_buf_sz);
443 pDesc->rd0.owner = OWNED_BY_NIC;
444 pDesc->rd1.req_count = cpu_to_le16(priv->rx_buf_sz);
447 /* init state, all RD is chip's */
448 for (uu = 0; uu < priv->opts.rx_descs1; uu++) {
449 pDesc = &priv->aRD1Ring[uu];
450 pDesc->rd0.res_count = cpu_to_le16(priv->rx_buf_sz);
451 pDesc->rd0.owner = OWNED_BY_NIC;
452 pDesc->rd1.req_count = cpu_to_le16(priv->rx_buf_sz);
455 /* set perPkt mode */
456 MACvRx0PerPktMode(priv->port_offset);
457 MACvRx1PerPktMode(priv->port_offset);
458 /* set MAC RD pointer */
459 MACvSetCurrRx0DescAddr(priv, priv->rd0_pool_dma);
461 MACvSetCurrRx1DescAddr(priv, priv->rd1_pool_dma);
465 * Description: Get response Control frame rate in CCK mode
469 * priv - The adapter to be set
470 * wRateIdx - Receiving data rate
474 * Return Value: response Control frame rate
476 static unsigned short CARDwGetCCKControlRate(struct vnt_private *priv,
477 unsigned short wRateIdx)
479 unsigned int ui = (unsigned int)wRateIdx;
481 while (ui > RATE_1M) {
482 if (priv->basic_rates & ((u32)0x1 << ui))
483 return (unsigned short)ui;
487 return (unsigned short)RATE_1M;
491 * Description: Get response Control frame rate in OFDM mode
495 * priv - The adapter to be set
496 * wRateIdx - Receiving data rate
500 * Return Value: response Control frame rate
502 static unsigned short CARDwGetOFDMControlRate(struct vnt_private *priv,
503 unsigned short wRateIdx)
505 unsigned int ui = (unsigned int)wRateIdx;
507 pr_debug("BASIC RATE: %X\n", priv->basic_rates);
509 if (!CARDbIsOFDMinBasicRate((void *)priv)) {
510 pr_debug("%s:(NO OFDM) %d\n", __func__, wRateIdx);
511 if (wRateIdx > RATE_24M)
515 while (ui > RATE_11M) {
516 if (priv->basic_rates & ((u32)0x1 << ui)) {
517 pr_debug("%s : %d\n", __func__, ui);
518 return (unsigned short)ui;
522 pr_debug("%s: 6M\n", __func__);
523 return (unsigned short)RATE_24M;
527 * Description: Set RSPINF
531 * priv - The adapter to be set
535 * Return Value: None.
537 void CARDvSetRSPINF(struct vnt_private *priv, u8 bb_type)
539 union vnt_phy_field_swap phy;
540 unsigned char byTxRate, byRsvTime; /* For OFDM */
543 spin_lock_irqsave(&priv->lock, flags);
546 MACvSelectPage1(priv->port_offset);
549 vnt_get_phy_field(priv, 14,
550 CARDwGetCCKControlRate(priv, RATE_1M),
551 PK_TYPE_11B, &phy.field_read);
553 /* swap over to get correct write order */
554 swap(phy.swap[0], phy.swap[1]);
556 VNSvOutPortD(priv->port_offset + MAC_REG_RSPINF_B_1, phy.field_write);
559 vnt_get_phy_field(priv, 14,
560 CARDwGetCCKControlRate(priv, RATE_2M),
561 PK_TYPE_11B, &phy.field_read);
563 swap(phy.swap[0], phy.swap[1]);
565 VNSvOutPortD(priv->port_offset + MAC_REG_RSPINF_B_2, phy.field_write);
568 vnt_get_phy_field(priv, 14,
569 CARDwGetCCKControlRate(priv, RATE_5M),
570 PK_TYPE_11B, &phy.field_read);
572 swap(phy.swap[0], phy.swap[1]);
574 VNSvOutPortD(priv->port_offset + MAC_REG_RSPINF_B_5, phy.field_write);
577 vnt_get_phy_field(priv, 14,
578 CARDwGetCCKControlRate(priv, RATE_11M),
579 PK_TYPE_11B, &phy.field_read);
581 swap(phy.swap[0], phy.swap[1]);
583 VNSvOutPortD(priv->port_offset + MAC_REG_RSPINF_B_11, phy.field_write);
586 s_vCalculateOFDMRParameter(RATE_6M,
590 VNSvOutPortW(priv->port_offset + MAC_REG_RSPINF_A_6,
591 MAKEWORD(byTxRate, byRsvTime));
593 s_vCalculateOFDMRParameter(RATE_9M,
597 VNSvOutPortW(priv->port_offset + MAC_REG_RSPINF_A_9,
598 MAKEWORD(byTxRate, byRsvTime));
600 s_vCalculateOFDMRParameter(RATE_12M,
604 VNSvOutPortW(priv->port_offset + MAC_REG_RSPINF_A_12,
605 MAKEWORD(byTxRate, byRsvTime));
607 s_vCalculateOFDMRParameter(RATE_18M,
611 VNSvOutPortW(priv->port_offset + MAC_REG_RSPINF_A_18,
612 MAKEWORD(byTxRate, byRsvTime));
614 s_vCalculateOFDMRParameter(RATE_24M,
618 VNSvOutPortW(priv->port_offset + MAC_REG_RSPINF_A_24,
619 MAKEWORD(byTxRate, byRsvTime));
621 s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)priv,
626 VNSvOutPortW(priv->port_offset + MAC_REG_RSPINF_A_36,
627 MAKEWORD(byTxRate, byRsvTime));
629 s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)priv,
634 VNSvOutPortW(priv->port_offset + MAC_REG_RSPINF_A_48,
635 MAKEWORD(byTxRate, byRsvTime));
637 s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)priv,
642 VNSvOutPortW(priv->port_offset + MAC_REG_RSPINF_A_54,
643 MAKEWORD(byTxRate, byRsvTime));
645 s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)priv,
650 VNSvOutPortW(priv->port_offset + MAC_REG_RSPINF_A_72,
651 MAKEWORD(byTxRate, byRsvTime));
653 MACvSelectPage0(priv->port_offset);
655 spin_unlock_irqrestore(&priv->lock, flags);
658 void CARDvUpdateBasicTopRate(struct vnt_private *priv)
660 unsigned char byTopOFDM = RATE_24M, byTopCCK = RATE_1M;
663 /* Determines the highest basic rate. */
664 for (ii = RATE_54M; ii >= RATE_6M; ii--) {
665 if ((priv->basic_rates) & ((u32)(1 << ii))) {
670 priv->byTopOFDMBasicRate = byTopOFDM;
672 for (ii = RATE_11M;; ii--) {
673 if ((priv->basic_rates) & ((u32)(1 << ii))) {
680 priv->byTopCCKBasicRate = byTopCCK;
683 bool CARDbIsOFDMinBasicRate(struct vnt_private *priv)
687 for (ii = RATE_54M; ii >= RATE_6M; ii--) {
688 if ((priv->basic_rates) & ((u32)BIT(ii)))
694 unsigned char CARDbyGetPktType(struct vnt_private *priv)
696 if (priv->byBBType == BB_TYPE_11A || priv->byBBType == BB_TYPE_11B)
697 return (unsigned char)priv->byBBType;
698 else if (CARDbIsOFDMinBasicRate((void *)priv))
705 * Description: Calculate TSF offset of two TSF input
706 * Get TSF Offset from RxBCN's TSF and local TSF
710 * priv - The adapter to be sync.
711 * qwTSF1 - Rx BCN's TSF
716 * Return Value: TSF Offset value
718 u64 CARDqGetTSFOffset(unsigned char byRxRate, u64 qwTSF1, u64 qwTSF2)
720 unsigned short wRxBcnTSFOffst;
722 wRxBcnTSFOffst = cwRXBCNTSFOff[byRxRate % MAX_RATE];
724 qwTSF2 += (u64)wRxBcnTSFOffst;
726 return qwTSF1 - qwTSF2;
730 * Description: Read NIC TSF counter
731 * Get local TSF counter
735 * priv - The adapter to be read
737 * qwCurrTSF - Current TSF counter
739 * Return Value: true if success; otherwise false
741 u64 vt6655_get_current_tsf(struct vnt_private *priv)
743 void __iomem *iobase = priv->port_offset;
748 MACvRegBitsOn(iobase, MAC_REG_TFTCTL, TFTCTL_TSFCNTRRD);
749 for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
750 data = ioread8(iobase + MAC_REG_TFTCTL);
751 if (!(data & TFTCTL_TSFCNTRRD))
754 if (ww == W_MAX_TIMEOUT)
756 low = ioread32(iobase + MAC_REG_TSFCNTR);
757 high = ioread32(iobase + MAC_REG_TSFCNTR + 4);
758 return le64_to_cpu(low + ((u64)high << 32));
762 * Description: Read NIC TSF counter
763 * Get NEXTTBTT from adjusted TSF and Beacon Interval
767 * qwTSF - Current TSF counter
768 * wbeaconInterval - Beacon Interval
770 * qwCurrTSF - Current TSF counter
772 * Return Value: TSF value of next Beacon
774 u64 CARDqGetNextTBTT(u64 qwTSF, unsigned short wBeaconInterval)
778 beacon_int = wBeaconInterval * 1024;
780 do_div(qwTSF, beacon_int);
789 * Description: Set NIC TSF counter for first Beacon time
790 * Get NEXTTBTT from adjusted TSF and Beacon Interval
795 * wBeaconInterval - Beacon Interval
801 void CARDvSetFirstNextTBTT(struct vnt_private *priv,
802 unsigned short wBeaconInterval)
804 void __iomem *iobase = priv->port_offset;
807 qwNextTBTT = vt6655_get_current_tsf(priv); /* Get Local TSF counter */
809 qwNextTBTT = CARDqGetNextTBTT(qwNextTBTT, wBeaconInterval);
811 VNSvOutPortD(iobase + MAC_REG_NEXTTBTT, (u32)qwNextTBTT);
812 VNSvOutPortD(iobase + MAC_REG_NEXTTBTT + 4, (u32)(qwNextTBTT >> 32));
813 MACvRegBitsOn(iobase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN);
817 * Description: Sync NIC TSF counter for Beacon time
818 * Get NEXTTBTT and write to HW
822 * priv - The adapter to be set
823 * qwTSF - Current TSF counter
824 * wBeaconInterval - Beacon Interval
830 void CARDvUpdateNextTBTT(struct vnt_private *priv, u64 qwTSF,
831 unsigned short wBeaconInterval)
833 void __iomem *iobase = priv->port_offset;
835 qwTSF = CARDqGetNextTBTT(qwTSF, wBeaconInterval);
837 VNSvOutPortD(iobase + MAC_REG_NEXTTBTT, (u32)qwTSF);
838 VNSvOutPortD(iobase + MAC_REG_NEXTTBTT + 4, (u32)(qwTSF >> 32));
839 MACvRegBitsOn(iobase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN);
840 pr_debug("Card:Update Next TBTT[%8llx]\n", qwTSF);