]> Git Repo - linux.git/blob - drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c
Linux 6.14-rc3
[linux.git] / drivers / net / wireless / broadcom / brcm80211 / brcmutil / d11.c
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);
This page took 0.045859 seconds and 4 git commands to generate.