1 // SPDX-License-Identifier: ISC
3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
4 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
7 #include <linux/kernel.h>
10 #include "mt76x02_phy.h"
12 void mt76x02_phy_set_rxpath(struct mt76x02_dev
*dev
)
16 val
= mt76_rr(dev
, MT_BBP(AGC
, 0));
19 switch (dev
->mt76
.chainmask
& 0xf) {
28 mt76_wr(dev
, MT_BBP(AGC
, 0), val
);
30 val
= mt76_rr(dev
, MT_BBP(AGC
, 0));
32 EXPORT_SYMBOL_GPL(mt76x02_phy_set_rxpath
);
34 void mt76x02_phy_set_txdac(struct mt76x02_dev
*dev
)
38 txpath
= (dev
->mt76
.chainmask
>> 8) & 0xf;
41 mt76_set(dev
, MT_BBP(TXBE
, 5), 0x3);
44 mt76_clear(dev
, MT_BBP(TXBE
, 5), 0x3);
48 EXPORT_SYMBOL_GPL(mt76x02_phy_set_txdac
);
51 mt76x02_tx_power_mask(u8 v1
, u8 v2
, u8 v3
, u8 v4
)
55 val
|= (v1
& (BIT(6) - 1)) << 0;
56 val
|= (v2
& (BIT(6) - 1)) << 8;
57 val
|= (v3
& (BIT(6) - 1)) << 16;
58 val
|= (v4
& (BIT(6) - 1)) << 24;
62 int mt76x02_get_max_rate_power(struct mt76_rate_power
*r
)
67 for (i
= 0; i
< sizeof(r
->all
); i
++)
68 ret
= max(ret
, r
->all
[i
]);
72 EXPORT_SYMBOL_GPL(mt76x02_get_max_rate_power
);
74 void mt76x02_limit_rate_power(struct mt76_rate_power
*r
, int limit
)
78 for (i
= 0; i
< sizeof(r
->all
); i
++)
79 if (r
->all
[i
] > limit
)
82 EXPORT_SYMBOL_GPL(mt76x02_limit_rate_power
);
84 void mt76x02_add_rate_power_offset(struct mt76_rate_power
*r
, int offset
)
88 for (i
= 0; i
< sizeof(r
->all
); i
++)
91 EXPORT_SYMBOL_GPL(mt76x02_add_rate_power_offset
);
93 void mt76x02_phy_set_txpower(struct mt76x02_dev
*dev
, int txp_0
, int txp_1
)
95 struct mt76_rate_power
*t
= &dev
->mt76
.rate_power
;
97 mt76_rmw_field(dev
, MT_TX_ALC_CFG_0
, MT_TX_ALC_CFG_0_CH_INIT_0
, txp_0
);
98 mt76_rmw_field(dev
, MT_TX_ALC_CFG_0
, MT_TX_ALC_CFG_0_CH_INIT_1
, txp_1
);
100 mt76_wr(dev
, MT_TX_PWR_CFG_0
,
101 mt76x02_tx_power_mask(t
->cck
[0], t
->cck
[2], t
->ofdm
[0],
103 mt76_wr(dev
, MT_TX_PWR_CFG_1
,
104 mt76x02_tx_power_mask(t
->ofdm
[4], t
->ofdm
[6], t
->ht
[0],
106 mt76_wr(dev
, MT_TX_PWR_CFG_2
,
107 mt76x02_tx_power_mask(t
->ht
[4], t
->ht
[6], t
->ht
[8],
109 mt76_wr(dev
, MT_TX_PWR_CFG_3
,
110 mt76x02_tx_power_mask(t
->ht
[12], t
->ht
[14], t
->stbc
[0],
112 mt76_wr(dev
, MT_TX_PWR_CFG_4
,
113 mt76x02_tx_power_mask(t
->stbc
[4], t
->stbc
[6], 0, 0));
114 mt76_wr(dev
, MT_TX_PWR_CFG_7
,
115 mt76x02_tx_power_mask(t
->ofdm
[7], t
->vht
[8], t
->ht
[7],
117 mt76_wr(dev
, MT_TX_PWR_CFG_8
,
118 mt76x02_tx_power_mask(t
->ht
[14], 0, t
->vht
[8], t
->vht
[9]));
119 mt76_wr(dev
, MT_TX_PWR_CFG_9
,
120 mt76x02_tx_power_mask(t
->ht
[7], 0, t
->stbc
[8], t
->stbc
[9]));
122 EXPORT_SYMBOL_GPL(mt76x02_phy_set_txpower
);
124 void mt76x02_phy_set_bw(struct mt76x02_dev
*dev
, int width
, u8 ctrl
)
126 int core_val
, agc_val
;
129 case NL80211_CHAN_WIDTH_80
:
133 case NL80211_CHAN_WIDTH_40
:
143 mt76_rmw_field(dev
, MT_BBP(CORE
, 1), MT_BBP_CORE_R1_BW
, core_val
);
144 mt76_rmw_field(dev
, MT_BBP(AGC
, 0), MT_BBP_AGC_R0_BW
, agc_val
);
145 mt76_rmw_field(dev
, MT_BBP(AGC
, 0), MT_BBP_AGC_R0_CTRL_CHAN
, ctrl
);
146 mt76_rmw_field(dev
, MT_BBP(TXBE
, 0), MT_BBP_TXBE_R0_CTRL_CHAN
, ctrl
);
148 EXPORT_SYMBOL_GPL(mt76x02_phy_set_bw
);
150 void mt76x02_phy_set_band(struct mt76x02_dev
*dev
, int band
,
154 case NL80211_BAND_2GHZ
:
155 mt76_set(dev
, MT_TX_BAND_CFG
, MT_TX_BAND_CFG_2G
);
156 mt76_clear(dev
, MT_TX_BAND_CFG
, MT_TX_BAND_CFG_5G
);
158 case NL80211_BAND_5GHZ
:
159 mt76_clear(dev
, MT_TX_BAND_CFG
, MT_TX_BAND_CFG_2G
);
160 mt76_set(dev
, MT_TX_BAND_CFG
, MT_TX_BAND_CFG_5G
);
164 mt76_rmw_field(dev
, MT_TX_BAND_CFG
, MT_TX_BAND_CFG_UPPER_40M
,
167 EXPORT_SYMBOL_GPL(mt76x02_phy_set_band
);
169 bool mt76x02_phy_adjust_vga_gain(struct mt76x02_dev
*dev
)
171 u8 limit
= dev
->cal
.low_gain
> 0 ? 16 : 4;
175 false_cca
= FIELD_GET(MT_RX_STAT_1_CCA_ERRORS
,
176 mt76_rr(dev
, MT_RX_STAT_1
));
177 dev
->cal
.false_cca
= false_cca
;
178 if (false_cca
> 800 && dev
->cal
.agc_gain_adjust
< limit
) {
179 dev
->cal
.agc_gain_adjust
+= 2;
181 } else if ((false_cca
< 10 && dev
->cal
.agc_gain_adjust
> 0) ||
182 (dev
->cal
.agc_gain_adjust
>= limit
&& false_cca
< 500)) {
183 dev
->cal
.agc_gain_adjust
-= 2;
187 dev
->cal
.agc_lowest_gain
= dev
->cal
.agc_gain_adjust
>= limit
;
191 EXPORT_SYMBOL_GPL(mt76x02_phy_adjust_vga_gain
);
193 void mt76x02_init_agc_gain(struct mt76x02_dev
*dev
)
195 dev
->cal
.agc_gain_init
[0] = mt76_get_field(dev
, MT_BBP(AGC
, 8),
197 dev
->cal
.agc_gain_init
[1] = mt76_get_field(dev
, MT_BBP(AGC
, 9),
199 memcpy(dev
->cal
.agc_gain_cur
, dev
->cal
.agc_gain_init
,
200 sizeof(dev
->cal
.agc_gain_cur
));
201 dev
->cal
.low_gain
= -1;
202 dev
->cal
.gain_init_done
= true;
204 EXPORT_SYMBOL_GPL(mt76x02_init_agc_gain
);