Linux 3.9-rc8
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / iwlwifi / iwl-nvm-parse.c
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
25  * in the file called LICENSE.GPL.
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>
65 #include "iwl-modparams.h"
66 #include "iwl-nvm-parse.h"
67
68 /* NVM offsets (in words) definitions */
69 enum 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) */
87 enum 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  */
104 static 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) */
121 static 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 (?)
152  */
153 enum iwl_nvm_channel_flags {
154         NVM_CHANNEL_VALID = BIT(0),
155         NVM_CHANNEL_IBSS = BIT(1),
156         NVM_CHANNEL_ACTIVE = BIT(3),
157         NVM_CHANNEL_RADAR = BIT(4),
158         NVM_CHANNEL_DFS = BIT(7),
159         NVM_CHANNEL_WIDE = BIT(8),
160         NVM_CHANNEL_40MHZ = BIT(9),
161 };
162
163 #define CHECK_AND_PRINT_I(x)    \
164         ((ch_flags & NVM_CHANNEL_##x) ? # x " " : "")
165
166 static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
167                                 struct iwl_nvm_data *data,
168                                 const __le16 * const nvm_ch_flags)
169 {
170         int ch_idx;
171         int n_channels = 0;
172         struct ieee80211_channel *channel;
173         u16 ch_flags;
174         bool is_5ghz;
175
176         for (ch_idx = 0; ch_idx < IWL_NUM_CHANNELS; ch_idx++) {
177                 ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx);
178                 if (!(ch_flags & NVM_CHANNEL_VALID)) {
179                         IWL_DEBUG_EEPROM(dev,
180                                          "Ch. %d Flags %x [%sGHz] - No traffic\n",
181                                          iwl_nvm_channels[ch_idx],
182                                          ch_flags,
183                                          (ch_idx >= NUM_2GHZ_CHANNELS) ?
184                                          "5.2" : "2.4");
185                         continue;
186                 }
187
188                 channel = &data->channels[n_channels];
189                 n_channels++;
190
191                 channel->hw_value = iwl_nvm_channels[ch_idx];
192                 channel->band = (ch_idx < NUM_2GHZ_CHANNELS) ?
193                                 IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
194                 channel->center_freq =
195                         ieee80211_channel_to_frequency(
196                                 channel->hw_value, channel->band);
197
198                 /* TODO: Need to be dependent to the NVM */
199                 channel->flags = IEEE80211_CHAN_NO_HT40;
200                 if (ch_idx < NUM_2GHZ_CHANNELS &&
201                     (ch_flags & NVM_CHANNEL_40MHZ)) {
202                         if (iwl_nvm_channels[ch_idx] <= LAST_2GHZ_HT_PLUS)
203                                 channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
204                         if (iwl_nvm_channels[ch_idx] >= FIRST_2GHZ_HT_MINUS)
205                                 channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
206                 } else if (iwl_nvm_channels[ch_idx] <= LAST_5GHZ_HT &&
207                            (ch_flags & NVM_CHANNEL_40MHZ)) {
208                         if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0)
209                                 channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
210                         else
211                                 channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
212                 }
213
214                 if (!(ch_flags & NVM_CHANNEL_IBSS))
215                         channel->flags |= IEEE80211_CHAN_NO_IBSS;
216
217                 if (!(ch_flags & NVM_CHANNEL_ACTIVE))
218                         channel->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
219
220                 if (ch_flags & NVM_CHANNEL_RADAR)
221                         channel->flags |= IEEE80211_CHAN_RADAR;
222
223                 /* Initialize regulatory-based run-time data */
224
225                 /* TODO: read the real value from the NVM */
226                 channel->max_power = 0;
227                 is_5ghz = channel->band == IEEE80211_BAND_5GHZ;
228                 IWL_DEBUG_EEPROM(dev,
229                                  "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n",
230                                  channel->hw_value,
231                                  is_5ghz ? "5.2" : "2.4",
232                                  CHECK_AND_PRINT_I(VALID),
233                                  CHECK_AND_PRINT_I(IBSS),
234                                  CHECK_AND_PRINT_I(ACTIVE),
235                                  CHECK_AND_PRINT_I(RADAR),
236                                  CHECK_AND_PRINT_I(WIDE),
237                                  CHECK_AND_PRINT_I(DFS),
238                                  ch_flags,
239                                  channel->max_power,
240                                  ((ch_flags & NVM_CHANNEL_IBSS) &&
241                                   !(ch_flags & NVM_CHANNEL_RADAR))
242                                         ? "" : "not ");
243         }
244
245         return n_channels;
246 }
247
248 static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
249                             struct iwl_nvm_data *data, const __le16 *nvm_sw)
250 {
251         int n_channels = iwl_init_channel_map(dev, cfg, data,
252                         &nvm_sw[NVM_CHANNELS]);
253         int n_used = 0;
254         struct ieee80211_supported_band *sband;
255
256         sband = &data->bands[IEEE80211_BAND_2GHZ];
257         sband->band = IEEE80211_BAND_2GHZ;
258         sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS];
259         sband->n_bitrates = N_RATES_24;
260         n_used += iwl_init_sband_channels(data, sband, n_channels,
261                                           IEEE80211_BAND_2GHZ);
262         iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ);
263
264         sband = &data->bands[IEEE80211_BAND_5GHZ];
265         sband->band = IEEE80211_BAND_5GHZ;
266         sband->bitrates = &iwl_cfg80211_rates[RATES_52_OFFS];
267         sband->n_bitrates = N_RATES_52;
268         n_used += iwl_init_sband_channels(data, sband, n_channels,
269                                           IEEE80211_BAND_5GHZ);
270         iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ);
271
272         if (n_channels != n_used)
273                 IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n",
274                             n_used, n_channels);
275 }
276
277 struct iwl_nvm_data *
278 iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
279                    const __le16 *nvm_hw, const __le16 *nvm_sw,
280                    const __le16 *nvm_calib)
281 {
282         struct iwl_nvm_data *data;
283         u8 hw_addr[ETH_ALEN];
284         u16 radio_cfg, sku;
285
286         data = kzalloc(sizeof(*data) +
287                        sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS,
288                        GFP_KERNEL);
289         if (!data)
290                 return NULL;
291
292         data->nvm_version = le16_to_cpup(nvm_sw + NVM_VERSION);
293
294         radio_cfg = le16_to_cpup(nvm_sw + RADIO_CFG);
295         data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK(radio_cfg);
296         data->radio_cfg_step = NVM_RF_CFG_STEP_MSK(radio_cfg);
297         data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK(radio_cfg);
298         data->radio_cfg_pnum = NVM_RF_CFG_PNUM_MSK(radio_cfg);
299         data->valid_tx_ant = NVM_RF_CFG_TX_ANT_MSK(radio_cfg);
300         data->valid_rx_ant = NVM_RF_CFG_RX_ANT_MSK(radio_cfg);
301
302         sku = le16_to_cpup(nvm_sw + SKU);
303         data->sku_cap_band_24GHz_enable = sku & NVM_SKU_CAP_BAND_24GHZ;
304         data->sku_cap_band_52GHz_enable = sku & NVM_SKU_CAP_BAND_52GHZ;
305         data->sku_cap_11n_enable = sku & NVM_SKU_CAP_11N_ENABLE;
306         if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL)
307                 data->sku_cap_11n_enable = false;
308
309         /* check overrides (some devices have wrong NVM) */
310         if (cfg->valid_tx_ant)
311                 data->valid_tx_ant = cfg->valid_tx_ant;
312         if (cfg->valid_rx_ant)
313                 data->valid_rx_ant = cfg->valid_rx_ant;
314
315         if (!data->valid_tx_ant || !data->valid_rx_ant) {
316                 IWL_ERR_DEV(dev, "invalid antennas (0x%x, 0x%x)\n",
317                             data->valid_tx_ant, data->valid_rx_ant);
318                 kfree(data);
319                 return NULL;
320         }
321
322         data->n_hw_addrs = le16_to_cpup(nvm_sw + N_HW_ADDRS);
323
324         data->xtal_calib[0] = *(nvm_calib + XTAL_CALIB);
325         data->xtal_calib[1] = *(nvm_calib + XTAL_CALIB + 1);
326
327         /* The byte order is little endian 16 bit, meaning 214365 */
328         memcpy(hw_addr, nvm_hw + HW_ADDR, ETH_ALEN);
329         data->hw_addr[0] = hw_addr[1];
330         data->hw_addr[1] = hw_addr[0];
331         data->hw_addr[2] = hw_addr[3];
332         data->hw_addr[3] = hw_addr[2];
333         data->hw_addr[4] = hw_addr[5];
334         data->hw_addr[5] = hw_addr[4];
335
336         iwl_init_sbands(dev, cfg, data, nvm_sw);
337
338         data->calib_version = 255;   /* TODO:
339                                         this value will prevent some checks from
340                                         failing, we need to check if this
341                                         field is still needed, and if it does,
342                                         where is it in the NVM*/
343
344         return data;
345 }
346 EXPORT_SYMBOL_GPL(iwl_parse_nvm_data);