Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/broadcom/brcm80211/brcmutil/d11.c
178665 views
1
// SPDX-License-Identifier: ISC
2
/*
3
* Copyright (c) 2013 Broadcom Corporation
4
*/
5
/*********************channel spec common functions*********************/
6
7
#include <linux/module.h>
8
9
#include <brcmu_utils.h>
10
#include <brcmu_wifi.h>
11
#include <brcmu_d11.h>
12
13
static u16 d11n_sb(enum brcmu_chan_sb sb)
14
{
15
switch (sb) {
16
case BRCMU_CHAN_SB_NONE:
17
return BRCMU_CHSPEC_D11N_SB_N;
18
case BRCMU_CHAN_SB_L:
19
return BRCMU_CHSPEC_D11N_SB_L;
20
case BRCMU_CHAN_SB_U:
21
return BRCMU_CHSPEC_D11N_SB_U;
22
default:
23
WARN_ON(1);
24
}
25
return 0;
26
}
27
28
static u16 d11n_bw(enum brcmu_chan_bw bw)
29
{
30
switch (bw) {
31
case BRCMU_CHAN_BW_20:
32
return BRCMU_CHSPEC_D11N_BW_20;
33
case BRCMU_CHAN_BW_40:
34
return BRCMU_CHSPEC_D11N_BW_40;
35
default:
36
WARN_ON(1);
37
}
38
return 0;
39
}
40
41
static void brcmu_d11n_encchspec(struct brcmu_chan *ch)
42
{
43
if (ch->bw == BRCMU_CHAN_BW_20)
44
ch->sb = BRCMU_CHAN_SB_NONE;
45
46
ch->chspec = 0;
47
brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_CH_MASK,
48
BRCMU_CHSPEC_CH_SHIFT, ch->chnum);
49
brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11N_SB_MASK,
50
0, d11n_sb(ch->sb));
51
brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11N_BW_MASK,
52
0, d11n_bw(ch->bw));
53
54
if (ch->chnum <= CH_MAX_2G_CHANNEL)
55
ch->chspec |= BRCMU_CHSPEC_D11N_BND_2G;
56
else
57
ch->chspec |= BRCMU_CHSPEC_D11N_BND_5G;
58
}
59
60
static u16 d11ac_bw(enum brcmu_chan_bw bw)
61
{
62
switch (bw) {
63
case BRCMU_CHAN_BW_20:
64
return BRCMU_CHSPEC_D11AC_BW_20;
65
case BRCMU_CHAN_BW_40:
66
return BRCMU_CHSPEC_D11AC_BW_40;
67
case BRCMU_CHAN_BW_80:
68
return BRCMU_CHSPEC_D11AC_BW_80;
69
case BRCMU_CHAN_BW_160:
70
return BRCMU_CHSPEC_D11AC_BW_160;
71
default:
72
WARN_ON(1);
73
}
74
return 0;
75
}
76
77
static void brcmu_d11ac_encchspec(struct brcmu_chan *ch)
78
{
79
if (ch->bw == BRCMU_CHAN_BW_20 || ch->sb == BRCMU_CHAN_SB_NONE)
80
ch->sb = BRCMU_CHAN_SB_L;
81
82
brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_CH_MASK,
83
BRCMU_CHSPEC_CH_SHIFT, ch->chnum);
84
brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11AC_SB_MASK,
85
BRCMU_CHSPEC_D11AC_SB_SHIFT, ch->sb);
86
brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11AC_BW_MASK,
87
0, d11ac_bw(ch->bw));
88
89
ch->chspec &= ~BRCMU_CHSPEC_D11AC_BND_MASK;
90
if (ch->chnum <= CH_MAX_2G_CHANNEL)
91
ch->chspec |= BRCMU_CHSPEC_D11AC_BND_2G;
92
else
93
ch->chspec |= BRCMU_CHSPEC_D11AC_BND_5G;
94
}
95
96
static void brcmu_d11n_decchspec(struct brcmu_chan *ch)
97
{
98
u16 val;
99
100
ch->chnum = (u8)(ch->chspec & BRCMU_CHSPEC_CH_MASK);
101
ch->control_ch_num = ch->chnum;
102
103
switch (ch->chspec & BRCMU_CHSPEC_D11N_BW_MASK) {
104
case BRCMU_CHSPEC_D11N_BW_20:
105
ch->bw = BRCMU_CHAN_BW_20;
106
ch->sb = BRCMU_CHAN_SB_NONE;
107
break;
108
case BRCMU_CHSPEC_D11N_BW_40:
109
ch->bw = BRCMU_CHAN_BW_40;
110
val = ch->chspec & BRCMU_CHSPEC_D11N_SB_MASK;
111
if (val == BRCMU_CHSPEC_D11N_SB_L) {
112
ch->sb = BRCMU_CHAN_SB_L;
113
ch->control_ch_num -= CH_10MHZ_APART;
114
} else {
115
ch->sb = BRCMU_CHAN_SB_U;
116
ch->control_ch_num += CH_10MHZ_APART;
117
}
118
break;
119
default:
120
WARN_ONCE(1, "Invalid chanspec 0x%04x\n", ch->chspec);
121
break;
122
}
123
124
switch (ch->chspec & BRCMU_CHSPEC_D11N_BND_MASK) {
125
case BRCMU_CHSPEC_D11N_BND_5G:
126
ch->band = BRCMU_CHAN_BAND_5G;
127
break;
128
case BRCMU_CHSPEC_D11N_BND_2G:
129
ch->band = BRCMU_CHAN_BAND_2G;
130
break;
131
default:
132
WARN_ONCE(1, "Invalid chanspec 0x%04x\n", ch->chspec);
133
break;
134
}
135
}
136
137
static void brcmu_d11ac_decchspec(struct brcmu_chan *ch)
138
{
139
u16 val;
140
141
ch->chnum = (u8)(ch->chspec & BRCMU_CHSPEC_CH_MASK);
142
ch->control_ch_num = ch->chnum;
143
144
switch (ch->chspec & BRCMU_CHSPEC_D11AC_BW_MASK) {
145
case BRCMU_CHSPEC_D11AC_BW_20:
146
ch->bw = BRCMU_CHAN_BW_20;
147
ch->sb = BRCMU_CHAN_SB_NONE;
148
break;
149
case BRCMU_CHSPEC_D11AC_BW_40:
150
ch->bw = BRCMU_CHAN_BW_40;
151
val = ch->chspec & BRCMU_CHSPEC_D11AC_SB_MASK;
152
if (val == BRCMU_CHSPEC_D11AC_SB_L) {
153
ch->sb = BRCMU_CHAN_SB_L;
154
ch->control_ch_num -= CH_10MHZ_APART;
155
} else if (val == BRCMU_CHSPEC_D11AC_SB_U) {
156
ch->sb = BRCMU_CHAN_SB_U;
157
ch->control_ch_num += CH_10MHZ_APART;
158
} else {
159
WARN_ONCE(1, "Invalid chanspec 0x%04x\n", ch->chspec);
160
}
161
break;
162
case BRCMU_CHSPEC_D11AC_BW_80:
163
ch->bw = BRCMU_CHAN_BW_80;
164
ch->sb = brcmu_maskget16(ch->chspec, BRCMU_CHSPEC_D11AC_SB_MASK,
165
BRCMU_CHSPEC_D11AC_SB_SHIFT);
166
switch (ch->sb) {
167
case BRCMU_CHAN_SB_LL:
168
ch->control_ch_num -= CH_30MHZ_APART;
169
break;
170
case BRCMU_CHAN_SB_LU:
171
ch->control_ch_num -= CH_10MHZ_APART;
172
break;
173
case BRCMU_CHAN_SB_UL:
174
ch->control_ch_num += CH_10MHZ_APART;
175
break;
176
case BRCMU_CHAN_SB_UU:
177
ch->control_ch_num += CH_30MHZ_APART;
178
break;
179
default:
180
WARN_ONCE(1, "Invalid chanspec 0x%04x\n", ch->chspec);
181
break;
182
}
183
break;
184
case BRCMU_CHSPEC_D11AC_BW_160:
185
ch->bw = BRCMU_CHAN_BW_160;
186
ch->sb = brcmu_maskget16(ch->chspec, BRCMU_CHSPEC_D11AC_SB_MASK,
187
BRCMU_CHSPEC_D11AC_SB_SHIFT);
188
switch (ch->sb) {
189
case BRCMU_CHAN_SB_LLL:
190
ch->control_ch_num -= CH_70MHZ_APART;
191
break;
192
case BRCMU_CHAN_SB_LLU:
193
ch->control_ch_num -= CH_50MHZ_APART;
194
break;
195
case BRCMU_CHAN_SB_LUL:
196
ch->control_ch_num -= CH_30MHZ_APART;
197
break;
198
case BRCMU_CHAN_SB_LUU:
199
ch->control_ch_num -= CH_10MHZ_APART;
200
break;
201
case BRCMU_CHAN_SB_ULL:
202
ch->control_ch_num += CH_10MHZ_APART;
203
break;
204
case BRCMU_CHAN_SB_ULU:
205
ch->control_ch_num += CH_30MHZ_APART;
206
break;
207
case BRCMU_CHAN_SB_UUL:
208
ch->control_ch_num += CH_50MHZ_APART;
209
break;
210
case BRCMU_CHAN_SB_UUU:
211
ch->control_ch_num += CH_70MHZ_APART;
212
break;
213
default:
214
WARN_ONCE(1, "Invalid chanspec 0x%04x\n", ch->chspec);
215
break;
216
}
217
break;
218
case BRCMU_CHSPEC_D11AC_BW_8080:
219
default:
220
WARN_ONCE(1, "Invalid chanspec 0x%04x\n", ch->chspec);
221
break;
222
}
223
224
switch (ch->chspec & BRCMU_CHSPEC_D11AC_BND_MASK) {
225
case BRCMU_CHSPEC_D11AC_BND_5G:
226
ch->band = BRCMU_CHAN_BAND_5G;
227
break;
228
case BRCMU_CHSPEC_D11AC_BND_2G:
229
ch->band = BRCMU_CHAN_BAND_2G;
230
break;
231
default:
232
WARN_ONCE(1, "Invalid chanspec 0x%04x\n", ch->chspec);
233
break;
234
}
235
}
236
237
void brcmu_d11_attach(struct brcmu_d11inf *d11inf)
238
{
239
if (d11inf->io_type == BRCMU_D11N_IOTYPE) {
240
d11inf->encchspec = brcmu_d11n_encchspec;
241
d11inf->decchspec = brcmu_d11n_decchspec;
242
} else {
243
d11inf->encchspec = brcmu_d11ac_encchspec;
244
d11inf->decchspec = brcmu_d11ac_decchspec;
245
}
246
}
247
EXPORT_SYMBOL(brcmu_d11_attach);
248
249