iwlwifi: export symbols only conditionally
[deliverable/linux.git] / drivers / net / wireless / iwlwifi / iwl-nvm-parse.c
CommitLineData
b1e1adfa
JB
1/******************************************************************************
2 *
3 * This file is provided under a dual BSD/GPLv2 license. When using or
4 * redistributing this file, you may do so under either license.
5 *
6 * GPL LICENSE SUMMARY
7 *
8 * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
22 * USA
23 *
24 * The full GNU General Public License is included in this distribution
410dc5aa 25 * in the file called COPYING.
b1e1adfa
JB
26 *
27 * Contact Information:
28 * Intel Linux Wireless <ilw@linux.intel.com>
29 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30 *
31 * BSD LICENSE
32 *
33 * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 *
40 * * Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * * Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in
44 * the documentation and/or other materials provided with the
45 * distribution.
46 * * Neither the name Intel Corporation nor the names of its
47 * contributors may be used to endorse or promote products derived
48 * from this software without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
54 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 *****************************************************************************/
62#include <linux/types.h>
63#include <linux/slab.h>
64#include <linux/export.h>
48e29340 65#include "iwl-drv.h"
b1e1adfa
JB
66#include "iwl-modparams.h"
67#include "iwl-nvm-parse.h"
68
69/* NVM offsets (in words) definitions */
70enum wkp_nvm_offsets {
71 /* NVM HW-Section offset (in words) definitions */
72 HW_ADDR = 0x15,
73
74/* NVM SW-Section offset (in words) definitions */
75 NVM_SW_SECTION = 0x1C0,
76 NVM_VERSION = 0,
77 RADIO_CFG = 1,
78 SKU = 2,
79 N_HW_ADDRS = 3,
80 NVM_CHANNELS = 0x1E0 - NVM_SW_SECTION,
81
82/* NVM calibration section offset (in words) definitions */
83 NVM_CALIB_SECTION = 0x2B8,
84 XTAL_CALIB = 0x316 - NVM_CALIB_SECTION
85};
86
87/* SKU Capabilities (actual values from NVM definition) */
88enum nvm_sku_bits {
89 NVM_SKU_CAP_BAND_24GHZ = BIT(0),
90 NVM_SKU_CAP_BAND_52GHZ = BIT(1),
91 NVM_SKU_CAP_11N_ENABLE = BIT(2),
92};
93
94/* radio config bits (actual values from NVM definition) */
95#define NVM_RF_CFG_DASH_MSK(x) (x & 0x3) /* bits 0-1 */
96#define NVM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */
97#define NVM_RF_CFG_TYPE_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */
98#define NVM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */
99#define NVM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */
100#define NVM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */
101
102/*
103 * These are the channel numbers in the order that they are stored in the NVM
104 */
105static const u8 iwl_nvm_channels[] = {
106 /* 2.4 GHz */
107 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
108 /* 5 GHz */
109 36, 40, 44 , 48, 52, 56, 60, 64,
110 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
111 149, 153, 157, 161, 165
112};
113
114#define IWL_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels)
115#define NUM_2GHZ_CHANNELS 14
116#define FIRST_2GHZ_HT_MINUS 5
117#define LAST_2GHZ_HT_PLUS 9
118#define LAST_5GHZ_HT 161
119
120
121/* rate data (static) */
122static struct ieee80211_rate iwl_cfg80211_rates[] = {
123 { .bitrate = 1 * 10, .hw_value = 0, .hw_value_short = 0, },
124 { .bitrate = 2 * 10, .hw_value = 1, .hw_value_short = 1,
125 .flags = IEEE80211_RATE_SHORT_PREAMBLE, },
126 { .bitrate = 5.5 * 10, .hw_value = 2, .hw_value_short = 2,
127 .flags = IEEE80211_RATE_SHORT_PREAMBLE, },
128 { .bitrate = 11 * 10, .hw_value = 3, .hw_value_short = 3,
129 .flags = IEEE80211_RATE_SHORT_PREAMBLE, },
130 { .bitrate = 6 * 10, .hw_value = 4, .hw_value_short = 4, },
131 { .bitrate = 9 * 10, .hw_value = 5, .hw_value_short = 5, },
132 { .bitrate = 12 * 10, .hw_value = 6, .hw_value_short = 6, },
133 { .bitrate = 18 * 10, .hw_value = 7, .hw_value_short = 7, },
134 { .bitrate = 24 * 10, .hw_value = 8, .hw_value_short = 8, },
135 { .bitrate = 36 * 10, .hw_value = 9, .hw_value_short = 9, },
136 { .bitrate = 48 * 10, .hw_value = 10, .hw_value_short = 10, },
137 { .bitrate = 54 * 10, .hw_value = 11, .hw_value_short = 11, },
138};
139#define RATES_24_OFFS 0
140#define N_RATES_24 ARRAY_SIZE(iwl_cfg80211_rates)
141#define RATES_52_OFFS 4
142#define N_RATES_52 (N_RATES_24 - RATES_52_OFFS)
143
144/**
145 * enum iwl_nvm_channel_flags - channel flags in NVM
146 * @NVM_CHANNEL_VALID: channel is usable for this SKU/geo
147 * @NVM_CHANNEL_IBSS: usable as an IBSS channel
148 * @NVM_CHANNEL_ACTIVE: active scanning allowed
149 * @NVM_CHANNEL_RADAR: radar detection required
150 * @NVM_CHANNEL_DFS: dynamic freq selection candidate
151 * @NVM_CHANNEL_WIDE: 20 MHz channel okay (?)
152 * @NVM_CHANNEL_40MHZ: 40 MHz channel okay (?)
33158fef
EL
153 * @NVM_CHANNEL_80MHZ: 80 MHz channel okay (?)
154 * @NVM_CHANNEL_160MHZ: 160 MHz channel okay (?)
b1e1adfa
JB
155 */
156enum iwl_nvm_channel_flags {
157 NVM_CHANNEL_VALID = BIT(0),
158 NVM_CHANNEL_IBSS = BIT(1),
159 NVM_CHANNEL_ACTIVE = BIT(3),
160 NVM_CHANNEL_RADAR = BIT(4),
161 NVM_CHANNEL_DFS = BIT(7),
162 NVM_CHANNEL_WIDE = BIT(8),
163 NVM_CHANNEL_40MHZ = BIT(9),
33158fef
EL
164 NVM_CHANNEL_80MHZ = BIT(10),
165 NVM_CHANNEL_160MHZ = BIT(11),
b1e1adfa
JB
166};
167
168#define CHECK_AND_PRINT_I(x) \
169 ((ch_flags & NVM_CHANNEL_##x) ? # x " " : "")
170
171static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
172 struct iwl_nvm_data *data,
173 const __le16 * const nvm_ch_flags)
174{
175 int ch_idx;
176 int n_channels = 0;
177 struct ieee80211_channel *channel;
178 u16 ch_flags;
179 bool is_5ghz;
180
181 for (ch_idx = 0; ch_idx < IWL_NUM_CHANNELS; ch_idx++) {
182 ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx);
183 if (!(ch_flags & NVM_CHANNEL_VALID)) {
184 IWL_DEBUG_EEPROM(dev,
185 "Ch. %d Flags %x [%sGHz] - No traffic\n",
186 iwl_nvm_channels[ch_idx],
187 ch_flags,
188 (ch_idx >= NUM_2GHZ_CHANNELS) ?
189 "5.2" : "2.4");
190 continue;
191 }
192
193 channel = &data->channels[n_channels];
194 n_channels++;
195
196 channel->hw_value = iwl_nvm_channels[ch_idx];
197 channel->band = (ch_idx < NUM_2GHZ_CHANNELS) ?
198 IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
199 channel->center_freq =
200 ieee80211_channel_to_frequency(
201 channel->hw_value, channel->band);
202
203 /* TODO: Need to be dependent to the NVM */
204 channel->flags = IEEE80211_CHAN_NO_HT40;
205 if (ch_idx < NUM_2GHZ_CHANNELS &&
206 (ch_flags & NVM_CHANNEL_40MHZ)) {
207 if (iwl_nvm_channels[ch_idx] <= LAST_2GHZ_HT_PLUS)
208 channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
209 if (iwl_nvm_channels[ch_idx] >= FIRST_2GHZ_HT_MINUS)
210 channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
211 } else if (iwl_nvm_channels[ch_idx] <= LAST_5GHZ_HT &&
212 (ch_flags & NVM_CHANNEL_40MHZ)) {
213 if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0)
214 channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
215 else
216 channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
217 }
33158fef
EL
218 if (!(ch_flags & NVM_CHANNEL_80MHZ))
219 channel->flags |= IEEE80211_CHAN_NO_80MHZ;
220 if (!(ch_flags & NVM_CHANNEL_160MHZ))
221 channel->flags |= IEEE80211_CHAN_NO_160MHZ;
b1e1adfa
JB
222
223 if (!(ch_flags & NVM_CHANNEL_IBSS))
224 channel->flags |= IEEE80211_CHAN_NO_IBSS;
225
226 if (!(ch_flags & NVM_CHANNEL_ACTIVE))
227 channel->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
228
229 if (ch_flags & NVM_CHANNEL_RADAR)
230 channel->flags |= IEEE80211_CHAN_RADAR;
231
232 /* Initialize regulatory-based run-time data */
233
234 /* TODO: read the real value from the NVM */
235 channel->max_power = 0;
236 is_5ghz = channel->band == IEEE80211_BAND_5GHZ;
237 IWL_DEBUG_EEPROM(dev,
238 "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n",
239 channel->hw_value,
240 is_5ghz ? "5.2" : "2.4",
241 CHECK_AND_PRINT_I(VALID),
242 CHECK_AND_PRINT_I(IBSS),
243 CHECK_AND_PRINT_I(ACTIVE),
244 CHECK_AND_PRINT_I(RADAR),
245 CHECK_AND_PRINT_I(WIDE),
246 CHECK_AND_PRINT_I(DFS),
247 ch_flags,
248 channel->max_power,
249 ((ch_flags & NVM_CHANNEL_IBSS) &&
250 !(ch_flags & NVM_CHANNEL_RADAR))
251 ? "" : "not ");
252 }
253
254 return n_channels;
255}
256
33158fef
EL
257static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
258 struct iwl_nvm_data *data,
259 struct ieee80211_sta_vht_cap *vht_cap)
260{
261 /* For now, assume new devices with NVM are VHT capable */
262
263 vht_cap->vht_supported = true;
264
265 vht_cap->cap = IEEE80211_VHT_CAP_SHORT_GI_80 |
266 IEEE80211_VHT_CAP_RXSTBC_1 |
267 IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
268 7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
269
270 if (iwlwifi_mod_params.amsdu_size_8K)
271 vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
272
273 vht_cap->vht_mcs.rx_mcs_map =
274 cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 |
275 IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 |
276 IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 |
277 IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 |
278 IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 |
279 IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 |
280 IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 |
281 IEEE80211_VHT_MCS_NOT_SUPPORTED << 14);
282
283 if (data->valid_rx_ant == 1 || cfg->rx_with_siso_diversity) {
284 vht_cap->cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN |
285 IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN;
286 /* this works because NOT_SUPPORTED == 3 */
287 vht_cap->vht_mcs.rx_mcs_map |=
288 cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << 2);
289 }
290
291 vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map;
292}
293
b1e1adfa
JB
294static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
295 struct iwl_nvm_data *data, const __le16 *nvm_sw)
296{
297 int n_channels = iwl_init_channel_map(dev, cfg, data,
298 &nvm_sw[NVM_CHANNELS]);
299 int n_used = 0;
300 struct ieee80211_supported_band *sband;
301
302 sband = &data->bands[IEEE80211_BAND_2GHZ];
303 sband->band = IEEE80211_BAND_2GHZ;
304 sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS];
305 sband->n_bitrates = N_RATES_24;
306 n_used += iwl_init_sband_channels(data, sband, n_channels,
307 IEEE80211_BAND_2GHZ);
308 iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ);
309
310 sband = &data->bands[IEEE80211_BAND_5GHZ];
311 sband->band = IEEE80211_BAND_5GHZ;
312 sband->bitrates = &iwl_cfg80211_rates[RATES_52_OFFS];
313 sband->n_bitrates = N_RATES_52;
314 n_used += iwl_init_sband_channels(data, sband, n_channels,
315 IEEE80211_BAND_5GHZ);
316 iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ);
33158fef 317 iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap);
b1e1adfa
JB
318
319 if (n_channels != n_used)
320 IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n",
321 n_used, n_channels);
322}
323
324struct iwl_nvm_data *
325iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
326 const __le16 *nvm_hw, const __le16 *nvm_sw,
327 const __le16 *nvm_calib)
328{
329 struct iwl_nvm_data *data;
330 u8 hw_addr[ETH_ALEN];
331 u16 radio_cfg, sku;
332
333 data = kzalloc(sizeof(*data) +
334 sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS,
335 GFP_KERNEL);
336 if (!data)
337 return NULL;
338
339 data->nvm_version = le16_to_cpup(nvm_sw + NVM_VERSION);
340
341 radio_cfg = le16_to_cpup(nvm_sw + RADIO_CFG);
342 data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK(radio_cfg);
343 data->radio_cfg_step = NVM_RF_CFG_STEP_MSK(radio_cfg);
344 data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK(radio_cfg);
345 data->radio_cfg_pnum = NVM_RF_CFG_PNUM_MSK(radio_cfg);
346 data->valid_tx_ant = NVM_RF_CFG_TX_ANT_MSK(radio_cfg);
347 data->valid_rx_ant = NVM_RF_CFG_RX_ANT_MSK(radio_cfg);
348
349 sku = le16_to_cpup(nvm_sw + SKU);
350 data->sku_cap_band_24GHz_enable = sku & NVM_SKU_CAP_BAND_24GHZ;
351 data->sku_cap_band_52GHz_enable = sku & NVM_SKU_CAP_BAND_52GHZ;
352 data->sku_cap_11n_enable = sku & NVM_SKU_CAP_11N_ENABLE;
353 if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL)
354 data->sku_cap_11n_enable = false;
355
356 /* check overrides (some devices have wrong NVM) */
357 if (cfg->valid_tx_ant)
358 data->valid_tx_ant = cfg->valid_tx_ant;
359 if (cfg->valid_rx_ant)
360 data->valid_rx_ant = cfg->valid_rx_ant;
361
362 if (!data->valid_tx_ant || !data->valid_rx_ant) {
363 IWL_ERR_DEV(dev, "invalid antennas (0x%x, 0x%x)\n",
364 data->valid_tx_ant, data->valid_rx_ant);
365 kfree(data);
366 return NULL;
367 }
368
369 data->n_hw_addrs = le16_to_cpup(nvm_sw + N_HW_ADDRS);
370
371 data->xtal_calib[0] = *(nvm_calib + XTAL_CALIB);
372 data->xtal_calib[1] = *(nvm_calib + XTAL_CALIB + 1);
373
374 /* The byte order is little endian 16 bit, meaning 214365 */
375 memcpy(hw_addr, nvm_hw + HW_ADDR, ETH_ALEN);
376 data->hw_addr[0] = hw_addr[1];
377 data->hw_addr[1] = hw_addr[0];
378 data->hw_addr[2] = hw_addr[3];
379 data->hw_addr[3] = hw_addr[2];
380 data->hw_addr[4] = hw_addr[5];
381 data->hw_addr[5] = hw_addr[4];
382
383 iwl_init_sbands(dev, cfg, data, nvm_sw);
384
385 data->calib_version = 255; /* TODO:
386 this value will prevent some checks from
387 failing, we need to check if this
388 field is still needed, and if it does,
389 where is it in the NVM*/
390
391 return data;
392}
48e29340 393IWL_EXPORT_SYMBOL(iwl_parse_nvm_data);
This page took 0.129335 seconds and 5 git commands to generate.