blob: 1ae6f2c1558d1b617ec9a92fb19e9dcfdca8c8ff [file] [log] [blame]
Johannes Bergb1e1adf2013-01-24 14:14:22 +01001/******************************************************************************
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
Emmanuel Grumbach410dc5a2013-02-18 09:22:28 +020025 * in the file called COPYING.
Johannes Bergb1e1adf2013-01-24 14:14:22 +010026 *
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>
65#include "iwl-modparams.h"
66#include "iwl-nvm-parse.h"
67
68/* NVM offsets (in words) definitions */
69enum wkp_nvm_offsets {
70 /* NVM HW-Section offset (in words) definitions */
71 HW_ADDR = 0x15,
72
73/* NVM SW-Section offset (in words) definitions */
74 NVM_SW_SECTION = 0x1C0,
75 NVM_VERSION = 0,
76 RADIO_CFG = 1,
77 SKU = 2,
78 N_HW_ADDRS = 3,
79 NVM_CHANNELS = 0x1E0 - NVM_SW_SECTION,
80
81/* NVM calibration section offset (in words) definitions */
82 NVM_CALIB_SECTION = 0x2B8,
83 XTAL_CALIB = 0x316 - NVM_CALIB_SECTION
84};
85
86/* SKU Capabilities (actual values from NVM definition) */
87enum nvm_sku_bits {
88 NVM_SKU_CAP_BAND_24GHZ = BIT(0),
89 NVM_SKU_CAP_BAND_52GHZ = BIT(1),
90 NVM_SKU_CAP_11N_ENABLE = BIT(2),
91};
92
93/* radio config bits (actual values from NVM definition) */
94#define NVM_RF_CFG_DASH_MSK(x) (x & 0x3) /* bits 0-1 */
95#define NVM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */
96#define NVM_RF_CFG_TYPE_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */
97#define NVM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */
98#define NVM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */
99#define NVM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */
100
101/*
102 * These are the channel numbers in the order that they are stored in the NVM
103 */
104static const u8 iwl_nvm_channels[] = {
105 /* 2.4 GHz */
106 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
107 /* 5 GHz */
108 36, 40, 44 , 48, 52, 56, 60, 64,
109 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
110 149, 153, 157, 161, 165
111};
112
113#define IWL_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels)
114#define NUM_2GHZ_CHANNELS 14
115#define FIRST_2GHZ_HT_MINUS 5
116#define LAST_2GHZ_HT_PLUS 9
117#define LAST_5GHZ_HT 161
118
119
120/* rate data (static) */
121static struct ieee80211_rate iwl_cfg80211_rates[] = {
122 { .bitrate = 1 * 10, .hw_value = 0, .hw_value_short = 0, },
123 { .bitrate = 2 * 10, .hw_value = 1, .hw_value_short = 1,
124 .flags = IEEE80211_RATE_SHORT_PREAMBLE, },
125 { .bitrate = 5.5 * 10, .hw_value = 2, .hw_value_short = 2,
126 .flags = IEEE80211_RATE_SHORT_PREAMBLE, },
127 { .bitrate = 11 * 10, .hw_value = 3, .hw_value_short = 3,
128 .flags = IEEE80211_RATE_SHORT_PREAMBLE, },
129 { .bitrate = 6 * 10, .hw_value = 4, .hw_value_short = 4, },
130 { .bitrate = 9 * 10, .hw_value = 5, .hw_value_short = 5, },
131 { .bitrate = 12 * 10, .hw_value = 6, .hw_value_short = 6, },
132 { .bitrate = 18 * 10, .hw_value = 7, .hw_value_short = 7, },
133 { .bitrate = 24 * 10, .hw_value = 8, .hw_value_short = 8, },
134 { .bitrate = 36 * 10, .hw_value = 9, .hw_value_short = 9, },
135 { .bitrate = 48 * 10, .hw_value = 10, .hw_value_short = 10, },
136 { .bitrate = 54 * 10, .hw_value = 11, .hw_value_short = 11, },
137};
138#define RATES_24_OFFS 0
139#define N_RATES_24 ARRAY_SIZE(iwl_cfg80211_rates)
140#define RATES_52_OFFS 4
141#define N_RATES_52 (N_RATES_24 - RATES_52_OFFS)
142
143/**
144 * enum iwl_nvm_channel_flags - channel flags in NVM
145 * @NVM_CHANNEL_VALID: channel is usable for this SKU/geo
146 * @NVM_CHANNEL_IBSS: usable as an IBSS channel
147 * @NVM_CHANNEL_ACTIVE: active scanning allowed
148 * @NVM_CHANNEL_RADAR: radar detection required
149 * @NVM_CHANNEL_DFS: dynamic freq selection candidate
150 * @NVM_CHANNEL_WIDE: 20 MHz channel okay (?)
151 * @NVM_CHANNEL_40MHZ: 40 MHz channel okay (?)
Eytan Lifshitz33158fe2013-02-20 11:01:13 +0200152 * @NVM_CHANNEL_80MHZ: 80 MHz channel okay (?)
153 * @NVM_CHANNEL_160MHZ: 160 MHz channel okay (?)
Johannes Bergb1e1adf2013-01-24 14:14:22 +0100154 */
155enum iwl_nvm_channel_flags {
156 NVM_CHANNEL_VALID = BIT(0),
157 NVM_CHANNEL_IBSS = BIT(1),
158 NVM_CHANNEL_ACTIVE = BIT(3),
159 NVM_CHANNEL_RADAR = BIT(4),
160 NVM_CHANNEL_DFS = BIT(7),
161 NVM_CHANNEL_WIDE = BIT(8),
162 NVM_CHANNEL_40MHZ = BIT(9),
Eytan Lifshitz33158fe2013-02-20 11:01:13 +0200163 NVM_CHANNEL_80MHZ = BIT(10),
164 NVM_CHANNEL_160MHZ = BIT(11),
Johannes Bergb1e1adf2013-01-24 14:14:22 +0100165};
166
167#define CHECK_AND_PRINT_I(x) \
168 ((ch_flags & NVM_CHANNEL_##x) ? # x " " : "")
169
170static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
171 struct iwl_nvm_data *data,
172 const __le16 * const nvm_ch_flags)
173{
174 int ch_idx;
175 int n_channels = 0;
176 struct ieee80211_channel *channel;
177 u16 ch_flags;
178 bool is_5ghz;
179
180 for (ch_idx = 0; ch_idx < IWL_NUM_CHANNELS; ch_idx++) {
181 ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx);
182 if (!(ch_flags & NVM_CHANNEL_VALID)) {
183 IWL_DEBUG_EEPROM(dev,
184 "Ch. %d Flags %x [%sGHz] - No traffic\n",
185 iwl_nvm_channels[ch_idx],
186 ch_flags,
187 (ch_idx >= NUM_2GHZ_CHANNELS) ?
188 "5.2" : "2.4");
189 continue;
190 }
191
192 channel = &data->channels[n_channels];
193 n_channels++;
194
195 channel->hw_value = iwl_nvm_channels[ch_idx];
196 channel->band = (ch_idx < NUM_2GHZ_CHANNELS) ?
197 IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
198 channel->center_freq =
199 ieee80211_channel_to_frequency(
200 channel->hw_value, channel->band);
201
202 /* TODO: Need to be dependent to the NVM */
203 channel->flags = IEEE80211_CHAN_NO_HT40;
204 if (ch_idx < NUM_2GHZ_CHANNELS &&
205 (ch_flags & NVM_CHANNEL_40MHZ)) {
206 if (iwl_nvm_channels[ch_idx] <= LAST_2GHZ_HT_PLUS)
207 channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
208 if (iwl_nvm_channels[ch_idx] >= FIRST_2GHZ_HT_MINUS)
209 channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
210 } else if (iwl_nvm_channels[ch_idx] <= LAST_5GHZ_HT &&
211 (ch_flags & NVM_CHANNEL_40MHZ)) {
212 if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0)
213 channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
214 else
215 channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
216 }
Eytan Lifshitz33158fe2013-02-20 11:01:13 +0200217 if (!(ch_flags & NVM_CHANNEL_80MHZ))
218 channel->flags |= IEEE80211_CHAN_NO_80MHZ;
219 if (!(ch_flags & NVM_CHANNEL_160MHZ))
220 channel->flags |= IEEE80211_CHAN_NO_160MHZ;
Johannes Bergb1e1adf2013-01-24 14:14:22 +0100221
222 if (!(ch_flags & NVM_CHANNEL_IBSS))
223 channel->flags |= IEEE80211_CHAN_NO_IBSS;
224
225 if (!(ch_flags & NVM_CHANNEL_ACTIVE))
226 channel->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
227
228 if (ch_flags & NVM_CHANNEL_RADAR)
229 channel->flags |= IEEE80211_CHAN_RADAR;
230
231 /* Initialize regulatory-based run-time data */
232
233 /* TODO: read the real value from the NVM */
234 channel->max_power = 0;
235 is_5ghz = channel->band == IEEE80211_BAND_5GHZ;
236 IWL_DEBUG_EEPROM(dev,
237 "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n",
238 channel->hw_value,
239 is_5ghz ? "5.2" : "2.4",
240 CHECK_AND_PRINT_I(VALID),
241 CHECK_AND_PRINT_I(IBSS),
242 CHECK_AND_PRINT_I(ACTIVE),
243 CHECK_AND_PRINT_I(RADAR),
244 CHECK_AND_PRINT_I(WIDE),
245 CHECK_AND_PRINT_I(DFS),
246 ch_flags,
247 channel->max_power,
248 ((ch_flags & NVM_CHANNEL_IBSS) &&
249 !(ch_flags & NVM_CHANNEL_RADAR))
250 ? "" : "not ");
251 }
252
253 return n_channels;
254}
255
Eytan Lifshitz33158fe2013-02-20 11:01:13 +0200256static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
257 struct iwl_nvm_data *data,
258 struct ieee80211_sta_vht_cap *vht_cap)
259{
260 /* For now, assume new devices with NVM are VHT capable */
261
262 vht_cap->vht_supported = true;
263
264 vht_cap->cap = IEEE80211_VHT_CAP_SHORT_GI_80 |
265 IEEE80211_VHT_CAP_RXSTBC_1 |
266 IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
267 7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
268
269 if (iwlwifi_mod_params.amsdu_size_8K)
270 vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
271
272 vht_cap->vht_mcs.rx_mcs_map =
273 cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 |
274 IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 |
275 IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 |
276 IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 |
277 IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 |
278 IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 |
279 IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 |
280 IEEE80211_VHT_MCS_NOT_SUPPORTED << 14);
281
282 if (data->valid_rx_ant == 1 || cfg->rx_with_siso_diversity) {
283 vht_cap->cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN |
284 IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN;
285 /* this works because NOT_SUPPORTED == 3 */
286 vht_cap->vht_mcs.rx_mcs_map |=
287 cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << 2);
288 }
289
290 vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map;
291}
292
Johannes Bergb1e1adf2013-01-24 14:14:22 +0100293static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
294 struct iwl_nvm_data *data, const __le16 *nvm_sw)
295{
296 int n_channels = iwl_init_channel_map(dev, cfg, data,
297 &nvm_sw[NVM_CHANNELS]);
298 int n_used = 0;
299 struct ieee80211_supported_band *sband;
300
301 sband = &data->bands[IEEE80211_BAND_2GHZ];
302 sband->band = IEEE80211_BAND_2GHZ;
303 sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS];
304 sband->n_bitrates = N_RATES_24;
305 n_used += iwl_init_sband_channels(data, sband, n_channels,
306 IEEE80211_BAND_2GHZ);
307 iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ);
308
309 sband = &data->bands[IEEE80211_BAND_5GHZ];
310 sband->band = IEEE80211_BAND_5GHZ;
311 sband->bitrates = &iwl_cfg80211_rates[RATES_52_OFFS];
312 sband->n_bitrates = N_RATES_52;
313 n_used += iwl_init_sband_channels(data, sband, n_channels,
314 IEEE80211_BAND_5GHZ);
315 iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ);
Eytan Lifshitz33158fe2013-02-20 11:01:13 +0200316 iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap);
Johannes Bergb1e1adf2013-01-24 14:14:22 +0100317
318 if (n_channels != n_used)
319 IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n",
320 n_used, n_channels);
321}
322
323struct iwl_nvm_data *
324iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
325 const __le16 *nvm_hw, const __le16 *nvm_sw,
326 const __le16 *nvm_calib)
327{
328 struct iwl_nvm_data *data;
329 u8 hw_addr[ETH_ALEN];
330 u16 radio_cfg, sku;
331
332 data = kzalloc(sizeof(*data) +
333 sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS,
334 GFP_KERNEL);
335 if (!data)
336 return NULL;
337
338 data->nvm_version = le16_to_cpup(nvm_sw + NVM_VERSION);
339
340 radio_cfg = le16_to_cpup(nvm_sw + RADIO_CFG);
341 data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK(radio_cfg);
342 data->radio_cfg_step = NVM_RF_CFG_STEP_MSK(radio_cfg);
343 data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK(radio_cfg);
344 data->radio_cfg_pnum = NVM_RF_CFG_PNUM_MSK(radio_cfg);
345 data->valid_tx_ant = NVM_RF_CFG_TX_ANT_MSK(radio_cfg);
346 data->valid_rx_ant = NVM_RF_CFG_RX_ANT_MSK(radio_cfg);
347
348 sku = le16_to_cpup(nvm_sw + SKU);
349 data->sku_cap_band_24GHz_enable = sku & NVM_SKU_CAP_BAND_24GHZ;
350 data->sku_cap_band_52GHz_enable = sku & NVM_SKU_CAP_BAND_52GHZ;
351 data->sku_cap_11n_enable = sku & NVM_SKU_CAP_11N_ENABLE;
352 if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL)
353 data->sku_cap_11n_enable = false;
354
355 /* check overrides (some devices have wrong NVM) */
356 if (cfg->valid_tx_ant)
357 data->valid_tx_ant = cfg->valid_tx_ant;
358 if (cfg->valid_rx_ant)
359 data->valid_rx_ant = cfg->valid_rx_ant;
360
361 if (!data->valid_tx_ant || !data->valid_rx_ant) {
362 IWL_ERR_DEV(dev, "invalid antennas (0x%x, 0x%x)\n",
363 data->valid_tx_ant, data->valid_rx_ant);
364 kfree(data);
365 return NULL;
366 }
367
368 data->n_hw_addrs = le16_to_cpup(nvm_sw + N_HW_ADDRS);
369
370 data->xtal_calib[0] = *(nvm_calib + XTAL_CALIB);
371 data->xtal_calib[1] = *(nvm_calib + XTAL_CALIB + 1);
372
373 /* The byte order is little endian 16 bit, meaning 214365 */
374 memcpy(hw_addr, nvm_hw + HW_ADDR, ETH_ALEN);
375 data->hw_addr[0] = hw_addr[1];
376 data->hw_addr[1] = hw_addr[0];
377 data->hw_addr[2] = hw_addr[3];
378 data->hw_addr[3] = hw_addr[2];
379 data->hw_addr[4] = hw_addr[5];
380 data->hw_addr[5] = hw_addr[4];
381
382 iwl_init_sbands(dev, cfg, data, nvm_sw);
383
384 data->calib_version = 255; /* TODO:
385 this value will prevent some checks from
386 failing, we need to check if this
387 field is still needed, and if it does,
388 where is it in the NVM*/
389
390 return data;
391}
392EXPORT_SYMBOL_GPL(iwl_parse_nvm_data);