blob: d8b79cb72b58d3153c095c5e93896a0ba99f539a [file] [log] [blame]
Franky Line3b919d2013-04-11 13:28:49 +02001/*
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
Arend van Spriel4439cbc2014-05-12 10:47:34 +020024static 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
39static 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
Franky Line3b919d2013-04-11 13:28:49 +020052static void brcmu_d11n_encchspec(struct brcmu_chan *ch)
53{
Arend van Spriel4439cbc2014-05-12 10:47:34 +020054 if (ch->bw == BRCMU_CHAN_BW_20)
55 ch->sb = BRCMU_CHAN_SB_NONE;
Franky Line3b919d2013-04-11 13:28:49 +020056
Arend van Spriel68339652014-05-27 12:56:25 +020057 ch->chspec = 0;
Arend van Spriel4439cbc2014-05-12 10:47:34 +020058 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));
Franky Line3b919d2013-04-11 13:28:49 +020064
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
Arend van Spriel4439cbc2014-05-12 10:47:34 +020071static 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
Franky Line3b919d2013-04-11 13:28:49 +020086static void brcmu_d11ac_encchspec(struct brcmu_chan *ch)
87{
Arend van Spriel4439cbc2014-05-12 10:47:34 +020088 if (ch->bw == BRCMU_CHAN_BW_20 || ch->sb == BRCMU_CHAN_SB_NONE)
89 ch->sb = BRCMU_CHAN_SB_L;
Franky Line3b919d2013-04-11 13:28:49 +020090
Arend van Spriel4439cbc2014-05-12 10:47:34 +020091 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));
Franky Line3b919d2013-04-11 13:28:49 +020097
Arend van Spriel4439cbc2014-05-12 10:47:34 +020098 ch->chspec &= ~BRCMU_CHSPEC_D11AC_BND_MASK;
Franky Line3b919d2013-04-11 13:28:49 +020099 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
105static void brcmu_d11n_decchspec(struct brcmu_chan *ch)
106{
107 u16 val;
108
109 ch->chnum = (u8)(ch->chspec & BRCMU_CHSPEC_CH_MASK);
Rafał Miłecki4712d882016-05-20 13:38:57 +0200110 ch->control_ch_num = ch->chnum;
Franky Line3b919d2013-04-11 13:28:49 +0200111
112 switch (ch->chspec & BRCMU_CHSPEC_D11N_BW_MASK) {
113 case BRCMU_CHSPEC_D11N_BW_20:
114 ch->bw = BRCMU_CHAN_BW_20;
Arend van Spriel4439cbc2014-05-12 10:47:34 +0200115 ch->sb = BRCMU_CHAN_SB_NONE;
Franky Line3b919d2013-04-11 13:28:49 +0200116 break;
117 case BRCMU_CHSPEC_D11N_BW_40:
118 ch->bw = BRCMU_CHAN_BW_40;
119 val = ch->chspec & BRCMU_CHSPEC_D11N_SB_MASK;
120 if (val == BRCMU_CHSPEC_D11N_SB_L) {
121 ch->sb = BRCMU_CHAN_SB_L;
Rafał Miłecki4712d882016-05-20 13:38:57 +0200122 ch->control_ch_num -= CH_10MHZ_APART;
Franky Line3b919d2013-04-11 13:28:49 +0200123 } else {
124 ch->sb = BRCMU_CHAN_SB_U;
Rafał Miłecki4712d882016-05-20 13:38:57 +0200125 ch->control_ch_num += CH_10MHZ_APART;
Franky Line3b919d2013-04-11 13:28:49 +0200126 }
127 break;
128 default:
129 WARN_ON_ONCE(1);
130 break;
131 }
132
133 switch (ch->chspec & BRCMU_CHSPEC_D11N_BND_MASK) {
134 case BRCMU_CHSPEC_D11N_BND_5G:
135 ch->band = BRCMU_CHAN_BAND_5G;
136 break;
137 case BRCMU_CHSPEC_D11N_BND_2G:
138 ch->band = BRCMU_CHAN_BAND_2G;
139 break;
140 default:
141 WARN_ON_ONCE(1);
142 break;
143 }
144}
145
146static void brcmu_d11ac_decchspec(struct brcmu_chan *ch)
147{
148 u16 val;
149
150 ch->chnum = (u8)(ch->chspec & BRCMU_CHSPEC_CH_MASK);
Rafał Miłecki4712d882016-05-20 13:38:57 +0200151 ch->control_ch_num = ch->chnum;
Franky Line3b919d2013-04-11 13:28:49 +0200152
153 switch (ch->chspec & BRCMU_CHSPEC_D11AC_BW_MASK) {
154 case BRCMU_CHSPEC_D11AC_BW_20:
155 ch->bw = BRCMU_CHAN_BW_20;
Arend van Spriel4439cbc2014-05-12 10:47:34 +0200156 ch->sb = BRCMU_CHAN_SB_NONE;
Franky Line3b919d2013-04-11 13:28:49 +0200157 break;
158 case BRCMU_CHSPEC_D11AC_BW_40:
159 ch->bw = BRCMU_CHAN_BW_40;
160 val = ch->chspec & BRCMU_CHSPEC_D11AC_SB_MASK;
161 if (val == BRCMU_CHSPEC_D11AC_SB_L) {
162 ch->sb = BRCMU_CHAN_SB_L;
Rafał Miłecki4712d882016-05-20 13:38:57 +0200163 ch->control_ch_num -= CH_10MHZ_APART;
Franky Line3b919d2013-04-11 13:28:49 +0200164 } else if (val == BRCMU_CHSPEC_D11AC_SB_U) {
165 ch->sb = BRCMU_CHAN_SB_U;
Rafał Miłecki4712d882016-05-20 13:38:57 +0200166 ch->control_ch_num += CH_10MHZ_APART;
Franky Line3b919d2013-04-11 13:28:49 +0200167 } else {
168 WARN_ON_ONCE(1);
169 }
170 break;
171 case BRCMU_CHSPEC_D11AC_BW_80:
172 ch->bw = BRCMU_CHAN_BW_80;
Arend van Spriel4439cbc2014-05-12 10:47:34 +0200173 ch->sb = brcmu_maskget16(ch->chspec, BRCMU_CHSPEC_D11AC_SB_MASK,
174 BRCMU_CHSPEC_D11AC_SB_SHIFT);
175 switch (ch->sb) {
176 case BRCMU_CHAN_SB_LL:
Rafał Miłecki4712d882016-05-20 13:38:57 +0200177 ch->control_ch_num -= CH_30MHZ_APART;
Arend van Spriel4439cbc2014-05-12 10:47:34 +0200178 break;
179 case BRCMU_CHAN_SB_LU:
Rafał Miłecki4712d882016-05-20 13:38:57 +0200180 ch->control_ch_num -= CH_10MHZ_APART;
Arend van Spriel4439cbc2014-05-12 10:47:34 +0200181 break;
182 case BRCMU_CHAN_SB_UL:
Rafał Miłecki4712d882016-05-20 13:38:57 +0200183 ch->control_ch_num += CH_10MHZ_APART;
Arend van Spriel4439cbc2014-05-12 10:47:34 +0200184 break;
185 case BRCMU_CHAN_SB_UU:
Rafał Miłecki4712d882016-05-20 13:38:57 +0200186 ch->control_ch_num += CH_30MHZ_APART;
Arend van Spriel4439cbc2014-05-12 10:47:34 +0200187 break;
188 default:
189 WARN_ON_ONCE(1);
190 break;
191 }
Franky Line3b919d2013-04-11 13:28:49 +0200192 break;
193 case BRCMU_CHSPEC_D11AC_BW_8080:
194 case BRCMU_CHSPEC_D11AC_BW_160:
195 default:
196 WARN_ON_ONCE(1);
197 break;
198 }
199
200 switch (ch->chspec & BRCMU_CHSPEC_D11AC_BND_MASK) {
201 case BRCMU_CHSPEC_D11AC_BND_5G:
202 ch->band = BRCMU_CHAN_BAND_5G;
203 break;
204 case BRCMU_CHSPEC_D11AC_BND_2G:
205 ch->band = BRCMU_CHAN_BAND_2G;
206 break;
207 default:
208 WARN_ON_ONCE(1);
209 break;
210 }
211}
212
213void brcmu_d11_attach(struct brcmu_d11inf *d11inf)
214{
215 if (d11inf->io_type == BRCMU_D11N_IOTYPE) {
216 d11inf->encchspec = brcmu_d11n_encchspec;
217 d11inf->decchspec = brcmu_d11n_decchspec;
218 } else {
219 d11inf->encchspec = brcmu_d11ac_encchspec;
220 d11inf->decchspec = brcmu_d11ac_decchspec;
221 }
222}
223EXPORT_SYMBOL(brcmu_d11_attach);