linux/drivers/net/wireless/wl12xx/wl1271_init.c
<<
>>
Prefs
   1/*
   2 * This file is part of wl1271
   3 *
   4 * Copyright (C) 2009 Nokia Corporation
   5 *
   6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License
  10 * version 2 as published by the Free Software Foundation.
  11 *
  12 * This program is distributed in the hope that it will be useful, but
  13 * WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 * General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  20 * 02110-1301 USA
  21 *
  22 */
  23
  24#include <linux/kernel.h>
  25#include <linux/module.h>
  26
  27#include "wl1271_init.h"
  28#include "wl12xx_80211.h"
  29#include "wl1271_acx.h"
  30#include "wl1271_cmd.h"
  31#include "wl1271_reg.h"
  32
  33static int wl1271_init_hwenc_config(struct wl1271 *wl)
  34{
  35        int ret;
  36
  37        ret = wl1271_acx_feature_cfg(wl);
  38        if (ret < 0) {
  39                wl1271_warning("couldn't set feature config");
  40                return ret;
  41        }
  42
  43        ret = wl1271_cmd_set_default_wep_key(wl, wl->default_key);
  44        if (ret < 0) {
  45                wl1271_warning("couldn't set default key");
  46                return ret;
  47        }
  48
  49        return 0;
  50}
  51
  52static int wl1271_init_templates_config(struct wl1271 *wl)
  53{
  54        int ret;
  55
  56        /* send empty templates for fw memory reservation */
  57        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
  58                                      sizeof(struct wl12xx_probe_req_template));
  59        if (ret < 0)
  60                return ret;
  61
  62        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL,
  63                                      sizeof(struct wl12xx_null_data_template));
  64        if (ret < 0)
  65                return ret;
  66
  67        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL,
  68                                      sizeof(struct wl12xx_ps_poll_template));
  69        if (ret < 0)
  70                return ret;
  71
  72        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL,
  73                                      sizeof
  74                                      (struct wl12xx_qos_null_data_template));
  75        if (ret < 0)
  76                return ret;
  77
  78        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL,
  79                                      sizeof
  80                                      (struct wl12xx_probe_resp_template));
  81        if (ret < 0)
  82                return ret;
  83
  84        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL,
  85                                      sizeof
  86                                      (struct wl12xx_beacon_template));
  87        if (ret < 0)
  88                return ret;
  89
  90        return 0;
  91}
  92
  93static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
  94{
  95        int ret;
  96
  97        ret = wl1271_acx_rx_msdu_life_time(wl, RX_MSDU_LIFETIME_DEF);
  98        if (ret < 0)
  99                return ret;
 100
 101        ret = wl1271_acx_rx_config(wl, config, filter);
 102        if (ret < 0)
 103                return ret;
 104
 105        return 0;
 106}
 107
 108static int wl1271_init_phy_config(struct wl1271 *wl)
 109{
 110        int ret;
 111
 112        ret = wl1271_acx_pd_threshold(wl);
 113        if (ret < 0)
 114                return ret;
 115
 116        ret = wl1271_acx_slot(wl, DEFAULT_SLOT_TIME);
 117        if (ret < 0)
 118                return ret;
 119
 120        ret = wl1271_acx_group_address_tbl(wl);
 121        if (ret < 0)
 122                return ret;
 123
 124        ret = wl1271_acx_service_period_timeout(wl);
 125        if (ret < 0)
 126                return ret;
 127
 128        ret = wl1271_acx_rts_threshold(wl, RTS_THRESHOLD_DEF);
 129        if (ret < 0)
 130                return ret;
 131
 132        return 0;
 133}
 134
 135static int wl1271_init_beacon_filter(struct wl1271 *wl)
 136{
 137        int ret;
 138
 139        ret = wl1271_acx_beacon_filter_opt(wl);
 140        if (ret < 0)
 141                return ret;
 142
 143        ret = wl1271_acx_beacon_filter_table(wl);
 144        if (ret < 0)
 145                return ret;
 146
 147        return 0;
 148}
 149
 150static int wl1271_init_pta(struct wl1271 *wl)
 151{
 152        int ret;
 153
 154        ret = wl1271_acx_sg_enable(wl);
 155        if (ret < 0)
 156                return ret;
 157
 158        ret = wl1271_acx_sg_cfg(wl);
 159        if (ret < 0)
 160                return ret;
 161
 162        return 0;
 163}
 164
 165static int wl1271_init_energy_detection(struct wl1271 *wl)
 166{
 167        int ret;
 168
 169        ret = wl1271_acx_cca_threshold(wl);
 170        if (ret < 0)
 171                return ret;
 172
 173        return 0;
 174}
 175
 176static int wl1271_init_beacon_broadcast(struct wl1271 *wl)
 177{
 178        int ret;
 179
 180        ret = wl1271_acx_bcn_dtim_options(wl);
 181        if (ret < 0)
 182                return ret;
 183
 184        return 0;
 185}
 186
 187static int wl1271_init_general_parms(struct wl1271 *wl)
 188{
 189        struct wl1271_general_parms *gen_parms;
 190        int ret;
 191
 192        gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
 193        if (!gen_parms)
 194                return -ENOMEM;
 195
 196        gen_parms->id = TEST_CMD_INI_FILE_GENERAL_PARAM;
 197
 198        gen_parms->ref_clk = REF_CLK_38_4_E;
 199        /* FIXME: magic numbers */
 200        gen_parms->settling_time = 5;
 201        gen_parms->clk_valid_on_wakeup = 0;
 202        gen_parms->dc2dcmode = 0;
 203        gen_parms->single_dual_band = 0;
 204        gen_parms->tx_bip_fem_autodetect = 1;
 205        gen_parms->tx_bip_fem_manufacturer = 1;
 206        gen_parms->settings = 1;
 207
 208        ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0);
 209        if (ret < 0) {
 210                wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
 211                return ret;
 212        }
 213
 214        kfree(gen_parms);
 215        return 0;
 216}
 217
 218static int wl1271_init_radio_parms(struct wl1271 *wl)
 219{
 220        /*
 221         * FIXME: All these magic numbers should be moved to some place where
 222         * they can be configured (separate file?)
 223         */
 224
 225        struct wl1271_radio_parms *radio_parms;
 226        int ret;
 227        u8 compensation[] = { 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8, 0xfc, 0x00,
 228                              0x08, 0x10, 0xf0, 0xf8, 0x00, 0x0a, 0x14 };
 229
 230        u8 tx_rate_limits_normal[]   = { 0x1e, 0x1f, 0x22, 0x24, 0x28, 0x29 };
 231        u8 tx_rate_limits_degraded[] = { 0x1b, 0x1c, 0x1e, 0x20, 0x24, 0x25 };
 232
 233        u8 tx_channel_limits_11b[] = { 0x22, 0x50, 0x50, 0x50,
 234                                       0x50, 0x50, 0x50, 0x50,
 235                                       0x50, 0x50, 0x22, 0x50,
 236                                       0x22, 0x50 };
 237
 238        u8 tx_channel_limits_ofdm[] = { 0x20, 0x50, 0x50, 0x50,
 239                                        0x50, 0x50, 0x50, 0x50,
 240                                        0x50, 0x50, 0x20, 0x50,
 241                                        0x20, 0x50 };
 242
 243        u8 tx_pdv_rate_offsets[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 244
 245        u8 tx_ibias[] = { 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x27 };
 246
 247        radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL);
 248        if (!radio_parms)
 249                return -ENOMEM;
 250
 251        radio_parms->id = TEST_CMD_INI_FILE_RADIO_PARAM;
 252
 253        /* Static radio parameters */
 254        radio_parms->rx_trace_loss = 10;
 255        radio_parms->tx_trace_loss = 10;
 256        memcpy(radio_parms->rx_rssi_and_proc_compens, compensation,
 257               sizeof(compensation));
 258
 259        /* We don't set the 5GHz -- N/A */
 260
 261        /* Dynamic radio parameters */
 262        radio_parms->tx_ref_pd_voltage = cpu_to_le16(0x24e);
 263        radio_parms->tx_ref_power = 0x78;
 264        radio_parms->tx_offset_db = 0x0;
 265
 266        memcpy(radio_parms->tx_rate_limits_normal, tx_rate_limits_normal,
 267               sizeof(tx_rate_limits_normal));
 268        memcpy(radio_parms->tx_rate_limits_degraded, tx_rate_limits_degraded,
 269               sizeof(tx_rate_limits_degraded));
 270
 271        memcpy(radio_parms->tx_channel_limits_11b, tx_channel_limits_11b,
 272               sizeof(tx_channel_limits_11b));
 273        memcpy(radio_parms->tx_channel_limits_ofdm, tx_channel_limits_ofdm,
 274               sizeof(tx_channel_limits_ofdm));
 275        memcpy(radio_parms->tx_pdv_rate_offsets, tx_pdv_rate_offsets,
 276               sizeof(tx_pdv_rate_offsets));
 277        memcpy(radio_parms->tx_ibias, tx_ibias,
 278               sizeof(tx_ibias));
 279
 280        radio_parms->rx_fem_insertion_loss = 0x14;
 281
 282        ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0);
 283        if (ret < 0)
 284                wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed");
 285
 286        kfree(radio_parms);
 287        return ret;
 288}
 289
 290int wl1271_hw_init(struct wl1271 *wl)
 291{
 292        int ret;
 293
 294        ret = wl1271_init_general_parms(wl);
 295        if (ret < 0)
 296                return ret;
 297
 298        ret = wl1271_init_radio_parms(wl);
 299        if (ret < 0)
 300                return ret;
 301
 302        /* Template settings */
 303        ret = wl1271_init_templates_config(wl);
 304        if (ret < 0)
 305                return ret;
 306
 307        /* Default memory configuration */
 308        ret = wl1271_acx_init_mem_config(wl);
 309        if (ret < 0)
 310                return ret;
 311
 312        /* RX config */
 313        ret = wl1271_init_rx_config(wl,
 314                                       RX_CFG_PROMISCUOUS | RX_CFG_TSF,
 315                                       RX_FILTER_OPTION_DEF);
 316        /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS,
 317           RX_FILTER_OPTION_FILTER_ALL); */
 318        if (ret < 0)
 319                goto out_free_memmap;
 320
 321        /* PHY layer config */
 322        ret = wl1271_init_phy_config(wl);
 323        if (ret < 0)
 324                goto out_free_memmap;
 325
 326        /* Beacon filtering */
 327        ret = wl1271_init_beacon_filter(wl);
 328        if (ret < 0)
 329                goto out_free_memmap;
 330
 331        /* Configure TX patch complete interrupt behavior */
 332        ret = wl1271_acx_tx_config_options(wl);
 333        if (ret < 0)
 334                goto out_free_memmap;
 335
 336        /* RX complete interrupt pacing */
 337        ret = wl1271_acx_init_rx_interrupt(wl);
 338        if (ret < 0)
 339                goto out_free_memmap;
 340
 341        /* Bluetooth WLAN coexistence */
 342        ret = wl1271_init_pta(wl);
 343        if (ret < 0)
 344                goto out_free_memmap;
 345
 346        /* Energy detection */
 347        ret = wl1271_init_energy_detection(wl);
 348        if (ret < 0)
 349                goto out_free_memmap;
 350
 351        /* Beacons and boradcast settings */
 352        ret = wl1271_init_beacon_broadcast(wl);
 353        if (ret < 0)
 354                goto out_free_memmap;
 355
 356        /* Default fragmentation threshold */
 357        ret = wl1271_acx_frag_threshold(wl);
 358        if (ret < 0)
 359                goto out_free_memmap;
 360
 361        /* Default TID configuration */
 362        ret = wl1271_acx_tid_cfg(wl);
 363        if (ret < 0)
 364                goto out_free_memmap;
 365
 366        /* Default AC configuration */
 367        ret = wl1271_acx_ac_cfg(wl);
 368        if (ret < 0)
 369                goto out_free_memmap;
 370
 371        /* Configure TX rate classes */
 372        ret = wl1271_acx_rate_policies(wl);
 373        if (ret < 0)
 374                goto out_free_memmap;
 375
 376        /* Enable data path */
 377        ret = wl1271_cmd_data_path(wl, wl->channel, 1);
 378        if (ret < 0)
 379                goto out_free_memmap;
 380
 381        /* Configure for ELP power saving */
 382        ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
 383        if (ret < 0)
 384                goto out_free_memmap;
 385
 386        /* Configure HW encryption */
 387        ret = wl1271_init_hwenc_config(wl);
 388        if (ret < 0)
 389                goto out_free_memmap;
 390
 391        return 0;
 392
 393 out_free_memmap:
 394        kfree(wl->target_mem_map);
 395
 396        return ret;
 397}
 398