1 // SPDX-License-Identifier: ISC
3 * Copyright (c) 2013 Broadcom Corporation
5 /*********************channel spec common functions*********************/
7 #include <linux/module.h>
9 #include <brcmu_utils.h>
10 #include <brcmu_wifi.h>
11 #include <brcmu_d11.h>
13 static u16
d11n_sb(enum brcmu_chan_sb sb
)
16 case BRCMU_CHAN_SB_NONE
:
17 return BRCMU_CHSPEC_D11N_SB_N
;
19 return BRCMU_CHSPEC_D11N_SB_L
;
21 return BRCMU_CHSPEC_D11N_SB_U
;
28 static u16
d11n_bw(enum brcmu_chan_bw 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
;
41 static void brcmu_d11n_encchspec(struct brcmu_chan
*ch
)
43 if (ch
->bw
== BRCMU_CHAN_BW_20
)
44 ch
->sb
= BRCMU_CHAN_SB_NONE
;
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
,
51 brcmu_maskset16(&ch
->chspec
, BRCMU_CHSPEC_D11N_BW_MASK
,
54 if (ch
->chnum
<= CH_MAX_2G_CHANNEL
)
55 ch
->chspec
|= BRCMU_CHSPEC_D11N_BND_2G
;
57 ch
->chspec
|= BRCMU_CHSPEC_D11N_BND_5G
;
60 static u16
d11ac_bw(enum brcmu_chan_bw 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
;
77 static void brcmu_d11ac_encchspec(struct brcmu_chan
*ch
)
79 if (ch
->bw
== BRCMU_CHAN_BW_20
|| ch
->sb
== BRCMU_CHAN_SB_NONE
)
80 ch
->sb
= BRCMU_CHAN_SB_L
;
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
,
89 ch
->chspec
&= ~BRCMU_CHSPEC_D11AC_BND_MASK
;
90 if (ch
->chnum
<= CH_MAX_2G_CHANNEL
)
91 ch
->chspec
|= BRCMU_CHSPEC_D11AC_BND_2G
;
93 ch
->chspec
|= BRCMU_CHSPEC_D11AC_BND_5G
;
96 static void brcmu_d11n_decchspec(struct brcmu_chan
*ch
)
100 ch
->chnum
= (u8
)(ch
->chspec
& BRCMU_CHSPEC_CH_MASK
);
101 ch
->control_ch_num
= ch
->chnum
;
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
;
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
;
115 ch
->sb
= BRCMU_CHAN_SB_U
;
116 ch
->control_ch_num
+= CH_10MHZ_APART
;
120 WARN_ONCE(1, "Invalid chanspec 0x%04x\n", ch
->chspec
);
124 switch (ch
->chspec
& BRCMU_CHSPEC_D11N_BND_MASK
) {
125 case BRCMU_CHSPEC_D11N_BND_5G
:
126 ch
->band
= BRCMU_CHAN_BAND_5G
;
128 case BRCMU_CHSPEC_D11N_BND_2G
:
129 ch
->band
= BRCMU_CHAN_BAND_2G
;
132 WARN_ONCE(1, "Invalid chanspec 0x%04x\n", ch
->chspec
);
137 static void brcmu_d11ac_decchspec(struct brcmu_chan
*ch
)
141 ch
->chnum
= (u8
)(ch
->chspec
& BRCMU_CHSPEC_CH_MASK
);
142 ch
->control_ch_num
= ch
->chnum
;
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
;
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
;
159 WARN_ONCE(1, "Invalid chanspec 0x%04x\n", ch
->chspec
);
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
);
167 case BRCMU_CHAN_SB_LL
:
168 ch
->control_ch_num
-= CH_30MHZ_APART
;
170 case BRCMU_CHAN_SB_LU
:
171 ch
->control_ch_num
-= CH_10MHZ_APART
;
173 case BRCMU_CHAN_SB_UL
:
174 ch
->control_ch_num
+= CH_10MHZ_APART
;
176 case BRCMU_CHAN_SB_UU
:
177 ch
->control_ch_num
+= CH_30MHZ_APART
;
180 WARN_ONCE(1, "Invalid chanspec 0x%04x\n", ch
->chspec
);
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
);
189 case BRCMU_CHAN_SB_LLL
:
190 ch
->control_ch_num
-= CH_70MHZ_APART
;
192 case BRCMU_CHAN_SB_LLU
:
193 ch
->control_ch_num
-= CH_50MHZ_APART
;
195 case BRCMU_CHAN_SB_LUL
:
196 ch
->control_ch_num
-= CH_30MHZ_APART
;
198 case BRCMU_CHAN_SB_LUU
:
199 ch
->control_ch_num
-= CH_10MHZ_APART
;
201 case BRCMU_CHAN_SB_ULL
:
202 ch
->control_ch_num
+= CH_10MHZ_APART
;
204 case BRCMU_CHAN_SB_ULU
:
205 ch
->control_ch_num
+= CH_30MHZ_APART
;
207 case BRCMU_CHAN_SB_UUL
:
208 ch
->control_ch_num
+= CH_50MHZ_APART
;
210 case BRCMU_CHAN_SB_UUU
:
211 ch
->control_ch_num
+= CH_70MHZ_APART
;
214 WARN_ONCE(1, "Invalid chanspec 0x%04x\n", ch
->chspec
);
218 case BRCMU_CHSPEC_D11AC_BW_8080
:
220 WARN_ONCE(1, "Invalid chanspec 0x%04x\n", ch
->chspec
);
224 switch (ch
->chspec
& BRCMU_CHSPEC_D11AC_BND_MASK
) {
225 case BRCMU_CHSPEC_D11AC_BND_5G
:
226 ch
->band
= BRCMU_CHAN_BAND_5G
;
228 case BRCMU_CHSPEC_D11AC_BND_2G
:
229 ch
->band
= BRCMU_CHAN_BAND_2G
;
232 WARN_ONCE(1, "Invalid chanspec 0x%04x\n", ch
->chspec
);
237 void brcmu_d11_attach(struct brcmu_d11inf
*d11inf
)
239 if (d11inf
->io_type
== BRCMU_D11N_IOTYPE
) {
240 d11inf
->encchspec
= brcmu_d11n_encchspec
;
241 d11inf
->decchspec
= brcmu_d11n_decchspec
;
243 d11inf
->encchspec
= brcmu_d11ac_encchspec
;
244 d11inf
->decchspec
= brcmu_d11ac_decchspec
;
247 EXPORT_SYMBOL(brcmu_d11_attach
);