Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / net / wireless / brcm80211 / brcmutil / d11.c
1 /*
2  * Copyright (c) 2013 Broadcom Corporation
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 /*********************channel spec common functions*********************/
17
18 #include <linux/module.h>
19
20 #include <brcmu_utils.h>
21 #include <brcmu_wifi.h>
22 #include <brcmu_d11.h>
23
24 static u16 d11n_sb(enum brcmu_chan_sb sb)
25 {
26         switch (sb) {
27         case BRCMU_CHAN_SB_NONE:
28                 return BRCMU_CHSPEC_D11N_SB_N;
29         case BRCMU_CHAN_SB_L:
30                 return BRCMU_CHSPEC_D11N_SB_L;
31         case BRCMU_CHAN_SB_U:
32                 return BRCMU_CHSPEC_D11N_SB_U;
33         default:
34                 WARN_ON(1);
35         }
36         return 0;
37 }
38
39 static u16 d11n_bw(enum brcmu_chan_bw bw)
40 {
41         switch (bw) {
42         case BRCMU_CHAN_BW_20:
43                 return BRCMU_CHSPEC_D11N_BW_20;
44         case BRCMU_CHAN_BW_40:
45                 return BRCMU_CHSPEC_D11N_BW_40;
46         default:
47                 WARN_ON(1);
48         }
49         return 0;
50 }
51
52 static void brcmu_d11n_encchspec(struct brcmu_chan *ch)
53 {
54         if (ch->bw == BRCMU_CHAN_BW_20)
55                 ch->sb = BRCMU_CHAN_SB_NONE;
56
57         ch->chspec = 0;
58         brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_CH_MASK,
59                         BRCMU_CHSPEC_CH_SHIFT, ch->chnum);
60         brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11N_SB_MASK,
61                         0, d11n_sb(ch->sb));
62         brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11N_BW_MASK,
63                         0, d11n_bw(ch->bw));
64
65         if (ch->chnum <= CH_MAX_2G_CHANNEL)
66                 ch->chspec |= BRCMU_CHSPEC_D11N_BND_2G;
67         else
68                 ch->chspec |= BRCMU_CHSPEC_D11N_BND_5G;
69 }
70
71 static u16 d11ac_bw(enum brcmu_chan_bw bw)
72 {
73         switch (bw) {
74         case BRCMU_CHAN_BW_20:
75                 return BRCMU_CHSPEC_D11AC_BW_20;
76         case BRCMU_CHAN_BW_40:
77                 return BRCMU_CHSPEC_D11AC_BW_40;
78         case BRCMU_CHAN_BW_80:
79                 return BRCMU_CHSPEC_D11AC_BW_80;
80         default:
81                 WARN_ON(1);
82         }
83         return 0;
84 }
85
86 static void brcmu_d11ac_encchspec(struct brcmu_chan *ch)
87 {
88         if (ch->bw == BRCMU_CHAN_BW_20 || ch->sb == BRCMU_CHAN_SB_NONE)
89                 ch->sb = BRCMU_CHAN_SB_L;
90
91         brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_CH_MASK,
92                         BRCMU_CHSPEC_CH_SHIFT, ch->chnum);
93         brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11AC_SB_MASK,
94                         BRCMU_CHSPEC_D11AC_SB_SHIFT, ch->sb);
95         brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11AC_BW_MASK,
96                         0, d11ac_bw(ch->bw));
97
98         ch->chspec &= ~BRCMU_CHSPEC_D11AC_BND_MASK;
99         if (ch->chnum <= CH_MAX_2G_CHANNEL)
100                 ch->chspec |= BRCMU_CHSPEC_D11AC_BND_2G;
101         else
102                 ch->chspec |= BRCMU_CHSPEC_D11AC_BND_5G;
103 }
104
105 static void brcmu_d11n_decchspec(struct brcmu_chan *ch)
106 {
107         u16 val;
108
109         ch->chnum = (u8)(ch->chspec & BRCMU_CHSPEC_CH_MASK);
110
111         switch (ch->chspec & BRCMU_CHSPEC_D11N_BW_MASK) {
112         case BRCMU_CHSPEC_D11N_BW_20:
113                 ch->bw = BRCMU_CHAN_BW_20;
114                 ch->sb = BRCMU_CHAN_SB_NONE;
115                 break;
116         case BRCMU_CHSPEC_D11N_BW_40:
117                 ch->bw = BRCMU_CHAN_BW_40;
118                 val = ch->chspec & BRCMU_CHSPEC_D11N_SB_MASK;
119                 if (val == BRCMU_CHSPEC_D11N_SB_L) {
120                         ch->sb = BRCMU_CHAN_SB_L;
121                         ch->chnum -= CH_10MHZ_APART;
122                 } else {
123                         ch->sb = BRCMU_CHAN_SB_U;
124                         ch->chnum += CH_10MHZ_APART;
125                 }
126                 break;
127         default:
128                 WARN_ON_ONCE(1);
129                 break;
130         }
131
132         switch (ch->chspec & BRCMU_CHSPEC_D11N_BND_MASK) {
133         case BRCMU_CHSPEC_D11N_BND_5G:
134                 ch->band = BRCMU_CHAN_BAND_5G;
135                 break;
136         case BRCMU_CHSPEC_D11N_BND_2G:
137                 ch->band = BRCMU_CHAN_BAND_2G;
138                 break;
139         default:
140                 WARN_ON_ONCE(1);
141                 break;
142         }
143 }
144
145 static void brcmu_d11ac_decchspec(struct brcmu_chan *ch)
146 {
147         u16 val;
148
149         ch->chnum = (u8)(ch->chspec & BRCMU_CHSPEC_CH_MASK);
150
151         switch (ch->chspec & BRCMU_CHSPEC_D11AC_BW_MASK) {
152         case BRCMU_CHSPEC_D11AC_BW_20:
153                 ch->bw = BRCMU_CHAN_BW_20;
154                 ch->sb = BRCMU_CHAN_SB_NONE;
155                 break;
156         case BRCMU_CHSPEC_D11AC_BW_40:
157                 ch->bw = BRCMU_CHAN_BW_40;
158                 val = ch->chspec & BRCMU_CHSPEC_D11AC_SB_MASK;
159                 if (val == BRCMU_CHSPEC_D11AC_SB_L) {
160                         ch->sb = BRCMU_CHAN_SB_L;
161                         ch->chnum -= CH_10MHZ_APART;
162                 } else if (val == BRCMU_CHSPEC_D11AC_SB_U) {
163                         ch->sb = BRCMU_CHAN_SB_U;
164                         ch->chnum += CH_10MHZ_APART;
165                 } else {
166                         WARN_ON_ONCE(1);
167                 }
168                 break;
169         case BRCMU_CHSPEC_D11AC_BW_80:
170                 ch->bw = BRCMU_CHAN_BW_80;
171                 ch->sb = brcmu_maskget16(ch->chspec, BRCMU_CHSPEC_D11AC_SB_MASK,
172                                          BRCMU_CHSPEC_D11AC_SB_SHIFT);
173                 switch (ch->sb) {
174                 case BRCMU_CHAN_SB_LL:
175                         ch->chnum -= CH_30MHZ_APART;
176                         break;
177                 case BRCMU_CHAN_SB_LU:
178                         ch->chnum -= CH_10MHZ_APART;
179                         break;
180                 case BRCMU_CHAN_SB_UL:
181                         ch->chnum += CH_10MHZ_APART;
182                         break;
183                 case BRCMU_CHAN_SB_UU:
184                         ch->chnum += CH_30MHZ_APART;
185                         break;
186                 default:
187                         WARN_ON_ONCE(1);
188                         break;
189                 }
190                 break;
191         case BRCMU_CHSPEC_D11AC_BW_8080:
192         case BRCMU_CHSPEC_D11AC_BW_160:
193         default:
194                 WARN_ON_ONCE(1);
195                 break;
196         }
197
198         switch (ch->chspec & BRCMU_CHSPEC_D11AC_BND_MASK) {
199         case BRCMU_CHSPEC_D11AC_BND_5G:
200                 ch->band = BRCMU_CHAN_BAND_5G;
201                 break;
202         case BRCMU_CHSPEC_D11AC_BND_2G:
203                 ch->band = BRCMU_CHAN_BAND_2G;
204                 break;
205         default:
206                 WARN_ON_ONCE(1);
207                 break;
208         }
209 }
210
211 void brcmu_d11_attach(struct brcmu_d11inf *d11inf)
212 {
213         if (d11inf->io_type == BRCMU_D11N_IOTYPE) {
214                 d11inf->encchspec = brcmu_d11n_encchspec;
215                 d11inf->decchspec = brcmu_d11n_decchspec;
216         } else {
217                 d11inf->encchspec = brcmu_d11ac_encchspec;
218                 d11inf->decchspec = brcmu_d11ac_decchspec;
219         }
220 }
221 EXPORT_SYMBOL(brcmu_d11_attach);