linux/drivers/net/wireless/ti/wl18xx/main.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * This file is part of wl18xx
   4 *
   5 * Copyright (C) 2011 Texas Instruments
   6 */
   7
   8#include <linux/module.h>
   9#include <linux/mod_devicetable.h>
  10#include <linux/platform_device.h>
  11#include <linux/ip.h>
  12#include <linux/firmware.h>
  13#include <linux/etherdevice.h>
  14#include <linux/irq.h>
  15
  16#include "../wlcore/wlcore.h"
  17#include "../wlcore/debug.h"
  18#include "../wlcore/io.h"
  19#include "../wlcore/acx.h"
  20#include "../wlcore/tx.h"
  21#include "../wlcore/rx.h"
  22#include "../wlcore/boot.h"
  23
  24#include "reg.h"
  25#include "conf.h"
  26#include "cmd.h"
  27#include "acx.h"
  28#include "tx.h"
  29#include "wl18xx.h"
  30#include "io.h"
  31#include "scan.h"
  32#include "event.h"
  33#include "debugfs.h"
  34
  35#define WL18XX_RX_CHECKSUM_MASK      0x40
  36
  37static char *ht_mode_param = NULL;
  38static char *board_type_param = NULL;
  39static bool checksum_param = false;
  40static int num_rx_desc_param = -1;
  41
  42/* phy paramters */
  43static int dc2dc_param = -1;
  44static int n_antennas_2_param = -1;
  45static int n_antennas_5_param = -1;
  46static int low_band_component_param = -1;
  47static int low_band_component_type_param = -1;
  48static int high_band_component_param = -1;
  49static int high_band_component_type_param = -1;
  50static int pwr_limit_reference_11_abg_param = -1;
  51
  52static const u8 wl18xx_rate_to_idx_2ghz[] = {
  53        /* MCS rates are used only with 11n */
  54        15,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS15 */
  55        14,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS14 */
  56        13,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS13 */
  57        12,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS12 */
  58        11,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS11 */
  59        10,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS10 */
  60        9,                             /* WL18XX_CONF_HW_RXTX_RATE_MCS9 */
  61        8,                             /* WL18XX_CONF_HW_RXTX_RATE_MCS8 */
  62        7,                             /* WL18XX_CONF_HW_RXTX_RATE_MCS7 */
  63        6,                             /* WL18XX_CONF_HW_RXTX_RATE_MCS6 */
  64        5,                             /* WL18XX_CONF_HW_RXTX_RATE_MCS5 */
  65        4,                             /* WL18XX_CONF_HW_RXTX_RATE_MCS4 */
  66        3,                             /* WL18XX_CONF_HW_RXTX_RATE_MCS3 */
  67        2,                             /* WL18XX_CONF_HW_RXTX_RATE_MCS2 */
  68        1,                             /* WL18XX_CONF_HW_RXTX_RATE_MCS1 */
  69        0,                             /* WL18XX_CONF_HW_RXTX_RATE_MCS0 */
  70
  71        11,                            /* WL18XX_CONF_HW_RXTX_RATE_54   */
  72        10,                            /* WL18XX_CONF_HW_RXTX_RATE_48   */
  73        9,                             /* WL18XX_CONF_HW_RXTX_RATE_36   */
  74        8,                             /* WL18XX_CONF_HW_RXTX_RATE_24   */
  75
  76        /* TI-specific rate */
  77        CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_22   */
  78
  79        7,                             /* WL18XX_CONF_HW_RXTX_RATE_18   */
  80        6,                             /* WL18XX_CONF_HW_RXTX_RATE_12   */
  81        3,                             /* WL18XX_CONF_HW_RXTX_RATE_11   */
  82        5,                             /* WL18XX_CONF_HW_RXTX_RATE_9    */
  83        4,                             /* WL18XX_CONF_HW_RXTX_RATE_6    */
  84        2,                             /* WL18XX_CONF_HW_RXTX_RATE_5_5  */
  85        1,                             /* WL18XX_CONF_HW_RXTX_RATE_2    */
  86        0                              /* WL18XX_CONF_HW_RXTX_RATE_1    */
  87};
  88
  89static const u8 wl18xx_rate_to_idx_5ghz[] = {
  90        /* MCS rates are used only with 11n */
  91        15,                           /* WL18XX_CONF_HW_RXTX_RATE_MCS15 */
  92        14,                           /* WL18XX_CONF_HW_RXTX_RATE_MCS14 */
  93        13,                           /* WL18XX_CONF_HW_RXTX_RATE_MCS13 */
  94        12,                           /* WL18XX_CONF_HW_RXTX_RATE_MCS12 */
  95        11,                           /* WL18XX_CONF_HW_RXTX_RATE_MCS11 */
  96        10,                           /* WL18XX_CONF_HW_RXTX_RATE_MCS10 */
  97        9,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS9 */
  98        8,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS8 */
  99        7,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS7 */
 100        6,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS6 */
 101        5,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS5 */
 102        4,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS4 */
 103        3,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS3 */
 104        2,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS2 */
 105        1,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS1 */
 106        0,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS0 */
 107
 108        7,                             /* WL18XX_CONF_HW_RXTX_RATE_54   */
 109        6,                             /* WL18XX_CONF_HW_RXTX_RATE_48   */
 110        5,                             /* WL18XX_CONF_HW_RXTX_RATE_36   */
 111        4,                             /* WL18XX_CONF_HW_RXTX_RATE_24   */
 112
 113        /* TI-specific rate */
 114        CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_22   */
 115
 116        3,                             /* WL18XX_CONF_HW_RXTX_RATE_18   */
 117        2,                             /* WL18XX_CONF_HW_RXTX_RATE_12   */
 118        CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_11   */
 119        1,                             /* WL18XX_CONF_HW_RXTX_RATE_9    */
 120        0,                             /* WL18XX_CONF_HW_RXTX_RATE_6    */
 121        CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_5_5  */
 122        CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_2    */
 123        CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_1    */
 124};
 125
 126static const u8 *wl18xx_band_rate_to_idx[] = {
 127        [NL80211_BAND_2GHZ] = wl18xx_rate_to_idx_2ghz,
 128        [NL80211_BAND_5GHZ] = wl18xx_rate_to_idx_5ghz
 129};
 130
 131enum wl18xx_hw_rates {
 132        WL18XX_CONF_HW_RXTX_RATE_MCS15 = 0,
 133        WL18XX_CONF_HW_RXTX_RATE_MCS14,
 134        WL18XX_CONF_HW_RXTX_RATE_MCS13,
 135        WL18XX_CONF_HW_RXTX_RATE_MCS12,
 136        WL18XX_CONF_HW_RXTX_RATE_MCS11,
 137        WL18XX_CONF_HW_RXTX_RATE_MCS10,
 138        WL18XX_CONF_HW_RXTX_RATE_MCS9,
 139        WL18XX_CONF_HW_RXTX_RATE_MCS8,
 140        WL18XX_CONF_HW_RXTX_RATE_MCS7,
 141        WL18XX_CONF_HW_RXTX_RATE_MCS6,
 142        WL18XX_CONF_HW_RXTX_RATE_MCS5,
 143        WL18XX_CONF_HW_RXTX_RATE_MCS4,
 144        WL18XX_CONF_HW_RXTX_RATE_MCS3,
 145        WL18XX_CONF_HW_RXTX_RATE_MCS2,
 146        WL18XX_CONF_HW_RXTX_RATE_MCS1,
 147        WL18XX_CONF_HW_RXTX_RATE_MCS0,
 148        WL18XX_CONF_HW_RXTX_RATE_54,
 149        WL18XX_CONF_HW_RXTX_RATE_48,
 150        WL18XX_CONF_HW_RXTX_RATE_36,
 151        WL18XX_CONF_HW_RXTX_RATE_24,
 152        WL18XX_CONF_HW_RXTX_RATE_22,
 153        WL18XX_CONF_HW_RXTX_RATE_18,
 154        WL18XX_CONF_HW_RXTX_RATE_12,
 155        WL18XX_CONF_HW_RXTX_RATE_11,
 156        WL18XX_CONF_HW_RXTX_RATE_9,
 157        WL18XX_CONF_HW_RXTX_RATE_6,
 158        WL18XX_CONF_HW_RXTX_RATE_5_5,
 159        WL18XX_CONF_HW_RXTX_RATE_2,
 160        WL18XX_CONF_HW_RXTX_RATE_1,
 161        WL18XX_CONF_HW_RXTX_RATE_MAX,
 162};
 163
 164static struct wlcore_conf wl18xx_conf = {
 165        .sg = {
 166                .params = {
 167                        [WL18XX_CONF_SG_PARAM_0] = 0,
 168                        /* Configuration Parameters */
 169                        [WL18XX_CONF_SG_ANTENNA_CONFIGURATION] = 0,
 170                        [WL18XX_CONF_SG_ZIGBEE_COEX] = 0,
 171                        [WL18XX_CONF_SG_TIME_SYNC] = 0,
 172                        [WL18XX_CONF_SG_PARAM_4] = 0,
 173                        [WL18XX_CONF_SG_PARAM_5] = 0,
 174                        [WL18XX_CONF_SG_PARAM_6] = 0,
 175                        [WL18XX_CONF_SG_PARAM_7] = 0,
 176                        [WL18XX_CONF_SG_PARAM_8] = 0,
 177                        [WL18XX_CONF_SG_PARAM_9] = 0,
 178                        [WL18XX_CONF_SG_PARAM_10] = 0,
 179                        [WL18XX_CONF_SG_PARAM_11] = 0,
 180                        [WL18XX_CONF_SG_PARAM_12] = 0,
 181                        [WL18XX_CONF_SG_PARAM_13] = 0,
 182                        [WL18XX_CONF_SG_PARAM_14] = 0,
 183                        [WL18XX_CONF_SG_PARAM_15] = 0,
 184                        [WL18XX_CONF_SG_PARAM_16] = 0,
 185                        [WL18XX_CONF_SG_PARAM_17] = 0,
 186                        [WL18XX_CONF_SG_PARAM_18] = 0,
 187                        [WL18XX_CONF_SG_PARAM_19] = 0,
 188                        [WL18XX_CONF_SG_PARAM_20] = 0,
 189                        [WL18XX_CONF_SG_PARAM_21] = 0,
 190                        [WL18XX_CONF_SG_PARAM_22] = 0,
 191                        [WL18XX_CONF_SG_PARAM_23] = 0,
 192                        [WL18XX_CONF_SG_PARAM_24] = 0,
 193                        [WL18XX_CONF_SG_PARAM_25] = 0,
 194                        /* Active Scan Parameters */
 195                        [WL18XX_CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
 196                        [WL18XX_CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
 197                        [WL18XX_CONF_SG_PARAM_28] = 0,
 198                        /* Passive Scan Parameters */
 199                        [WL18XX_CONF_SG_PARAM_29] = 0,
 200                        [WL18XX_CONF_SG_PARAM_30] = 0,
 201                        [WL18XX_CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200,
 202                        /* Passive Scan in Dual Antenna Parameters */
 203                        [WL18XX_CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN] = 0,
 204                        [WL18XX_CONF_SG_BEACON_HV3_COLL_TH_IN_PASSIVE_SCAN] = 0,
 205                        [WL18XX_CONF_SG_TX_RX_PROTECT_BW_IN_PASSIVE_SCAN] = 0,
 206                        /* General Parameters */
 207                        [WL18XX_CONF_SG_STA_FORCE_PS_IN_BT_SCO] = 1,
 208                        [WL18XX_CONF_SG_PARAM_36] = 0,
 209                        [WL18XX_CONF_SG_BEACON_MISS_PERCENT] = 60,
 210                        [WL18XX_CONF_SG_PARAM_38] = 0,
 211                        [WL18XX_CONF_SG_RXT] = 1200,
 212                        [WL18XX_CONF_SG_UNUSED] = 0,
 213                        [WL18XX_CONF_SG_ADAPTIVE_RXT_TXT] = 1,
 214                        [WL18XX_CONF_SG_GENERAL_USAGE_BIT_MAP] = 3,
 215                        [WL18XX_CONF_SG_HV3_MAX_SERVED] = 6,
 216                        [WL18XX_CONF_SG_PARAM_44] = 0,
 217                        [WL18XX_CONF_SG_PARAM_45] = 0,
 218                        [WL18XX_CONF_SG_CONSECUTIVE_CTS_THRESHOLD] = 2,
 219                        [WL18XX_CONF_SG_GEMINI_PARAM_47] = 0,
 220                        [WL18XX_CONF_SG_STA_CONNECTION_PROTECTION_TIME] = 0,
 221                        /* AP Parameters */
 222                        [WL18XX_CONF_SG_AP_BEACON_MISS_TX] = 3,
 223                        [WL18XX_CONF_SG_PARAM_50] = 0,
 224                        [WL18XX_CONF_SG_AP_BEACON_WINDOW_INTERVAL] = 2,
 225                        [WL18XX_CONF_SG_AP_CONNECTION_PROTECTION_TIME] = 30,
 226                        [WL18XX_CONF_SG_PARAM_53] = 0,
 227                        [WL18XX_CONF_SG_PARAM_54] = 0,
 228                        /* CTS Diluting Parameters */
 229                        [WL18XX_CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH] = 0,
 230                        [WL18XX_CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER] = 0,
 231                        [WL18XX_CONF_SG_TEMP_PARAM_1] = 0,
 232                        [WL18XX_CONF_SG_TEMP_PARAM_2] = 0,
 233                        [WL18XX_CONF_SG_TEMP_PARAM_3] = 0,
 234                        [WL18XX_CONF_SG_TEMP_PARAM_4] = 0,
 235                        [WL18XX_CONF_SG_TEMP_PARAM_5] = 0,
 236                        [WL18XX_CONF_SG_TEMP_PARAM_6] = 0,
 237                        [WL18XX_CONF_SG_TEMP_PARAM_7] = 0,
 238                        [WL18XX_CONF_SG_TEMP_PARAM_8] = 0,
 239                        [WL18XX_CONF_SG_TEMP_PARAM_9] = 0,
 240                        [WL18XX_CONF_SG_TEMP_PARAM_10] = 0,
 241                },
 242                .state = CONF_SG_PROTECTIVE,
 243        },
 244        .rx = {
 245                .rx_msdu_life_time           = 512000,
 246                .packet_detection_threshold  = 0,
 247                .ps_poll_timeout             = 15,
 248                .upsd_timeout                = 15,
 249                .rts_threshold               = IEEE80211_MAX_RTS_THRESHOLD,
 250                .rx_cca_threshold            = 0,
 251                .irq_blk_threshold           = 0xFFFF,
 252                .irq_pkt_threshold           = 0,
 253                .irq_timeout                 = 600,
 254                .queue_type                  = CONF_RX_QUEUE_TYPE_LOW_PRIORITY,
 255        },
 256        .tx = {
 257                .tx_energy_detection         = 0,
 258                .sta_rc_conf                 = {
 259                        .enabled_rates       = 0,
 260                        .short_retry_limit   = 10,
 261                        .long_retry_limit    = 10,
 262                        .aflags              = 0,
 263                },
 264                .ac_conf_count               = 4,
 265                .ac_conf                     = {
 266                        [CONF_TX_AC_BE] = {
 267                                .ac          = CONF_TX_AC_BE,
 268                                .cw_min      = 15,
 269                                .cw_max      = 63,
 270                                .aifsn       = 3,
 271                                .tx_op_limit = 0,
 272                        },
 273                        [CONF_TX_AC_BK] = {
 274                                .ac          = CONF_TX_AC_BK,
 275                                .cw_min      = 15,
 276                                .cw_max      = 63,
 277                                .aifsn       = 7,
 278                                .tx_op_limit = 0,
 279                        },
 280                        [CONF_TX_AC_VI] = {
 281                                .ac          = CONF_TX_AC_VI,
 282                                .cw_min      = 15,
 283                                .cw_max      = 63,
 284                                .aifsn       = CONF_TX_AIFS_PIFS,
 285                                .tx_op_limit = 3008,
 286                        },
 287                        [CONF_TX_AC_VO] = {
 288                                .ac          = CONF_TX_AC_VO,
 289                                .cw_min      = 15,
 290                                .cw_max      = 63,
 291                                .aifsn       = CONF_TX_AIFS_PIFS,
 292                                .tx_op_limit = 1504,
 293                        },
 294                },
 295                .max_tx_retries = 100,
 296                .ap_aging_period = 300,
 297                .tid_conf_count = 4,
 298                .tid_conf = {
 299                        [CONF_TX_AC_BE] = {
 300                                .queue_id    = CONF_TX_AC_BE,
 301                                .channel_type = CONF_CHANNEL_TYPE_EDCF,
 302                                .tsid        = CONF_TX_AC_BE,
 303                                .ps_scheme   = CONF_PS_SCHEME_LEGACY,
 304                                .ack_policy  = CONF_ACK_POLICY_LEGACY,
 305                                .apsd_conf   = {0, 0},
 306                        },
 307                        [CONF_TX_AC_BK] = {
 308                                .queue_id    = CONF_TX_AC_BK,
 309                                .channel_type = CONF_CHANNEL_TYPE_EDCF,
 310                                .tsid        = CONF_TX_AC_BK,
 311                                .ps_scheme   = CONF_PS_SCHEME_LEGACY,
 312                                .ack_policy  = CONF_ACK_POLICY_LEGACY,
 313                                .apsd_conf   = {0, 0},
 314                        },
 315                        [CONF_TX_AC_VI] = {
 316                                .queue_id    = CONF_TX_AC_VI,
 317                                .channel_type = CONF_CHANNEL_TYPE_EDCF,
 318                                .tsid        = CONF_TX_AC_VI,
 319                                .ps_scheme   = CONF_PS_SCHEME_LEGACY,
 320                                .ack_policy  = CONF_ACK_POLICY_LEGACY,
 321                                .apsd_conf   = {0, 0},
 322                        },
 323                        [CONF_TX_AC_VO] = {
 324                                .queue_id    = CONF_TX_AC_VO,
 325                                .channel_type = CONF_CHANNEL_TYPE_EDCF,
 326                                .tsid        = CONF_TX_AC_VO,
 327                                .ps_scheme   = CONF_PS_SCHEME_LEGACY,
 328                                .ack_policy  = CONF_ACK_POLICY_LEGACY,
 329                                .apsd_conf   = {0, 0},
 330                        },
 331                },
 332                .frag_threshold              = IEEE80211_MAX_FRAG_THRESHOLD,
 333                .tx_compl_timeout            = 350,
 334                .tx_compl_threshold          = 10,
 335                .basic_rate                  = CONF_HW_BIT_RATE_1MBPS,
 336                .basic_rate_5                = CONF_HW_BIT_RATE_6MBPS,
 337                .tmpl_short_retry_limit      = 10,
 338                .tmpl_long_retry_limit       = 10,
 339                .tx_watchdog_timeout         = 5000,
 340                .slow_link_thold             = 3,
 341                .fast_link_thold             = 30,
 342        },
 343        .conn = {
 344                .wake_up_event               = CONF_WAKE_UP_EVENT_DTIM,
 345                .listen_interval             = 1,
 346                .suspend_wake_up_event       = CONF_WAKE_UP_EVENT_N_DTIM,
 347                .suspend_listen_interval     = 3,
 348                .bcn_filt_mode               = CONF_BCN_FILT_MODE_ENABLED,
 349                .bcn_filt_ie_count           = 3,
 350                .bcn_filt_ie = {
 351                        [0] = {
 352                                .ie          = WLAN_EID_CHANNEL_SWITCH,
 353                                .rule        = CONF_BCN_RULE_PASS_ON_APPEARANCE,
 354                        },
 355                        [1] = {
 356                                .ie          = WLAN_EID_HT_OPERATION,
 357                                .rule        = CONF_BCN_RULE_PASS_ON_CHANGE,
 358                        },
 359                        [2] = {
 360                                .ie          = WLAN_EID_ERP_INFO,
 361                                .rule        = CONF_BCN_RULE_PASS_ON_CHANGE,
 362                        },
 363                },
 364                .synch_fail_thold            = 12,
 365                .bss_lose_timeout            = 400,
 366                .beacon_rx_timeout           = 10000,
 367                .broadcast_timeout           = 20000,
 368                .rx_broadcast_in_ps          = 1,
 369                .ps_poll_threshold           = 10,
 370                .bet_enable                  = CONF_BET_MODE_ENABLE,
 371                .bet_max_consecutive         = 50,
 372                .psm_entry_retries           = 8,
 373                .psm_exit_retries            = 16,
 374                .psm_entry_nullfunc_retries  = 3,
 375                .dynamic_ps_timeout          = 1500,
 376                .forced_ps                   = false,
 377                .keep_alive_interval         = 55000,
 378                .max_listen_interval         = 20,
 379                .sta_sleep_auth              = WL1271_PSM_ILLEGAL,
 380                .suspend_rx_ba_activity      = 0,
 381        },
 382        .itrim = {
 383                .enable = false,
 384                .timeout = 50000,
 385        },
 386        .pm_config = {
 387                .host_clk_settling_time = 5000,
 388                .host_fast_wakeup_support = CONF_FAST_WAKEUP_DISABLE,
 389        },
 390        .roam_trigger = {
 391                .trigger_pacing               = 1,
 392                .avg_weight_rssi_beacon       = 20,
 393                .avg_weight_rssi_data         = 10,
 394                .avg_weight_snr_beacon        = 20,
 395                .avg_weight_snr_data          = 10,
 396        },
 397        .scan = {
 398                .min_dwell_time_active        = 7500,
 399                .max_dwell_time_active        = 30000,
 400                .min_dwell_time_active_long   = 25000,
 401                .max_dwell_time_active_long   = 50000,
 402                .dwell_time_passive           = 100000,
 403                .dwell_time_dfs               = 150000,
 404                .num_probe_reqs               = 2,
 405                .split_scan_timeout           = 50000,
 406        },
 407        .sched_scan = {
 408                /*
 409                 * Values are in TU/1000 but since sched scan FW command
 410                 * params are in TUs rounding up may occur.
 411                 */
 412                .base_dwell_time                = 7500,
 413                .max_dwell_time_delta           = 22500,
 414                /* based on 250bits per probe @1Mbps */
 415                .dwell_time_delta_per_probe     = 2000,
 416                /* based on 250bits per probe @6Mbps (plus a bit more) */
 417                .dwell_time_delta_per_probe_5   = 350,
 418                .dwell_time_passive             = 100000,
 419                .dwell_time_dfs                 = 150000,
 420                .num_probe_reqs                 = 2,
 421                .rssi_threshold                 = -90,
 422                .snr_threshold                  = 0,
 423                .num_short_intervals            = SCAN_MAX_SHORT_INTERVALS,
 424                .long_interval                  = 30000,
 425        },
 426        .ht = {
 427                .rx_ba_win_size = 32,
 428                .tx_ba_win_size = 64,
 429                .inactivity_timeout = 10000,
 430                .tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP,
 431        },
 432        .mem = {
 433                .num_stations                 = 1,
 434                .ssid_profiles                = 1,
 435                .rx_block_num                 = 40,
 436                .tx_min_block_num             = 40,
 437                .dynamic_memory               = 1,
 438                .min_req_tx_blocks            = 45,
 439                .min_req_rx_blocks            = 22,
 440                .tx_min                       = 27,
 441        },
 442        .fm_coex = {
 443                .enable                       = true,
 444                .swallow_period               = 5,
 445                .n_divider_fref_set_1         = 0xff,       /* default */
 446                .n_divider_fref_set_2         = 12,
 447                .m_divider_fref_set_1         = 0xffff,
 448                .m_divider_fref_set_2         = 148,        /* default */
 449                .coex_pll_stabilization_time  = 0xffffffff, /* default */
 450                .ldo_stabilization_time       = 0xffff,     /* default */
 451                .fm_disturbed_band_margin     = 0xff,       /* default */
 452                .swallow_clk_diff             = 0xff,       /* default */
 453        },
 454        .rx_streaming = {
 455                .duration                      = 150,
 456                .queues                        = 0x1,
 457                .interval                      = 20,
 458                .always                        = 0,
 459        },
 460        .fwlog = {
 461                .mode                         = WL12XX_FWLOG_CONTINUOUS,
 462                .mem_blocks                   = 0,
 463                .severity                     = 0,
 464                .timestamp                    = WL12XX_FWLOG_TIMESTAMP_DISABLED,
 465                .output                       = WL12XX_FWLOG_OUTPUT_DBG_PINS,
 466                .threshold                    = 0,
 467        },
 468        .rate = {
 469                .rate_retry_score = 32000,
 470                .per_add = 8192,
 471                .per_th1 = 2048,
 472                .per_th2 = 4096,
 473                .max_per = 8100,
 474                .inverse_curiosity_factor = 5,
 475                .tx_fail_low_th = 4,
 476                .tx_fail_high_th = 10,
 477                .per_alpha_shift = 4,
 478                .per_add_shift = 13,
 479                .per_beta1_shift = 10,
 480                .per_beta2_shift = 8,
 481                .rate_check_up = 2,
 482                .rate_check_down = 12,
 483                .rate_retry_policy = {
 484                        0x00, 0x00, 0x00, 0x00, 0x00,
 485                        0x00, 0x00, 0x00, 0x00, 0x00,
 486                        0x00, 0x00, 0x00,
 487                },
 488        },
 489        .hangover = {
 490                .recover_time               = 0,
 491                .hangover_period            = 20,
 492                .dynamic_mode               = 1,
 493                .early_termination_mode     = 1,
 494                .max_period                 = 20,
 495                .min_period                 = 1,
 496                .increase_delta             = 1,
 497                .decrease_delta             = 2,
 498                .quiet_time                 = 4,
 499                .increase_time              = 1,
 500                .window_size                = 16,
 501        },
 502        .recovery = {
 503                .bug_on_recovery            = 0,
 504                .no_recovery                = 0,
 505        },
 506};
 507
 508static struct wl18xx_priv_conf wl18xx_default_priv_conf = {
 509        .ht = {
 510                .mode                           = HT_MODE_WIDE,
 511        },
 512        .phy = {
 513                .phy_standalone                 = 0x00,
 514                .primary_clock_setting_time     = 0x05,
 515                .clock_valid_on_wake_up         = 0x00,
 516                .secondary_clock_setting_time   = 0x05,
 517                .board_type                     = BOARD_TYPE_HDK_18XX,
 518                .auto_detect                    = 0x00,
 519                .dedicated_fem                  = FEM_NONE,
 520                .low_band_component             = COMPONENT_3_WAY_SWITCH,
 521                .low_band_component_type        = 0x05,
 522                .high_band_component            = COMPONENT_2_WAY_SWITCH,
 523                .high_band_component_type       = 0x09,
 524                .tcxo_ldo_voltage               = 0x00,
 525                .xtal_itrim_val                 = 0x04,
 526                .srf_state                      = 0x00,
 527                .io_configuration               = 0x01,
 528                .sdio_configuration             = 0x00,
 529                .settings                       = 0x00,
 530                .enable_clpc                    = 0x00,
 531                .enable_tx_low_pwr_on_siso_rdl  = 0x00,
 532                .rx_profile                     = 0x00,
 533                .pwr_limit_reference_11_abg     = 0x64,
 534                .per_chan_pwr_limit_arr_11abg   = {
 535                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 536                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 537                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 538                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 539                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 540                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 541                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 542                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 543                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 544                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 545                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 546                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 547                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 548                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 549                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 550                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 551                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
 552                .pwr_limit_reference_11p        = 0x64,
 553                .per_chan_bo_mode_11_abg        = { 0x00, 0x00, 0x00, 0x00,
 554                                                    0x00, 0x00, 0x00, 0x00,
 555                                                    0x00, 0x00, 0x00, 0x00,
 556                                                    0x00 },
 557                .per_chan_bo_mode_11_p          = { 0x00, 0x00, 0x00, 0x00 },
 558                .per_chan_pwr_limit_arr_11p     = { 0xff, 0xff, 0xff, 0xff,
 559                                                    0xff, 0xff, 0xff },
 560                .psat                           = 0,
 561                .external_pa_dc2dc              = 0,
 562                .number_of_assembled_ant2_4     = 2,
 563                .number_of_assembled_ant5       = 1,
 564                .low_power_val                  = 0xff,
 565                .med_power_val                  = 0xff,
 566                .high_power_val                 = 0xff,
 567                .low_power_val_2nd              = 0xff,
 568                .med_power_val_2nd              = 0xff,
 569                .high_power_val_2nd             = 0xff,
 570                .tx_rf_margin                   = 1,
 571        },
 572        .ap_sleep = {               /* disabled by default */
 573                .idle_duty_cycle        = 0,
 574                .connected_duty_cycle   = 0,
 575                .max_stations_thresh    = 0,
 576                .idle_conn_thresh       = 0,
 577        },
 578};
 579
 580static const struct wlcore_partition_set wl18xx_ptable[PART_TABLE_LEN] = {
 581        [PART_TOP_PRCM_ELP_SOC] = {
 582                .mem  = { .start = 0x00A00000, .size  = 0x00012000 },
 583                .reg  = { .start = 0x00807000, .size  = 0x00005000 },
 584                .mem2 = { .start = 0x00800000, .size  = 0x0000B000 },
 585                .mem3 = { .start = 0x00401594, .size  = 0x00001020 },
 586        },
 587        [PART_DOWN] = {
 588                .mem  = { .start = 0x00000000, .size  = 0x00014000 },
 589                .reg  = { .start = 0x00810000, .size  = 0x0000BFFF },
 590                .mem2 = { .start = 0x00000000, .size  = 0x00000000 },
 591                .mem3 = { .start = 0x00000000, .size  = 0x00000000 },
 592        },
 593        [PART_BOOT] = {
 594                .mem  = { .start = 0x00700000, .size = 0x0000030c },
 595                .reg  = { .start = 0x00802000, .size = 0x00014578 },
 596                .mem2 = { .start = 0x00B00404, .size = 0x00001000 },
 597                .mem3 = { .start = 0x00C00000, .size = 0x00000400 },
 598        },
 599        [PART_WORK] = {
 600                .mem  = { .start = 0x00800000, .size  = 0x000050FC },
 601                .reg  = { .start = 0x00B00404, .size  = 0x00001000 },
 602                .mem2 = { .start = 0x00C00000, .size  = 0x00000400 },
 603                .mem3 = { .start = 0x00401594, .size  = 0x00001020 },
 604        },
 605        [PART_PHY_INIT] = {
 606                .mem  = { .start = WL18XX_PHY_INIT_MEM_ADDR,
 607                          .size  = WL18XX_PHY_INIT_MEM_SIZE },
 608                .reg  = { .start = 0x00000000, .size = 0x00000000 },
 609                .mem2 = { .start = 0x00000000, .size = 0x00000000 },
 610                .mem3 = { .start = 0x00000000, .size = 0x00000000 },
 611        },
 612};
 613
 614static const int wl18xx_rtable[REG_TABLE_LEN] = {
 615        [REG_ECPU_CONTROL]              = WL18XX_REG_ECPU_CONTROL,
 616        [REG_INTERRUPT_NO_CLEAR]        = WL18XX_REG_INTERRUPT_NO_CLEAR,
 617        [REG_INTERRUPT_ACK]             = WL18XX_REG_INTERRUPT_ACK,
 618        [REG_COMMAND_MAILBOX_PTR]       = WL18XX_REG_COMMAND_MAILBOX_PTR,
 619        [REG_EVENT_MAILBOX_PTR]         = WL18XX_REG_EVENT_MAILBOX_PTR,
 620        [REG_INTERRUPT_TRIG]            = WL18XX_REG_INTERRUPT_TRIG_H,
 621        [REG_INTERRUPT_MASK]            = WL18XX_REG_INTERRUPT_MASK,
 622        [REG_PC_ON_RECOVERY]            = WL18XX_SCR_PAD4,
 623        [REG_CHIP_ID_B]                 = WL18XX_REG_CHIP_ID_B,
 624        [REG_CMD_MBOX_ADDRESS]          = WL18XX_CMD_MBOX_ADDRESS,
 625
 626        /* data access memory addresses, used with partition translation */
 627        [REG_SLV_MEM_DATA]              = WL18XX_SLV_MEM_DATA,
 628        [REG_SLV_REG_DATA]              = WL18XX_SLV_REG_DATA,
 629
 630        /* raw data access memory addresses */
 631        [REG_RAW_FW_STATUS_ADDR]        = WL18XX_FW_STATUS_ADDR,
 632};
 633
 634static const struct wl18xx_clk_cfg wl18xx_clk_table_coex[NUM_CLOCK_CONFIGS] = {
 635        [CLOCK_CONFIG_16_2_M]   = { 8,  121, 0, 0, false },
 636        [CLOCK_CONFIG_16_368_M] = { 8,  120, 0, 0, false },
 637        [CLOCK_CONFIG_16_8_M]   = { 8,  117, 0, 0, false },
 638        [CLOCK_CONFIG_19_2_M]   = { 10, 128, 0, 0, false },
 639        [CLOCK_CONFIG_26_M]     = { 11, 104, 0, 0, false },
 640        [CLOCK_CONFIG_32_736_M] = { 8,  120, 0, 0, false },
 641        [CLOCK_CONFIG_33_6_M]   = { 8,  117, 0, 0, false },
 642        [CLOCK_CONFIG_38_468_M] = { 10, 128, 0, 0, false },
 643        [CLOCK_CONFIG_52_M]     = { 11, 104, 0, 0, false },
 644};
 645
 646static const struct wl18xx_clk_cfg wl18xx_clk_table[NUM_CLOCK_CONFIGS] = {
 647        [CLOCK_CONFIG_16_2_M]   = { 7,  104,  801, 4,  true },
 648        [CLOCK_CONFIG_16_368_M] = { 9,  132, 3751, 4,  true },
 649        [CLOCK_CONFIG_16_8_M]   = { 7,  100,    0, 0, false },
 650        [CLOCK_CONFIG_19_2_M]   = { 8,  100,    0, 0, false },
 651        [CLOCK_CONFIG_26_M]     = { 13, 120,    0, 0, false },
 652        [CLOCK_CONFIG_32_736_M] = { 9,  132, 3751, 4,  true },
 653        [CLOCK_CONFIG_33_6_M]   = { 7,  100,    0, 0, false },
 654        [CLOCK_CONFIG_38_468_M] = { 8,  100,    0, 0, false },
 655        [CLOCK_CONFIG_52_M]     = { 13, 120,    0, 0, false },
 656};
 657
 658/* TODO: maybe move to a new header file? */
 659#define WL18XX_FW_NAME "ti-connectivity/wl18xx-fw-4.bin"
 660
 661static int wl18xx_identify_chip(struct wl1271 *wl)
 662{
 663        int ret = 0;
 664
 665        switch (wl->chip.id) {
 666        case CHIP_ID_185x_PG20:
 667                wl1271_debug(DEBUG_BOOT, "chip id 0x%x (185x PG20)",
 668                                 wl->chip.id);
 669                wl->sr_fw_name = WL18XX_FW_NAME;
 670                /* wl18xx uses the same firmware for PLT */
 671                wl->plt_fw_name = WL18XX_FW_NAME;
 672                wl->quirks |= WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN |
 673                              WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN |
 674                              WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN |
 675                              WLCORE_QUIRK_TX_PAD_LAST_FRAME |
 676                              WLCORE_QUIRK_REGDOMAIN_CONF |
 677                              WLCORE_QUIRK_DUAL_PROBE_TMPL;
 678
 679                wlcore_set_min_fw_ver(wl, WL18XX_CHIP_VER,
 680                                      WL18XX_IFTYPE_VER,  WL18XX_MAJOR_VER,
 681                                      WL18XX_SUBTYPE_VER, WL18XX_MINOR_VER,
 682                                      /* there's no separate multi-role FW */
 683                                      0, 0, 0, 0);
 684                break;
 685        case CHIP_ID_185x_PG10:
 686                wl1271_warning("chip id 0x%x (185x PG10) is deprecated",
 687                               wl->chip.id);
 688                ret = -ENODEV;
 689                goto out;
 690
 691        default:
 692                wl1271_warning("unsupported chip id: 0x%x", wl->chip.id);
 693                ret = -ENODEV;
 694                goto out;
 695        }
 696
 697        wl->fw_mem_block_size = 272;
 698        wl->fwlog_end = 0x40000000;
 699
 700        wl->scan_templ_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4;
 701        wl->scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5;
 702        wl->sched_scan_templ_id_2_4 = CMD_TEMPL_PROBE_REQ_2_4_PERIODIC;
 703        wl->sched_scan_templ_id_5 = CMD_TEMPL_PROBE_REQ_5_PERIODIC;
 704        wl->max_channels_5 = WL18XX_MAX_CHANNELS_5GHZ;
 705        wl->ba_rx_session_count_max = WL18XX_RX_BA_MAX_SESSIONS;
 706out:
 707        return ret;
 708}
 709
 710static int wl18xx_set_clk(struct wl1271 *wl)
 711{
 712        u16 clk_freq;
 713        int ret;
 714
 715        ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
 716        if (ret < 0)
 717                goto out;
 718
 719        /* TODO: PG2: apparently we need to read the clk type */
 720
 721        ret = wl18xx_top_reg_read(wl, PRIMARY_CLK_DETECT, &clk_freq);
 722        if (ret < 0)
 723                goto out;
 724
 725        wl1271_debug(DEBUG_BOOT, "clock freq %d (%d, %d, %d, %d, %s)", clk_freq,
 726                     wl18xx_clk_table[clk_freq].n, wl18xx_clk_table[clk_freq].m,
 727                     wl18xx_clk_table[clk_freq].p, wl18xx_clk_table[clk_freq].q,
 728                     wl18xx_clk_table[clk_freq].swallow ? "swallow" : "spit");
 729
 730        /* coex PLL configuration */
 731        ret = wl18xx_top_reg_write(wl, PLLSH_COEX_PLL_N,
 732                                   wl18xx_clk_table_coex[clk_freq].n);
 733        if (ret < 0)
 734                goto out;
 735
 736        ret = wl18xx_top_reg_write(wl, PLLSH_COEX_PLL_M,
 737                                   wl18xx_clk_table_coex[clk_freq].m);
 738        if (ret < 0)
 739                goto out;
 740
 741        /* bypass the swallowing logic */
 742        ret = wl18xx_top_reg_write(wl, PLLSH_COEX_PLL_SWALLOW_EN,
 743                                   PLLSH_COEX_PLL_SWALLOW_EN_VAL1);
 744        if (ret < 0)
 745                goto out;
 746
 747        ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_N,
 748                                   wl18xx_clk_table[clk_freq].n);
 749        if (ret < 0)
 750                goto out;
 751
 752        ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_M,
 753                                   wl18xx_clk_table[clk_freq].m);
 754        if (ret < 0)
 755                goto out;
 756
 757        if (wl18xx_clk_table[clk_freq].swallow) {
 758                /* first the 16 lower bits */
 759                ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_1,
 760                                           wl18xx_clk_table[clk_freq].q &
 761                                           PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK);
 762                if (ret < 0)
 763                        goto out;
 764
 765                /* then the 16 higher bits, masked out */
 766                ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_2,
 767                                        (wl18xx_clk_table[clk_freq].q >> 16) &
 768                                        PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK);
 769                if (ret < 0)
 770                        goto out;
 771
 772                /* first the 16 lower bits */
 773                ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_1,
 774                                           wl18xx_clk_table[clk_freq].p &
 775                                           PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK);
 776                if (ret < 0)
 777                        goto out;
 778
 779                /* then the 16 higher bits, masked out */
 780                ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_2,
 781                                        (wl18xx_clk_table[clk_freq].p >> 16) &
 782                                        PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK);
 783                if (ret < 0)
 784                        goto out;
 785        } else {
 786                ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_SWALLOW_EN,
 787                                           PLLSH_WCS_PLL_SWALLOW_EN_VAL2);
 788                if (ret < 0)
 789                        goto out;
 790        }
 791
 792        /* choose WCS PLL */
 793        ret = wl18xx_top_reg_write(wl, PLLSH_WL_PLL_SEL,
 794                                   PLLSH_WL_PLL_SEL_WCS_PLL);
 795        if (ret < 0)
 796                goto out;
 797
 798        /* enable both PLLs */
 799        ret = wl18xx_top_reg_write(wl, PLLSH_WL_PLL_EN, PLLSH_WL_PLL_EN_VAL1);
 800        if (ret < 0)
 801                goto out;
 802
 803        udelay(1000);
 804
 805        /* disable coex PLL */
 806        ret = wl18xx_top_reg_write(wl, PLLSH_WL_PLL_EN, PLLSH_WL_PLL_EN_VAL2);
 807        if (ret < 0)
 808                goto out;
 809
 810        /* reset the swallowing logic */
 811        ret = wl18xx_top_reg_write(wl, PLLSH_COEX_PLL_SWALLOW_EN,
 812                                   PLLSH_COEX_PLL_SWALLOW_EN_VAL2);
 813
 814out:
 815        return ret;
 816}
 817
 818static int wl18xx_boot_soft_reset(struct wl1271 *wl)
 819{
 820        int ret;
 821
 822        /* disable Rx/Tx */
 823        ret = wlcore_write32(wl, WL18XX_ENABLE, 0x0);
 824        if (ret < 0)
 825                goto out;
 826
 827        /* disable auto calibration on start*/
 828        ret = wlcore_write32(wl, WL18XX_SPARE_A2, 0xffff);
 829
 830out:
 831        return ret;
 832}
 833
 834static int wl18xx_pre_boot(struct wl1271 *wl)
 835{
 836        int ret;
 837
 838        ret = wl18xx_set_clk(wl);
 839        if (ret < 0)
 840                goto out;
 841
 842        /* Continue the ELP wake up sequence */
 843        ret = wlcore_write32(wl, WL18XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
 844        if (ret < 0)
 845                goto out;
 846
 847        udelay(500);
 848
 849        ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
 850        if (ret < 0)
 851                goto out;
 852
 853        /* Disable interrupts */
 854        ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
 855        if (ret < 0)
 856                goto out;
 857
 858        ret = wl18xx_boot_soft_reset(wl);
 859
 860out:
 861        return ret;
 862}
 863
 864static int wl18xx_pre_upload(struct wl1271 *wl)
 865{
 866        u32 tmp;
 867        int ret;
 868        u16 irq_invert;
 869
 870        BUILD_BUG_ON(sizeof(struct wl18xx_mac_and_phy_params) >
 871                WL18XX_PHY_INIT_MEM_SIZE);
 872
 873        ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
 874        if (ret < 0)
 875                goto out;
 876
 877        /* TODO: check if this is all needed */
 878        ret = wlcore_write32(wl, WL18XX_EEPROMLESS_IND, WL18XX_EEPROMLESS_IND);
 879        if (ret < 0)
 880                goto out;
 881
 882        ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &tmp);
 883        if (ret < 0)
 884                goto out;
 885
 886        wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);
 887
 888        ret = wlcore_read32(wl, WL18XX_SCR_PAD2, &tmp);
 889        if (ret < 0)
 890                goto out;
 891
 892        /*
 893         * Workaround for FDSP code RAM corruption (needed for PG2.1
 894         * and newer; for older chips it's a NOP).  Change FDSP clock
 895         * settings so that it's muxed to the ATGP clock instead of
 896         * its own clock.
 897         */
 898
 899        ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]);
 900        if (ret < 0)
 901                goto out;
 902
 903        /* disable FDSP clock */
 904        ret = wlcore_write32(wl, WL18XX_PHY_FPGA_SPARE_1,
 905                             MEM_FDSP_CLK_120_DISABLE);
 906        if (ret < 0)
 907                goto out;
 908
 909        /* set ATPG clock toward FDSP Code RAM rather than its own clock */
 910        ret = wlcore_write32(wl, WL18XX_PHY_FPGA_SPARE_1,
 911                             MEM_FDSP_CODERAM_FUNC_CLK_SEL);
 912        if (ret < 0)
 913                goto out;
 914
 915        /* re-enable FDSP clock */
 916        ret = wlcore_write32(wl, WL18XX_PHY_FPGA_SPARE_1,
 917                             MEM_FDSP_CLK_120_ENABLE);
 918        if (ret < 0)
 919                goto out;
 920
 921        ret = irq_get_trigger_type(wl->irq);
 922        if ((ret == IRQ_TYPE_LEVEL_LOW) || (ret == IRQ_TYPE_EDGE_FALLING)) {
 923                wl1271_info("using inverted interrupt logic: %d", ret);
 924                ret = wlcore_set_partition(wl,
 925                                           &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
 926                if (ret < 0)
 927                        goto out;
 928
 929                ret = wl18xx_top_reg_read(wl, TOP_FN0_CCCR_REG_32, &irq_invert);
 930                if (ret < 0)
 931                        goto out;
 932
 933                irq_invert |= BIT(1);
 934                ret = wl18xx_top_reg_write(wl, TOP_FN0_CCCR_REG_32, irq_invert);
 935                if (ret < 0)
 936                        goto out;
 937
 938                ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]);
 939        }
 940
 941out:
 942        return ret;
 943}
 944
 945static int wl18xx_set_mac_and_phy(struct wl1271 *wl)
 946{
 947        struct wl18xx_priv *priv = wl->priv;
 948        struct wl18xx_mac_and_phy_params *params;
 949        int ret;
 950
 951        params = kmemdup(&priv->conf.phy, sizeof(*params), GFP_KERNEL);
 952        if (!params) {
 953                ret = -ENOMEM;
 954                goto out;
 955        }
 956
 957        ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]);
 958        if (ret < 0)
 959                goto out;
 960
 961        ret = wlcore_write(wl, WL18XX_PHY_INIT_MEM_ADDR, params,
 962                           sizeof(*params), false);
 963
 964out:
 965        kfree(params);
 966        return ret;
 967}
 968
 969static int wl18xx_enable_interrupts(struct wl1271 *wl)
 970{
 971        u32 event_mask, intr_mask;
 972        int ret;
 973
 974        event_mask = WL18XX_ACX_EVENTS_VECTOR;
 975        intr_mask = WL18XX_INTR_MASK;
 976
 977        ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, event_mask);
 978        if (ret < 0)
 979                goto out;
 980
 981        wlcore_enable_interrupts(wl);
 982
 983        ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK,
 984                               WL1271_ACX_INTR_ALL & ~intr_mask);
 985        if (ret < 0)
 986                goto disable_interrupts;
 987
 988        return ret;
 989
 990disable_interrupts:
 991        wlcore_disable_interrupts(wl);
 992
 993out:
 994        return ret;
 995}
 996
 997static int wl18xx_boot(struct wl1271 *wl)
 998{
 999        int ret;
1000
1001        ret = wl18xx_pre_boot(wl);
1002        if (ret < 0)
1003                goto out;
1004
1005        ret = wl18xx_pre_upload(wl);
1006        if (ret < 0)
1007                goto out;
1008
1009        ret = wlcore_boot_upload_firmware(wl);
1010        if (ret < 0)
1011                goto out;
1012
1013        ret = wl18xx_set_mac_and_phy(wl);
1014        if (ret < 0)
1015                goto out;
1016
1017        wl->event_mask = BSS_LOSS_EVENT_ID |
1018                SCAN_COMPLETE_EVENT_ID |
1019                RADAR_DETECTED_EVENT_ID |
1020                RSSI_SNR_TRIGGER_0_EVENT_ID |
1021                PERIODIC_SCAN_COMPLETE_EVENT_ID |
1022                PERIODIC_SCAN_REPORT_EVENT_ID |
1023                DUMMY_PACKET_EVENT_ID |
1024                PEER_REMOVE_COMPLETE_EVENT_ID |
1025                BA_SESSION_RX_CONSTRAINT_EVENT_ID |
1026                REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
1027                INACTIVE_STA_EVENT_ID |
1028                CHANNEL_SWITCH_COMPLETE_EVENT_ID |
1029                DFS_CHANNELS_CONFIG_COMPLETE_EVENT |
1030                SMART_CONFIG_SYNC_EVENT_ID |
1031                SMART_CONFIG_DECODE_EVENT_ID |
1032                TIME_SYNC_EVENT_ID |
1033                FW_LOGGER_INDICATION |
1034                RX_BA_WIN_SIZE_CHANGE_EVENT_ID;
1035
1036        wl->ap_event_mask = MAX_TX_FAILURE_EVENT_ID;
1037
1038        ret = wlcore_boot_run_firmware(wl);
1039        if (ret < 0)
1040                goto out;
1041
1042        ret = wl18xx_enable_interrupts(wl);
1043
1044out:
1045        return ret;
1046}
1047
1048static int wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
1049                               void *buf, size_t len)
1050{
1051        struct wl18xx_priv *priv = wl->priv;
1052
1053        memcpy(priv->cmd_buf, buf, len);
1054        memset(priv->cmd_buf + len, 0, WL18XX_CMD_MAX_SIZE - len);
1055
1056        return wlcore_write(wl, cmd_box_addr, priv->cmd_buf,
1057                            WL18XX_CMD_MAX_SIZE, false);
1058}
1059
1060static int wl18xx_ack_event(struct wl1271 *wl)
1061{
1062        return wlcore_write_reg(wl, REG_INTERRUPT_TRIG,
1063                                WL18XX_INTR_TRIG_EVENT_ACK);
1064}
1065
1066static u32 wl18xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks)
1067{
1068        u32 blk_size = WL18XX_TX_HW_BLOCK_SIZE;
1069        return (len + blk_size - 1) / blk_size + spare_blks;
1070}
1071
1072static void
1073wl18xx_set_tx_desc_blocks(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
1074                          u32 blks, u32 spare_blks)
1075{
1076        desc->wl18xx_mem.total_mem_blocks = blks;
1077}
1078
1079static void
1080wl18xx_set_tx_desc_data_len(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
1081                            struct sk_buff *skb)
1082{
1083        desc->length = cpu_to_le16(skb->len);
1084
1085        /* if only the last frame is to be padded, we unset this bit on Tx */
1086        if (wl->quirks & WLCORE_QUIRK_TX_PAD_LAST_FRAME)
1087                desc->wl18xx_mem.ctrl = WL18XX_TX_CTRL_NOT_PADDED;
1088        else
1089                desc->wl18xx_mem.ctrl = 0;
1090
1091        wl1271_debug(DEBUG_TX, "tx_fill_hdr: hlid: %d "
1092                     "len: %d life: %d mem: %d", desc->hlid,
1093                     le16_to_cpu(desc->length),
1094                     le16_to_cpu(desc->life_time),
1095                     desc->wl18xx_mem.total_mem_blocks);
1096}
1097
1098static enum wl_rx_buf_align
1099wl18xx_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc)
1100{
1101        if (rx_desc & RX_BUF_PADDED_PAYLOAD)
1102                return WLCORE_RX_BUF_PADDED;
1103
1104        return WLCORE_RX_BUF_ALIGNED;
1105}
1106
1107static u32 wl18xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data,
1108                                    u32 data_len)
1109{
1110        struct wl1271_rx_descriptor *desc = rx_data;
1111
1112        /* invalid packet */
1113        if (data_len < sizeof(*desc))
1114                return 0;
1115
1116        return data_len - sizeof(*desc);
1117}
1118
1119static void wl18xx_tx_immediate_completion(struct wl1271 *wl)
1120{
1121        wl18xx_tx_immediate_complete(wl);
1122}
1123
1124static int wl18xx_set_host_cfg_bitmap(struct wl1271 *wl, u32 extra_mem_blk)
1125{
1126        int ret;
1127        u32 sdio_align_size = 0;
1128        u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE |
1129                              HOST_IF_CFG_ADD_RX_ALIGNMENT;
1130
1131        /* Enable Tx SDIO padding */
1132        if (wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN) {
1133                host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK;
1134                sdio_align_size = WL12XX_BUS_BLOCK_SIZE;
1135        }
1136
1137        /* Enable Rx SDIO padding */
1138        if (wl->quirks & WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN) {
1139                host_cfg_bitmap |= HOST_IF_CFG_RX_PAD_TO_SDIO_BLK;
1140                sdio_align_size = WL12XX_BUS_BLOCK_SIZE;
1141        }
1142
1143        ret = wl18xx_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap,
1144                                            sdio_align_size, extra_mem_blk,
1145                                            WL18XX_HOST_IF_LEN_SIZE_FIELD);
1146        if (ret < 0)
1147                return ret;
1148
1149        return 0;
1150}
1151
1152static int wl18xx_hw_init(struct wl1271 *wl)
1153{
1154        int ret;
1155        struct wl18xx_priv *priv = wl->priv;
1156
1157        /* (re)init private structures. Relevant on recovery as well. */
1158        priv->last_fw_rls_idx = 0;
1159        priv->extra_spare_key_count = 0;
1160
1161        /* set the default amount of spare blocks in the bitmap */
1162        ret = wl18xx_set_host_cfg_bitmap(wl, WL18XX_TX_HW_BLOCK_SPARE);
1163        if (ret < 0)
1164                return ret;
1165
1166        /* set the dynamic fw traces bitmap */
1167        ret = wl18xx_acx_dynamic_fw_traces(wl);
1168        if (ret < 0)
1169                return ret;
1170
1171        if (checksum_param) {
1172                ret = wl18xx_acx_set_checksum_state(wl);
1173                if (ret != 0)
1174                        return ret;
1175        }
1176
1177        return ret;
1178}
1179
1180static void wl18xx_convert_fw_status(struct wl1271 *wl, void *raw_fw_status,
1181                                     struct wl_fw_status *fw_status)
1182{
1183        struct wl18xx_fw_status *int_fw_status = raw_fw_status;
1184
1185        fw_status->intr = le32_to_cpu(int_fw_status->intr);
1186        fw_status->fw_rx_counter = int_fw_status->fw_rx_counter;
1187        fw_status->drv_rx_counter = int_fw_status->drv_rx_counter;
1188        fw_status->tx_results_counter = int_fw_status->tx_results_counter;
1189        fw_status->rx_pkt_descs = int_fw_status->rx_pkt_descs;
1190
1191        fw_status->fw_localtime = le32_to_cpu(int_fw_status->fw_localtime);
1192        fw_status->link_ps_bitmap = le32_to_cpu(int_fw_status->link_ps_bitmap);
1193        fw_status->link_fast_bitmap =
1194                        le32_to_cpu(int_fw_status->link_fast_bitmap);
1195        fw_status->total_released_blks =
1196                        le32_to_cpu(int_fw_status->total_released_blks);
1197        fw_status->tx_total = le32_to_cpu(int_fw_status->tx_total);
1198
1199        fw_status->counters.tx_released_pkts =
1200                        int_fw_status->counters.tx_released_pkts;
1201        fw_status->counters.tx_lnk_free_pkts =
1202                        int_fw_status->counters.tx_lnk_free_pkts;
1203        fw_status->counters.tx_voice_released_blks =
1204                        int_fw_status->counters.tx_voice_released_blks;
1205        fw_status->counters.tx_last_rate =
1206                        int_fw_status->counters.tx_last_rate;
1207        fw_status->counters.tx_last_rate_mbps =
1208                        int_fw_status->counters.tx_last_rate_mbps;
1209        fw_status->counters.hlid =
1210                        int_fw_status->counters.hlid;
1211
1212        fw_status->log_start_addr = le32_to_cpu(int_fw_status->log_start_addr);
1213
1214        fw_status->priv = &int_fw_status->priv;
1215}
1216
1217static void wl18xx_set_tx_desc_csum(struct wl1271 *wl,
1218                                    struct wl1271_tx_hw_descr *desc,
1219                                    struct sk_buff *skb)
1220{
1221        u32 ip_hdr_offset;
1222        struct iphdr *ip_hdr;
1223
1224        if (!checksum_param) {
1225                desc->wl18xx_checksum_data = 0;
1226                return;
1227        }
1228
1229        if (skb->ip_summed != CHECKSUM_PARTIAL) {
1230                desc->wl18xx_checksum_data = 0;
1231                return;
1232        }
1233
1234        ip_hdr_offset = skb_network_header(skb) - skb_mac_header(skb);
1235        if (WARN_ON(ip_hdr_offset >= (1<<7))) {
1236                desc->wl18xx_checksum_data = 0;
1237                return;
1238        }
1239
1240        desc->wl18xx_checksum_data = ip_hdr_offset << 1;
1241
1242        /* FW is interested only in the LSB of the protocol  TCP=0 UDP=1 */
1243        ip_hdr = (void *)skb_network_header(skb);
1244        desc->wl18xx_checksum_data |= (ip_hdr->protocol & 0x01);
1245}
1246
1247static void wl18xx_set_rx_csum(struct wl1271 *wl,
1248                               struct wl1271_rx_descriptor *desc,
1249                               struct sk_buff *skb)
1250{
1251        if (desc->status & WL18XX_RX_CHECKSUM_MASK)
1252                skb->ip_summed = CHECKSUM_UNNECESSARY;
1253}
1254
1255static bool wl18xx_is_mimo_supported(struct wl1271 *wl)
1256{
1257        struct wl18xx_priv *priv = wl->priv;
1258
1259        /* only support MIMO with multiple antennas, and when SISO
1260         * is not forced through config
1261         */
1262        return (priv->conf.phy.number_of_assembled_ant2_4 >= 2) &&
1263               (priv->conf.ht.mode != HT_MODE_WIDE) &&
1264               (priv->conf.ht.mode != HT_MODE_SISO20);
1265}
1266
1267/*
1268 * TODO: instead of having these two functions to get the rate mask,
1269 * we should modify the wlvif->rate_set instead
1270 */
1271static u32 wl18xx_sta_get_ap_rate_mask(struct wl1271 *wl,
1272                                       struct wl12xx_vif *wlvif)
1273{
1274        u32 hw_rate_set = wlvif->rate_set;
1275
1276        if (wlvif->channel_type == NL80211_CHAN_HT40MINUS ||
1277            wlvif->channel_type == NL80211_CHAN_HT40PLUS) {
1278                wl1271_debug(DEBUG_ACX, "using wide channel rate mask");
1279                hw_rate_set |= CONF_TX_RATE_USE_WIDE_CHAN;
1280
1281                /* we don't support MIMO in wide-channel mode */
1282                hw_rate_set &= ~CONF_TX_MIMO_RATES;
1283        } else if (wl18xx_is_mimo_supported(wl)) {
1284                wl1271_debug(DEBUG_ACX, "using MIMO channel rate mask");
1285                hw_rate_set |= CONF_TX_MIMO_RATES;
1286        }
1287
1288        return hw_rate_set;
1289}
1290
1291static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl,
1292                                             struct wl12xx_vif *wlvif)
1293{
1294        if (wlvif->channel_type == NL80211_CHAN_HT40MINUS ||
1295            wlvif->channel_type == NL80211_CHAN_HT40PLUS) {
1296                wl1271_debug(DEBUG_ACX, "using wide channel rate mask");
1297
1298                /* sanity check - we don't support this */
1299                if (WARN_ON(wlvif->band != NL80211_BAND_5GHZ))
1300                        return 0;
1301
1302                return CONF_TX_RATE_USE_WIDE_CHAN;
1303        } else if (wl18xx_is_mimo_supported(wl) &&
1304                   wlvif->band == NL80211_BAND_2GHZ) {
1305                wl1271_debug(DEBUG_ACX, "using MIMO rate mask");
1306                /*
1307                 * we don't care about HT channel here - if a peer doesn't
1308                 * support MIMO, we won't enable it in its rates
1309                 */
1310                return CONF_TX_MIMO_RATES;
1311        } else {
1312                return 0;
1313        }
1314}
1315
1316static const char *wl18xx_rdl_name(enum wl18xx_rdl_num rdl_num)
1317{
1318        switch (rdl_num) {
1319        case RDL_1_HP:
1320                return "183xH";
1321        case RDL_2_SP:
1322                return "183x or 180x";
1323        case RDL_3_HP:
1324                return "187xH";
1325        case RDL_4_SP:
1326                return "187x";
1327        case RDL_5_SP:
1328                return "RDL11 - Not Supported";
1329        case RDL_6_SP:
1330                return "180xD";
1331        case RDL_7_SP:
1332                return "RDL13 - Not Supported (1893Q)";
1333        case RDL_8_SP:
1334                return "18xxQ";
1335        case RDL_NONE:
1336                return "UNTRIMMED";
1337        default:
1338                return "UNKNOWN";
1339        }
1340}
1341
1342static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
1343{
1344        u32 fuse;
1345        s8 rom = 0, metal = 0, pg_ver = 0, rdl_ver = 0, package_type = 0;
1346        int ret;
1347
1348        ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
1349        if (ret < 0)
1350                goto out;
1351
1352        ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_2_3, &fuse);
1353        if (ret < 0)
1354                goto out;
1355
1356        package_type = (fuse >> WL18XX_PACKAGE_TYPE_OFFSET) & 1;
1357
1358        ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_1_3, &fuse);
1359        if (ret < 0)
1360                goto out;
1361
1362        pg_ver = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET;
1363        rom = (fuse & WL18XX_ROM_VER_MASK) >> WL18XX_ROM_VER_OFFSET;
1364
1365        if ((rom <= 0xE) && (package_type == WL18XX_PACKAGE_TYPE_WSP))
1366                metal = (fuse & WL18XX_METAL_VER_MASK) >>
1367                        WL18XX_METAL_VER_OFFSET;
1368        else
1369                metal = (fuse & WL18XX_NEW_METAL_VER_MASK) >>
1370                        WL18XX_NEW_METAL_VER_OFFSET;
1371
1372        ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_2_3, &fuse);
1373        if (ret < 0)
1374                goto out;
1375
1376        rdl_ver = (fuse & WL18XX_RDL_VER_MASK) >> WL18XX_RDL_VER_OFFSET;
1377
1378        wl1271_info("wl18xx HW: %s, PG %d.%d (ROM 0x%x)",
1379                    wl18xx_rdl_name(rdl_ver), pg_ver, metal, rom);
1380
1381        if (ver)
1382                *ver = pg_ver;
1383
1384        ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
1385
1386out:
1387        return ret;
1388}
1389
1390static int wl18xx_load_conf_file(struct device *dev, struct wlcore_conf *conf,
1391                                 struct wl18xx_priv_conf *priv_conf,
1392                                 const char *file)
1393{
1394        struct wlcore_conf_file *conf_file;
1395        const struct firmware *fw;
1396        int ret;
1397
1398        ret = request_firmware(&fw, file, dev);
1399        if (ret < 0) {
1400                wl1271_error("could not get configuration binary %s: %d",
1401                             file, ret);
1402                return ret;
1403        }
1404
1405        if (fw->size != WL18XX_CONF_SIZE) {
1406                wl1271_error("%s configuration binary size is wrong, expected %zu got %zu",
1407                             file, WL18XX_CONF_SIZE, fw->size);
1408                ret = -EINVAL;
1409                goto out_release;
1410        }
1411
1412        conf_file = (struct wlcore_conf_file *) fw->data;
1413
1414        if (conf_file->header.magic != cpu_to_le32(WL18XX_CONF_MAGIC)) {
1415                wl1271_error("configuration binary file magic number mismatch, "
1416                             "expected 0x%0x got 0x%0x", WL18XX_CONF_MAGIC,
1417                             conf_file->header.magic);
1418                ret = -EINVAL;
1419                goto out_release;
1420        }
1421
1422        if (conf_file->header.version != cpu_to_le32(WL18XX_CONF_VERSION)) {
1423                wl1271_error("configuration binary file version not supported, "
1424                             "expected 0x%08x got 0x%08x",
1425                             WL18XX_CONF_VERSION, conf_file->header.version);
1426                ret = -EINVAL;
1427                goto out_release;
1428        }
1429
1430        memcpy(conf, &conf_file->core, sizeof(*conf));
1431        memcpy(priv_conf, &conf_file->priv, sizeof(*priv_conf));
1432
1433out_release:
1434        release_firmware(fw);
1435        return ret;
1436}
1437
1438static int wl18xx_conf_init(struct wl1271 *wl, struct device *dev)
1439{
1440        struct platform_device *pdev = wl->pdev;
1441        struct wlcore_platdev_data *pdata = dev_get_platdata(&pdev->dev);
1442        struct wl18xx_priv *priv = wl->priv;
1443
1444        if (wl18xx_load_conf_file(dev, &wl->conf, &priv->conf,
1445                                  pdata->family->cfg_name) < 0) {
1446                wl1271_warning("falling back to default config");
1447
1448                /* apply driver default configuration */
1449                memcpy(&wl->conf, &wl18xx_conf, sizeof(wl->conf));
1450                /* apply default private configuration */
1451                memcpy(&priv->conf, &wl18xx_default_priv_conf,
1452                       sizeof(priv->conf));
1453        }
1454
1455        return 0;
1456}
1457
1458static int wl18xx_plt_init(struct wl1271 *wl)
1459{
1460        int ret;
1461
1462        /* calibrator based auto/fem detect not supported for 18xx */
1463        if (wl->plt_mode == PLT_FEM_DETECT) {
1464                wl1271_error("wl18xx_plt_init: PLT FEM_DETECT not supported");
1465                return -EINVAL;
1466        }
1467
1468        ret = wlcore_write32(wl, WL18XX_SCR_PAD8, WL18XX_SCR_PAD8_PLT);
1469        if (ret < 0)
1470                return ret;
1471
1472        return wl->ops->boot(wl);
1473}
1474
1475static int wl18xx_get_mac(struct wl1271 *wl)
1476{
1477        u32 mac1, mac2;
1478        int ret;
1479
1480        ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
1481        if (ret < 0)
1482                goto out;
1483
1484        ret = wlcore_read32(wl, WL18XX_REG_FUSE_BD_ADDR_1, &mac1);
1485        if (ret < 0)
1486                goto out;
1487
1488        ret = wlcore_read32(wl, WL18XX_REG_FUSE_BD_ADDR_2, &mac2);
1489        if (ret < 0)
1490                goto out;
1491
1492        /* these are the two parts of the BD_ADDR */
1493        wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) +
1494                ((mac1 & 0xff000000) >> 24);
1495        wl->fuse_nic_addr = (mac1 & 0xffffff);
1496
1497        if (!wl->fuse_oui_addr && !wl->fuse_nic_addr) {
1498                u8 mac[ETH_ALEN];
1499
1500                eth_random_addr(mac);
1501
1502                wl->fuse_oui_addr = (mac[0] << 16) + (mac[1] << 8) + mac[2];
1503                wl->fuse_nic_addr = (mac[3] << 16) + (mac[4] << 8) + mac[5];
1504                wl1271_warning("MAC address from fuse not available, using random locally administered addresses.");
1505        }
1506
1507        ret = wlcore_set_partition(wl, &wl->ptable[PART_DOWN]);
1508
1509out:
1510        return ret;
1511}
1512
1513static int wl18xx_handle_static_data(struct wl1271 *wl,
1514                                     struct wl1271_static_data *static_data)
1515{
1516        struct wl18xx_static_data_priv *static_data_priv =
1517                (struct wl18xx_static_data_priv *) static_data->priv;
1518
1519        strncpy(wl->chip.phy_fw_ver_str, static_data_priv->phy_version,
1520                sizeof(wl->chip.phy_fw_ver_str));
1521
1522        /* make sure the string is NULL-terminated */
1523        wl->chip.phy_fw_ver_str[sizeof(wl->chip.phy_fw_ver_str) - 1] = '\0';
1524
1525        wl1271_info("PHY firmware version: %s", static_data_priv->phy_version);
1526
1527        return 0;
1528}
1529
1530static int wl18xx_get_spare_blocks(struct wl1271 *wl, bool is_gem)
1531{
1532        struct wl18xx_priv *priv = wl->priv;
1533
1534        /* If we have keys requiring extra spare, indulge them */
1535        if (priv->extra_spare_key_count)
1536                return WL18XX_TX_HW_EXTRA_BLOCK_SPARE;
1537
1538        return WL18XX_TX_HW_BLOCK_SPARE;
1539}
1540
1541static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
1542                          struct ieee80211_vif *vif,
1543                          struct ieee80211_sta *sta,
1544                          struct ieee80211_key_conf *key_conf)
1545{
1546        struct wl18xx_priv *priv = wl->priv;
1547        bool change_spare = false, special_enc;
1548        int ret;
1549
1550        wl1271_debug(DEBUG_CRYPT, "extra spare keys before: %d",
1551                     priv->extra_spare_key_count);
1552
1553        special_enc = key_conf->cipher == WL1271_CIPHER_SUITE_GEM ||
1554                      key_conf->cipher == WLAN_CIPHER_SUITE_TKIP;
1555
1556        ret = wlcore_set_key(wl, cmd, vif, sta, key_conf);
1557        if (ret < 0)
1558                goto out;
1559
1560        /*
1561         * when adding the first or removing the last GEM/TKIP key,
1562         * we have to adjust the number of spare blocks.
1563         */
1564        if (special_enc) {
1565                if (cmd == SET_KEY) {
1566                        /* first key */
1567                        change_spare = (priv->extra_spare_key_count == 0);
1568                        priv->extra_spare_key_count++;
1569                } else if (cmd == DISABLE_KEY) {
1570                        /* last key */
1571                        change_spare = (priv->extra_spare_key_count == 1);
1572                        priv->extra_spare_key_count--;
1573                }
1574        }
1575
1576        wl1271_debug(DEBUG_CRYPT, "extra spare keys after: %d",
1577                     priv->extra_spare_key_count);
1578
1579        if (!change_spare)
1580                goto out;
1581
1582        /* key is now set, change the spare blocks */
1583        if (priv->extra_spare_key_count)
1584                ret = wl18xx_set_host_cfg_bitmap(wl,
1585                                        WL18XX_TX_HW_EXTRA_BLOCK_SPARE);
1586        else
1587                ret = wl18xx_set_host_cfg_bitmap(wl,
1588                                        WL18XX_TX_HW_BLOCK_SPARE);
1589
1590out:
1591        return ret;
1592}
1593
1594static u32 wl18xx_pre_pkt_send(struct wl1271 *wl,
1595                               u32 buf_offset, u32 last_len)
1596{
1597        if (wl->quirks & WLCORE_QUIRK_TX_PAD_LAST_FRAME) {
1598                struct wl1271_tx_hw_descr *last_desc;
1599
1600                /* get the last TX HW descriptor written to the aggr buf */
1601                last_desc = (struct wl1271_tx_hw_descr *)(wl->aggr_buf +
1602                                                        buf_offset - last_len);
1603
1604                /* the last frame is padded up to an SDIO block */
1605                last_desc->wl18xx_mem.ctrl &= ~WL18XX_TX_CTRL_NOT_PADDED;
1606                return ALIGN(buf_offset, WL12XX_BUS_BLOCK_SIZE);
1607        }
1608
1609        /* no modifications */
1610        return buf_offset;
1611}
1612
1613static void wl18xx_sta_rc_update(struct wl1271 *wl,
1614                                 struct wl12xx_vif *wlvif)
1615{
1616        bool wide = wlvif->rc_update_bw >= IEEE80211_STA_RX_BW_40;
1617
1618        wl1271_debug(DEBUG_MAC80211, "mac80211 sta_rc_update wide %d", wide);
1619
1620        /* sanity */
1621        if (WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS))
1622                return;
1623
1624        /* ignore the change before association */
1625        if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
1626                return;
1627
1628        /*
1629         * If we started out as wide, we can change the operation mode. If we
1630         * thought this was a 20mhz AP, we have to reconnect
1631         */
1632        if (wlvif->sta.role_chan_type == NL80211_CHAN_HT40MINUS ||
1633            wlvif->sta.role_chan_type == NL80211_CHAN_HT40PLUS)
1634                wl18xx_acx_peer_ht_operation_mode(wl, wlvif->sta.hlid, wide);
1635        else
1636                ieee80211_connection_loss(wl12xx_wlvif_to_vif(wlvif));
1637}
1638
1639static int wl18xx_set_peer_cap(struct wl1271 *wl,
1640                               struct ieee80211_sta_ht_cap *ht_cap,
1641                               bool allow_ht_operation,
1642                               u32 rate_set, u8 hlid)
1643{
1644        return wl18xx_acx_set_peer_cap(wl, ht_cap, allow_ht_operation,
1645                                       rate_set, hlid);
1646}
1647
1648static bool wl18xx_lnk_high_prio(struct wl1271 *wl, u8 hlid,
1649                                 struct wl1271_link *lnk)
1650{
1651        u8 thold;
1652        struct wl18xx_fw_status_priv *status_priv =
1653                (struct wl18xx_fw_status_priv *)wl->fw_status->priv;
1654        unsigned long suspend_bitmap;
1655
1656        /* if we don't have the link map yet, assume they all low prio */
1657        if (!status_priv)
1658                return false;
1659
1660        /* suspended links are never high priority */
1661        suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
1662        if (test_bit(hlid, &suspend_bitmap))
1663                return false;
1664
1665        /* the priority thresholds are taken from FW */
1666        if (test_bit(hlid, &wl->fw_fast_lnk_map) &&
1667            !test_bit(hlid, &wl->ap_fw_ps_map))
1668                thold = status_priv->tx_fast_link_prio_threshold;
1669        else
1670                thold = status_priv->tx_slow_link_prio_threshold;
1671
1672        return lnk->allocated_pkts < thold;
1673}
1674
1675static bool wl18xx_lnk_low_prio(struct wl1271 *wl, u8 hlid,
1676                                struct wl1271_link *lnk)
1677{
1678        u8 thold;
1679        struct wl18xx_fw_status_priv *status_priv =
1680                (struct wl18xx_fw_status_priv *)wl->fw_status->priv;
1681        unsigned long suspend_bitmap;
1682
1683        /* if we don't have the link map yet, assume they all low prio */
1684        if (!status_priv)
1685                return true;
1686
1687        suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
1688        if (test_bit(hlid, &suspend_bitmap))
1689                thold = status_priv->tx_suspend_threshold;
1690        else if (test_bit(hlid, &wl->fw_fast_lnk_map) &&
1691                 !test_bit(hlid, &wl->ap_fw_ps_map))
1692                thold = status_priv->tx_fast_stop_threshold;
1693        else
1694                thold = status_priv->tx_slow_stop_threshold;
1695
1696        return lnk->allocated_pkts < thold;
1697}
1698
1699static u32 wl18xx_convert_hwaddr(struct wl1271 *wl, u32 hwaddr)
1700{
1701        return hwaddr & ~0x80000000;
1702}
1703
1704static int wl18xx_setup(struct wl1271 *wl);
1705
1706static struct wlcore_ops wl18xx_ops = {
1707        .setup          = wl18xx_setup,
1708        .identify_chip  = wl18xx_identify_chip,
1709        .boot           = wl18xx_boot,
1710        .plt_init       = wl18xx_plt_init,
1711        .trigger_cmd    = wl18xx_trigger_cmd,
1712        .ack_event      = wl18xx_ack_event,
1713        .wait_for_event = wl18xx_wait_for_event,
1714        .process_mailbox_events = wl18xx_process_mailbox_events,
1715        .calc_tx_blocks = wl18xx_calc_tx_blocks,
1716        .set_tx_desc_blocks = wl18xx_set_tx_desc_blocks,
1717        .set_tx_desc_data_len = wl18xx_set_tx_desc_data_len,
1718        .get_rx_buf_align = wl18xx_get_rx_buf_align,
1719        .get_rx_packet_len = wl18xx_get_rx_packet_len,
1720        .tx_immediate_compl = wl18xx_tx_immediate_completion,
1721        .tx_delayed_compl = NULL,
1722        .hw_init        = wl18xx_hw_init,
1723        .convert_fw_status = wl18xx_convert_fw_status,
1724        .set_tx_desc_csum = wl18xx_set_tx_desc_csum,
1725        .get_pg_ver     = wl18xx_get_pg_ver,
1726        .set_rx_csum = wl18xx_set_rx_csum,
1727        .sta_get_ap_rate_mask = wl18xx_sta_get_ap_rate_mask,
1728        .ap_get_mimo_wide_rate_mask = wl18xx_ap_get_mimo_wide_rate_mask,
1729        .get_mac        = wl18xx_get_mac,
1730        .debugfs_init   = wl18xx_debugfs_add_files,
1731        .scan_start     = wl18xx_scan_start,
1732        .scan_stop      = wl18xx_scan_stop,
1733        .sched_scan_start       = wl18xx_sched_scan_start,
1734        .sched_scan_stop        = wl18xx_scan_sched_scan_stop,
1735        .handle_static_data     = wl18xx_handle_static_data,
1736        .get_spare_blocks = wl18xx_get_spare_blocks,
1737        .set_key        = wl18xx_set_key,
1738        .channel_switch = wl18xx_cmd_channel_switch,
1739        .pre_pkt_send   = wl18xx_pre_pkt_send,
1740        .sta_rc_update  = wl18xx_sta_rc_update,
1741        .set_peer_cap   = wl18xx_set_peer_cap,
1742        .convert_hwaddr = wl18xx_convert_hwaddr,
1743        .lnk_high_prio  = wl18xx_lnk_high_prio,
1744        .lnk_low_prio   = wl18xx_lnk_low_prio,
1745        .smart_config_start = wl18xx_cmd_smart_config_start,
1746        .smart_config_stop  = wl18xx_cmd_smart_config_stop,
1747        .smart_config_set_group_key = wl18xx_cmd_smart_config_set_group_key,
1748        .interrupt_notify = wl18xx_acx_interrupt_notify_config,
1749        .rx_ba_filter   = wl18xx_acx_rx_ba_filter,
1750        .ap_sleep       = wl18xx_acx_ap_sleep,
1751        .set_cac        = wl18xx_cmd_set_cac,
1752        .dfs_master_restart     = wl18xx_cmd_dfs_master_restart,
1753};
1754
1755/* HT cap appropriate for wide channels in 2Ghz */
1756static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_2ghz = {
1757        .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 |
1758               IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_DSSSCCK40 |
1759               IEEE80211_HT_CAP_GRN_FLD,
1760        .ht_supported = true,
1761        .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K,
1762        .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
1763        .mcs = {
1764                .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
1765                .rx_highest = cpu_to_le16(150),
1766                .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
1767                },
1768};
1769
1770/* HT cap appropriate for wide channels in 5Ghz */
1771static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_5ghz = {
1772        .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 |
1773               IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
1774               IEEE80211_HT_CAP_GRN_FLD,
1775        .ht_supported = true,
1776        .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K,
1777        .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
1778        .mcs = {
1779                .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
1780                .rx_highest = cpu_to_le16(150),
1781                .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
1782                },
1783};
1784
1785/* HT cap appropriate for SISO 20 */
1786static struct ieee80211_sta_ht_cap wl18xx_siso20_ht_cap = {
1787        .cap = IEEE80211_HT_CAP_SGI_20 |
1788               IEEE80211_HT_CAP_GRN_FLD,
1789        .ht_supported = true,
1790        .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K,
1791        .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
1792        .mcs = {
1793                .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
1794                .rx_highest = cpu_to_le16(72),
1795                .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
1796                },
1797};
1798
1799/* HT cap appropriate for MIMO rates in 20mhz channel */
1800static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_2ghz = {
1801        .cap = IEEE80211_HT_CAP_SGI_20 |
1802               IEEE80211_HT_CAP_GRN_FLD,
1803        .ht_supported = true,
1804        .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K,
1805        .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
1806        .mcs = {
1807                .rx_mask = { 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, },
1808                .rx_highest = cpu_to_le16(144),
1809                .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
1810                },
1811};
1812
1813static const struct ieee80211_iface_limit wl18xx_iface_limits[] = {
1814        {
1815                .max = 2,
1816                .types = BIT(NL80211_IFTYPE_STATION),
1817        },
1818        {
1819                .max = 1,
1820                .types =   BIT(NL80211_IFTYPE_AP)
1821                         | BIT(NL80211_IFTYPE_P2P_GO)
1822                         | BIT(NL80211_IFTYPE_P2P_CLIENT)
1823#ifdef CONFIG_MAC80211_MESH
1824                         | BIT(NL80211_IFTYPE_MESH_POINT)
1825#endif
1826        },
1827        {
1828                .max = 1,
1829                .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
1830        },
1831};
1832
1833static const struct ieee80211_iface_limit wl18xx_iface_ap_limits[] = {
1834        {
1835                .max = 2,
1836                .types = BIT(NL80211_IFTYPE_AP),
1837        },
1838#ifdef CONFIG_MAC80211_MESH
1839        {
1840                .max = 1,
1841                .types = BIT(NL80211_IFTYPE_MESH_POINT),
1842        },
1843#endif
1844        {
1845                .max = 1,
1846                .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
1847        },
1848};
1849
1850static const struct ieee80211_iface_combination
1851wl18xx_iface_combinations[] = {
1852        {
1853                .max_interfaces = 3,
1854                .limits = wl18xx_iface_limits,
1855                .n_limits = ARRAY_SIZE(wl18xx_iface_limits),
1856                .num_different_channels = 2,
1857        },
1858        {
1859                .max_interfaces = 2,
1860                .limits = wl18xx_iface_ap_limits,
1861                .n_limits = ARRAY_SIZE(wl18xx_iface_ap_limits),
1862                .num_different_channels = 1,
1863                .radar_detect_widths =  BIT(NL80211_CHAN_NO_HT) |
1864                                        BIT(NL80211_CHAN_HT20) |
1865                                        BIT(NL80211_CHAN_HT40MINUS) |
1866                                        BIT(NL80211_CHAN_HT40PLUS),
1867        }
1868};
1869
1870static int wl18xx_setup(struct wl1271 *wl)
1871{
1872        struct wl18xx_priv *priv = wl->priv;
1873        int ret;
1874
1875        BUILD_BUG_ON(WL18XX_MAX_LINKS > WLCORE_MAX_LINKS);
1876        BUILD_BUG_ON(WL18XX_MAX_AP_STATIONS > WL18XX_MAX_LINKS);
1877        BUILD_BUG_ON(WL18XX_CONF_SG_PARAMS_MAX > WLCORE_CONF_SG_PARAMS_MAX);
1878
1879        wl->rtable = wl18xx_rtable;
1880        wl->num_tx_desc = WL18XX_NUM_TX_DESCRIPTORS;
1881        wl->num_rx_desc = WL18XX_NUM_RX_DESCRIPTORS;
1882        wl->num_links = WL18XX_MAX_LINKS;
1883        wl->max_ap_stations = WL18XX_MAX_AP_STATIONS;
1884        wl->iface_combinations = wl18xx_iface_combinations;
1885        wl->n_iface_combinations = ARRAY_SIZE(wl18xx_iface_combinations);
1886        wl->num_mac_addr = WL18XX_NUM_MAC_ADDRESSES;
1887        wl->band_rate_to_idx = wl18xx_band_rate_to_idx;
1888        wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX;
1889        wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0;
1890        wl->fw_status_len = sizeof(struct wl18xx_fw_status);
1891        wl->fw_status_priv_len = sizeof(struct wl18xx_fw_status_priv);
1892        wl->stats.fw_stats_len = sizeof(struct wl18xx_acx_statistics);
1893        wl->static_data_priv_len = sizeof(struct wl18xx_static_data_priv);
1894
1895        if (num_rx_desc_param != -1)
1896                wl->num_rx_desc = num_rx_desc_param;
1897
1898        ret = wl18xx_conf_init(wl, wl->dev);
1899        if (ret < 0)
1900                return ret;
1901
1902        /* If the module param is set, update it in conf */
1903        if (board_type_param) {
1904                if (!strcmp(board_type_param, "fpga")) {
1905                        priv->conf.phy.board_type = BOARD_TYPE_FPGA_18XX;
1906                } else if (!strcmp(board_type_param, "hdk")) {
1907                        priv->conf.phy.board_type = BOARD_TYPE_HDK_18XX;
1908                } else if (!strcmp(board_type_param, "dvp")) {
1909                        priv->conf.phy.board_type = BOARD_TYPE_DVP_18XX;
1910                } else if (!strcmp(board_type_param, "evb")) {
1911                        priv->conf.phy.board_type = BOARD_TYPE_EVB_18XX;
1912                } else if (!strcmp(board_type_param, "com8")) {
1913                        priv->conf.phy.board_type = BOARD_TYPE_COM8_18XX;
1914                } else {
1915                        wl1271_error("invalid board type '%s'",
1916                                board_type_param);
1917                        return -EINVAL;
1918                }
1919        }
1920
1921        if (priv->conf.phy.board_type >= NUM_BOARD_TYPES) {
1922                wl1271_error("invalid board type '%d'",
1923                        priv->conf.phy.board_type);
1924                return -EINVAL;
1925        }
1926
1927        if (low_band_component_param != -1)
1928                priv->conf.phy.low_band_component = low_band_component_param;
1929        if (low_band_component_type_param != -1)
1930                priv->conf.phy.low_band_component_type =
1931                        low_band_component_type_param;
1932        if (high_band_component_param != -1)
1933                priv->conf.phy.high_band_component = high_band_component_param;
1934        if (high_band_component_type_param != -1)
1935                priv->conf.phy.high_band_component_type =
1936                        high_band_component_type_param;
1937        if (pwr_limit_reference_11_abg_param != -1)
1938                priv->conf.phy.pwr_limit_reference_11_abg =
1939                        pwr_limit_reference_11_abg_param;
1940        if (n_antennas_2_param != -1)
1941                priv->conf.phy.number_of_assembled_ant2_4 = n_antennas_2_param;
1942        if (n_antennas_5_param != -1)
1943                priv->conf.phy.number_of_assembled_ant5 = n_antennas_5_param;
1944        if (dc2dc_param != -1)
1945                priv->conf.phy.external_pa_dc2dc = dc2dc_param;
1946
1947        if (ht_mode_param) {
1948                if (!strcmp(ht_mode_param, "default"))
1949                        priv->conf.ht.mode = HT_MODE_DEFAULT;
1950                else if (!strcmp(ht_mode_param, "wide"))
1951                        priv->conf.ht.mode = HT_MODE_WIDE;
1952                else if (!strcmp(ht_mode_param, "siso20"))
1953                        priv->conf.ht.mode = HT_MODE_SISO20;
1954                else {
1955                        wl1271_error("invalid ht_mode '%s'", ht_mode_param);
1956                        return -EINVAL;
1957                }
1958        }
1959
1960        if (priv->conf.ht.mode == HT_MODE_DEFAULT) {
1961                /*
1962                 * Only support mimo with multiple antennas. Fall back to
1963                 * siso40.
1964                 */
1965                if (wl18xx_is_mimo_supported(wl))
1966                        wlcore_set_ht_cap(wl, NL80211_BAND_2GHZ,
1967                                          &wl18xx_mimo_ht_cap_2ghz);
1968                else
1969                        wlcore_set_ht_cap(wl, NL80211_BAND_2GHZ,
1970                                          &wl18xx_siso40_ht_cap_2ghz);
1971
1972                /* 5Ghz is always wide */
1973                wlcore_set_ht_cap(wl, NL80211_BAND_5GHZ,
1974                                  &wl18xx_siso40_ht_cap_5ghz);
1975        } else if (priv->conf.ht.mode == HT_MODE_WIDE) {
1976                wlcore_set_ht_cap(wl, NL80211_BAND_2GHZ,
1977                                  &wl18xx_siso40_ht_cap_2ghz);
1978                wlcore_set_ht_cap(wl, NL80211_BAND_5GHZ,
1979                                  &wl18xx_siso40_ht_cap_5ghz);
1980        } else if (priv->conf.ht.mode == HT_MODE_SISO20) {
1981                wlcore_set_ht_cap(wl, NL80211_BAND_2GHZ,
1982                                  &wl18xx_siso20_ht_cap);
1983                wlcore_set_ht_cap(wl, NL80211_BAND_5GHZ,
1984                                  &wl18xx_siso20_ht_cap);
1985        }
1986
1987        if (!checksum_param) {
1988                wl18xx_ops.set_rx_csum = NULL;
1989                wl18xx_ops.init_vif = NULL;
1990        }
1991
1992        /* Enable 11a Band only if we have 5G antennas */
1993        wl->enable_11a = (priv->conf.phy.number_of_assembled_ant5 != 0);
1994
1995        return 0;
1996}
1997
1998static int wl18xx_probe(struct platform_device *pdev)
1999{
2000        struct wl1271 *wl;
2001        struct ieee80211_hw *hw;
2002        int ret;
2003
2004        hw = wlcore_alloc_hw(sizeof(struct wl18xx_priv),
2005                             WL18XX_AGGR_BUFFER_SIZE,
2006                             sizeof(struct wl18xx_event_mailbox));
2007        if (IS_ERR(hw)) {
2008                wl1271_error("can't allocate hw");
2009                ret = PTR_ERR(hw);
2010                goto out;
2011        }
2012
2013        wl = hw->priv;
2014        wl->ops = &wl18xx_ops;
2015        wl->ptable = wl18xx_ptable;
2016        ret = wlcore_probe(wl, pdev);
2017        if (ret)
2018                goto out_free;
2019
2020        return ret;
2021
2022out_free:
2023        wlcore_free_hw(wl);
2024out:
2025        return ret;
2026}
2027
2028static const struct platform_device_id wl18xx_id_table[] = {
2029        { "wl18xx", 0 },
2030        {  } /* Terminating Entry */
2031};
2032MODULE_DEVICE_TABLE(platform, wl18xx_id_table);
2033
2034static struct platform_driver wl18xx_driver = {
2035        .probe          = wl18xx_probe,
2036        .remove         = wlcore_remove,
2037        .id_table       = wl18xx_id_table,
2038        .driver = {
2039                .name   = "wl18xx_driver",
2040        }
2041};
2042
2043module_platform_driver(wl18xx_driver);
2044module_param_named(ht_mode, ht_mode_param, charp, 0400);
2045MODULE_PARM_DESC(ht_mode, "Force HT mode: wide or siso20");
2046
2047module_param_named(board_type, board_type_param, charp, 0400);
2048MODULE_PARM_DESC(board_type, "Board type: fpga, hdk (default), evb, com8 or "
2049                 "dvp");
2050
2051module_param_named(checksum, checksum_param, bool, 0400);
2052MODULE_PARM_DESC(checksum, "Enable TCP checksum: boolean (defaults to false)");
2053
2054module_param_named(dc2dc, dc2dc_param, int, 0400);
2055MODULE_PARM_DESC(dc2dc, "External DC2DC: u8 (defaults to 0)");
2056
2057module_param_named(n_antennas_2, n_antennas_2_param, int, 0400);
2058MODULE_PARM_DESC(n_antennas_2,
2059                 "Number of installed 2.4GHz antennas: 1 (default) or 2");
2060
2061module_param_named(n_antennas_5, n_antennas_5_param, int, 0400);
2062MODULE_PARM_DESC(n_antennas_5,
2063                 "Number of installed 5GHz antennas: 1 (default) or 2");
2064
2065module_param_named(low_band_component, low_band_component_param, int, 0400);
2066MODULE_PARM_DESC(low_band_component, "Low band component: u8 "
2067                 "(default is 0x01)");
2068
2069module_param_named(low_band_component_type, low_band_component_type_param,
2070                   int, 0400);
2071MODULE_PARM_DESC(low_band_component_type, "Low band component type: u8 "
2072                 "(default is 0x05 or 0x06 depending on the board_type)");
2073
2074module_param_named(high_band_component, high_band_component_param, int, 0400);
2075MODULE_PARM_DESC(high_band_component, "High band component: u8, "
2076                 "(default is 0x01)");
2077
2078module_param_named(high_band_component_type, high_band_component_type_param,
2079                   int, 0400);
2080MODULE_PARM_DESC(high_band_component_type, "High band component type: u8 "
2081                 "(default is 0x09)");
2082
2083module_param_named(pwr_limit_reference_11_abg,
2084                   pwr_limit_reference_11_abg_param, int, 0400);
2085MODULE_PARM_DESC(pwr_limit_reference_11_abg, "Power limit reference: u8 "
2086                 "(default is 0xc8)");
2087
2088module_param_named(num_rx_desc, num_rx_desc_param, int, 0400);
2089MODULE_PARM_DESC(num_rx_desc_param,
2090                 "Number of Rx descriptors: u8 (default is 32)");
2091
2092MODULE_LICENSE("GPL v2");
2093MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
2094MODULE_FIRMWARE(WL18XX_FW_NAME);
2095