root/drivers/net/wireless/st/cw1200/main.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cw1200_init_common
  2. cw1200_register_common
  3. cw1200_free_common
  4. cw1200_unregister_common
  5. cw1200_dpll_from_clk
  6. cw1200_core_probe
  7. cw1200_core_release

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * mac80211 glue code for mac80211 ST-Ericsson CW1200 drivers
   4  *
   5  * Copyright (c) 2010, ST-Ericsson
   6  * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>
   7  *
   8  * Based on:
   9  * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
  10  * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de>
  11  * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
  12  *
  13  * Based on:
  14  * - the islsm (softmac prism54) driver, which is:
  15  *   Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
  16  * - stlc45xx driver
  17  *   Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
  18  */
  19 
  20 #include <linux/module.h>
  21 #include <linux/firmware.h>
  22 #include <linux/etherdevice.h>
  23 #include <linux/vmalloc.h>
  24 #include <linux/random.h>
  25 #include <linux/sched.h>
  26 #include <net/mac80211.h>
  27 
  28 #include "cw1200.h"
  29 #include "txrx.h"
  30 #include "hwbus.h"
  31 #include "fwio.h"
  32 #include "hwio.h"
  33 #include "bh.h"
  34 #include "sta.h"
  35 #include "scan.h"
  36 #include "debug.h"
  37 #include "pm.h"
  38 
  39 MODULE_AUTHOR("Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>");
  40 MODULE_DESCRIPTION("Softmac ST-Ericsson CW1200 common code");
  41 MODULE_LICENSE("GPL");
  42 MODULE_ALIAS("cw1200_core");
  43 
  44 /* Accept MAC address of the form macaddr=0x00,0x80,0xE1,0x30,0x40,0x50 */
  45 static u8 cw1200_mac_template[ETH_ALEN] = {0x02, 0x80, 0xe1, 0x00, 0x00, 0x00};
  46 module_param_array_named(macaddr, cw1200_mac_template, byte, NULL, 0444);
  47 MODULE_PARM_DESC(macaddr, "Override platform_data MAC address");
  48 
  49 static char *cw1200_sdd_path;
  50 module_param(cw1200_sdd_path, charp, 0644);
  51 MODULE_PARM_DESC(cw1200_sdd_path, "Override platform_data SDD file");
  52 static int cw1200_refclk;
  53 module_param(cw1200_refclk, int, 0644);
  54 MODULE_PARM_DESC(cw1200_refclk, "Override platform_data reference clock");
  55 
  56 int cw1200_power_mode = wsm_power_mode_quiescent;
  57 module_param(cw1200_power_mode, int, 0644);
  58 MODULE_PARM_DESC(cw1200_power_mode, "WSM power mode.  0 == active, 1 == doze, 2 == quiescent (default)");
  59 
  60 #define RATETAB_ENT(_rate, _rateid, _flags)             \
  61         {                                               \
  62                 .bitrate        = (_rate),              \
  63                 .hw_value       = (_rateid),            \
  64                 .flags          = (_flags),             \
  65         }
  66 
  67 static struct ieee80211_rate cw1200_rates[] = {
  68         RATETAB_ENT(10,  0,   0),
  69         RATETAB_ENT(20,  1,   0),
  70         RATETAB_ENT(55,  2,   0),
  71         RATETAB_ENT(110, 3,   0),
  72         RATETAB_ENT(60,  6,  0),
  73         RATETAB_ENT(90,  7,  0),
  74         RATETAB_ENT(120, 8,  0),
  75         RATETAB_ENT(180, 9,  0),
  76         RATETAB_ENT(240, 10, 0),
  77         RATETAB_ENT(360, 11, 0),
  78         RATETAB_ENT(480, 12, 0),
  79         RATETAB_ENT(540, 13, 0),
  80 };
  81 
  82 static struct ieee80211_rate cw1200_mcs_rates[] = {
  83         RATETAB_ENT(65,  14, IEEE80211_TX_RC_MCS),
  84         RATETAB_ENT(130, 15, IEEE80211_TX_RC_MCS),
  85         RATETAB_ENT(195, 16, IEEE80211_TX_RC_MCS),
  86         RATETAB_ENT(260, 17, IEEE80211_TX_RC_MCS),
  87         RATETAB_ENT(390, 18, IEEE80211_TX_RC_MCS),
  88         RATETAB_ENT(520, 19, IEEE80211_TX_RC_MCS),
  89         RATETAB_ENT(585, 20, IEEE80211_TX_RC_MCS),
  90         RATETAB_ENT(650, 21, IEEE80211_TX_RC_MCS),
  91 };
  92 
  93 #define cw1200_a_rates          (cw1200_rates + 4)
  94 #define cw1200_a_rates_size     (ARRAY_SIZE(cw1200_rates) - 4)
  95 #define cw1200_g_rates          (cw1200_rates + 0)
  96 #define cw1200_g_rates_size     (ARRAY_SIZE(cw1200_rates))
  97 #define cw1200_n_rates          (cw1200_mcs_rates)
  98 #define cw1200_n_rates_size     (ARRAY_SIZE(cw1200_mcs_rates))
  99 
 100 
 101 #define CHAN2G(_channel, _freq, _flags) {                       \
 102         .band                   = NL80211_BAND_2GHZ,            \
 103         .center_freq            = (_freq),                      \
 104         .hw_value               = (_channel),                   \
 105         .flags                  = (_flags),                     \
 106         .max_antenna_gain       = 0,                            \
 107         .max_power              = 30,                           \
 108 }
 109 
 110 #define CHAN5G(_channel, _flags) {                              \
 111         .band                   = NL80211_BAND_5GHZ,            \
 112         .center_freq    = 5000 + (5 * (_channel)),              \
 113         .hw_value               = (_channel),                   \
 114         .flags                  = (_flags),                     \
 115         .max_antenna_gain       = 0,                            \
 116         .max_power              = 30,                           \
 117 }
 118 
 119 static struct ieee80211_channel cw1200_2ghz_chantable[] = {
 120         CHAN2G(1, 2412, 0),
 121         CHAN2G(2, 2417, 0),
 122         CHAN2G(3, 2422, 0),
 123         CHAN2G(4, 2427, 0),
 124         CHAN2G(5, 2432, 0),
 125         CHAN2G(6, 2437, 0),
 126         CHAN2G(7, 2442, 0),
 127         CHAN2G(8, 2447, 0),
 128         CHAN2G(9, 2452, 0),
 129         CHAN2G(10, 2457, 0),
 130         CHAN2G(11, 2462, 0),
 131         CHAN2G(12, 2467, 0),
 132         CHAN2G(13, 2472, 0),
 133         CHAN2G(14, 2484, 0),
 134 };
 135 
 136 static struct ieee80211_channel cw1200_5ghz_chantable[] = {
 137         CHAN5G(34, 0),          CHAN5G(36, 0),
 138         CHAN5G(38, 0),          CHAN5G(40, 0),
 139         CHAN5G(42, 0),          CHAN5G(44, 0),
 140         CHAN5G(46, 0),          CHAN5G(48, 0),
 141         CHAN5G(52, 0),          CHAN5G(56, 0),
 142         CHAN5G(60, 0),          CHAN5G(64, 0),
 143         CHAN5G(100, 0),         CHAN5G(104, 0),
 144         CHAN5G(108, 0),         CHAN5G(112, 0),
 145         CHAN5G(116, 0),         CHAN5G(120, 0),
 146         CHAN5G(124, 0),         CHAN5G(128, 0),
 147         CHAN5G(132, 0),         CHAN5G(136, 0),
 148         CHAN5G(140, 0),         CHAN5G(149, 0),
 149         CHAN5G(153, 0),         CHAN5G(157, 0),
 150         CHAN5G(161, 0),         CHAN5G(165, 0),
 151         CHAN5G(184, 0),         CHAN5G(188, 0),
 152         CHAN5G(192, 0),         CHAN5G(196, 0),
 153         CHAN5G(200, 0),         CHAN5G(204, 0),
 154         CHAN5G(208, 0),         CHAN5G(212, 0),
 155         CHAN5G(216, 0),
 156 };
 157 
 158 static struct ieee80211_supported_band cw1200_band_2ghz = {
 159         .channels = cw1200_2ghz_chantable,
 160         .n_channels = ARRAY_SIZE(cw1200_2ghz_chantable),
 161         .bitrates = cw1200_g_rates,
 162         .n_bitrates = cw1200_g_rates_size,
 163         .ht_cap = {
 164                 .cap = IEEE80211_HT_CAP_GRN_FLD |
 165                         (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) |
 166                         IEEE80211_HT_CAP_MAX_AMSDU,
 167                 .ht_supported = 1,
 168                 .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K,
 169                 .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE,
 170                 .mcs = {
 171                         .rx_mask[0] = 0xFF,
 172                         .rx_highest = __cpu_to_le16(0x41),
 173                         .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
 174                 },
 175         },
 176 };
 177 
 178 static struct ieee80211_supported_band cw1200_band_5ghz = {
 179         .channels = cw1200_5ghz_chantable,
 180         .n_channels = ARRAY_SIZE(cw1200_5ghz_chantable),
 181         .bitrates = cw1200_a_rates,
 182         .n_bitrates = cw1200_a_rates_size,
 183         .ht_cap = {
 184                 .cap = IEEE80211_HT_CAP_GRN_FLD |
 185                         (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) |
 186                         IEEE80211_HT_CAP_MAX_AMSDU,
 187                 .ht_supported = 1,
 188                 .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K,
 189                 .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE,
 190                 .mcs = {
 191                         .rx_mask[0] = 0xFF,
 192                         .rx_highest = __cpu_to_le16(0x41),
 193                         .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
 194                 },
 195         },
 196 };
 197 
 198 static const unsigned long cw1200_ttl[] = {
 199         1 * HZ, /* VO */
 200         2 * HZ, /* VI */
 201         5 * HZ, /* BE */
 202         10 * HZ /* BK */
 203 };
 204 
 205 static const struct ieee80211_ops cw1200_ops = {
 206         .start                  = cw1200_start,
 207         .stop                   = cw1200_stop,
 208         .add_interface          = cw1200_add_interface,
 209         .remove_interface       = cw1200_remove_interface,
 210         .change_interface       = cw1200_change_interface,
 211         .tx                     = cw1200_tx,
 212         .hw_scan                = cw1200_hw_scan,
 213         .set_tim                = cw1200_set_tim,
 214         .sta_notify             = cw1200_sta_notify,
 215         .sta_add                = cw1200_sta_add,
 216         .sta_remove             = cw1200_sta_remove,
 217         .set_key                = cw1200_set_key,
 218         .set_rts_threshold      = cw1200_set_rts_threshold,
 219         .config                 = cw1200_config,
 220         .bss_info_changed       = cw1200_bss_info_changed,
 221         .prepare_multicast      = cw1200_prepare_multicast,
 222         .configure_filter       = cw1200_configure_filter,
 223         .conf_tx                = cw1200_conf_tx,
 224         .get_stats              = cw1200_get_stats,
 225         .ampdu_action           = cw1200_ampdu_action,
 226         .flush                  = cw1200_flush,
 227 #ifdef CONFIG_PM
 228         .suspend                = cw1200_wow_suspend,
 229         .resume                 = cw1200_wow_resume,
 230 #endif
 231         /* Intentionally not offloaded:                                 */
 232         /*.channel_switch       = cw1200_channel_switch,                */
 233         /*.remain_on_channel    = cw1200_remain_on_channel,             */
 234         /*.cancel_remain_on_channel = cw1200_cancel_remain_on_channel,  */
 235 };
 236 
 237 static int cw1200_ba_rx_tids = -1;
 238 static int cw1200_ba_tx_tids = -1;
 239 module_param(cw1200_ba_rx_tids, int, 0644);
 240 module_param(cw1200_ba_tx_tids, int, 0644);
 241 MODULE_PARM_DESC(cw1200_ba_rx_tids, "Block ACK RX TIDs");
 242 MODULE_PARM_DESC(cw1200_ba_tx_tids, "Block ACK TX TIDs");
 243 
 244 #ifdef CONFIG_PM
 245 static const struct wiphy_wowlan_support cw1200_wowlan_support = {
 246         /* Support only for limited wowlan functionalities */
 247         .flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_DISCONNECT,
 248 };
 249 #endif
 250 
 251 
 252 static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr,
 253                                                 const bool have_5ghz)
 254 {
 255         int i, band;
 256         struct ieee80211_hw *hw;
 257         struct cw1200_common *priv;
 258 
 259         hw = ieee80211_alloc_hw(sizeof(struct cw1200_common), &cw1200_ops);
 260         if (!hw)
 261                 return NULL;
 262 
 263         priv = hw->priv;
 264         priv->hw = hw;
 265         priv->hw_type = -1;
 266         priv->mode = NL80211_IFTYPE_UNSPECIFIED;
 267         priv->rates = cw1200_rates; /* TODO: fetch from FW */
 268         priv->mcs_rates = cw1200_n_rates;
 269         if (cw1200_ba_rx_tids != -1)
 270                 priv->ba_rx_tid_mask = cw1200_ba_rx_tids;
 271         else
 272                 priv->ba_rx_tid_mask = 0xFF; /* Enable RX BLKACK for all TIDs */
 273         if (cw1200_ba_tx_tids != -1)
 274                 priv->ba_tx_tid_mask = cw1200_ba_tx_tids;
 275         else
 276                 priv->ba_tx_tid_mask = 0xff; /* Enable TX BLKACK for all TIDs */
 277 
 278         ieee80211_hw_set(hw, NEED_DTIM_BEFORE_ASSOC);
 279         ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW);
 280         ieee80211_hw_set(hw, AMPDU_AGGREGATION);
 281         ieee80211_hw_set(hw, CONNECTION_MONITOR);
 282         ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
 283         ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
 284         ieee80211_hw_set(hw, SIGNAL_DBM);
 285         ieee80211_hw_set(hw, SUPPORTS_PS);
 286 
 287         hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
 288                                           BIT(NL80211_IFTYPE_ADHOC) |
 289                                           BIT(NL80211_IFTYPE_AP) |
 290                                           BIT(NL80211_IFTYPE_MESH_POINT) |
 291                                           BIT(NL80211_IFTYPE_P2P_CLIENT) |
 292                                           BIT(NL80211_IFTYPE_P2P_GO);
 293 
 294 #ifdef CONFIG_PM
 295         hw->wiphy->wowlan = &cw1200_wowlan_support;
 296 #endif
 297 
 298         hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
 299 
 300         hw->queues = 4;
 301 
 302         priv->rts_threshold = -1;
 303 
 304         hw->max_rates = 8;
 305         hw->max_rate_tries = 15;
 306         hw->extra_tx_headroom = WSM_TX_EXTRA_HEADROOM +
 307                 8;  /* TKIP IV */
 308 
 309         hw->sta_data_size = sizeof(struct cw1200_sta_priv);
 310 
 311         hw->wiphy->bands[NL80211_BAND_2GHZ] = &cw1200_band_2ghz;
 312         if (have_5ghz)
 313                 hw->wiphy->bands[NL80211_BAND_5GHZ] = &cw1200_band_5ghz;
 314 
 315         /* Channel params have to be cleared before registering wiphy again */
 316         for (band = 0; band < NUM_NL80211_BANDS; band++) {
 317                 struct ieee80211_supported_band *sband = hw->wiphy->bands[band];
 318                 if (!sband)
 319                         continue;
 320                 for (i = 0; i < sband->n_channels; i++) {
 321                         sband->channels[i].flags = 0;
 322                         sband->channels[i].max_antenna_gain = 0;
 323                         sband->channels[i].max_power = 30;
 324                 }
 325         }
 326 
 327         hw->wiphy->max_scan_ssids = 2;
 328         hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
 329 
 330         if (macaddr)
 331                 SET_IEEE80211_PERM_ADDR(hw, (u8 *)macaddr);
 332         else
 333                 SET_IEEE80211_PERM_ADDR(hw, cw1200_mac_template);
 334 
 335         /* Fix up mac address if necessary */
 336         if (hw->wiphy->perm_addr[3] == 0 &&
 337             hw->wiphy->perm_addr[4] == 0 &&
 338             hw->wiphy->perm_addr[5] == 0) {
 339                 get_random_bytes(&hw->wiphy->perm_addr[3], 3);
 340         }
 341 
 342         mutex_init(&priv->wsm_cmd_mux);
 343         mutex_init(&priv->conf_mutex);
 344         priv->workqueue = create_singlethread_workqueue("cw1200_wq");
 345         if (!priv->workqueue) {
 346                 ieee80211_free_hw(hw);
 347                 return NULL;
 348         }
 349 
 350         sema_init(&priv->scan.lock, 1);
 351         INIT_WORK(&priv->scan.work, cw1200_scan_work);
 352         INIT_DELAYED_WORK(&priv->scan.probe_work, cw1200_probe_work);
 353         INIT_DELAYED_WORK(&priv->scan.timeout, cw1200_scan_timeout);
 354         INIT_DELAYED_WORK(&priv->clear_recent_scan_work,
 355                           cw1200_clear_recent_scan_work);
 356         INIT_DELAYED_WORK(&priv->join_timeout, cw1200_join_timeout);
 357         INIT_WORK(&priv->unjoin_work, cw1200_unjoin_work);
 358         INIT_WORK(&priv->join_complete_work, cw1200_join_complete_work);
 359         INIT_WORK(&priv->wep_key_work, cw1200_wep_key_work);
 360         INIT_WORK(&priv->tx_policy_upload_work, tx_policy_upload_work);
 361         spin_lock_init(&priv->event_queue_lock);
 362         INIT_LIST_HEAD(&priv->event_queue);
 363         INIT_WORK(&priv->event_handler, cw1200_event_handler);
 364         INIT_DELAYED_WORK(&priv->bss_loss_work, cw1200_bss_loss_work);
 365         INIT_WORK(&priv->bss_params_work, cw1200_bss_params_work);
 366         spin_lock_init(&priv->bss_loss_lock);
 367         spin_lock_init(&priv->ps_state_lock);
 368         INIT_WORK(&priv->set_cts_work, cw1200_set_cts_work);
 369         INIT_WORK(&priv->set_tim_work, cw1200_set_tim_work);
 370         INIT_WORK(&priv->multicast_start_work, cw1200_multicast_start_work);
 371         INIT_WORK(&priv->multicast_stop_work, cw1200_multicast_stop_work);
 372         INIT_WORK(&priv->link_id_work, cw1200_link_id_work);
 373         INIT_DELAYED_WORK(&priv->link_id_gc_work, cw1200_link_id_gc_work);
 374         INIT_WORK(&priv->linkid_reset_work, cw1200_link_id_reset);
 375         INIT_WORK(&priv->update_filtering_work, cw1200_update_filtering_work);
 376         INIT_WORK(&priv->set_beacon_wakeup_period_work,
 377                   cw1200_set_beacon_wakeup_period_work);
 378         timer_setup(&priv->mcast_timeout, cw1200_mcast_timeout, 0);
 379 
 380         if (cw1200_queue_stats_init(&priv->tx_queue_stats,
 381                                     CW1200_LINK_ID_MAX,
 382                                     cw1200_skb_dtor,
 383                                     priv)) {
 384                 ieee80211_free_hw(hw);
 385                 return NULL;
 386         }
 387 
 388         for (i = 0; i < 4; ++i) {
 389                 if (cw1200_queue_init(&priv->tx_queue[i],
 390                                       &priv->tx_queue_stats, i, 16,
 391                                       cw1200_ttl[i])) {
 392                         for (; i > 0; i--)
 393                                 cw1200_queue_deinit(&priv->tx_queue[i - 1]);
 394                         cw1200_queue_stats_deinit(&priv->tx_queue_stats);
 395                         ieee80211_free_hw(hw);
 396                         return NULL;
 397                 }
 398         }
 399 
 400         init_waitqueue_head(&priv->channel_switch_done);
 401         init_waitqueue_head(&priv->wsm_cmd_wq);
 402         init_waitqueue_head(&priv->wsm_startup_done);
 403         init_waitqueue_head(&priv->ps_mode_switch_done);
 404         wsm_buf_init(&priv->wsm_cmd_buf);
 405         spin_lock_init(&priv->wsm_cmd.lock);
 406         priv->wsm_cmd.done = 1;
 407         tx_policy_init(priv);
 408 
 409         return hw;
 410 }
 411 
 412 static int cw1200_register_common(struct ieee80211_hw *dev)
 413 {
 414         struct cw1200_common *priv = dev->priv;
 415         int err;
 416 
 417 #ifdef CONFIG_PM
 418         err = cw1200_pm_init(&priv->pm_state, priv);
 419         if (err) {
 420                 pr_err("Cannot init PM. (%d).\n",
 421                        err);
 422                 return err;
 423         }
 424 #endif
 425 
 426         err = ieee80211_register_hw(dev);
 427         if (err) {
 428                 pr_err("Cannot register device (%d).\n",
 429                        err);
 430 #ifdef CONFIG_PM
 431                 cw1200_pm_deinit(&priv->pm_state);
 432 #endif
 433                 return err;
 434         }
 435 
 436         cw1200_debug_init(priv);
 437 
 438         pr_info("Registered as '%s'\n", wiphy_name(dev->wiphy));
 439         return 0;
 440 }
 441 
 442 static void cw1200_free_common(struct ieee80211_hw *dev)
 443 {
 444         ieee80211_free_hw(dev);
 445 }
 446 
 447 static void cw1200_unregister_common(struct ieee80211_hw *dev)
 448 {
 449         struct cw1200_common *priv = dev->priv;
 450         int i;
 451 
 452         ieee80211_unregister_hw(dev);
 453 
 454         del_timer_sync(&priv->mcast_timeout);
 455         cw1200_unregister_bh(priv);
 456 
 457         cw1200_debug_release(priv);
 458 
 459         mutex_destroy(&priv->conf_mutex);
 460 
 461         wsm_buf_deinit(&priv->wsm_cmd_buf);
 462 
 463         destroy_workqueue(priv->workqueue);
 464         priv->workqueue = NULL;
 465 
 466         if (priv->sdd) {
 467                 release_firmware(priv->sdd);
 468                 priv->sdd = NULL;
 469         }
 470 
 471         for (i = 0; i < 4; ++i)
 472                 cw1200_queue_deinit(&priv->tx_queue[i]);
 473 
 474         cw1200_queue_stats_deinit(&priv->tx_queue_stats);
 475 #ifdef CONFIG_PM
 476         cw1200_pm_deinit(&priv->pm_state);
 477 #endif
 478 }
 479 
 480 /* Clock is in KHz */
 481 u32 cw1200_dpll_from_clk(u16 clk_khz)
 482 {
 483         switch (clk_khz) {
 484         case 0x32C8: /* 13000 KHz */
 485                 return 0x1D89D241;
 486         case 0x3E80: /* 16000 KHz */
 487                 return 0x000001E1;
 488         case 0x41A0: /* 16800 KHz */
 489                 return 0x124931C1;
 490         case 0x4B00: /* 19200 KHz */
 491                 return 0x00000191;
 492         case 0x5DC0: /* 24000 KHz */
 493                 return 0x00000141;
 494         case 0x6590: /* 26000 KHz */
 495                 return 0x0EC4F121;
 496         case 0x8340: /* 33600 KHz */
 497                 return 0x092490E1;
 498         case 0x9600: /* 38400 KHz */
 499                 return 0x100010C1;
 500         case 0x9C40: /* 40000 KHz */
 501                 return 0x000000C1;
 502         case 0xBB80: /* 48000 KHz */
 503                 return 0x000000A1;
 504         case 0xCB20: /* 52000 KHz */
 505                 return 0x07627091;
 506         default:
 507                 pr_err("Unknown Refclk freq (0x%04x), using 26000KHz\n",
 508                        clk_khz);
 509                 return 0x0EC4F121;
 510         }
 511 }
 512 
 513 int cw1200_core_probe(const struct hwbus_ops *hwbus_ops,
 514                       struct hwbus_priv *hwbus,
 515                       struct device *pdev,
 516                       struct cw1200_common **core,
 517                       int ref_clk, const u8 *macaddr,
 518                       const char *sdd_path, bool have_5ghz)
 519 {
 520         int err = -EINVAL;
 521         struct ieee80211_hw *dev;
 522         struct cw1200_common *priv;
 523         struct wsm_operational_mode mode = {
 524                 .power_mode = cw1200_power_mode,
 525                 .disable_more_flag_usage = true,
 526         };
 527 
 528         dev = cw1200_init_common(macaddr, have_5ghz);
 529         if (!dev)
 530                 goto err;
 531 
 532         priv = dev->priv;
 533         priv->hw_refclk = ref_clk;
 534         if (cw1200_refclk)
 535                 priv->hw_refclk = cw1200_refclk;
 536 
 537         priv->sdd_path = (char *)sdd_path;
 538         if (cw1200_sdd_path)
 539                 priv->sdd_path = cw1200_sdd_path;
 540 
 541         priv->hwbus_ops = hwbus_ops;
 542         priv->hwbus_priv = hwbus;
 543         priv->pdev = pdev;
 544         SET_IEEE80211_DEV(priv->hw, pdev);
 545 
 546         /* Pass struct cw1200_common back up */
 547         *core = priv;
 548 
 549         err = cw1200_register_bh(priv);
 550         if (err)
 551                 goto err1;
 552 
 553         err = cw1200_load_firmware(priv);
 554         if (err)
 555                 goto err2;
 556 
 557         if (wait_event_interruptible_timeout(priv->wsm_startup_done,
 558                                              priv->firmware_ready,
 559                                              3*HZ) <= 0) {
 560                 /* TODO: Need to find how to reset device
 561                    in QUEUE mode properly.
 562                 */
 563                 pr_err("Timeout waiting on device startup\n");
 564                 err = -ETIMEDOUT;
 565                 goto err2;
 566         }
 567 
 568         /* Set low-power mode. */
 569         wsm_set_operational_mode(priv, &mode);
 570 
 571         /* Enable multi-TX confirmation */
 572         wsm_use_multi_tx_conf(priv, true);
 573 
 574         err = cw1200_register_common(dev);
 575         if (err)
 576                 goto err2;
 577 
 578         return err;
 579 
 580 err2:
 581         cw1200_unregister_bh(priv);
 582 err1:
 583         cw1200_free_common(dev);
 584 err:
 585         *core = NULL;
 586         return err;
 587 }
 588 EXPORT_SYMBOL_GPL(cw1200_core_probe);
 589 
 590 void cw1200_core_release(struct cw1200_common *self)
 591 {
 592         /* Disable device interrupts */
 593         self->hwbus_ops->lock(self->hwbus_priv);
 594         __cw1200_irq_enable(self, 0);
 595         self->hwbus_ops->unlock(self->hwbus_priv);
 596 
 597         /* And then clean up */
 598         cw1200_unregister_common(self->hw);
 599         cw1200_free_common(self->hw);
 600         return;
 601 }
 602 EXPORT_SYMBOL_GPL(cw1200_core_release);

/* [<][>][^][v][top][bottom][index][help] */